[
  {
    "path": ".github/dependabot.yml",
    "content": "version: 2\nupdates:\n- package-ecosystem: composer\n  directory: \"/\"\n  schedule:\n    interval: daily\n    time: \"21:00\"\n  open-pull-requests-limit: 10\n"
  },
  {
    "path": ".github/stale.yml",
    "content": "# Number of days of inactivity before an issue becomes stale\ndaysUntilStale: 60\n# Number of days of inactivity before a stale issue is closed\ndaysUntilClose: 7\n# Issues with these labels will never be considered stale\nexemptLabels:\n  - pinned\n  - security\n# Label to use when marking an issue as stale\nstaleLabel: wontfix\n# Comment to post when marking an issue as stale. Set to `false` to disable\nmarkComment: >\n  This issue has been automatically marked as stale because it has not had\n  recent activity. It will be closed if no further activity occurs. Thank you\n  for your contributions.\n# Comment to post when closing a stale issue. Set to `false` to disable\ncloseComment: false\n"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\nphpunit.phar\n/vendor\ncomposer.phar\ncomposer.lock\n*.project\n.idea/\n.php_cs.cache\n.vscode/"
  },
  {
    "path": ".travis.yml",
    "content": "language: php\n\nphp:\n  - 7.2\n  - 7.3\n  - 7.4\n  - 8.0\n\nmatrix:\n  fast_finish: true\n  allow_failures:\n    - php: hhvm\n\nsudo: false\n\nservices:\n  - mysql\n\nbefore_script:\n  - mysql -e 'create database if not exists laravel_admin_test;'\n  - travis_retry composer self-update\n  - travis_retry composer install --no-interaction\n\nscript:\n  - composer test\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\nSee https://laravel-admin.org/docs/\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contribute\n\n## Introduction\n\nFirst, thank you for considering contributing to laravel-admin! It's people like you that make the open source community such a great community! 😊\n\nWe welcome any type of contribution, not only code. You can help with \n- **QA**: file bug reports, the more details you can give the better (e.g. screenshots with the console open)\n- **Marketing**: writing blog posts, howto's, printing stickers, ...\n- **Community**: presenting the project at meetups, organizing a dedicated meetup for the local community, ...\n- **Code**: take a look at the [open issues](issues). Even if you can't write code, commenting on them, showing that you care about a given issue matters. It helps us triage them.\n- **Money**: we welcome financial contributions in full transparency on our [open collective](https://opencollective.com/laravel-admin).\n\n## Your First Contribution\n\nWorking on your first Pull Request? You can learn how from this *free* series, [How to Contribute to an Open Source Project on GitHub](https://app.egghead.io/playlists/how-to-contribute-to-an-open-source-project-on-github).\n\n## Submitting code\n\nAny code change should be submitted as a pull request. The description should explain what the code does and give steps to execute it. The pull request should also contain tests.\n\n## Code review process\n\nThe bigger the pull request, the longer it will take to review and merge. Try to break down large pull requests in smaller chunks that are easier to review and merge.\nIt is also always helpful to have some context for your pull request. What was the purpose? Why does it matter to you?\n\n## Financial contributions\n\nWe also welcome financial contributions in full transparency on our [open collective](https://opencollective.com/laravel-admin).\nAnyone can file an expense. If the expense makes sense for the development of the community, it will be \"merged\" in the ledger of our open collective by the core contributors and the person who filed the expense will be reimbursed.\n\n## Questions\n\nIf you have any questions, create an [issue](issue) (protip: do a quick search first to see if someone else didn't ask the same question before!).\nYou can also reach us at hello@laravel-admin.opencollective.com.\n\n## Credits\n\n### Contributors\n\nThank you to all the people who have already contributed to laravel-admin!\n<a href=\"graphs/contributors\"><img src=\"https://opencollective.com/laravel-admin/contributors.svg?width=890\" /></a>\n\n\n### Backers\n\nThank you to all our backers! [[Become a backer](https://opencollective.com/laravel-admin#backer)]\n\n<a href=\"https://opencollective.com/laravel-admin#backers\" target=\"_blank\"><img src=\"https://opencollective.com/laravel-admin/backers.svg?width=890\"></a>\n\n\n### Sponsors\n\nThank you to all our sponsors! (please ask your company to also support this open source project by [becoming a sponsor](https://opencollective.com/laravel-admin#sponsor))\n\n<a href=\"https://opencollective.com/laravel-admin/sponsor/0/website\" target=\"_blank\"><img src=\"https://opencollective.com/laravel-admin/sponsor/0/avatar.svg\"></a>\n<a href=\"https://opencollective.com/laravel-admin/sponsor/1/website\" target=\"_blank\"><img src=\"https://opencollective.com/laravel-admin/sponsor/1/avatar.svg\"></a>\n<a href=\"https://opencollective.com/laravel-admin/sponsor/2/website\" target=\"_blank\"><img src=\"https://opencollective.com/laravel-admin/sponsor/2/avatar.svg\"></a>\n<a href=\"https://opencollective.com/laravel-admin/sponsor/3/website\" target=\"_blank\"><img src=\"https://opencollective.com/laravel-admin/sponsor/3/avatar.svg\"></a>\n<a href=\"https://opencollective.com/laravel-admin/sponsor/4/website\" target=\"_blank\"><img src=\"https://opencollective.com/laravel-admin/sponsor/4/avatar.svg\"></a>\n<a href=\"https://opencollective.com/laravel-admin/sponsor/5/website\" target=\"_blank\"><img src=\"https://opencollective.com/laravel-admin/sponsor/5/avatar.svg\"></a>\n<a href=\"https://opencollective.com/laravel-admin/sponsor/6/website\" target=\"_blank\"><img src=\"https://opencollective.com/laravel-admin/sponsor/6/avatar.svg\"></a>\n<a href=\"https://opencollective.com/laravel-admin/sponsor/7/website\" target=\"_blank\"><img src=\"https://opencollective.com/laravel-admin/sponsor/7/avatar.svg\"></a>\n<a href=\"https://opencollective.com/laravel-admin/sponsor/8/website\" target=\"_blank\"><img src=\"https://opencollective.com/laravel-admin/sponsor/8/avatar.svg\"></a>\n<a href=\"https://opencollective.com/laravel-admin/sponsor/9/website\" target=\"_blank\"><img src=\"https://opencollective.com/laravel-admin/sponsor/9/avatar.svg\"></a>\n\n<!-- This `CONTRIBUTING.md` is based on @nayafia's template https://github.com/nayafia/contributing-template -->\n"
  },
  {
    "path": "FUNDING.yml",
    "content": "# These are supported funding model platforms\n\nopen_collective: laravel-admin\ncustom: http://laravel-admin.org/donate\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 Jens Segers\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "<p align=\"center\">\n<a href=\"https://laravel-admin.org/\">\n<img src=\"https://laravel-admin.org/images/logo002.png\" alt=\"laravel-admin\">\n</a>\n\n<p align=\"center\">⛵<code>laravel-admin</code> is administrative interface builder for laravel which can help you build CRUD backends just with few lines of code.</p>\n\n<p align=\"center\">\n<a href=\"https://laravel-admin.org/docs\">Documentation</a> |\n<a href=\"https://laravel-admin.org/docs/zh\">中文文档</a> |\n<a href=\"https://demo.laravel-admin.org\">Demo</a> |\n<a href=\"https://github.com/z-song/demo.laravel-admin.org\">Demo source code</a> |\n<a href=\"#extensions\">Extensions</a>\n</p>\n\n<p align=\"center\">\n    <a href=\"https://travis-ci.org/z-song/laravel-admin\">\n        <img src=\"https://travis-ci.org/z-song/laravel-admin.svg?branch=master\" alt=\"Build Status\">\n    </a>\n    <a href=\"https://styleci.io/repos/48796179\">\n        <img src=\"https://styleci.io/repos/48796179/shield\" alt=\"StyleCI\">\n    </a>\n    <a href=\"https://packagist.org/packages/encore/laravel-admin\">\n        <img src=\"https://img.shields.io/packagist/l/encore/laravel-admin.svg?maxAge=2592000&&style=flat-square\" alt=\"Packagist\">\n    </a>\n    <a href=\"https://packagist.org/packages/encore/laravel-admin\">\n        <img src=\"https://img.shields.io/packagist/dt/encore/laravel-admin.svg?style=flat-square\" alt=\"Total Downloads\">\n    </a>\n    <a href=\"https://github.com/z-song/laravel-admin\">\n        <img src=\"https://img.shields.io/badge/Awesome-Laravel-brightgreen.svg?style=flat-square\" alt=\"Awesome Laravel\">\n    </a>\n    <a href=\"#backers\" alt=\"sponsors on Open Collective\">\n        <img src=\"https://opencollective.com/laravel-admin/backers/badge.svg?style=flat-square\" />\n    </a> \n    <a href=\"https://www.paypal.me/zousong\" alt=\"Paypal donate\">\n        <img src=\"https://img.shields.io/badge/Donate-Paypal-green.svg?style=flat-square\" />\n    </a> \n</div>\n\n<p align=\"center\">\n    Inspired by <a href=\"https://github.com/sleeping-owl/admin\" target=\"_blank\">SleepingOwlAdmin</a> and <a href=\"https://github.com/zofe/rapyd-laravel\" target=\"_blank\">rapyd-laravel</a>.\n</p>\n\nSponsor\n------------\n\n<a href=\"https://ter.li/32ifxj\">\n<img src=\"https://user-images.githubusercontent.com/1479100/102449272-dc356880-406e-11eb-9079-169c8c2af81c.png\" alt=\"laravel-admin\" width=\"200px;\">\n</a>\n\n\nRequirements\n------------\n - PHP >= 7.0.0\n - Laravel >= 5.5.0\n - Fileinfo PHP Extension\n\nInstallation\n------------\n\n> This package requires PHP 7+ and Laravel 5.5, for old versions please refer to [1.4](https://laravel-admin.org/docs/v1.4/#/)\n\nFirst, install laravel 5.5, and make sure that the database connection settings are correct.\n\n```\ncomposer require encore/laravel-admin\n```\n\nThen run these commands to publish assets and config：\n\n```\nphp artisan vendor:publish --provider=\"Encore\\Admin\\AdminServiceProvider\"\n```\nAfter run command you can find config file in `config/admin.php`, in this file you can change the install directory,db connection or table names.\n\nAt last run following command to finish install.\n```\nphp artisan admin:install\n```\n\nOpen `http://localhost/admin/` in browser,use username `admin` and password `admin` to login.\n\nConfigurations\n------------\nThe file `config/admin.php` contains an array of configurations, you can find the default configurations in there.\n\nRight to left support\n------------\njust go to this path `<YOUR_PROJECT_PATH>\\vendor\\encore\\laravel-admin\\src\\Traits\\HasAssets.php` and modify `$baseCss` array for loading right to left (rtl) version of bootstap and AdminLTE css files.    \n**bootstrap.min.css** change it to **bootstrap.rtl.min.css**    \n**AdminLTE.min.css** change it to **AdminLTE.rtl.min.css**  \n\n## Extensions\n\n| Extension                                        | Description                              | laravel-admin                              |\n| ------------------------------------------------ | ---------------------------------------- |---------------------------------------- |\n| [helpers](https://github.com/laravel-admin-extensions/helpers)             | Several tools to help you in development | ~1.5 |\n| [media-manager](https://github.com/laravel-admin-extensions/media-manager) | Provides a web interface to manage local files          | ~1.5 |\n| [api-tester](https://github.com/laravel-admin-extensions/api-tester) | Help you to test the local laravel APIs          |~1.5 |\n| [scheduling](https://github.com/laravel-admin-extensions/scheduling) | Scheduling task manager for laravel-admin          |~1.5 |\n| [redis-manager](https://github.com/laravel-admin-extensions/redis-manager) | Redis manager for laravel-admin          |~1.5 |\n| [backup](https://github.com/laravel-admin-extensions/backup) | An admin interface for managing backups          |~1.5 |\n| [log-viewer](https://github.com/laravel-admin-extensions/log-viewer) | Log viewer for laravel           |~1.5 |\n| [config](https://github.com/laravel-admin-extensions/config) | Config manager for laravel-admin          |~1.5 |\n| [reporter](https://github.com/laravel-admin-extensions/reporter) | Provides a developer-friendly web interface to view the exception          |~1.5 |\n| [wangEditor](https://github.com/laravel-admin-extensions/wangEditor) | A rich text editor based on [wangeditor](http://www.wangeditor.com/)         |~1.6 |\n| [summernote](https://github.com/laravel-admin-extensions/summernote) | A rich text editor based on [summernote](https://summernote.org/)          |~1.6 |\n| [china-distpicker](https://github.com/laravel-admin-extensions/china-distpicker) | 一个基于[distpicker](https://github.com/fengyuanchen/distpicker)的中国省市区选择器          |~1.6 |\n| [simplemde](https://github.com/laravel-admin-extensions/simplemde) | A markdown editor based on [simplemde](https://github.com/sparksuite/simplemde-markdown-editor)          |~1.6 |\n| [phpinfo](https://github.com/laravel-admin-extensions/phpinfo) | Integrate the `phpinfo` page into laravel-admin          |~1.6 |\n| [php-editor](https://github.com/laravel-admin-extensions/php-editor) <br/> [python-editor](https://github.com/laravel-admin-extensions/python-editor) <br/> [js-editor](https://github.com/laravel-admin-extensions/js-editor)<br/> [css-editor](https://github.com/laravel-admin-extensions/css-editor)<br/> [clike-editor](https://github.com/laravel-admin-extensions/clike-editor)| Several programing language editor extensions based on code-mirror          |~1.6 |\n| [star-rating](https://github.com/laravel-admin-extensions/star-rating) | Star Rating extension for laravel-admin          |~1.6 |\n| [json-editor](https://github.com/laravel-admin-extensions/json-editor) | JSON Editor for Laravel-admin          |~1.6 |\n| [grid-lightbox](https://github.com/laravel-admin-extensions/grid-lightbox) | Turn your grid into a lightbox & gallery          |~1.6 |\n| [daterangepicker](https://github.com/laravel-admin-extensions/daterangepicker) | Integrates daterangepicker into laravel-admin          |~1.6 |\n| [material-ui](https://github.com/laravel-admin-extensions/material-ui) | Material-UI extension for laravel-admin          |~1.6 |\n| [sparkline](https://github.com/laravel-admin-extensions/sparkline) | Integrates jQuery sparkline into laravel-admin          |~1.6 |\n| [chartjs](https://github.com/laravel-admin-extensions/chartjs) | Use Chartjs in laravel-admin          |~1.6 |\n| [echarts](https://github.com/laravel-admin-extensions/echarts) | Use Echarts in laravel-admin          |~1.6 |\n| [simditor](https://github.com/laravel-admin-extensions/simditor) | Integrates simditor full-rich editor into laravel-admin          |~1.6 |\n| [cropper](https://github.com/laravel-admin-extensions/cropper) | A simple jQuery image cropping plugin.          |~1.6 |\n| [composer-viewer](https://github.com/laravel-admin-extensions/composer-viewer) | A web interface of composer packages in laravel.          |~1.6 |\n| [data-table](https://github.com/laravel-admin-extensions/data-table) | Advanced table widget for laravel-admin |~1.6 |\n| [watermark](https://github.com/laravel-admin-extensions/watermark) | Text watermark for laravel-admin |~1.6 |\n| [google-authenticator](https://github.com/ylic/laravel-admin-google-authenticator) | Google authenticator |~1.6 |\n\n\n\n## Contributors\n This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].\n<a href=\"graphs/contributors\"><img src=\"https://opencollective.com/laravel-admin/contributors.svg?width=890&button=false\" /></a>\n ## Backers\n Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/laravel-admin#backer)]\n <a href=\"https://opencollective.com/laravel-admin#backers\" target=\"_blank\"><img src=\"https://opencollective.com/laravel-admin/backers.svg?width=890\"></a>\n ## Sponsors\n Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/laravel-admin#sponsor)]\n <a href=\"https://opencollective.com/laravel-admin/sponsor/0/website\" target=\"_blank\"><img src=\"https://opencollective.com/laravel-admin/sponsor/0/avatar.svg\"></a>\n<a href=\"https://opencollective.com/laravel-admin/sponsor/1/website\" target=\"_blank\"><img src=\"https://opencollective.com/laravel-admin/sponsor/1/avatar.svg\"></a>\n<a href=\"https://opencollective.com/laravel-admin/sponsor/2/website\" target=\"_blank\"><img src=\"https://opencollective.com/laravel-admin/sponsor/2/avatar.svg\"></a>\n<a href=\"https://opencollective.com/laravel-admin/sponsor/3/website\" target=\"_blank\"><img src=\"https://opencollective.com/laravel-admin/sponsor/3/avatar.svg\"></a>\n<a href=\"https://opencollective.com/laravel-admin/sponsor/4/website\" target=\"_blank\"><img src=\"https://opencollective.com/laravel-admin/sponsor/4/avatar.svg\"></a>\n<a href=\"https://opencollective.com/laravel-admin/sponsor/5/website\" target=\"_blank\"><img src=\"https://opencollective.com/laravel-admin/sponsor/5/avatar.svg\"></a>\n<a href=\"https://opencollective.com/laravel-admin/sponsor/6/website\" target=\"_blank\"><img src=\"https://opencollective.com/laravel-admin/sponsor/6/avatar.svg\"></a>\n<a href=\"https://opencollective.com/laravel-admin/sponsor/7/website\" target=\"_blank\"><img src=\"https://opencollective.com/laravel-admin/sponsor/7/avatar.svg\"></a>\n<a href=\"https://opencollective.com/laravel-admin/sponsor/8/website\" target=\"_blank\"><img src=\"https://opencollective.com/laravel-admin/sponsor/8/avatar.svg\"></a>\n<a href=\"https://opencollective.com/laravel-admin/sponsor/9/website\" target=\"_blank\"><img src=\"https://opencollective.com/laravel-admin/sponsor/9/avatar.svg\"></a>\n\nOther\n------------\n`laravel-admin` based on following plugins or services:\n\n+ [Laravel](https://laravel.com/)\n+ [AdminLTE](https://adminlte.io/)\n+ [Datetimepicker](http://eonasdan.github.io/bootstrap-datetimepicker/)\n+ [font-awesome](http://fontawesome.io)\n+ [moment](http://momentjs.com/)\n+ [Google map](https://www.google.com/maps)\n+ [Tencent map](http://lbs.qq.com/)\n+ [bootstrap-fileinput](https://github.com/kartik-v/bootstrap-fileinput)\n+ [jquery-pjax](https://github.com/defunkt/jquery-pjax)\n+ [Nestable](http://dbushell.github.io/Nestable/)\n+ [toastr](http://codeseven.github.io/toastr/)\n+ [X-editable](http://github.com/vitalets/x-editable)\n+ [bootstrap-number-input](https://github.com/wpic/bootstrap-number-input)\n+ [fontawesome-iconpicker](https://github.com/itsjavi/fontawesome-iconpicker)\n+ [sweetalert2](https://github.com/sweetalert2/sweetalert2)\n\nLicense\n------------\n`laravel-admin` is licensed under [The MIT License (MIT)](LICENSE).\n"
  },
  {
    "path": "composer.json",
    "content": "{\n    \"name\": \"encore/laravel-admin\",\n    \"description\": \"laravel admin\",\n    \"type\": \"library\",\n    \"keywords\": [\"laravel\", \"admin\", \"grid\", \"form\"],\n    \"homepage\": \"https://github.com/z-song/laravel-admin\",\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\n            \"name\": \"zsong\",\n            \"email\": \"zosong@126.com\"\n        }\n    ],\n    \"require\": {\n        \"php\": \">=7.0.0\",\n        \"symfony/dom-crawler\": \"~3.1|~4.0|~5.0\",\n        \"laravel/framework\": \">=5.5\",\n        \"doctrine/dbal\": \"2.*|3.*\"\n    },\n    \"require-dev\": {\n        \"laravel/laravel\": \">=5.5\",\n        \"fzaninotto/faker\": \"~1.4\",\n        \"intervention/image\": \"~2.3\",\n        \"laravel/browser-kit-testing\": \"^6.0\",\n        \"spatie/phpunit-watcher\": \"^1.22.0\"\n    },\n    \"autoload\": {\n        \"psr-4\": {\n            \"Encore\\\\Admin\\\\\": \"src/\"\n        },\n        \"files\": [\n            \"src/helpers.php\"\n        ]\n    },\n    \"autoload-dev\": {\n        \"psr-4\": {\n            \"Tests\\\\Models\\\\\": \"tests/models\",\n            \"Tests\\\\Controllers\\\\\": \"tests/controllers\"\n        },\n        \"classmap\": [\n            \"tests/TestCase.php\"\n        ]\n    },\n    \"scripts\": {\n        \"test\": \"./vendor/bin/phpunit\"\n    },\n    \"suggest\": {\n        \"intervention/image\": \"Required to handling and manipulation upload images (~2.3).\",\n        \"spatie/eloquent-sortable\": \"Required to built orderable gird.\"\n    },\n    \"extra\": {\n        \"laravel\": {\n            \"providers\": [\n                \"Encore\\\\Admin\\\\AdminServiceProvider\"\n            ],\n            \"aliases\": {\n                \"Admin\": \"Encore\\\\Admin\\\\Facades\\\\Admin\"\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "config/admin.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Laravel-admin name\n    |--------------------------------------------------------------------------\n    |\n    | This value is the name of laravel-admin, This setting is displayed on the\n    | login page.\n    |\n    */\n    'name' => 'Laravel-admin',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Laravel-admin logo\n    |--------------------------------------------------------------------------\n    |\n    | The logo of all admin pages. You can also set it as an image by using a\n    | `img` tag, eg '<img src=\"http://logo-url\" alt=\"Admin logo\">'.\n    |\n    */\n    'logo' => '<b>Laravel</b> admin',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Laravel-admin mini logo\n    |--------------------------------------------------------------------------\n    |\n    | The logo of all admin pages when the sidebar menu is collapsed. You can\n    | also set it as an image by using a `img` tag, eg\n    | '<img src=\"http://logo-url\" alt=\"Admin logo\">'.\n    |\n    */\n    'logo-mini' => '<b>La</b>',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Laravel-admin bootstrap setting\n    |--------------------------------------------------------------------------\n    |\n    | This value is the path of laravel-admin bootstrap file.\n    |\n    */\n    'bootstrap' => app_path('Admin/bootstrap.php'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Laravel-admin route settings\n    |--------------------------------------------------------------------------\n    |\n    | The routing configuration of the admin page, including the path prefix,\n    | the controller namespace, and the default middleware. If you want to\n    | access through the root path, just set the prefix to empty string.\n    |\n    */\n    'route' => [\n\n        'prefix' => env('ADMIN_ROUTE_PREFIX', 'admin'),\n\n        'namespace' => 'App\\\\Admin\\\\Controllers',\n\n        'middleware' => ['web', 'admin'],\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Laravel-admin install directory\n    |--------------------------------------------------------------------------\n    |\n    | The installation directory of the controller and routing configuration\n    | files of the administration page. The default is `app/Admin`, which must\n    | be set before running `artisan admin::install` to take effect.\n    |\n    */\n    'directory' => app_path('Admin'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Laravel-admin html title\n    |--------------------------------------------------------------------------\n    |\n    | Html title for all pages.\n    |\n    */\n    'title' => 'Admin',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Access via `https`\n    |--------------------------------------------------------------------------\n    |\n    | If your page is going to be accessed via https, set it to `true`.\n    |\n    */\n    'https' => env('ADMIN_HTTPS', false),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Laravel-admin auth setting\n    |--------------------------------------------------------------------------\n    |\n    | Authentication settings for all admin pages. Include an authentication\n    | guard and a user provider setting of authentication driver.\n    |\n    | You can specify a controller for `login` `logout` and other auth routes.\n    |\n    */\n    'auth' => [\n\n        'controller' => App\\Admin\\Controllers\\AuthController::class,\n\n        'guard' => 'admin',\n\n        'guards' => [\n            'admin' => [\n                'driver'   => 'session',\n                'provider' => 'admin',\n            ],\n        ],\n\n        'providers' => [\n            'admin' => [\n                'driver' => 'eloquent',\n                'model'  => Encore\\Admin\\Auth\\Database\\Administrator::class,\n            ],\n        ],\n\n        // Add \"remember me\" to login form\n        'remember' => true,\n\n        // Redirect to the specified URI when user is not authorized.\n        'redirect_to' => 'auth/login',\n\n        // The URIs that should be excluded from authorization.\n        'excepts' => [\n            'auth/login',\n            'auth/logout',\n        ],\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Laravel-admin upload setting\n    |--------------------------------------------------------------------------\n    |\n    | File system configuration for form upload files and images, including\n    | disk and upload path.\n    |\n    */\n    'upload' => [\n\n        // Disk in `config/filesystem.php`.\n        'disk' => 'admin',\n\n        // Image and file upload path under the disk above.\n        'directory' => [\n            'image' => 'images',\n            'file'  => 'files',\n        ],\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Laravel-admin database settings\n    |--------------------------------------------------------------------------\n    |\n    | Here are database settings for laravel-admin builtin model & tables.\n    |\n    */\n    'database' => [\n\n        // Database connection for following tables.\n        'connection' => '',\n\n        // User tables and model.\n        'users_table' => 'admin_users',\n        'users_model' => Encore\\Admin\\Auth\\Database\\Administrator::class,\n\n        // Role table and model.\n        'roles_table' => 'admin_roles',\n        'roles_model' => Encore\\Admin\\Auth\\Database\\Role::class,\n\n        // Permission table and model.\n        'permissions_table' => 'admin_permissions',\n        'permissions_model' => Encore\\Admin\\Auth\\Database\\Permission::class,\n\n        // Menu table and model.\n        'menu_table' => 'admin_menu',\n        'menu_model' => Encore\\Admin\\Auth\\Database\\Menu::class,\n\n        // Pivot table for table above.\n        'operation_log_table'    => 'admin_operation_log',\n        'user_permissions_table' => 'admin_user_permissions',\n        'role_users_table'       => 'admin_role_users',\n        'role_permissions_table' => 'admin_role_permissions',\n        'role_menu_table'        => 'admin_role_menu',\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | User operation log setting\n    |--------------------------------------------------------------------------\n    |\n    | By setting this option to open or close operation log in laravel-admin.\n    |\n    */\n    'operation_log' => [\n\n        'enable' => true,\n\n        /*\n         * Only logging allowed methods in the list\n         */\n        'allowed_methods' => ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE', 'PATCH'],\n\n        /*\n         * Routes that will not log to database.\n         *\n         * All method to path like: admin/auth/logs\n         * or specific method to path like: get:admin/auth/logs.\n         */\n        'except' => [\n            env('ADMIN_ROUTE_PREFIX', 'admin').'/auth/logs*',\n        ],\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Indicates whether to check route permission.\n    |--------------------------------------------------------------------------\n    */\n    'check_route_permission' => true,\n\n    /*\n    |--------------------------------------------------------------------------\n    | Indicates whether to check menu roles.\n    |--------------------------------------------------------------------------\n    */\n    'check_menu_roles'       => true,\n\n    /*\n    |--------------------------------------------------------------------------\n    | User default avatar\n    |--------------------------------------------------------------------------\n    |\n    | Set a default avatar for newly created users.\n    |\n    */\n    'default_avatar' => '/vendor/laravel-admin/AdminLTE/dist/img/user2-160x160.jpg',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Admin map field provider\n    |--------------------------------------------------------------------------\n    |\n    | Supported: \"tencent\", \"google\", \"yandex\".\n    |\n    */\n    'map_provider' => 'google',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Application Skin\n    |--------------------------------------------------------------------------\n    |\n    | This value is the skin of admin pages.\n    | @see https://adminlte.io/docs/2.4/layout\n    |\n    | Supported:\n    |    \"skin-blue\", \"skin-blue-light\", \"skin-yellow\", \"skin-yellow-light\",\n    |    \"skin-green\", \"skin-green-light\", \"skin-purple\", \"skin-purple-light\",\n    |    \"skin-red\", \"skin-red-light\", \"skin-black\", \"skin-black-light\".\n    |\n    */\n    'skin' => env('ADMIN_SKIN', 'skin-blue-light'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Application layout\n    |--------------------------------------------------------------------------\n    |\n    | This value is the layout of admin pages.\n    | @see https://adminlte.io/docs/2.4/layout\n    |\n    | Supported: \"fixed\", \"layout-boxed\", \"layout-top-nav\", \"sidebar-collapse\",\n    | \"sidebar-mini\".\n    |\n    */\n    'layout' => ['sidebar-mini', 'sidebar-collapse'],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Login page background image\n    |--------------------------------------------------------------------------\n    |\n    | This value is used to set the background image of login page.\n    |\n    */\n    'login_background_image' => '',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Show version at footer\n    |--------------------------------------------------------------------------\n    |\n    | Whether to display the version number of laravel-admin at the footer of\n    | each page\n    |\n    */\n    'show_version' => true,\n\n    /*\n    |--------------------------------------------------------------------------\n    | Show environment at footer\n    |--------------------------------------------------------------------------\n    |\n    | Whether to display the environment at the footer of each page\n    |\n    */\n    'show_environment' => true,\n\n    /*\n    |--------------------------------------------------------------------------\n    | Menu bind to permission\n    |--------------------------------------------------------------------------\n    |\n    | whether enable menu bind to a permission\n    */\n    'menu_bind_permission' => true,\n\n    /*\n    |--------------------------------------------------------------------------\n    | Enable default breadcrumb\n    |--------------------------------------------------------------------------\n    |\n    | Whether enable default breadcrumb for every page content.\n    */\n    'enable_default_breadcrumb' => true,\n\n    /*\n    |--------------------------------------------------------------------------\n    | Enable/Disable assets minify\n    |--------------------------------------------------------------------------\n    */\n    'minify_assets' => [\n\n        // Assets will not be minified.\n        'excepts' => [\n\n        ],\n\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Enable/Disable sidebar menu search\n    |--------------------------------------------------------------------------\n    */\n    'enable_menu_search' => true,\n\n    /*\n    |--------------------------------------------------------------------------\n    | Exclude route from generate menu command\n    |--------------------------------------------------------------------------\n    */\n    'menu_exclude' => [\n        '_handle_selectable_',\n        '_handle_renderable_',\n    ],\n\n    /*\n    |--------------------------------------------------------------------------\n    | Alert message that will displayed on top of the page.\n    |--------------------------------------------------------------------------\n    */\n    'top_alert' => '',\n\n    /*\n    |--------------------------------------------------------------------------\n    | The global Grid action display class.\n    |--------------------------------------------------------------------------\n    */\n    'grid_action_class' => \\Encore\\Admin\\Grid\\Displayers\\DropdownActions::class,\n\n    /*\n    |--------------------------------------------------------------------------\n    | Extension Directory\n    |--------------------------------------------------------------------------\n    |\n    | When you use command `php artisan admin:extend` to generate extensions,\n    | the extension files will be generated in this directory.\n    */\n    'extension_dir' => app_path('Admin/Extensions'),\n\n    /*\n    |--------------------------------------------------------------------------\n    | Settings for extensions.\n    |--------------------------------------------------------------------------\n    |\n    | You can find all available extensions here\n    | https://github.com/laravel-admin-extensions.\n    |\n    */\n    'extensions' => [\n\n    ],\n];\n"
  },
  {
    "path": "database/migrations/2016_01_04_173148_create_admin_tables.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\nuse Illuminate\\Support\\Facades\\Schema;\n\nclass CreateAdminTables extends Migration\n{\n    /**\n     * {@inheritdoc}\n     */\n    public function getConnection()\n    {\n        return config('admin.database.connection') ?: config('database.default');\n    }\n\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create(config('admin.database.users_table'), function (Blueprint $table) {\n            $table->increments('id');\n            $table->string('username', 190)->unique();\n            $table->string('password', 60);\n            $table->string('name');\n            $table->string('avatar')->nullable();\n            $table->string('remember_token', 100)->nullable();\n            $table->timestamps();\n        });\n\n        Schema::create(config('admin.database.roles_table'), function (Blueprint $table) {\n            $table->increments('id');\n            $table->string('name', 50)->unique();\n            $table->string('slug', 50)->unique();\n            $table->timestamps();\n        });\n\n        Schema::create(config('admin.database.permissions_table'), function (Blueprint $table) {\n            $table->increments('id');\n            $table->string('name', 50)->unique();\n            $table->string('slug', 50)->unique();\n            $table->string('http_method')->nullable();\n            $table->text('http_path')->nullable();\n            $table->timestamps();\n        });\n\n        Schema::create(config('admin.database.menu_table'), function (Blueprint $table) {\n            $table->increments('id');\n            $table->integer('parent_id')->default(0);\n            $table->integer('order')->default(0);\n            $table->string('title', 50);\n            $table->string('icon', 50);\n            $table->string('uri')->nullable();\n            $table->string('permission')->nullable();\n\n            $table->timestamps();\n        });\n\n        Schema::create(config('admin.database.role_users_table'), function (Blueprint $table) {\n            $table->integer('role_id');\n            $table->integer('user_id');\n            $table->index(['role_id', 'user_id']);\n            $table->timestamps();\n        });\n\n        Schema::create(config('admin.database.role_permissions_table'), function (Blueprint $table) {\n            $table->integer('role_id');\n            $table->integer('permission_id');\n            $table->index(['role_id', 'permission_id']);\n            $table->timestamps();\n        });\n\n        Schema::create(config('admin.database.user_permissions_table'), function (Blueprint $table) {\n            $table->integer('user_id');\n            $table->integer('permission_id');\n            $table->index(['user_id', 'permission_id']);\n            $table->timestamps();\n        });\n\n        Schema::create(config('admin.database.role_menu_table'), function (Blueprint $table) {\n            $table->integer('role_id');\n            $table->integer('menu_id');\n            $table->index(['role_id', 'menu_id']);\n            $table->timestamps();\n        });\n\n        Schema::create(config('admin.database.operation_log_table'), function (Blueprint $table) {\n            $table->increments('id');\n            $table->integer('user_id');\n            $table->string('path');\n            $table->string('method', 10);\n            $table->string('ip');\n            $table->text('input');\n            $table->index('user_id');\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists(config('admin.database.users_table'));\n        Schema::dropIfExists(config('admin.database.roles_table'));\n        Schema::dropIfExists(config('admin.database.permissions_table'));\n        Schema::dropIfExists(config('admin.database.menu_table'));\n        Schema::dropIfExists(config('admin.database.user_permissions_table'));\n        Schema::dropIfExists(config('admin.database.role_users_table'));\n        Schema::dropIfExists(config('admin.database.role_permissions_table'));\n        Schema::dropIfExists(config('admin.database.role_menu_table'));\n        Schema::dropIfExists(config('admin.database.operation_log_table'));\n    }\n}\n"
  },
  {
    "path": "docs/en/LICENSE.md",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 Jens Segers\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "docs/en/README.md",
    "content": "laravel-admin\n=====\n\n[![Build Status](https://travis-ci.org/z-song/laravel-admin.svg?branch=master)](https://travis-ci.org/z-song/laravel-admin)\n[![StyleCI](https://styleci.io/repos/48796179/shield)](https://styleci.io/repos/48796179)\n[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/z-song/laravel-admin/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/z-song/laravel-admin/?branch=master)\n[![Packagist](https://img.shields.io/packagist/l/encore/laravel-admin.svg?maxAge=2592000)](https://packagist.org/packages/encore/laravel-admin)\n[![Total Downloads](https://img.shields.io/packagist/dt/encore/laravel-admin.svg?style=flat-square)](https://packagist.org/packages/encore/laravel-admin)\n[![Awesome Laravel](https://img.shields.io/badge/Awesome-Laravel-brightgreen.svg)](https://github.com/z-song/laravel-admin)\n\n`laravel-admin` is administrative interface builder for laravel which can help you build CRUD backends just with few lines of code.\n\n[Demo](http://laravel-admin.org/demo) use `username/password:admin/admin`\n\nInspired by [SleepingOwlAdmin](https://github.com/sleeping-owl/admin) and [rapyd-laravel](https://github.com/zofe/rapyd-laravel).\n\n[Documentation](http://laravel-admin.org/docs) | [中文文档](http://laravel-admin.org/docs/#/zh/)\n\nScreenshots\n------------\n\n![laravel-admin](https://cloud.githubusercontent.com/assets/1479100/19625297/3b3deb64-9947-11e6-807c-cffa999004be.jpg)\n\nInstallation\n------------\n\n> This package requires PHP 7+ and Laravel 5.5, for old versions please refer to [1.4](http://laravel-admin.org/docs/v1.4/#/) \n\nFirst, install laravel 5.5, and make sure that the database connection settings are correct.\n\n```\ncomposer require encore/laravel-admin 1.5.*\n```\n\nThen run these commands to publish assets and config：\n\n```\nphp artisan vendor:publish --provider=\"Encore\\Admin\\AdminServiceProvider\"\n```\nAfter run command you can find config file in `config/admin.php`, in this file you can change the install directory,db connection or table names.\n\nAt last run following command to finish install. \n```\nphp artisan admin:install\n```\n\nOpen `http://localhost/admin/` in browser,use username `admin` and password `admin` to login.\n\nDefault Settings\n------------\nThe file in `config/admin.php` contains an array of settings, you can find the default settings in there.\n\n\nOther\n------------\n`laravel-admin` based on following plugins or services:\n\n+ [Laravel](https://laravel.com/)\n+ [AdminLTE](https://almsaeedstudio.com/)\n+ [Datetimepicker](http://eonasdan.github.io/bootstrap-datetimepicker/)\n+ [font-awesome](http://fontawesome.io)\n+ [moment](http://momentjs.com/)\n+ [Google map](https://www.google.com/maps)\n+ [Tencent map](http://lbs.qq.com/)\n+ [bootstrap-fileinput](https://github.com/kartik-v/bootstrap-fileinput)\n+ [jquery-pjax](https://github.com/defunkt/jquery-pjax)\n+ [Nestable](http://dbushell.github.io/Nestable/)\n+ [toastr](http://codeseven.github.io/toastr/)\n+ [X-editable](http://github.com/vitalets/x-editable)\n+ [bootstrap-number-input](https://github.com/wpic/bootstrap-number-input)\n+ [fontawesome-iconpicker](https://github.com/itsjavi/fontawesome-iconpicker)\n\nLicense\n------------\n`laravel-admin` is licensed under [The MIT License (MIT)](LICENSE).\n"
  },
  {
    "path": "docs/en/_sidebar.md",
    "content": "\n- Getting started\n  - [Installation](/en/installation.md)\n  - [Quick start](/en/quick-start.md)\n  - [Page content & Layout](/en/content-layout.md)\n- Model grid\n  - [Basic usage](/en/model-grid.md)\n  - [Row actions](/en/model-grid-actions.md)\n  - [Column actions](/en/model-grid-column.md)\n  - [Custom tools](/en/model-grid-custom-tools.md)\n  - [Filters](/en/model-grid-filters.md)\n  - [Data export](/en/model-grid-export.md)\n- Model form\n  - [Basic usage](/en/model-form.md)\n  - [Image/File upload](/en/model-form-upload.md)\n  - [Form fields](/en/model-form-fields.md)\n  - [Form field management](/en/model-form-field-management.md)\n  - [Form validation](/en/model-form-validation.md)\n  - [Save callback](/en/model-form-callback.md)\n- [Model-tree](/en/model-tree.md)\n- Admin extensions\n  - [Helpers](/en/extension-helpers.md)\n  - [Media manager](/en/extension-media-manager.md)\n  - [API tester](/en/extension-api-tester.md)\n  - [Config manager](/en/extension-config.md)\n  - [Task scheduling](/en/extension-scheduling.md)\n- [Widgets](/en/widgets.md)\n- [Permissions](/en/permission.md)\n- [Custom authentication](/en/custom-authentication.md)\n- [Custom Navbar](/en/custom-navbar.md)\n- [Custom chart](/en/custom-chart.md)\n- [Helpers](/en/helpers.md)\n- [Upgrade precautions](/en/upgrade.md)\n- [Change log](/en/change-log.md)"
  },
  {
    "path": "docs/en/change-log.md",
    "content": "# Change log\n\n## v1.2.9、v1.3.3、v1.4.1\n\n- Add user settings and modify avatar function\n- Embedded form support\n- Support for customize navigation bar (upper right corner)\n- Add scaffolding, database command line tool, web artisan help tool\n- Support for customize login page and login logic\n- The form supports setting the width and setting the action\n- Optimize table filters\n- Fix bugs, optimize code and logic"
  },
  {
    "path": "docs/en/content-layout.md",
    "content": "# Page content\n\nThe layout usage of `laravel-admin` can be found in the `index()` method of the home page's layout file [HomeController.php](https://github.com/z-song/laravel-admin/blob/master/src/Console/stubs/HomeController.stub).\n\nThe `Encore\\Admin\\Layout\\Content` class is used to implement the layout of the content area. The `Content::body ($element)` method is used to add page content:\n\nThe page code for an unfilled content is as follows：\n\n```php\npublic function index()\n{\n    return Admin::content(function (Content $content) {\n\n        // optional\n        $content->header('page header');\n        \n        // optional\n        $content->description('page description');\n\n        // add breadcrumb since v1.5.7\n        $content->breadcrumb(\n            ['text' => 'Dashboard', 'url' => '/admin'],\n            ['text' => 'User management', 'url' => '/admin/users'],\n            ['text' => 'Edit user']\n        );\n\n        // Fill the page body part, you can put any renderable objects here\n        $content->body('hello world');\n    });\n}\n```\n\nMethod `$content->body();` can accepts any renderable objects, like string, number, class that has method `__toString`,  or implements `Renderable`、`Htmlable` interface , include Laravel View objects.\n\n## Layout\n\n`laravel-admin` use grid system of bootstrap,The length of each line is 12, the following is a few simple examples:\n\nAdd a line of content:\n\n```php\n$content->row('hello')\n\n---------------------------------\n|hello                          |\n|                               |\n|                               |\n|                               |\n|                               |\n|                               |\n---------------------------------\n\n```\n\nAdd multiple columns within the line：\n\n```php\n$content->row(function(Row $row) {\n    $row->column(4, 'foo');\n    $row->column(4, 'bar');\n    $row->column(4, 'baz');\n});\n----------------------------------\n|foo       |bar       |baz       |\n|          |          |          |\n|          |          |          |\n|          |          |          |\n|          |          |          |\n|          |          |          |\n----------------------------------\n\n\n$content->row(function(Row $row) {\n    $row->column(4, 'foo');\n    $row->column(8, 'bar');\n});\n----------------------------------\n|foo       |bar                  |\n|          |                     |\n|          |                     |\n|          |                     |\n|          |                     |\n|          |                     |\n----------------------------------\n\n```\n\nColumn in the column：\n\n```php\n$content->row(function (Row $row) {\n\n    $row->column(4, 'xxx');\n\n    $row->column(8, function (Column $column) {\n        $column->row('111');\n        $column->row('222');\n        $column->row('333');\n    });\n});\n----------------------------------\n|xxx       |111                  |\n|          |---------------------|\n|          |222                  |\n|          |---------------------|\n|          |333                  |\n|          |                     |\n----------------------------------\n\n\n```\n\n\nAdd rows in rows and add columns：\n\n```php\n$content->row(function (Row $row) {\n\n    $row->column(4, 'xxx');\n\n    $row->column(8, function (Column $column) {\n        $column->row('111');\n        $column->row('222');\n        $column->row(function(Row $row) {\n            $row->column(6, '444');\n            $row->column(6, '555');\n        });\n    });\n});\n----------------------------------\n|xxx       |111                  |\n|          |---------------------|\n|          |222                  |\n|          |---------------------|\n|          |444      |555        |\n|          |         |           |\n----------------------------------\n```\n\nAdd body into a page：\n\nCreate a blade view file inside `/project/resources/views/admin/custom.blade.php`\n\n```php\n    public function customPage($id)\n    {\n        $content = new Content();\n        $content->header('View');\n        $content->description('Description...');\n        $content->body('admin.custom',['id' => $id]);\n        return $content;\n    }\n```\n"
  },
  {
    "path": "docs/en/custom-authentication.md",
    "content": "# Custom authentication\n\nIf you do not use the `laravel-admin` built-in authentication login logic, you can refer to the following way to customize the login authentication logic.\n\nFirst of all, you need define a `User provider`, used to obtain the user identity, such as `app/Providers/CustomUserProvider.php`:\n\n```php\n<?php\n\nnamespace App\\Providers;\n\nuse Illuminate\\Contracts\\Auth\\Authenticatable;\nuse Illuminate\\Contracts\\Auth\\UserProvider;\n\nclass CustomUserProvider implements UserProvider\n{\n    public function retrieveById($identifier)\n    {}\n\n    public function retrieveByToken($identifier, $token)\n    {}\n\n    public function updateRememberToken(Authenticatable $user, $token)\n    {}\n\n    public function retrieveByCredentials(array $credentials)\n    {\n        // Use $credentials to get the user data, and then return an object implements interface `Illuminate\\Contracts\\Auth\\Authenticatable` \n    }\n\n    public function validateCredentials(Authenticatable $user, array $credentials)\n    {\n        // Verify the user with the username password in $ credentials, return `true` or `false`\n    }\n}\n\n```\n\nIn the methods `retrieveByCredentials` and `validateCredentials` the parameter `$credentials` is the user name and password array submitted on the login page, you can use `$credentials` to implement your own login logic.\n\nThe definition of interface `Illuminate\\Contracts\\Auth\\Authenticatable`:\n```php\n<?php\n\nnamespace Illuminate\\Contracts\\Auth;\n\ninterface Authenticatable {\n\n    public function getAuthIdentifierName();\n    public function getAuthIdentifier();\n    public function getAuthPassword();\n    public function getRememberToken();\n    public function setRememberToken($value);\n    public function getRememberTokenName();\n\n}\n```\n\nFor more details about custom authentication please refer to [adding-custom-user-providers](https://laravel.com/docs/5.5/authentication#adding-custom-user-providers).\n\n\nAfter you created cusom user provider, you will need to extend Laravel with it:\n\n```php\n<?php\n\nnamespace App\\Providers;\n\nuse Illuminate\\Support\\Facades\\Auth;\nuse Illuminate\\Foundation\\Support\\Providers\\AuthServiceProvider as ServiceProvider;\n\nclass AuthServiceProvider extends ServiceProvider\n{\n    /**\n     * Register any application authentication / authorization services.\n     *\n     * @return void\n     */\n    public function boot()\n    {\n        $this->registerPolicies();\n\n        Auth::provider('custom', function ($app, array $config) {\n            \n            // Return an instance of Illuminate\\Contracts\\Auth\\UserProvider...\n            return new CustomUserProvider();\n        });\n    }\n}\n```\n\nFinally modify the configuration, open `config/admin.php`, find the `auth` part:\n\n```php\n    'auth' => [\n        'guards' => [\n            'admin' => [\n                'driver' => 'session',\n                'provider' => 'admin',\n            ]\n        ],\n\n        // Modify the following\n        'providers' => [\n            'admin' => [\n                'driver' => 'custom',\n            ]\n        ],\n    ],\n```\nThis completes the logic of custom authentication.\n"
  },
  {
    "path": "docs/en/custom-chart.md",
    "content": "# Custom chart\n\n`laravel-admin 1.5` has removed all the chart components. If you want to add chart components to the page, you can refer to the following process\n\nUse `chartjs` for example, first download [chartjs](http://chartjs.org/), put it under the public directory, such as in the `public/vendor/chartjs` directory\n\nThen import the component in `app/Admin/bootstrap.php`:\n```php\nuse Encore\\Admin\\Facades\\Admin;\n\nAdmin::js('/vendor/chartjs/dist/Chart.min.js');\n\n```\n\nCreate a new view file `resources/views/admin/charts/bar.blade.php`\n\n```php\n<canvas id=\"myChart\" width=\"400\" height=\"400\"></canvas>\n<script>\n$(function () {\n    var ctx = document.getElementById(\"myChart\").getContext('2d');\n    var myChart = new Chart(ctx, {\n        type: 'bar',\n        data: {\n            labels: [\"Red\", \"Blue\", \"Yellow\", \"Green\", \"Purple\", \"Orange\"],\n            datasets: [{\n                label: '# of Votes',\n                data: [12, 19, 3, 5, 2, 3],\n                backgroundColor: [\n                    'rgba(255, 99, 132, 0.2)',\n                    'rgba(54, 162, 235, 0.2)',\n                    'rgba(255, 206, 86, 0.2)',\n                    'rgba(75, 192, 192, 0.2)',\n                    'rgba(153, 102, 255, 0.2)',\n                    'rgba(255, 159, 64, 0.2)'\n                ],\n                borderColor: [\n                    'rgba(255,99,132,1)',\n                    'rgba(54, 162, 235, 1)',\n                    'rgba(255, 206, 86, 1)',\n                    'rgba(75, 192, 192, 1)',\n                    'rgba(153, 102, 255, 1)',\n                    'rgba(255, 159, 64, 1)'\n                ],\n                borderWidth: 1\n            }]\n        },\n        options: {\n            scales: {\n                yAxes: [{\n                    ticks: {\n                        beginAtZero:true\n                    }\n                }]\n            }\n        }\n    });\n});\n</script>\n```\n\nAnd then you can introduce this chart view anywhere on the page:\n\n```php\npublic function index()\n{\n    return Admin::content(function (Content $content) {\n\n        $content->header('chart');\n        $content->description('.....');\n        \n        $content->body(view('admin.charts.bar'));\n    });\n}\n\n```\n\nIn the above way you can introduce any chart library. multi-chart page layout, refer to [view layout] (/en/layout.md)"
  },
  {
    "path": "docs/en/custom-navbar.md",
    "content": "# Customize the head navigation bar\n\nSince version `1.5.6`, you can add the html element to the top navigation bar, open `app/Admin/bootstrap.php`:\n```php\nuse Encore\\Admin\\Facades\\Admin;\n\nAdmin::navbar(function (\\Encore\\Admin\\Widgets\\Navbar $navbar) {\n\n    $navbar->left('html...');\n\n    $navbar->right('html...');\n\n});\n```\n\nMethods `left` and `right` are used to add content to the left and right sides of the head, the method parameters can be any object that can be rendered (objects which impletements `Htmlable`, `Renderable`, or has method `__toString()`) or strings.\n\n## Add elements to the left\n\nFor example, add a search bar on the left, first create a view `resources/views/search-bar.blade.php`:\n```php\n<style>\n\n.search-form {\n    width: 250px;\n    margin: 10px 0 0 20px;\n    border-radius: 3px;\n    float: left;\n}\n.search-form input[type=\"text\"] {\n    color: #666;\n    border: 0;\n}\n\n.search-form .btn {\n    color: #999;\n    background-color: #fff;\n    border: 0;\n}\n\n</style>\n\n<form action=\"/admin/posts\" method=\"get\" class=\"search-form\" pjax-container>\n    <div class=\"input-group input-group-sm \">\n        <input type=\"text\" name=\"title\" class=\"form-control\" placeholder=\"Search...\">\n        <span class=\"input-group-btn\">\n            <button type=\"submit\" name=\"search\" id=\"search-btn\" class=\"btn btn-flat\"><i class=\"fa fa-search\"></i></button>\n          </span>\n    </div>\n</form>\n```\nThen add it to the head navigation bar:\n```php\n$navbar->left(view('search-bar'));\n```\n\n## Add elements to the right\n\nYou can only add the `<li>` tag on the right side of the navigation, such as adding some prompt icons, creating a new rendering class `app/Admin/Extensions/Nav/Links.php`\n```php\n<?php\n\nnamespace App\\Admin\\Extensions\\Nav;\n\nclass Links\n{\n    public function __toString()\n    {\n        return <<<HTML\n\n<li>\n    <a href=\"#\">\n      <i class=\"fa fa-envelope-o\"></i>\n      <span class=\"label label-success\">4</span>\n    </a>\n</li>\n\n<li>\n    <a href=\"#\">\n      <i class=\"fa fa-bell-o\"></i>\n      <span class=\"label label-warning\">7</span>\n    </a>\n</li>\n\n<li>\n    <a href=\"#\">\n      <i class=\"fa fa-flag-o\"></i>\n      <span class=\"label label-danger\">9</span>\n    </a>\n</li>\n\nHTML;\n    }\n}\n```\n\nThen add it to the head navigation bar:\n```php\n$navbar->right(new \\App\\Admin\\Extensions\\Nav\\Links());\n```\n\nOr use the following html to add a drop-down menu:\n```html\n<li class=\"dropdown notifications-menu\">\n<a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\" aria-expanded=\"false\">\n  <i class=\"fa fa-bell-o\"></i>\n  <span class=\"label label-warning\">10</span>\n</a>\n<ul class=\"dropdown-menu\">\n  <li class=\"header\">You have 10 notifications</li>\n  <li>\n    <!-- inner menu: contains the actual data -->\n    <ul class=\"menu\">\n      <li>\n        <a href=\"#\">\n          <i class=\"fa fa-users text-aqua\"></i> 5 new members joined today\n        </a>\n      </li>\n      <li>\n        <a href=\"#\">\n          <i class=\"fa fa-warning text-yellow\"></i> Very long description here that may not fit into the\n          page and may cause design problems\n        </a>\n      </li>\n      <li>\n        <a href=\"#\">\n          <i class=\"fa fa-users text-red\"></i> 5 new members joined\n        </a>\n      </li>\n\n      <li>\n        <a href=\"#\">\n          <i class=\"fa fa-shopping-cart text-green\"></i> 25 sales made\n        </a>\n      </li>\n      <li>\n        <a href=\"#\">\n          <i class=\"fa fa-user text-red\"></i> You changed your username\n        </a>\n      </li>\n    </ul>\n  </li>\n  <li class=\"footer\"><a href=\"#\">View all</a></li>\n</ul>\n</li>\n```\n\nMore components can be found here [Bootstrap](https://getbootstrap.com/)\n"
  },
  {
    "path": "docs/en/extension-api-tester.md",
    "content": "# Laravel API tester\n\n`api-tester` is an API testing tool developed for `laravel` that helps you test your laravel API like `postman`.\n\n![wx20170809-164424](https://user-images.githubusercontent.com/1479100/29112946-1e32971c-7d22-11e7-8cc0-5b7ad25d084e.png)\n\n## Installation\n\n```shell\n$ composer require laravel-admin-ext/api-tester -vvv\n\n$ php artisan vendor:publish --tag=api-tester\n\n```\nAnd then run the following command to import menus and permissions (which can also be added manually)\n\n```shell\n$ php artisan admin:import api-tester\n```\n\nThen you can find the entry link in the admin menu, `http://localhost/admin/api-tester`.\n\n## Usage\n\nOpen `routes/api.php` try to add an api:\n\n```php\nRoute::get('test', function () {\n    return 'hello world';\n});\n```\n\nOpen the `api-tester` page, you can see `api/test` on the left, select it and click the `Send` button to send request to the api\n\n### Login as\n\n`Login as` Fill in the user id you want to log in, you can log in as the user to request the API, add the following API:\n\n```php\nuse Illuminate\\Http\\Request;\n\nRoute::middleware('auth:api')->get('user', function (Request $request) {\n    return $request->user();\n});\n```\nFill in the user ID in `Login as` input , then request the api and will respond with the user's model\n\n### Parameters\n\nUsed to set the request parameters for api , the type can be a string or file, add the following API:\n\n```php\nuse Illuminate\\Http\\Request;\n\nRoute::get('parameters', function (Request $request) {\n    return $request->all();\n});\n```\n\nFill in the parameters send request and you can see the results"
  },
  {
    "path": "docs/en/extension-config.md",
    "content": "# Configuration management\n\nThis tool will store the configuration data in the database\n\n![wx20170810-100226](https://user-images.githubusercontent.com/1479100/29151322-0879681a-7db3-11e7-8005-03310686c884.png)\n\n## Installation\n\n```\n$ composer require laravel-admin-ext/config\n\n$ php artisan migrate\n```\n\nOpen `app/Providers/AppServiceProvider.php`, and call the `Config::load()` method within the `boot` method:\n\n```php\n<?php\n\nnamespace App\\Providers;\n\nuse Encore\\Admin\\Config\\Config;\nuse Illuminate\\Support\\ServiceProvider;\n\nclass AppServiceProvider extends ServiceProvider\n{\n    public function boot()\n    {\n        Config::load();  // Add this\n    }\n}\n```\n\nThen run the command to import menus and permissions (which can also be added manually)\n\n```\n$ php artisan admin:import config\n```\n\nOpen `http://localhost/admin/config`.\n\n## Usage\n\nAfter add config in the panel, use `config($key)` to get value you configured."
  },
  {
    "path": "docs/en/extension-helpers.md",
    "content": "# Helpers\n\nAdded support for developers, available in development to help improve efficiency, currently providing `scaffolding`, `database command line` and `artisan command line `three tools, if there are better other utilities The idea of welcome to provide advice.\n\nInstallation:\n```php\ncomposer require laravel-admin-ext/helpers\n\nphp artisan admin:import helpers\n```\n\n> Part of the function of the tool will create or delete files in the project, there may be some file or directory permissions errors, the problem needs to be resolved.\n> Another part of the database and artisan command can not be used in the web environment.\n    \n## Scaffold\n\nThis Tool can help you build controller, model, migrate files, and run migration files.\naccess by visit `http://localhost/admin/helpers/scaffold`.\n\nWhich set the migration table structure, the primary key field is automatically generated do not need to fill out.\n\n![qq20170220-2](https://cloud.githubusercontent.com/assets/1479100/23147949/cbf03e84-f81d-11e6-82b7-d7929c3033a0.png)\n\n## Database command line\n\nDatabase command line tool for web integration,Currently supports `mysql`,` mongodb` and `redis`,access by visit `http://localhost/admin/helpers/terminal/database`.\n\nChange the database connection in the upper right corner, and then in the bottom of the input box to enter the corresponding database query and then enter, you can get the query results:\n\n![qq20170220-3](https://cloud.githubusercontent.com/assets/1479100/23147951/ce08e5d6-f81d-11e6-8b20-605e8cd06167.png)\n\nThe use of the database and the operation of the database is consistent, you can run the selected database support query.\n\n## Artisan command line\n\nWeb version of `Laravel`'s `artisan` command line,you can run artisan commands in it,access it by visit `http://localhost/admin/helpers/terminal/artisan`.\n\n![qq20170220-1](https://cloud.githubusercontent.com/assets/1479100/23147963/da8a5d30-f81d-11e6-97b9-239eea900ad3.png)\n\n\n## Route list\n\nThis tool can use more intuitive to show all the routes, including uri, http methods and middleware, and also you can query routes. access it by visit`http://localhost/admin/helpers/routes`.\n\n![helpers_routes](https://user-images.githubusercontent.com/1479100/30899066-e8bdd5ca-a390-11e7-809d-4ceccd0da27f.png)"
  },
  {
    "path": "docs/en/extension-media-manager.md",
    "content": "# Media manager\n\nThis tool for manage local files\n\n![wx20170809-170104](https://user-images.githubusercontent.com/1479100/29113762-99886c32-7d24-11e7-922d-5981a5849c7a.png)\n\n## Installation\n\n```\n$ composer require laravel-admin-ext/media-manager -vvv\n\n$ php artisan admin:import media-manager\n```\n\n## Configuration\n\nOpen  `config/admin.php` specify the disk you want to manage\n\n```php\n\n    'extensions' => [\n\n        'media-manager' => [\n            'disk' => 'public'   // Points to the disk set in config/filesystem.php\n        ],\n    ],\n\n```\n\n`disk` is the local disk you configured in `config/filesystem.php`, visit by access `http://localhost/admin/media`.\n\nNote If you want to preview the picture in the disk, you must set the access url in the disk configuration:\n\n\n`config/filesystem.php`：\n```php\n\n    'disks' => [\n\n        'public' => [\n            'driver' => 'local',\n            'root' => storage_path('app/public'),\n            'url' => env('APP_URL').'/storage',    // set url\n            'visibility' => 'public',\n        ],\n        \n        ...\n    ]\n```\n\n"
  },
  {
    "path": "docs/en/extension-scheduling.md",
    "content": "# Task scheduling\n\nThis tool is a web interface for manage Laravel's scheduled tasks\n\n![wx20170810-101048](https://user-images.githubusercontent.com/1479100/29151552-8affc0b2-7db4-11e7-932a-a10d8a42ec50.png)\n\n## Installation\n\n```\n$ composer require laravel-admin-ext/scheduling -vvv\n\n$ php artisan admin:import scheduling\n```\n\nThen open `http://localhost/admin/scheduling`\n\n## Add tasks\n\nOpen `app/Console/Kernel.php`, try adding two scheduled tasks:\n\n```php\nclass Kernel extends ConsoleKernel\n{\n    protected function schedule(Schedule $schedule)\n    {\n        $schedule->command('inspire')->everyTenMinutes();\n        \n        $schedule->command('route:list')->dailyAt('02:00');\n    }\n}\n\n```\n\nAnd then you can see the tasks with details in the page, and you can also directly run these two tasks in the page.\n"
  },
  {
    "path": "docs/en/installation.md",
    "content": "# Installation\n\n> This package requires PHP 7+ and Laravel 5.5, for old versions please refer to [1.4](http://laravel-admin.org/docs/v1.4/#/)\n\nFirst, install laravel, and make sure that the database connection settings are correct.\n\nThen install require this package with command:\n```\ncomposer require encore/laravel-admin \"1.5.*\"\n```\n\nPublish assets and config with command：\n```\nphp artisan vendor:publish --provider=\"Encore\\Admin\\AdminServiceProvider\"\n```\n\nAfter runnung previous command you can find config file in `config/admin.php`, in this file you can change default install directory (```/app/Admin```), db connection or table names.\n\nAt last run following command to finish install:\n```\nphp artisan admin:install\n```\n\nTo check that all is working, run `php artisan serve` and open `http://localhost/admin/` in browser, use username `admin` and password `admin` to login.\n\n## Generated files\n\nAfter the installation is complete, the following files are generated in the project directory:\n\n### Configuration file\n\nAfter the installation is complete, all configurations are in the `config/admin.php` file.\n\n### Admin files\n\nAfter install,you can find directory`app/Admin`,and then most of our develop work is under this directory.\n\n```\napp/Admin\n├── Controllers\n│   ├── ExampleController.php\n│   └── HomeController.php\n├── bootstrap.php\n└── routes.php\n```\n\n`app/Admin/routes.php` is used to define routes.\n\n`app/Admin/bootstrap.php` is bootstrapper for laravel-admin, for usage examples see comments inside it.\n\nThe `app/Admin/Controllers` directory is used to store all the controllers.\nThe `HomeController.php` file under this directory is used to handle home request of admin.\nThe `ExampleController.php` file is a controller example.\n\n### Static assets\n\nThe front-end static files are in the `/public/packages/admin` directory.\n"
  },
  {
    "path": "docs/en/model-form-callback.md",
    "content": "# Model form callback\n\n`model-form` currently has three methods for receiving callback functions:\n\n```php\n// callback after form submission\n$form->submitted(function (Form $form) {\n    //...\n});\n\n// callback before save\n$form->saving(function (Form $form) {\n    //...\n});\n\n// callback after save\n$form->saved(function (Form $form) {\n    //...\n});\n\n```\nIf required, you can add additional fields to ignore using the submitted function e.g.\n```php\n$form->submitted(function (Form $form) {\n    $form->ignore('username');\n\n});\n\n```\nThe form data that is currently submitted can be retrieved from the callback parameter `$form`:\n\n```php\n$form->saving(function (Form $form) {\n\n    dump($form->username);\n\n});\n\n```\n\nGet data in model\n```php\n$form->saved(function (Form $form) {\n\n    $form->model()->id;\n\n});\n```\n\nCan redirect other urls by returning an instance of `Symfony\\Component\\HttpFoundation\\Response` directly in the callback:\n\n```php\n$form->saving(function (Form $form) {\n\n    // returns a simple response\n    return response('xxxx');\n\n});\n\n$form->saving(function (Form $form) {\n\n    // redirect url\n    return redirect('/admin/users');\n\n});\n\n$form->saving(function (Form $form) {\n\n    // throws an exception\n    throw new \\Exception('Error friends. . .');\n\n});\n\n```\n\nReturn error or success information on the page:\n\n```php\nuse Illuminate\\Support\\MessageBag;\n\n// redirect back with an error message\n$form->saving(function ($form) {\n\n    $error = new MessageBag([\n        'title'   => 'title...',\n        'message' => 'message....',\n    ]);\n\n    return back()->with(compact('error'));\n});\n\n// redirect back with a successful message\n$form->saving(function ($form) {\n\n    $success = new MessageBag([\n        'title'   => 'title...',\n        'message' => 'message....',\n    ]);\n\n    return back()->with(compact('success'));\n});\n\n```\n"
  },
  {
    "path": "docs/en/model-form-field-management.md",
    "content": "# Fields management\n\n\n## Remove field\n\nThe built-in `map` and `editor` fields requires the front-end files via cdn, and if there are problems with the network, they can be removed in the following ways\n\nLocate the file `app/Admin/bootstrap.php`. If the file does not exist, update `laravel-admin` and create this file.\n\n```php\n\n<?php\n\nuse Encore\\Admin\\Form;\n\nForm::forget('map');\nForm::forget('editor');\n\n// or\n\nForm::forget(['map', 'editor']);\n\n```\n\nThis removes the two fields, which can be used to remove the other fields.\n\n## Extend the custom field\n\nExtend a PHP code editor based on [codemirror](http://codemirror.net/index.html) with the following steps.\n\nsee [PHP mode](http://codemirror.net/mode/php/).\n\nDownload and unzip the [codemirror](http://codemirror.net/codemirror.zip) library to the front-end resource directory, for example, in the directory `public/packages/codemirror-5.20.2`.\n\nCreate a new field class `app/Admin/Extensions/PHPEditor.php`:\n\n```php\n<?php\n\nnamespace App\\Admin\\Extensions;\n\nuse Encore\\Admin\\Form\\Field;\n\nclass PHPEditor extends Field\n{\n    protected $view = 'admin.php-editor';\n\n    protected static $css = [\n        '/packages/codemirror-5.20.2/lib/codemirror.css',\n    ];\n\n    protected static $js = [\n        '/packages/codemirror-5.20.2/lib/codemirror.js',\n        '/packages/codemirror-5.20.2/addon/edit/matchbrackets.js',\n        '/packages/codemirror-5.20.2/mode/htmlmixed/htmlmixed.js',\n        '/packages/codemirror-5.20.2/mode/xml/xml.js',\n        '/packages/codemirror-5.20.2/mode/javascript/javascript.js',\n        '/packages/codemirror-5.20.2/mode/css/css.js',\n        '/packages/codemirror-5.20.2/mode/clike/clike.js',\n        '/packages/codemirror-5.20.2/mode/php/php.js',\n    ];\n\n    public function render()\n    {\n        $this->script = <<<EOT\n\nCodeMirror.fromTextArea(document.getElementById(\"{$this->id}\"), {\n    lineNumbers: true,\n    mode: \"text/x-php\",\n    extraKeys: {\n        \"Tab\": function(cm){\n            cm.replaceSelection(\"    \" , \"end\");\n        }\n     }\n});\n\nEOT;\n        return parent::render();\n\n    }\n}\n\n```\n\n>Static resources in the class can also be imported from outside, see [Editor.php](https://github.com/z-song/laravel-admin/blob/1.3/src/Form/Field/Editor.php)\n\nCreate a view file `resources/views/admin/php-editor.blade.php`:\n\n```php\n\n<div class=\"form-group {!! !$errors->has($label) ?: 'has-error' !!}\">\n\n    <label for=\"{{$id}}\" class=\"col-sm-2 control-label\">{{$label}}</label>\n\n    <div class=\"col-sm-6\">\n\n        @include('admin::form.error')\n\n        <textarea class=\"form-control\" id=\"{{$id}}\" name=\"{{$name}}\" placeholder=\"{{ trans('admin::lang.input') }} {{$label}}\" {!! $attributes !!} >{{ old($column, $value) }}</textarea>\n    </div>\n</div>\n\n```\n\nFinally, find the file `app/Admin/bootstrap.php`, if the file does not exist, update `laravel-admin`, and then create this file, add the following code:\n\n```\n<?php\n\nuse App\\Admin\\Extensions\\PHPEditor;\nuse Encore\\Admin\\Form;\n\nForm::extend('php', PHPEditor::class);\n\n```\n\nAnd then you can use PHP editor in [model-form](/en/model-form.md):\n\n```\n\n$form->php('code');\n\n```\n\nIn this way, you can add any form fields you want to add.\n\n## Integrate CKEditor\n\nHere is another example to show you how to integrate ckeditor.\n\nAt first download [CKEditor](http://ckeditor.com/download), unzip to public directory, for example `public/packages/ckeditor/`.\n\nThen Write Extension class `app/Admin/Extensions/Form/CKEditor.php`:\n```php\n<?php\n\nnamespace App\\Admin\\Extensions\\Form;\n\nuse Encore\\Admin\\Form\\Field;\n\nclass CKEditor extends Field\n{\n    public static $js = [\n        '/packages/ckeditor/ckeditor.js',\n        '/packages/ckeditor/adapters/jquery.js',\n    ];\n\n    protected $view = 'admin.ckeditor';\n\n    public function render()\n    {\n        $this->script = \"$('textarea.{$this->getElementClass()}').ckeditor();\";\n\n        return parent::render();\n    }\n}\n```\nAdd blade file `resources/views/admin/ckeditor.blade.php` for view `admin.ckeditor` : \n```php\n<div class=\"form-group {!! !$errors->has($errorKey) ?: 'has-error' !!}\">\n\n    <label for=\"{{$id}}\" class=\"col-sm-2 control-label\">{{$label}}</label>\n\n    <div class=\"col-sm-6\">\n\n        @include('admin::form.error')\n\n        <textarea class=\"form-control {{$class}}\" id=\"{{$id}}\" name=\"{{$name}}\" placeholder=\"{{ $placeholder }}\" {!! $attributes !!} >{{ old($column, $value) }}</textarea>\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>\n\n```\nRegister this extension in `app/Admin/bootstrap.php`:\n\n```php\nuse Encore\\Admin\\Form;\nuse App\\Admin\\Extensions\\Form\\CKEditor;\n\nForm::extend('ckeditor', CKEditor::class);\n```\nAfter this you can use ckeditor in your form:\n\n```php\n$form->ckeditor('content');\n```\n"
  },
  {
    "path": "docs/en/model-form-fields.md",
    "content": "# Builtin form fields\n\nThere are a lots of form components built into the `model-form` to help you quickly build forms.\n\n## Public methods\n\n### Set the value to save\n```php\n$form->text('title')->value('text...');\n```\n\n### Set default value\n```php\n$form->text('title')->default('text...');\n```\n\n### Set help message\n```php\n$form->text('title')->help('help...');\n```\n\n### Set fa-icon class\n```php\n$form->text('title')->icon('fa-copy');\n```\n\n### Set attributes of field element\n```php\n$form->text('title')->attribute(['data-title' => 'title...']);\n\n$form->text('title')->attribute('data-title', 'title...');\n```\n\n### Set placeholder\n```php\n$form->text('title')->placeholder('Please input...');\n```\n\n### Model-form-tab\n\nIf the form contains too many fields, will lead to form page is too long, in which case you can use the tab to separate the form:\n\n```php\n\n$form->tab('Basic info', function ($form) {\n    \n    $form->text('username');\n    $form->email('email');\n    \n})->tab('Profile', function ($form) {\n                       \n   $form->image('avatar');\n   $form->text('address');\n   $form->mobile('phone');\n   \n})->tab('Jobs', function ($form) {\n                         \n     $form->hasMany('jobs', function () {\n         $form->text('company');\n         $form->date('start_date');\n         $form->date('end_date');\n     });\n\n  })\n\n```\n\n## Text input\n\n```php\n$form->text($column, [$label]);\n\n// Add a submission validation rule\n$form->text($column, [$label])->rules('required|min:10');\n```\n\n## Select\n```php\n$form->select($column[, $label])->options([1 => 'foo', 2 => 'bar', 'val' => 'Option name']);\n```\n\nIf have too many options, you can load option by ajax:\n\n```php\n$form->select('user_id')->options(function ($id) {\n    $user = User::find($id);\n\n    if ($user) {\n        return [$user->id => $user->name];\n    }\n})->ajax('/admin/api/users');\n\n// using ajax and show selected item:\n\n$form->select('user_id')->options(User::class)->ajax('/admin/api/users');\n\n// or specifying the name and id\n\n$form->select('user_id')->options(User::class, 'name', 'id')->ajax('/admin/api/users');\n```\n\n<sub>Notice：if you have modified the value of the `route.prefix` in the `config/admin.php` file, this api route should be modified to `config('admin.route.prefix').'/api/users'`.</sub>\n\nThe controller method for api `/admin/api/users` is:\n\n```php\npublic function users(Request $request)\n{\n    $q = $request->get('q');\n\n    return User::where('name', 'like', \"%$q%\")->paginate(null, ['id', 'name as text']);\n}\n\n```\n\nThe json returned from api `/admin/demo/options`:\n```\n{\n    \"total\": 4,\n    \"per_page\": 15,\n    \"current_page\": 1,\n    \"last_page\": 1,\n    \"next_page_url\": null,\n    \"prev_page_url\": null,\n    \"from\": 1,\n    \"to\": 3,\n    \"data\": [\n        {\n            \"id\": 9,\n            \"text\": \"xxx\"\n        },\n        {\n            \"id\": 21,\n            \"text\": \"xxx\"\n        },\n        {\n            \"id\": 42,\n            \"text\": \"xxx\"\n        },\n        {\n            \"id\": 48,\n            \"text\": \"xxx\"\n        }\n    ]\n}\n```\n\n### Select linkage\n\n`select` component supports one-way linkage of parent-child relationship:\n```php\n$form->select('province')->options(...)->load('city', '/api/city');\n\n$form->select('city');\n\n```\n\nWhere `load('city', '/api/city');` means that, after the current select option is changed, the current option will call the api `/api/city` via the argument` q` api returns the data to fill the options for the city selection box, where api `/api/city` returns the data format that must match:\n\n```php\n[\n    {\n        \"id\": 1,\n        \"text\": \"foo\"\n    },\n    {\n        \"id\": 2,\n        \"text\": \"bar\"\n    },\n    ...\n]\n```\nThe code for the controller action is as follows:\n\n```php\npublic function city(Request $request)\n{\n    $provinceId = $request->get('q');\n\n    return ChinaArea::city()->where('parent_id', $provinceId)->get(['id', DB::raw('name as text')]);\n}\n```\n\n## Multiple select\n```php\n$form->multipleSelect($column[, $label])->options([1 => 'foo', 2 => 'bar', 'val' => 'Option name']);\n\n// using ajax and show selected items:\n\n$form->multipleSelect($column[, $label])->options(Model::class)->ajax('ajax_url');\n\n// or specifying the name and id\n\n$form->multipleSelect($column[, $label])->options(Model::class, 'name', 'id')->ajax('ajax_url');\n```\n\nYou can store value of multiple select in two ways, one is `many-to-many` relation.\n\n```\n\nclass Post extends Models\n{\n    public function tags()\n    {\n        return $this->belongsToMany(Tag::class);\n    }\n}\n\n$form->multipleSelect('tags')->options(Tag::all()->pluck('name', 'id'));\n\n```\n\nThe second is to store the option array into a single field. If the field is a string type, it is necessary to define [accessor and Mutator](https://laravel.com/docs/5.5/eloquent-mutators) for the field.\n\nIf have too many options, you can load option by ajax\n\n```php\n$form->select('user_id')->options(function ($id) {\n    $user = User::find($id);\n\n    if ($user) {\n        return [$user->id => $user->name];\n    }\n})->ajax('/admin/api/users');\n```\n\n<sub>Notice：If you have modified the value of the `route.prefix` in the `config/admin.php` file, this api route should be modified to `config('admin.route.prefix').'/api/users'`.</sub>\n\nThe controller method for api `/admin/api/users` is:\n\n```php\npublic function users(Request $request)\n{\n    $q = $request->get('q');\n\n    return User::where('name', 'like', \"%$q%\")->paginate(null, ['id', 'name as text']);\n}\n\n```\n\nThe json returned from api `/admin/demo/options`:\n```\n{\n    \"total\": 4,\n    \"per_page\": 15,\n    \"current_page\": 1,\n    \"last_page\": 1,\n    \"next_page_url\": null,\n    \"prev_page_url\": null,\n    \"from\": 1,\n    \"to\": 3,\n    \"data\": [\n        {\n            \"id\": 9,\n            \"text\": \"xxx\"\n        },\n        {\n            \"id\": 21,\n            \"text\": \"xxx\"\n        },\n        {\n            \"id\": 42,\n            \"text\": \"xxx\"\n        },\n        {\n            \"id\": 48,\n            \"text\": \"xxx\"\n        }\n    ]\n}\n```\n\n## Listbox\n\nThe usage is as same as mutipleSelect.\n\n```php\n$form->listbox($column[, $label])->options([1 => 'foo', 2 => 'bar', 'val' => 'Option name']);\n```\n\n## Textarea\n```php\n$form->textarea($column[, $label])->rows(10);\n```\n\n## Radio\n```php\n$form->radio($column[, $label])->options(['m' => 'Female', 'f'=> 'Male'])->default('m');\n\n$form->radio($column[, $label])->options(['m' => 'Female', 'f'=> 'Male'])->default('m')->stacked();\n```\n\n## Checkbox\n\n`checkbox` can store values in two ways, see[multiple select](#Multiple select)\n\nThe `options()` method is used to set options:\n```php\n$form->checkbox($column[, $label])->options([1 => 'foo', 2 => 'bar', 'val' => 'Option name']);\n\n$form->checkbox($column[, $label])->options([1 => 'foo', 2 => 'bar', 'val' => 'Option name'])->stacked();\n```\n\n## Email input\n```php\n$form->email($column[, $label]);\n```\n\n## Password input\n```php\n$form->password($column[, $label]);\n```\n\n## URL input\n```php\n$form->url($column[, $label]);\n```\n\n## Ip input\n```php\n$form->ip($column[, $label]);\n```\n\n## Phone number input\n```php\n$form->mobile($column[, $label])->options(['mask' => '999 9999 9999']);\n```\n\n## Color select\n```php\n$form->color($column[, $label])->default('#ccc');\n```\n\n## Time input\n```php\n$form->time($column[, $label]);\n\n// Set the time format, more formats reference http://momentjs.com/docs/#/displaying/format/    \n$form->time($column[, $label])->format('HH:mm:ss');\n```\n\n## Date input\n```php\n$form->date($column[, $label]);\n\n// Date format setting,more format please see http://momentjs.com/docs/#/displaying/format/\n$form->date($column[, $label])->format('YYYY-MM-DD');\n```\n\n## Datetime input\n```php\n$form->datetime($column[, $label]);\n\n// Set the date format, more format reference http://momentjs.com/docs/#/displaying/format/\n$form->datetime($column[, $label])->format('YYYY-MM-DD HH:mm:ss');\n```\n\n## Time range select\n`$startTime`、`$endTime`is the start and end time fields:\n```php\n$form->timeRange($startTime, $endTime, 'Time Range');\n```\n\n## Date range select\n`$startDate`、`$endDate`is the start and end date fields:\n```php\n$form->dateRange($startDate, $endDate, 'Date Range');\n```\n\n## Datetime range select\n`$startDateTime`、`$endDateTime` is the start and end datetime fields:\n```php\n$form->datetimeRange($startDateTime, $endDateTime, 'DateTime Range');\n```\n\n## Currency input\n```php\n$form->currency($column[, $label]);\n\n// set the unit symbol\n$form->currency($column[, $label])->symbol('￥');\n\n```\n\n## Number input\n```php\n$form->number($column[, $label]);\n```\n\n## Rate input\n```php\n$form->rate($column[, $label]);\n```\n\n## Image upload\n\nBefore use upload field, you must complete upload configuration, see [image/file upload](/en/model-form-upload.md).\n\nYou can use compression, crop, add watermarks and other methods, please refer to [[Intervention] (http://image.intervention.io/getting_started/introduction)], picture upload directory in the file `config / admin.php` `Upload.image` configuration, if the directory does not exist, you need to create the directory and open write permissions:\n```php\n$form->image($column[, $label]);\n\n// Modify the image upload path and file name\n$form->image($column[, $label])->move($dir, $name);\n\n// Crop picture\n$form->image($column[, $label])->crop(int $width, int $height, [int $x, int $y]);\n\n// Add a watermark\n$form->image($column[, $label])->insert($watermark, 'center');\n\n// add delete button\n$form->image($column[, $label])->removable();\n\n```\n\n## File upload\n\nBefore use upload field, you must complete upload configuration, see [image/file upload](/en/model-form-upload.md).\n\nThe file upload directory is configured in `upload.file` in the file `config/admin.php`. If the directory does not exist, it needs to be created and write-enabled.\n```php\n$form->file($column[, $label]);\n\n// Modify the file upload path and file name\n$form->file($column[, $label])->move($dir, $name);\n\n// And set the upload file type\n$form->file($column[, $label])->rules('mimes:doc,docx,xlsx');\n\n// add delete button\n$form->file($column[, $label])->removable();\n\n```\n\n## Multiple image/file upload\n\n```php\n// multiple image\n$form->multipleImage($column[, $label]);\n\n// multiple file\n$form->multipleFile($column[, $label]);\n\n// add delete button\n$form->multipleFile($column[, $label])->removable();\n```\n\nThe type of data submitted from multiple image/file field is array, if you the type of column in mysql table is array, or use mongodb, then you can save the array directly, \nbut if you use string type to store the array data ,you need to specify a string format, For example, if you want to use json string to store the array data, you need to define\n a mutator for the column in model mutator, such as the field named `pictures`, define mutator:\n\n```php\npublic function setPicturesAttribute($pictures)\n{\n    if (is_array($pictures)) {\n        $this->attributes['pictures'] = json_encode($pictures);\n    }\n}\n\npublic function getPicturesAttribute($pictures)\n{\n    return json_decode($pictures, true);\n}\n```\nOf course, you can also specify any other format.\n\n## Map\n\nThe map field refers to the network resource, and if there is a problem with the network refer to [form Component Management](/en/model-form-field-management.md) to remove the component.\n\nUsed to select the latitude and longitude, `$ latitude`,` $ longitude` for the latitude and longitude field, using Tencent map when `locale` set of laravel is` zh_CN`, otherwise use Google Maps:\n```php\n$form->map($latitude, $longitude, $label);\n\n// Use Tencent map\n$form->map($latitude, $longitude, $label)->useTencentMap();\n\n// Use google map\n$form->map($latitude, $longitude, $label)->useGoogleMap();\n```\n\n## Slider\nCan be used to select the type of digital fields, such as age:\n```php\n$form->slider($column[, $label])->options(['max' => 100, 'min' => 1, 'step' => 1, 'postfix' => 'years old']);\n```\nMore options please ref to https://github.com/IonDen/ion.rangeSlider#settings\n\n## Rich text editor\n\nThe editor field refers to the network resource, and if there is a problem with the network refer to [form Component Management](/en/model-form-field-management.md) to remove the component.\n\n```php\n$form->editor($column[, $label]);\n```\n\n## Hidden field\n```php\n$form->hidden($column);\n```\n\n## Switch\n`On` and` off` pairs of switches with the values `1` and` 0`:\n```php\n$states = [\n    'on'  => ['value' => 1, 'text' => 'enable', 'color' => 'success'],\n    'off' => ['value' => 0, 'text' => 'disable', 'color' => 'danger'],\n];\n\n$form->switch($column[, $label])->states($states);\n```\n\n## Display field\nOnly display the fields and without any action:\n```php\n$form->display($column[, $label]);\n```\n\n## Divide\n```php\n$form->divide();\n```\n\n## Html\ninsert html,the argument passed in could be objects which impletements `Htmlable`、`Renderable`, or has method `__toString()`\n```php\n$form->html('html contents');\n```\n\n## Tags\nInsert the comma (,) separated string `tags`\n```php\n$form->tags('keywords');\n```\n\n## Icon\nSelect the `font-awesome` icon.\n```php\n$form->icon('icon');\n```\n\n## HasMany\n\nOne-to-many built-in tables for dealing with one-to-many relationships. Here is a simple example:\n\nThere are two tables are one-to-many relationship:\n\n```sql\nCREATE TABLE `demo_painters` (\n  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n  `username` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n  `bio` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;\n\nCREATE TABLE `demo_paintings` (\n  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n  `painter_id` int(10) unsigned NOT NULL,\n  `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n  `body` text COLLATE utf8_unicode_ci NOT NULL,\n  `completed_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  PRIMARY KEY (`id`),\n  KEY painter_id (`painter_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;\n```\n\nThe model of tables are:\n```php\n<?php\n\nnamespace App\\Models\\Demo;\n\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass Painter extends Model\n{\n    public function paintings()\n    {\n        return $this->hasMany(Painting::class, 'painter_id');\n    }\n}\n\n<?php\n\nnamespace App\\Models\\Demo;\n\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass Painting extends Model\n{\n    protected $fillable = ['title', 'body', 'completed_at'];\n\n    public function painter()\n    {\n        return $this->belongsTo(Painter::class, 'painter_id');\n    }\n}\n```\n\nBuild the form code as follows:\n```php\n$form->display('id', 'ID');\n\n$form->text('username')->rules('required');\n$form->textarea('bio')->rules('required');\n\n$form->hasMany('paintings', function (Form\\NestedForm $form) {\n    $form->text('title');\n    $form->image('body');\n    $form->datetime('completed_at');\n});\n\n$form->display('created_at', 'Created At');\n$form->display('updated_at', 'Updated At');\n```\n\n## Embeds\n\nUsed to handle the `JSON` type field data of `mysql` or `object` type data of `mongodb`, or the data values of multiple fields can be stored in the form of the` JSON` string in the character type of mysql\n\nSuch as the `extra` column of the `JSON` or string type in the orders table, used to store data for multiple fields:\n\n```php\nclass Order extends Model\n{\n    protected $casts = [\n        'extra' => 'json',\n    ];\n}\n```\nAnd then use in the form:\n```php\n$form->embeds('extra', function ($form) {\n\n    $form->text('extra1')->rules('required');\n    $form->email('extra2')->rules('required');\n    $form->mobile('extra3');\n    $form->datetime('extra4');\n\n    $form->dateRange('extra5', 'extra6', 'Date range')->rules('required');\n\n});\n\n// Customize the title\n$form->embeds('extra', 'Extra', function ($form) {\n    ...\n});\n```\n\nCallback function inside the form element to create the method call and the outside is the same.\n"
  },
  {
    "path": "docs/en/model-form-upload.md",
    "content": "# File/Image upload\n\n[model-form](/en/model-form.md) can build file and image upload field with following codes\n\n```php\n$form->file('file_column');\n$form->image('image_column');\n```\n\n### Change store path and name\n\n```php\n\n// change upload path\n$form->image('picture')->move('public/upload/image1/');\n\n// use a unique name (md5(uniqid()).extension)\n$form->image('picture')->uniqueName();\n\n// specify filename\n$form->image('picture')->name(function ($file) {\n    return 'test.'.$file->guessExtension();\n});\n\n```\n\n[model-form](/en/model-form.md) both support for local and cloud storage upload\n\n### Upload to local\n\nfirst add storage configuration, add a disk in `config/filesystems.php`:\n\n```php\n\n'disks' => [\n    ... ,\n\n    'admin' => [\n        'driver' => 'local',\n        'root' => public_path('uploads'),\n        'visibility' => 'public',\n        'url' => env('APP_URL').'/uploads',\n    ],\n],\n\n```\n\nset upload path to `public/upload`(public_path('upload')).\n\nAnd then in `config/admin.php` select the `disk` set up above：\n\n```php\n\n'upload'  => [\n\n    'disk' => 'admin',\n\n    'directory'  => [\n        'image'  => 'image',\n        'file'   => 'file',\n    ],\n],\n\n```\n\nSet `disk` to the` admin` that you added above,`directory.image` and `directory.file` is the upload path for `$form->image($column)` and `$form->file($column)`.\n\n`host` is url prefix for your uploaded files.\n\n\n### Upload to cloud\n\nIf you need to upload to the cloud storage, need to install a driver which supports `flysystem` adapter, take `qiniu` cloud storage as example.\n\nfirst install [zgldh/qiniu-laravel-storage](https://github.com/zgldh/qiniu-laravel-storage).\n\nAlso configure the disk, in the `config/filesystems.php` add an item:\n\n```php\n'disks' => [\n    ... ,\n    'qiniu' => [\n        'driver'  => 'qiniu',\n        'domains' => [\n            'default'   => 'xxxxx.com1.z0.glb.clouddn.com', \n            'https'     => 'dn-yourdomain.qbox.me',       \n            'custom'    => 'static.abc.com',              \n         ],\n        'access_key'=> '',  //AccessKey\n        'secret_key'=> '',  //SecretKey\n        'bucket'    => '',  //Bucket\n        'notify_url'=> '',  //\n        'url'       => 'http://of8kfibjo.bkt.clouddn.com/',\n    ],\n],\n\n```\n\nThen modify the upload configuration of `laravel-admin` and open `config/admin.php` to find:\n\n```php\n\n'upload'  => [\n\n    'disk' => 'qiniu',\n\n    'directory'  => [\n        'image'  => 'image',\n        'file'   => 'file',\n    ],\n],\n\n```\n\nSelect the above configuration` qiniu` for `disk`"
  },
  {
    "path": "docs/en/model-form-validation.md",
    "content": "Form validation\n========\n\n`model-form` uses laravel's validation rules to verify the data submitted by the form:\n\n```php\n$form->text('title')->rules('required|min:3');\n\n// Complex validation rules can be implemented in the callback\n$form->text('title')->rules(function ($form) {\n    \n    // If it is not an edit state, add field unique verification\n    if (!$id = $form->model()->id) {\n        return 'unique:users,email_address';\n    }\n    \n});\n\n```\n\nYou can also customize the error message for the validation rule:\n\n```php\n$form->text('code')->rules('required|regex:/^\\d+$/|min:10', [\n    'regex' => 'code must be numbers',\n    'min'   => 'code can not be less than 10 characters',\n]);\n```\n\nIf you want to allow the field to be empty, first in the database table to face the field set to `NULL`, and then\n\n```php\n$form->text('title')->rules('nullable');\n```\n\nPlease refer to the more rules [Validation](https://laravel.com/docs/5.5/validation)."
  },
  {
    "path": "docs/en/model-form.md",
    "content": "# Model-Form\n\nThe `Encore\\Admin\\Form` class is used to generate a data model-based form. For example, there is a` movies` table in the database\n\n```sql\nCREATE TABLE `movies` (\n  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n  `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n  `director` int(10) unsigned NOT NULL,\n  `describe` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n  `rate` tinyint unsigned NOT NULL,\n  `released` enum(0, 1),\n  `release_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;\n\n```\n\nThe corresponding data model is `App\\Models\\Movie`, and the following code can generate the` movies` data form:\n\n```php\n\nuse App\\Models\\Movie;\nuse Encore\\Admin\\Form;\nuse Encore\\Admin\\Facades\\Admin;\n\n$grid = Admin::form(Movie::class, function(Form $grid){\n\n    // Displays the record id\n    $form->display('id', 'ID');\n\n    // Add an input box of type text\n    $form->text('title', 'Movie title');\n    \n    $directors = [\n        1 => 'John',\n        2 => 'Smith',\n        3 => 'Kate',\n    ];\n    \n    $form->select('director', 'Director')->options($directors);\n    \n    // Add textarea for the describe field\n    $form->textarea('describe', 'Describe');\n    \n    // Number input\n    $form->number('rate', 'Rate');\n    \n    // Add a switch field\n    $form->switch('released', 'Released?');\n    \n    // Add a date and time selection box\n    $form->dateTime('release_at', 'release time');\n    \n    // Display two time column \n    $form->display('created_at', 'Created time');\n    $form->display('updated_at', 'Updated time');\n});\n\n```\n\n## Custom tools\n\nThe top right corner of the form has two button tools by default. You can modify it in the following way:\n\n```php\n$form->tools(function (Form\\Tools $tools) {\n\n    // Disable back btn.\n    $tools->disableBackButton();\n    \n    // Disable list btn\n    $tools->disableListButton();\n\n    // Add a button, the argument can be a string, or an instance of the object that implements the Renderable or Htmlable interface\n    $tools->add('<a class=\"btn btn-sm btn-danger\"><i class=\"fa fa-trash\"></i>&nbsp;&nbsp;delete</a>');\n});\n```\n\n## Other methods\n\nDisable submit btn:\n\n```php\n$form->disableSubmit();\n```\n\nDisable reset btn:\n```php\n$form->disableReset();\n```\n\nIgnore fields to store\n```php\n$form->ignore('column1', 'column2', 'column3');\n```\n\nSet width for label and field\n\n```php\n$form->setWidth(10, 2);\n```\n\nSet form action\n\n```php\n$form->setAction('admin/users');\n```\n\n## Model relationship\n\n\n### One to One\nThe `users` table and the `profiles` table are generated one-to-one relation through the `profiles.user_id` field.\n\n```sql\n\nCREATE TABLE `users` (\n`id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n`email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\nPRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;\n\nCREATE TABLE `profiles` (\n`id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n`user_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n`age` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n`gender` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\nPRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;\n```\n\nThe corresponding data model are:\n\n```php\n\nclass User extends Model\n{\n    public function profile()\n    {\n        return $this->hasOne(Profile::class);\n    }\n}\n\nclass Profile extends Model\n{\n    public function user()\n    {\n        return $this->belongsTo(User::class);\n    }\n}\n\n```\n\nYou can associate them in a form with the following code:\n\n```php\nAdmin::form(User::class, function (Form $form) {\n\n    $form->display('id');\n\n    $form->text('name');\n    $form->text('email');\n    \n    $form->text('profile.age');\n    $form->text('profile.gender');\n\n    $form->datetime('created_at');\n    $form->datetime('updated_at');\n});\n\n```\n"
  },
  {
    "path": "docs/en/model-grid-actions.md",
    "content": "# Model grid row actions\n\n`model-grid` By default, there are two actions `edit` and `delete`, which can be turned off in the following way:\n\n```php\n $grid->actions(function ($actions) {\n    $actions->disableDelete();\n    $actions->disableEdit();\n});\n```\nYou can get the data for the current row by `$actions` parameter passed in:\n```php\n $grid->actions(function ($actions) {\n    \n    // the array of data for the current row\n    $actions->row;\n    \n    // gets the current row primary key value\n    $actions->getKey();\n});\n```\n\nIf you have a custom action button, you can add the following:\n\n```php\n$grid->actions(function ($actions) {\n    \n    // append an action.\n    $actions->append('<a href=\"\"><i class=\"fa fa-eye\"></i></a>');\n\n    // prepend an action.\n    $actions->prepend('<a href=\"\"><i class=\"fa fa-paper-plane\"></i></a>');\n}\n```\n\nIf you have more complex actions, you can refer to the following ways:\n\nFirst define the action class:\n```php\n<?php\n\nnamespace App\\Admin\\Extensions;\n\nuse Encore\\Admin\\Admin;\n\nclass CheckRow\n{\n    protected $id;\n\n    public function __construct($id)\n    {\n        $this->id = $id;\n    }\n\n    protected function script()\n    {\n        return <<<SCRIPT\n\n$('.grid-check-row').on('click', function () {\n    \n    // Your code.\n    console.log($(this).data('id'));\n    \n});\n\nSCRIPT;\n    }\n\n    protected function render()\n    {\n        Admin::script($this->script());\n\n        return \"<a class='btn btn-xs btn-success fa fa-check grid-check-row' data-id='{$this->id}'></a>\";\n    }\n    \n    public function __toString()\n    {\n        return $this->render();\n    }\n}\n```\nThen add the action:\n```php\n$grid->actions(function ($actions) {\n    \n    // add action\n    $actions->append(new CheckRow($actions->getKey()));\n}\n```\n\nRow manipulations with column conditions:\nFor row attributes, you can use `$row->model()` array or `$row->column()` method.\nYou need to set style after setting attributes. Otherwise style method will be by-passed \n```php\n$grid->rows(function ($row) {\n   // if relased column value is Yes\n   if ( $row->column('released') == 'Yes' ) {\n        // Set attributes for row.\n        $row->setAttributes([ 'data-row-id' => $row->model()['id'], 'data-row-date' => $row->column('release_date') ]);\n        // Set style of row\n        $row->style(\"background-color:green\");\n    }\n\n});\n```\n"
  },
  {
    "path": "docs/en/model-grid-column.md",
    "content": "# Model-grid column\n\n`model-grid` built-in a lot of the operation of the column, you can use these methods very flexible operation of the column data.\n\nThe `Encore\\Admin\\Grid\\Column` object has a built-in `display()` method to handle the value of the current column through the incoming callback function:\n```php\n$grid->column('title')->display(function ($title) {\n\n    return \"<span style='color:blue'>$title</span>\";\n    \n});\n```\n\nThe `display` callback bound to the current row data object as a parent object, you can use the data in current row by this way:\n```php\n\n$grid->first_name();\n\n$grid->last_name();\n\n$grid->column('full_name')->display(function () {\n    return $this->first_name . ' ' . $this->last_name;\n});\n```\n\n> method `value()` is a alias to method `display()`.\n\n## Built-in methods\n\n`model-grid` has built-in methods to help you extend the column functionality\n\n### editable\n\nWith the help of `editable.js`, you can edit the data in the grid directly:\n```php\n$grid->title()->editable();\n\n$grid->title()->editable('textarea');\n\n$grid->title()->editable('select', [1 => 'option1', 2 => 'option2', 3 => 'option3']);\n\n$grid->birth()->editable('date');\n\n$grid->published_at()->editable('datetime');\n\n$grid->column('year')->editable('year');\n\n$grid->column('month')->editable('month');\n\n$grid->column('day')->editable('day');\n\n```\n\n### switch\n\n> notice: If set up a switch for a column the grid, then need to set the column in the form of the same switch\n\nQuickly turn a column into a switch component using the following methods:\n```php\n$grid->status()->switch();\n\n// set the `text`、`color`、and `value`\n$states = [\n    'on'  => ['value' => 1, 'text' => 'YES', 'color' => 'primary'],\n    'off' => ['value' => 2, 'text' => 'NO', 'color' => 'default'],\n];\n$grid->status()->switch($states);\n\n```\n\n### switchGroup\n\n> notice: If set up switch for some columns the grid, then need to set these columns in the form of the same switch\n\nTo quickly change a column into a switch component group, use the following method:\n```php\n$states = [\n    'on' => ['text' => 'YES'],\n    'off' => ['text' => 'NO'],\n];\n\n$grid->column('switch_group')->switchGroup([\n    'hot'       => 'Hot',\n    'new'       => 'New',\n    'recommend' => 'Recommend',\n], $states);\n\n```\n\n### select\n\n```php\n$grid->options()->select([\n    1 => 'Sed ut perspiciatis unde omni',\n    2 => 'voluptatem accusantium doloremque',\n    3 => 'dicta sunt explicabo',\n    4 => 'laudantium, totam rem aperiam',\n]);\n```\n\n### radio\n```php\n$grid->options()->radio([\n    1 => 'Sed ut perspiciatis unde omni',\n    2 => 'voluptatem accusantium doloremque',\n    3 => 'dicta sunt explicabo',\n    4 => 'laudantium, totam rem aperiam',\n]);\n```\n\n### checkbox\n```php\n$grid->options()->checkbox([\n    1 => 'Sed ut perspiciatis unde omni',\n    2 => 'voluptatem accusantium doloremque',\n    3 => 'dicta sunt explicabo',\n    4 => 'laudantium, totam rem aperiam',\n]);\n```\n\n### image\n\n```php\n$grid->picture()->image();\n\n//Set host, width and height\n$grid->picture()->image('http://xxx.com', 100, 100);\n\n// display multiple images\n$grid->pictures()->display(function ($pictures) {\n    \n    return json_decode($pictures, true);\n    \n})->image('http://xxx.com', 100, 100);\n```\n\n### label\n```php\n$grid->name()->label();\n\n//Set color,defaults to `success`, other options `danger`、`warning`、`info`、`primary`、`default`、`success`\n$grid->name()->label('danger');\n\n// can handle a array\n$grid->keywords()->label();\n```\n\n### badge\n\n```php\n$grid->name()->badge();\n\n//Set color,defaults to `success`, other options `danger`、`warning`、`info`、`primary`、`default`、`success`\n$grid->name()->badge('danger');\n\n// can handle a array\n$grid->keywords()->badge();\n```\n\n## Extend the column\n\nThere are two ways to extend the column function, the first one is through the anonymous function.\n\nAdd following code to `app/Admin/bootstrap.php`:\n```php\nuse Encore\\Admin\\Grid\\Column;\n\nColumn::extend('color', function ($value, $color) {\n    return \"<span style='color: $color'>$value</span>\";\n});\n```\nUse this extension in `model-grid`:\n```php\n\n$grid->title()->color('#ccc');\n\n```\n\nIf the column display logic is more complex, you can implement with an extension class.\n\nExtension class `app/Admin/Extensions/Popover.php`:\n```php\n<?php\n\nnamespace App\\Admin\\Extensions;\n\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Grid\\Displayers\\AbstractDisplayer;\n\nclass Popover extends AbstractDisplayer\n{\n    public function display($placement = 'left')\n    {\n        Admin::script(\"$('[data-toggle=\\\"popover\\\"]').popover()\");\n\n        return <<<EOT\n<button type=\"button\"\n    class=\"btn btn-secondary\"\n    title=\"popover\"\n    data-container=\"body\"\n    data-toggle=\"popover\"\n    data-placement=\"$placement\"\n    data-content=\"{$this->value}\"\n    >\n  Popover\n</button>\n\nEOT;\n\n    }\n}\n```\nAnd then register the extension in `app/Admin/bootstrap.php`：\n```php\nuse Encore\\Admin\\Grid\\Column;\nuse App\\Admin\\Extensions\\Popover;\n\nColumn::extend('popover', Popover::class);\n```\nUse the extension in `model-grid`：\n```php\n$grid->desciption()->popover('right');\n```\n\n\n## helpers\n### String operations\nIf the current output data is a string, you can call the method of class `Illuminate\\Support\\Str`.\n\nFor example, the following column shows the string value of the `title` field:\n\n```php\n$grid->title();\n```\n\nCall `Str::limit()` on `title` colum.\n\nCan call `Str::limit()` method on the output string of the `title` column.\n\n```php\n$grid->title()->limit(30);\n```\n\nContinue to call `Illuminate\\Support\\Str` method:\n\n```php\n$grid->title()->limit(30)->ucfirst();\n\n$grid->title()->limit(30)->ucfirst()->substr(1, 10);\n\n```\n\n### Array operations\nIf the current output data is a array, you can call the method of class `Illuminate\\Support\\Collection`.\n\nFor example, the `tags` column is an array of data retrieved from a one-to-many relationship:\n```php\n$grid->tags();\n\narray (\n  0 => \n  array (\n    'id' => '16',\n    'name' => 'php',\n    'created_at' => '2016-11-13 14:03:03',\n    'updated_at' => '2016-12-25 04:29:35',\n    \n  ),\n  1 => \n  array (\n    'id' => '17',\n    'name' => 'python',\n    'created_at' => '2016-11-13 14:03:09',\n    'updated_at' => '2016-12-25 04:30:27',\n  ),\n)\n\n```\n\nCall the `Collection::pluck()` method to get the `name` column from the array\n```php\n$grid->tags()->pluck('name');\n\narray (\n    0 => 'php',\n    1 => 'python',\n  ),\n\n```\n\nThe output data is still a array after above, so you can call methods of `Illuminate\\Support\\Collection` continue.\n\n```php\n$grid->tags()->pluck('name')->map('ucwords');\n\narray (\n    0 => 'Php',\n    1 => 'Python',\n  ),\n```\nOutputs the array as a string\n```php\n$grid->tags()->pluck('name')->map('ucwords')->implode('-');\n\n\"Php-Python\"\n```\n\n### Mixed use\n\nIn the above two types of method calls, as long as the output of the previous step is to determine the type of value, you can call the corresponding type of method, it can be very flexible mix.\n\nFor example, the `images` field is a JSON-formatted string type that stores a multiple-picture address array:\n\n```php\n\n$grid->images();\n\n\"['foo.jpg', 'bar.png']\"\n\n// chain method calls to display multiple images\n$grid->images()->display(function ($images) {\n\n    return json_decode($images, true);\n    \n})->map(function ($path) {\n\n    return 'http://localhost/images/'. $path;\n    \n})->image();\n\n```\n\n\n\n\n"
  },
  {
    "path": "docs/en/model-grid-custom-tools.md",
    "content": "# Custom tools\n\n`model-grid` has `batch delete` and `refresh` operations tools as default, `model-grid` provides custom tool functionality if there are more operational requirements, the following example will show you how to add a `Gender selector` button group tool.\n\nFirst define the tool class `app/Admin/Extensions/Tools/UserGender.php`：\n\n```php\n<?php\n\nnamespace App\\Admin\\Extensions\\Tools;\n\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Grid\\Tools\\AbstractTool;\nuse Illuminate\\Support\\Facades\\Request;\n\nclass UserGender extends AbstractTool\n{\n    protected function script()\n    {\n        $url = Request::fullUrlWithQuery(['gender' => '_gender_']);\n\n        return <<<EOT\n    \n$('input:radio.user-gender').change(function () {\n\n    var url = \"$url\".replace('_gender_', $(this).val());\n\n    $.pjax({container:'#pjax-container', url: url });\n\n});\n\nEOT;\n    }\n\n    public function render()\n    {\n        Admin::script($this->script());\n\n        $options = [\n            'all'   => 'All',\n            'm'     => 'Male',\n            'f'     => 'Female',\n        ];\n\n        return view('admin.tools.gender', compact('options'));\n    }\n}\n\n```\nThe blade file of view `admin.tools.gender` is `resources/views/admin/tools/gender.blade.php`:\n```php\n<div class=\"btn-group\" data-toggle=\"buttons\">\n    @foreach($options as $option => $label)\n    <label class=\"btn btn-default btn-sm {{ \\Request::get('gender', 'all') == $option ? 'active' : '' }}\">\n        <input type=\"radio\" class=\"user-gender\" value=\"{{ $option }}\">{{$label}}\n    </label>\n    @endforeach\n</div>\n```\n\nImport this tool in `model-grid`：\n```php\n\n$grid->tools(function ($tools) {\n    $tools->append(new UserGender());\n});\n\n```\n\nIn the `model-grid`, pass `gender` query to model：\n```php\nif (in_array(Request::get('gender'), ['m', 'f'])) {\n    $grid->model()->where('gender', Request::get('gender'));\n}\n```\n\nYou can refer to the above way to add your own tools.\n\n## Batch operation\n\nAt present, the default implementation of the batch delete operation, if you want to turn off the batch delete operation:\n```php\n$grid->tools(function ($tools) {\n    $tools->batch(function ($batch) {\n        $batch->disableDelete();\n    });\n});\n\n```\n\nIf you want to add a custom batch operation, you can refer to the following example.\n\nThe following example will show you how to implements a `post batch release` operation:\n\nFirst define the tool class `app/Admin/Extensions/Tools/ReleasePost.php`：\n```php\n<?php\n\nnamespace App\\Admin\\Extensions\\Tools;\n\nuse Encore\\Admin\\Grid\\Tools\\BatchAction;\n\nclass ReleasePost extends BatchAction\n{\n    protected $action;\n\n    public function __construct($action = 1)\n    {\n        $this->action = $action;\n    }\n    \n    public function script()\n    {\n        return <<<EOT\n        \n$('{$this->getElementClass()}').on('click', function() {\n\n    $.ajax({\n        method: 'post',\n        url: '{$this->resource}/release',\n        data: {\n            _token:LA.token,\n            ids: selectedRows(),\n            action: {$this->action}\n        },\n        success: function () {\n            $.pjax.reload('#pjax-container');\n            toastr.success('操作成功');\n        }\n    });\n});\n\nEOT;\n\n    }\n}\n```\n\nSee the code above, use ajax to pass the selected `ids` to back-end api through a POST request, the back-end api modifies the state of the corresponding data according to the received `ids`, and then front-end refresh the page (pjax reload), and pop-up a `toastr` prompt operation is successful.\n\nImport this operation in `model-grid`：\n```php\n$grid->tools(function ($tools) {\n    $tools->batch(function ($batch) {\n        $batch->add('Release post', new ReleasePost(1));\n        $batch->add('Unrelease post', new ReleasePost(0));\n    });\n});\n```\n\nSo that the batch operation of the drop-down button will add the following two operations, the final step is to add an api to handle the request of the batch operation, the api code is as follows:\n```php\n\nclass PostController extends Controller\n{\n    ...\n    \n    public function release(Request $request)\n    {\n        foreach (Post::find($request->get('ids')) as $post) {\n            $post->released = $request->get('action');\n            $post->save();\n        }\n    }\n    \n    ...\n}\n```\n\nThen add a route for the api above:\n```php\n$router->post('posts/release', 'PostController@release');\n```\n\nThis completes the entire process."
  },
  {
    "path": "docs/en/model-grid-export.md",
    "content": "Data export\n=======\n\n`model-grid` built-in export function is to achieve a simple csv format file export, if you encounter a file coding problem or can not meet their own needs, you can follow the steps below to customize the export function\n\nThis example uses [Laravel-Excel](https://github.com/Maatwebsite/Laravel-Excel) as an excel library, and of course you can use any other excel library.\n\nFirst install it:\n\n```shell\ncomposer require maatwebsite/excel:~2.1.0\n\nphp artisan vendor:publish --provider=\"Maatwebsite\\Excel\\ExcelServiceProvider\"\n```\n\nAnd then create a new custom export class, such as `app/Admin/Extensions/ExcelExpoter.php`:\n```php\n<?php\n\nnamespace App\\Admin\\Extensions;\n\nuse Encore\\Admin\\Grid\\Exporters\\AbstractExporter;\nuse Maatwebsite\\Excel\\Facades\\Excel;\nuse Illuminate\\Support\\Arr;\n\nclass ExcelExpoter extends AbstractExporter\n{\n    public function export()\n    {\n        Excel::create('Filename', function($excel) {\n\n            $excel->sheet('Sheetname', function($sheet) {\n\n                // This logic get the columns that need to be exported from the table data\n                $rows = collect($this->getData())->map(function ($item) {\n                    return Arr::only($item, ['id', 'title', 'content', 'rate', 'keywords']);\n                });\n\n                $sheet->rows($rows);\n\n            });\n\n        })->export('xls');\n    }\n}\n```\n\nAnd then use this class in `model-grid`:\n```php\n\nuse App\\Admin\\Extensions\\ExcelExpoter;\n\n$grid->exporter(new ExcelExpoter());\n\n```\n\nFor more information on how to use `Laravel-Excel`, refer to [laravel-excel/docs](http://www.maatwebsite.nl/laravel-excel/docs)"
  },
  {
    "path": "docs/en/model-grid-filters.md",
    "content": "# Model grid filters\n\n`model-grid`Provides a set of data filters:\n\n```php\n$grid->filter(function($filter){\n\n    // Remove the default id filter\n    $filter->disableIdFilter();\n\n    // Add a column filter\n    $filter->like('name', 'name');\n    ...\n\n});\n\n```\n\n## Filter type\n\nCurrently supported filter types are the following:\n\n### Equal\n`sql: ... WHERE `column` = \"\"$input\"\"`：\n```php\n$filter->equal('column', $label);\n```\n\n### Not equal\n`sql: ... WHERE `column` != \"\"$input\"\"`：\n```php\n$filter->notEqual('column', $label);\n```\n\n### Like\n`sql: ... WHERE `column` LIKE \"%\"$input\"%\"`：\n```php\n$filter->like('column', $label);\n```\n\n### Ilike\n`sql: ... WHERE `column` ILIKE \"%\"$input\"%\"`：\n```php\n$filter->ilike('column', $label);\n```\n\n### Greater then\n`sql: ... WHERE `column` > \"$input\"`：\n```php\n$filter->gt('column', $label);\n```\n\n### Less than\n`sql: ... WHERE `column` < \"$input\"`：\n```php\n$filter->lt('column', $label);\n```\n\n### Between\n`sql: ... WHERE `column` BETWEEN \"$start\" AND \"$end\"`：\n```php\n$filter->between('column', $label);\n\n// set datetime field type\n$filter->between('column', $label)->datetime();\n\n// set time field type\n$filter->between('column', $label)->time();\n```\n\n### In\n`sql: ... WHERE `column` in (...$inputs)`：\n```php\n$filter->in('column', $label)->multipleSelect(['key' => 'value']);\n```\n\n### NotIn\n`sql: ... WHERE `column` not in (...$inputs)`：\n```php\n$filter->notIn('column', $label)->multipleSelect(['key' => 'value']);\n```\n\n### Date\n`sql: ... WHERE DATE(`column`) = \"$input\"`：\n```php\n$filter->date('column', $label);\n```\n\n### Day\n`sql: ... WHERE DAY(`column`) = \"$input\"`：\n```php\n$filter->day('column', $label);\n```\n\n### Month\n`sql: ... WHERE MONTH(`column`) = \"$input\"`：\n```php\n$filter->month('column', $label);\n```\n\n### year\n`sql: ... WHERE YEAR(`column`) = \"$input\"`：\n```php\n$filter->year('column', $label);\n```\n\n### Where\n\nYou can use `where` to build more complex query filtering\n\n`sql: ... WHERE `title` LIKE \"%$input\" OR `content` LIKE \"%$input\"`：\n```php\n$filter->where(function ($query) {\n\n    $query->where('title', 'like', \"%{$this->input}%\")\n        ->orWhere('content', 'like', \"%{$this->input}%\");\n\n}, 'Text');\n```\n\n`sql: ... WHERE `rate` >= 6 AND `created_at` = {$input}`:\n```php\n$filter->where(function ($query) {\n\n    $query->whereRaw(\"`rate` >= 6 AND `created_at` = {$this->input}\");\n\n}, 'Text');\n```\n\nRelationship query, query the corresponding relationship `profile` field:\n```php\n$filter->where(function ($query) {\n\n    $query->whereHas('profile', function ($query) {\n        $query->where('address', 'like', \"%{$this->input}%\")->orWhere('email', 'like', \"%{$this->input}%\");\n    });\n\n}, 'Address or mobile');\n```\n\n## Field type\n\nThe default field type is text input, set placeholder for text input:\n\n```php\n$filter->equal('column')->placeholder('Please input...');\n```\n\nYou can also restrict the user input format by using some of the following methods:\n\n```php\n$filter->equal('column')->url();\n\n$filter->equal('column')->email();\n\n$filter->equal('column')->integer();\n\n$filter->equal('column')->ip();\n\n$filter->equal('column')->mac();\n\n$filter->equal('column')->mobile();\n\n// $options refer to https://github.com/RobinHerbots/Inputmask/blob/4.x/README_numeric.md\n$filter->equal('column')->decimal($options = []);\n\n// $options refer to https://github.com/RobinHerbots/Inputmask/blob/4.x/README_numeric.md\n$filter->equal('column')->currency($options = []);\n\n// $options refer to https://github.com/RobinHerbots/Inputmask/blob/4.x/README_numeric.md\n$filter->equal('column')->percentage($options = []);\n\n// $options refer to https://github.com/RobinHerbots/Inputmask\n$filter->equal('column')->inputmask($options = [], $icon = 'pencil');\n```\n\n### Select\n```php\n$filter->equal('column')->select(['key' => 'value'...]);\n\n// Or from the api to obtain data, api format reference model-form `select` component\n$filter->equal('column')->select('api/users');\n```\n\n### multipleSelect\nGenerally used in conjunction with `in` and` notIn` need to query the array of two types of inquiries can also be used in the `type` type of query:\n```php\n$filter->in('column')->multipleSelect(['key' => 'value'...]);\n\n// // Or from the api to obtain data, api format reference model-form `multipleSelect` component\n$filter->in('column')->multipleSelect('api/users');\n```\n\n### radio\nThe more common scenario is the selection of categories\n\n```php\n$filter->equal('released')->radio([\n    ''   => 'All',\n    0    => 'Unreleased',\n    1    => 'Released',\n]);\n```\n\n### checkbox\nThe more common scene is do the scope query with `whereIn`:\n\n```php\n$filter->in('gender')->checkbox([\n    'm'    => 'Male',\n    'f'    => 'Female',\n]);\n```\n\n### datetime\n\nUse date and time components,`$options` parameter and value reference [bootstrap-datetimepicker](http://eonasdan.github.io/bootstrap-datetimepicker/Options/)\n\n```php\n$filter->equal('column')->datetime($options);\n\n// `date()` equals to `datetime(['format' => 'YYYY-MM-DD'])`\n$filter->equal('column')->date();\n\n// `time()` equals to `datetime(['format' => 'HH:mm:ss'])`\n$filter->equal('column')->time();\n\n// `day()` equals to `datetime(['format' => 'DD'])`\n$filter->equal('column')->day();\n\n// `month()` equals to `datetime(['format' => 'MM'])`\n$filter->equal('column')->month();\n\n// `year()` equals to `datetime(['format' => 'YYYY'])`\n$filter->equal('column')->year();\n\n```\n\n## Complex query filter\n\nYou can use the `$this->input` to trigger complex custom queries:\n```php\n$filter->where(function ($query) {\n    switch ($this->input) {\n        case 'yes':\n            // custom complex query if the 'yes' option is selected\n            $query->has('somerelationship');\n            break;\n        case 'no':\n            $query->doesntHave('somerelationship');\n            break;\n    }\n}, 'Label of the field', 'name_for_url_shortcut')->radio([\n    '' => 'All',\n    'yes' => 'Only with relationship',\n    'no' => 'Only without relationship',\n]);\n```\n"
  },
  {
    "path": "docs/en/model-grid.md",
    "content": "# Model-grid\n\nClass `Encore\\Admin\\Grid` is used to generate tables based on the data model,for example,we have a table `movies` in database:\n\n```sql\nCREATE TABLE `movies` (\n  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n  `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n  `director` int(10) unsigned NOT NULL,\n  `describe` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n  `rate` tinyint unsigned NOT NULL,\n  `released` enum(0, 1),\n  `release_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;\n\n```\n\nAnd the model of this table is `App\\Models\\Movie`,The following code can generate the data grid for table `movies`:\n\n```php\n\nuse App\\Models\\Movie;\nuse Encore\\Admin\\Grid;\nuse Encore\\Admin\\Facades\\Admin;\n\n$grid = Admin::grid(Movie::class, function(Grid $grid){\n\n    // The first column displays the id field and sets the column as a sortable column\n    $grid->id('ID')->sortable();\n\n    // The second column shows the title field, because the title field name and the Grid object's title method conflict, so use Grid's column () method instead\n    $grid->column('title');\n    \n    // The third column shows the director field, which is set by the display($callback) method to display the corresponding user name in the users table\n    $grid->director()->display(function($userId) {\n        return User::find($userId)->name;\n    });\n    \n    // The fourth column appears as the describe field\n    $grid->describe();\n    \n    // The fifth column is displayed as the rate field\n    $grid->rate();\n\n    // The sixth column shows the released field, formatting the display output through the display($callback) method\n    $grid->released('Release?')->display(function ($released) {\n        return $released ? 'yes' : 'no';\n    });\n\n    // The following shows the columns for the three time fields\n    $grid->release_at();\n    $grid->created_at();\n    $grid->updated_at();\n\n    // The filter($callback) method is used to set up a simple search box for the table\n    $grid->filter(function ($filter) {\n    \n        // Sets the range query for the created_at field\n        $filter->between('created_at', 'Created Time')->datetime();\n    });\n});\n\n```\n\n## Basic Usage\n\n#### Add a column\n```php\n\n// Add the column directly through the field name `username`\n$grid->username('Username');\n\n// The effect is the same as above\n$grid->column('username', 'Username');\n\n// Add multiple columns\n$grid->columns('email', 'username' ...);\n```\n\n#### Modify the source data\n```php\n$grid->model()->where('id', '>', 100);\n\n$grid->model()->orderBy('id', 'desc');\n\n$grid->model()->take(100);\n\n```\n\n#### Sets the number of lines displayed per page\n\n```php\n// The default is 15 per page\n$grid->paginate(20);\n```\n\n#### Modify the display output of column\n\n```php\nuse Illuminate\\Support\\Str;\n$grid->text()->display(function($text) {\n    return Str::limit($text, 30, '...');\n});\n\n$grid->name()->display(function ($name) {\n    return \"<span class='label'>$name</span>\";\n});\n\n$grid->email()->display(function ($email) {\n    return \"mailto:$email\";\n});\n\n// column not in table\n$grid->column('column_not_in_table')->display(function () {\n    return 'blablabla....';\n});\n\n```\n\nThe closure passed to method `display()` is bind to row data object, you can use other column data in current row.\n\n```php\n$grid->first_name();\n$grid->last_name();\n\n// column not in table\n$grid->column('full_name')->display(function () {\n    return $this->first_name.' '.$this->last_name;\n});\n```\n\n#### Disable the create button \n```php\n$grid->disableCreateButton();\n```\n\n#### Disable Pagination\n```php\n$grid->disablePagination();\n```\n\n#### Disable all tools on header of grid. Filter, refresh, export, batch actions\n```php\n$grid->disableTools();\n```\n\n#### Disable data filter\n```php\n$grid->disableFilter();\n```\n\n#### Disable the export button\n```php\n$grid->disableExport();\n```\n\n#### Disable row selector\n```php\n$grid->disableRowSelector();\n```\n\n#### Disable row actions\n```php\n$grid->disableActions();\n```\n\n#### Enable orderable grid\n```php\n$grid->orderable();\n```\n\n#### Set options for perPage selector\n```php\n$grid->perPages([10, 20, 30, 40, 50]);\n```\n\n## Relation\n\n\n### One to one\n\nThe `users` table and the `profiles` table are generated one-to-one relation through the `profiles.user_id` field.\n\n```sql\n\nCREATE TABLE `users` (\n`id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n`email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\nPRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;\n\nCREATE TABLE `profiles` (\n`id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n`user_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n`age` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n`gender` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\nPRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;\n```\n\nThe corresponding data model are:\n\n```php\n\nclass User extends Model\n{\n    public function profile()\n    {\n        return $this->hasOne(Profile::class);\n    }\n}\n\nclass Profile extends Model\n{\n    public function user()\n    {\n        return $this->belongsTo(User::class);\n    }\n}\n\n```\n\nYou can associate them in a grid with the following code:\n\n```php\nAdmin::grid(User::class, function (Grid $grid) {\n\n    $grid->id('ID')->sortable();\n\n    $grid->name();\n    $grid->email();\n    \n    $grid->column('profile.age');\n    $grid->column('profile.gender');\n\n    //or\n    $grid->profile()->age();\n    $grid->profile()->gender();\n\n    $grid->created_at();\n    $grid->updated_at();\n});\n\n```\n\n### One to many\n\nThe `posts` and `comments` tables generate a one-to-many association via the `comments.post_id` field\n\n```sql\n\nCREATE TABLE `posts` (\n`id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n`title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n`content` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\nPRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;\n\nCREATE TABLE `comments` (\n`id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n`post_id` int(10) unsigned NOT NULL,\n`content` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\nPRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;\n```\n\nThe corresponding data model are:\n\n```php\n\nclass Post extends Model\n{\n    public function comments()\n    {\n        return $this->hasMany(Comment::class);\n    }\n}\n\nclass Comment extends Model\n{\n    public function post()\n    {\n        return $this->belongsTo(Post::class);\n    }\n}\n\n```\n\nYou can associate them in a grid with the following code:\n\n```php\n\nreturn Admin::grid(Post::class, function (Grid $grid) {\n    $grid->id('id')->sortable();\n    $grid->title();\n    $grid->content();\n\n    $grid->comments('Comments count')->display(function ($comments) {\n        $count = count($comments);\n        return \"<span class='label label-warning'>{$count}</span>\";\n    });\n\n    $grid->created_at();\n    $grid->updated_at();\n});\n\n\nreturn Admin::grid(Comment::class, function (Grid $grid) {\n    $grid->id('id');\n    $grid->post()->title();\n    $grid->content();\n\n    $grid->created_at()->sortable();\n    $grid->updated_at();\n});\n\n```\n\n### Many to many\n\nThe `users` and` roles` tables produce a many-to-many relationship through the pivot table `role_user`\n\n```sql\n\nCREATE TABLE `users` (\n  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n  `username` varchar(190) COLLATE utf8_unicode_ci NOT NULL,\n  `password` varchar(60) COLLATE utf8_unicode_ci NOT NULL,\n  `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n  `created_at` timestamp NULL DEFAULT NULL,\n  `updated_at` timestamp NULL DEFAULT NULL,\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `users_username_unique` (`username`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci\n\nCREATE TABLE `roles` (\n  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n  `name` varchar(50) COLLATE utf8_unicode_ci NOT NULL,\n  `slug` varchar(50) COLLATE utf8_unicode_ci NOT NULL,\n  `created_at` timestamp NULL DEFAULT NULL,\n  `updated_at` timestamp NULL DEFAULT NULL,\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `roles_name_unique` (`name`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci\n\nCREATE TABLE `role_users` (\n  `role_id` int(11) NOT NULL,\n  `user_id` int(11) NOT NULL,\n  `created_at` timestamp NULL DEFAULT NULL,\n  `updated_at` timestamp NULL DEFAULT NULL,\n  KEY `role_users_role_id_user_id_index` (`role_id`,`user_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci\n```\n\nThe corresponding data model are:\n\n```php\n\nclass User extends Model\n{\n    public function roles()\n    {\n        return $this->belongsToMany(Role::class);\n    }\n}\n\nclass Role extends Model\n{\n    public function users()\n    {\n        return $this->belongsToMany(User::class);\n    }\n}\n\n```\n\nYou can associate them in a grid with the following code:\n\n```php\nreturn Admin::grid(User::class, function (Grid $grid) {\n    $grid->id('ID')->sortable();\n    $grid->username();\n    $grid->name();\n\n    $grid->roles()->display(function ($roles) {\n\n        $roles = array_map(function ($role) {\n            return \"<span class='label label-success'>{$role['name']}</span>\";\n        }, $roles);\n\n        return join('&nbsp;', $roles);\n    });\n\n    $grid->created_at();\n    $grid->updated_at();\n});\n\n```\n"
  },
  {
    "path": "docs/en/model-tree.md",
    "content": "# Model-tree\n\nCan be achieved through a `model-tree` to a tree-like components, you can drag the way to achieve the level of data, sorting and other operations, the following is the basic usage.\n\n## Table structure and model\n\nTo use `model-tree`, you have to follow the convention of the table structure:\n\n```sql\nCREATE TABLE `demo_categories` (\n  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n  `parent_id` int(11) NOT NULL DEFAULT '0',\n  `order` int(11) NOT NULL DEFAULT '0',\n  `title` varchar(50) COLLATE utf8_unicode_ci NOT NULL,\n  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci\n```\nThe above table structure has three necessary fields `parent_id`, `order`, `title`, and the other fields are not required.\n\nThe corresponding model is `app/Models/Category.php`:\n```php\n<?php\n\nnamespace App\\Models\\Demo;\n\nuse Encore\\Admin\\Traits\\ModelTree;\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass Category extends Model\n{\n    use ModelTree;\n\n    protected $table = 'demo_categories';\n}\n```\n\nTable structure in the three fields `parent_id`,` order`, `title` field name can be amended:\n\n```php\n<?php\n\nnamespace App\\Models\\Demo;\n\nuse Encore\\Admin\\Traits\\ModelTree;\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass Category extends Model\n{\n    use ModelTree;\n\n    protected $table = 'demo_categories';\n\n    public function __construct(array $attributes = [])\n    {\n        parent::__construct($attributes);\n        \n        $this->setParentColumn('pid');\n        $this->setOrderColumn('sort');\n        $this->setTitleColumn('name');\n    }\n}\n```\n## Usage\n然后就是在页面中使用`model-tree`了：\n\nThen use `model-tree` in your page\n\n```php\n<?php\n\nnamespace App\\Admin\\Controllers\\Demo;\n\nuse App\\Http\\Controllers\\Controller;\nuse App\\Models\\Category;\nuse Encore\\Admin\\Form;\nuse Encore\\Admin\\Facades\\Admin;\nuse Encore\\Admin\\Layout\\Content;\nuse Encore\\Admin\\Controllers\\ModelForm;\nuse Encore\\Admin\\Tree;\n\nclass CategoryController extends Controller\n{\n    use ModelForm;\n    \n    public function index()\n    {\n        return Admin::content(function (Content $content) {\n            $content->header('Categories');\n            $content->body(Category::tree());\n        });\n    }\n}\n```\nYou can modify the display of branch in the following ways:\n```php\nCategory::tree(function ($tree) {\n    $tree->branch(function ($branch) {\n        $src = config('admin.upload.host') . '/' . $branch['logo'] ;\n        $logo = \"<img src='$src' style='max-width:30px;max-height:30px' class='img'/>\";\n\n        return \"{$branch['id']} - {$branch['title']} $logo\";\n    });\n})\n```\n\nThe `$branch` parameter is array of current row data.\n\nIf you want to modify the query of the model, use the following way:\n```php\n\nCategory::tree(function ($tree) {\n\n    $tree->query(function ($model) {\n        return $model->where('type', 1);\n    });\n    \n})\n```\n\n\n"
  },
  {
    "path": "docs/en/permission.md",
    "content": "# Access Control\n\n`laravel-admin` has built-in` RBAC` permissions control module, expand the left sidebar `Auth`, you can see user, permissions and roles management panel, the use of permissions control as follows:\n\n## Route permission\n\nIn the `laravel-admin 1.5`, the permissions and routes are bound together, in the edit permission page which set the current permissions can access the routing, in the `HTTP method` select box to select the method of access to the path, in the `HTTP path` textarea fill in the path to access.\n\nFor example, to add a permission, the permission can access the path `/admin/users` in GET method, then `HTTP method` select `GET`, `HTTP path` fill in `/users`.\n\nIf you want to access all paths with the prefix `/admin/users`, then the `HTTP path` fill in `/users*`, if the permissions include multiple access paths, wrap the line for each path.\n\n## Page permission\n\nIf you want to control the user's permissions in the page, you can refer to the following example\n\n### example1\n\nFor example, there is now a scene, here is a article module, we use create articles as an example\n\nAt first open `http://localhost/admi/auth/permissions`, fill up slug field with text `create-post`, and `Create post` in name field, then assign this permission to some roles.\n\nIn your controller action: \n```php\nuse Encore\\Admin\\Auth\\Permission;\n\nclass PostController extends Controller\n{\n    public function create()\n    {\n        // check permission, only the roles with permission `create-post` can visit this action\n        Permission::check('create-post');\n    }\n}\n```\n\n### example2\n\nIf you want to control the page elements of the user's display, then you need to first define permissions, such as `delete-image` and `view-title-column`, respectively, to control the permissions to delete pictures and display a column in grid, then assign these two permissions to roles, add following code to the grid：\n```php\n$grid->actions(function ($actions) {\n\n    // The roles with this permission will not able to see the delete button in actions column.\n    if (!Admin::user()->can('delete-image')) {\n        $actions->disableDelete();\n    }\n});\n\n// Only roles with permission `view-title-column` can view this column in grid\nif (Admin::user()->can('view-title-column')) {\n    $grid->column('title');\n}\n```\n\n## Other methods\n\nGet current user object.\n```php\nAdmin::user();\n```\n\nGet current user id.\n```php\nAdmin::user()->id;\n```\n\nGet user's roles.\n```php\nAdmin::user()->roles;\n```\n\nGet user's permissions.\n```php\nAdmin::user()->permissions;\n```\n\nUser is role.\n```php\nAdmin::user()->isRole('developer');\n```\n\nUser has permission.\n```php\nAdmin::user()->can('create-post');\n```\n\nUser don't has permission.\n```php\nAdmin::user()->cannot('delete-post');\n```\n\nIs user super administrator.\n```php\nAdmin::user()->isAdministrator();\n```\n\nIs user in one of roles.\n```php\nAdmin::user()->inRoles(['editor', 'developer']);\n```\n\n## Permission middleware\n\nYou can use permission middleware in the routes to control the routing permission\n\n```php\n\n// Allow roles `administrator` and `editor` access the routes under group.\nRoute::group([\n    'middleware' => 'admin.permission:allow,administrator,editor',\n], function ($router) {\n\n    $router->resource('users', UserController::class);\n    ...\n    \n});\n\n// Deny roles `developer` and `operator` access the routes under group.\nRoute::group([\n    'middleware' => 'admin.permission:deny,developer,operator',\n], function ($router) {\n\n    $router->resource('users', UserController::class);\n    ...\n    \n});\n\n// User has permission `edit-post`、`create-post` and `delete-post` can access routes under group.\nRoute::group([\n    'middleware' => 'admin.permission:check,edit-post,create-post,delete-post',\n], function ($router) {\n\n    $router->resource('posts', PostController::class);\n    ...\n    \n});\n```\n\nThe usage of permission middleware is just as same as other middleware.\n\n\n"
  },
  {
    "path": "docs/en/quick-start.md",
    "content": "# Quick start\n\nWe use `users` table come with `Laravel` for example,the structure of table is:\n```sql\nCREATE TABLE `users` (\n  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n  `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n  `email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n  `password` varchar(60) COLLATE utf8_unicode_ci NOT NULL,\n  `remember_token` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,\n  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `users_email_unique` (`email`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci\n```\nAnd the model for this table is `App\\User.php`\n\nYou can follow these steps to setup `CRUD` interfaces of table `users`:\n\n## Add controller\n\nUse the following command to create a controller for `App\\User` model\n\n```php\nphp artisan admin:make UserController --model=App\\\\User\n\n// under windows use:\nphp artisan admin:make UserController --model=App\\User\n```\nThe above command will create the controller in `app/Admin/Controllers/UserController.php`.\n\n## Add route\n\nAdd a route in `app/Admin/routes.php`：\n```\n$router->resource('demo/users', UserController::class);\n```\n\n## Add left menu item\n\nOpen `http://localhost:8000/admin/auth/menu`, add menu link and refresh the page, then you can find a link item in left menu bar.\n\n> Where `uri` fills in the path part that does not contain the prefix of the route, such as the full path `http://localhost:8000/admin/demo/users`, just input `demo/users`, If you want to add an external link, just fill in the full url, such as `http://laravel-admin.org/`.\n\n### Menu translations\n\nappend menu titles in menu_titles index at your language files.\nFor example 'Work Units' title:\n\nin resources/lang/es/admin.php\n```php\n...\n// lowercase and replace spaces with _\n'menu_titles' => [\n    'work_units' => 'Unidades de trabajo'\n],\n```\n\n## Build grid and form\n\nThe rest needs to be done is open `app/Admin/Contollers/UserController.php`, find `form()` and `grid()` method and write few lines of code with `model-grid` and `model-form`,for more detail, please read [model-grid](/en/model-grid.md) and [model-form](/en/model-form.md).\n"
  },
  {
    "path": "docs/en/upgrade.md",
    "content": "# Upgrade precautions\n\nBecause `laravel-admin 1.5` built-in table structure has been modified, it is recommended that you re-install `laravel 5.5` and `laravel-admin 1.5`, and then migrate the code over\n\nCode migration needs attention：\n\n- Please refer to the table structure changes [tables.php](https://github.com/z-song/laravel-admin/blob/master/database/migrations/2016_01_04_173148_create_admin_tables.php)\n- Routing file structure is modified please refer to [routes.stub](https://github.com/z-song/laravel-admin/blob/master/src/Console/stubs/routes.stub)\n- Please refer to the configuration file structure changes [admin.php](https://github.com/z-song/laravel-admin/blob/master/config/admin.php)\n- The chart component has been removed and can no longer be used, please refer to [Custom chart](/en/custom-chart.md)"
  },
  {
    "path": "docs/en/widgets.md",
    "content": "# Web widgets\n\n## Box\n\n`Encore\\Admin\\Widgets\\Box` used to generate box components:\n\n```php\nuse Encore\\Admin\\Widgets\\Box;\n\n$box = new Box('Box Title', 'Box content');\n\n$box->removable();\n\n$box->collapsable();\n\n$box->style('info');\n\n$box->solid();\n\necho $box;\n\n```\n\nThe `$content` parameter is the content element of the Box, which can be either an implementation of the `Illuminate\\Contracts\\Support\\Renderable` interface, or other printable variables.\n\n`Box::title($title)` method is used to set the Box component title.\n\n`Box::content($content)` method is used to set the content element of a Box component.\n\n`Box::removable()` method sets the Box component as removable.\n\n`Box::collapsable()` method sets the Box component as collapsable.\n\n`Box::style($style)` method sets the style of the Box component to fill in `primary`, `info`, `danger`, `warning`, `success`, `default`.\n\n`Box::solid()` method adds a border to the Box component.\n\n## Collapse\n\n`Encore\\Admin\\Widgets\\Collapse` class used to generate folding components:\n```php\nuse Encore\\Admin\\Widgets\\Collapse;\n\n$collapse = new Collapse();\n\n$collapse->add('Bar', 'xxxxx');\n$collapse->add('Orders', new Table());\n\necho $collapse->render();\n\n```\n\n`Collapse::add($title, $content)` method is used to add a collapsed item to the collapsing component. The `$title` parameter sets the title of the item. The`$content` parameter is used to .\n\n\n## Form\n\n`Encore\\Admin\\Widgets\\Form` class is used to quickly build a form:\n\n```php\n\n$form = new Form();\n\n$form->action('example');\n\n$form->email('email')->default('qwe@aweq.com');\n$form->password('password');\n$form->text('name');\n$form->url('url');\n$form->color('color');\n$form->map('lat', 'lng');\n$form->date('date');\n$form->json('val');\n$form->dateRange('created_at', 'updated_at');\n\necho $form->render();\n```\n\n`Form::__construct($data = [])` generates a form object. If the `$data` parameter is passed, the elements in the `$data` array will be filled into the form.\n\n`Form::action($uri)` method is used to set the form submission address.\n\n`Form::method($method)` method is used to set the submit method of the form, the default is `POST` method.\n\n`Form::disablePjax()` disable pjax for form submit.\n\n## Infobox\n\n`Encore\\Admin\\Widgets\\InfoBox` class is used to generate the information presentation block:\n\n```php\nuse Encore\\Admin\\Widgets\\InfoBox;\n\n$infoBox = new InfoBox('New Users', 'users', 'aqua', '/admin/users', '1024');\n\necho $infoBox->render();\n\n```\n\nRefer to the section on the `InfoBox` in the `index()` method of the home page layout file [HomeController.php](https://github.com/z-song/laravel-admin/blob/master/src/Console/stubs/HomeController.stub).\n\n## Tab component\n\n`Encore\\Admin\\Widgets\\Tab` class is used to generate the tab components:\n\n```php\nuse Encore\\Admin\\Widgets\\Tab;\n\n$tab = new Tab();\n\n$tab->add('Pie', $pie);\n$tab->add('Table', new Table());\n$tab->add('Text', 'blablablabla....');\n\necho $tab->render();\n\n```\n\n`Tab::add($title, $content)` method is used to add new tab, `$title` is tab title, `$content` is tab content.\n\n## Table\n\n`Encore\\Admin\\Widgets\\Table` class is used to generate tables:\n\n```php\nuse Encore\\Admin\\Widgets\\Table;\n\n// table 1\n$headers = ['Id', 'Email', 'Name', 'Company'];\n$rows = [\n    [1, 'labore21@yahoo.com', 'Ms. Clotilde Gibson', 'Goodwin-Watsica'],\n    [2, 'omnis.in@hotmail.com', 'Allie Kuhic', 'Murphy, Koepp and Morar'],\n    [3, 'quia65@hotmail.com', 'Prof. Drew Heller', 'Kihn LLC'],\n    [4, 'xet@yahoo.com', 'William Koss', 'Becker-Raynor'],\n    [5, 'ipsa.aut@gmail.com', 'Ms. Antonietta Kozey Jr.'],\n];\n\n$table = new Table($headers, $rows);\n\necho $table->render();\n\n// table 2\n$headers = ['Keys', 'Values'];\n$rows = [\n    'name'   => 'Joe',\n    'age'    => 25,\n    'gender' => 'Male',\n    'birth'  => '1989-12-05',\n];\n\n$table = new Table($headers, $rows);\n\necho $table->render();\n\n```\n\n"
  },
  {
    "path": "docs/issue_template.md",
    "content": "- Laravel Version: #.#.#\n- PHP Version:\n- Laravel-admin: #.#.#\n\n### Description:\n\n\n### Steps To Reproduce:\n"
  },
  {
    "path": "docs/zh/LICENSE.md",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 Jens Segers\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "docs/zh/README.md",
    "content": "# laravel-admin\n\n[![Build Status](https://travis-ci.org/z-song/laravel-admin.svg?branch=master)](https://travis-ci.org/z-song/laravel-admin)\n[![StyleCI](https://styleci.io/repos/48796179/shield)](https://styleci.io/repos/48796179)\n[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/z-song/laravel-admin/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/z-song/laravel-admin/?branch=master)\n[![Packagist](https://img.shields.io/packagist/l/encore/laravel-admin.svg?maxAge=2592000)](https://packagist.org/packages/encore/laravel-admin)\n[![Total Downloads](https://img.shields.io/packagist/dt/encore/laravel-admin.svg?style=flat-square)](https://packagist.org/packages/encore/laravel-admin)\n\n`laravel-admin` 是一个可以快速帮你构建后台管理的工具，它提供的页面组件和表单元素等功能，能帮助你使用很少的代码就实现功能完善的后台管理功能。\n\n> 当前版本(1.5)需要安装`PHP 7+`和`Laravel 5.5`, 如果你使用更早的版本，请参考文档: [1.4](http://laravel-admin.org/docs/v1.4/#/zh/) \n\n## 特性\n\n+ 内置用户和权限系统\n+ `model-grid`支持快速构建数据表格\n+ `model-form`支持快速构建数据表单\n+ `model-tree`支持快速构建树状数据\n+ 内置40+种form元素组件、以及支持扩展组件\n+ 支持`Laravel`的多种模型关系\n+ `mysql`、`mongodb`、`pgsql`等多数据库支持\n+ 支持引入第三方前端库\n+ 数据库和artisan命令行工具的web实现\n+ 支持自定义图表\n+ 多种常用web组件\n+ 支持本地和oss文件上传\n\n## Demo\n\n打开`http://laravel-admin.org/demo/`，用账号密码`admin/admin`登陆\n\n# 依赖\n\n`laravel-admin` 基于以下组件或者服务:\n\n+ [Laravel](https://laravel.com/)\n+ [AdminLTE](https://almsaeedstudio.com/)\n+ [Datetimepicker](http://eonasdan.github.io/bootstrap-datetimepicker/)\n+ [font-awesome](http://fontawesome.io)\n+ [moment](http://momentjs.com/)\n+ [Google map](https://www.google.com/maps)\n+ [Tencent map](http://lbs.qq.com/)\n+ [bootstrap-fileinput](https://github.com/kartik-v/bootstrap-fileinput)\n+ [jquery-pjax](https://github.com/defunkt/jquery-pjax)\n+ [Nestable](http://dbushell.github.io/Nestable/)\n+ [toastr](http://codeseven.github.io/toastr/)\n+ [X-editable](http://github.com/vitalets/x-editable)\n+ [bootstrap-number-input](https://github.com/wpic/bootstrap-number-input)\n+ [fontawesome-iconpicker](https://github.com/itsjavi/fontawesome-iconpicker)\n\n## 交流\n\nQQ群:278455482(已满)、635881319(已满)、533701919\n\n> 为了避免广告及不看文档用户，请先到github star此项目，然后附上github账号申请入群\n\n> 另外我已经屏蔽群私聊，所以请不要找我私聊，也请尽量不要在群里面 @我 🙏\n\n## 支持\n\n如果觉得这个项目帮你节约了时间，不妨支持一下;)\n\n![-1](https://cloud.githubusercontent.com/assets/1479100/23287423/45c68202-fa78-11e6-8125-3e365101a313.jpg)\n\n## License\n\n`laravel-admin` is licensed under [The MIT License (MIT)](zh/LICENSE).\n"
  },
  {
    "path": "docs/zh/_sidebar.md",
    "content": "\n- 入门\n  - [安装](/zh/installation.md)\n  - [快速开始](/zh/quick-start.md)\n  - [页面内容和布局](/zh/content-layout.md)\n- 模型表格\n  - [基本使用](/zh/model-grid.md)\n  - [行的使用和扩展](/zh/model-grid-actions.md)\n  - [列的使用和扩展](/zh/model-grid-column.md)\n  - [自定义工具](/zh/model-grid-custom-tools.md)\n  - [修改表格数据源](/zh/model-grid-data.md)\n  - [查询过滤](/zh/model-grid-filters.md)\n  - [数据导出](/zh/model-grid-export.md)\n- 模型表单\n  - [基本使用](/zh/model-form.md)\n  - [图片/文件上传](/zh/model-form-upload.md)\n  - [Form组件使用](/zh/model-form-fields.md)\n  - [Form组件管理](/zh/model-form-field-management.md)\n  - [表单验证](/zh/model-form-validation.md)\n  - [保存回调](/zh/model-form-callback.md)\n- [数据模型树](/zh/model-tree.md)\n- Admin扩展\n  - [帮助工具](/zh/extension-helpers.md)\n  - [文件管理](/zh/extension-media-manager.md)\n  - [API tester](/zh/extension-api-tester.md)\n  - [配置管理](/zh/extension-config.md)\n  - [计划任务](/zh/extension-scheduling.md)\n- [前端组件](/zh/widgets.md)\n- [权限控制](/zh/permission.md)\n- [自定义登陆认证](/zh/custom-authentication.md)\n- [自定义头部导航](/zh/custom-navbar.md)\n- [自定义图表](/zh/custom-chart.md)\n- [常见问题](/zh/qa.md)\n- [升级注意事项](/zh/upgrade.md)\n- [Change log](/zh/change-log.md)"
  },
  {
    "path": "docs/zh/change-log.md",
    "content": "# Change log\n\n## v1.2.9、v1.3.3、v1.4.1\n\n- 添加用户设置和修改头像功能\n- model-form自定义工具[参考](zh/model-form.md?id=自定义工具)\n- 内嵌表单支持[参考](zh/model-form-fields.md?id=embeds)\n- 支持自定义导航条（右上角）[参考](https://github.com/z-song/laravel-admin/issues/392)\n- 添加脚手架、数据库命令行工具、web artisan帮助工具[参考](zh/helpers.md)\n- 支持自定义登陆页面和登陆逻辑[参考](zh/qa.md?id=自定义登陆页面和登陆逻辑)\n- 表单支持设置宽度、设置action[参考](zh/model-form.md?id=其它方法)\n- 优化表格过滤器\n- 修复bug，优化代码和逻辑"
  },
  {
    "path": "docs/zh/content-layout.md",
    "content": "# 页面内容\n\n`laravel-admin`的布局可参考后台首页的布局文件[HomeController.php](https://github.com/z-song/laravel-admin/blob/master/src/Console/stubs/HomeController.stub)的`index()`方法。\n\n`Encore\\Admin\\Layout\\Content`类用来实现内容区的布局。`Content::body($content)`方法用来添加页面内容：\n\n一个简单的后台页面代码如下：\n\n```php\npublic function index()\n{\n    return Admin::content(function (Content $content) {\n\n        // 选填\n        $content->header('填写页面头标题');\n        \n        // 选填\n        $content->description('填写页面描述小标题');\n        \n        // 添加面包屑导航 since v1.5.7\n        $content->breadcrumb(\n            ['text' => '首页', 'url' => '/admin'],\n            ['text' => '用户管理', 'url' => '/admin/users'],\n            ['text' => '编辑用户']\n        );\n\n        // 填充页面body部分，这里可以填入任何可被渲染的对象\n        $content->body('hello world');\n    });\n}\n\n```\n\n其中`$content->body();`方法可以接受任何可字符串化的对象作为参数，可以是字符串、数字、包含了`__toString`方法的对象，实现了`Renderable`、`Htmlable`接口的对象，包括laravel的视图。\n\n\n## 布局\n\n`laravel-admin`的布局使用bootstrap的栅格系统，每行的长度是12，下面是几个简单的示例：\n\n添加一行内容:\n\n```php\n$content->row('hello')\n\n---------------------------------\n|hello                          |\n|                               |\n|                               |\n|                               |\n|                               |\n|                               |\n---------------------------------\n\n```\n\n行内添加多列：\n\n```php\n$content->row(function(Row $row) {\n    $row->column(4, 'foo');\n    $row->column(4, 'bar');\n    $row->column(4, 'baz');\n});\n----------------------------------\n|foo       |bar       |baz       |\n|          |          |          |\n|          |          |          |\n|          |          |          |\n|          |          |          |\n|          |          |          |\n----------------------------------\n\n\n$content->row(function(Row $row) {\n    $row->column(4, 'foo');\n    $row->column(8, 'bar');\n});\n----------------------------------\n|foo       |bar                  |\n|          |                     |\n|          |                     |\n|          |                     |\n|          |                     |\n|          |                     |\n----------------------------------\n\n```\n\n列中添加行：\n\n```php\n$content->row(function (Row $row) {\n\n    $row->column(4, 'xxx');\n\n    $row->column(8, function (Column $column) {\n        $column->row('111');\n        $column->row('222');\n        $column->row('333');\n    });\n});\n----------------------------------\n|xxx       |111                  |\n|          |---------------------|\n|          |222                  |\n|          |---------------------|\n|          |333                  |\n|          |                     |\n----------------------------------\n\n\n```\n\n\n列中添加行, 行内再添加列：\n\n```php\n$content->row(function (Row $row) {\n\n    $row->column(4, 'xxx');\n\n    $row->column(8, function (Column $column) {\n        $column->row('111');\n        $column->row('222');\n        $column->row(function(Row $row) {\n            $row->column(6, '444');\n            $row->column(6, '555');\n        });\n    });\n});\n----------------------------------\n|xxx       |111                  |\n|          |---------------------|\n|          |222                  |\n|          |---------------------|\n|          |444      |555        |\n|          |         |           |\n----------------------------------\n```\n\n"
  },
  {
    "path": "docs/zh/custom-authentication.md",
    "content": "# 自定义登陆\n\n如果不使用`laravel-admin`内置的认证登陆逻辑，可以参考下面的方式自定义登陆认证逻辑\n\n首先要先定义一个`user provider`，用来获取用户身份, 比如`app/Providers/CustomUserProvider.php`：\n\n```php\n<?php\n\nnamespace App\\Providers;\n\nuse Illuminate\\Contracts\\Auth\\Authenticatable;\nuse Illuminate\\Contracts\\Auth\\UserProvider;\n\nclass CustomUserProvider implements UserProvider\n{\n    public function retrieveById($identifier)\n    {}\n\n    public function retrieveByToken($identifier, $token)\n    {}\n\n    public function updateRememberToken(Authenticatable $user, $token)\n    {}\n\n    public function retrieveByCredentials(array $credentials)\n    {\n        // 用$credentials里面的用户名密码去获取用户信息，然后返回Illuminate\\Contracts\\Auth\\Authenticatable对象\n    }\n\n    public function validateCredentials(Authenticatable $user, array $credentials)\n    {\n        // 用$credentials里面的用户名密码校验用户，返回true或false\n    }\n}\n\n```\n\n在方法`retrieveByCredentials`和`validateCredentials`中, 传入的`$credentials`就是登陆页面提交的用户名和密码数组，然后你可以使用`$credentials`去实现自己的登陆逻辑\n\nInterface `Illuminate\\Contracts\\Auth\\Authenticatable`的定义如下：\n```php\n<?php\n\nnamespace Illuminate\\Contracts\\Auth;\n\ninterface Authenticatable {\n\n    public function getAuthIdentifierName();\n    public function getAuthIdentifier();\n    public function getAuthPassword();\n    public function getRememberToken();\n    public function setRememberToken($value);\n    public function getRememberTokenName();\n\n}\n```\n\n上面interface每个方法的解释参考[adding-custom-user-providers](https://laravel.com/docs/5.5/authentication#adding-custom-user-providers)\n\n定义好了`User provider`之后，打开`app/Providers/AuthServiceProvider.php`注册它：\n\n```php\n<?php\n\nnamespace App\\Providers;\n\nuse Illuminate\\Support\\Facades\\Auth;\nuse Illuminate\\Foundation\\Support\\Providers\\AuthServiceProvider as ServiceProvider;\n\nclass AuthServiceProvider extends ServiceProvider\n{\n    /**\n     * Register any application authentication / authorization services.\n     *\n     * @return void\n     */\n    public function boot()\n    {\n        $this->registerPolicies();\n\n        Auth::provider('custom', function ($app, array $config) {\n            \n            // Return an instance of Illuminate\\Contracts\\Auth\\UserProvider...\n            return new CustomUserProvider();\n        });\n    }\n}\n```\n\n最后修改一下配置,打开`config/admin.php`，找到`auth`部分修改:\n\n```php\n    'auth' => [\n        'guards' => [\n            'admin' => [\n                'driver' => 'session',\n                'provider' => 'admin',\n            ]\n        ],\n\n        // 修改下面\n        'providers' => [\n            'admin' => [\n                'driver' => 'custom',\n            ]\n        ],\n    ],\n```\n这样就完成了自定义登陆认证的逻辑，自定义登陆算是laravel中比较复杂的部分，需要开发者有耐心的一步步调试完成。\n\n"
  },
  {
    "path": "docs/zh/custom-chart.md",
    "content": "# 自定义图表\n\n`laravel-admin 1.5`已经移除了所有的图表组件，如果要在页面中加入图表组件，可以参考下面的流程\n\n用`chartjs`举例，首先要下载[chartjs](http://chartjs.org/)，放到public目录下面，比如放在`public/vendor/chartjs`目录\n\n然后在`app/Admin/bootstrap.php`引入组件：\n```php\nuse Encore\\Admin\\Facades\\Admin;\n\nAdmin::js('/vendor/chartjs/dist/Chart.min.js');\n\n```\n\n新建视图文件 `resources/views/admin/charts/bar.blade.php`\n\n```php\n<canvas id=\"myChart\" width=\"400\" height=\"400\"></canvas>\n<script>\n\n$(function () {\n   var ctx = document.getElementById(\"myChart\").getContext('2d');\n   var myChart = new Chart(ctx, {\n       type: 'bar',\n       data: {\n           labels: [\"Red\", \"Blue\", \"Yellow\", \"Green\", \"Purple\", \"Orange\"],\n           datasets: [{\n               label: '# of Votes',\n               data: [12, 19, 3, 5, 2, 3],\n               backgroundColor: [\n                   'rgba(255, 99, 132, 0.2)',\n                   'rgba(54, 162, 235, 0.2)',\n                   'rgba(255, 206, 86, 0.2)',\n                   'rgba(75, 192, 192, 0.2)',\n                   'rgba(153, 102, 255, 0.2)',\n                   'rgba(255, 159, 64, 0.2)'\n               ],\n               borderColor: [\n                   'rgba(255,99,132,1)',\n                   'rgba(54, 162, 235, 1)',\n                   'rgba(255, 206, 86, 1)',\n                   'rgba(75, 192, 192, 1)',\n                   'rgba(153, 102, 255, 1)',\n                   'rgba(255, 159, 64, 1)'\n               ],\n               borderWidth: 1\n           }]\n       },\n       options: {\n           scales: {\n               yAxes: [{\n                   ticks: {\n                       beginAtZero:true\n                   }\n               }]\n           }\n       }\n   }); \n});\n</script>\n```\n\n然后就可以在页面的任何地方引入这个图表视图了：\n\n```php\npublic function index()\n{\n    return Admin::content(function (Content $content) {\n\n        $content->header('chart');\n        $content->description('.....');\n        \n        $content->body(view('admin.charts.bar'));\n    });\n}\n\n```\n\n按照上面的方式可以引入任意图表库，多图表页面的布局，参考[视图布局](/zh/layout.md)"
  },
  {
    "path": "docs/zh/custom-navbar.md",
    "content": "# 自定义头部导航条\n\n从版本`1.5.6`开始，可以在顶部导航条上添加html元素了,  打开`app/Admin/bootstrap.php`：\n```php\nuse Encore\\Admin\\Facades\\Admin;\n\nAdmin::navbar(function (\\Encore\\Admin\\Widgets\\Navbar $navbar) {\n\n    $navbar->left('html...');\n\n    $navbar->right('html...');\n\n});\n```\n\n`left`和`right`方法分别用来在头部的左右两边添加内容，方法参数可以是任何可以渲染的对象(实现了`Htmlable`、`Renderable`接口或者包含`__toString()`方法的对象)或字符串\n\n## 左侧添加示例\n\n举个例子，比如在左边添加一个搜索条，先创建一个blade视图`resources/views/search-bar.blade.php`：\n```php\n<style>\n\n.search-form {\n    width: 250px;\n    margin: 10px 0 0 20px;\n    border-radius: 3px;\n    float: left;\n}\n.search-form input[type=\"text\"] {\n    color: #666;\n    border: 0;\n}\n\n.search-form .btn {\n    color: #999;\n    background-color: #fff;\n    border: 0;\n}\n\n</style>\n\n<form action=\"/admin/posts\" method=\"get\" class=\"search-form\" pjax-container>\n    <div class=\"input-group input-group-sm \">\n        <input type=\"text\" name=\"title\" class=\"form-control\" placeholder=\"Search...\">\n        <span class=\"input-group-btn\">\n            <button type=\"submit\" name=\"search\" id=\"search-btn\" class=\"btn btn-flat\"><i class=\"fa fa-search\"></i></button>\n          </span>\n    </div>\n</form>\n```\n然后加入头部导航条：\n```php\n$navbar->left(view('search-bar'));\n```\n\n## 右侧添加示例\n\n导航右侧只能添加`<li>`标签, 比如要添加一些提示图标，新建渲染对象`app/Admin/Extensions/Nav/Links.php`\n```php\n<?php\n\nnamespace App\\Admin\\Extensions\\Nav;\n\nclass Links\n{\n    public function __toString()\n    {\n        return <<<HTML\n\n<li>\n    <a href=\"#\">\n      <i class=\"fa fa-envelope-o\"></i>\n      <span class=\"label label-success\">4</span>\n    </a>\n</li>\n\n<li>\n    <a href=\"#\">\n      <i class=\"fa fa-bell-o\"></i>\n      <span class=\"label label-warning\">7</span>\n    </a>\n</li>\n\n<li>\n    <a href=\"#\">\n      <i class=\"fa fa-flag-o\"></i>\n      <span class=\"label label-danger\">9</span>\n    </a>\n</li>\n\nHTML;\n    }\n}\n```\n\n然后加入头部导航条：\n```php\n$navbar->right(new \\App\\Admin\\Extensions\\Nav\\Links());\n```\n\n或者用下面的html加入下拉菜单：\n```html\n<li class=\"dropdown notifications-menu\">\n<a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\" aria-expanded=\"false\">\n  <i class=\"fa fa-bell-o\"></i>\n  <span class=\"label label-warning\">10</span>\n</a>\n<ul class=\"dropdown-menu\">\n  <li class=\"header\">You have 10 notifications</li>\n  <li>\n    <!-- inner menu: contains the actual data -->\n    <ul class=\"menu\">\n      <li>\n        <a href=\"#\">\n          <i class=\"fa fa-users text-aqua\"></i> 5 new members joined today\n        </a>\n      </li>\n      <li>\n        <a href=\"#\">\n          <i class=\"fa fa-warning text-yellow\"></i> Very long description here that may not fit into the\n          page and may cause design problems\n        </a>\n      </li>\n      <li>\n        <a href=\"#\">\n          <i class=\"fa fa-users text-red\"></i> 5 new members joined\n        </a>\n      </li>\n\n      <li>\n        <a href=\"#\">\n          <i class=\"fa fa-shopping-cart text-green\"></i> 25 sales made\n        </a>\n      </li>\n      <li>\n        <a href=\"#\">\n          <i class=\"fa fa-user text-red\"></i> You changed your username\n        </a>\n      </li>\n    </ul>\n  </li>\n  <li class=\"footer\"><a href=\"#\">View all</a></li>\n</ul>\n</li>\n```\n\n更多的组件可以参考[Bootstrap](https://getbootstrap.com/)"
  },
  {
    "path": "docs/zh/extension-api-tester.md",
    "content": "# Laravel API测试\n\n`api-tester`是专门针对`laravel`开发的API测试工具，能够帮助你像`postman`一样测试你的laravel API。\n\n![wx20170809-164424](https://user-images.githubusercontent.com/1479100/29112946-1e32971c-7d22-11e7-8cc0-5b7ad25d084e.png)\n\n## 安装\n\n```shell\n$ composer require laravel-admin-ext/api-tester -vvv\n\n$ php artisan vendor:publish --tag=api-tester\n\n```\n然后运行下面的命令导入菜单和权限（也可以手动添加）\n\n```shell\n$ php artisan admin:import api-tester\n```\n\n然后就能在后台的左侧菜单找到入口链接，`http://localhost/admin/api-tester`。\n\n## 使用\n\n打开`routes/api.php`试着添加一个api:\n\n```php\nRoute::get('test', function () {\n    return 'hello world';\n});\n```\n\n打开`api-tester`页面，就能在左侧看到`api/test`, 选择它然后点击右侧的`Send`，就能请求这个API，下面会输出请求结果, \n\n### Login as\n\n`Login as`填写你要登陆的用户的id, 就可以以这个用户的身份登陆来请求API，加入下面的API：\n\n```php\nuse Illuminate\\Http\\Request;\n\nRoute::middleware('auth:api')->get('user', function (Request $request) {\n    return $request->user();\n});\n```\n`Login as`填写用户ID，请求接口后就能返回这个用户的模型\n\n### Parameters\n\n用来填写接口的请求参数，类型可以是字符串或者文件, 添加下面的API：\n\n```php\nuse Illuminate\\Http\\Request;\n\nRoute::get('parameters', function (Request $request) {\n    return $request->all();\n});\n```\n\n然后填写参数可以看到效果"
  },
  {
    "path": "docs/zh/extension-config.md",
    "content": "# 配置管理\n\n这个工具将配置数据存在数据库中，然后在能在Laravel中能像普通配置一样使用\n\n![wx20170810-100226](https://user-images.githubusercontent.com/1479100/29151322-0879681a-7db3-11e7-8005-03310686c884.png)\n\n## 安装\n\n```\n$ composer require laravel-admin-ext/config\n\n$ php artisan migrate\n```\n\n打开`app/Providers/AppServiceProvider.php`, 在`boot`方法中添加`Config::load();`:\n\n```php\n<?php\n\nnamespace App\\Providers;\n\nuse Encore\\Admin\\Config\\Config;\nuse Illuminate\\Support\\ServiceProvider;\n\nclass AppServiceProvider extends ServiceProvider\n{\n    public function boot()\n    {\n        Config::load();  // 加上这一行\n    }\n}\n```\n\n最后运行命令导入菜单和权限（也可以手动添加）\n\n```\n$ php artisan admin:import config\n```\n\n然后打开`http://localhost/admin/config`访问.\n\n## 使用\n\n打开`http://localhost/admin/config`，添加一项配置，填写`Name`、`Value`、和`Description`, `Name`是配置的`key`,`Description`是选填的配置注释\n\n最后在程序中使用`config($key)`来获取配置，注意，配置的`Name`不要和`config`目录中的已存在的配置冲突，不然会覆盖掉系统的配置\n\n"
  },
  {
    "path": "docs/zh/extension-helpers.md",
    "content": "# 帮助工具\n\n在最新的版本中新增了面向开发人员的帮助工具，能在开发中提供帮助提高效率，目前提供`脚手架`，`数据库命令行`和`artisan命令行`三个工具，如果有更好的其它实用工具的想法，欢迎提供建议。\n\n安装：\n```php\ncomposer require laravel-admin-ext/helpers\n\nphp artisan admin:import helpers\n```\n\n> 工具的部分功能会在项目中创建或删除文件，可能会出现文件或目录权限的问题，这个问题需要自行解决。\n> 另外部分数据库和artisan命令无法在web环境下使用。\n\n## 脚手架工具\n\n脚手架工具能帮你一键生成控制器、模型、迁移文件，并运行迁移文件，访问`http://localhost/admin/helpers/scaffold`打开。\n\n其中设置迁移表结构的时候，主键字段是自动生成的不需要填写。\n\n![qq20170220-2](https://cloud.githubusercontent.com/assets/1479100/23147949/cbf03e84-f81d-11e6-82b7-d7929c3033a0.png)\n\n## 数据库命令行\n\n数据库命令行工具的web集成，目前支持`mysql`、`mongodb` 和 `redis`，访问`http://localhost/admin/helpers/terminal/database`打开。\n\n在右上角的`select`选择框切换数据库连接，然后在底部的输入框输入对应数据库的查询语句然后回车，就能得到查询结果：\n\n![qq20170220-3](https://cloud.githubusercontent.com/assets/1479100/23147951/ce08e5d6-f81d-11e6-8b20-605e8cd06167.png)\n\n实用方式和终端上操作数据库是一致的，可以运行所选择数据库的所支持的查询语句。\n\n## artisan命令行工具\n\n`Laravel`的`artisan`命令的web实现，可以在上面运行artisan命令，访问`http://localhost/admin/helpers/terminal/artisan`打开。\n\n![qq20170220-1](https://cloud.githubusercontent.com/assets/1479100/23147963/da8a5d30-f81d-11e6-97b9-239eea900ad3.png)\n\n## 路由列表\n\n这个工具能用用比较直观的展现出系统的所有路由，包括路由的uri、方法和中间件等，还能查询路由。访问`http://localhost/admin/helpers/routes`打开。\n\n![helpers_routes](https://user-images.githubusercontent.com/1479100/30899066-e8bdd5ca-a390-11e7-809d-4ceccd0da27f.png)\n"
  },
  {
    "path": "docs/zh/extension-media-manager.md",
    "content": "# 文件管理\n\n文件管理是一个对本地文件的可视化管理的工具\n\n![wx20170809-170104](https://user-images.githubusercontent.com/1479100/29113762-99886c32-7d24-11e7-922d-5981a5849c7a.png)\n\n## 安装\n\n```\n$ composer require laravel-admin-ext/media-manager -vvv\n\n$ php artisan admin:import media-manager\n```\n\n## 配置\n\n打开`config/admin.php`指定你要管理的disk\n\n```php\n\n    'extensions' => [\n\n        'media-manager' => [\n            'disk' => 'public'   // 指向config/filesystem.php中设置的disk\n        ],\n    ],\n\n```\n\n`disk`为`config/filesystem.php`中设置的本地disk，然后打开`http://localhost/admin/media`访问.\n\n注意如果要预览disk中的图片，必须在disk中设置访问url前缀： \n\n\n`config/filesystem.php`：\n```php\n\n    'disks' => [\n\n        'public' => [\n            'driver' => 'local',\n            'root' => storage_path('app/public'),\n            'url' => env('APP_URL').'/storage',    // 设置文件访问url\n            'visibility' => 'public',\n        ],\n        \n        ...\n    ]\n```\n\n"
  },
  {
    "path": "docs/zh/extension-scheduling.md",
    "content": "# 定时任务\n\n这个工具是管理Laravel计划任务的web管理页面\n\n![wx20170810-101048](https://user-images.githubusercontent.com/1479100/29151552-8affc0b2-7db4-11e7-932a-a10d8a42ec50.png)\n\n## 安装\n\n```\n$ composer require laravel-admin-ext/scheduling -vvv\n\n$ php artisan admin:import scheduling\n```\n\n打开`http://localhost/admin/scheduling`访问。\n\n## 添加任务\n\n打开`app/Console/Kernel.php`， 试着添加两项计划任务：\n\n```php\nclass Kernel extends ConsoleKernel\n{\n    protected function schedule(Schedule $schedule)\n    {\n        $schedule->command('inspire')->everyTenMinutes();\n        \n        $schedule->command('route:list')->dailyAt('02:00');\n    }\n}\n\n```\n\n然后就能在后台看到这两项计划任务的详细情况，也能直接运行这两个计划任务。\n"
  },
  {
    "path": "docs/zh/installation.md",
    "content": "# 安装\n\n> 当前版本(1.5)需要安装`PHP 7+`和`Laravel 5.5`, 如果你使用更早的版本，请参考文档: [1.4](http://laravel-admin.org/docs/v1.4/#/zh/) \n\n首先确保安装好了`laravel`，并且数据库连接设置正确。\n\n```\ncomposer require encore/laravel-admin \"1.5.*\"\n```\n\n然后运行下面的命令来发布资源：\n\n```\nphp artisan vendor:publish --provider=\"Encore\\Admin\\AdminServiceProvider\"\n```\n\n在该命令会生成配置文件`config/admin.php`，可以在里面修改安装的地址、数据库连接、以及表名，建议都是用默认配置不修改。\n\n然后运行下面的命令完成安装：\n```\nphp artisan admin:install\n```\n\n启动服务后，在浏览器打开 `http://localhost/admin/` ,使用用户名 `admin` 和密码 `admin`登陆.\n\n## 生成的文件\n\n安装完成之后,会在项目目录中生成以下的文件:\n\n### 配置文件\n\n安装完成之后，`laravel-admin`所有的配置都在`config/admin.php`文件中。\n\n### 后台项目文件\n安装完成之后，后台的安装目录为`app/Admin`，之后大部分的后台开发编码工作都是在这个目录下进行。\n\n```\napp/Admin\n├── Controllers\n│   ├── ExampleController.php\n│   └── HomeController.php\n├── bootstrap.php\n└── routes.php\n```\n\n`app/Admin/routes.php`文件用来配置后台路由。\n\n`app/Admin/bootstrap.php` 是`laravel-admin`的启动文件, 使用方法请参考文件里面的注释.\n\n`app/Admin/Controllers`目录用来存放后台控制器文件，该目录下的`HomeController.php`文件是后台首页的显示控制器，`ExampleController.php`为实例文件。\n\n### 静态文件\n\n后台所需的前端静态文件在`/public/vendor/laravel-admin`目录下."
  },
  {
    "path": "docs/zh/model-form-callback.md",
    "content": "# 模型表单回调\n\n`model-form`目前提供了两个方法来接收回调函数：\n\n```php\n//保存前回调\n$form->saving(function (Form $form) {\n    //...\n});\n\n//保存后回调\n$form->saved(function (Form $form) {\n    //...\n});\n\n```\n可以从回调参数`$form`中获取当前提交的表单数据：\n\n```php\n$form->saving(function (Form $form) {\n\n    dump($form->username);\n\n});\n\n```\n\n获取获取模型中的数据\n```php\n$form->saved(function (Form $form) {\n\n    $form->model()->id;\n\n});\n```\n\n可以直接在回调中返回`Symfony\\Component\\HttpFoundation\\Response`的实例，来跳转或进入页面：\n```php\n$form->saving(function (Form $form) {\n\n    // 返回一个简单response\n    return response('xxxx');\n\n});\n\n$form->saving(function (Form $form) {\n\n    // 跳转页面\n    return redirect('/admin/users');\n\n});\n\n$form->saving(function (Form $form) {\n\n    // 抛出异常\n    throw new \\Exception('出错啦。。。');\n\n});\n\n```\n\n返回错误或者成功信息在页面上：\n\n```php\nuse Illuminate\\Support\\MessageBag;\n\n// 抛出错误信息\n$form->saving(function ($form) {\n\n    $error = new MessageBag([\n        'title'   => 'title...',\n        'message' => 'message....',\n    ]);\n\n    return back()->with(compact('error'));\n});\n\n// 抛出成功信息\n$form->saving(function ($form) {\n\n    $success = new MessageBag([\n        'title'   => 'title...',\n        'message' => 'message....',\n    ]);\n\n    return back()->with(compact('success'));\n});\n\n```"
  },
  {
    "path": "docs/zh/model-form-field-management.md",
    "content": "# 组件管理\n\n## 移除已有组件\n\nform表单内置的`map`和`editor`组件通过cdn的方式引用了前端文件，如果网络方面有问题，可以通过下面的方式将它们移除\n\n找到文件`app/Admin/bootstrap.php`,如果文件不存在，请更新`laravel-admin`，然后新建该文件\n\n```php\n\n<?php\n\nuse Encore\\Admin\\Form;\n\nForm::forget('map');\nForm::forget('editor');\n\n// or\n\nForm::forget(['map', 'editor']);\n\n```\n\n这样就去掉了这两个组件，可以通过该方式去掉其它组件。\n\n\n## 扩展自定义组件\n\n\n### 集成富文本编辑器wangEditor\n\n[wangEditor](http://www.wangeditor.com/)是一个优秀的国产的轻量级富文本编辑器，如果`laravel-admin`自带的基于`ckeditor`的编辑器组件使用上有问题，可以通过下面的步骤可以集成它，并覆盖掉`ckeditor`：\n\n先下载前端库文件[wangEditor](https://github.com/wangfupeng1988/wangEditor/releases)，解压到目录`public/vendor/wangEditor-3.0.9`。\n\n然后新建组件类`app/Admin/Extensions/WangEditor.php`。\n\n```php\n\n<?php\n\nnamespace App\\Admin\\Extensions;\n\nuse Encore\\Admin\\Form\\Field;\n\nclass WangEditor extends Field\n{\n    protected $view = 'admin.wang-editor';\n\n    protected static $css = [\n        '/vendor/wangEditor-3.0.9/release/wangEditor.min.css',\n    ];\n\n    protected static $js = [\n        '/vendor/wangEditor-3.0.9/release/wangEditor.min.js',\n    ];\n\n    public function render()\n    {\n        $name = $this->formatName($this->column);\n\n        $this->script = <<<EOT\n\nvar E = window.wangEditor\nvar editor = new E('#{$this->id}');\neditor.customConfig.zIndex = 0\neditor.customConfig.uploadImgShowBase64 = true\neditor.customConfig.onchange = function (html) {\n    $('input[name=$name]').val(html);\n}\neditor.create()\n\nEOT;\n        return parent::render();\n    }\n}\n\n```\n\n新建视图文件`resources/views/admin/wang-editor.blade.php`：\n```php\n<div class=\"form-group {!! !$errors->has($label) ?: 'has-error' !!}\">\n\n    <label for=\"{{$id}}\" class=\"col-sm-2 control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\">\n\n        @include('admin::form.error')\n\n        <div id=\"{{$id}}\" style=\"width: 100%; height: 100%;\">\n            <p>{!! old($column, $value) !!}</p>\n        </div>\n\n        <input type=\"hidden\" name=\"{{$name}}\" value=\"{{ old($column, $value) }}\" />\n\n    </div>\n</div>\n```\n\n然后注册进`laravel-admin`,在`app/Admin/bootstrap.php`中添加以下代码：\n\n```php\n\n<?php\n\nuse App\\Admin\\Extensions\\WangEditor;\nuse Encore\\Admin\\Form;\n\nForm::extend('editor', WangEditor::class);\n\n```\n\n调用:\n\n```\n\n$form->editor('body');\n\n```\n\n### 集成富文本编辑器ckeditor\n\n先下载[ckeditor](http://ckeditor.com/download) 并解压到/public目录，比如放在`/public/packages/`目录下。\n\n然后新建扩展文件`app/Admin/Extensions/Form/CKEditor.php`:\n```php\n<?php\n\nnamespace App\\Admin\\Extensions\\Form;\n\nuse Encore\\Admin\\Form\\Field;\n\nclass CKEditor extends Field\n{\n    public static $js = [\n        '/packages/ckeditor/ckeditor.js',\n        '/packages/ckeditor/adapters/jquery.js',\n    ];\n\n    protected $view = 'admin.ckeditor';\n\n    public function render()\n    {\n        $this->script = \"$('textarea.{$this->getElementClass()}').ckeditor();\";\n\n        return parent::render();\n    }\n}\n```\n\n新建view `resources/views/admin/ckeditor.blade.php`:\n```php\n<div class=\"form-group {!! !$errors->has($errorKey) ?: 'has-error' !!}\">\n\n    <label for=\"{{$id}}\" class=\"col-sm-2 control-label\">{{$label}}</label>\n\n    <div class=\"col-sm-6\">\n\n        @include('admin::form.error')\n\n        <textarea class=\"form-control {{ $class }}\" name=\"{{$name}}\" placeholder=\"{{ $placeholder }}\" {!! $attributes !!} >{{ old($column, $value) }}</textarea>\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>\n\n```\n\n然后在`app/Admin/bootstrap.php`中引入扩展：\n```php\nuse App\\Admin\\Extensions\\Form\\CKEditor;\nuse Encore\\Admin\\Form;\n\nForm::extend('ckeditor', CKEditor::class);\n```\n\n然后就能在form中使用了:\n```php\n$form->ckeditor('content');\n```\n\n### 集成PHP editor\n\n\n通过下面的步骤来扩展一个基于[codemirror](http://codemirror.net/index.html)的PHP代码编辑器，效果参考[PHP mode](http://codemirror.net/mode/php/)。\n\n先将[codemirror](http://codemirror.net/codemirror.zip)库下载并解压到前端资源目录下，比如放在`public/packages/codemirror-5.20.2`目录下。\n\n新建组件类`app/Admin/Extensions/PHPEditor.php`:\n\n```php\n<?php\n\nnamespace App\\Admin\\Extensions;\n\nuse Encore\\Admin\\Form\\Field;\n\nclass PHPEditor extends Field\n{\n    protected $view = 'admin.php-editor';\n\n    protected static $css = [\n        '/packages/codemirror-5.20.2/lib/codemirror.css',\n    ];\n\n    protected static $js = [\n        '/packages/codemirror-5.20.2/lib/codemirror.js',\n        '/packages/codemirror-5.20.2/addon/edit/matchbrackets.js',\n        '/packages/codemirror-5.20.2/mode/htmlmixed/htmlmixed.js',\n        '/packages/codemirror-5.20.2/mode/xml/xml.js',\n        '/packages/codemirror-5.20.2/mode/javascript/javascript.js',\n        '/packages/codemirror-5.20.2/mode/css/css.js',\n        '/packages/codemirror-5.20.2/mode/clike/clike.js',\n        '/packages/codemirror-5.20.2/mode/php/php.js',\n    ];\n\n    public function render()\n    {\n        $this->script = <<<EOT\n\nCodeMirror.fromTextArea(document.getElementById(\"{$this->id}\"), {\n    lineNumbers: true,\n    mode: \"text/x-php\",\n    extraKeys: {\n        \"Tab\": function(cm){\n            cm.replaceSelection(\"    \" , \"end\");\n        }\n     }\n});\n\nEOT;\n        return parent::render();\n\n    }\n}\n\n```\n\n>类中的静态资源也同样可以从外部引入，参考[Editor.php](https://github.com/z-song/laravel-admin/blob/1.3/src/Form/Field/Editor.php)\n\n创建视图`resources/views/admin/php-editor.blade.php`:\n\n```php\n\n<div class=\"form-group {!! !$errors->has($label) ?: 'has-error' !!}\">\n\n    <label for=\"{{$id}}\" class=\"col-sm-2 control-label\">{{$label}}</label>\n\n    <div class=\"col-sm-6\">\n\n        @include('admin::form.error')\n\n        <textarea class=\"form-control\" id=\"{{$id}}\" name=\"{{$name}}\" placeholder=\"{{ trans('admin::lang.input') }} {{$label}}\" {!! $attributes !!} >{{ old($column, $value) }}</textarea>\n    </div>\n</div>\n\n```\n\n最后找到文件`app/Admin/bootstrap.php`,如果文件不存在，请更新`laravel-admin`，然后新建该文件,添加下面代码：\n\n```\n<?php\n\nuse App\\Admin\\Extensions\\PHPEditor;\nuse Encore\\Admin\\Form;\n\nForm::extend('php', PHPEditor::class);\n\n```\n\n这样就能在[model-form](/zh/model-form.md)中使用PHP编辑器了：\n\n```\n\n$form->php('code');\n\n```\n\n通过这种方式，可以添加任意你想要添加的form组件。"
  },
  {
    "path": "docs/zh/model-form-fields.md",
    "content": "# 表单组件\n\n在`model-form`中内置了大量的form组件来帮助你快速的构建form表单\n\n## 公共方法\n\n### 设置保存值\n```php\n$form->text('title')->value('text...');\n```\n\n### 设置默认值\n```php\n$form->text('title')->default('text...');\n```\n\n### 设置help信息\n```php\n$form->text('title')->help('help...');\n```\n\n### 设置属性\n```php\n$form->text('title')->attribute(['data-title' => 'title...']);\n\n$form->text('title')->attribute('data-title', 'title...');\n```\n\n### 设置placeholder\n```php\n$form->text('title')->placeholder('请输入。。。');\n```\n\n### model-form-tab\n\n如果表单元素太多,会导致form页面太长, 这种情况下可以使用tab来分隔form:\n\n```php\n\n$form->tab('Basic info', function ($form) {\n    \n    $form->text('username');\n    $form->email('email');\n    \n})->tab('Profile', function ($form) {\n                       \n   $form->image('avatar');\n   $form->text('address');\n   $form->mobile('phone');\n   \n})->tab('Jobs', function ($form) {\n                         \n     $form->hasMany('jobs', function () {\n         $form->text('company');\n         $form->date('start_date');\n         $form->date('end_date');\n     });\n\n  })\n\n```\n\n## 文本输入框\n\n```php\n$form->text($column, [$label]);\n\n// 添加提交验证规则\n$form->text($column, [$label])->rules('required|min:10');\n```\n\n## select选择框\n```php\n$form->select($column[, $label])->options([1 => 'foo', 2 => 'bar', 'val' => 'Option name']);\n```\n\n或者从api中获取选项列表：\n```php\n$form->select($column[, $label])->options('/api/users');\n\n// 使用ajax并显示所选项目\n\n$form->select($column[, $label])->options(Model::class)->ajax('/api/users');\n\n// 或指定名称和ID\n\n$form->select($column[, $label])->options(Model::class, 'name', 'id')->ajax('/api/users');\n```\n其中api接口的格式必须为下面格式：\n```php\n[\n    {\n        \"id\": 9,\n        \"text\": \"xxx\"\n    },\n    {\n        \"id\": 21,\n        \"text\": \"xxx\"\n    },\n    ...\n]\n```\n\n如果选项过多，可通过ajax方式动态分页载入选项：\n\n```php\n$form->select('user_id')->options(function ($id) {\n    $user = User::find($id);\n\n    if ($user) {\n        return [$user->id => $user->name];\n    }\n})->ajax('/admin/api/users');\n```\n\n<sub>注：如果你修改了`config/admin.php`配置文件中`route.prefix`的值，此处的接口路由应该修改为`config('admin.route.prefix').'/api/users'`。</sub>\n\nAPI `/admin/api/users`接口的代码：\n\n```php\npublic function users(Request $request)\n{\n    $q = $request->get('q');\n\n    return User::where('name', 'like', \"%$q%\")->paginate(null, ['id', 'name as text']);\n}\n\n```\n接口返回的数据结构为\n```\n{\n    \"total\": 4,\n    \"per_page\": 15,\n    \"current_page\": 1,\n    \"last_page\": 1,\n    \"next_page_url\": null,\n    \"prev_page_url\": null,\n    \"from\": 1,\n    \"to\": 3,\n    \"data\": [\n        {\n            \"id\": 9,\n            \"text\": \"xxx\"\n        },\n        {\n            \"id\": 21,\n            \"text\": \"xxx\"\n        },\n        {\n            \"id\": 42,\n            \"text\": \"xxx\"\n        },\n        {\n            \"id\": 48,\n            \"text\": \"xxx\"\n        }\n    ]\n}\n```\n\n### select 联动\n\n`select`组件支持父子关系的单向联动：\n```php\n$form->select('province')->options(...)->load('city', '/api/city');\n\n$form->select('city');\n\n```\n\n其中`load('city', '/api/city');`的意思是，在当前select的选项切换之后，会把当前选项的值通过参数`q`, 调用接口`/api/city`，并把api返回的数据填充为city选择框的选项，其中api`/api/city`返回的数据格式必须符合:\n\n```php\n[\n    {\n        \"id\": 9,\n        \"text\": \"xxx\"\n    },\n    {\n        \"id\": 21,\n        \"text\": \"xxx\"\n    },\n    ...\n]\n```\n控制器action的代码示例如下：\n\n```php\npublic function city(Request $request)\n{\n    $provinceId = $request->get('q');\n\n    return ChinaArea::city()->where('parent_id', $provinceId)->get(['id', DB::raw('name as text')]);\n}\n```\n\n## 多选框\n\n```php\n$form->multipleSelect($column[, $label])->options([1 => 'foo', 2 => 'bar', 'val' => 'Option name']);\n\n// 使用ajax并显示所选项目：\n\n$form->multipleSelect($column[, $label])->options(Model::class)->ajax('ajax_url');\n\n// 或指定名称和ID\n\n$form->multipleSelect($column[, $label])->options(Model::class, 'name', 'id')->ajax('ajax_url');\n```\n\n多选框可以处理两种情况，第一种是`ManyToMany`的关系。\n\n```\n\nclass Post extends Models\n{\n    public function tags()\n    {\n        return $this->belongsToMany(Tag::class);\n    }\n}\n\n$form->multipleSelect('tags')->options(Tag::all()->pluck('name', 'id'));\n\n```\n\n第二种是将选项数组存储到单字段中，如果字段是字符串类型，那就需要在模型里面为该字段定义[访问器和修改器](https://laravel.com/docs/5.5/eloquent-mutators)来存储和读取了。\n\n如果选项过多，可通过ajax方式动态分页载入选项：\n\n```php\n$form->select('friends')->options(function ($ids) {\n\n    return User::find($ids)->pluck('name', 'id');\n    \n})->ajax('/admin/api/users');\n```\n\n<sub>注：如果你修改了`config/admin.php`配置文件中`route.prefix`的值，此处的接口路由应该修改为`config('admin.route.prefix').'/api/users'`。</sub>\n\nAPI `/admin/api/users`接口的代码：\n\n```php\npublic function users(Request $request)\n{\n    $q = $request->get('q');\n\n    return User::where('name', 'like', \"%$q%\")->paginate(null, ['id', 'name as text']);\n}\n\n```\n接口返回的数据结构为\n```\n{\n    \"total\": 4,\n    \"per_page\": 15,\n    \"current_page\": 1,\n    \"last_page\": 1,\n    \"next_page_url\": null,\n    \"prev_page_url\": null,\n    \"from\": 1,\n    \"to\": 3,\n    \"data\": [\n        {\n            \"id\": 9,\n            \"text\": \"xxx\"\n        },\n        {\n            \"id\": 21,\n            \"text\": \"xxx\"\n        },\n        {\n            \"id\": 42,\n            \"text\": \"xxx\"\n        },\n        {\n            \"id\": 48,\n            \"text\": \"xxx\"\n        }\n    ]\n}\n```\n\n## listbox\n\n使用方法和`multipleSelect`类似\n\n```php\n$form->listbox($column[, $label])->options([1 => 'foo', 2 => 'bar', 'val' => 'Option name']);\n```\n\n## textarea输入框\n```php\n$form->textarea($column[, $label])->rows(10);\n```\n\n## radio选择\n```php\n$form->radio($column[, $label])->options(['m' => 'Female', 'f'=> 'Male'])->default('m');\n\n// 竖排\n$form->radio($column[, $label])->options(['m' => 'Female', 'f'=> 'Male'])->stacked();\n```\n\n## checkbox选择\n\n`checkbox`能处理两种数据存储情况，参考[多选框](#多选框)\n\n`options()`方法用来设置选择项:\n```php\n$form->checkbox($column[, $label])->options([1 => 'foo', 2 => 'bar', 'val' => 'Option name']);\n\n// 竖排\n$form->checkbox($column[, $label])->options([1 => 'foo', 2 => 'bar', 'val' => 'Option name'])->stacked();\n```\n\n## email个数输入框\n```php\n$form->email($column[, $label]);\n```\n\n## 密码输入框\n```php\n$form->password($column[, $label]);\n```\n\n## url输入框\n```php\n$form->url($column[, $label]);\n```\n\n## ip输入框\n```php\n$form->ip($column[, $label]);\n```\n\n## 电话号码输入框\n```php\n$form->mobile($column[, $label])->options(['mask' => '999 9999 9999']);\n```\n\n## 颜色选择框\n```php\n$form->color($column[, $label])->default('#ccc');\n```\n\n## 时间输入框\n```php\n$form->time($column[, $label]);\n\n// 设置时间格式，更多格式参考http://momentjs.com/docs/#/displaying/format/\n$form->time($column[, $label])->format('HH:mm:ss');\n```\n\n## 日期输入框\n```php\n$form->date($column[, $label]);\n\n// 设置日期格式，更多格式参考http://momentjs.com/docs/#/displaying/format/\n$form->date($column[, $label])->format('YYYY-MM-DD');\n```\n\n## 日期时间输入框\n```php\n$form->datetime($column[, $label]);\n\n// 设置日期格式，更多格式参考http://momentjs.com/docs/#/displaying/format/\n$form->datetime($column[, $label])->format('YYYY-MM-DD HH:mm:ss');\n```\n\n## 时间范围选择框\n`$startTime`、`$endTime`为开始和结束时间字段:\n```php\n$form->timeRange($startTime, $endTime, 'Time Range');\n```\n\n## 日期范围选框\n`$startDate`、`$endDate`为开始和结束日期字段:\n```php\n$form->dateRange($startDate, $endDate, 'Date Range');\n```\n\n## 时间日期范围选择框\n`$startDateTime`、`$endDateTime`为开始和结束时间日期:\n```php\n$form->datetimeRange($startDateTime, $endDateTime, 'DateTime Range');\n```\n\n## 货币输入框\n```php\n$form->currency($column[, $label]);\n\n// 设置单位符号\n$form->currency($column[, $label])->symbol('￥');\n\n```\n\n## 数字输入框\n```php\n$form->number($column[, $label]);\n```\n\n## 比例输入框\n```php\n$form->rate($column[, $label]);\n```\n\n## 图片上传\n\n使用图片上传功能之前需要先完成上传配置，请参考:[图片/文件上传](/zh/model-form-upload.md).\n\n图片上传目录在文件`config/admin.php`中的`upload.image`中配置，如果目录不存在，需要创建该目录并开放写权限。\n\n可以使用压缩、裁切、添加水印等各种方法,需要先安装[intervention/image](http://image.intervention.io/getting_started/installation).\n\n更多使用方法请参考[[Intervention](http://image.intervention.io/getting_started/introduction)]：\n```php\n$form->image($column[, $label]);\n\n// 修改图片上传路径和文件名\n$form->image($column[, $label])->move($dir, $name);\n\n// 剪裁图片\n$form->image($column[, $label])->crop(int $width, int $height, [int $x, int $y]);\n\n// 加水印\n$form->image($column[, $label])->insert($watermark, 'center');\n\n// 添加图片删除按钮\n$form->image($column[, $label])->removable();\n\n```\n\n## 文件上传\n\n使用图片上传功能之前需要先完成上传配置，请参考:[图片/文件上传](/zh/model-form-upload.md).\n\n文件上传目录在文件`config/admin.php`中的`upload.file`中配置，如果目录不存在，需要创建该目录并开放写权限。\n```php\n$form->file($column[, $label]);\n\n// 修改文件上传路径和文件名\n$form->file($column[, $label])->move($dir, $name);\n\n// 并设置上传文件类型\n$form->file($column[, $label])->rules('mimes:doc,docx,xlsx');\n\n// 添加文件删除按钮\n$form->file($column[, $label])->removable();\n\n```\n\n## 多图/文件上传\n\n```php\n// 多图\n$form->multipleImage($column[, $label]);\n\n// 添加删除按钮\n$form->multipleImage($column[, $label])->removable();\n\n// 多文件\n$form->multipleFile($column[, $label]);\n\n// 添加删除按钮\n$form->multipleFile($column[, $label])->removable();\n```\n\n多图/文件上传的时候提交的数据为文件路径数组,可以直接用mysql的`JSON`类型字段存储,如果用mongodb的话也能直接存储,但是如果用字符串类型来存储的话,就需要指定数据的存储格式了,\n比如,如果要用json字符串来存储文件数据,就需要在模型中定义字段的mutator,比如字段名为`pictures`,定义mutator:\n```php\npublic function setPicturesAttribute($pictures)\n{\n    if (is_array($pictures)) {\n        $this->attributes['pictures'] = json_encode($pictures);\n    }\n}\n\npublic function getPicturesAttribute($pictures)\n{\n    return json_decode($pictures, true);\n}\n```\n当然你也可以指定其它任何格式.\n\n## 地图控件\n\n地图组件引用了网络资源，默认关闭,如果要开启这个组件参考[form组件管理](/zh/model-form-field-management.md)\n\n地图控件，用来选择经纬度,`$latitude`, `$longitude`为经纬度字段，`Laravel`的`locale`设置为`zh_CN`的时候使用腾讯地图，否则使用Google地图：\n```php\n$form->map($latitude, $longitude, $label);\n```\n\n## 滑动选择控件\n可以用来数字类型字段的选择，比如年龄：\n```php\n$form->slider($column[, $label])->options(['max' => 100, 'min' => 1, 'step' => 1, 'postfix' => 'years old']);\n```\n更多options请参考:https://github.com/IonDen/ion.rangeSlider#settings\n\n## 富文本编辑框\n\n编辑器组件引用了网络资源，默认关闭,如果要开启这个组件参考[form组件管理](/zh/model-form-field-management.md).\n\n```php\n$form->editor($column[, $label]);\n```\n\n## 隐藏域\n```php\n$form->hidden($column);\n```\n\n## 开关选择\n`on`和`off`对用开关的两个值`1`和`0`:\n```php\n$states = [\n    'on'  => ['value' => 1, 'text' => '打开', 'color' => 'success'],\n    'off' => ['value' => 0, 'text' => '关闭', 'color' => 'danger'],\n];\n\n$form->switch($column[, $label])->states($states);\n```\n\n## 显示字段\n只显示字段，不做任何操作：\n```php\n$form->display($column[, $label]);\n\n\n//更复杂的显示\n$form->display($column[, $label])->with(function ($value) {\n    return \"<img src=\"$value\" />\";\n});\n```\n\n## 分割线\n```php\n$form->divide();\n```\n\n## Html\n插入html内容，参数可以是实现了`Htmlable`、`Renderable`或者实现了`__toString()`方法的类\n```php\n$form->html('你的html内容', $label = '');\n```\n\n## 标签\n插入逗号(,)隔开的字符串`tags`\n```php\n$form->tags('keywords');\n```\n\n`tags`同样支持`ManyToMany`的关系，示例如下：\n\n```php\n$form->tags('tags', '文章标签')\n    ->pluck('name', 'id') // name 为需要显示的 Tag 模型的字段，id 为主键\n    ->options(Tag::all());// 下拉框选项\n```\n\n注意：处理`ManyToMany`关系时必须调用`pluck`方法，指定显示的字段名和主键。\n此外 `options` 方法传入一个`Collection`对象时，`options`会自动调用该对象的`pluck`方法转为`['主键名' => '显示字段名']` 数组，作为下拉框选项。或者可以直接使用`['主键名' => '显示字段名']`这样的数组作为参数。\n\n`tags`还支持`saving`方法用于处理提交的数据，示例如下：\n\n```php\n$form->tags('tags', '文章标签')\n    ->pluck('name', 'id')\n    ->options(Tag::all())\n    ->saving(function ($value) {\n        return $value;\n    });\n```\n\n`saving` 方法接收一个「参数为 tags 的提交值，返回值为修改后的 tags 提交值」的闭包，可以用于实现自动创建新 tag 或其它功能。\n\n## 图标\n选择`font-awesome`图标\n```php\n$form->icon('icon');\n```\n\n## 一对多\n\n一对多内嵌表格，用于处理一对多的关系，下面是个简单的例子：\n\n有两张表是一对多关系：\n\n```sql\nCREATE TABLE `demo_painters` (\n  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n  `username` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n  `bio` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;\n\nCREATE TABLE `demo_paintings` (\n  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n  `painter_id` int(10) unsigned NOT NULL,\n  `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n  `body` text COLLATE utf8_unicode_ci NOT NULL,\n  `completed_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  PRIMARY KEY (`id`),\n  KEY painter_id (`painter_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;\n```\n\n表的模型为：\n```php\n<?php\n\nnamespace App\\Models\\Demo;\n\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass Painter extends Model\n{\n    public function paintings()\n    {\n        return $this->hasMany(Painting::class, 'painter_id');\n    }\n}\n\n<?php\n\nnamespace App\\Models\\Demo;\n\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass Painting extends Model\n{\n    protected $fillable = ['title', 'body', 'completed_at'];\n\n    public function painter()\n    {\n        return $this->belongsTo(Painter::class, 'painter_id');\n    }\n}\n```\n\n构建表单代码如下：\n```php\n$form->display('id', 'ID');\n\n$form->text('username')->rules('required');\n$form->textarea('bio')->rules('required');\n\n$form->hasMany('paintings', function (Form\\NestedForm $form) {\n    $form->text('title');\n    $form->image('body');\n    $form->datetime('completed_at');\n});\n\n$form->display('created_at', 'Created At');\n$form->display('updated_at', 'Updated At');\n\n// 也可以设置label\n\n$form->hasMany('paintings', '画作', function (Form\\NestedForm $form) {\n    \n});\n```\n\n## 内嵌\n\n用于处理`mysql`的`JSON`类型字段数据或者`mongodb`的`object`类型数据，也可以将多个field的数据值以`JSON`字符串的形式存储在`mysql`的字符串类型字段中\n\n比如`orders`表中的`JSON`或字符串类型的`extra`字段，用来存储多个field的数据，先定义model:\n```php\nclass Order extends Model\n{\n    protected $casts = [\n        'extra' => 'json',\n    ];\n}\n```\n然后在form中使用：\n```php\n$form->embeds('extra', function ($form) {\n\n    $form->text('extra1')->rules('required');\n    $form->email('extra2')->rules('required');\n    $form->mobile('extra3');\n    $form->datetime('extra4');\n\n    $form->dateRange('extra5', 'extra6', '范围')->rules('required');\n\n});\n\n// 自定义标题\n$form->embeds('extra', '附加信息', function ($form) {\n    ...\n});\n```\n\n回调函数里面构建表单元素的方法调用和外面是一样的。\n"
  },
  {
    "path": "docs/zh/model-form-upload.md",
    "content": "# 文件/图片上传\n\n[model-form](/zh/model-form.md)通过以下的调用来生成form元素。\n\n```php\n$form->file('file_column');\n$form->image('image_column');\n```\n\n## 修改存储路径或文件名\n\n```php\n\n// 修改上传目录\n$form->image('picture')->move('public/upload/image1/');\n\n// 使用随机生成文件名 (md5(uniqid()).extension)\n$form->image('picture')->uniqueName();\n\n// 自定义文件名\n$form->image('picture')->name(function ($file) {\n    return 'test.'.$file->guessExtension();\n});\n\n```\n\n[model-form](/zh/model-form.md)支持本地和云存储的文件上传\n\n## 本地上传\n\n先添加存储配置，`config/filesystems.php` 添加一项`disk`:\n\n```php\n\n'disks' => [\n    ... ,\n\n    'admin' => [\n        'driver' => 'local',\n        'root' => public_path('uploads'),\n        'visibility' => 'public',\n        'url' => env('APP_URL').'/uploads',\n    ],\n],\n\n```\n\n设置上传的路径为`public/uploads`(public_path('uploads'))。\n\n然后选择上传的`disk`，打开`config/admin.php`找到：\n\n```php\n    \n'upload'  => [\n\n    'disk' => 'admin',\n\n    'directory'  => [\n        'image'  => 'images',\n        'file'   => 'files',\n    ]\n],\n\n```\n\n将`disk`设置为上面添加的`admin`，`directory.image`和`directory.file`分别为用`$form->image($column)`和`$form->file($column)`上传的图片和文件的上传目录。\n\n\n## 云盘上传\n\n如果需要上传到云存储，需要安装对应`laravel storage`的适配器，拿七牛云存储举例\n\n首先安装 [zgldh/qiniu-laravel-storage](https://github.com/zgldh/qiniu-laravel-storage)\n\n同样配置好disk，在`config/filesystems.php` 添加一项:\n\n```php\n'disks' => [\n    ... ,\n    'qiniu' => [\n        'driver'  => 'qiniu',\n        'domains' => [\n            'default'   => 'xxxxx.com1.z0.glb.clouddn.com', //你的七牛域名\n            'https'     => 'dn-yourdomain.qbox.me',         //你的HTTPS域名\n            'custom'    => 'static.abc.com',                //你的自定义域名\n         ],\n        'access_key'=> '',  //AccessKey\n        'secret_key'=> '',  //SecretKey\n        'bucket'    => '',  //Bucket名字\n        'notify_url'=> '',  //持久化处理回调地址\n        'url'       => 'http://of8kfibjo.bkt.clouddn.com/',  // 填写文件访问根url\n    ],\n],\n\n```\n\n然后修改`laravel-admin`的上传配置，打开`config/admin.php`找到：\n\n```php\n\n'upload'  => [\n\n    'disk' => 'qiniu',\n\n    'directory'  => [\n        'image'  => 'image',\n        'file'   => 'file',\n    ],\n],\n\n```\n\n`disk`选择上面配置的`qiniu`。\n"
  },
  {
    "path": "docs/zh/model-form-validation.md",
    "content": "表单验证\n========\n\n`model-form`使用laravel的验证规则来验证表单提交的数据：\n\n```php\n$form->text('title')->rules('required|min:3');\n\n// 复杂的验证规则可以在回调里面实现\n$form->text('title')->rules(function ($form) {\n    \n    // 如果不是编辑状态，则添加字段唯一验证\n    if (!$id = $form->model()->id) {\n        return 'unique:users,email_address';\n    }\n    \n});\n\n```\n\n也可以给验证规则自定义错误提示消息：\n\n```php\n$form->text('code')->rules('required|regex:/^\\d+$/|min:10', [\n    'regex' => 'code必须全部为数字',\n    'min'   => 'code不能少于10个字符',\n]);\n```\n\n如果要允许字段为空，首先要在数据库的表里面对该字段设置为`NULL`，然后\n\n```php\n$form->text('title')->rules('nullable');\n```\n\n更多规则请参考[Validation](https://laravel.com/docs/5.5/validation)."
  },
  {
    "path": "docs/zh/model-form.md",
    "content": "# 基于数据模型的表单\n\n`Encore\\Admin\\Form`类用于生成基于数据模型的表单，先来个例子，数据库中有`movies`表\n\n```sql\nCREATE TABLE `movies` (\n  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n  `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n  `director` int(10) unsigned NOT NULL,\n  `describe` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n  `rate` tinyint unsigned NOT NULL,\n  `released` enum(0, 1),\n  `release_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;\n\n```\n\n对应的数据模型为`App\\Models\\Movie`，下面的代码可以生成`movies`的数据表单：\n\n```php\n\nuse App\\Models\\Movie;\nuse Encore\\Admin\\Form;\nuse Encore\\Admin\\Facades\\Admin;\n\n$grid = Admin::form(Movie::class, function(Form $form){\n\n    // 显示记录id\n    $form->display('id', 'ID');\n\n    // 添加text类型的input框\n    $form->text('title', '电影标题');\n    \n    $directors = [\n        1 => 'John',\n        2 => 'Smith',\n        3 => 'Kate',\n    ];\n    \n    $form->select('director', '导演')->options($directors);\n    \n    // 添加describe的textarea输入框\n    $form->textarea('describe', '简介');\n    \n    // 数字输入框\n    $form->number('rate', '打分');\n    \n    // 添加开关操作\n    $form->switch('released', '发布？');\n    \n    // 添加日期时间选择框\n    $form->datetime('release_at', '发布时间');\n    \n    // 两个时间显示\n    $form->display('created_at', '创建时间');\n    $form->display('updated_at', '修改时间');\n});\n\n```\n\n## 自定义工具\n\n表单右上角默认有返回和跳转列表两个按钮工具, 可以使用下面的方式修改它:\n\n```php\n$form->tools(function (Form\\Tools $tools) {\n\n    // 去掉返回按钮\n    $tools->disableBackButton();\n    \n    // 去掉跳转列表按钮\n    $tools->disableListButton();\n\n    // 添加一个按钮, 参数可以是字符串, 或者实现了Renderable或Htmlable接口的对象实例\n    $tools->add('<a class=\"btn btn-sm btn-danger\"><i class=\"fa fa-trash\"></i>&nbsp;&nbsp;delete</a>');\n});\n```\n\n## 其它方法\n\n去掉提交按钮:\n\n```php\n$form->disableSubmit();\n```\n\n去掉重置按钮:\n```php\n$form->disableReset();\n```\n\n忽略掉不需要保存的字段\n\n```php\n$form->ignore(['column1', 'column2', 'column3']);\n```\n\n设置宽度\n\n```php\n$form->setWidth(10, 2);\n```\n\n设置表单提交的action\n\n```php\n$form->setAction('admin/users');\n```\n\n## 关联模型\n\n\n### 一对一\n`users`表和`profiles`表通过`profiles.user_id`字段生成一对一关联\n\n```sql\n\nCREATE TABLE `users` (\n`id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n`email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\nPRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;\n\nCREATE TABLE `profiles` (\n`id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n`user_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n`age` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n`gender` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\nPRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;\n```\n\n对应的数据模分别为:\n\n```php\n\nclass User extends Model\n{\n    public function profile()\n    {\n        return $this->hasOne(Profile::class);\n    }\n}\n\nclass Profile extends Model\n{\n    public function user()\n    {\n        return $this->belongsTo(User::class);\n    }\n}\n\n```\n\n通过下面的代码可以关联在一个form里面:\n\n```php\nAdmin::form(User::class, function (Form $form) {\n\n    $form->display('id');\n\n    $form->text('name');\n    $form->text('email');\n    \n    $form->text('profile.age');\n    $form->text('profile.gender');\n\n    $form->datetime('created_at');\n    $form->datetime('updated_at');\n});\n\n```\n"
  },
  {
    "path": "docs/zh/model-grid-actions.md",
    "content": "# 模型表格行操作\n\n`model-grid`默认有三个行操作`编辑`、`删除`和`详情`，可以通过下面的方式关闭它们：\n\n```php\n $grid->actions(function ($actions) {\n    $actions->disableDelete();\n    $actions->disableEdit();\n    $actions->disableView();\n});\n```\n可以通过传入的`$actions`参数来获取当前行的数据：\n```php\n $grid->actions(function ($actions) {\n    \n    // 当前行的数据数组\n    $actions->row;\n    \n    // 获取当前行主键值\n    $actions->getKey();\n});\n```\n\n如果有自定义的操作按钮，可以通过下面的方式添加：\n\n```php\n$grid->actions(function ($actions) {\n    \n    // append一个操作\n    $actions->append('<a href=\"\"><i class=\"fa fa-eye\"></i></a>');\n\n    // prepend一个操作\n    $actions->prepend('<a href=\"\"><i class=\"fa fa-paper-plane\"></i></a>');\n}\n```\n\n如果有比较复杂的操作，可以参考下面的方式：\n\n\n先定义操作类\n```php\n<?php\n\nnamespace App\\Admin\\Extensions;\n\nuse Encore\\Admin\\Admin;\n\nclass CheckRow\n{\n    protected $id;\n\n    public function __construct($id)\n    {\n        $this->id = $id;\n    }\n\n    protected function script()\n    {\n        return <<<SCRIPT\n\n$('.grid-check-row').on('click', function () {\n    \n    // Your code.\n    console.log($(this).data('id'));\n    \n});\n\nSCRIPT;\n    }\n\n    protected function render()\n    {\n        Admin::script($this->script());\n\n        return \"<a class='btn btn-xs btn-success fa fa-check grid-check-row' data-id='{$this->id}'></a>\";\n    }\n    \n    public function __toString()\n    {\n        return $this->render();\n    }\n}\n```\n然后添加操作：\n```php\n$grid->actions(function ($actions) {\n    \n    // 添加操作\n    $actions->append(new CheckRow($actions->getKey()));\n});\n```\n"
  },
  {
    "path": "docs/zh/model-grid-column.md",
    "content": "# 列操作\n\n`model-grid`内置了很多对于列的操作方法，可以通过这些方法很灵活的操作列数据。\n\n`Encore\\Admin\\Grid\\Column`对象内置了`display()`方法来通过传入的回调函数来处理当前列的值，\n```php\n$grid->column('title')->display(function ($title) {\n\n    return \"<span style='color:blue'>$title</span>\";\n    \n});\n```\n在传入的匿名函数中可以通过任何方式对数据进行处理，另外匿名函数绑定了当前列的数据作为父对象，可以在函数中调用当前行的数据：\n```php\n\n$grid->first_name();\n\n$grid->last_name();\n\n// 不存在的`full_name`字段\n$grid->column('full_name')->display(function () {\n    return $this->first_name . ' ' . $this->last_name;\n});\n```\n\n> `value()`方法作为`display()`方法的别名存在\n\n## 内置方法\n\n`model-grid`内置了若干方法来帮助你扩展列功能\n\n### editable\n\n通过`editable.js`的帮助，可以让你在表格中直接编辑数据，使用方法如下\n```php\n$grid->title()->editable();\n\n$grid->title()->editable('textarea');\n\n$grid->title()->editable('select', [1 => 'option1', 2 => 'option2', 3 => 'option3']);\n\n// select 支持传递闭包作为参数，该闭包接收参数为当前行对应的模型\n$grid->title()->editable('select', function($row) {\n    if ($row->title === 'test') {\n        return ['test1', 'test2'];\n    }\n    return ['test3', 'test4'];\n});\n\n$grid->birth()->editable('date');\n\n$grid->published_at()->editable('datetime');\n\n$grid->column('year')->editable('year');\n\n$grid->column('month')->editable('month');\n\n$grid->column('day')->editable('day');\n\n```\n\n### switch\n\n> 注意：在`grid`中对某字段设置了`switch`，同时需要在`form`里面对该字段设置同样的`switch`\n\n快速将列变成开关组件，使用方法如下：\n```php\n$grid->status()->switch();\n\n// 设置text、color、和存储值\n$states = [\n    'on'  => ['value' => 1, 'text' => '打开', 'color' => 'primary'],\n    'off' => ['value' => 2, 'text' => '关闭', 'color' => 'default'],\n];\n$grid->status()->switch($states);\n\n```\n\n### switchGroup\n\n> 注意：在`grid`中对某些字段设置了`switch`，同时需要在`form`里面对这些字段设置同样的`switch`\n\n快速将列变成开关组件组，使用方法如下：\n```php\n$states = [\n    'on' => ['text' => 'YES'],\n    'off' => ['text' => 'NO'],\n];\n\n$grid->column('switch_group')->switchGroup([\n    'hot'        => '热门',\n    'new'        => '最新',\n    'recommend'  => '推荐',\n    'image.show' => '显示图片', // 更新对应关联模型\n], $states);\n\n```\n\n### select\n\n```php\n$grid->options()->select([\n    1 => 'Sed ut perspiciatis unde omni',\n    2 => 'voluptatem accusantium doloremque',\n    3 => 'dicta sunt explicabo',\n    4 => 'laudantium, totam rem aperiam',\n]);\n```\n\n`select` 也支持参数为闭包，使用方法和`editable`的`select`类似。\n\n### radio\n```php\n$grid->options()->radio([\n    1 => 'Sed ut perspiciatis unde omni',\n    2 => 'voluptatem accusantium doloremque',\n    3 => 'dicta sunt explicabo',\n    4 => 'laudantium, totam rem aperiam',\n]);\n```\n\n`radio` 也支持参数为闭包，使用方法和`editable`的`select`类似。\n\n### checkbox\n```php\n$grid->options()->checkbox([\n    1 => 'Sed ut perspiciatis unde omni',\n    2 => 'voluptatem accusantium doloremque',\n    3 => 'dicta sunt explicabo',\n    4 => 'laudantium, totam rem aperiam',\n]);\n```\n\n`checkbox` 也支持参数为闭包，使用方法和`editable`的`select`类似。\n\n### image\n\n```php\n$grid->picture()->image();\n\n//设置服务器和宽高\n$grid->picture()->image('http://xxx.com', 100, 100);\n\n// 显示多图\n$grid->pictures()->display(function ($pictures) {\n    \n    return json_decode($pictures, true);\n    \n})->image('http://xxx.com', 100, 100);\n```\n\n### label\n```php\n$grid->name()->label();\n\n//设置颜色，默认`success`,可选`danger`、`warning`、`info`、`primary`、`default`、`success`\n$grid->name()->label('danger');\n\n// 接收数组\n$grid->keywords()->label();\n```\n\n### badge\n\n```php\n$grid->name()->badge();\n\n//设置颜色，默认`success`,可选`danger`、`warning`、`info`、`primary`、`default`、`success`\n$grid->name()->badge('danger');\n\n// 接收数组\n$grid->keywords()->badge();\n```\n\n## 扩展列功能\n\n可以通过两种方式扩展列功能，第一种是通过匿名函数的方式。\n\n在`app/Admin/bootstrap.php`加入以下代码:\n```php\nuse Encore\\Admin\\Grid\\Column;\n\nColumn::extend('color', function ($value, $color) {\n    return \"<span style='color: $color'>$value</span>\"\n});\n```\n然后在`model-grid`中使用这个扩展：\n```php\n\n$grid->title()->color('#ccc');\n\n```\n\n如果列显示逻辑比较复杂，可以通过扩展类来实现。\n\n扩展类`app/Admin/Extensions/Popover.php`:\n```php\n<?php\n\nnamespace App\\Admin\\Extensions;\n\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Grid\\Displayers\\AbstractDisplayer;\n\nclass Popover extends AbstractDisplayer\n{\n    public function display($placement = 'left')\n    {\n        Admin::script(\"$('[data-toggle=\\\"popover\\\"]').popover()\");\n\n        return <<<EOT\n<button type=\"button\"\n    class=\"btn btn-secondary\"\n    title=\"popover\"\n    data-container=\"body\"\n    data-toggle=\"popover\"\n    data-placement=\"$placement\"\n    data-content=\"{$this->value}\"\n    >\n  弹出提示\n</button>\n\nEOT;\n\n    }\n}\n```\n然后在`app/Admin/bootstrap.php`注册扩展类：\n```php\nuse Encore\\Admin\\Grid\\Column;\nuse App\\Admin\\Extensions\\Popover;\n\nColumn::extend('popover', Popover::class);\n```\n然后就能在`model-grid`中使用了：\n```php\n$grid->desciption()->popover('right');\n```\n\n\n## 帮助方法\n### 字符串操作\n如果当前里的输出数据为字符串，那么可以通过链式方法调用`Illuminate\\Support\\Str`的方法。\n\n比如有如下一列，显示`title`字段的字符串值:\n\n```php\n$grid->title();\n```\n\n在`title`列输出的字符串基础上调用`Str::limit()`方法\n```php\n$grid->title()->limit(30);\n```\n调用方法之后输出的还是字符串，所以可以继续调用`Illuminate\\Support\\Str`的方法：\n```php\n$grid->title()->limit(30)->ucfirst();\n\n$grid->title()->limit(30)->ucfirst()->substr(1, 10);\n\n```\n\n### 数组操作\n如果当前列输出的是数组，可以直接链式调用`Illuminate\\Support\\Collection`方法。\n\n比如`tags`列是从一对多关系取出来的数组数据：\n```php\n$grid->tags();\n\narray (\n  0 => \n  array (\n    'id' => '16',\n    'name' => 'php',\n    'created_at' => '2016-11-13 14:03:03',\n    'updated_at' => '2016-12-25 04:29:35',\n    \n  ),\n  1 => \n  array (\n    'id' => '17',\n    'name' => 'python',\n    'created_at' => '2016-11-13 14:03:09',\n    'updated_at' => '2016-12-25 04:30:27',\n  ),\n)\n\n```\n\n调用`Collection::pluck()`方法取出数组的中的`name`列\n```php\n$grid->tags()->pluck('name');\n\narray (\n    0 => 'php',\n    1 => 'python',\n  ),\n\n```\n取出`name`列之后输出的还是数组，还能继续调用用`Illuminate\\Support\\Collection`的方法\n\n```php\n$grid->tags()->pluck('name')->map('ucwords');\n\narray (\n    0 => 'Php',\n    1 => 'Python',\n  ),\n```\n将数组输出为字符串\n```php\n$grid->tags()->pluck('name')->map('ucwords')->implode('-');\n\n\"Php-Python\"\n```\n\n### 混合使用\n\n在上面两种类型的方法调用中，只要上一步输出的是确定类型的值，便可以调用类型对应的方法，所以可以很灵活的混合使用。\n\n比如`images`字段是存储多图片地址数组的JSON格式字符串类型：\n```php\n\n$grid->images();\n\n\"['foo.jpg', 'bar.png']\"\n\n// 链式方法调用来显示多图\n$grid->images()->display(function ($images) {\n\n    return json_decode($images, true);\n    \n})->map(function ($path) {\n\n    return 'http://localhost/images/'. $path;\n    \n})->image();\n\n```\n\n\n\n\n"
  },
  {
    "path": "docs/zh/model-grid-custom-tools.md",
    "content": "# 自定义工具\n\n在`model-grid`的头部默认有`批量删除`和`刷新`两个操作工具，如果有更多的操作需求，`model-grid`提供了自定义工具的功能,下面的示例添加一个性别分类选择的按钮组工具。\n\n先定义工具类`app/Admin/Extensions/Tools/UserGender.php`：\n\n```php\n<?php\n\nnamespace App\\Admin\\Extensions\\Tools;\n\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Grid\\Tools\\AbstractTool;\nuse Illuminate\\Support\\Facades\\Request;\n\nclass UserGender extends AbstractTool\n{\n    protected function script()\n    {\n        $url = Request::fullUrlWithQuery(['gender' => '_gender_']);\n\n        return <<<EOT\n    \n$('input:radio.user-gender').change(function () {\n\n    var url = \"$url\".replace('_gender_', $(this).val());\n\n    $.pjax({container:'#pjax-container', url: url });\n\n});\n\nEOT;\n    }\n\n    public function render()\n    {\n        Admin::script($this->script());\n\n        $options = [\n            'all'   => 'All',\n            'm'     => 'Male',\n            'f'     => 'Female',\n        ];\n\n        return view('admin.tools.gender', compact('options'));\n    }\n}\n\n```\n视图`admin.tools.gender`文件为`resources/views/admin/tools/gender.blade.php`:\n```php\n<div class=\"btn-group\" data-toggle=\"buttons\">\n    @foreach($options as $option => $label)\n    <label class=\"btn btn-default btn-sm {{ \\Request::get('gender', 'all') == $option ? 'active' : '' }}\">\n        <input type=\"radio\" class=\"user-gender\" value=\"{{ $option }}\">{{$label}}\n    </label>\n    @endforeach\n</div>\n```\n\n在`model-grid`引入这个工具：\n```php\n\n$grid->tools(function ($tools) {\n    $tools->append(new UserGender());\n});\n\n```\n\n在`model-grid`定义中接收到`gender`参数后，做好数据查询就可以了：\n```php\nif (in_array(Request::get('gender'), ['m', 'f'])) {\n    $grid->model()->where('gender', Request::get('gender'));\n}\n```\n\n可以参考上面的方式来添加自己的工具。\n\n## 批量操作\n\n目前默认实现了批量删除操作的功能，如果要关掉批量删除操作：\n```php\n$grid->tools(function ($tools) {\n    $tools->batch(function ($batch) {\n        $batch->disableDelete();\n    });\n});\n\n```\n\n如果要添加自定义的批量操作，可以参考下面的例子。\n\n下面是扩展一个对文章批量发布的功能：\n\n先定义操作类`app/Admin/Extensions/Tools/ReleasePost.php`：\n```php\n<?php\n\nnamespace App\\Admin\\Extensions\\Tools;\n\nuse Encore\\Admin\\Grid\\Tools\\BatchAction;\n\nclass ReleasePost extends BatchAction\n{\n    protected $action;\n\n    public function __construct($action = 1)\n    {\n        $this->action = $action;\n    }\n    \n    public function script()\n    {\n        return <<<EOT\n        \n$('{$this->getElementClass()}').on('click', function() {\n\n    $.ajax({\n        method: 'post',\n        url: '{$this->resource}/release',\n        data: {\n            _token:LA.token,\n            ids: selectedRows(),\n            action: {$this->action}\n        },\n        success: function () {\n            $.pjax.reload('#pjax-container');\n            toastr.success('操作成功');\n        }\n    });\n});\n\nEOT;\n\n    }\n}\n```\n看代码的实现，通过click操作发送一个post请求，把选中的行数据`id`通过数组的形式传给后端接口，后端接口拿到`id`列表和要修改的状态来更新数据，然后前端刷新页面(pjax reload)，并弹出`toastr`提示操作成功。\n\n在`model-grid`中加入这个批量操作功能：\n```php\n$grid->tools(function ($tools) {\n    $tools->batch(function ($batch) {\n        $batch->add('发布文章', new ReleasePost(1));\n        $batch->add('文章下线', new ReleasePost(0));\n    });\n});\n```\n\n这样批量操作下拉按钮下面就会添加两个操作项，最后一步就是添加一个接口来处理批量操作的请求了，接口代码如下：\n```php\n\nclass PostController extends Controller\n{\n    ...\n    \n    public function release(Request $request)\n    {\n        foreach (Post::find($request->get('ids')) as $post) {\n            $post->released = $request->get('action');\n            $post->save();\n        }\n    }\n    \n    ...\n}\n```\n\n然后添加路由指向上面的接口：\n```php\n$router->post('posts/release', 'PostController@release');\n```\n\n这样整个流程就完成了。"
  },
  {
    "path": "docs/zh/model-grid-data.md",
    "content": "# 表格数据源\n\n## 数据来自模型\n\n如果使用模型来获取数据，那么修改来源数据就非常简单：\n```php\n// 添加默认查询条件\n$grid->model()->where('id', '>', 100);\n\n// 设置初始排序条件\n$grid->model()->orderBy('id', 'desc');\n\n...\n\n```\n\n其它查询方法可以参考`eloquent`的查询方法.\n\n## 数据来自外部API\n\n如果数据是来自外部的API，需要展示在数据表格中那么可以建立model,然后覆盖掉模型的几个获取数据的方法来实现, 下面的例子用`豆瓣电影`的API获取并展示数据：\n\n```php\n<?php\n\nnamespace App\\Models\\Movie;\n\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Pagination\\LengthAwarePaginator;\nuse Illuminate\\Support\\Facades\\Request;\n\nclass InTheater extends Model\n{\n    public function paginate()\n    {\n        $perPage = Request::get('per_page', 10);\n\n        $page = Request::get('page', 1);\n\n        $start = ($page-1)*$perPage;\n\n        $data = file_get_contents(\"https://api.douban.com/v2/movie/in_theaters?city=上海&start=$start&count=$perPage\");\n\n        $data = json_decode($data, true);\n\n        extract($data);\n\n        $movies = static::hydrate($subjects);\n\n        $paginator = new LengthAwarePaginator($movies, $total, $perPage);\n\n        $paginator->setPath(url()->current());\n\n        return $paginator;\n    }\n\n    public static function with($relations)\n    {\n        return new static;\n    }\n}\n```\n通过覆盖模型的`paginate`和`with`方法获取API数据, 通过`findOrFail`方法来获取单项数据展示在表单中\n\n同理如果要在form表单中获取或者保存数据那么也可以通过覆盖相应的方法来实现：\n```php\n// 获取单项数据展示在form中\npublic function findOrFail($id)\n{\n    $data = file_get_contents(\"http://api.douban.com/v2/movie/subject/$id\");\n\n    $data = json_decode($data, true);\n\n    return static::newFromBuilder($data);\n}\n\n// 保存提交的form数据\npublic function save(array $options = [])\n{\n    $attributes = $this->getAttributes();\n    \n    // save $attributes\n}\n```\n\n## 数据来自复杂SQL查询\n\n如果来源数据需要执行比较复杂的SQL语句获取，那么有两个办法, 第一个办法就是上面的方法，覆盖掉model的方法实现\n```php\n\npublic function paginate()\n{\n    $perPage = Request::get('per_page', 10);\n\n    $page = Request::get('page', 1);\n\n    $start = ($page-1)*$perPage;\n\n    // 运行sql获取数据数组\n    $sql = 'select * from ...';\n    \n    $result = DB::select($sql);\n    \n    $movies = static::hydrate($result);\n\n    $paginator = new LengthAwarePaginator($movies, $total, $perPage);\n\n    $paginator->setPath(url()->current());\n\n    return $paginator;\n}\n\npublic static function with($relations)\n{\n    return new static;\n}\n\n\n```\n\n第二个方式是在数据库中建立视图和model绑定（未测试过，理论上可行）\n"
  },
  {
    "path": "docs/zh/model-grid-export.md",
    "content": "数据导出\n=======\n\n`model-grid`内置的导出功能只是实现了简单的csv格式文件的导出，如果遇到文件编码问题或者满足不了自己需求的情况，可以按照下面的步骤来自定义导出功能\n\n本示例用[Laravel-Excel](https://github.com/Maatwebsite/Laravel-Excel)作为excel操作库，当然也可以使用任何其他excel库\n\n首先安装好它：\n\n```shell\ncomposer require maatwebsite/excel:~2.1.0\n\nphp artisan vendor:publish --provider=\"Maatwebsite\\Excel\\ExcelServiceProvider\"\n```\n\n然后新建自定义导出类，比如`app/Admin/Extensions/ExcelExpoter.php`:\n```php\n<?php\n\nnamespace App\\Admin\\Extensions;\n\nuse Encore\\Admin\\Grid\\Exporters\\AbstractExporter;\nuse Maatwebsite\\Excel\\Facades\\Excel;\nuse Illuminate\\Support\\Arr;\n\nclass ExcelExpoter extends AbstractExporter\n{\n    public function export()\n    {\n        Excel::create('Filename', function($excel) {\n\n            $excel->sheet('Sheetname', function($sheet) {\n\n                // 这段逻辑是从表格数据中取出需要导出的字段\n                $rows = collect($this->getData())->map(function ($item) {\n                    return Arr::only($item, ['id', 'title', 'content', 'rate', 'keywords']);\n                });\n\n                $sheet->rows($rows);\n\n            });\n\n        })->export('xls');\n    }\n}\n```\n\n然后在`model-grid`中使用这个导出类：\n```php\n\nuse App\\Admin\\Extensions\\ExcelExpoter;\n\n$grid->exporter(new ExcelExpoter());\n\n```\n\n有关更多`Laravel-Excel`的使用方法，参考[laravel-excel/docs](http://www.maatwebsite.nl/laravel-excel/docs)"
  },
  {
    "path": "docs/zh/model-grid-exporter.md",
    "content": "# 自定义导出\n\nlaravel-admin的数据表格默认支持导出csv文件，\n\n```php\n<?php\n\nnamespace App\\Admin\\Extensions;\n\nuse Encore\\Admin\\Grid\\Exporters\\AbstractExporter;\n\nclass CustomExporter extends AbstractExporter\n{\n    public function export()\n    {\n        $filename = $this->getTable().'.csv';\n\n        $data = $this->getData();\n\n        $output = '';\n\n        $headers = [\n            'Content-Encoding'    => 'UTF-8',\n            'Content-Type'        => 'text/csv;charset=UTF-8',\n            'Content-Disposition' => \"attachment; filename=\\\"$filename\\\"\",\n        ];\n\n        response(rtrim($output, \"\\n\"), 200, $headers)->send();\n\n        exit;\n    }\n}\n```"
  },
  {
    "path": "docs/zh/model-grid-filters.md",
    "content": "# 数据查询过滤\n\n`model-grid`提供了一系列的方法实现表格数据的查询过滤：\n\n```php\n$grid->filter(function($filter){\n\n    // 去掉默认的id过滤器\n    $filter->disableIdFilter();\n    \n    // 自定义id过滤器，在去掉默认id过滤器后必须调用 setId 方法，\n    // 并设置一个和主键不同的值，自定义的id过滤器才会显示。\n    $filter->equal('id', '产品序列号')->setId('product_id');\n\n    // 在这里添加字段过滤器\n    $filter->like('name', 'name');\n    ...\n\n});\n\n```\n## 查询类型\n\n目前支持的过滤类型有下面这些:\n\n### equal\n`sql: ... WHERE `column` = \"$input\"`：\n```php\n$filter->equal('column', $label);\n```\n\n### not equal\n`sql: ... WHERE `column` != \"$input\"`：\n```php\n$filter->notEqual('column', $label);\n```\n\n### like\n`sql: ... WHERE `column` LIKE \"%$input%\"`：\n```php\n$filter->like('column', $label);\n```\n\n### ilike\n`sql: ... WHERE `column` ILIKE \"%$input%\"`：\n```php\n$filter->ilike('column', $label);\n```\n\n### 大于\n`sql: ... WHERE `column` > \"$input\"`：\n```php\n$filter->gt('column', $label);\n```\n\n### 小于\n`sql: ... WHERE `column` < \"$input\"`：\n```php\n$filter->lt('column', $label);\n```\n\n### between\n`sql: ... WHERE `column` BETWEEN \"$start\" AND \"$end\"`：\n```php\n$filter->between('column', $label);\n\n// 设置datetime类型\n$filter->between('column', $label)->datetime();\n\n// 设置time类型\n$filter->between('column', $label)->time();\n```\n\n### in\n`sql: ... WHERE `column` in (...$inputs)`：\n```php\n$filter->in('column', $label)->multipleSelect(['key' => 'value']);\n```\n\n### notIn\n`sql: ... WHERE `column` not in (...$inputs)`：\n```php\n$filter->notIn('column', $label)->multipleSelect(['key' => 'value']);\n```\n\n### date\n`sql: ... WHERE DATE(`column`) = \"$input\"`：\n```php\n$filter->date('column', $label);\n```\n\n### day\n`sql: ... WHERE DAY(`column`) = \"$input\"`：\n```php\n$filter->day('column', $label);\n```\n\n### month\n`sql: ... WHERE MONTH(`column`) = \"$input\"`：\n```php\n$filter->month('column', $label);\n```\n\n### year\n`sql: ... WHERE YEAR(`column`) = \"$input\"`：\n```php\n$filter->year('column', $label);\n```\n\n### where\n\n可以用where来构建比较复杂的查询过滤\n\n`sql: ... WHERE `title` LIKE \"%$input\" OR `content` LIKE \"%$input\"`：\n```php\n$filter->where(function ($query) {\n\n    $query->where('title', 'like', \"%{$this->input}%\")\n        ->orWhere('content', 'like', \"%{$this->input}%\");\n\n}, 'Text');\n```\n\n`sql: ... WHERE `rate` >= 6 AND `created_at` = {$input}`:\n```php\n$filter->where(function ($query) {\n\n    $query->whereRaw(\"`rate` >= 6 AND `created_at` = {$this->input}\");\n\n}, 'Text');\n```\n\n关系查询，查询对应关系`profile`的字段：\n```php\n$filter->where(function ($query) {\n\n    $query->whereHas('profile', function ($query) {\n        $query->where('address', 'like', \"%{$this->input}%\")->orWhere('email', 'like', \"%{$this->input}%\");\n    });\n\n}, '地址或手机号');\n```\n\n## 表单类型\n\n### text\n\n表单类型默认是text input，可以设置placeholder：\n\n```php\n$filter->equal('column')->placeholder('请输入。。。');\n```\n\n也可以通过下面的一些方法来限制用户输入格式：\n\n```php\n$filter->equal('column')->url();\n\n$filter->equal('column')->email();\n\n$filter->equal('column')->integer();\n\n$filter->equal('column')->ip();\n\n$filter->equal('column')->mac();\n\n$filter->equal('column')->mobile();\n\n// $options 参考 https://github.com/RobinHerbots/Inputmask/blob/4.x/README_numeric.md\n$filter->equal('column')->decimal($options = []);\n\n// $options 参考 https://github.com/RobinHerbots/Inputmask/blob/4.x/README_numeric.md\n$filter->equal('column')->currency($options = []);\n\n// $options 参考 https://github.com/RobinHerbots/Inputmask/blob/4.x/README_numeric.md\n$filter->equal('column')->percentage($options = []);\n\n// $options 参考 https://github.com/RobinHerbots/Inputmask, $icon为input前面的图标\n$filter->equal('column')->inputmask($options = [], $icon = 'pencil');\n```\n\n### select\n```php\n$filter->equal('column')->select(['key' => 'value'...]);\n\n// 或者从api获取数据，api的格式参考model-form的select组件\n$filter->equal('column')->select('api/users');\n```\n\n### multipleSelect\n一般用来配合`in`和`notIn`两个需要查询数组的查询类型使用，也可以在`where`类型的查询中使用：\n```php\n$filter->in('column')->multipleSelect(['key' => 'value'...]);\n\n// 或者从api获取数据，api的格式参考model-form的multipleSelect组件\n$filter->in('column')->multipleSelect('api/users');\n```\n\n### radio\n比较常见的场景是选择分类\n\n```php\n$filter->equal('released')->radio([\n    ''   => 'All',\n    0    => 'Unreleased',\n    1    => 'Released',\n]);\n```\n\n### checkbox\n比较常见的场景是配合`whereIn`来做范围筛选\n\n```php\n$filter->in('gender')->checkbox([\n    'm'    => 'Male',\n    'f'    => 'Female',\n]);\n```\n\n### datetime\n\n通过日期时间组件来查询，`$options`的参数和值参考[bootstrap-datetimepicker](http://eonasdan.github.io/bootstrap-datetimepicker/Options/)\n\n```php\n$filter->equal('column')->datetime($options);\n\n// `date()` 相当于 `datetime(['format' => 'YYYY-MM-DD'])`\n$filter->equal('column')->date();\n\n// `time()` 相当于 `datetime(['format' => 'HH:mm:ss'])`\n$filter->equal('column')->time();\n\n// `day()` 相当于 `datetime(['format' => 'DD'])`\n$filter->equal('column')->day();\n\n// `month()` 相当于 `datetime(['format' => 'MM'])`\n$filter->equal('column')->month();\n\n// `year()` 相当于 `datetime(['format' => 'YYYY'])`\n$filter->equal('column')->year();\n\n```\n"
  },
  {
    "path": "docs/zh/model-grid.md",
    "content": "# 基于数据模型的表格\n\n`Encore\\Admin\\Grid`类用于生成基于数据模型的表格，先来个例子，数据库中有`movies`表\n\n```sql\nCREATE TABLE `movies` (\n  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n  `title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n  `director` int(10) unsigned NOT NULL,\n  `describe` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n  `rate` tinyint unsigned NOT NULL,\n  `released` enum(0, 1),\n  `release_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;\n\n```\n\n对应的数据模型为`App\\Models\\Movie`，下面的代码可以生成表`movies`的数据表格：\n\n```php\n\nuse App\\Models\\Movie;\nuse Encore\\Admin\\Grid;\nuse Encore\\Admin\\Facades\\Admin;\n\n$grid = Admin::grid(Movie::class, function(Grid $grid){\n\n    // 第一列显示id字段，并将这一列设置为可排序列\n    $grid->id('ID')->sortable();\n\n    // 第二列显示title字段，由于title字段名和Grid对象的title方法冲突，所以用Grid的column()方法代替\n    $grid->column('title');\n    \n    // 第三列显示director字段，通过display($callback)方法设置这一列的显示内容为users表中对应的用户名\n    $grid->director()->display(function($userId) {\n        return User::find($userId)->name;\n    });\n    \n    // 第四列显示为describe字段\n    $grid->describe();\n    \n    // 第五列显示为rate字段\n    $grid->rate();\n\n    // 第六列显示released字段，通过display($callback)方法来格式化显示输出\n    $grid->released('上映?')->display(function ($released) {\n        return $released ? '是' : '否';\n    });\n\n    // 下面为三个时间字段的列显示\n    $grid->release_at();\n    $grid->created_at();\n    $grid->updated_at();\n\n    // filter($callback)方法用来设置表格的简单搜索框\n    $grid->filter(function ($filter) {\n    \n        // 设置created_at字段的范围查询\n        $filter->between('created_at', 'Created Time')->datetime();\n    });\n});\n\n```\n\n## 基本使用方法\n\n#### 添加列\n```php\n\n// 直接通过字段名`username`添加列\n$grid->username('用户名');\n\n// 效果和上面一样\n$grid->column('username', '用户名');\n\n// 添加多列\n$grid->columns('email', 'username' ...);\n```\n\n#### 修改来源数据\n```php\n$grid->model()->where('id', '>', 100);\n\n$grid->model()->orderBy('id', 'desc');\n\n$grid->model()->take(100);\n\n...\n\n```\n\n其它查询方法可以参考`eloquent`的查询方法.\n\n#### 设置每页显示行数\n\n```php\n// 默认为每页20条\n$grid->paginate(15);\n```\n\n#### 修改显示输出\n\n\n```php\nuse Illuminate\\Support\\Str;\n$grid->text()->display(function($text) {\n    return Str::limit($text, 30, '...');\n});\n\n$grid->name()->display(function ($name) {\n    return \"<span class='label'>$name</span>\";\n});\n\n$grid->email()->display(function ($email) {\n    return \"mailto:$email\";\n});\n\n// 添加不存在的字段\n$grid->column('column_not_in_table')->display(function () {\n    return 'blablabla....';\n});\n```\n\n`display()`方法接收的匿名函数绑定了当前行的数据对象，可以在里面调用当前行的其它字段数据\n\n```php\n$grid->first_name();\n$grid->last_name();\n\n// 不存的字段列\n$grid->column('full_name')->display(function () {\n    return $this->first_name.' '.$this->last_name;\n});\n```\n\n#### 禁用创建按钮\n```php\n$grid->disableCreateButton();\n```\n\n#### 禁用分页条\n```php\n$grid->disablePagination();\n```\n\n#### 禁用查询过滤器\n```php\n$grid->disableFilter();\n```\n\n#### 禁用导出数据按钮\n```php\n$grid->disableExport();\n```\n\n#### 禁用行选择checkbox\n```php\n$grid->disableRowSelector();\n```\n\n#### 禁用行操作列\n```php\n$grid->disableActions();\n```\n\n#### 设置分页选择器选项\n```php\n$grid->perPages([10, 20, 30, 40, 50]);\n```\n\n## 关联模型\n\n\n### 一对一\n`users`表和`profiles`表通过`profiles.user_id`字段生成一对一关联\n\n```sql\n\nCREATE TABLE `users` (\n`id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n`email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\nPRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;\n\nCREATE TABLE `profiles` (\n`id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n`user_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n`age` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n`gender` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\nPRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;\n```\n\n对应的数据模分别为:\n\n```php\n\nclass User extends Model\n{\n    public function profile()\n    {\n        return $this->hasOne(Profile::class);\n    }\n}\n\nclass Profile extends Model\n{\n    public function user()\n    {\n        return $this->belongsTo(User::class);\n    }\n}\n\n```\n\n通过下面的代码可以关联在一个grid里面:\n\n```php\nAdmin::grid(User::class, function (Grid $grid) {\n\n    $grid->id('ID')->sortable();\n\n    $grid->name();\n    $grid->email();\n    \n    $grid->column('profile.age');\n    $grid->column('profile.gender');\n\n    //or\n    $grid->profile()->age();\n    $grid->profile()->gender();\n\n    $grid->created_at();\n    $grid->updated_at();\n});\n\n```\n\n### 一对多\n\n`posts`表和`comments`表通过`comments.post_id`字段生成一对多关联\n\n```sql\n\nCREATE TABLE `posts` (\n`id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n`title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n`content` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\nPRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;\n\nCREATE TABLE `comments` (\n`id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n`post_id` int(10) unsigned NOT NULL,\n`content` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n`created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n`updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\nPRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;\n```\n\n对应的数据模分别为:\n\n```php\n\nclass Post extends Model\n{\n    public function comments()\n    {\n        return $this->hasMany(Comment::class);\n    }\n}\n\nclass Comment extends Model\n{\n    public function post()\n    {\n        return $this->belongsTo(Post::class);\n    }\n}\n\n```\n\n通过下面的代码可以让两个模型在grid里面互相关联:\n\n```php\n\nreturn Admin::grid(Post::class, function (Grid $grid) {\n    $grid->id('id')->sortable();\n    $grid->title();\n    $grid->content();\n\n    $grid->comments('评论数')->display(function ($comments) {\n        $count = count($comments);\n        return \"<span class='label label-warning'>{$count}</span>\";\n    });\n\n    $grid->created_at();\n    $grid->updated_at();\n});\n\n\nreturn Admin::grid(Comment::class, function (Grid $grid) {\n    $grid->id('id');\n    $grid->post()->title();\n    $grid->content();\n\n    $grid->created_at()->sortable();\n    $grid->updated_at();\n});\n\n```\n\n### 多对多\n\n`users`和`roles`表通过中间表`role_users`产生多对多关系\n\n```sql\n\nCREATE TABLE `users` (\n  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n  `username` varchar(190) COLLATE utf8_unicode_ci NOT NULL,\n  `password` varchar(60) COLLATE utf8_unicode_ci NOT NULL,\n  `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n  `created_at` timestamp NULL DEFAULT NULL,\n  `updated_at` timestamp NULL DEFAULT NULL,\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `users_username_unique` (`username`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci\n\nCREATE TABLE `roles` (\n  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n  `name` varchar(50) COLLATE utf8_unicode_ci NOT NULL,\n  `slug` varchar(50) COLLATE utf8_unicode_ci NOT NULL,\n  `created_at` timestamp NULL DEFAULT NULL,\n  `updated_at` timestamp NULL DEFAULT NULL,\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `roles_name_unique` (`name`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci\n\nCREATE TABLE `role_users` (\n  `role_id` int(11) NOT NULL,\n  `user_id` int(11) NOT NULL,\n  `created_at` timestamp NULL DEFAULT NULL,\n  `updated_at` timestamp NULL DEFAULT NULL,\n  KEY `role_users_role_id_user_id_index` (`role_id`,`user_id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci\n```\n\n对应的数据模分别为:\n\n```php\n\nclass User extends Model\n{\n    public function roles()\n    {\n        return $this->belongsToMany(Role::class);\n    }\n}\n\nclass Role extends Model\n{\n    public function users()\n    {\n        return $this->belongsToMany(User::class);\n    }\n}\n\n```\n\n通过下面的代码可以让两个模型在grid里面互相关联:\n\n\n```php\nreturn Admin::grid(User::class, function (Grid $grid) {\n    $grid->id('ID')->sortable();\n    $grid->username();\n    $grid->name();\n\n    $grid->roles()->display(function ($roles) {\n\n        $roles = array_map(function ($role) {\n            return \"<span class='label label-success'>{$role['name']}</span>\";\n        }, $roles);\n\n        return join('&nbsp;', $roles);\n    });\n\n    $grid->created_at();\n    $grid->updated_at();\n});\n\n```\n"
  },
  {
    "path": "docs/zh/model-tree.md",
    "content": "# 模型树\n\n可以通过`model-tree`来实现一个树状组件，可以用拖拽的方式实现数据的层级、排序等操作，下面是基本的用法.\n\n## 表结构和模型\n要使用`model-tree`，要遵守约定的表结构：\n```sql\nCREATE TABLE `demo_categories` (\n  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n  `parent_id` int(11) NOT NULL DEFAULT '0',\n  `order` int(11) NOT NULL DEFAULT '0',\n  `title` varchar(50) COLLATE utf8_unicode_ci NOT NULL,\n  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,\n  `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n  PRIMARY KEY (`id`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci\n```\n上面的表格结构里面有三个必要的字段`parent_id`、`order`、`title`,其它字段没有要求。\n\n对应的模型为`app/Models/Category.php`:\n```php\n<?php\n\nnamespace App\\Models\\Demo;\n\nuse Encore\\Admin\\Traits\\ModelTree;\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass Category extends Model\n{\n    use ModelTree;\n\n    protected $table = 'demo_categories';\n}\n```\n表结构中的三个字段`parent_id`、`order`、`title`的字段名也是可以修改的：\n```php\n<?php\n\nnamespace App\\Models\\Demo;\n\nuse Encore\\Admin\\Traits\\ModelTree;\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass Category extends Model\n{\n    use ModelTree;\n\n    protected $table = 'demo_categories';\n\n    public function __construct(array $attributes = [])\n    {\n        parent::__construct($attributes);\n        \n        $this->setParentColumn('pid');\n        $this->setOrderColumn('sort');\n        $this->setTitleColumn('name');\n    }\n}\n```\n## 使用方法\n然后就是在页面中使用`model-tree`了：\n```php\n<?php\n\nnamespace App\\Admin\\Controllers\\Demo;\n\nuse App\\Http\\Controllers\\Controller;\nuse App\\Models\\Category;\nuse Encore\\Admin\\Form;\nuse Encore\\Admin\\Facades\\Admin;\nuse Encore\\Admin\\Layout\\Content;\nuse Encore\\Admin\\Controllers\\ModelForm;\nuse Encore\\Admin\\Tree;\n\nclass CategoryController extends Controller\n{\n    use ModelForm;\n    \n    public function index()\n    {\n        return Admin::content(function (Content $content) {\n            $content->header('树状模型');\n            $content->body(Category::tree());\n        });\n    }\n}\n```\n可以通过下面的方式来修改行数据的显示：\n```php\nCategory::tree(function ($tree) {\n    $tree->branch(function ($branch) {\n        $src = config('admin.upload.host') . '/' . $branch['logo'] ;\n        $logo = \"<img src='$src' style='max-width:30px;max-height:30px' class='img'/>\";\n\n        return \"{$branch['id']} - {$branch['title']} $logo\";\n    });\n})\n```\n在回调函数中返回的字符串类型数据，就是在树状组件中的每一行的显示内容，`$branch`参数是当前行的数据数组。\n\n如果要修改模型的查询，用下面的方式\n```php\n\nCategory::tree(function ($tree) {\n\n    $tree->query(function ($model) {\n        return $model->where('type', 1);\n    });\n    \n})\n```\n\n```\n\n\n"
  },
  {
    "path": "docs/zh/permission.md",
    "content": "# 权限控制\n\n`laravel-admin`已经内置了`RBAC`权限控制模块，展开左侧边栏的`Auth`，下面有用户、角色、权限三项的管理面板，权限控制的使用如下：\n\n## 路由控制\n\n在`laravel-admin 1.5`中，权限和路由是绑定在一起的，在编辑权限页面里面设置当前权限能访问的路由，在`HTTP方法`select框中选择访问路由的方法，在`HTTP路径`textarea中填写能访问的路径。\n\n比如要添加一个权限，该权限可以以`GET`方式访问路径`/admin/users`，那么`HTTP方法`选择`GET`，`HTTP路径`填写`/users`。\n\n如果要访问前缀是`/admin/users`的所有路径，那么`HTTP路径`填写`/users*`，如果权限包括多个访问路径，换行填写每条路径。\n\n## 页面控制\n\n如果你要在页面中控制用户的权限，可以参考下面的例子\n\n### 场景1\n\n比如现在有一个场景，对文章发布模块做权限管理，以创建文章为例\n\n首先创建一项权限，进入`http://localhost/admin/auth/permissions`，权限标识（slug）填写`create-post`，权限名称填写`创建文章`，这样权限就创建好了。\n第二步可以把这个权限直接附加给个人或者角色，在用户编辑页面可以直接把上面创建好的权限附加给当前编辑用户，也可以在编辑角色页面附加给某个角色。\n第三步，在创建文章控制器里面添加控制代码：\n```php\nuse Encore\\Admin\\Auth\\Permission;\n\nclass PostController extends Controller\n{\n    public function create()\n    {\n        // 检查权限，有create-post权限的用户或者角色可以访问创建文章页面\n        Permission::check('create-post');\n    }\n}\n```\n这样就完成了一个页面的权限控制。\n\n### 场景2\n\n如果你要在表格中控制用户对元素的显示，那么需要先定义两个权限，比如权限标示`delete-image`、和`view-title-column`分别用来控制有删除图片的权限和显示某一列的权限，把这两个权限赋给你设置的角色，然后在grid中加入代码：\n```php\n$grid->actions(function ($actions) {\n\n    // 没有`delete-image`权限的角色不显示删除按钮\n    if (!Admin::user()->can('delete-image')) {\n        $actions->disableDelete();\n    }\n});\n\n// 只有具有`view-title-column`权限的用户才能显示`title`这一列\nif (Admin::user()->can('view-title-column')) {\n    $grid->column('title');\n}\n```\n\n## 相关方法\n\n获取当前用户对象\n```php\nAdmin::user();\n```\n\n获取当前用户id\n```php\nAdmin::user()->id;\n```\n\n获取用户角色\n```php\nAdmin::user()->roles;\n```\n\n获取用户的权限\n```php\nAdmin::user()->permissions;\n```\n\n用户是否某个角色\n```php\nAdmin::user()->isRole('developer');\n```\n\n是否有某个权限\n```php\nAdmin::user()->can('create-post');\n```\n\n是否没有某个权限\n```php\nAdmin::user()->cannot('delete-post');\n```\n\n是否是超级管理员\n```php\nAdmin::user()->isAdministrator();\n```\n\n是否是其中的角色\n```php\nAdmin::user()->inRoles(['editor', 'developer']);\n```\n\n## 权限中间件\n\n可以在路由配置上结合权限中间件来控制路由的权限\n\n```php\n\n// 允许administrator、editor两个角色访问group里面的路由\nRoute::group([\n    'middleware' => 'admin.permission:allow,administrator,editor',\n], function ($router) {\n\n    $router->resource('users', UserController::class);\n    ...\n    \n});\n\n// 禁止developer、operator两个角色访问group里面的路由\nRoute::group([\n    'middleware' => 'admin.permission:deny,developer,operator',\n], function ($router) {\n\n    $router->resource('users', UserController::class);\n    ...\n    \n});\n\n// 有edit-post、create-post、delete-post三个权限的用户可以访问group里面的路由\nRoute::group([\n    'middleware' => 'admin.permission:check,edit-post,create-post,delete-post',\n], function ($router) {\n\n    $router->resource('posts', PostController::class);\n    ...\n    \n});\n```\n\n权限中间件和其它中间件使用方法一致。\n\n"
  },
  {
    "path": "docs/zh/qa.md",
    "content": "# 常见问题汇总\n\n## 重写内置视图\n\n如果有需要自己修改view，但是不方便直接修改`laravel-admin`的情况，可以用下面的办法解决\n\n复制`vendor/encore/laravel-admin/views`到项目的`resources/views/admin`，然后在`app/Admin/bootstrap.php`文件中加入代码：\n\n```php\napp('view')->prependNamespace('admin', resource_path('views/admin'));\n```\n\n这样就用`resources/views/admin`下的视图覆盖了`laravel-admin`的视图，要注意的问题是，更新`laravel-admin`的时候，如果遇到视图方面的问题，需要重新复制`vendor/encore/laravel-admin/views`到项目的`resources/views/admin`中，注意备份原来已经修改过的视图。\n\n## 设置语言\n\n完成安装之后，默认语言为英文(en)，如果要使用中文，打开`config/app.php`，将`locale`设置为`zh-CN`即可。\n\n## 关于扩展自定义组件\n\n`laravel-admin`默认引用了大量前端资源，如果有网络问题或者有不需要使用的组件，可以参考[form组件管理](/zh/model-form-field-management.md)将其移除。\n\n关于富文本编辑器，由于静态资源包文件普遍太大，所以`laravel-admin`默认通过cdn的方式引用`ckeditor`，建议大家根据自己的需求扩展编辑器，自行配置。\n\n## 关于前端资源问题\n\n如果需要使用自己的前端文件，可以在`app/Admin/bootstrap.php`中引入：\n\n```php\nAdmin::css('path/to/your/css');\nAdmin::css('path/to/your/js');\n```\n\n\n## 重写登陆页面和登陆逻辑\n\n在路由文件`app/Admin/routes.php`中，覆盖掉登陆页面和登陆逻辑的路由，即可实现自定义的功能\n\n```php\nRoute::group([\n    'prefix'        => config('admin.prefix'),\n    'namespace'     => Admin::controllerNamespace(),\n    'middleware'    => ['web', 'admin'],\n], function (Router $router) {\n\n    $router->get('auth/login', 'AuthController@getLogin');\n    $router->post('auth/login', 'AuthController@postLogin');\n    \n});\n\n```\n\n在自定义的路由器AuthController中的`getLogin`、`postLogin`方法里分别实现自己的登陆页面和登陆逻辑。\n\n参考控制器文件[AuthController.php](https://github.com/z-song/laravel-admin/blob/master/src/Controllers/AuthController.php)，视图文件[login.blade.php](https://github.com/z-song/laravel-admin/blob/master/views/login.blade.php)\n\n## 更新静态资源\n\n如果遇到更新之后,部分组件不能正常使用,那有可能是`laravel-admin`自带的静态资源有更新了,需要运行命令`php artisan vendor:publish --tag=laravel-admin-assets --force`来重新发布前端资源，发布之后不要忘记清理浏览器缓存."
  },
  {
    "path": "docs/zh/quick-start.md",
    "content": "# 快速开始\n\n## 数据表结构\n用`Laravel`自带的`users`表举例,表结构为：\n```sql\nCREATE TABLE `users` (\n  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,\n  `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n  `email` varchar(255) COLLATE utf8_unicode_ci NOT NULL,\n  `password` varchar(60) COLLATE utf8_unicode_ci NOT NULL,\n  `remember_token` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL,\n  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',\n  PRIMARY KEY (`id`),\n  UNIQUE KEY `users_email_unique` (`email`)\n) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci\n```\n对应的数据模型为文件 `App\\User.php`\n\n`laravel-admin`可以通过使用以下几步来快速生成`users`表的`CURD`操作页面：\n\n## 添加路由器\n\n使用下面的命令来创建一个对应`App\\User`模型的路由器\n```php\nphp artisan admin:make UserController --model=App\\\\User\n\n// 在windows系统中\nphp artisan admin:make UserController --model=App\\User\n```\n\n上面的命令会创建路由器文件`app/Admin/Controllers/UserController.php`.\n\n## 添加路由配置\n\n在`laravel-admin`的路由配置文件`app/Admin/routes.php`里添加一行：\n```\n$router->resource('users', UserController::class);\n```\n\n## 添加左侧菜单栏连接\n\n打开`http://localhost:8000/admin/auth/menu`，添加对应的menu, 然后就能在后台管理页面的左侧边栏看到用户管理页面的链接入口了。\n\n> 其中`uri`填写不包含路由前缀的的路径部分，比如完整路径是`http://localhost:8000/admin/demo/users`, 那么就填`demo/users`，如果要添加外部链接，只要填写完整的url即可，比如`http://laravel-admin.org/`.\n\n### 菜单翻译\n\n在您的语言文件的menu_titles索引中追加菜单标题。\n例如“工作单位”标题：\n\n在resources/lang/es/admin.php中\n```php\n...\n// 用_小写并用_替换空格\n'menu_titles' => [\n    'work_units' => 'Unidades de trabajo'\n],\n```\n\n## 创建表格表单\n\n剩下的工作就是构建数据表格和表单了，打开 `app/Admin/Contollers/UserController.php`,找到`form()`和`grid()`方法，然添加构建代码更多详细使用请查看[model-grid](/zh/model-grid.md)和[model-form](/zh/model-form.md)。\n"
  },
  {
    "path": "docs/zh/upgrade.md",
    "content": "# 升级注意事项\n\n因为laravel-admin 1.5的内置表结构有修改，所以建议大家重新安装laravel 5.5和laravel-admin 1.5，然后再将代码迁移过来\n\n代码迁移需要注意的事项：\n\n- 表结构有修改 请参考 [tables.php](https://github.com/z-song/laravel-admin/blob/master/database/migrations/2016_01_04_173148_create_admin_tables.php)\n- 路由文件结构有修改 请参考 [routes.stub](https://github.com/z-song/laravel-admin/blob/master/src/Console/stubs/routes.stub)\n- 配置文件结构有修改 请参考 [admin.php](https://github.com/z-song/laravel-admin/blob/master/config/admin.php)\n- 图表组件已经移除，不能再使用,参考 [自定义图表](/zh/custom-chart.md)"
  },
  {
    "path": "docs/zh/widgets.md",
    "content": "# 前端组件\n\n## Box组件\n\n`Encore\\Admin\\Widgets\\Box`用来生成box组件：\n\n```php\nuse Encore\\Admin\\Widgets\\Box;\n\n$box = new Box('Box标题', 'Box内容');\n\n$box->removable();\n\n$box->collapsable();\n\n$box->style('info');\n\n$box->solid();\n\necho $box;\n\n```\n\n`Box::__construct($title, $content)`,`$title`参数为Box组件的标题，`$content`参数为Box的内容元素，可以是实现了`Illuminate\\Contracts\\Support\\Renderable`接口的对象或者其他可打印变量。\n\n`Box::title($title)`方法用来设置Box组件标题。\n\n`Box::content($content)`方法用来设置Box组件的内容元素。\n\n`Box::removable()`方法将Box组件设置为可关闭。\n\n`Box::collapsable()`方法将Box组件设置为可展开和收起。\n\n`Box::style($style)`方法设置Box组件的样式，可填值为`primary`,`info`,`danger`,`warning`,`success`,`default`。\n\n`Box::solid()`方法为Box组件添加边框。\n\n## Collapse组件\n\n`Encore\\Admin\\Widgets\\Collapse`类用来生成折叠插件：\n```php\nuse Encore\\Admin\\Widgets\\Collapse;\n\n$collapse = new Collapse();\n\n$collapse->add('Bar', 'xxxxx');\n$collapse->add('Orders', new Table());\n\necho $collapse->render();\n\n```\n\n`Collapse::add($title, $content)`方法用来给折叠组件添加一个折叠项，`$title`参数设置该折叠项的标题，`$content`参数用来舍子折叠区的内用。\n\n\n## 表单\n\n`Encore\\Admin\\Widgets\\Form`类用来快速构建表单：\n\n```php\n\n$form = new Form();\n\n$form->action('example');\n\n$form->email('email')->default('qwe@aweq.com');\n$form->password('password');\n$form->text('name', '输入框');\n$form->url('url');\n$form->color('color');\n$form->map('lat', 'lng');\n$form->date('date');\n$form->json('val');\n$form->dateRange('created_at', 'updated_at');\n\necho $form->render();\n```\n`Form::__construct($data = [])`生成一个form对象，如果传入了`$data`参数，`$data`数组中的元素将会按照`key`对应填入`form`对应name的表单中。\n\n`Form::action($uri)`方法用来设置表单提交地址。\n\n`Form::method($method)`方法用来设置form表单的提交方法,默认为`POST`方法。\n\n`Form::disablePjax()` 不使用pjax方式提交表单。\n\n\n## Infobox组件\n\n`Encore\\Admin\\Widgets\\InfoBox`类用来生成信息展示块：\n\n```php\nuse Encore\\Admin\\Widgets\\InfoBox;\n\n$infoBox = new InfoBox('New Users', 'users', 'aqua', '/admin/users', '1024');\n\necho $infoBox->render();\n\n```\n\n效果请参考后台首页的布局文件[HomeController.php](https://github.com/z-song/laravel-admin/blob/master/src/Console/stubs/HomeController.stub)的`index()`方法中，关于`InfoBox`的部分。\n\n## Tab组件\n\n`Encore\\Admin\\Widgets\\Tab`类用来生成选项卡组件：\n\n```php\nuse Encore\\Admin\\Widgets\\Tab;\n\n$tab = new Tab();\n\n$tab->add('Pie', $pie);\n$tab->add('Table', new Table());\n$tab->add('Text', 'blablablabla....');\n\necho $tab->render();\n\n```\n\n`Tab::add($title, $content)`方法用来添加一个选项卡，`$title`为选项标题，`$content`选项卡内容。\n\n## Table\n\n`Encore\\Admin\\Widgets\\Table`类用来生成表格：\n\n```php\nuse Encore\\Admin\\Widgets\\Table;\n\n// table 1\n$headers = ['Id', 'Email', 'Name', 'Company'];\n$rows = [\n    [1, 'labore21@yahoo.com', 'Ms. Clotilde Gibson', 'Goodwin-Watsica'],\n    [2, 'omnis.in@hotmail.com', 'Allie Kuhic', 'Murphy, Koepp and Morar'],\n    [3, 'quia65@hotmail.com', 'Prof. Drew Heller', 'Kihn LLC'],\n    [4, 'xet@yahoo.com', 'William Koss', 'Becker-Raynor'],\n    [5, 'ipsa.aut@gmail.com', 'Ms. Antonietta Kozey Jr.'],\n];\n\n$table = new Table($headers, $rows);\n\necho $table->render();\n\n// table 2\n$headers = ['Keys', 'Values'];\n$rows = [\n    'name'   => 'Joe',\n    'age'    => 25,\n    'gender' => 'Male',\n    'birth'  => '1989-12-05',\n];\n\n$table = new Table($headers, $rows);\n\necho $table->render();\n\n```\n\n"
  },
  {
    "path": "phpunit.xml.dist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<phpunit backupGlobals=\"false\"\n         backupStaticAttributes=\"false\"\n         bootstrap=\"vendor/autoload.php\"\n         colors=\"true\"\n         convertErrorsToExceptions=\"true\"\n         convertNoticesToExceptions=\"true\"\n         convertWarningsToExceptions=\"true\"\n         processIsolation=\"false\"\n         stopOnFailure=\"true\"\n         verbose=\"true\"\n        >\n    <testsuites>\n        <testsuite name=\"all\">\n            <directory>tests/</directory>\n        </testsuite>\n    </testsuites>\n</phpunit>"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/bootstrap-slider/bootstrap-slider.js",
    "content": "/*! =========================================================\n * bootstrap-slider.js\n *\n * Maintainers: \n *\t\tKyle Kemp \n *\t\t\t- Twitter: @seiyria\n *\t\t\t- Github:  seiyria\n *\t\tRohit Kalkur\n *\t\t\t- Twitter: @Rovolutionary\n *\t\t\t- Github:  rovolution\n *\n * =========================================================\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ========================================================= */\n\n\n/**\n * Bridget makes jQuery widgets\n * v1.0.1\n * MIT license\n */\n( function( $ ) {\n\n\t( function( $ ) {\n\n\t\t'use strict';\n\n\t\t// -------------------------- utils -------------------------- //\n\n\t\tvar slice = Array.prototype.slice;\n\n\t\tfunction noop() {}\n\n\t\t// -------------------------- definition -------------------------- //\n\n\t\tfunction defineBridget( $ ) {\n\n\t\t\t// bail if no jQuery\n\t\t\tif ( !$ ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// -------------------------- addOptionMethod -------------------------- //\n\n\t\t\t/**\n\t\t\t * adds option method -> $().plugin('option', {...})\n\t\t\t * @param {Function} PluginClass - constructor class\n\t\t\t */\n\t\t\tfunction addOptionMethod( PluginClass ) {\n\t\t\t\t// don't overwrite original option method\n\t\t\t\tif ( PluginClass.prototype.option ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t  // option setter\n\t\t\t  PluginClass.prototype.option = function( opts ) {\n\t\t\t    // bail out if not an object\n\t\t\t    if ( !$.isPlainObject( opts ) ){\n\t\t\t      return;\n\t\t\t    }\n\t\t\t    this.options = $.extend( true, this.options, opts );\n\t\t\t  };\n\t\t\t}\n\n\n\t\t\t// -------------------------- plugin bridge -------------------------- //\n\n\t\t\t// helper function for logging errors\n\t\t\t// $.error breaks jQuery chaining\n\t\t\tvar logError = typeof console === 'undefined' ? noop :\n\t\t\t  function( message ) {\n\t\t\t    console.error( message );\n\t\t\t  };\n\n\t\t\t/**\n\t\t\t * jQuery plugin bridge, access methods like $elem.plugin('method')\n\t\t\t * @param {String} namespace - plugin name\n\t\t\t * @param {Function} PluginClass - constructor class\n\t\t\t */\n\t\t\tfunction bridge( namespace, PluginClass ) {\n\t\t\t  // add to jQuery fn namespace\n\t\t\t  $.fn[ namespace ] = function( options ) {\n\t\t\t    if ( typeof options === 'string' ) {\n\t\t\t      // call plugin method when first argument is a string\n\t\t\t      // get arguments for method\n\t\t\t      var args = slice.call( arguments, 1 );\n\n\t\t\t      for ( var i=0, len = this.length; i < len; i++ ) {\n\t\t\t        var elem = this[i];\n\t\t\t        var instance = $.data( elem, namespace );\n\t\t\t        if ( !instance ) {\n\t\t\t          logError( \"cannot call methods on \" + namespace + \" prior to initialization; \" +\n\t\t\t            \"attempted to call '\" + options + \"'\" );\n\t\t\t          continue;\n\t\t\t        }\n\t\t\t        if ( !$.isFunction( instance[options] ) || options.charAt(0) === '_' ) {\n\t\t\t          logError( \"no such method '\" + options + \"' for \" + namespace + \" instance\" );\n\t\t\t          continue;\n\t\t\t        }\n\n\t\t\t        // trigger method with arguments\n\t\t\t        var returnValue = instance[ options ].apply( instance, args);\n\n\t\t\t        // break look and return first value if provided\n\t\t\t        if ( returnValue !== undefined && returnValue !== instance) {\n\t\t\t          return returnValue;\n\t\t\t        }\n\t\t\t      }\n\t\t\t      // return this if no return value\n\t\t\t      return this;\n\t\t\t    } else {\n\t\t\t      var objects = this.map( function() {\n\t\t\t        var instance = $.data( this, namespace );\n\t\t\t        if ( instance ) {\n\t\t\t          // apply options & init\n\t\t\t          instance.option( options );\n\t\t\t          instance._init();\n\t\t\t        } else {\n\t\t\t          // initialize new instance\n\t\t\t          instance = new PluginClass( this, options );\n\t\t\t          $.data( this, namespace, instance );\n\t\t\t        }\n\t\t\t        return $(this);\n\t\t\t      });\n\n\t\t\t      if(!objects || objects.length > 1) {\n\t\t\t      \treturn objects;\n\t\t\t      } else {\n\t\t\t      \treturn objects[0];\n\t\t\t      }\n\t\t\t    }\n\t\t\t  };\n\n\t\t\t}\n\n\t\t\t// -------------------------- bridget -------------------------- //\n\n\t\t\t/**\n\t\t\t * converts a Prototypical class into a proper jQuery plugin\n\t\t\t *   the class must have a ._init method\n\t\t\t * @param {String} namespace - plugin name, used in $().pluginName\n\t\t\t * @param {Function} PluginClass - constructor class\n\t\t\t */\n\t\t\t$.bridget = function( namespace, PluginClass ) {\n\t\t\t  addOptionMethod( PluginClass );\n\t\t\t  bridge( namespace, PluginClass );\n\t\t\t};\n\n\t\t\treturn $.bridget;\n\n\t\t}\n\n\t  \t// get jquery from browser global\n\t  \tdefineBridget( $ );\n\n\t})( $ );\n\n\n\t/*************************************************\n\t\t\t\t\t\n\t\t\tBOOTSTRAP-SLIDER SOURCE CODE\n\n\t**************************************************/\n\n\t(function( $ ) {\n\n\t\tvar ErrorMsgs = {\n\t\t\tformatInvalidInputErrorMsg : function(input) {\n\t\t\t\treturn \"Invalid input value '\" + input + \"' passed in\";\n\t\t\t},\n\t\t\tcallingContextNotSliderInstance : \"Calling context element does not have instance of Slider bound to it. Check your code to make sure the JQuery object returned from the call to the slider() initializer is calling the method\"\n\t\t};\n\n\n\n\t\t/*************************************************\n\t\t\t\t\t\t\n\t\t\t\t\t\t\tCONSTRUCTOR\n\n\t\t**************************************************/\n\t\tvar Slider = function(element, options) {\n\t\t\tcreateNewSlider.call(this, element, options);\n\t\t\treturn this;\n\t\t};\n\n\t\tfunction createNewSlider(element, options) {\n\t\t\t/*************************************************\n\t\t\t\t\t\t\n\t\t\t\t\t\t\tCreate Markup\n\n\t\t\t**************************************************/\n\t\t\tif(typeof element === \"string\") {\n\t\t\t\tthis.element = document.querySelector(element);\n\t\t\t} else if(element instanceof HTMLElement) {\n\t\t\t\tthis.element = element;\n\t\t\t}\n\t\t\t\n\t\t\tvar origWidth = this.element.style.width;\n\t\t\tvar updateSlider = false;\n\t\t\tvar parent = this.element.parentNode;\n\t\t\tvar sliderTrackSelection;\n\t\t\tvar sliderMinHandle;\n\t\t\tvar sliderMaxHandle;\n\n\t\t\tif (this.sliderElem) {\n\t\t\t\tupdateSlider = true;\n\t\t\t} else {\n\t\t\t\t/* Create elements needed for slider */\n\t\t\t\tthis.sliderElem = document.createElement(\"div\");\n\t\t\t\tthis.sliderElem.className = \"slider\";\n\n\t\t\t\t/* Create slider track elements */\n\t\t\t\tvar sliderTrack = document.createElement(\"div\");\n\t\t\t\tsliderTrack.className = \"slider-track\";\n\n\t\t\t\tsliderTrackSelection = document.createElement(\"div\");\n\t\t\t\tsliderTrackSelection.className = \"slider-selection\";\n\n\t\t\t\tsliderMinHandle = document.createElement(\"div\");\n\t\t\t\tsliderMinHandle.className = \"slider-handle min-slider-handle\";\n\n\t\t\t\tsliderMaxHandle = document.createElement(\"div\");\n\t\t\t\tsliderMaxHandle.className = \"slider-handle max-slider-handle\";\n\n\t\t\t\tsliderTrack.appendChild(sliderTrackSelection);\n\t\t\t\tsliderTrack.appendChild(sliderMinHandle);\n\t\t\t\tsliderTrack.appendChild(sliderMaxHandle);\n\n\t\t\t\tvar createAndAppendTooltipSubElements = function(tooltipElem) {\n\t\t\t\t\tvar arrow = document.createElement(\"div\");\n\t\t\t\t\tarrow.className = \"tooltip-arrow\";\n\n\t\t\t\t\tvar inner = document.createElement(\"div\");\n\t\t\t\t\tinner.className = \"tooltip-inner\";\n\n\t\t\t\t\ttooltipElem.appendChild(arrow);\n\t\t\t\t\ttooltipElem.appendChild(inner);\n\t\t\t\t};\n\n\t\t\t\t/* Create tooltip elements */\n\t\t\t\tvar sliderTooltip = document.createElement(\"div\");\n\t\t\t\tsliderTooltip.className = \"tooltip tooltip-main\";\n\t\t\t\tcreateAndAppendTooltipSubElements(sliderTooltip);\n\n\t\t\t\tvar sliderTooltipMin = document.createElement(\"div\");\n\t\t\t\tsliderTooltipMin.className = \"tooltip tooltip-min\";\n\t\t\t\tcreateAndAppendTooltipSubElements(sliderTooltipMin);\n\n\t\t\t\tvar sliderTooltipMax = document.createElement(\"div\");\n\t\t\t\tsliderTooltipMax.className = \"tooltip tooltip-max\";\n\t\t\t\tcreateAndAppendTooltipSubElements(sliderTooltipMax);\n\n\n\t\t\t\t/* Append components to sliderElem */\n\t\t\t\tthis.sliderElem.appendChild(sliderTrack);\n\t\t\t\tthis.sliderElem.appendChild(sliderTooltip);\n\t\t\t\tthis.sliderElem.appendChild(sliderTooltipMin);\n\t\t\t\tthis.sliderElem.appendChild(sliderTooltipMax);\n\n\t\t\t\t/* Append slider element to parent container, right before the original <input> element */\n\t\t\t\tparent.insertBefore(this.sliderElem, this.element);\n\t\t\t\t\n\t\t\t\t/* Hide original <input> element */\n\t\t\t\tthis.element.style.display = \"none\";\n\t\t\t}\n\t\t\t/* If JQuery exists, cache JQ references */\n\t\t\tif($) {\n\t\t\t\tthis.$element = $(this.element);\n\t\t\t\tthis.$sliderElem = $(this.sliderElem);\n\t\t\t}\n\n\t\t\t/*************************************************\n\t\t\t\t\t\t\n\t\t\t\t\t\t\tProcess Options\n\n\t\t\t**************************************************/\n\t\t\toptions = options ? options : {};\n\t\t\tvar optionTypes = Object.keys(this.defaultOptions);\n\n\t\t\tfor(var i = 0; i < optionTypes.length; i++) {\n\t\t\t\tvar optName = optionTypes[i];\n\n\t\t\t\t// First check if an option was passed in via the constructor\n\t\t\t\tvar val = options[optName];\n\t\t\t\t// If no data attrib, then check data atrributes\n\t\t\t\tval = (typeof val !== 'undefined') ? val : getDataAttrib(this.element, optName);\n\t\t\t\t// Finally, if nothing was specified, use the defaults\n\t\t\t\tval = (val !== null) ? val : this.defaultOptions[optName];\n\n\t\t\t\t// Set all options on the instance of the Slider\n\t\t\t\tif(!this.options) {\n\t\t\t\t\tthis.options = {};\n\t\t\t\t}\n\t\t\t\tthis.options[optName] = val;\n\t\t\t}\n\n\t\t\tfunction getDataAttrib(element, optName) {\n\t\t\t\tvar dataName = \"data-slider-\" + optName;\n\t\t\t\tvar dataValString = element.getAttribute(dataName);\n\t\t\t\t\n\t\t\t\ttry {\n\t\t\t\t\treturn JSON.parse(dataValString);\n\t\t\t\t}\n\t\t\t\tcatch(err) {\n\t\t\t\t\treturn dataValString;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*************************************************\n\t\t\t\t\t\t\n\t\t\t\t\t\t\t\tSetup\n\n\t\t\t**************************************************/\n\t\t\tthis.eventToCallbackMap = {};\n\t\t\tthis.sliderElem.id = this.options.id;\n\n\t\t\tthis.touchCapable = 'ontouchstart' in window || (window.DocumentTouch && document instanceof window.DocumentTouch);\n\n\t\t\tthis.tooltip = this.sliderElem.querySelector('.tooltip-main');\n\t\t\tthis.tooltipInner = this.tooltip.querySelector('.tooltip-inner');\n\n\t\t\tthis.tooltip_min = this.sliderElem.querySelector('.tooltip-min');\n\t\t\tthis.tooltipInner_min = this.tooltip_min.querySelector('.tooltip-inner');\n\n\t\t\tthis.tooltip_max = this.sliderElem.querySelector('.tooltip-max');\n\t\t\tthis.tooltipInner_max= this.tooltip_max.querySelector('.tooltip-inner');\n\n\t\t\tif (updateSlider === true) {\n\t\t\t\t// Reset classes\n\t\t\t\tthis._removeClass(this.sliderElem, 'slider-horizontal');\n\t\t\t\tthis._removeClass(this.sliderElem, 'slider-vertical');\n\t\t\t\tthis._removeClass(this.tooltip, 'hide');\n\t\t\t\tthis._removeClass(this.tooltip_min, 'hide');\n\t\t\t\tthis._removeClass(this.tooltip_max, 'hide');\n\n\t\t\t\t// Undo existing inline styles for track\n\t\t\t\t[\"left\", \"top\", \"width\", \"height\"].forEach(function(prop) {\n\t\t\t\t\tthis._removeProperty(this.trackSelection, prop);\n\t\t\t\t}, this);\n\n\t\t\t\t// Undo inline styles on handles\n\t\t\t\t[this.handle1, this.handle2].forEach(function(handle) {\n\t\t\t\t\tthis._removeProperty(handle, 'left');\n\t\t\t\t\tthis._removeProperty(handle, 'top');\t\n\t\t\t\t}, this);\n\n\t\t\t\t// Undo inline styles and classes on tooltips\n\t\t\t\t[this.tooltip, this.tooltip_min, this.tooltip_max].forEach(function(tooltip) {\n\t\t\t\t\tthis._removeProperty(tooltip, 'left');\n\t\t\t\t\tthis._removeProperty(tooltip, 'top');\n\t\t\t\t\tthis._removeProperty(tooltip, 'margin-left');\n\t\t\t\t\tthis._removeProperty(tooltip, 'margin-top');\n\n\t\t\t\t\tthis._removeClass(tooltip, 'right');\n\t\t\t\t\tthis._removeClass(tooltip, 'top');\n\t\t\t\t}, this);\n\t\t\t}\n\n\t\t\tif(this.options.orientation === 'vertical') {\n\t\t\t\tthis._addClass(this.sliderElem,'slider-vertical');\n\t\t\t\t\n\t\t\t\tthis.stylePos = 'top';\n\t\t\t\tthis.mousePos = 'pageY';\n\t\t\t\tthis.sizePos = 'offsetHeight';\n\n\t\t\t\tthis._addClass(this.tooltip, 'right');\n\t\t\t\tthis.tooltip.style.left = '100%';\n\t\t\t\t\n\t\t\t\tthis._addClass(this.tooltip_min, 'right');\n\t\t\t\tthis.tooltip_min.style.left = '100%';\n\n\t\t\t\tthis._addClass(this.tooltip_max, 'right');\n\t\t\t\tthis.tooltip_max.style.left = '100%';\n\t\t\t} else {\n\t\t\t\tthis._addClass(this.sliderElem, 'slider-horizontal');\n\t\t\t\tthis.sliderElem.style.width = origWidth;\n\n\t\t\t\tthis.options.orientation = 'horizontal';\n\t\t\t\tthis.stylePos = 'left';\n\t\t\t\tthis.mousePos = 'pageX';\n\t\t\t\tthis.sizePos = 'offsetWidth';\n\t\t\t\t\n\t\t\t\tthis._addClass(this.tooltip, 'top');\n\t\t\t\tthis.tooltip.style.top = -this.tooltip.outerHeight - 14 + 'px';\n\t\t\t\t\n\t\t\t\tthis._addClass(this.tooltip_min, 'top');\n\t\t\t\tthis.tooltip_min.style.top = -this.tooltip_min.outerHeight - 14 + 'px';\n\n\t\t\t\tthis._addClass(this.tooltip_max, 'top');\n\t\t\t\tthis.tooltip_max.style.top = -this.tooltip_max.outerHeight - 14 + 'px';\n\t\t\t}\n\n\t\t\tif (this.options.value instanceof Array) {\n\t\t\t\tthis.options.range = true;\n\t\t\t} else if (this.options.range) {\n\t\t\t\t// User wants a range, but value is not an array\n\t\t\t\tthis.options.value = [this.options.value, this.options.max];\n\t\t\t}\n\n\t\t\tthis.trackSelection = sliderTrackSelection || this.trackSelection;\n\t\t\tif (this.options.selection === 'none') {\n\t\t\t\tthis._addClass(this.trackSelection, 'hide');\n\t\t\t}\n\n\t\t\tthis.handle1 = sliderMinHandle || this.handle1;\n\t\t\tthis.handle2 = sliderMaxHandle || this.handle2;\n\n\t\t\tif (updateSlider === true) {\n\t\t\t\t// Reset classes\n\t\t\t\tthis._removeClass(this.handle1, 'round triangle');\n\t\t\t\tthis._removeClass(this.handle2, 'round triangle hide');\n\t\t\t}\n\n\t\t\tvar availableHandleModifiers = ['round', 'triangle', 'custom'];\n\t\t\tvar isValidHandleType = availableHandleModifiers.indexOf(this.options.handle) !== -1;\n\t\t\tif (isValidHandleType) {\n\t\t\t\tthis._addClass(this.handle1, this.options.handle);\n\t\t\t\tthis._addClass(this.handle2, this.options.handle);\n\t\t\t}\n\n\t\t\tthis.offset = this._offset(this.sliderElem);\n\t\t\tthis.size = this.sliderElem[this.sizePos];\n\t\t\tthis.setValue(this.options.value);\n\n\t\t\t/******************************************\n\t\t\t\t\t\t\n\t\t\t\t\t\tBind Event Listeners\n\n\t\t\t******************************************/\n\n\t\t\t// Bind keyboard handlers\n\t\t\tthis.handle1Keydown = this._keydown.bind(this, 0);\n\t\t\tthis.handle1.addEventListener(\"keydown\", this.handle1Keydown, false);\n\n\t\t\tthis.handle2Keydown = this._keydown.bind(this, 0);\n\t\t\tthis.handle2.addEventListener(\"keydown\", this.handle2Keydown, false);\n\n\t\t\tif (this.touchCapable) {\n\t\t\t\t// Bind touch handlers\n\t\t\t\tthis.mousedown = this._mousedown.bind(this);\n\t\t\t\tthis.sliderElem.addEventListener(\"touchstart\", this.mousedown, false);\n\t\t\t} else {\n\t\t\t\t// Bind mouse handlers\n\t\t\t\tthis.mousedown = this._mousedown.bind(this);\n\t\t\t\tthis.sliderElem.addEventListener(\"mousedown\", this.mousedown, false);\n\t\t\t}\n\n\t\t\t// Bind tooltip-related handlers\n\t\t\tif(this.options.tooltip === 'hide') {\n\t\t\t\tthis._addClass(this.tooltip, 'hide');\n\t\t\t\tthis._addClass(this.tooltip_min, 'hide');\n\t\t\t\tthis._addClass(this.tooltip_max, 'hide');\n\t\t\t} else if(this.options.tooltip === 'always') {\n\t\t\t\tthis._showTooltip();\n\t\t\t\tthis._alwaysShowTooltip = true;\n\t\t\t} else {\n\t\t\t\tthis.showTooltip = this._showTooltip.bind(this);\n\t\t\t\tthis.hideTooltip = this._hideTooltip.bind(this);\n\n\t\t\t\tthis.sliderElem.addEventListener(\"mouseenter\", this.showTooltip, false);\n\t\t\t\tthis.sliderElem.addEventListener(\"mouseleave\", this.hideTooltip, false);\n\n\t\t\t\tthis.handle1.addEventListener(\"focus\", this.showTooltip, false);\n\t\t\t\tthis.handle1.addEventListener(\"blur\", this.hideTooltip, false);\n\n\t\t\t\tthis.handle2.addEventListener(\"focus\", this.showTooltip, false);\n\t\t\t\tthis.handle2.addEventListener(\"blur\", this.hideTooltip, false);\n\t\t\t}\n\n\t\t\tif(this.options.enabled) {\n\t\t\t\tthis.enable();\n\t\t\t} else {\n\t\t\t\tthis.disable();\n\t\t\t}\n\t\t}\n\n\t\t/*************************************************\n\t\t\t\t\t\t\n\t\t\t\t\tINSTANCE PROPERTIES/METHODS\n\n\t\t- Any methods bound to the prototype are considered \n\t\tpart of the plugin's `public` interface\n\n\t\t**************************************************/\n\t\tSlider.prototype = {\n\t\t\t_init: function() {}, // NOTE: Must exist to support bridget\n\n\t\t\tconstructor: Slider,\n\n\t\t\tdefaultOptions: {\n\t\t\t\tid: \"\",\n\t\t\t  \tmin: 0,\n\t\t\t\tmax: 10,\n\t\t\t\tstep: 1,\n\t\t\t\tprecision: 0,\n\t\t\t\torientation: 'horizontal',\n\t\t\t\tvalue: 5,\n\t\t\t\trange: false,\n\t\t\t\tselection: 'before',\n\t\t\t\ttooltip: 'show',\n\t\t\t\ttooltip_split: false,\n\t\t\t\thandle: 'round',\n\t\t\t\treversed: false,\n\t\t\t\tenabled: true,\n\t\t\t\tformatter: function(val) {\n\t\t\t\t\tif(val instanceof Array) {\n\t\t\t\t\t\treturn val[0] + \" : \" + val[1];\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn val;\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tnatural_arrow_keys: false\n\t\t\t},\n\t\t\t\n\t\t\tover: false,\n\t\t\t\n\t\t\tinDrag: false,\n\n\t\t\tgetValue: function() {\n\t\t\t\tif (this.options.range) {\n\t\t\t\t\treturn this.options.value;\n\t\t\t\t}\n\t\t\t\treturn this.options.value[0];\n\t\t\t},\n\n\t\t\tsetValue: function(val, triggerSlideEvent) {\n\t\t\t\tif (!val) {\n\t\t\t\t\tval = 0;\n\t\t\t\t}\n\t\t\t\tthis.options.value = this._validateInputValue(val);\n\t\t\t\tvar applyPrecision = this._applyPrecision.bind(this);\n\n\t\t\t\tif (this.options.range) {\n\t\t\t\t\tthis.options.value[0] = applyPrecision(this.options.value[0]);\n\t\t\t\t\tthis.options.value[1] = applyPrecision(this.options.value[1]); \n\n\t\t\t\t\tthis.options.value[0] = Math.max(this.options.min, Math.min(this.options.max, this.options.value[0]));\n\t\t\t\t\tthis.options.value[1] = Math.max(this.options.min, Math.min(this.options.max, this.options.value[1]));\n\t\t\t\t} else {\n\t\t\t\t\tthis.options.value = applyPrecision(this.options.value);\n\t\t\t\t\tthis.options.value = [ Math.max(this.options.min, Math.min(this.options.max, this.options.value))];\n\t\t\t\t\tthis._addClass(this.handle2, 'hide');\n\t\t\t\t\tif (this.options.selection === 'after') {\n\t\t\t\t\t\tthis.options.value[1] = this.options.max;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.options.value[1] = this.options.min;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tthis.diff = this.options.max - this.options.min;\n\t\t\t\tif (this.diff > 0) {\n\t\t\t\t\tthis.percentage = [\n\t\t\t\t\t\t(this.options.value[0] - this.options.min) * 100 / this.diff,\n\t\t\t\t\t\t(this.options.value[1] - this.options.min) * 100 / this.diff,\n\t\t\t\t\t\tthis.options.step * 100 / this.diff\n\t\t\t\t\t];\n\t\t\t\t} else {\n\t\t\t\t\tthis.percentage = [0, 0, 100];\n\t\t\t\t}\n\n\t\t\t\tthis._layout();\n\n\t\t\t\tvar sliderValue = this.options.range ? this.options.value : this.options.value[0];\n\t\t\t\tthis._setDataVal(sliderValue);\n\n\t\t\t\tif(triggerSlideEvent === true) {\n\t\t\t\t\tthis._trigger('slide', sliderValue);\n\t\t\t\t}\n\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\tdestroy: function(){\n\t\t\t\t// Remove event handlers on slider elements\n\t\t\t\tthis._removeSliderEventHandlers();\n\n\t\t\t\t// Remove the slider from the DOM\n\t\t\t\tthis.sliderElem.parentNode.removeChild(this.sliderElem);\n\t\t\t\t/* Show original <input> element */\n\t\t\t\tthis.element.style.display = \"\";\n\n\t\t\t\t// Clear out custom event bindings\n\t\t\t\tthis._cleanUpEventCallbacksMap();\n\n\t\t\t\t// Remove data values\n\t\t\t\tthis.element.removeAttribute(\"data\");\n\n\t\t\t\t// Remove JQuery handlers/data\n\t\t\t\tif($) {\n\t\t\t\t\tthis._unbindJQueryEventHandlers();\n\t\t\t\t\tthis.$element.removeData('slider');\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tdisable: function() {\n\t\t\t\tthis.options.enabled = false;\n\t\t\t\tthis.handle1.removeAttribute(\"tabindex\");\n\t\t\t\tthis.handle2.removeAttribute(\"tabindex\");\n\t\t\t\tthis._addClass(this.sliderElem, 'slider-disabled');\n\t\t\t\tthis._trigger('slideDisabled');\n\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\tenable: function() {\n\t\t\t\tthis.options.enabled = true;\n\t\t\t\tthis.handle1.setAttribute(\"tabindex\", 0);\n\t\t\t\tthis.handle2.setAttribute(\"tabindex\", 0);\n\t\t\t\tthis._removeClass(this.sliderElem, 'slider-disabled');\n\t\t\t\tthis._trigger('slideEnabled');\n\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\ttoggle: function() {\n\t\t\t\tif(this.options.enabled) {\n\t\t\t\t\tthis.disable();\n\t\t\t\t} else {\n\t\t\t\t\tthis.enable();\n\t\t\t\t}\n\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\tisEnabled: function() {\n\t\t\t\treturn this.options.enabled;\n\t\t\t},\n\n\t\t\ton: function(evt, callback) {\n\t\t\t\tif($) {\n\t\t\t\t\tthis.$element.on(evt, callback);\n\t\t\t\t\tthis.$sliderElem.on(evt, callback);\n\t\t\t\t} else {\n\t\t\t\t\tthis._bindNonQueryEventHandler(evt, callback);\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\tgetAttribute: function(attribute) {\n\t\t\t\tif(attribute) {\n\t\t\t\t\treturn this.options[attribute];\t\t\n\t\t\t\t} else {\n\t\t\t\t\treturn this.options;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tsetAttribute: function(attribute, value) {\n\t\t\t\tthis.options[attribute] = value;\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\trefresh: function() {\n\t\t\t\tthis._removeSliderEventHandlers();\n\t\t\t\tcreateNewSlider.call(this, this.element, this.options);\n\t\t\t\tif($) {\n\t\t\t\t\t// Bind new instance of slider to the element\n\t\t\t\t\t$.data(this.element, 'slider', this);\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\t\n\t\t\t/******************************+\n\t\t\t\t\t\n\t\t\t\t\t\tHELPERS\n\n\t\t\t- Any method that is not part of the public interface.\n\t\t\t- Place it underneath this comment block and write its signature like so:\n\n\t\t\t  \t\t\t\t\t_fnName : function() {...}\n\n\t\t\t********************************/\n\t\t\t_removeSliderEventHandlers: function() {\n\t\t\t\t// Remove event listeners from handle1\n\t\t\t\tthis.handle1.removeEventListener(\"keydown\", this.handle1Keydown, false);\n\t\t\t\tthis.handle1.removeEventListener(\"focus\", this.showTooltip, false);\n\t\t\t\tthis.handle1.removeEventListener(\"blur\", this.hideTooltip, false);\n\n\t\t\t\t// Remove event listeners from handle2\n\t\t\t\tthis.handle2.removeEventListener(\"keydown\", this.handle2Keydown, false);\n\t\t\t\tthis.handle2.removeEventListener(\"focus\", this.handle2Keydown, false);\n\t\t\t\tthis.handle2.removeEventListener(\"blur\", this.handle2Keydown, false);\n\n\t\t\t\t// Remove event listeners from sliderElem\n\t\t\t\tthis.sliderElem.removeEventListener(\"mouseenter\", this.showTooltip, false);\n\t\t\t\tthis.sliderElem.removeEventListener(\"mouseleave\", this.hideTooltip, false);\n\t\t\t\tthis.sliderElem.removeEventListener(\"touchstart\", this.mousedown, false);\n\t\t\t\tthis.sliderElem.removeEventListener(\"mousedown\", this.mousedown, false);\n\t\t\t},\n\t\t\t_bindNonQueryEventHandler: function(evt, callback) {\n\t\t\t\tif(this.eventToCallbackMap[evt]===undefined) {\n\t\t\t\t\tthis.eventToCallbackMap[evt] = [];\n\t\t\t\t}\n\t\t\t\tthis.eventToCallbackMap[evt].push(callback);\n\t\t\t},\n\t\t\t_cleanUpEventCallbacksMap: function() {\n\t\t\t\tvar eventNames = Object.keys(this.eventToCallbackMap);\n\t\t\t\tfor(var i = 0; i < eventNames.length; i++) {\n\t\t\t\t\tvar eventName = eventNames[i];\n\t\t\t\t\tthis.eventToCallbackMap[eventName] = null;\n\t\t\t\t}\n\t\t\t},\n\t\t\t_showTooltip: function() {\n\t\t\t\tif (this.options.tooltip_split === false ){\n\t            \tthis._addClass(this.tooltip, 'in');\n\t\t        } else {\n\t\t            this._addClass(this.tooltip_min, 'in');\n\t\t            this._addClass(this.tooltip_max, 'in');\n\t\t        }\n\t\t\t\tthis.over = true;\n\t\t\t},\n\t\t\t_hideTooltip: function() {\n\t\t\t\tif (this.inDrag === false && this.alwaysShowTooltip !== true) {\n\t\t\t\t\tthis._removeClass(this.tooltip, 'in');\n\t\t\t\t\tthis._removeClass(this.tooltip_min, 'in');\n\t\t\t\t\tthis._removeClass(this.tooltip_max, 'in');\n\t\t\t\t}\n\t\t\t\tthis.over = false;\n\t\t\t},\n\t\t\t\t_layout: function() {\t\t\t\n\t\t\t\tvar positionPercentages;\n\n\t\t\t\tif(this.options.reversed) {\n\t\t\t\t\tpositionPercentages = [ 100 - this.percentage[0], this.percentage[1] ];\n\t\t\t\t} else {\n\t\t\t\t\tpositionPercentages = [ this.percentage[0], this.percentage[1] ];\n\t\t\t\t}\n\n\t\t\t\tthis.handle1.style[this.stylePos] = positionPercentages[0]+'%';\n\t\t\t\tthis.handle2.style[this.stylePos] = positionPercentages[1]+'%';\n\n\t\t\t\tif (this.options.orientation === 'vertical') {\n\t\t\t\t\tthis.trackSelection.style.top = Math.min(positionPercentages[0], positionPercentages[1]) +'%';\n\t\t\t\t\tthis.trackSelection.style.height = Math.abs(positionPercentages[0] - positionPercentages[1]) +'%';\n\t\t\t\t} else {\n\t\t\t\t\tthis.trackSelection.style.left = Math.min(positionPercentages[0], positionPercentages[1]) +'%';\n\t\t\t\t\tthis.trackSelection.style.width = Math.abs(positionPercentages[0] - positionPercentages[1]) +'%';\n\n\t\t\t        var offset_min = this.tooltip_min.getBoundingClientRect();\n\t\t\t        var offset_max = this.tooltip_max.getBoundingClientRect();\n\n\t\t\t        if (offset_min.right > offset_max.left) {\n\t\t\t            this._removeClass(this.tooltip_max, 'top');\n\t\t\t            this._addClass(this.tooltip_max, 'bottom');\n\t\t\t            this.tooltip_max.style.top = 18 + 'px';\n\t\t\t        } else {\n\t\t\t            this._removeClass(this.tooltip_max, 'bottom');\n\t\t\t            this._addClass(this.tooltip_max, 'top');\n\t\t\t            this.tooltip_max.style.top = -30 + 'px';\n\t\t\t        }\n\t \t\t\t}\n\n\n\t \t\t\tvar formattedTooltipVal;\n\n\t\t\t\tif (this.options.range) {\n\t\t\t\t\tformattedTooltipVal = this.options.formatter(this.options.value);\n\t\t\t\t\tthis._setText(this.tooltipInner, formattedTooltipVal);\n\t\t\t\t\tthis.tooltip.style[this.stylePos] = (positionPercentages[1] + positionPercentages[0])/2 + '%';\n\n\t\t\t\t\tif (this.options.orientation === 'vertical') {\n\t\t\t\t\t\tthis._css(this.tooltip, 'margin-top', -this.tooltip.offsetHeight / 2 + 'px');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis._css(this.tooltip, 'margin-left', -this.tooltip.offsetWidth / 2 + 'px');\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tif (this.options.orientation === 'vertical') {\n\t\t\t\t\t\tthis._css(this.tooltip, 'margin-top', -this.tooltip.offsetHeight / 2 + 'px');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis._css(this.tooltip, 'margin-left', -this.tooltip.offsetWidth / 2 + 'px');\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t\tvar innerTooltipMinText = this.options.formatter(this.options.value[0]);\n\t\t\t\t\tthis._setText(this.tooltipInner_min, innerTooltipMinText);\n\n\t\t\t\t\tvar innerTooltipMaxText = this.options.formatter(this.options.value[1]);\n\t\t\t\t\tthis._setText(this.tooltipInner_max, innerTooltipMaxText);\n\n\t\t\t\t\tthis.tooltip_min.style[this.stylePos] = positionPercentages[0] + '%';\n\n\t\t\t\t\tif (this.options.orientation === 'vertical') {\n\t\t\t\t\t\tthis._css(this.tooltip_min, 'margin-top', -this.tooltip_min.offsetHeight / 2 + 'px');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis._css(this.tooltip_min, 'margin-left', -this.tooltip_min.offsetWidth / 2 + 'px');\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.tooltip_max.style[this.stylePos] = positionPercentages[1] + '%';\n\n\t\t\t\t\tif (this.options.orientation === 'vertical') {\n\t\t\t\t\t\tthis._css(this.tooltip_max, 'margin-top', -this.tooltip_max.offsetHeight / 2 + 'px');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis._css(this.tooltip_max, 'margin-left', -this.tooltip_max.offsetWidth / 2 + 'px');\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tformattedTooltipVal = this.options.formatter(this.options.value[0]);\n\t\t\t\t\tthis._setText(this.tooltipInner, formattedTooltipVal);\n\n\t\t\t\t\tthis.tooltip.style[this.stylePos] = positionPercentages[0] + '%';\n\t\t\t\t\tif (this.options.orientation === 'vertical') {\n\t\t\t\t\t\tthis._css(this.tooltip, 'margin-top', -this.tooltip.offsetHeight / 2 + 'px');\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis._css(this.tooltip, 'margin-left', -this.tooltip.offsetWidth / 2 + 'px');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t_removeProperty: function(element, prop) {\n\t\t\t\tif (element.style.removeProperty) {\n\t\t\t\t    element.style.removeProperty(prop);\n\t\t\t\t} else {\n\t\t\t\t    element.style.removeAttribute(prop);\n\t\t\t\t}\n\t\t\t},\n\t\t\t_mousedown: function(ev) {\n\t\t\t\tif(!this.options.enabled) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tthis._triggerFocusOnHandle();\n\n\t\t\t\tthis.offset = this._offset(this.sliderElem);\n\t\t\t\tthis.size = this.sliderElem[this.sizePos];\n\n\t\t\t\tvar percentage = this._getPercentage(ev);\n\n\t\t\t\tif (this.options.range) {\n\t\t\t\t\tvar diff1 = Math.abs(this.percentage[0] - percentage);\n\t\t\t\t\tvar diff2 = Math.abs(this.percentage[1] - percentage);\n\t\t\t\t\tthis.dragged = (diff1 < diff2) ? 0 : 1;\n\t\t\t\t} else {\n\t\t\t\t\tthis.dragged = 0;\n\t\t\t\t}\n\n\t\t\t\tthis.percentage[this.dragged] = this.options.reversed ? 100 - percentage : percentage;\n\t\t\t\tthis._layout();\n\n\t\t\t\tthis.mousemove = this._mousemove.bind(this);\n\t\t\t\tthis.mouseup = this._mouseup.bind(this);\n\n\t\t\t\tif (this.touchCapable) {\n\t\t\t\t\t// Touch: Bind touch events:\n\t\t\t\t\tdocument.addEventListener(\"touchmove\", this.mousemove, false);\n\t\t\t\t\tdocument.addEventListener(\"touchend\", this.mouseup, false);\n\t\t\t\t} else {\n\t\t\t\t\t// Bind mouse events:\n\t\t\t\t\tdocument.addEventListener(\"mousemove\", this.mousemove, false);\n\t\t\t\t\tdocument.addEventListener(\"mouseup\", this.mouseup, false);\n\t\t\t\t}\n\n\t\t\t\tthis.inDrag = true;\n\n\t\t\t\tvar val = this._calculateValue();\n\t\t\t\tthis._trigger('slideStart', val);\n\t\t\t\tthis._setDataVal(val);\n\t\t\t\tthis.setValue(val);\n\n\t\t\t\tthis._pauseEvent(ev);\n\n\t\t\t\treturn true;\n\t\t\t},\n\t\t\t_triggerFocusOnHandle: function(handleIdx) {\n\t\t\t\tif(handleIdx === 0) {\n\t\t\t\t\tthis.handle1.focus();\n\t\t\t\t}\n\t\t\t\tif(handleIdx === 1) {\n\t\t\t\t\tthis.handle2.focus();\n\t\t\t\t}\n\t\t\t},\n\t\t\t_keydown: function(handleIdx, ev) {\n\t\t\t\tif(!this.options.enabled) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tvar dir;\n\t\t\t\tswitch (ev.keyCode) {\n\t\t\t\t\tcase 37: // left\n\t\t\t\t\tcase 40: // down\n\t\t\t\t\t\tdir = -1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase 39: // right\n\t\t\t\t\tcase 38: // up\n\t\t\t\t\t\tdir = 1;\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tif (!dir) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// use natural arrow keys instead of from min to max\n\t\t\t\tif (this.options.natural_arrow_keys) {\n\t\t\t\t\tvar ifVerticalAndNotReversed = (this.options.orientation === 'vertical' && !this.options.reversed);\n\t\t\t\t\tvar ifHorizontalAndReversed = (this.options.orientation === 'horizontal' && this.options.reversed);\n\n\t\t\t\t\tif (ifVerticalAndNotReversed || ifHorizontalAndReversed) {\n\t\t\t\t\t\tdir = dir * -1;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tvar oneStepValuePercentageChange = dir * this.percentage[2];\n\t\t\t\tvar percentage = this.percentage[handleIdx] + oneStepValuePercentageChange;\n\n\t\t\t\tif (percentage > 100) {\n\t\t\t\t\tpercentage = 100;\n\t\t\t\t} else if (percentage < 0) {\n\t\t\t\t\tpercentage = 0;\n\t\t\t\t}\n\n\t\t\t\tthis.dragged = handleIdx;\n\t\t\t\tthis._adjustPercentageForRangeSliders(percentage);\n\t\t\t\tthis.percentage[this.dragged] = percentage;\n\t\t\t\tthis._layout();\n\n\t\t\t\tvar val = this._calculateValue();\n\t\t\t\t\n\t\t\t\tthis._trigger('slideStart', val);\n\t\t\t\tthis._setDataVal(val);\n\t\t\t\tthis.setValue(val, true);\n\n\t\t\t\tthis._trigger('slideStop', val);\n\t\t\t\tthis._setDataVal(val);\n\t\t\t\t\n\t\t\t\tthis._pauseEvent(ev);\n\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t_pauseEvent: function(ev) {\n\t\t\t\tif(ev.stopPropagation) {\n\t\t\t\t\tev.stopPropagation();\n\t\t\t\t}\n\t\t\t    if(ev.preventDefault) {\n\t\t\t    \tev.preventDefault();\n\t\t\t    }\n\t\t\t    ev.cancelBubble=true;\n\t\t\t    ev.returnValue=false;\t\t\t\n\t\t\t},\n\t\t\t_mousemove: function(ev) {\n\t\t\t\tif(!this.options.enabled) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\n\t\t\t\tvar percentage = this._getPercentage(ev);\n\t\t\t\tthis._adjustPercentageForRangeSliders(percentage);\n\t\t\t\tthis.percentage[this.dragged] = this.options.reversed ? 100 - percentage : percentage;\n\t\t\t\tthis._layout();\n\n\t\t\t\tvar val = this._calculateValue();\n\t\t\t\tthis.setValue(val, true);\n\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t_adjustPercentageForRangeSliders: function(percentage) {\n\t\t\t\tif (this.options.range) {\n\t\t\t\t\tif (this.dragged === 0 && this.percentage[1] < percentage) {\n\t\t\t\t\t\tthis.percentage[0] = this.percentage[1];\n\t\t\t\t\t\tthis.dragged = 1;\n\t\t\t\t\t} else if (this.dragged === 1 && this.percentage[0] > percentage) {\n\t\t\t\t\t\tthis.percentage[1] = this.percentage[0];\n\t\t\t\t\t\tthis.dragged = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t_mouseup: function() {\n\t\t\t\tif(!this.options.enabled) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tif (this.touchCapable) {\n\t\t\t\t\t// Touch: Unbind touch event handlers:\n\t\t\t\t\tdocument.removeEventListener(\"touchmove\", this.mousemove, false);\n\t\t\t\t\tdocument.removeEventListener(\"touchend\", this.mouseup, false);\n\t\t\t\t} else {\n\t\t\t\t\t// Unbind mouse event handlers:\n\t\t\t\t\tdocument.removeEventListener(\"mousemove\", this.mousemove, false);\n\t\t\t\t\tdocument.removeEventListener(\"mouseup\", this.mouseup, false);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tthis.inDrag = false;\n\t\t\t\tif (this.over === false) {\n\t\t\t\t\tthis._hideTooltip();\n\t\t\t\t}\n\t\t\t\tvar val = this._calculateValue();\n\t\t\t\t\n\t\t\t\tthis._layout();\n\t\t\t\tthis._setDataVal(val);\n\t\t\t\tthis._trigger('slideStop', val);\n\t\t\t\t\n\t\t\t\treturn false;\n\t\t\t},\n\t\t\t_calculateValue: function() {\n\t\t\t\tvar val;\n\t\t\t\tif (this.options.range) {\n\t\t\t\t\tval = [this.options.min,this.options.max];\n\t\t\t        if (this.percentage[0] !== 0){\n\t\t\t            val[0] = (Math.max(this.options.min, this.options.min + Math.round((this.diff * this.percentage[0]/100)/this.options.step)*this.options.step));\n\t\t\t            val[0] = this._applyPrecision(val[0]);\n\t\t\t        }\n\t\t\t        if (this.percentage[1] !== 100){\n\t\t\t            val[1] = (Math.min(this.options.max, this.options.min + Math.round((this.diff * this.percentage[1]/100)/this.options.step)*this.options.step));\n\t\t\t            val[1] = this._applyPrecision(val[1]);\n\t\t\t        }\n\t\t\t\t\tthis.options.value = val;\n\t\t\t\t} else {\n\t\t\t\t\tval = (this.options.min + Math.round((this.diff * this.percentage[0]/100)/this.options.step)*this.options.step);\n\t\t\t\t\tif (val < this.options.min) {\n\t\t\t\t\t\tval = this.options.min;\n\t\t\t\t\t}\n\t\t\t\t\telse if (val > this.options.max) {\n\t\t\t\t\t\tval = this.options.max;\n\t\t\t\t\t}\n\t\t\t\t\tval = parseFloat(val);\n\t\t\t\t\tval = this._applyPrecision(val);\n\t\t\t\t\tthis.options.value = [val, this.options.value[1]];\n\t\t\t\t}\n\t\t\t\treturn val;\n\t\t\t},\n\t\t\t_applyPrecision: function(val) {\n\t\t\t\tvar precision = this.options.precision || this._getNumDigitsAfterDecimalPlace(this.step);\n\t\t\t\treturn this._applyToFixedAndParseFloat(val, precision);\n\t\t\t},\n\t\t\t_getNumDigitsAfterDecimalPlace: function(num) {\n\t\t\t\tvar match = (''+num).match(/(?:\\.(\\d+))?(?:[eE]([+-]?\\d+))?$/);\n\t\t\t\tif (!match) { return 0; }\n\t\t\t\treturn Math.max(0, (match[1] ? match[1].length : 0) - (match[2] ? +match[2] : 0));\n\t\t\t},\n\t\t\t_applyToFixedAndParseFloat: function(num, toFixedInput) {\n\t\t\t\tvar truncatedNum = num.toFixed(toFixedInput);\n\t\t\t\treturn parseFloat(truncatedNum);\n\t\t\t},\n\t\t\t/*\n\t\t\t\tCredits to Mike Samuel for the following method!\n\t\t\t\tSource: http://stackoverflow.com/questions/10454518/javascript-how-to-retrieve-the-number-of-decimals-of-a-string-number\n\t\t\t*/\n\t\t\t_getPercentage: function(ev) {\n\t\t\t\tif (this.touchCapable && (ev.type === 'touchstart' || ev.type === 'touchmove')) {\n\t\t\t\t\tev = ev.touches[0];\n\t\t\t\t}\n\t\t\t\tvar percentage = (ev[this.mousePos] - this.offset[this.stylePos])*100/this.size;\n\t\t\t\tpercentage = Math.round(percentage/this.percentage[2])*this.percentage[2];\n\t\t\t\treturn Math.max(0, Math.min(100, percentage));\n\t\t\t},\n\t\t\t_validateInputValue: function(val) {\n\t\t\t\tif(typeof val === 'number') {\n\t\t\t\t\treturn val;\n\t\t\t\t} else if(val instanceof Array) {\n\t\t\t\t\tthis._validateArray(val);\n\t\t\t\t\treturn val;\n\t\t\t\t} else {\n\t\t\t\t\tthrow new Error( ErrorMsgs.formatInvalidInputErrorMsg(val) );\n\t\t\t\t}\n\t\t\t},\n\t\t\t_validateArray: function(val) {\n\t\t\t\tfor(var i = 0; i < val.length; i++) {\n\t\t\t\t\tvar input =  val[i];\n\t\t\t\t\tif (typeof input !== 'number') { throw new Error( ErrorMsgs.formatInvalidInputErrorMsg(input) ); }\n\t\t\t\t}\n\t\t\t},\n\t\t\t_setDataVal: function(val) {\n\t\t\t\tvar value = \"value: '\" + val + \"'\";\n\t\t\t\tthis.element.setAttribute('data', value);\n\t\t\t\tthis.element.setAttribute('value', val);\n\t\t\t},\n\t\t\t_trigger: function(evt, val) {\n\t\t\t\tval = val || undefined;\n\n\t\t\t\tvar callbackFnArray = this.eventToCallbackMap[evt];\n\t\t\t\tif(callbackFnArray && callbackFnArray.length) {\n\t\t\t\t\tfor(var i = 0; i < callbackFnArray.length; i++) {\n\t\t\t\t\t\tvar callbackFn = callbackFnArray[i];\n\t\t\t\t\t\tcallbackFn(val);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t/* If JQuery exists, trigger JQuery events */\n\t\t\t\tif($) {\n\t\t\t\t\tthis._triggerJQueryEvent(evt, val);\n\t\t\t\t}\n\t\t\t},\n\t\t\t_triggerJQueryEvent: function(evt, val) {\n\t\t\t\tvar eventData = {\n\t\t\t\t\ttype: evt,\n\t\t\t\t\tvalue: val\n\t\t\t\t};\n\t\t\t\tthis.$element.trigger(eventData);\n\t\t\t\tthis.$sliderElem.trigger(eventData);\n\t\t\t},\n\t\t\t_unbindJQueryEventHandlers: function() {\n\t\t\t\tthis.$element.off();\n\t\t\t\tthis.$sliderElem.off();\n\t\t\t},\n\t\t\t_setText: function(element, text) {\n\t\t\t\tif(typeof element.innerText !== \"undefined\") {\n\t\t\t \t\telement.innerText = text;\n\t\t\t \t} else if(typeof element.textContent !== \"undefined\") {\n\t\t\t \t\telement.textContent = text;\n\t\t\t \t}\n\t\t\t},\n\t\t\t_removeClass: function(element, classString) {\n\t\t\t\tvar classes = classString.split(\" \");\n\t\t\t\tvar newClasses = element.className;\n\n\t\t\t\tfor(var i = 0; i < classes.length; i++) {\n\t\t\t\t\tvar classTag = classes[i];\n\t\t\t\t\tvar regex = new RegExp(\"(?:\\\\s|^)\" + classTag + \"(?:\\\\s|$)\");\n\t\t\t\t\tnewClasses = newClasses.replace(regex, \" \");\n\t\t\t\t}\n\n\t\t\t\telement.className = newClasses.trim();\n\t\t\t},\n\t\t\t_addClass: function(element, classString) {\n\t\t\t\tvar classes = classString.split(\" \");\n\t\t\t\tvar newClasses = element.className;\n\n\t\t\t\tfor(var i = 0; i < classes.length; i++) {\n\t\t\t\t\tvar classTag = classes[i];\n\t\t\t\t\tvar regex = new RegExp(\"(?:\\\\s|^)\" + classTag + \"(?:\\\\s|$)\");\n\t\t\t\t\tvar ifClassExists = regex.test(newClasses);\n\t\t\t\t\t\n\t\t\t\t\tif(!ifClassExists) {\n\t\t\t\t\t\tnewClasses += \" \" + classTag;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\telement.className = newClasses.trim();\n\t\t\t},\n\t\t\t_offset: function (obj) {\n\t\t\t\tvar ol = 0;\n\t\t\t\tvar ot = 0;\n\t\t\t\tif (obj.offsetParent) {\n\t\t\t\t\tdo {\n\t\t\t\t\t  ol += obj.offsetLeft;\n\t\t\t\t\t  ot += obj.offsetTop;\n\t\t\t\t\t} while (obj = obj.offsetParent);\n\t\t\t\t}\n\t\t\t\treturn {\n\t\t\t\t\tleft: ol,\n\t\t\t\t\ttop: ot\n\t\t\t\t};\n\t\t\t},\n\t\t\t_css: function(elementRef, styleName, value) {\n\t\t\t\telementRef.style[styleName] = value;\n\t\t\t}\n\t\t};\n\n\t\t/*********************************\n\n\t\t\tAttach to global namespace\n\n\t\t*********************************/\n\t\tif($) {\n\t\t\tvar namespace = $.fn.slider ? 'bootstrapSlider' : 'slider';\n\t\t\t$.bridget(namespace, Slider);\n\t\t} else {\n\t\t\twindow.Slider = Slider;\n\t\t}\n\n\n\t})( $ );\n\n})( window.jQuery );"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/bootstrap-slider/slider.css",
    "content": "/*!\n * Slider for Bootstrap\n *\n * Copyright 2012 Stefan Petre\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n */\n.slider {\n    display: block;\n    vertical-align: middle;\n    position: relative;\n\n}\n.slider.slider-horizontal {\n    width: 100%;\n    height: 20px;\n    margin-bottom: 20px;\n}\n.slider.slider-horizontal:last-of-type {\n    margin-bottom: 0;\n}\n.slider.slider-horizontal .slider-track {\n    height: 10px;\n    width: 100%;\n    margin-top: -5px;\n    top: 50%;\n    left: 0;\n}\n.slider.slider-horizontal .slider-selection {\n    height: 100%;\n    top: 0;\n    bottom: 0;\n}\n.slider.slider-horizontal .slider-handle {\n    margin-left: -10px;\n    margin-top: -5px;\n}\n.slider.slider-horizontal .slider-handle.triangle {\n    border-width: 0 10px 10px 10px;\n    width: 0;\n    height: 0;\n    border-bottom-color: #0480be;\n    margin-top: 0;\n}\n.slider.slider-vertical {\n    height: 230px;\n    width: 20px;\n    margin-right: 20px;\n    display: inline-block;\n}\n.slider.slider-vertical:last-of-type {\n    margin-right: 0;\n}\n.slider.slider-vertical .slider-track {\n    width: 10px;\n    height: 100%;\n    margin-left: -5px;\n    left: 50%;\n    top: 0;\n}\n.slider.slider-vertical .slider-selection {\n    width: 100%;\n    left: 0;\n    top: 0;\n    bottom: 0;\n}\n.slider.slider-vertical .slider-handle {\n    margin-left: -5px;\n    margin-top: -10px;\n}\n.slider.slider-vertical .slider-handle.triangle {\n    border-width: 10px 0 10px 10px;\n    width: 1px;\n    height: 1px;\n    border-left-color: #0480be;\n    margin-left: 0;\n}\n.slider input {\n    display: none;\n}\n.slider .tooltip-inner {\n    white-space: nowrap;\n}\n.slider-track {\n    position: absolute;\n    cursor: pointer;\n    background-color: #f7f7f7;\n    background-image: -moz-linear-gradient(top, #f0f0f0, #f9f9f9);\n    background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f0f0f0), to(#f9f9f9));\n    background-image: -webkit-linear-gradient(top, #f0f0f0, #f9f9f9);\n    background-image: -o-linear-gradient(top, #f0f0f0, #f9f9f9);\n    background-image: linear-gradient(to bottom, #f0f0f0, #f9f9f9);\n    background-repeat: repeat-x;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0f0f0', endColorstr='#fff9f9f9', GradientType=0);\n    -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n    -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n    box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);\n    -webkit-border-radius: 4px;\n    -moz-border-radius: 4px;\n    border-radius: 4px;\n}\n.slider-selection {\n    position: absolute;\n    background-color: #f7f7f7;\n    background-image: -moz-linear-gradient(top, #f9f9f9, #f5f5f5);\n    background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f9f9f9), to(#f5f5f5));\n    background-image: -webkit-linear-gradient(top, #f9f9f9, #f5f5f5);\n    background-image: -o-linear-gradient(top, #f9f9f9, #f5f5f5);\n    background-image: linear-gradient(to bottom, #f9f9f9, #f5f5f5);\n    background-repeat: repeat-x;\n    filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff9f9f9', endColorstr='#fff5f5f5', GradientType=0);\n    -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n    -moz-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n    box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);\n    -webkit-box-sizing: border-box;\n    -moz-box-sizing: border-box;\n    box-sizing: border-box;\n    -webkit-border-radius: 4px;\n    -moz-border-radius: 4px;\n    border-radius: 4px;\n}\n.slider-handle {\n    position: absolute;\n    width: 20px;\n    height: 20px;\n    background-color: #444;\n    -webkit-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);\n    -moz-box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);\n    box-shadow: inset 0 1px 0 rgba(255,255,255,.2), 0 1px 2px rgba(0,0,0,.05);\n    opacity: 1;\n    border: 0px solid transparent;\n}\n.slider-handle.round {\n    -webkit-border-radius: 20px;\n    -moz-border-radius: 20px;\n    border-radius: 20px;\n}\n.slider-handle.triangle {\n    background: transparent none;\n}\n\n.slider-disabled .slider-selection {\n    opacity: 0.5;\n}\n\n#red .slider-selection {\n    background: #f56954;\n}\n\n#blue .slider-selection {\n    background: #3c8dbc;\n}\n\n#green .slider-selection {\n    background: #00a65a;\n}\n\n#yellow .slider-selection {\n    background: #f39c12;\n}\n\n#aqua .slider-selection {\n    background: #00c0ef;\n}\n\n#purple .slider-selection {\n    background: #932ab6;\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/all.css",
    "content": "/* iCheck plugin skins\n----------------------------------- */\n@import url(\"minimal/_all.css\");\n/*\n@import url(\"minimal/minimal.css\");\n@import url(\"minimal/red.css\");\n@import url(\"minimal/green.css\");\n@import url(\"minimal/blue.css\");\n@import url(\"minimal/aero.css\");\n@import url(\"minimal/grey.css\");\n@import url(\"minimal/orange.css\");\n@import url(\"minimal/yellow.css\");\n@import url(\"minimal/pink.css\");\n@import url(\"minimal/purple.css\");\n*/\n\n@import url(\"square/_all.css\");\n/*\n@import url(\"square/square.css\");\n@import url(\"square/red.css\");\n@import url(\"square/green.css\");\n@import url(\"square/blue.css\");\n@import url(\"square/aero.css\");\n@import url(\"square/grey.css\");\n@import url(\"square/orange.css\");\n@import url(\"square/yellow.css\");\n@import url(\"square/pink.css\");\n@import url(\"square/purple.css\");\n*/\n\n@import url(\"flat/_all.css\");\n/*\n@import url(\"flat/flat.css\");\n@import url(\"flat/red.css\");\n@import url(\"flat/green.css\");\n@import url(\"flat/blue.css\");\n@import url(\"flat/aero.css\");\n@import url(\"flat/grey.css\");\n@import url(\"flat/orange.css\");\n@import url(\"flat/yellow.css\");\n@import url(\"flat/pink.css\");\n@import url(\"flat/purple.css\");\n*/\n\n@import url(\"line/_all.css\");\n/*\n@import url(\"line/line.css\");\n@import url(\"line/red.css\");\n@import url(\"line/green.css\");\n@import url(\"line/blue.css\");\n@import url(\"line/aero.css\");\n@import url(\"line/grey.css\");\n@import url(\"line/orange.css\");\n@import url(\"line/yellow.css\");\n@import url(\"line/pink.css\");\n@import url(\"line/purple.css\");\n*/\n\n@import url(\"polaris/polaris.css\");\n\n@import url(\"futurico/futurico.css\");"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/flat/_all.css",
    "content": "/* iCheck plugin Flat skin\n----------------------------------- */\n.icheckbox_flat,\n.iradio_flat {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(flat.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat {\n    background-position: 0 0;\n}\n    .icheckbox_flat.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat {\n    background-position: -88px 0;\n}\n    .iradio_flat.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat,\n    .iradio_flat {\n        background-image: url(flat@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}\n\n/* red */\n.icheckbox_flat-red,\n.iradio_flat-red {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(red.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-red {\n    background-position: 0 0;\n}\n    .icheckbox_flat-red.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-red.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-red.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-red {\n    background-position: -88px 0;\n}\n    .iradio_flat-red.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-red.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-red.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-red,\n    .iradio_flat-red {\n        background-image: url(red@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}\n\n/* green */\n.icheckbox_flat-green,\n.iradio_flat-green {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(green.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-green {\n    background-position: 0 0;\n}\n    .icheckbox_flat-green.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-green.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-green.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-green {\n    background-position: -88px 0;\n}\n    .iradio_flat-green.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-green.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-green.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-green,\n    .iradio_flat-green {\n        background-image: url(green@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}\n\n/* blue */\n.icheckbox_flat-blue,\n.iradio_flat-blue {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(blue.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-blue {\n    background-position: 0 0;\n}\n    .icheckbox_flat-blue.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-blue.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-blue.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-blue {\n    background-position: -88px 0;\n}\n    .iradio_flat-blue.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-blue.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-blue.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-blue,\n    .iradio_flat-blue {\n        background-image: url(blue@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}\n\n/* aero */\n.icheckbox_flat-aero,\n.iradio_flat-aero {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(aero.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-aero {\n    background-position: 0 0;\n}\n    .icheckbox_flat-aero.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-aero.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-aero.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-aero {\n    background-position: -88px 0;\n}\n    .iradio_flat-aero.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-aero.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-aero.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-aero,\n    .iradio_flat-aero {\n        background-image: url(aero@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}\n\n/* grey */\n.icheckbox_flat-grey,\n.iradio_flat-grey {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(grey.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-grey {\n    background-position: 0 0;\n}\n    .icheckbox_flat-grey.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-grey.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-grey.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-grey {\n    background-position: -88px 0;\n}\n    .iradio_flat-grey.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-grey.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-grey.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-grey,\n    .iradio_flat-grey {\n        background-image: url(grey@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}\n\n/* orange */\n.icheckbox_flat-orange,\n.iradio_flat-orange {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(orange.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-orange {\n    background-position: 0 0;\n}\n    .icheckbox_flat-orange.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-orange.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-orange.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-orange {\n    background-position: -88px 0;\n}\n    .iradio_flat-orange.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-orange.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-orange.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-orange,\n    .iradio_flat-orange {\n        background-image: url(orange@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}\n\n/* yellow */\n.icheckbox_flat-yellow,\n.iradio_flat-yellow {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(yellow.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-yellow {\n    background-position: 0 0;\n}\n    .icheckbox_flat-yellow.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-yellow.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-yellow.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-yellow {\n    background-position: -88px 0;\n}\n    .iradio_flat-yellow.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-yellow.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-yellow.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-yellow,\n    .iradio_flat-yellow {\n        background-image: url(yellow@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}\n\n/* pink */\n.icheckbox_flat-pink,\n.iradio_flat-pink {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(pink.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-pink {\n    background-position: 0 0;\n}\n    .icheckbox_flat-pink.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-pink.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-pink.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-pink {\n    background-position: -88px 0;\n}\n    .iradio_flat-pink.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-pink.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-pink.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-pink,\n    .iradio_flat-pink {\n        background-image: url(pink@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}\n\n/* purple */\n.icheckbox_flat-purple,\n.iradio_flat-purple {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(purple.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-purple {\n    background-position: 0 0;\n}\n    .icheckbox_flat-purple.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-purple.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-purple.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-purple {\n    background-position: -88px 0;\n}\n    .iradio_flat-purple.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-purple.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-purple.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-purple,\n    .iradio_flat-purple {\n        background-image: url(purple@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/flat/aero.css",
    "content": "/* iCheck plugin Flat skin, aero\n----------------------------------- */\n.icheckbox_flat-aero,\n.iradio_flat-aero {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(aero.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-aero {\n    background-position: 0 0;\n}\n    .icheckbox_flat-aero.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-aero.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-aero.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-aero {\n    background-position: -88px 0;\n}\n    .iradio_flat-aero.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-aero.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-aero.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-aero,\n    .iradio_flat-aero {\n        background-image: url(aero@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/flat/blue.css",
    "content": "/* iCheck plugin Flat skin, blue\n----------------------------------- */\n.icheckbox_flat-blue,\n.iradio_flat-blue {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(blue.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-blue {\n    background-position: 0 0;\n}\n    .icheckbox_flat-blue.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-blue.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-blue.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-blue {\n    background-position: -88px 0;\n}\n    .iradio_flat-blue.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-blue.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-blue.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-blue,\n    .iradio_flat-blue {\n        background-image: url(blue@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/flat/flat.css",
    "content": "/* iCheck plugin flat skin, black\n----------------------------------- */\n.icheckbox_flat,\n.iradio_flat {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(flat.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat {\n    background-position: 0 0;\n}\n    .icheckbox_flat.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat {\n    background-position: -88px 0;\n}\n    .iradio_flat.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat,\n    .iradio_flat {\n        background-image: url(flat@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/flat/green.css",
    "content": "/* iCheck plugin Flat skin, green\n----------------------------------- */\n.icheckbox_flat-green,\n.iradio_flat-green {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(green.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-green {\n    background-position: 0 0;\n}\n    .icheckbox_flat-green.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-green.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-green.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-green {\n    background-position: -88px 0;\n}\n    .iradio_flat-green.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-green.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-green.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-green,\n    .iradio_flat-green {\n        background-image: url(green@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/flat/grey.css",
    "content": "/* iCheck plugin Flat skin, grey\n----------------------------------- */\n.icheckbox_flat-grey,\n.iradio_flat-grey {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(grey.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-grey {\n    background-position: 0 0;\n}\n    .icheckbox_flat-grey.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-grey.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-grey.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-grey {\n    background-position: -88px 0;\n}\n    .iradio_flat-grey.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-grey.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-grey.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-grey,\n    .iradio_flat-grey {\n        background-image: url(grey@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/flat/orange.css",
    "content": "/* iCheck plugin Flat skin, orange\n----------------------------------- */\n.icheckbox_flat-orange,\n.iradio_flat-orange {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(orange.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-orange {\n    background-position: 0 0;\n}\n    .icheckbox_flat-orange.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-orange.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-orange.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-orange {\n    background-position: -88px 0;\n}\n    .iradio_flat-orange.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-orange.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-orange.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-orange,\n    .iradio_flat-orange {\n        background-image: url(orange@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/flat/pink.css",
    "content": "/* iCheck plugin Flat skin, pink\n----------------------------------- */\n.icheckbox_flat-pink,\n.iradio_flat-pink {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(pink.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-pink {\n    background-position: 0 0;\n}\n    .icheckbox_flat-pink.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-pink.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-pink.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-pink {\n    background-position: -88px 0;\n}\n    .iradio_flat-pink.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-pink.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-pink.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-pink,\n    .iradio_flat-pink {\n        background-image: url(pink@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/flat/purple.css",
    "content": "/* iCheck plugin Flat skin, purple\n----------------------------------- */\n.icheckbox_flat-purple,\n.iradio_flat-purple {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(purple.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-purple {\n    background-position: 0 0;\n}\n    .icheckbox_flat-purple.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-purple.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-purple.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-purple {\n    background-position: -88px 0;\n}\n    .iradio_flat-purple.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-purple.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-purple.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-purple,\n    .iradio_flat-purple {\n        background-image: url(purple@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/flat/red.css",
    "content": "/* iCheck plugin Flat skin, red\n----------------------------------- */\n.icheckbox_flat-red,\n.iradio_flat-red {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(red.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-red {\n    background-position: 0 0;\n}\n    .icheckbox_flat-red.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-red.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-red.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-red {\n    background-position: -88px 0;\n}\n    .iradio_flat-red.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-red.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-red.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-red,\n    .iradio_flat-red {\n        background-image: url(red@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/flat/yellow.css",
    "content": "/* iCheck plugin Flat skin, yellow\n----------------------------------- */\n.icheckbox_flat-yellow,\n.iradio_flat-yellow {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 20px;\n    height: 20px;\n    background: url(yellow.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_flat-yellow {\n    background-position: 0 0;\n}\n    .icheckbox_flat-yellow.checked {\n        background-position: -22px 0;\n    }\n    .icheckbox_flat-yellow.disabled {\n        background-position: -44px 0;\n        cursor: default;\n    }\n    .icheckbox_flat-yellow.checked.disabled {\n        background-position: -66px 0;\n    }\n\n.iradio_flat-yellow {\n    background-position: -88px 0;\n}\n    .iradio_flat-yellow.checked {\n        background-position: -110px 0;\n    }\n    .iradio_flat-yellow.disabled {\n        background-position: -132px 0;\n        cursor: default;\n    }\n    .iradio_flat-yellow.checked.disabled {\n        background-position: -154px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_flat-yellow,\n    .iradio_flat-yellow {\n        background-image: url(yellow@2x.png);\n        -webkit-background-size: 176px 22px;\n        background-size: 176px 22px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/futurico/futurico.css",
    "content": "/* iCheck plugin Futurico skin\n----------------------------------- */\n.icheckbox_futurico,\n.iradio_futurico {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 16px;\n    height: 17px;\n    background: url(futurico.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_futurico {\n    background-position: 0 0;\n}\n    .icheckbox_futurico.checked {\n        background-position: -18px 0;\n    }\n    .icheckbox_futurico.disabled {\n        background-position: -36px 0;\n        cursor: default;\n    }\n    .icheckbox_futurico.checked.disabled {\n        background-position: -54px 0;\n    }\n\n.iradio_futurico {\n    background-position: -72px 0;\n}\n    .iradio_futurico.checked {\n        background-position: -90px 0;\n    }\n    .iradio_futurico.disabled {\n        background-position: -108px 0;\n        cursor: default;\n    }\n    .iradio_futurico.checked.disabled {\n        background-position: -126px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_futurico,\n    .iradio_futurico {\n        background-image: url(futurico@2x.png);\n        -webkit-background-size: 144px 19px;\n        background-size: 144px 19px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/line/_all.css",
    "content": "/* iCheck plugin Line skin\n----------------------------------- */\n.icheckbox_line,\n.iradio_line {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #000;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line .icheck_line-icon,\n    .iradio_line .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line.hover,\n    .icheckbox_line.checked.hover,\n    .iradio_line.hover {\n        background: #444;\n    }\n    .icheckbox_line.checked,\n    .iradio_line.checked {\n        background: #000;\n    }\n        .icheckbox_line.checked .icheck_line-icon,\n        .iradio_line.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line.disabled,\n    .iradio_line.disabled {\n        background: #ccc;\n        cursor: default;\n    }\n        .icheckbox_line.disabled .icheck_line-icon,\n        .iradio_line.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line.checked.disabled,\n    .iradio_line.checked.disabled {\n        background: #ccc;\n    }\n        .icheckbox_line.checked.disabled .icheck_line-icon,\n        .iradio_line.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line .icheck_line-icon,\n    .iradio_line .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}\n\n/* red */\n.icheckbox_line-red,\n.iradio_line-red {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #e56c69;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-red .icheck_line-icon,\n    .iradio_line-red .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-red.hover,\n    .icheckbox_line-red.checked.hover,\n    .iradio_line-red.hover {\n        background: #E98582;\n    }\n    .icheckbox_line-red.checked,\n    .iradio_line-red.checked {\n        background: #e56c69;\n    }\n        .icheckbox_line-red.checked .icheck_line-icon,\n        .iradio_line-red.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-red.disabled,\n    .iradio_line-red.disabled {\n        background: #F7D3D2;\n        cursor: default;\n    }\n        .icheckbox_line-red.disabled .icheck_line-icon,\n        .iradio_line-red.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-red.checked.disabled,\n    .iradio_line-red.checked.disabled {\n        background: #F7D3D2;\n    }\n        .icheckbox_line-red.checked.disabled .icheck_line-icon,\n        .iradio_line-red.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-red .icheck_line-icon,\n    .iradio_line-red .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}\n\n/* green */\n.icheckbox_line-green,\n.iradio_line-green {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #1b7e5a;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-green .icheck_line-icon,\n    .iradio_line-green .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-green.hover,\n    .icheckbox_line-green.checked.hover,\n    .iradio_line-green.hover {\n        background: #24AA7A;\n    }\n    .icheckbox_line-green.checked,\n    .iradio_line-green.checked {\n        background: #1b7e5a;\n    }\n        .icheckbox_line-green.checked .icheck_line-icon,\n        .iradio_line-green.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-green.disabled,\n    .iradio_line-green.disabled {\n        background: #89E6C4;\n        cursor: default;\n    }\n        .icheckbox_line-green.disabled .icheck_line-icon,\n        .iradio_line-green.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-green.checked.disabled,\n    .iradio_line-green.checked.disabled {\n        background: #89E6C4;\n    }\n        .icheckbox_line-green.checked.disabled .icheck_line-icon,\n        .iradio_line-green.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-green .icheck_line-icon,\n    .iradio_line-green .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}\n\n/* blue */\n.icheckbox_line-blue,\n.iradio_line-blue {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #2489c5;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-blue .icheck_line-icon,\n    .iradio_line-blue .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-blue.hover,\n    .icheckbox_line-blue.checked.hover,\n    .iradio_line-blue.hover {\n        background: #3DA0DB;\n    }\n    .icheckbox_line-blue.checked,\n    .iradio_line-blue.checked {\n        background: #2489c5;\n    }\n        .icheckbox_line-blue.checked .icheck_line-icon,\n        .iradio_line-blue.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-blue.disabled,\n    .iradio_line-blue.disabled {\n        background: #ADD7F0;\n        cursor: default;\n    }\n        .icheckbox_line-blue.disabled .icheck_line-icon,\n        .iradio_line-blue.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-blue.checked.disabled,\n    .iradio_line-blue.checked.disabled {\n        background: #ADD7F0;\n    }\n        .icheckbox_line-blue.checked.disabled .icheck_line-icon,\n        .iradio_line-blue.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-blue .icheck_line-icon,\n    .iradio_line-blue .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}\n\n/* aero */\n.icheckbox_line-aero,\n.iradio_line-aero {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #9cc2cb;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-aero .icheck_line-icon,\n    .iradio_line-aero .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-aero.hover,\n    .icheckbox_line-aero.checked.hover,\n    .iradio_line-aero.hover {\n        background: #B5D1D8;\n    }\n    .icheckbox_line-aero.checked,\n    .iradio_line-aero.checked {\n        background: #9cc2cb;\n    }\n        .icheckbox_line-aero.checked .icheck_line-icon,\n        .iradio_line-aero.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-aero.disabled,\n    .iradio_line-aero.disabled {\n        background: #D2E4E8;\n        cursor: default;\n    }\n        .icheckbox_line-aero.disabled .icheck_line-icon,\n        .iradio_line-aero.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-aero.checked.disabled,\n    .iradio_line-aero.checked.disabled {\n        background: #D2E4E8;\n    }\n        .icheckbox_line-aero.checked.disabled .icheck_line-icon,\n        .iradio_line-aero.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-aero .icheck_line-icon,\n    .iradio_line-aero .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}\n\n/* grey */\n.icheckbox_line-grey,\n.iradio_line-grey {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #73716e;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-grey .icheck_line-icon,\n    .iradio_line-grey .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-grey.hover,\n    .icheckbox_line-grey.checked.hover,\n    .iradio_line-grey.hover {\n        background: #8B8986;\n    }\n    .icheckbox_line-grey.checked,\n    .iradio_line-grey.checked {\n        background: #73716e;\n    }\n        .icheckbox_line-grey.checked .icheck_line-icon,\n        .iradio_line-grey.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-grey.disabled,\n    .iradio_line-grey.disabled {\n        background: #D5D4D3;\n        cursor: default;\n    }\n        .icheckbox_line-grey.disabled .icheck_line-icon,\n        .iradio_line-grey.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-grey.checked.disabled,\n    .iradio_line-grey.checked.disabled {\n        background: #D5D4D3;\n    }\n        .icheckbox_line-grey.checked.disabled .icheck_line-icon,\n        .iradio_line-grey.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-grey .icheck_line-icon,\n    .iradio_line-grey .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}\n\n/* orange */\n.icheckbox_line-orange,\n.iradio_line-orange {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #f70;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-orange .icheck_line-icon,\n    .iradio_line-orange .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-orange.hover,\n    .icheckbox_line-orange.checked.hover,\n    .iradio_line-orange.hover {\n        background: #FF9233;\n    }\n    .icheckbox_line-orange.checked,\n    .iradio_line-orange.checked {\n        background: #f70;\n    }\n        .icheckbox_line-orange.checked .icheck_line-icon,\n        .iradio_line-orange.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-orange.disabled,\n    .iradio_line-orange.disabled {\n        background: #FFD6B3;\n        cursor: default;\n    }\n        .icheckbox_line-orange.disabled .icheck_line-icon,\n        .iradio_line-orange.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-orange.checked.disabled,\n    .iradio_line-orange.checked.disabled {\n        background: #FFD6B3;\n    }\n        .icheckbox_line-orange.checked.disabled .icheck_line-icon,\n        .iradio_line-orange.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-orange .icheck_line-icon,\n    .iradio_line-orange .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}\n\n/* yellow */\n.icheckbox_line-yellow,\n.iradio_line-yellow {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #FFC414;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-yellow .icheck_line-icon,\n    .iradio_line-yellow .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-yellow.hover,\n    .icheckbox_line-yellow.checked.hover,\n    .iradio_line-yellow.hover {\n        background: #FFD34F;\n    }\n    .icheckbox_line-yellow.checked,\n    .iradio_line-yellow.checked {\n        background: #FFC414;\n    }\n        .icheckbox_line-yellow.checked .icheck_line-icon,\n        .iradio_line-yellow.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-yellow.disabled,\n    .iradio_line-yellow.disabled {\n        background: #FFE495;\n        cursor: default;\n    }\n        .icheckbox_line-yellow.disabled .icheck_line-icon,\n        .iradio_line-yellow.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-yellow.checked.disabled,\n    .iradio_line-yellow.checked.disabled {\n        background: #FFE495;\n    }\n        .icheckbox_line-yellow.checked.disabled .icheck_line-icon,\n        .iradio_line-yellow.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-yellow .icheck_line-icon,\n    .iradio_line-yellow .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}\n\n/* pink */\n.icheckbox_line-pink,\n.iradio_line-pink {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #a77a94;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-pink .icheck_line-icon,\n    .iradio_line-pink .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-pink.hover,\n    .icheckbox_line-pink.checked.hover,\n    .iradio_line-pink.hover {\n        background: #B995A9;\n    }\n    .icheckbox_line-pink.checked,\n    .iradio_line-pink.checked {\n        background: #a77a94;\n    }\n        .icheckbox_line-pink.checked .icheck_line-icon,\n        .iradio_line-pink.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-pink.disabled,\n    .iradio_line-pink.disabled {\n        background: #E0D0DA;\n        cursor: default;\n    }\n        .icheckbox_line-pink.disabled .icheck_line-icon,\n        .iradio_line-pink.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-pink.checked.disabled,\n    .iradio_line-pink.checked.disabled {\n        background: #E0D0DA;\n    }\n        .icheckbox_line-pink.checked.disabled .icheck_line-icon,\n        .iradio_line-pink.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-pink .icheck_line-icon,\n    .iradio_line-pink .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}\n\n/* purple */\n.icheckbox_line-purple,\n.iradio_line-purple {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #6a5a8c;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-purple .icheck_line-icon,\n    .iradio_line-purple .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-purple.hover,\n    .icheckbox_line-purple.checked.hover,\n    .iradio_line-purple.hover {\n        background: #8677A7;\n    }\n    .icheckbox_line-purple.checked,\n    .iradio_line-purple.checked {\n        background: #6a5a8c;\n    }\n        .icheckbox_line-purple.checked .icheck_line-icon,\n        .iradio_line-purple.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-purple.disabled,\n    .iradio_line-purple.disabled {\n        background: #D2CCDE;\n        cursor: default;\n    }\n        .icheckbox_line-purple.disabled .icheck_line-icon,\n        .iradio_line-purple.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-purple.checked.disabled,\n    .iradio_line-purple.checked.disabled {\n        background: #D2CCDE;\n    }\n        .icheckbox_line-purple.checked.disabled .icheck_line-icon,\n        .iradio_line-purple.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-purple .icheck_line-icon,\n    .iradio_line-purple .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/line/aero.css",
    "content": "/* iCheck plugin Line skin, aero\n----------------------------------- */\n.icheckbox_line-aero,\n.iradio_line-aero {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #9cc2cb;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-aero .icheck_line-icon,\n    .iradio_line-aero .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-aero.hover,\n    .icheckbox_line-aero.checked.hover,\n    .iradio_line-aero.hover {\n        background: #B5D1D8;\n    }\n    .icheckbox_line-aero.checked,\n    .iradio_line-aero.checked {\n        background: #9cc2cb;\n    }\n        .icheckbox_line-aero.checked .icheck_line-icon,\n        .iradio_line-aero.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-aero.disabled,\n    .iradio_line-aero.disabled {\n        background: #D2E4E8;\n        cursor: default;\n    }\n        .icheckbox_line-aero.disabled .icheck_line-icon,\n        .iradio_line-aero.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-aero.checked.disabled,\n    .iradio_line-aero.checked.disabled {\n        background: #D2E4E8;\n    }\n        .icheckbox_line-aero.checked.disabled .icheck_line-icon,\n        .iradio_line-aero.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-aero .icheck_line-icon,\n    .iradio_line-aero .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/line/blue.css",
    "content": "/* iCheck plugin Line skin, blue\n----------------------------------- */\n.icheckbox_line-blue,\n.iradio_line-blue {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #2489c5;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-blue .icheck_line-icon,\n    .iradio_line-blue .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-blue.hover,\n    .icheckbox_line-blue.checked.hover,\n    .iradio_line-blue.hover {\n        background: #3DA0DB;\n    }\n    .icheckbox_line-blue.checked,\n    .iradio_line-blue.checked {\n        background: #2489c5;\n    }\n        .icheckbox_line-blue.checked .icheck_line-icon,\n        .iradio_line-blue.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-blue.disabled,\n    .iradio_line-blue.disabled {\n        background: #ADD7F0;\n        cursor: default;\n    }\n        .icheckbox_line-blue.disabled .icheck_line-icon,\n        .iradio_line-blue.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-blue.checked.disabled,\n    .iradio_line-blue.checked.disabled {\n        background: #ADD7F0;\n    }\n        .icheckbox_line-blue.checked.disabled .icheck_line-icon,\n        .iradio_line-blue.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-blue .icheck_line-icon,\n    .iradio_line-blue .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/line/green.css",
    "content": "/* iCheck plugin Line skin, green\n----------------------------------- */\n.icheckbox_line-green,\n.iradio_line-green {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #1b7e5a;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-green .icheck_line-icon,\n    .iradio_line-green .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-green.hover,\n    .icheckbox_line-green.checked.hover,\n    .iradio_line-green.hover {\n        background: #24AA7A;\n    }\n    .icheckbox_line-green.checked,\n    .iradio_line-green.checked {\n        background: #1b7e5a;\n    }\n        .icheckbox_line-green.checked .icheck_line-icon,\n        .iradio_line-green.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-green.disabled,\n    .iradio_line-green.disabled {\n        background: #89E6C4;\n        cursor: default;\n    }\n        .icheckbox_line-green.disabled .icheck_line-icon,\n        .iradio_line-green.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-green.checked.disabled,\n    .iradio_line-green.checked.disabled {\n        background: #89E6C4;\n    }\n        .icheckbox_line-green.checked.disabled .icheck_line-icon,\n        .iradio_line-green.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-green .icheck_line-icon,\n    .iradio_line-green .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/line/grey.css",
    "content": "/* iCheck plugin Line skin, grey\n----------------------------------- */\n.icheckbox_line-grey,\n.iradio_line-grey {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #73716e;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-grey .icheck_line-icon,\n    .iradio_line-grey .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-grey.hover,\n    .icheckbox_line-grey.checked.hover,\n    .iradio_line-grey.hover {\n        background: #8B8986;\n    }\n    .icheckbox_line-grey.checked,\n    .iradio_line-grey.checked {\n        background: #73716e;\n    }\n        .icheckbox_line-grey.checked .icheck_line-icon,\n        .iradio_line-grey.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-grey.disabled,\n    .iradio_line-grey.disabled {\n        background: #D5D4D3;\n        cursor: default;\n    }\n        .icheckbox_line-grey.disabled .icheck_line-icon,\n        .iradio_line-grey.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-grey.checked.disabled,\n    .iradio_line-grey.checked.disabled {\n        background: #D5D4D3;\n    }\n        .icheckbox_line-grey.checked.disabled .icheck_line-icon,\n        .iradio_line-grey.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-grey .icheck_line-icon,\n    .iradio_line-grey .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/line/line.css",
    "content": "/* iCheck plugin Line skin, black\n----------------------------------- */\n.icheckbox_line,\n.iradio_line {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #000;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line .icheck_line-icon,\n    .iradio_line .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line.hover,\n    .icheckbox_line.checked.hover,\n    .iradio_line.hover {\n        background: #444;\n    }\n    .icheckbox_line.checked,\n    .iradio_line.checked {\n        background: #000;\n    }\n        .icheckbox_line.checked .icheck_line-icon,\n        .iradio_line.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line.disabled,\n    .iradio_line.disabled {\n        background: #ccc;\n        cursor: default;\n    }\n        .icheckbox_line.disabled .icheck_line-icon,\n        .iradio_line.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line.checked.disabled,\n    .iradio_line.checked.disabled {\n        background: #ccc;\n    }\n        .icheckbox_line.checked.disabled .icheck_line-icon,\n        .iradio_line.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line .icheck_line-icon,\n    .iradio_line .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/line/orange.css",
    "content": "/* iCheck plugin Line skin, orange\n----------------------------------- */\n.icheckbox_line-orange,\n.iradio_line-orange {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #f70;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-orange .icheck_line-icon,\n    .iradio_line-orange .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-orange.hover,\n    .icheckbox_line-orange.checked.hover,\n    .iradio_line-orange.hover {\n        background: #FF9233;\n    }\n    .icheckbox_line-orange.checked,\n    .iradio_line-orange.checked {\n        background: #f70;\n    }\n        .icheckbox_line-orange.checked .icheck_line-icon,\n        .iradio_line-orange.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-orange.disabled,\n    .iradio_line-orange.disabled {\n        background: #FFD6B3;\n        cursor: default;\n    }\n        .icheckbox_line-orange.disabled .icheck_line-icon,\n        .iradio_line-orange.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-orange.checked.disabled,\n    .iradio_line-orange.checked.disabled {\n        background: #FFD6B3;\n    }\n        .icheckbox_line-orange.checked.disabled .icheck_line-icon,\n        .iradio_line-orange.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-orange .icheck_line-icon,\n    .iradio_line-orange .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/line/pink.css",
    "content": "/* iCheck plugin Line skin, pink\n----------------------------------- */\n.icheckbox_line-pink,\n.iradio_line-pink {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #a77a94;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-pink .icheck_line-icon,\n    .iradio_line-pink .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-pink.hover,\n    .icheckbox_line-pink.checked.hover,\n    .iradio_line-pink.hover {\n        background: #B995A9;\n    }\n    .icheckbox_line-pink.checked,\n    .iradio_line-pink.checked {\n        background: #a77a94;\n    }\n        .icheckbox_line-pink.checked .icheck_line-icon,\n        .iradio_line-pink.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-pink.disabled,\n    .iradio_line-pink.disabled {\n        background: #E0D0DA;\n        cursor: default;\n    }\n        .icheckbox_line-pink.disabled .icheck_line-icon,\n        .iradio_line-pink.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-pink.checked.disabled,\n    .iradio_line-pink.checked.disabled {\n        background: #E0D0DA;\n    }\n        .icheckbox_line-pink.checked.disabled .icheck_line-icon,\n        .iradio_line-pink.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-pink .icheck_line-icon,\n    .iradio_line-pink .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/line/purple.css",
    "content": "/* iCheck plugin Line skin, purple\n----------------------------------- */\n.icheckbox_line-purple,\n.iradio_line-purple {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #6a5a8c;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-purple .icheck_line-icon,\n    .iradio_line-purple .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-purple.hover,\n    .icheckbox_line-purple.checked.hover,\n    .iradio_line-purple.hover {\n        background: #8677A7;\n    }\n    .icheckbox_line-purple.checked,\n    .iradio_line-purple.checked {\n        background: #6a5a8c;\n    }\n        .icheckbox_line-purple.checked .icheck_line-icon,\n        .iradio_line-purple.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-purple.disabled,\n    .iradio_line-purple.disabled {\n        background: #D2CCDE;\n        cursor: default;\n    }\n        .icheckbox_line-purple.disabled .icheck_line-icon,\n        .iradio_line-purple.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-purple.checked.disabled,\n    .iradio_line-purple.checked.disabled {\n        background: #D2CCDE;\n    }\n        .icheckbox_line-purple.checked.disabled .icheck_line-icon,\n        .iradio_line-purple.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-purple .icheck_line-icon,\n    .iradio_line-purple .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/line/red.css",
    "content": "/* iCheck plugin Line skin, red\n----------------------------------- */\n.icheckbox_line-red,\n.iradio_line-red {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #e56c69;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-red .icheck_line-icon,\n    .iradio_line-red .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-red.hover,\n    .icheckbox_line-red.checked.hover,\n    .iradio_line-red.hover {\n        background: #E98582;\n    }\n    .icheckbox_line-red.checked,\n    .iradio_line-red.checked {\n        background: #e56c69;\n    }\n        .icheckbox_line-red.checked .icheck_line-icon,\n        .iradio_line-red.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-red.disabled,\n    .iradio_line-red.disabled {\n        background: #F7D3D2;\n        cursor: default;\n    }\n        .icheckbox_line-red.disabled .icheck_line-icon,\n        .iradio_line-red.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-red.checked.disabled,\n    .iradio_line-red.checked.disabled {\n        background: #F7D3D2;\n    }\n        .icheckbox_line-red.checked.disabled .icheck_line-icon,\n        .iradio_line-red.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-red .icheck_line-icon,\n    .iradio_line-red .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/line/yellow.css",
    "content": "/* iCheck plugin Line skin, yellow\n----------------------------------- */\n.icheckbox_line-yellow,\n.iradio_line-yellow {\n    position: relative;\n    display: block;\n    margin: 0;\n    padding: 5px 15px 5px 38px;\n    font-size: 13px;\n    line-height: 17px;\n    color: #fff;\n    background: #FFC414;\n    border: none;\n    -webkit-border-radius: 3px;\n    -moz-border-radius: 3px;\n    border-radius: 3px;\n    cursor: pointer;\n}\n    .icheckbox_line-yellow .icheck_line-icon,\n    .iradio_line-yellow .icheck_line-icon {\n        position: absolute;\n        top: 50%;\n        left: 13px;\n        width: 13px;\n        height: 11px;\n        margin: -5px 0 0 0;\n        padding: 0;\n        overflow: hidden;\n        background: url(line.png) no-repeat;\n        border: none;\n    }\n    .icheckbox_line-yellow.hover,\n    .icheckbox_line-yellow.checked.hover,\n    .iradio_line-yellow.hover {\n        background: #FFD34F;\n    }\n    .icheckbox_line-yellow.checked,\n    .iradio_line-yellow.checked {\n        background: #FFC414;\n    }\n        .icheckbox_line-yellow.checked .icheck_line-icon,\n        .iradio_line-yellow.checked .icheck_line-icon {\n            background-position: -15px 0;\n        }\n    .icheckbox_line-yellow.disabled,\n    .iradio_line-yellow.disabled {\n        background: #FFE495;\n        cursor: default;\n    }\n        .icheckbox_line-yellow.disabled .icheck_line-icon,\n        .iradio_line-yellow.disabled .icheck_line-icon {\n            background-position: -30px 0;\n        }\n    .icheckbox_line-yellow.checked.disabled,\n    .iradio_line-yellow.checked.disabled {\n        background: #FFE495;\n    }\n        .icheckbox_line-yellow.checked.disabled .icheck_line-icon,\n        .iradio_line-yellow.checked.disabled .icheck_line-icon {\n            background-position: -45px 0;\n        }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_line-yellow .icheck_line-icon,\n    .iradio_line-yellow .icheck_line-icon {\n        background-image: url(line@2x.png);\n        -webkit-background-size: 60px 13px;\n        background-size: 60px 13px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/minimal/_all.css",
    "content": "/* red */\n.icheckbox_minimal-red,\n.iradio_minimal-red {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(red.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-red {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-red.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-red.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-red.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-red.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-red {\n    background-position: -100px 0;\n}\n    .iradio_minimal-red.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-red.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-red.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-red.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-red,\n    .iradio_minimal-red {\n        background-image: url(red@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}\n\n/* green */\n.icheckbox_minimal-green,\n.iradio_minimal-green {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(green.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-green {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-green.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-green.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-green.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-green.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-green {\n    background-position: -100px 0;\n}\n    .iradio_minimal-green.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-green.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-green.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-green.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-green,\n    .iradio_minimal-green {\n        background-image: url(green@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}\n\n/* blue */\n.icheckbox_minimal-blue,\n.iradio_minimal-blue {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(blue.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-blue {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-blue.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-blue.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-blue.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-blue.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-blue {\n    background-position: -100px 0;\n}\n    .iradio_minimal-blue.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-blue.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-blue.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-blue.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-blue,\n    .iradio_minimal-blue {\n        background-image: url(blue@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}\n\n/* aero */\n.icheckbox_minimal-aero,\n.iradio_minimal-aero {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(aero.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-aero {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-aero.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-aero.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-aero.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-aero.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-aero {\n    background-position: -100px 0;\n}\n    .iradio_minimal-aero.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-aero.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-aero.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-aero.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-aero,\n    .iradio_minimal-aero {\n        background-image: url(aero@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}\n\n/* grey */\n.icheckbox_minimal-grey,\n.iradio_minimal-grey {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(grey.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-grey {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-grey.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-grey.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-grey.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-grey.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-grey {\n    background-position: -100px 0;\n}\n    .iradio_minimal-grey.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-grey.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-grey.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-grey.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-grey,\n    .iradio_minimal-grey {\n        background-image: url(grey@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}\n\n/* orange */\n.icheckbox_minimal-orange,\n.iradio_minimal-orange {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(orange.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-orange {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-orange.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-orange.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-orange.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-orange.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-orange {\n    background-position: -100px 0;\n}\n    .iradio_minimal-orange.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-orange.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-orange.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-orange.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-orange,\n    .iradio_minimal-orange {\n        background-image: url(orange@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}\n\n/* yellow */\n.icheckbox_minimal-yellow,\n.iradio_minimal-yellow {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(yellow.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-yellow {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-yellow.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-yellow.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-yellow.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-yellow.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-yellow {\n    background-position: -100px 0;\n}\n    .iradio_minimal-yellow.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-yellow.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-yellow.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-yellow.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-yellow,\n    .iradio_minimal-yellow {\n        background-image: url(yellow@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}\n\n/* pink */\n.icheckbox_minimal-pink,\n.iradio_minimal-pink {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(pink.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-pink {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-pink.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-pink.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-pink.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-pink.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-pink {\n    background-position: -100px 0;\n}\n    .iradio_minimal-pink.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-pink.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-pink.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-pink.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-pink,\n    .iradio_minimal-pink {\n        background-image: url(pink@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}\n\n/* purple */\n.icheckbox_minimal-purple,\n.iradio_minimal-purple {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(purple.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-purple {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-purple.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-purple.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-purple.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-purple.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-purple {\n    background-position: -100px 0;\n}\n    .iradio_minimal-purple.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-purple.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-purple.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-purple.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-purple,\n    .iradio_minimal-purple {\n        background-image: url(purple@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/minimal/aero.css",
    "content": "/* iCheck plugin Minimal skin, aero\n----------------------------------- */\n.icheckbox_minimal-aero,\n.iradio_minimal-aero {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(aero.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-aero {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-aero.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-aero.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-aero.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-aero.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-aero {\n    background-position: -100px 0;\n}\n    .iradio_minimal-aero.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-aero.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-aero.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-aero.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-aero,\n    .iradio_minimal-aero {\n        background-image: url(aero@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/minimal/blue.css",
    "content": "/* iCheck plugin Minimal skin, blue\n----------------------------------- */\n.icheckbox_minimal-blue,\n.iradio_minimal-blue {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(blue.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-blue {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-blue.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-blue.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-blue.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-blue.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-blue {\n    background-position: -100px 0;\n}\n    .iradio_minimal-blue.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-blue.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-blue.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-blue.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-blue,\n    .iradio_minimal-blue {\n        background-image: url(blue@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/minimal/green.css",
    "content": "/* iCheck plugin Minimal skin, green\n----------------------------------- */\n.icheckbox_minimal-green,\n.iradio_minimal-green {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(green.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-green {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-green.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-green.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-green.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-green.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-green {\n    background-position: -100px 0;\n}\n    .iradio_minimal-green.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-green.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-green.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-green.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-green,\n    .iradio_minimal-green {\n        background-image: url(green@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/minimal/grey.css",
    "content": "/* iCheck plugin Minimal skin, grey\n----------------------------------- */\n.icheckbox_minimal-grey,\n.iradio_minimal-grey {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(grey.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-grey {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-grey.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-grey.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-grey.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-grey.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-grey {\n    background-position: -100px 0;\n}\n    .iradio_minimal-grey.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-grey.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-grey.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-grey.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-grey,\n    .iradio_minimal-grey {\n        background-image: url(grey@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/minimal/minimal.css",
    "content": "/* iCheck plugin Minimal skin, black\n----------------------------------- */\n.icheckbox_minimal,\n.iradio_minimal {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(minimal.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal {\n    background-position: 0 0;\n}\n    .icheckbox_minimal.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal {\n    background-position: -100px 0;\n}\n    .iradio_minimal.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal,\n    .iradio_minimal {\n        background-image: url(minimal@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/minimal/orange.css",
    "content": "/* iCheck plugin Minimal skin, orange\n----------------------------------- */\n.icheckbox_minimal-orange,\n.iradio_minimal-orange {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(orange.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-orange {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-orange.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-orange.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-orange.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-orange.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-orange {\n    background-position: -100px 0;\n}\n    .iradio_minimal-orange.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-orange.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-orange.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-orange.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-orange,\n    .iradio_minimal-orange {\n        background-image: url(orange@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/minimal/pink.css",
    "content": "/* iCheck plugin Minimal skin, pink\n----------------------------------- */\n.icheckbox_minimal-pink,\n.iradio_minimal-pink {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(pink.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-pink {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-pink.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-pink.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-pink.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-pink.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-pink {\n    background-position: -100px 0;\n}\n    .iradio_minimal-pink.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-pink.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-pink.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-pink.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-pink,\n    .iradio_minimal-pink {\n        background-image: url(pink@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/minimal/purple.css",
    "content": "/* iCheck plugin Minimal skin, purple\n----------------------------------- */\n.icheckbox_minimal-purple,\n.iradio_minimal-purple {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(purple.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-purple {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-purple.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-purple.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-purple.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-purple.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-purple {\n    background-position: -100px 0;\n}\n    .iradio_minimal-purple.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-purple.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-purple.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-purple.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-purple,\n    .iradio_minimal-purple {\n        background-image: url(purple@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/minimal/red.css",
    "content": "/* iCheck plugin Minimal skin, red\n----------------------------------- */\n.icheckbox_minimal-red,\n.iradio_minimal-red {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(red.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-red {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-red.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-red.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-red.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-red.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-red {\n    background-position: -100px 0;\n}\n    .iradio_minimal-red.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-red.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-red.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-red.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-red,\n    .iradio_minimal-red {\n        background-image: url(red@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/minimal/yellow.css",
    "content": "/* iCheck plugin Minimal skin, yellow\n----------------------------------- */\n.icheckbox_minimal-yellow,\n.iradio_minimal-yellow {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 18px;\n    height: 18px;\n    background: url(yellow.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_minimal-yellow {\n    background-position: 0 0;\n}\n    .icheckbox_minimal-yellow.hover {\n        background-position: -20px 0;\n    }\n    .icheckbox_minimal-yellow.checked {\n        background-position: -40px 0;\n    }\n    .icheckbox_minimal-yellow.disabled {\n        background-position: -60px 0;\n        cursor: default;\n    }\n    .icheckbox_minimal-yellow.checked.disabled {\n        background-position: -80px 0;\n    }\n\n.iradio_minimal-yellow {\n    background-position: -100px 0;\n}\n    .iradio_minimal-yellow.hover {\n        background-position: -120px 0;\n    }\n    .iradio_minimal-yellow.checked {\n        background-position: -140px 0;\n    }\n    .iradio_minimal-yellow.disabled {\n        background-position: -160px 0;\n        cursor: default;\n    }\n    .iradio_minimal-yellow.checked.disabled {\n        background-position: -180px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 1.5),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_minimal-yellow,\n    .iradio_minimal-yellow {\n        background-image: url(yellow@2x.png);\n        -webkit-background-size: 200px 20px;\n        background-size: 200px 20px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/polaris/polaris.css",
    "content": "/* iCheck plugin Polaris skin\n----------------------------------- */\n.icheckbox_polaris,\n.iradio_polaris {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 29px;\n    height: 29px;\n    background: url(polaris.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_polaris {\n    background-position: 0 0;\n}\n    .icheckbox_polaris.hover {\n        background-position: -31px 0;\n    }\n    .icheckbox_polaris.checked {\n        background-position: -62px 0;\n    }\n    .icheckbox_polaris.disabled {\n        background-position: -93px 0;\n        cursor: default;\n    }\n    .icheckbox_polaris.checked.disabled {\n        background-position: -124px 0;\n    }\n\n.iradio_polaris {\n    background-position: -155px 0;\n}\n    .iradio_polaris.hover {\n        background-position: -186px 0;\n    }\n    .iradio_polaris.checked {\n        background-position: -217px 0;\n    }\n    .iradio_polaris.disabled {\n        background-position: -248px 0;\n        cursor: default;\n    }\n    .iradio_polaris.checked.disabled {\n        background-position: -279px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_polaris,\n    .iradio_polaris {\n        background-image: url(polaris@2x.png);\n        -webkit-background-size: 310px 31px;\n        background-size: 310px 31px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/square/_all.css",
    "content": "/* iCheck plugin Square skin\n----------------------------------- */\n.icheckbox_square,\n.iradio_square {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(square.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square {\n    background-position: 0 0;\n}\n    .icheckbox_square.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square {\n    background-position: -120px 0;\n}\n    .iradio_square.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square,\n    .iradio_square {\n        background-image: url(square@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}\n\n/* red */\n.icheckbox_square-red,\n.iradio_square-red {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(red.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-red {\n    background-position: 0 0;\n}\n    .icheckbox_square-red.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-red.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-red.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-red.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-red {\n    background-position: -120px 0;\n}\n    .iradio_square-red.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-red.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-red.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-red.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-red,\n    .iradio_square-red {\n        background-image: url(red@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}\n\n/* green */\n.icheckbox_square-green,\n.iradio_square-green {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(green.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-green {\n    background-position: 0 0;\n}\n    .icheckbox_square-green.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-green.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-green.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-green.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-green {\n    background-position: -120px 0;\n}\n    .iradio_square-green.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-green.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-green.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-green.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-green,\n    .iradio_square-green {\n        background-image: url(green@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}\n\n/* blue */\n.icheckbox_square-blue,\n.iradio_square-blue {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(blue.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-blue {\n    background-position: 0 0;\n}\n    .icheckbox_square-blue.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-blue.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-blue.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-blue.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-blue {\n    background-position: -120px 0;\n}\n    .iradio_square-blue.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-blue.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-blue.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-blue.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-blue,\n    .iradio_square-blue {\n        background-image: url(blue@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}\n\n/* aero */\n.icheckbox_square-aero,\n.iradio_square-aero {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(aero.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-aero {\n    background-position: 0 0;\n}\n    .icheckbox_square-aero.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-aero.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-aero.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-aero.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-aero {\n    background-position: -120px 0;\n}\n    .iradio_square-aero.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-aero.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-aero.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-aero.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-aero,\n    .iradio_square-aero {\n        background-image: url(aero@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}\n\n/* grey */\n.icheckbox_square-grey,\n.iradio_square-grey {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(grey.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-grey {\n    background-position: 0 0;\n}\n    .icheckbox_square-grey.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-grey.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-grey.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-grey.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-grey {\n    background-position: -120px 0;\n}\n    .iradio_square-grey.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-grey.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-grey.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-grey.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-grey,\n    .iradio_square-grey {\n        background-image: url(grey@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}\n\n/* orange */\n.icheckbox_square-orange,\n.iradio_square-orange {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(orange.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-orange {\n    background-position: 0 0;\n}\n    .icheckbox_square-orange.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-orange.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-orange.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-orange.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-orange {\n    background-position: -120px 0;\n}\n    .iradio_square-orange.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-orange.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-orange.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-orange.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-orange,\n    .iradio_square-orange {\n        background-image: url(orange@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}\n\n/* yellow */\n.icheckbox_square-yellow,\n.iradio_square-yellow {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(yellow.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-yellow {\n    background-position: 0 0;\n}\n    .icheckbox_square-yellow.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-yellow.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-yellow.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-yellow.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-yellow {\n    background-position: -120px 0;\n}\n    .iradio_square-yellow.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-yellow.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-yellow.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-yellow.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-yellow,\n    .iradio_square-yellow {\n        background-image: url(yellow@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}\n\n/* pink */\n.icheckbox_square-pink,\n.iradio_square-pink {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(pink.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-pink {\n    background-position: 0 0;\n}\n    .icheckbox_square-pink.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-pink.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-pink.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-pink.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-pink {\n    background-position: -120px 0;\n}\n    .iradio_square-pink.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-pink.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-pink.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-pink.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-pink,\n    .iradio_square-pink {\n        background-image: url(pink@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}\n\n/* purple */\n.icheckbox_square-purple,\n.iradio_square-purple {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(purple.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-purple {\n    background-position: 0 0;\n}\n    .icheckbox_square-purple.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-purple.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-purple.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-purple.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-purple {\n    background-position: -120px 0;\n}\n    .iradio_square-purple.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-purple.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-purple.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-purple.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-purple,\n    .iradio_square-purple {\n        background-image: url(purple@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/square/aero.css",
    "content": "/* iCheck plugin Square skin, aero\n----------------------------------- */\n.icheckbox_square-aero,\n.iradio_square-aero {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(aero.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-aero {\n    background-position: 0 0;\n}\n    .icheckbox_square-aero.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-aero.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-aero.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-aero.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-aero {\n    background-position: -120px 0;\n}\n    .iradio_square-aero.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-aero.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-aero.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-aero.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-aero,\n    .iradio_square-aero {\n        background-image: url(aero@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/square/blue.css",
    "content": "/* iCheck plugin Square skin, blue\n----------------------------------- */\n.icheckbox_square-blue,\n.iradio_square-blue {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(blue.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-blue {\n    background-position: 0 0;\n}\n    .icheckbox_square-blue.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-blue.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-blue.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-blue.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-blue {\n    background-position: -120px 0;\n}\n    .iradio_square-blue.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-blue.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-blue.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-blue.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-blue,\n    .iradio_square-blue {\n        background-image: url(blue@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/square/green.css",
    "content": "/* iCheck plugin Square skin, green\n----------------------------------- */\n.icheckbox_square-green,\n.iradio_square-green {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(green.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-green {\n    background-position: 0 0;\n}\n    .icheckbox_square-green.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-green.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-green.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-green.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-green {\n    background-position: -120px 0;\n}\n    .iradio_square-green.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-green.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-green.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-green.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-green,\n    .iradio_square-green {\n        background-image: url(green@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/square/grey.css",
    "content": "/* iCheck plugin Square skin, grey\n----------------------------------- */\n.icheckbox_square-grey,\n.iradio_square-grey {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(grey.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-grey {\n    background-position: 0 0;\n}\n    .icheckbox_square-grey.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-grey.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-grey.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-grey.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-grey {\n    background-position: -120px 0;\n}\n    .iradio_square-grey.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-grey.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-grey.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-grey.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-grey,\n    .iradio_square-grey {\n        background-image: url(grey@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/square/orange.css",
    "content": "/* iCheck plugin Square skin, orange\n----------------------------------- */\n.icheckbox_square-orange,\n.iradio_square-orange {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(orange.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-orange {\n    background-position: 0 0;\n}\n    .icheckbox_square-orange.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-orange.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-orange.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-orange.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-orange {\n    background-position: -120px 0;\n}\n    .iradio_square-orange.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-orange.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-orange.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-orange.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-orange,\n    .iradio_square-orange {\n        background-image: url(orange@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/square/pink.css",
    "content": "/* iCheck plugin Square skin, pink\n----------------------------------- */\n.icheckbox_square-pink,\n.iradio_square-pink {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(pink.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-pink {\n    background-position: 0 0;\n}\n    .icheckbox_square-pink.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-pink.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-pink.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-pink.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-pink {\n    background-position: -120px 0;\n}\n    .iradio_square-pink.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-pink.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-pink.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-pink.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-pink,\n    .iradio_square-pink {\n        background-image: url(pink@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/square/purple.css",
    "content": "/* iCheck plugin Square skin, purple\n----------------------------------- */\n.icheckbox_square-purple,\n.iradio_square-purple {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(purple.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-purple {\n    background-position: 0 0;\n}\n    .icheckbox_square-purple.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-purple.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-purple.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-purple.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-purple {\n    background-position: -120px 0;\n}\n    .iradio_square-purple.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-purple.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-purple.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-purple.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-purple,\n    .iradio_square-purple {\n        background-image: url(purple@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/square/red.css",
    "content": "/* iCheck plugin Square skin, red\n----------------------------------- */\n.icheckbox_square-red,\n.iradio_square-red {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(red.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-red {\n    background-position: 0 0;\n}\n    .icheckbox_square-red.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-red.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-red.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-red.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-red {\n    background-position: -120px 0;\n}\n    .iradio_square-red.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-red.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-red.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-red.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-red,\n    .iradio_square-red {\n        background-image: url(red@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/square/square.css",
    "content": "/* iCheck plugin Square skin, black\n----------------------------------- */\n.icheckbox_square,\n.iradio_square {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(square.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square {\n    background-position: 0 0;\n}\n    .icheckbox_square.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square {\n    background-position: -120px 0;\n}\n    .iradio_square.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square,\n    .iradio_square {\n        background-image: url(square@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/iCheck/square/yellow.css",
    "content": "/* iCheck plugin Square skin, yellow\n----------------------------------- */\n.icheckbox_square-yellow,\n.iradio_square-yellow {\n    display: inline-block;\n    *display: inline;\n    vertical-align: middle;\n    margin: 0;\n    padding: 0;\n    width: 22px;\n    height: 22px;\n    background: url(yellow.png) no-repeat;\n    border: none;\n    cursor: pointer;\n}\n\n.icheckbox_square-yellow {\n    background-position: 0 0;\n}\n    .icheckbox_square-yellow.hover {\n        background-position: -24px 0;\n    }\n    .icheckbox_square-yellow.checked {\n        background-position: -48px 0;\n    }\n    .icheckbox_square-yellow.disabled {\n        background-position: -72px 0;\n        cursor: default;\n    }\n    .icheckbox_square-yellow.checked.disabled {\n        background-position: -96px 0;\n    }\n\n.iradio_square-yellow {\n    background-position: -120px 0;\n}\n    .iradio_square-yellow.hover {\n        background-position: -144px 0;\n    }\n    .iradio_square-yellow.checked {\n        background-position: -168px 0;\n    }\n    .iradio_square-yellow.disabled {\n        background-position: -192px 0;\n        cursor: default;\n    }\n    .iradio_square-yellow.checked.disabled {\n        background-position: -216px 0;\n    }\n\n/* Retina support */\n@media only screen and (-webkit-min-device-pixel-ratio: 1.5),\n       only screen and (-moz-min-device-pixel-ratio: 1.5),\n       only screen and (-o-min-device-pixel-ratio: 3/2),\n       only screen and (min-device-pixel-ratio: 1.5) {\n    .icheckbox_square-yellow,\n    .iradio_square-yellow {\n        background-image: url(yellow@2x.png);\n        -webkit-background-size: 240px 24px;\n        background-size: 240px 24px;\n    }\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/input-mask/phone-codes/phone-be.json",
    "content": "[\n\t{ \"mask\": \"+32(53)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Aalst (Alost)\" },\n\t{ \"mask\": \"+32(3)###-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Antwerpen (Anvers)\" },\n\t{ \"mask\": \"+32(63)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Arlon\" },\n\t{ \"mask\": \"+32(67)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Ath\" },\n\t{ \"mask\": \"+32(50)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Brugge (Bruges)\" },\n\t{ \"mask\": \"+32(2)###-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Brussel/Bruxelles (Brussels)\" },\n\t{ \"mask\": \"+32(71)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Charleroi\" },\n\t{ \"mask\": \"+32(60)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Chimay\" },\n\t{ \"mask\": \"+32(83)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Ciney\" },\n\t{ \"mask\": \"+32(52)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Dendermonde\" },\n\t{ \"mask\": \"+32(13)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Diest\" },\n\t{ \"mask\": \"+32(82)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Dinant\" },\n\t{ \"mask\": \"+32(86)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Durbuy\" },\n\t{ \"mask\": \"+32(89)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Genk\" },\n\t{ \"mask\": \"+32(9)###-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Gent (Gand)\" },\n\t{ \"mask\": \"+32(11)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Hasselt\" },\n\t{ \"mask\": \"+32(14)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Herentals\" },\n\t{ \"mask\": \"+32(85)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Huy (Hoei)\" },\n\t{ \"mask\": \"+32(64)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"La Louvière\" },\n\t{ \"mask\": \"+32(16)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Leuven (Louvain)\" },\n\t{ \"mask\": \"+32(61)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Libramont\" },\n\t{ \"mask\": \"+32(4)###-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Liège (Luik)\" },\n\t{ \"mask\": \"+32(15)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Mechelen (Malines)\" },\n\t{ \"mask\": \"+32(47#)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Mobile Phones\" },    \n\t{ \"mask\": \"+32(48#)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Mobile Phones\" },    \n\t{ \"mask\": \"+32(49#)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Mobile Phones\" },    \n\t{ \"mask\": \"+32(65)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Mons (Bergen)\" },\n\t{ \"mask\": \"+32(81)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Namur (Namen)\" },\t\n\t{ \"mask\": \"+32(58)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Nieuwpoort (Nieuport)\" },\t\n\t{ \"mask\": \"+32(54)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Ninove\" },\n\t{ \"mask\": \"+32(67)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Nivelles (Nijvel)\" },\n\t{ \"mask\": \"+32(59)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Oostende (Ostende)\" },\n\t{ \"mask\": \"+32(51)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Roeselare (Roulers)\" },\n\t{ \"mask\": \"+32(55)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Ronse\" },\t\n\t{ \"mask\": \"+32(80)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Stavelot\" },\n\t{ \"mask\": \"+32(12)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Tongeren (Tongres)\" },\n\t{ \"mask\": \"+32(69)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Tounai\" },\n\t{ \"mask\": \"+32(14)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Turnhout\" },\n\t{ \"mask\": \"+32(87)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Verviers\" },\n\t{ \"mask\": \"+32(58)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Veurne\" },\n\t{ \"mask\": \"+32(19)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Wareme\" },\n\t{ \"mask\": \"+32(10)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Wavre (Waver)\" },\n\t{ \"mask\": \"+32(50)##-##-##\", \"cc\": \"BE\", \"cd\": \"Belgium\", \"city\": \"Zeebrugge\" }\n]"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/input-mask/phone-codes/phone-codes.json",
    "content": "[\n\t{ \"mask\": \"+247-####\", \"cc\": \"AC\", \"name_en\": \"Ascension\", \"desc_en\": \"\", \"name_ru\": \"Остров Вознесения\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+376-###-###\", \"cc\": \"AD\", \"name_en\": \"Andorra\", \"desc_en\": \"\", \"name_ru\": \"Андорра\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+971-5#-###-####\", \"cc\": \"AE\", \"name_en\": \"United Arab Emirates\", \"desc_en\": \"mobile\", \"name_ru\": \"Объединенные Арабские Эмираты\", \"desc_ru\": \"мобильные\" },\n\t{ \"mask\": \"+971-#-###-####\", \"cc\": \"AE\", \"name_en\": \"United Arab Emirates\", \"desc_en\": \"\", \"name_ru\": \"Объединенные Арабские Эмираты\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+93-##-###-####\", \"cc\": \"AF\", \"name_en\": \"Afghanistan\", \"desc_en\": \"\", \"name_ru\": \"Афганистан\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+1(268)###-####\", \"cc\": \"AG\", \"name_en\": \"Antigua & Barbuda\", \"desc_en\": \"\", \"name_ru\": \"Антигуа и Барбуда\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+1(264)###-####\", \"cc\": \"AI\", \"name_en\": \"Anguilla\", \"desc_en\": \"\", \"name_ru\": \"Ангилья\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+355(###)###-###\", \"cc\": \"AL\", \"name_en\": \"Albania\", \"desc_en\": \"\", \"name_ru\": \"Албания\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+374-##-###-###\", \"cc\": \"AM\", \"name_en\": \"Armenia\", \"desc_en\": \"\", \"name_ru\": \"Армения\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+599-###-####\", \"cc\": \"AN\", \"name_en\": \"Caribbean Netherlands\", \"desc_en\": \"\", \"name_ru\": \"Карибские Нидерланды\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+599-###-####\", \"cc\": \"AN\", \"name_en\": \"Netherlands Antilles\", \"desc_en\": \"\", \"name_ru\": \"Нидерландские Антильские острова\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+599-9###-####\", \"cc\": \"AN\", \"name_en\": \"Netherlands Antilles\", \"desc_en\": \"Curacao\", \"name_ru\": \"Нидерландские Антильские острова\", \"desc_ru\": \"Кюрасао\" },\n\t{ \"mask\": \"+244(###)###-###\", \"cc\": \"AO\", \"name_en\": \"Angola\", \"desc_en\": \"\", \"name_ru\": \"Ангола\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+672-1##-###\", \"cc\": \"AQ\", \"name_en\": \"Australian bases in Antarctica\", \"desc_en\": \"\", \"name_ru\": \"Австралийская антарктическая база\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+54(###)###-####\", \"cc\": \"AR\", \"name_en\": \"Argentina\", \"desc_en\": \"\", \"name_ru\": \"Аргентина\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+1(684)###-####\", \"cc\": \"AS\", \"name_en\": \"American Samoa\", \"desc_en\": \"\", \"name_ru\": \"Американское Самоа\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+43(###)###-####\", \"cc\": \"AT\", \"name_en\": \"Austria\", \"desc_en\": \"\", \"name_ru\": \"Австрия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+61-#-####-####\", \"cc\": \"AU\", \"name_en\": \"Australia\", \"desc_en\": \"\", \"name_ru\": \"Австралия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+297-###-####\", \"cc\": \"AW\", \"name_en\": \"Aruba\", \"desc_en\": \"\", \"name_ru\": \"Аруба\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+994-##-###-##-##\", \"cc\": \"AZ\", \"name_en\": \"Azerbaijan\", \"desc_en\": \"\", \"name_ru\": \"Азербайджан\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+387-##-#####\", \"cc\": \"BA\", \"name_en\": \"Bosnia and Herzegovina\", \"desc_en\": \"\", \"name_ru\": \"Босния и Герцеговина\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+387-##-####\", \"cc\": \"BA\", \"name_en\": \"Bosnia and Herzegovina\", \"desc_en\": \"\", \"name_ru\": \"Босния и Герцеговина\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+1(246)###-####\", \"cc\": \"BB\", \"name_en\": \"Barbados\", \"desc_en\": \"\", \"name_ru\": \"Барбадос\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+880-##-###-###\", \"cc\": \"BD\", \"name_en\": \"Bangladesh\", \"desc_en\": \"\", \"name_ru\": \"Бангладеш\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+32(###)###-###\", \"cc\": \"BE\", \"name_en\": \"Belgium\", \"desc_en\": \"\", \"name_ru\": \"Бельгия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+226-##-##-####\", \"cc\": \"BF\", \"name_en\": \"Burkina Faso\", \"desc_en\": \"\", \"name_ru\": \"Буркина Фасо\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+359(###)###-###\", \"cc\": \"BG\", \"name_en\": \"Bulgaria\", \"desc_en\": \"\", \"name_ru\": \"Болгария\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+973-####-####\", \"cc\": \"BH\", \"name_en\": \"Bahrain\", \"desc_en\": \"\", \"name_ru\": \"Бахрейн\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+257-##-##-####\", \"cc\": \"BI\", \"name_en\": \"Burundi\", \"desc_en\": \"\", \"name_ru\": \"Бурунди\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+229-##-##-####\", \"cc\": \"BJ\", \"name_en\": \"Benin\", \"desc_en\": \"\", \"name_ru\": \"Бенин\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+1(441)###-####\", \"cc\": \"BM\", \"name_en\": \"Bermuda\", \"desc_en\": \"\", \"name_ru\": \"Бермудские острова\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+673-###-####\", \"cc\": \"BN\", \"name_en\": \"Brunei Darussalam\", \"desc_en\": \"\", \"name_ru\": \"Бруней-Даруссалам\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+591-#-###-####\", \"cc\": \"BO\", \"name_en\": \"Bolivia\", \"desc_en\": \"\", \"name_ru\": \"Боливия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+55-##-####[#]-####\", \"cc\": \"BR\", \"name_en\": \"Brazil\", \"desc_en\": \"\", \"name_ru\": \"Бразилия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+1(242)###-####\", \"cc\": \"BS\", \"name_en\": \"Bahamas\", \"desc_en\": \"\", \"name_ru\": \"Багамские Острова\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+975-17-###-###\", \"cc\": \"BT\", \"name_en\": \"Bhutan\", \"desc_en\": \"\", \"name_ru\": \"Бутан\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+975-#-###-###\", \"cc\": \"BT\", \"name_en\": \"Bhutan\", \"desc_en\": \"\", \"name_ru\": \"Бутан\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+267-##-###-###\", \"cc\": \"BW\", \"name_en\": \"Botswana\", \"desc_en\": \"\", \"name_ru\": \"Ботсвана\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+375(##)###-##-##\", \"cc\": \"BY\", \"name_en\": \"Belarus\", \"desc_en\": \"\", \"name_ru\": \"Беларусь (Белоруссия)\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+501-###-####\", \"cc\": \"BZ\", \"name_en\": \"Belize\", \"desc_en\": \"\", \"name_ru\": \"Белиз\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+243(###)###-###\", \"cc\": \"CD\", \"name_en\": \"Dem. Rep. Congo\", \"desc_en\": \"\", \"name_ru\": \"Дем. Респ. Конго (Киншаса)\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+236-##-##-####\", \"cc\": \"CF\", \"name_en\": \"Central African Republic\", \"desc_en\": \"\", \"name_ru\": \"Центральноафриканская Республика\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+242-##-###-####\", \"cc\": \"CG\", \"name_en\": \"Congo (Brazzaville)\", \"desc_en\": \"\", \"name_ru\": \"Конго (Браззавиль)\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+41-##-###-####\", \"cc\": \"CH\", \"name_en\": \"Switzerland\", \"desc_en\": \"\", \"name_ru\": \"Швейцария\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+225-##-###-###\", \"cc\": \"CI\", \"name_en\": \"Cote d’Ivoire (Ivory Coast)\", \"desc_en\": \"\", \"name_ru\": \"Кот-д’Ивуар\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+682-##-###\", \"cc\": \"CK\", \"name_en\": \"Cook Islands\", \"desc_en\": \"\", \"name_ru\": \"Острова Кука\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+56-#-####-####\", \"cc\": \"CL\", \"name_en\": \"Chile\", \"desc_en\": \"\", \"name_ru\": \"Чили\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+237-####-####\", \"cc\": \"CM\", \"name_en\": \"Cameroon\", \"desc_en\": \"\", \"name_ru\": \"Камерун\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+86(###)####-####\", \"cc\": \"CN\", \"name_en\": \"China (PRC)\", \"desc_en\": \"\", \"name_ru\": \"Китайская Н.Р.\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+86(###)####-###\", \"cc\": \"CN\", \"name_en\": \"China (PRC)\", \"desc_en\": \"\", \"name_ru\": \"Китайская Н.Р.\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+86-##-#####-#####\", \"cc\": \"CN\", \"name_en\": \"China (PRC)\", \"desc_en\": \"\", \"name_ru\": \"Китайская Н.Р.\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+57(###)###-####\", \"cc\": \"CO\", \"name_en\": \"Colombia\", \"desc_en\": \"\", \"name_ru\": \"Колумбия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+506-####-####\", \"cc\": \"CR\", \"name_en\": \"Costa Rica\", \"desc_en\": \"\", \"name_ru\": \"Коста-Рика\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+53-#-###-####\", \"cc\": \"CU\", \"name_en\": \"Cuba\", \"desc_en\": \"\", \"name_ru\": \"Куба\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+238(###)##-##\", \"cc\": \"CV\", \"name_en\": \"Cape Verde\", \"desc_en\": \"\", \"name_ru\": \"Кабо-Верде\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+599-###-####\", \"cc\": \"CW\", \"name_en\": \"Curacao\", \"desc_en\": \"\", \"name_ru\": \"Кюрасао\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+357-##-###-###\", \"cc\": \"CY\", \"name_en\": \"Cyprus\", \"desc_en\": \"\", \"name_ru\": \"Кипр\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+420(###)###-###\", \"cc\": \"CZ\", \"name_en\": \"Czech Republic\", \"desc_en\": \"\", \"name_ru\": \"Чехия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+49(####)###-####\", \"cc\": \"DE\", \"name_en\": \"Germany\", \"desc_en\": \"\", \"name_ru\": \"Германия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+49(###)###-####\", \"cc\": \"DE\", \"name_en\": \"Germany\", \"desc_en\": \"\", \"name_ru\": \"Германия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+49(###)##-####\", \"cc\": \"DE\", \"name_en\": \"Germany\", \"desc_en\": \"\", \"name_ru\": \"Германия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+49(###)##-###\", \"cc\": \"DE\", \"name_en\": \"Germany\", \"desc_en\": \"\", \"name_ru\": \"Германия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+49(###)##-##\", \"cc\": \"DE\", \"name_en\": \"Germany\", \"desc_en\": \"\", \"name_ru\": \"Германия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+49-###-###\", \"cc\": \"DE\", \"name_en\": \"Germany\", \"desc_en\": \"\", \"name_ru\": \"Германия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+253-##-##-##-##\", \"cc\": \"DJ\", \"name_en\": \"Djibouti\", \"desc_en\": \"\", \"name_ru\": \"Джибути\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+45-##-##-##-##\", \"cc\": \"DK\", \"name_en\": \"Denmark\", \"desc_en\": \"\", \"name_ru\": \"Дания\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+1(767)###-####\", \"cc\": \"DM\", \"name_en\": \"Dominica\", \"desc_en\": \"\", \"name_ru\": \"Доминика\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+1(809)###-####\", \"cc\": \"DO\", \"name_en\": \"Dominican Republic\", \"desc_en\": \"\", \"name_ru\": \"Доминиканская Республика\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+1(829)###-####\", \"cc\": \"DO\", \"name_en\": \"Dominican Republic\", \"desc_en\": \"\", \"name_ru\": \"Доминиканская Республика\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+1(849)###-####\", \"cc\": \"DO\", \"name_en\": \"Dominican Republic\", \"desc_en\": \"\", \"name_ru\": \"Доминиканская Республика\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+213-##-###-####\", \"cc\": \"DZ\", \"name_en\": \"Algeria\", \"desc_en\": \"\", \"name_ru\": \"Алжир\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+593-##-###-####\", \"cc\": \"EC\", \"name_en\": \"Ecuador \", \"desc_en\": \"mobile\", \"name_ru\": \"Эквадор \", \"desc_ru\": \"мобильные\" },\n\t{ \"mask\": \"+593-#-###-####\", \"cc\": \"EC\", \"name_en\": \"Ecuador\", \"desc_en\": \"\", \"name_ru\": \"Эквадор\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+372-####-####\", \"cc\": \"EE\", \"name_en\": \"Estonia \", \"desc_en\": \"mobile\", \"name_ru\": \"Эстония \", \"desc_ru\": \"мобильные\" },\n\t{ \"mask\": \"+372-###-####\", \"cc\": \"EE\", \"name_en\": \"Estonia\", \"desc_en\": \"\", \"name_ru\": \"Эстония\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+20(###)###-####\", \"cc\": \"EG\", \"name_en\": \"Egypt\", \"desc_en\": \"\", \"name_ru\": \"Египет\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+291-#-###-###\", \"cc\": \"ER\", \"name_en\": \"Eritrea\", \"desc_en\": \"\", \"name_ru\": \"Эритрея\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+34(###)###-###\", \"cc\": \"ES\", \"name_en\": \"Spain\", \"desc_en\": \"\", \"name_ru\": \"Испания\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+251-##-###-####\", \"cc\": \"ET\", \"name_en\": \"Ethiopia\", \"desc_en\": \"\", \"name_ru\": \"Эфиопия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+358(###)###-##-##\", \"cc\": \"FI\", \"name_en\": \"Finland\", \"desc_en\": \"\", \"name_ru\": \"Финляндия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+679-##-#####\", \"cc\": \"FJ\", \"name_en\": \"Fiji\", \"desc_en\": \"\", \"name_ru\": \"Фиджи\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+500-#####\", \"cc\": \"FK\", \"name_en\": \"Falkland Islands\", \"desc_en\": \"\", \"name_ru\": \"Фолклендские острова\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+691-###-####\", \"cc\": \"FM\", \"name_en\": \"F.S. Micronesia\", \"desc_en\": \"\", \"name_ru\": \"Ф.Ш. Микронезии\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+298-###-###\", \"cc\": \"FO\", \"name_en\": \"Faroe Islands\", \"desc_en\": \"\", \"name_ru\": \"Фарерские острова\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+262-#####-####\", \"cc\": \"FR\", \"name_en\": \"Mayotte\", \"desc_en\": \"\", \"name_ru\": \"Майотта\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+33(###)###-###\", \"cc\": \"FR\", \"name_en\": \"France\", \"desc_en\": \"\", \"name_ru\": \"Франция\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+508-##-####\", \"cc\": \"FR\", \"name_en\": \"St Pierre & Miquelon\", \"desc_en\": \"\", \"name_ru\": \"Сен-Пьер и Микелон\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+590(###)###-###\", \"cc\": \"FR\", \"name_en\": \"Guadeloupe\", \"desc_en\": \"\", \"name_ru\": \"Гваделупа\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+241-#-##-##-##\", \"cc\": \"GA\", \"name_en\": \"Gabon\", \"desc_en\": \"\", \"name_ru\": \"Габон\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+1(473)###-####\", \"cc\": \"GD\", \"name_en\": \"Grenada\", \"desc_en\": \"\", \"name_ru\": \"Гренада\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+995(###)###-###\", \"cc\": \"GE\", \"name_en\": \"Rep. of Georgia\", \"desc_en\": \"\", \"name_ru\": \"Грузия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+594-#####-####\", \"cc\": \"GF\", \"name_en\": \"Guiana (French)\", \"desc_en\": \"\", \"name_ru\": \"Фр. Гвиана\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+233(###)###-###\", \"cc\": \"GH\", \"name_en\": \"Ghana\", \"desc_en\": \"\", \"name_ru\": \"Гана\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+350-###-#####\", \"cc\": \"GI\", \"name_en\": \"Gibraltar\", \"desc_en\": \"\", \"name_ru\": \"Гибралтар\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+299-##-##-##\", \"cc\": \"GL\", \"name_en\": \"Greenland\", \"desc_en\": \"\", \"name_ru\": \"Гренландия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+220(###)##-##\", \"cc\": \"GM\", \"name_en\": \"Gambia\", \"desc_en\": \"\", \"name_ru\": \"Гамбия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+224-##-###-###\", \"cc\": \"GN\", \"name_en\": \"Guinea\", \"desc_en\": \"\", \"name_ru\": \"Гвинея\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+240-##-###-####\", \"cc\": \"GQ\", \"name_en\": \"Equatorial Guinea\", \"desc_en\": \"\", \"name_ru\": \"Экваториальная Гвинея\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+30(###)###-####\", \"cc\": \"GR\", \"name_en\": \"Greece\", \"desc_en\": \"\", \"name_ru\": \"Греция\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+502-#-###-####\", \"cc\": \"GT\", \"name_en\": \"Guatemala\", \"desc_en\": \"\", \"name_ru\": \"Гватемала\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+1(671)###-####\", \"cc\": \"GU\", \"name_en\": \"Guam\", \"desc_en\": \"\", \"name_ru\": \"Гуам\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+245-#-######\", \"cc\": \"GW\", \"name_en\": \"Guinea-Bissau\", \"desc_en\": \"\", \"name_ru\": \"Гвинея-Бисау\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+592-###-####\", \"cc\": \"GY\", \"name_en\": \"Guyana\", \"desc_en\": \"\", \"name_ru\": \"Гайана\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+852-####-####\", \"cc\": \"HK\", \"name_en\": \"Hong Kong\", \"desc_en\": \"\", \"name_ru\": \"Гонконг\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+504-####-####\", \"cc\": \"HN\", \"name_en\": \"Honduras\", \"desc_en\": \"\", \"name_ru\": \"Гондурас\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+385-##-###-###\", \"cc\": \"HR\", \"name_en\": \"Croatia\", \"desc_en\": \"\", \"name_ru\": \"Хорватия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+509-##-##-####\", \"cc\": \"HT\", \"name_en\": \"Haiti\", \"desc_en\": \"\", \"name_ru\": \"Гаити\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+36(###)###-###\", \"cc\": \"HU\", \"name_en\": \"Hungary\", \"desc_en\": \"\", \"name_ru\": \"Венгрия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+62(8##)###-####\", \"cc\": \"ID\", \"name_en\": \"Indonesia \", \"desc_en\": \"mobile\", \"name_ru\": \"Индонезия \", \"desc_ru\": \"мобильные\" },\n\t{ \"mask\": \"+62-##-###-##\", \"cc\": \"ID\", \"name_en\": \"Indonesia\", \"desc_en\": \"\", \"name_ru\": \"Индонезия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+62-##-###-###\", \"cc\": \"ID\", \"name_en\": \"Indonesia\", \"desc_en\": \"\", \"name_ru\": \"Индонезия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+62-##-###-####\", \"cc\": \"ID\", \"name_en\": \"Indonesia\", \"desc_en\": \"\", \"name_ru\": \"Индонезия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+62(8##)###-###\", \"cc\": \"ID\", \"name_en\": \"Indonesia \", \"desc_en\": \"mobile\", \"name_ru\": \"Индонезия \", \"desc_ru\": \"мобильные\" },\n\t{ \"mask\": \"+62(8##)###-##-###\", \"cc\": \"ID\", \"name_en\": \"Indonesia \", \"desc_en\": \"mobile\", \"name_ru\": \"Индонезия \", \"desc_ru\": \"мобильные\" },\n\t{ \"mask\": \"+353(###)###-###\", \"cc\": \"IE\", \"name_en\": \"Ireland\", \"desc_en\": \"\", \"name_ru\": \"Ирландия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+972-5#-###-####\", \"cc\": \"IL\", \"name_en\": \"Israel \", \"desc_en\": \"mobile\", \"name_ru\": \"Израиль \", \"desc_ru\": \"мобильные\" },\n\t{ \"mask\": \"+972-#-###-####\", \"cc\": \"IL\", \"name_en\": \"Israel\", \"desc_en\": \"\", \"name_ru\": \"Израиль\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+91(####)###-###\", \"cc\": \"IN\", \"name_en\": \"India\", \"desc_en\": \"\", \"name_ru\": \"Индия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+246-###-####\", \"cc\": \"IO\", \"name_en\": \"Diego Garcia\", \"desc_en\": \"\", \"name_ru\": \"Диего-Гарсия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+964(###)###-####\", \"cc\": \"IQ\", \"name_en\": \"Iraq\", \"desc_en\": \"\", \"name_ru\": \"Ирак\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+98(###)###-####\", \"cc\": \"IR\", \"name_en\": \"Iran\", \"desc_en\": \"\", \"name_ru\": \"Иран\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+354-###-####\", \"cc\": \"IS\", \"name_en\": \"Iceland\", \"desc_en\": \"\", \"name_ru\": \"Исландия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+39(###)####-###\", \"cc\": \"IT\", \"name_en\": \"Italy\", \"desc_en\": \"\", \"name_ru\": \"Италия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+1(876)###-####\", \"cc\": \"JM\", \"name_en\": \"Jamaica\", \"desc_en\": \"\", \"name_ru\": \"Ямайка\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+962-#-####-####\", \"cc\": \"JO\", \"name_en\": \"Jordan\", \"desc_en\": \"\", \"name_ru\": \"Иордания\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+81-##-####-####\", \"cc\": \"JP\", \"name_en\": \"Japan \", \"desc_en\": \"mobile\", \"name_ru\": \"Япония \", \"desc_ru\": \"мобильные\" },\n\t{ \"mask\": \"+81(###)###-###\", \"cc\": \"JP\", \"name_en\": \"Japan\", \"desc_en\": \"\", \"name_ru\": \"Япония\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+254-###-######\", \"cc\": \"KE\", \"name_en\": \"Kenya\", \"desc_en\": \"\", \"name_ru\": \"Кения\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+996(###)###-###\", \"cc\": \"KG\", \"name_en\": \"Kyrgyzstan\", \"desc_en\": \"\", \"name_ru\": \"Киргизия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+855-##-###-###\", \"cc\": \"KH\", \"name_en\": \"Cambodia\", \"desc_en\": \"\", \"name_ru\": \"Камбоджа\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+686-##-###\", \"cc\": \"KI\", \"name_en\": \"Kiribati\", \"desc_en\": \"\", \"name_ru\": \"Кирибати\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+269-##-#####\", \"cc\": \"KM\", \"name_en\": \"Comoros\", \"desc_en\": \"\", \"name_ru\": \"Коморы\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+1(869)###-####\", \"cc\": \"KN\", \"name_en\": \"Saint Kitts & Nevis\", \"desc_en\": \"\", \"name_ru\": \"Сент-Китс и Невис\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+850-191-###-####\", \"cc\": \"KP\", \"name_en\": \"DPR Korea (North) \", \"desc_en\": \"mobile\", \"name_ru\": \"Корейская НДР \", \"desc_ru\": \"мобильные\" },\n\t{ \"mask\": \"+850-##-###-###\", \"cc\": \"KP\", \"name_en\": \"DPR Korea (North)\", \"desc_en\": \"\", \"name_ru\": \"Корейская НДР\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+850-###-####-###\", \"cc\": \"KP\", \"name_en\": \"DPR Korea (North)\", \"desc_en\": \"\", \"name_ru\": \"Корейская НДР\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+850-###-###\", \"cc\": \"KP\", \"name_en\": \"DPR Korea (North)\", \"desc_en\": \"\", \"name_ru\": \"Корейская НДР\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+850-####-####\", \"cc\": \"KP\", \"name_en\": \"DPR Korea (North)\", \"desc_en\": \"\", \"name_ru\": \"Корейская НДР\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+850-####-#############\", \"cc\": \"KP\", \"name_en\": \"DPR Korea (North)\", \"desc_en\": \"\", \"name_ru\": \"Корейская НДР\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+82-##-###-####\", \"cc\": \"KR\", \"name_en\": \"Korea (South)\", \"desc_en\": \"\", \"name_ru\": \"Респ. Корея\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+965-####-####\", \"cc\": \"KW\", \"name_en\": \"Kuwait\", \"desc_en\": \"\", \"name_ru\": \"Кувейт\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+1(345)###-####\", \"cc\": \"KY\", \"name_en\": \"Cayman Islands\", \"desc_en\": \"\", \"name_ru\": \"Каймановы острова\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+7(6##)###-##-##\", \"cc\": \"KZ\", \"name_en\": \"Kazakhstan\", \"desc_en\": \"\", \"name_ru\": \"Казахстан\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+7(7##)###-##-##\", \"cc\": \"KZ\", \"name_en\": \"Kazakhstan\", \"desc_en\": \"\", \"name_ru\": \"Казахстан\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+856(20##)###-###\", \"cc\": \"LA\", \"name_en\": \"Laos \", \"desc_en\": \"mobile\", \"name_ru\": \"Лаос \", \"desc_ru\": \"мобильные\" },\n\t{ \"mask\": \"+856-##-###-###\", \"cc\": \"LA\", \"name_en\": \"Laos\", \"desc_en\": \"\", \"name_ru\": \"Лаос\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+961-##-###-###\", \"cc\": \"LB\", \"name_en\": \"Lebanon \", \"desc_en\": \"mobile\", \"name_ru\": \"Ливан \", \"desc_ru\": \"мобильные\" },\n\t{ \"mask\": \"+961-#-###-###\", \"cc\": \"LB\", \"name_en\": \"Lebanon\", \"desc_en\": \"\", \"name_ru\": \"Ливан\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+1(758)###-####\", \"cc\": \"LC\", \"name_en\": \"Saint Lucia\", \"desc_en\": \"\", \"name_ru\": \"Сент-Люсия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+423(###)###-####\", \"cc\": \"LI\", \"name_en\": \"Liechtenstein\", \"desc_en\": \"\", \"name_ru\": \"Лихтенштейн\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+94-##-###-####\", \"cc\": \"LK\", \"name_en\": \"Sri Lanka\", \"desc_en\": \"\", \"name_ru\": \"Шри-Ланка\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+231-##-###-###\", \"cc\": \"LR\", \"name_en\": \"Liberia\", \"desc_en\": \"\", \"name_ru\": \"Либерия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+266-#-###-####\", \"cc\": \"LS\", \"name_en\": \"Lesotho\", \"desc_en\": \"\", \"name_ru\": \"Лесото\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+370(###)##-###\", \"cc\": \"LT\", \"name_en\": \"Lithuania\", \"desc_en\": \"\", \"name_ru\": \"Литва\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+352(###)###-###\", \"cc\": \"LU\", \"name_en\": \"Luxembourg\", \"desc_en\": \"\", \"name_ru\": \"Люксембург\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+371-##-###-###\", \"cc\": \"LV\", \"name_en\": \"Latvia\", \"desc_en\": \"\", \"name_ru\": \"Латвия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+218-##-###-###\", \"cc\": \"LY\", \"name_en\": \"Libya\", \"desc_en\": \"\", \"name_ru\": \"Ливия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+218-21-###-####\", \"cc\": \"LY\", \"name_en\": \"Libya\", \"desc_en\": \"Tripoli\", \"name_ru\": \"Ливия\", \"desc_ru\": \"Триполи\" },\n\t{ \"mask\": \"+212-##-####-###\", \"cc\": \"MA\", \"name_en\": \"Morocco\", \"desc_en\": \"\", \"name_ru\": \"Марокко\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+377(###)###-###\", \"cc\": \"MC\", \"name_en\": \"Monaco\", \"desc_en\": \"\", \"name_ru\": \"Монако\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+377-##-###-###\", \"cc\": \"MC\", \"name_en\": \"Monaco\", \"desc_en\": \"\", \"name_ru\": \"Монако\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+373-####-####\", \"cc\": \"MD\", \"name_en\": \"Moldova\", \"desc_en\": \"\", \"name_ru\": \"Молдова\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+382-##-###-###\", \"cc\": \"ME\", \"name_en\": \"Montenegro\", \"desc_en\": \"\", \"name_ru\": \"Черногория\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+261-##-##-#####\", \"cc\": \"MG\", \"name_en\": \"Madagascar\", \"desc_en\": \"\", \"name_ru\": \"Мадагаскар\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+692-###-####\", \"cc\": \"MH\", \"name_en\": \"Marshall Islands\", \"desc_en\": \"\", \"name_ru\": \"Маршалловы Острова\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+389-##-###-###\", \"cc\": \"MK\", \"name_en\": \"Republic of Macedonia\", \"desc_en\": \"\", \"name_ru\": \"Респ. Македония\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+223-##-##-####\", \"cc\": \"ML\", \"name_en\": \"Mali\", \"desc_en\": \"\", \"name_ru\": \"Мали\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+95-##-###-###\", \"cc\": \"MM\", \"name_en\": \"Burma (Myanmar)\", \"desc_en\": \"\", \"name_ru\": \"Бирма (Мьянма)\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+95-#-###-###\", \"cc\": \"MM\", \"name_en\": \"Burma (Myanmar)\", \"desc_en\": \"\", \"name_ru\": \"Бирма (Мьянма)\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+95-###-###\", \"cc\": \"MM\", \"name_en\": \"Burma (Myanmar)\", \"desc_en\": \"\", \"name_ru\": \"Бирма (Мьянма)\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+976-##-##-####\", \"cc\": \"MN\", \"name_en\": \"Mongolia\", \"desc_en\": \"\", \"name_ru\": \"Монголия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+853-####-####\", \"cc\": \"MO\", \"name_en\": \"Macau\", \"desc_en\": \"\", \"name_ru\": \"Макао\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+1(670)###-####\", \"cc\": \"MP\", \"name_en\": \"Northern Mariana Islands\", \"desc_en\": \"\", \"name_ru\": \"Северные Марианские острова Сайпан\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+596(###)##-##-##\", \"cc\": \"MQ\", \"name_en\": \"Martinique\", \"desc_en\": \"\", \"name_ru\": \"Мартиника\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+222-##-##-####\", \"cc\": \"MR\", \"name_en\": \"Mauritania\", \"desc_en\": \"\", \"name_ru\": \"Мавритания\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+1(664)###-####\", \"cc\": \"MS\", \"name_en\": \"Montserrat\", \"desc_en\": \"\", \"name_ru\": \"Монтсеррат\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+356-####-####\", \"cc\": \"MT\", \"name_en\": \"Malta\", \"desc_en\": \"\", \"name_ru\": \"Мальта\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+230-###-####\", \"cc\": \"MU\", \"name_en\": \"Mauritius\", \"desc_en\": \"\", \"name_ru\": \"Маврикий\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+960-###-####\", \"cc\": \"MV\", \"name_en\": \"Maldives\", \"desc_en\": \"\", \"name_ru\": \"Мальдивские острова\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+265-1-###-###\", \"cc\": \"MW\", \"name_en\": \"Malawi\", \"desc_en\": \"Telecom Ltd\", \"name_ru\": \"Малави\", \"desc_ru\": \"Telecom Ltd\" },\n\t{ \"mask\": \"+265-#-####-####\", \"cc\": \"MW\", \"name_en\": \"Malawi\", \"desc_en\": \"\", \"name_ru\": \"Малави\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+52(###)###-####\", \"cc\": \"MX\", \"name_en\": \"Mexico\", \"desc_en\": \"\", \"name_ru\": \"Мексика\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+52-##-##-####\", \"cc\": \"MX\", \"name_en\": \"Mexico\", \"desc_en\": \"\", \"name_ru\": \"Мексика\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+60-##-###-####\", \"cc\": \"MY\", \"name_en\": \"Malaysia \", \"desc_en\": \"mobile\", \"name_ru\": \"Малайзия \", \"desc_ru\": \"мобильные\" },\n\t{ \"mask\": \"+60(###)###-###\", \"cc\": \"MY\", \"name_en\": \"Malaysia\", \"desc_en\": \"\", \"name_ru\": \"Малайзия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+60-##-###-###\", \"cc\": \"MY\", \"name_en\": \"Malaysia\", \"desc_en\": \"\", \"name_ru\": \"Малайзия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+60-#-###-###\", \"cc\": \"MY\", \"name_en\": \"Malaysia\", \"desc_en\": \"\", \"name_ru\": \"Малайзия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+258-##-###-###\", \"cc\": \"MZ\", \"name_en\": \"Mozambique\", \"desc_en\": \"\", \"name_ru\": \"Мозамбик\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+264-##-###-####\", \"cc\": \"NA\", \"name_en\": \"Namibia\", \"desc_en\": \"\", \"name_ru\": \"Намибия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+687-##-####\", \"cc\": \"NC\", \"name_en\": \"New Caledonia\", \"desc_en\": \"\", \"name_ru\": \"Новая Каледония\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+227-##-##-####\", \"cc\": \"NE\", \"name_en\": \"Niger\", \"desc_en\": \"\", \"name_ru\": \"Нигер\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+672-3##-###\", \"cc\": \"NF\", \"name_en\": \"Norfolk Island\", \"desc_en\": \"\", \"name_ru\": \"Норфолк (остров)\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+234(###)###-####\", \"cc\": \"NG\", \"name_en\": \"Nigeria\", \"desc_en\": \"\", \"name_ru\": \"Нигерия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+234-##-###-###\", \"cc\": \"NG\", \"name_en\": \"Nigeria\", \"desc_en\": \"\", \"name_ru\": \"Нигерия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+234-##-###-##\", \"cc\": \"NG\", \"name_en\": \"Nigeria\", \"desc_en\": \"\", \"name_ru\": \"Нигерия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+234(###)###-####\", \"cc\": \"NG\", \"name_en\": \"Nigeria \", \"desc_en\": \"mobile\", \"name_ru\": \"Нигерия \", \"desc_ru\": \"мобильные\" },\n\t{ \"mask\": \"+505-####-####\", \"cc\": \"NI\", \"name_en\": \"Nicaragua\", \"desc_en\": \"\", \"name_ru\": \"Никарагуа\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+31-##-###-####\", \"cc\": \"NL\", \"name_en\": \"Netherlands\", \"desc_en\": \"\", \"name_ru\": \"Нидерланды\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+47(###)##-###\", \"cc\": \"NO\", \"name_en\": \"Norway\", \"desc_en\": \"\", \"name_ru\": \"Норвегия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+977-##-###-###\", \"cc\": \"NP\", \"name_en\": \"Nepal\", \"desc_en\": \"\", \"name_ru\": \"Непал\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+674-###-####\", \"cc\": \"NR\", \"name_en\": \"Nauru\", \"desc_en\": \"\", \"name_ru\": \"Науру\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+683-####\", \"cc\": \"NU\", \"name_en\": \"Niue\", \"desc_en\": \"\", \"name_ru\": \"Ниуэ\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+64(###)###-###\", \"cc\": \"NZ\", \"name_en\": \"New Zealand\", \"desc_en\": \"\", \"name_ru\": \"Новая Зеландия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+64-##-###-###\", \"cc\": \"NZ\", \"name_en\": \"New Zealand\", \"desc_en\": \"\", \"name_ru\": \"Новая Зеландия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+64(###)###-####\", \"cc\": \"NZ\", \"name_en\": \"New Zealand\", \"desc_en\": \"\", \"name_ru\": \"Новая Зеландия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+968-##-###-###\", \"cc\": \"OM\", \"name_en\": \"Oman\", \"desc_en\": \"\", \"name_ru\": \"Оман\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+507-###-####\", \"cc\": \"PA\", \"name_en\": \"Panama\", \"desc_en\": \"\", \"name_ru\": \"Панама\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+51(###)###-###\", \"cc\": \"PE\", \"name_en\": \"Peru\", \"desc_en\": \"\", \"name_ru\": \"Перу\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+689-##-##-##\", \"cc\": \"PF\", \"name_en\": \"French Polynesia\", \"desc_en\": \"\", \"name_ru\": \"Французская Полинезия (Таити)\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+675(###)##-###\", \"cc\": \"PG\", \"name_en\": \"Papua New Guinea\", \"desc_en\": \"\", \"name_ru\": \"Папуа-Новая Гвинея\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+63(###)###-####\", \"cc\": \"PH\", \"name_en\": \"Philippines\", \"desc_en\": \"\", \"name_ru\": \"Филиппины\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+92(###)###-####\", \"cc\": \"PK\", \"name_en\": \"Pakistan\", \"desc_en\": \"\", \"name_ru\": \"Пакистан\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+48(###)###-###\", \"cc\": \"PL\", \"name_en\": \"Poland\", \"desc_en\": \"\", \"name_ru\": \"Польша\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+970-##-###-####\", \"cc\": \"PS\", \"name_en\": \"Palestine\", \"desc_en\": \"\", \"name_ru\": \"Палестина\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+351-##-###-####\", \"cc\": \"PT\", \"name_en\": \"Portugal\", \"desc_en\": \"\", \"name_ru\": \"Португалия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+680-###-####\", \"cc\": \"PW\", \"name_en\": \"Palau\", \"desc_en\": \"\", \"name_ru\": \"Палау\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+595(###)###-###\", \"cc\": \"PY\", \"name_en\": \"Paraguay\", \"desc_en\": \"\", \"name_ru\": \"Парагвай\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+974-####-####\", \"cc\": \"QA\", \"name_en\": \"Qatar\", \"desc_en\": \"\", \"name_ru\": \"Катар\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+262-#####-####\", \"cc\": \"RE\", \"name_en\": \"Reunion\", \"desc_en\": \"\", \"name_ru\": \"Реюньон\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+40-##-###-####\", \"cc\": \"RO\", \"name_en\": \"Romania\", \"desc_en\": \"\", \"name_ru\": \"Румыния\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+381-##-###-####\", \"cc\": \"RS\", \"name_en\": \"Serbia\", \"desc_en\": \"\", \"name_ru\": \"Сербия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+7(###)###-##-##\", \"cc\": \"RU\", \"name_en\": \"Russia\", \"desc_en\": \"\", \"name_ru\": \"Россия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+250(###)###-###\", \"cc\": \"RW\", \"name_en\": \"Rwanda\", \"desc_en\": \"\", \"name_ru\": \"Руанда\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+966-5-####-####\", \"cc\": \"SA\", \"name_en\": \"Saudi Arabia \", \"desc_en\": \"mobile\", \"name_ru\": \"Саудовская Аравия \", \"desc_ru\": \"мобильные\" },\n\t{ \"mask\": \"+966-#-###-####\", \"cc\": \"SA\", \"name_en\": \"Saudi Arabia\", \"desc_en\": \"\", \"name_ru\": \"Саудовская Аравия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+677-###-####\", \"cc\": \"SB\", \"name_en\": \"Solomon Islands \", \"desc_en\": \"mobile\", \"name_ru\": \"Соломоновы Острова \", \"desc_ru\": \"мобильные\" },\n\t{ \"mask\": \"+677-#####\", \"cc\": \"SB\", \"name_en\": \"Solomon Islands\", \"desc_en\": \"\", \"name_ru\": \"Соломоновы Острова\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+248-#-###-###\", \"cc\": \"SC\", \"name_en\": \"Seychelles\", \"desc_en\": \"\", \"name_ru\": \"Сейшелы\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+249-##-###-####\", \"cc\": \"SD\", \"name_en\": \"Sudan\", \"desc_en\": \"\", \"name_ru\": \"Судан\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+46-##-###-####\", \"cc\": \"SE\", \"name_en\": \"Sweden\", \"desc_en\": \"\", \"name_ru\": \"Швеция\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+65-####-####\", \"cc\": \"SG\", \"name_en\": \"Singapore\", \"desc_en\": \"\", \"name_ru\": \"Сингапур\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+290-####\", \"cc\": \"SH\", \"name_en\": \"Saint Helena\", \"desc_en\": \"\", \"name_ru\": \"Остров Святой Елены\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+290-####\", \"cc\": \"SH\", \"name_en\": \"Tristan da Cunha\", \"desc_en\": \"\", \"name_ru\": \"Тристан-да-Кунья\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+386-##-###-###\", \"cc\": \"SI\", \"name_en\": \"Slovenia\", \"desc_en\": \"\", \"name_ru\": \"Словения\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+421(###)###-###\", \"cc\": \"SK\", \"name_en\": \"Slovakia\", \"desc_en\": \"\", \"name_ru\": \"Словакия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+232-##-######\", \"cc\": \"SL\", \"name_en\": \"Sierra Leone\", \"desc_en\": \"\", \"name_ru\": \"Сьерра-Леоне\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+378-####-######\", \"cc\": \"SM\", \"name_en\": \"San Marino\", \"desc_en\": \"\", \"name_ru\": \"Сан-Марино\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+221-##-###-####\", \"cc\": \"SN\", \"name_en\": \"Senegal\", \"desc_en\": \"\", \"name_ru\": \"Сенегал\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+252-##-###-###\", \"cc\": \"SO\", \"name_en\": \"Somalia\", \"desc_en\": \"\", \"name_ru\": \"Сомали\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+252-#-###-###\", \"cc\": \"SO\", \"name_en\": \"Somalia\", \"desc_en\": \"\", \"name_ru\": \"Сомали\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+252-#-###-###\", \"cc\": \"SO\", \"name_en\": \"Somalia \", \"desc_en\": \"mobile\", \"name_ru\": \"Сомали \", \"desc_ru\": \"мобильные\" },\n\t{ \"mask\": \"+597-###-####\", \"cc\": \"SR\", \"name_en\": \"Suriname \", \"desc_en\": \"mobile\", \"name_ru\": \"Суринам \", \"desc_ru\": \"мобильные\" },\n\t{ \"mask\": \"+597-###-###\", \"cc\": \"SR\", \"name_en\": \"Suriname\", \"desc_en\": \"\", \"name_ru\": \"Суринам\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+211-##-###-####\", \"cc\": \"SS\", \"name_en\": \"South Sudan\", \"desc_en\": \"\", \"name_ru\": \"Южный Судан\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+239-##-#####\", \"cc\": \"ST\", \"name_en\": \"Sao Tome and Principe\", \"desc_en\": \"\", \"name_ru\": \"Сан-Томе и Принсипи\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+503-##-##-####\", \"cc\": \"SV\", \"name_en\": \"El Salvador\", \"desc_en\": \"\", \"name_ru\": \"Сальвадор\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+1(721)###-####\", \"cc\": \"SX\", \"name_en\": \"Sint Maarten\", \"desc_en\": \"\", \"name_ru\": \"Синт-Маартен\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+963-##-####-###\", \"cc\": \"SY\", \"name_en\": \"Syrian Arab Republic\", \"desc_en\": \"\", \"name_ru\": \"Сирийская арабская республика\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+268-##-##-####\", \"cc\": \"SZ\", \"name_en\": \"Swaziland\", \"desc_en\": \"\", \"name_ru\": \"Свазиленд\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+1(649)###-####\", \"cc\": \"TC\", \"name_en\": \"Turks & Caicos\", \"desc_en\": \"\", \"name_ru\": \"Тёркс и Кайкос\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+235-##-##-##-##\", \"cc\": \"TD\", \"name_en\": \"Chad\", \"desc_en\": \"\", \"name_ru\": \"Чад\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+228-##-###-###\", \"cc\": \"TG\", \"name_en\": \"Togo\", \"desc_en\": \"\", \"name_ru\": \"Того\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+66-##-###-####\", \"cc\": \"TH\", \"name_en\": \"Thailand \", \"desc_en\": \"mobile\", \"name_ru\": \"Таиланд \", \"desc_ru\": \"мобильные\" },\n\t{ \"mask\": \"+66-##-###-###\", \"cc\": \"TH\", \"name_en\": \"Thailand\", \"desc_en\": \"\", \"name_ru\": \"Таиланд\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+992-##-###-####\", \"cc\": \"TJ\", \"name_en\": \"Tajikistan\", \"desc_en\": \"\", \"name_ru\": \"Таджикистан\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+690-####\", \"cc\": \"TK\", \"name_en\": \"Tokelau\", \"desc_en\": \"\", \"name_ru\": \"Токелау\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+670-###-####\", \"cc\": \"TL\", \"name_en\": \"East Timor\", \"desc_en\": \"\", \"name_ru\": \"Восточный Тимор\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+670-77#-#####\", \"cc\": \"TL\", \"name_en\": \"East Timor\", \"desc_en\": \"Timor Telecom\", \"name_ru\": \"Восточный Тимор\", \"desc_ru\": \"Timor Telecom\" },\n\t{ \"mask\": \"+670-78#-#####\", \"cc\": \"TL\", \"name_en\": \"East Timor\", \"desc_en\": \"Timor Telecom\", \"name_ru\": \"Восточный Тимор\", \"desc_ru\": \"Timor Telecom\" },\n\t{ \"mask\": \"+993-#-###-####\", \"cc\": \"TM\", \"name_en\": \"Turkmenistan\", \"desc_en\": \"\", \"name_ru\": \"Туркменистан\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+216-##-###-###\", \"cc\": \"TN\", \"name_en\": \"Tunisia\", \"desc_en\": \"\", \"name_ru\": \"Тунис\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+676-#####\", \"cc\": \"TO\", \"name_en\": \"Tonga\", \"desc_en\": \"\", \"name_ru\": \"Тонга\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+90(###)###-####\", \"cc\": \"TR\", \"name_en\": \"Turkey\", \"desc_en\": \"\", \"name_ru\": \"Турция\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+1(868)###-####\", \"cc\": \"TT\", \"name_en\": \"Trinidad & Tobago\", \"desc_en\": \"\", \"name_ru\": \"Тринидад и Тобаго\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+688-90####\", \"cc\": \"TV\", \"name_en\": \"Tuvalu \", \"desc_en\": \"mobile\", \"name_ru\": \"Тувалу \", \"desc_ru\": \"мобильные\" },\n\t{ \"mask\": \"+688-2####\", \"cc\": \"TV\", \"name_en\": \"Tuvalu\", \"desc_en\": \"\", \"name_ru\": \"Тувалу\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+886-#-####-####\", \"cc\": \"TW\", \"name_en\": \"Taiwan\", \"desc_en\": \"\", \"name_ru\": \"Тайвань\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+886-####-####\", \"cc\": \"TW\", \"name_en\": \"Taiwan\", \"desc_en\": \"\", \"name_ru\": \"Тайвань\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+255-##-###-####\", \"cc\": \"TZ\", \"name_en\": \"Tanzania\", \"desc_en\": \"\", \"name_ru\": \"Танзания\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+380(##)###-##-##\", \"cc\": \"UA\", \"name_en\": \"Ukraine\", \"desc_en\": \"\", \"name_ru\": \"Украина\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+256(###)###-###\", \"cc\": \"UG\", \"name_en\": \"Uganda\", \"desc_en\": \"\", \"name_ru\": \"Уганда\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+44-##-####-####\", \"cc\": \"UK\", \"name_en\": \"United Kingdom\", \"desc_en\": \"\", \"name_ru\": \"Великобритания\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+598-#-###-##-##\", \"cc\": \"UY\", \"name_en\": \"Uruguay\", \"desc_en\": \"\", \"name_ru\": \"Уругвай\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+998-##-###-####\", \"cc\": \"UZ\", \"name_en\": \"Uzbekistan\", \"desc_en\": \"\", \"name_ru\": \"Узбекистан\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+39-6-698-#####\", \"cc\": \"VA\", \"name_en\": \"Vatican City\", \"desc_en\": \"\", \"name_ru\": \"Ватикан\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+1(784)###-####\", \"cc\": \"VC\", \"name_en\": \"Saint Vincent & the Grenadines\", \"desc_en\": \"\", \"name_ru\": \"Сент-Винсент и Гренадины\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+58(###)###-####\", \"cc\": \"VE\", \"name_en\": \"Venezuela\", \"desc_en\": \"\", \"name_ru\": \"Венесуэла\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+1(284)###-####\", \"cc\": \"VG\", \"name_en\": \"British Virgin Islands\", \"desc_en\": \"\", \"name_ru\": \"Британские Виргинские острова\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+1(340)###-####\", \"cc\": \"VI\", \"name_en\": \"US Virgin Islands\", \"desc_en\": \"\", \"name_ru\": \"Американские Виргинские острова\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+84-##-####-###\", \"cc\": \"VN\", \"name_en\": \"Vietnam\", \"desc_en\": \"\", \"name_ru\": \"Вьетнам\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+84(###)####-###\", \"cc\": \"VN\", \"name_en\": \"Vietnam\", \"desc_en\": \"\", \"name_ru\": \"Вьетнам\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+678-##-#####\", \"cc\": \"VU\", \"name_en\": \"Vanuatu \", \"desc_en\": \"mobile\", \"name_ru\": \"Вануату \", \"desc_ru\": \"мобильные\" },\n\t{ \"mask\": \"+678-#####\", \"cc\": \"VU\", \"name_en\": \"Vanuatu\", \"desc_en\": \"\", \"name_ru\": \"Вануату\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+681-##-####\", \"cc\": \"WF\", \"name_en\": \"Wallis and Futuna\", \"desc_en\": \"\", \"name_ru\": \"Уоллис и Футуна\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+685-##-####\", \"cc\": \"WS\", \"name_en\": \"Samoa\", \"desc_en\": \"\", \"name_ru\": \"Самоа\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+967-###-###-###\", \"cc\": \"YE\", \"name_en\": \"Yemen \", \"desc_en\": \"mobile\", \"name_ru\": \"Йемен \", \"desc_ru\": \"мобильные\" },\n\t{ \"mask\": \"+967-#-###-###\", \"cc\": \"YE\", \"name_en\": \"Yemen\", \"desc_en\": \"\", \"name_ru\": \"Йемен\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+967-##-###-###\", \"cc\": \"YE\", \"name_en\": \"Yemen\", \"desc_en\": \"\", \"name_ru\": \"Йемен\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+27-##-###-####\", \"cc\": \"ZA\", \"name_en\": \"South Africa\", \"desc_en\": \"\", \"name_ru\": \"Южно-Африканская Респ.\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+260-##-###-####\", \"cc\": \"ZM\", \"name_en\": \"Zambia\", \"desc_en\": \"\", \"name_ru\": \"Замбия\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+263-#-######\", \"cc\": \"ZW\", \"name_en\": \"Zimbabwe\", \"desc_en\": \"\", \"name_ru\": \"Зимбабве\", \"desc_ru\": \"\" },\n\t{ \"mask\": \"+1(###)###-####\", \"cc\": [\"US\", \"CA\"], \"name_en\": \"USA and Canada\", \"desc_en\": \"\", \"name_ru\": \"США и Канада\", \"desc_ru\": \"\" }\n]\n"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/input-mask/phone-codes/readme.txt",
    "content": "more phone masks can be found at https://github.com/andr-04/inputmask-multi "
  },
  {
    "path": "resources/assets/AdminLTE/plugins/ionslider/ion.rangeSlider.css",
    "content": "/* Ion.RangeSlider\n// css version 1.8.5\n// by Denis Ineshin | ionden.com\n// ===================================================================================================================*/\n\n/* =====================================================================================================================\n// RangeSlider */\n\n.irs {\n    position: relative; display: block;\n}\n    .irs-line {\n        position: relative; display: block;\n        overflow: hidden;\n    }\n        .irs-line-left, .irs-line-mid, .irs-line-right {\n            position: absolute; display: block;\n            top: 0;\n        }\n        .irs-line-left {\n            left: 0; width: 10%;\n        }\n        .irs-line-mid {\n            left: 10%; width: 80%;\n        }\n        .irs-line-right {\n            right: 0; width: 10%;\n        }\n\n    .irs-diapason {\n        position: absolute; display: block;\n        left: 0; width: 100%;\n    }\n    .irs-slider {\n        position: absolute; display: block;\n        cursor: default;\n        z-index: 1;\n    }\n        .irs-slider.single {\n            left: 10px;\n        }\n            .irs-slider.single:before {\n                position: absolute; display: block; content: \"\";\n                top: -30%; left: -30%;\n                width: 160%; height: 160%;\n                background: rgba(0,0,0,0.0);\n            }\n        .irs-slider.from {\n            left: 100px;\n        }\n            .irs-slider.from:before {\n                position: absolute; display: block; content: \"\";\n                top: -30%; left: -30%;\n                width: 130%; height: 160%;\n                background: rgba(0,0,0,0.0);\n            }\n        .irs-slider.to {\n            left: 300px;\n        }\n            .irs-slider.to:before {\n                position: absolute; display: block; content: \"\";\n                top: -30%; left: 0;\n                width: 130%; height: 160%;\n                background: rgba(0,0,0,0.0);\n            }\n        .irs-slider.last {\n            z-index: 2;\n        }\n\n    .irs-min {\n        position: absolute; display: block;\n        left: 0;\n        cursor: default;\n    }\n    .irs-max {\n        position: absolute; display: block;\n        right: 0;\n        cursor: default;\n    }\n\n    .irs-from, .irs-to, .irs-single {\n        position: absolute; display: block;\n        top: 0; left: 0;\n        cursor: default;\n        white-space: nowrap;\n    }\n\n\n.irs-grid {\n    position: absolute; display: none;\n    bottom: 0; left: 0;\n    width: 100%; height: 20px;\n}\n.irs-with-grid .irs-grid {\n    display: block;\n}\n    .irs-grid-pol {\n        position: absolute;\n        top: 0; left: 0;\n        width: 1px; height: 8px;\n        background: #000;\n    }\n    .irs-grid-pol.small {\n        height: 4px;\n    }\n    .irs-grid-text {\n        position: absolute;\n        bottom: 0; left: 0;\n        width: 100px;\n        white-space: nowrap;\n        text-align: center;\n        font-size: 9px; line-height: 9px;\n        color: #000;\n    }\n\n.irs-disable-mask {\n    position: absolute; display: block;\n    top: 0; left: 0;\n    width: 100%; height: 100%;\n    cursor: default;\n    background: rgba(0,0,0,0.0);\n    z-index: 2;\n}\n.irs-disabled {\n    opacity: 0.4;\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/ionslider/ion.rangeSlider.skinFlat.css",
    "content": "/* Ion.RangeSlider, Flat UI Skin\n// css version 1.8.5\n// by Denis Ineshin | ionden.com\n// ===================================================================================================================*/\n\n/* =====================================================================================================================\n// Skin details */\n\n.irs-line-mid,\n.irs-line-left,\n.irs-line-right,\n.irs-diapason,\n.irs-slider {\n    background: url(img/sprite-skin-flat.png) repeat-x;\n}\n\n.irs {\n    height: 40px;\n}\n.irs-with-grid {\n    height: 60px;\n}\n.irs-line {\n    height: 12px; top: 25px;\n}\n    .irs-line-left {\n        height: 12px;\n        background-position: 0 -30px;\n    }\n    .irs-line-mid {\n        height: 12px;\n        background-position: 0 0;\n    }\n    .irs-line-right {\n        height: 12px;\n        background-position: 100% -30px;\n    }\n\n.irs-diapason {\n    height: 12px; top: 25px;\n    background-position: 0 -60px;\n}\n\n.irs-slider {\n    width: 16px; height: 18px;\n    top: 22px;\n    background-position: 0 -90px;\n}\n#irs-active-slider, .irs-slider:hover {\n    background-position: 0 -120px;\n}\n\n.irs-min, .irs-max {\n    color: #999;\n    font-size: 10px; line-height: 1.333;\n    text-shadow: none;\n    top: 0; padding: 1px 3px;\n    background: #e1e4e9;\n    border-radius: 4px;\n}\n\n.irs-from, .irs-to, .irs-single {\n    color: #fff;\n    font-size: 10px; line-height: 1.333;\n    text-shadow: none;\n    padding: 1px 5px;\n    background: #ed5565;\n    border-radius: 4px;\n}\n.irs-from:after, .irs-to:after, .irs-single:after {\n    position: absolute; display: block; content: \"\";\n    bottom: -6px; left: 50%;\n    width: 0; height: 0;\n    margin-left: -3px;\n    overflow: hidden;\n    border: 3px solid transparent;\n    border-top-color: #ed5565;\n}\n\n\n.irs-grid-pol {\n    background: #e1e4e9;\n}\n.irs-grid-text {\n    color: #999;\n}\n\n.irs-disabled {\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/ionslider/ion.rangeSlider.skinNice.css",
    "content": "/* Ion.RangeSlider, Nice Skin\n// css version 1.8.5\n// by Denis Ineshin | ionden.com\n// ===================================================================================================================*/\n\n/* =====================================================================================================================\n// Skin details */\n\n.irs-line-mid,\n.irs-line-left,\n.irs-line-right,\n.irs-diapason,\n.irs-slider {\n    background: url(img/sprite-skin-nice.png) repeat-x;\n}\n\n.irs {\n    height: 40px;\n}\n.irs-with-grid {\n    height: 60px;\n}\n.irs-line {\n    height: 8px; top: 25px;\n}\n    .irs-line-left {\n        height: 8px;\n        background-position: 0 -30px;\n    }\n    .irs-line-mid {\n        height: 8px;\n        background-position: 0 0;\n    }\n    .irs-line-right {\n        height: 8px;\n        background-position: 100% -30px;\n    }\n\n.irs-diapason {\n    height: 8px; top: 25px;\n    background-position: 0 -60px;\n}\n\n.irs-slider {\n    width: 22px; height: 22px;\n    top: 17px;\n    background-position: 0 -90px;\n}\n#irs-active-slider, .irs-slider:hover {\n    background-position: 0 -120px;\n}\n\n.irs-min, .irs-max {\n    color: #999;\n    font-size: 10px; line-height: 1.333;\n    text-shadow: none;\n    top: 0; padding: 1px 3px;\n    background: rgba(0,0,0,0.1);\n    border-radius: 3px;\n}\n.lt-ie9 .irs-min, .lt-ie9 .irs-max {\n    background: #ccc;\n}\n\n.irs-from, .irs-to, .irs-single {\n    color: #fff;\n    font-size: 10px; line-height: 1.333;\n    text-shadow: none;\n    padding: 1px 5px;\n    background: rgba(0,0,0,0.3);\n    border-radius: 3px;\n}\n.lt-ie9 .irs-from, .lt-ie9 .irs-to, .lt-ie9 .irs-single {\n    background: #999;\n}\n\n.irs-grid-pol {\n    background: #99a4ac;\n}\n.irs-grid-text {\n    color: #99a4ac;\n}\n\n.irs-disabled {\n}"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/ar.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/ar\",[],function(){return{errorLoading:function(){return\"لا يمكن تحميل النتائج\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"الرجاء حذف \"+t+\" عناصر\";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"الرجاء إضافة \"+t+\" عناصر\";return n},loadingMore:function(){return\"جاري تحميل نتائج إضافية...\"},maximumSelected:function(e){var t=\"تستطيع إختيار \"+e.maximum+\" بنود فقط\";return t},noResults:function(){return\"لم يتم العثور على أي نتائج\"},searching:function(){return\"جاري البحث…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/az.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/az\",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum;return t+\" simvol silin\"},inputTooShort:function(e){var t=e.minimum-e.input.length;return t+\" simvol daxil edin\"},loadingMore:function(){return\"Daha çox nəticə yüklənir…\"},maximumSelected:function(e){return\"Sadəcə \"+e.maximum+\" element seçə bilərsiniz\"},noResults:function(){return\"Nəticə tapılmadı\"},searching:function(){return\"Axtarılır…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/bg.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/bg\",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Моля въведете с \"+t+\" по-малко символ\";return t>1&&(n+=\"a\"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Моля въведете още \"+t+\" символ\";return t>1&&(n+=\"a\"),n},loadingMore:function(){return\"Зареждат се още…\"},maximumSelected:function(e){var t=\"Можете да направите до \"+e.maximum+\" \";return e.maximum>1?t+=\"избора\":t+=\"избор\",t},noResults:function(){return\"Няма намерени съвпадения\"},searching:function(){return\"Търсене…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/ca.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/ca\",[],function(){return{errorLoading:function(){return\"La càrrega ha fallat\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Si us plau, elimina \"+t+\" car\";return t==1?n+=\"àcter\":n+=\"àcters\",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Si us plau, introdueix \"+t+\" car\";return t==1?n+=\"àcter\":n+=\"àcters\",n},loadingMore:function(){return\"Carregant més resultats…\"},maximumSelected:function(e){var t=\"Només es pot seleccionar \"+e.maximum+\" element\";return e.maximum!=1&&(t+=\"s\"),t},noResults:function(){return\"No s'han trobat resultats\"},searching:function(){return\"Cercant…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/cs.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/cs\",[],function(){function e(e,t){switch(e){case 2:return t?\"dva\":\"dvě\";case 3:return\"tři\";case 4:return\"čtyři\"}return\"\"}return{errorLoading:function(){return\"Výsledky nemohly být načteny.\"},inputTooLong:function(t){var n=t.input.length-t.maximum;return n==1?\"Prosím zadejte o jeden znak méně\":n<=4?\"Prosím zadejte o \"+e(n,!0)+\" znaky méně\":\"Prosím zadejte o \"+n+\" znaků méně\"},inputTooShort:function(t){var n=t.minimum-t.input.length;return n==1?\"Prosím zadejte ještě jeden znak\":n<=4?\"Prosím zadejte ještě další \"+e(n,!0)+\" znaky\":\"Prosím zadejte ještě dalších \"+n+\" znaků\"},loadingMore:function(){return\"Načítají se další výsledky…\"},maximumSelected:function(t){var n=t.maximum;return n==1?\"Můžete zvolit jen jednu položku\":n<=4?\"Můžete zvolit maximálně \"+e(n,!1)+\" položky\":\"Můžete zvolit maximálně \"+n+\" položek\"},noResults:function(){return\"Nenalezeny žádné položky\"},searching:function(){return\"Vyhledávání…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/da.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/da\",[],function(){return{errorLoading:function(){return\"Resultaterne kunne ikke indlæses.\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Angiv venligst \"+t+\" tegn mindre\";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Angiv venligst \"+t+\" tegn mere\";return n},loadingMore:function(){return\"Indlæser flere resultater…\"},maximumSelected:function(e){var t=\"Du kan kun vælge \"+e.maximum+\" emne\";return e.maximum!=1&&(t+=\"r\"),t},noResults:function(){return\"Ingen resultater fundet\"},searching:function(){return\"Søger…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/de.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/de\",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum;return\"Bitte \"+t+\" Zeichen weniger eingeben\"},inputTooShort:function(e){var t=e.minimum-e.input.length;return\"Bitte \"+t+\" Zeichen mehr eingeben\"},loadingMore:function(){return\"Lade mehr Ergebnisse…\"},maximumSelected:function(e){var t=\"Sie können nur \"+e.maximum+\" Eintr\";return e.maximum===1?t+=\"ag\":t+=\"äge\",t+=\" auswählen\",t},noResults:function(){return\"Keine Übereinstimmungen gefunden\"},searching:function(){return\"Suche…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/el.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/el\",[],function(){return{errorLoading:function(){return\"Τα αποτελέσματα δεν μπόρεσαν να φορτώσουν.\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Παρακαλώ διαγράψτε \"+t+\" χαρακτήρ\";return t==1&&(n+=\"α\"),t!=1&&(n+=\"ες\"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Παρακαλώ συμπληρώστε \"+t+\" ή περισσότερους χαρακτήρες\";return n},loadingMore:function(){return\"Φόρτωση περισσότερων αποτελεσμάτων…\"},maximumSelected:function(e){var t=\"Μπορείτε να επιλέξετε μόνο \"+e.maximum+\" επιλογ\";return e.maximum==1&&(t+=\"ή\"),e.maximum!=1&&(t+=\"ές\"),t},noResults:function(){return\"Δεν βρέθηκαν αποτελέσματα\"},searching:function(){return\"Αναζήτηση…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/en.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/en\",[],function(){return{errorLoading:function(){return\"The results could not be loaded.\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Please delete \"+t+\" character\";return t!=1&&(n+=\"s\"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Please enter \"+t+\" or more characters\";return n},loadingMore:function(){return\"Loading more results…\"},maximumSelected:function(e){var t=\"You can only select \"+e.maximum+\" item\";return e.maximum!=1&&(t+=\"s\"),t},noResults:function(){return\"No results found\"},searching:function(){return\"Searching…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/es.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/es\",[],function(){return{errorLoading:function(){return\"La carga falló\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Por favor, elimine \"+t+\" car\";return t==1?n+=\"ácter\":n+=\"acteres\",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Por favor, introduzca \"+t+\" car\";return t==1?n+=\"ácter\":n+=\"acteres\",n},loadingMore:function(){return\"Cargando más resultados…\"},maximumSelected:function(e){var t=\"Sólo puede seleccionar \"+e.maximum+\" elemento\";return e.maximum!=1&&(t+=\"s\"),t},noResults:function(){return\"No se encontraron resultados\"},searching:function(){return\"Buscando…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/et.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/et\",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Sisesta \"+t+\" täht\";return t!=1&&(n+=\"e\"),n+=\" vähem\",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Sisesta \"+t+\" täht\";return t!=1&&(n+=\"e\"),n+=\" rohkem\",n},loadingMore:function(){return\"Laen tulemusi…\"},maximumSelected:function(e){var t=\"Saad vaid \"+e.maximum+\" tulemus\";return e.maximum==1?t+=\"e\":t+=\"t\",t+=\" valida\",t},noResults:function(){return\"Tulemused puuduvad\"},searching:function(){return\"Otsin…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/eu.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/eu\",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Idatzi \";return t==1?n+=\"karaktere bat\":n+=t+\" karaktere\",n+=\" gutxiago\",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Idatzi \";return t==1?n+=\"karaktere bat\":n+=t+\" karaktere\",n+=\" gehiago\",n},loadingMore:function(){return\"Emaitza gehiago kargatzen…\"},maximumSelected:function(e){return e.maximum===1?\"Elementu bakarra hauta dezakezu\":e.maximum+\" elementu hauta ditzakezu soilik\"},noResults:function(){return\"Ez da bat datorrenik aurkitu\"},searching:function(){return\"Bilatzen…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/fa.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/fa\",[],function(){return{errorLoading:function(){return\"امکان بارگذاری نتایج وجود ندارد.\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"لطفاً \"+t+\" کاراکتر را حذف نمایید\";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"لطفاً تعداد \"+t+\" کاراکتر یا بیشتر وارد نمایید\";return n},loadingMore:function(){return\"در حال بارگذاری نتایج بیشتر...\"},maximumSelected:function(e){var t=\"شما تنها می‌توانید \"+e.maximum+\" آیتم را انتخاب نمایید\";return t},noResults:function(){return\"هیچ نتیجه‌ای یافت نشد\"},searching:function(){return\"در حال جستجو...\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/fi.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/fi\",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum;return\"Ole hyvä ja anna \"+t+\" merkkiä vähemmän\"},inputTooShort:function(e){var t=e.minimum-e.input.length;return\"Ole hyvä ja anna \"+t+\" merkkiä lisää\"},loadingMore:function(){return\"Ladataan lisää tuloksia…\"},maximumSelected:function(e){return\"Voit valita ainoastaan \"+e.maximum+\" kpl\"},noResults:function(){return\"Ei tuloksia\"},searching:function(){}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/fr.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/fr\",[],function(){return{errorLoading:function(){return\"Les résultats ne peuvent pas être chargés.\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Supprimez \"+t+\" caractère\";return t!==1&&(n+=\"s\"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Saisissez \"+t+\" caractère\";return t!==1&&(n+=\"s\"),n},loadingMore:function(){return\"Chargement de résultats supplémentaires…\"},maximumSelected:function(e){var t=\"Vous pouvez seulement sélectionner \"+e.maximum+\" élément\";return e.maximum!==1&&(t+=\"s\"),t},noResults:function(){return\"Aucun résultat trouvé\"},searching:function(){return\"Recherche en cours…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/gl.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/gl\",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Elimine \";return t===1?n+=\"un carácter\":n+=t+\" caracteres\",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Engada \";return t===1?n+=\"un carácter\":n+=t+\" caracteres\",n},loadingMore:function(){return\"Cargando máis resultados…\"},maximumSelected:function(e){var t=\"Só pode \";return e.maximum===1?t+=\"un elemento\":t+=e.maximum+\" elementos\",t},noResults:function(){return\"Non se atoparon resultados\"},searching:function(){return\"Buscando…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/he.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/he\",[],function(){return{errorLoading:function(){return\"שגיאה בטעינת התוצאות\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"נא למחוק \";return t===1?n+=\"תו אחד\":n+=t+\" תווים\",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"נא להכניס \";return t===1?n+=\"תו אחד\":n+=t+\" תווים\",n+=\" או יותר\",n},loadingMore:function(){return\"טוען תוצאות נוספות…\"},maximumSelected:function(e){var t=\"באפשרותך לבחור עד \";return e.maximum===1?t+=\"פריט אחד\":t+=e.maximum+\" פריטים\",t},noResults:function(){return\"לא נמצאו תוצאות\"},searching:function(){return\"מחפש…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/hi.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/hi\",[],function(){return{errorLoading:function(){return\"परिणामों को लोड नहीं किया जा सका।\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=t+\" अक्षर को हटा दें\";return t>1&&(n=t+\" अक्षरों को हटा दें \"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"कृपया \"+t+\" या अधिक अक्षर दर्ज करें\";return n},loadingMore:function(){return\"अधिक परिणाम लोड हो रहे है...\"},maximumSelected:function(e){var t=\"आप केवल \"+e.maximum+\" आइटम का चयन कर सकते हैं\";return t},noResults:function(){return\"कोई परिणाम नहीं मिला\"},searching:function(){return\"खोज रहा है...\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/hr.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/hr\",[],function(){function e(e){var t=\" \"+e+\" znak\";return e%10<5&&e%10>0&&(e%100<5||e%100>19)?e%10>1&&(t+=\"a\"):t+=\"ova\",t}return{errorLoading:function(){return\"Preuzimanje nije uspjelo.\"},inputTooLong:function(t){var n=t.input.length-t.maximum;return\"Unesite \"+e(n)},inputTooShort:function(t){var n=t.minimum-t.input.length;return\"Unesite još \"+e(n)},loadingMore:function(){return\"Učitavanje rezultata…\"},maximumSelected:function(e){return\"Maksimalan broj odabranih stavki je \"+e.maximum},noResults:function(){return\"Nema rezultata\"},searching:function(){return\"Pretraga…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/hu.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/hu\",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum;return\"Túl hosszú. \"+t+\" karakterrel több, mint kellene.\"},inputTooShort:function(e){var t=e.minimum-e.input.length;return\"Túl rövid. Még \"+t+\" karakter hiányzik.\"},loadingMore:function(){return\"Töltés…\"},maximumSelected:function(e){return\"Csak \"+e.maximum+\" elemet lehet kiválasztani.\"},noResults:function(){return\"Nincs találat.\"},searching:function(){return\"Keresés…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/id.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/id\",[],function(){return{errorLoading:function(){return\"Data tidak boleh diambil.\"},inputTooLong:function(e){var t=e.input.length-e.maximum;return\"Hapuskan \"+t+\" huruf\"},inputTooShort:function(e){var t=e.minimum-e.input.length;return\"Masukkan \"+t+\" huruf lagi\"},loadingMore:function(){return\"Mengambil data…\"},maximumSelected:function(e){return\"Anda hanya dapat memilih \"+e.maximum+\" pilihan\"},noResults:function(){return\"Tidak ada data yang sesuai\"},searching:function(){return\"Mencari…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/is.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/is\",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Vinsamlegast styttið texta um \"+t+\" staf\";return t<=1?n:n+\"i\"},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Vinsamlegast skrifið \"+t+\" staf\";return t>1&&(n+=\"i\"),n+=\" í viðbót\",n},loadingMore:function(){return\"Sæki fleiri niðurstöður…\"},maximumSelected:function(e){return\"Þú getur aðeins valið \"+e.maximum+\" atriði\"},noResults:function(){return\"Ekkert fannst\"},searching:function(){return\"Leita…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/it.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/it\",[],function(){return{errorLoading:function(){return\"I risultati non possono essere caricati.\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Per favore cancella \"+t+\" caratter\";return t!==1?n+=\"i\":n+=\"e\",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Per favore inserisci \"+t+\" o più caratteri\";return n},loadingMore:function(){return\"Caricando più risultati…\"},maximumSelected:function(e){var t=\"Puoi selezionare solo \"+e.maximum+\" element\";return e.maximum!==1?t+=\"i\":t+=\"o\",t},noResults:function(){return\"Nessun risultato trovato\"},searching:function(){return\"Sto cercando…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/ja.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/ja\",[],function(){return{errorLoading:function(){return\"結果が読み込まれませんでした\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=t+\" 文字を削除してください\";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"少なくとも \"+t+\" 文字を入力してください\";return n},loadingMore:function(){return\"読み込み中…\"},maximumSelected:function(e){var t=e.maximum+\" 件しか選択できません\";return t},noResults:function(){return\"対象が見つかりません\"},searching:function(){return\"検索しています…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/km.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/km\",[],function(){return{errorLoading:function(){return\"មិនអាចទាញយកទិន្នន័យ\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"សូមលុបចេញ  \"+t+\" អក្សរ\";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"សូមបញ្ចូល\"+t+\" អក្សរ រឺ ច្រើនជាងនេះ\";return n},loadingMore:function(){return\"កំពុងទាញយកទិន្នន័យបន្ថែម...\"},maximumSelected:function(e){var t=\"អ្នកអាចជ្រើសរើសបានតែ \"+e.maximum+\" ជម្រើសប៉ុណ្ណោះ\";return t},noResults:function(){return\"មិនមានលទ្ធផល\"},searching:function(){return\"កំពុងស្វែងរក...\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/ko.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/ko\",[],function(){return{errorLoading:function(){return\"결과를 불러올 수 없습니다.\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"너무 깁니다. \"+t+\" 글자 지워주세요.\";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"너무 짧습니다. \"+t+\" 글자 더 입력해주세요.\";return n},loadingMore:function(){return\"불러오는 중…\"},maximumSelected:function(e){var t=\"최대 \"+e.maximum+\"개까지만 선택 가능합니다.\";return t},noResults:function(){return\"결과가 없습니다.\"},searching:function(){return\"검색 중…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/lt.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/lt\",[],function(){function e(e,t,n,r){return e%10===1&&(e%100<11||e%100>19)?t:e%10>=2&&e%10<=9&&(e%100<11||e%100>19)?n:r}return{inputTooLong:function(t){var n=t.input.length-t.maximum,r=\"Pašalinkite \"+n+\" simbol\";return r+=e(n,\"į\",\"ius\",\"ių\"),r},inputTooShort:function(t){var n=t.minimum-t.input.length,r=\"Įrašykite dar \"+n+\" simbol\";return r+=e(n,\"į\",\"ius\",\"ių\"),r},loadingMore:function(){return\"Kraunama daugiau rezultatų…\"},maximumSelected:function(t){var n=\"Jūs galite pasirinkti tik \"+t.maximum+\" element\";return n+=e(t.maximum,\"ą\",\"us\",\"ų\"),n},noResults:function(){return\"Atitikmenų nerasta\"},searching:function(){return\"Ieškoma…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/lv.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/lv\",[],function(){function e(e,t,n,r){return e===11?t:e%10===1?n:r}return{inputTooLong:function(t){var n=t.input.length-t.maximum,r=\"Lūdzu ievadiet par  \"+n;return r+=\" simbol\"+e(n,\"iem\",\"u\",\"iem\"),r+\" mazāk\"},inputTooShort:function(t){var n=t.minimum-t.input.length,r=\"Lūdzu ievadiet vēl \"+n;return r+=\" simbol\"+e(n,\"us\",\"u\",\"us\"),r},loadingMore:function(){return\"Datu ielāde…\"},maximumSelected:function(t){var n=\"Jūs varat izvēlēties ne vairāk kā \"+t.maximum;return n+=\" element\"+e(t.maximum,\"us\",\"u\",\"us\"),n},noResults:function(){return\"Sakritību nav\"},searching:function(){return\"Meklēšana…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/mk.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/mk\",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Ве молиме внесете \"+e.maximum+\" помалку карактер\";return e.maximum!==1&&(n+=\"и\"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Ве молиме внесете уште \"+e.maximum+\" карактер\";return e.maximum!==1&&(n+=\"и\"),n},loadingMore:function(){return\"Вчитување резултати…\"},maximumSelected:function(e){var t=\"Можете да изберете само \"+e.maximum+\" ставк\";return e.maximum===1?t+=\"а\":t+=\"и\",t},noResults:function(){return\"Нема пронајдено совпаѓања\"},searching:function(){return\"Пребарување…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/ms.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/ms\",[],function(){return{errorLoading:function(){return\"Keputusan tidak berjaya dimuatkan.\"},inputTooLong:function(e){var t=e.input.length-e.maximum;return\"Sila hapuskan \"+t+\" aksara\"},inputTooShort:function(e){var t=e.minimum-e.input.length;return\"Sila masukkan \"+t+\" atau lebih aksara\"},loadingMore:function(){return\"Sedang memuatkan keputusan…\"},maximumSelected:function(e){return\"Anda hanya boleh memilih \"+e.maximum+\" pilihan\"},noResults:function(){return\"Tiada padanan yang ditemui\"},searching:function(){return\"Mencari…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/nb.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/nb\",[],function(){return{errorLoading:function(){return\"Kunne ikke hente resultater.\"},inputTooLong:function(e){var t=e.input.length-e.maximum;return\"Vennligst fjern \"+t+\" tegn\"},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Vennligst skriv inn \";return t>1?n+=\" flere tegn\":n+=\" tegn til\",n},loadingMore:function(){return\"Laster flere resultater…\"},maximumSelected:function(e){return\"Du kan velge maks \"+e.maximum+\" elementer\"},noResults:function(){return\"Ingen treff\"},searching:function(){return\"Søker…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/nl.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/nl\",[],function(){return{errorLoading:function(){return\"De resultaten konden niet worden geladen.\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Gelieve \"+t+\" karakters te verwijderen\";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Gelieve \"+t+\" of meer karakters in te voeren\";return n},loadingMore:function(){return\"Meer resultaten laden…\"},maximumSelected:function(e){var t=e.maximum==1?\"kan\":\"kunnen\",n=\"Er \"+t+\" maar \"+e.maximum+\" item\";return e.maximum!=1&&(n+=\"s\"),n+=\" worden geselecteerd\",n},noResults:function(){return\"Geen resultaten gevonden…\"},searching:function(){return\"Zoeken…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/pl.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/pl\",[],function(){var e=[\"znak\",\"znaki\",\"znaków\"],t=[\"element\",\"elementy\",\"elementów\"],n=function(t,n){if(t===1)return n[0];if(t>1&&t<=4)return n[1];if(t>=5)return n[2]};return{errorLoading:function(){return\"Nie można załadować wyników.\"},inputTooLong:function(t){var r=t.input.length-t.maximum;return\"Usuń \"+r+\" \"+n(r,e)},inputTooShort:function(t){var r=t.minimum-t.input.length;return\"Podaj przynajmniej \"+r+\" \"+n(r,e)},loadingMore:function(){return\"Trwa ładowanie…\"},maximumSelected:function(e){return\"Możesz zaznaczyć tylko \"+e.maximum+\" \"+n(e.maximum,t)},noResults:function(){return\"Brak wyników\"},searching:function(){return\"Trwa wyszukiwanie…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/pt-BR.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/pt-BR\",[],function(){return{errorLoading:function(){return\"Os resultados não puderam ser carregados.\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Apague \"+t+\" caracter\";return t!=1&&(n+=\"es\"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Digite \"+t+\" ou mais caracteres\";return n},loadingMore:function(){return\"Carregando mais resultados…\"},maximumSelected:function(e){var t=\"Você só pode selecionar \"+e.maximum+\" ite\";return e.maximum==1?t+=\"m\":t+=\"ns\",t},noResults:function(){return\"Nenhum resultado encontrado\"},searching:function(){return\"Buscando…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/pt.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/pt\",[],function(){return{errorLoading:function(){return\"Os resultados não puderam ser carregados.\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Por favor apague \"+t+\" \";return n+=t!=1?\"caracteres\":\"carácter\",n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Introduza \"+t+\" ou mais caracteres\";return n},loadingMore:function(){return\"A carregar mais resultados…\"},maximumSelected:function(e){var t=\"Apenas pode seleccionar \"+e.maximum+\" \";return t+=e.maximum!=1?\"itens\":\"item\",t},noResults:function(){return\"Sem resultados\"},searching:function(){return\"A procurar…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/ro.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/ro\",[],function(){return{errorLoading:function(){return\"Rezultatele nu au putut fi incărcate.\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Vă rugăm să ștergeți\"+t+\" caracter\";return t!==1&&(n+=\"e\"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Vă rugăm să introduceți \"+t+\"sau mai multe caractere\";return n},loadingMore:function(){return\"Se încarcă mai multe rezultate…\"},maximumSelected:function(e){var t=\"Aveți voie să selectați cel mult \"+e.maximum;return t+=\" element\",e.maximum!==1&&(t+=\"e\"),t},noResults:function(){return\"Nu au fost găsite rezultate\"},searching:function(){return\"Căutare…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/ru.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/ru\",[],function(){function e(e,t,n,r){return e%10<5&&e%10>0&&e%100<5||e%100>20?e%10>1?n:t:r}return{errorLoading:function(){return\"Невозможно загрузить результаты\"},inputTooLong:function(t){var n=t.input.length-t.maximum,r=\"Пожалуйста, введите на \"+n+\" символ\";return r+=e(n,\"\",\"a\",\"ов\"),r+=\" меньше\",r},inputTooShort:function(t){var n=t.minimum-t.input.length,r=\"Пожалуйста, введите еще хотя бы \"+n+\" символ\";return r+=e(n,\"\",\"a\",\"ов\"),r},loadingMore:function(){return\"Загрузка данных…\"},maximumSelected:function(t){var n=\"Вы можете выбрать не более \"+t.maximum+\" элемент\";return n+=e(t.maximum,\"\",\"a\",\"ов\"),n},noResults:function(){return\"Совпадений не найдено\"},searching:function(){return\"Поиск…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/sk.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/sk\",[],function(){var e={2:function(e){return e?\"dva\":\"dve\"},3:function(){return\"tri\"},4:function(){return\"štyri\"}};return{inputTooLong:function(t){var n=t.input.length-t.maximum;return n==1?\"Prosím, zadajte o jeden znak menej\":n>=2&&n<=4?\"Prosím, zadajte o \"+e[n](!0)+\" znaky menej\":\"Prosím, zadajte o \"+n+\" znakov menej\"},inputTooShort:function(t){var n=t.minimum-t.input.length;return n==1?\"Prosím, zadajte ešte jeden znak\":n<=4?\"Prosím, zadajte ešte ďalšie \"+e[n](!0)+\" znaky\":\"Prosím, zadajte ešte ďalších \"+n+\" znakov\"},loadingMore:function(){return\"Loading more results…\"},maximumSelected:function(t){return t.maximum==1?\"Môžete zvoliť len jednu položku\":t.maximum>=2&&t.maximum<=4?\"Môžete zvoliť najviac \"+e[t.maximum](!1)+\" položky\":\"Môžete zvoliť najviac \"+t.maximum+\" položiek\"},noResults:function(){return\"Nenašli sa žiadne položky\"},searching:function(){return\"Vyhľadávanie…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/sr-Cyrl.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/sr-Cyrl\",[],function(){function e(e,t,n,r){return e%10==1&&e%100!=11?t:e%10>=2&&e%10<=4&&(e%100<12||e%100>14)?n:r}return{errorLoading:function(){return\"Преузимање није успело.\"},inputTooLong:function(t){var n=t.input.length-t.maximum,r=\"Обришите \"+n+\" симбол\";return r+=e(n,\"\",\"а\",\"а\"),r},inputTooShort:function(t){var n=t.minimum-t.input.length,r=\"Укуцајте бар још \"+n+\" симбол\";return r+=e(n,\"\",\"а\",\"а\"),r},loadingMore:function(){return\"Преузимање још резултата…\"},maximumSelected:function(t){var n=\"Можете изабрати само \"+t.maximum+\" ставк\";return n+=e(t.maximum,\"у\",\"е\",\"и\"),n},noResults:function(){return\"Ништа није пронађено\"},searching:function(){return\"Претрага…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/sr.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/sr\",[],function(){function e(e,t,n,r){return e%10==1&&e%100!=11?t:e%10>=2&&e%10<=4&&(e%100<12||e%100>14)?n:r}return{errorLoading:function(){return\"Preuzimanje nije uspelo.\"},inputTooLong:function(t){var n=t.input.length-t.maximum,r=\"Obrišite \"+n+\" simbol\";return r+=e(n,\"\",\"a\",\"a\"),r},inputTooShort:function(t){var n=t.minimum-t.input.length,r=\"Ukucajte bar još \"+n+\" simbol\";return r+=e(n,\"\",\"a\",\"a\"),r},loadingMore:function(){return\"Preuzimanje još rezultata…\"},maximumSelected:function(t){var n=\"Možete izabrati samo \"+t.maximum+\" stavk\";return n+=e(t.maximum,\"u\",\"e\",\"i\"),n},noResults:function(){return\"Ništa nije pronađeno\"},searching:function(){return\"Pretraga…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/sv.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/sv\",[],function(){return{errorLoading:function(){return\"Resultat kunde inte laddas.\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Vänligen sudda ut \"+t+\" tecken\";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Vänligen skriv in \"+t+\" eller fler tecken\";return n},loadingMore:function(){return\"Laddar fler resultat…\"},maximumSelected:function(e){var t=\"Du kan max välja \"+e.maximum+\" element\";return t},noResults:function(){return\"Inga träffar\"},searching:function(){return\"Söker…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/th.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/th\",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"โปรดลบออก \"+t+\" ตัวอักษร\";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"โปรดพิมพ์เพิ่มอีก \"+t+\" ตัวอักษร\";return n},loadingMore:function(){return\"กำลังค้นข้อมูลเพิ่ม…\"},maximumSelected:function(e){var t=\"คุณสามารถเลือกได้ไม่เกิน \"+e.maximum+\" รายการ\";return t},noResults:function(){return\"ไม่พบข้อมูล\"},searching:function(){return\"กำลังค้นข้อมูล…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/tr.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/tr\",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n=t+\" karakter daha girmelisiniz\";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"En az \"+t+\" karakter daha girmelisiniz\";return n},loadingMore:function(){return\"Daha fazla…\"},maximumSelected:function(e){var t=\"Sadece \"+e.maximum+\" seçim yapabilirsiniz\";return t},noResults:function(){return\"Sonuç bulunamadı\"},searching:function(){return\"Aranıyor…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/uk.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/uk\",[],function(){function e(e,t,n,r){return e%100>10&&e%100<15?r:e%10===1?t:e%10>1&&e%10<5?n:r}return{errorLoading:function(){return\"Неможливо завантажити результати\"},inputTooLong:function(t){var n=t.input.length-t.maximum;return\"Будь ласка, видаліть \"+n+\" \"+e(t.maximum,\"літеру\",\"літери\",\"літер\")},inputTooShort:function(e){var t=e.minimum-e.input.length;return\"Будь ласка, введіть \"+t+\" або більше літер\"},loadingMore:function(){return\"Завантаження інших результатів…\"},maximumSelected:function(t){return\"Ви можете вибрати лише \"+t.maximum+\" \"+e(t.maximum,\"пункт\",\"пункти\",\"пунктів\")},noResults:function(){return\"Нічого не знайдено\"},searching:function(){return\"Пошук…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/vi.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/vi\",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"Vui lòng nhập ít hơn \"+t+\" ký tự\";return t!=1&&(n+=\"s\"),n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"Vui lòng nhập nhiều hơn \"+t+' ký tự\"';return n},loadingMore:function(){return\"Đang lấy thêm kết quả…\"},maximumSelected:function(e){var t=\"Chỉ có thể chọn được \"+e.maximum+\" lựa chọn\";return t},noResults:function(){return\"Không tìm thấy kết quả\"},searching:function(){return\"Đang tìm…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/zh-CN.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/zh-CN\",[],function(){return{errorLoading:function(){return\"无法载入结果。\"},inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"请删除\"+t+\"个字符\";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"请再输入至少\"+t+\"个字符\";return n},loadingMore:function(){return\"载入更多结果…\"},maximumSelected:function(e){var t=\"最多只能选择\"+e.maximum+\"个项目\";return t},noResults:function(){return\"未找到结果\"},searching:function(){return\"搜索中…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/AdminLTE/plugins/select2/i18n/zh-TW.js",
    "content": "/*! Select2 4.0.3 | https://github.com/select2/select2/blob/master/LICENSE.md */\n\n(function(){if(jQuery&&jQuery.fn&&jQuery.fn.select2&&jQuery.fn.select2.amd)var e=jQuery.fn.select2.amd;return e.define(\"select2/i18n/zh-TW\",[],function(){return{inputTooLong:function(e){var t=e.input.length-e.maximum,n=\"請刪掉\"+t+\"個字元\";return n},inputTooShort:function(e){var t=e.minimum-e.input.length,n=\"請再輸入\"+t+\"個字元\";return n},loadingMore:function(){return\"載入中…\"},maximumSelected:function(e){var t=\"你只能選擇最多\"+e.maximum+\"項\";return t},noResults:function(){return\"沒有找到相符的項目\"},searching:function(){return\"搜尋中…\"}}}),{define:e.define,require:e.require}})();"
  },
  {
    "path": "resources/assets/bootstrap-fileinput/js/plugins/canvas-to-blob.js",
    "content": "/*\n * JavaScript Canvas to Blob 2.0.5\n * https://github.com/blueimp/JavaScript-Canvas-to-Blob\n *\n * Copyright 2012, Sebastian Tschan\n * https://blueimp.net\n *\n * Licensed under the MIT license:\n * http://www.opensource.org/licenses/MIT\n *\n * Based on stackoverflow user Stoive's code snippet:\n * http://stackoverflow.com/q/4998908\n */\n\n/*jslint nomen: true, regexp: true */\n/*global window, atob, Blob, ArrayBuffer, Uint8Array, define */\n\n(function (window) {\n    'use strict';\n    var CanvasPrototype = window.HTMLCanvasElement &&\n            window.HTMLCanvasElement.prototype,\n        hasBlobConstructor = window.Blob && (function () {\n            try {\n                return Boolean(new Blob());\n            } catch (e) {\n                return false;\n            }\n        }()),\n        hasArrayBufferViewSupport = hasBlobConstructor && window.Uint8Array &&\n            (function () {\n                try {\n                    return new Blob([new Uint8Array(100)]).size === 100;\n                } catch (e) {\n                    return false;\n                }\n            }()),\n        BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder ||\n            window.MozBlobBuilder || window.MSBlobBuilder,\n        dataURLtoBlob = (hasBlobConstructor || BlobBuilder) && window.atob &&\n            window.ArrayBuffer && window.Uint8Array && function (dataURI) {\n                var byteString,\n                    arrayBuffer,\n                    intArray,\n                    i,\n                    mimeString,\n                    bb;\n                if (dataURI.split(',')[0].indexOf('base64') >= 0) {\n                    // Convert base64 to raw binary data held in a string:\n                    byteString = atob(dataURI.split(',')[1]);\n                } else {\n                    // Convert base64/URLEncoded data component to raw binary data:\n                    byteString = decodeURIComponent(dataURI.split(',')[1]);\n                }\n                // Write the bytes of the string to an ArrayBuffer:\n                arrayBuffer = new ArrayBuffer(byteString.length);\n                intArray = new Uint8Array(arrayBuffer);\n                for (i = 0; i < byteString.length; i += 1) {\n                    intArray[i] = byteString.charCodeAt(i);\n                }\n                // Separate out the mime component:\n                mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];\n                // Write the ArrayBuffer (or ArrayBufferView) to a blob:\n                if (hasBlobConstructor) {\n                    return new Blob(\n                        [hasArrayBufferViewSupport ? intArray : arrayBuffer],\n                        {type: mimeString}\n                    );\n                }\n                bb = new BlobBuilder();\n                bb.append(arrayBuffer);\n                return bb.getBlob(mimeString);\n            };\n    if (window.HTMLCanvasElement && !CanvasPrototype.toBlob) {\n        if (CanvasPrototype.mozGetAsFile) {\n            CanvasPrototype.toBlob = function (callback, type, quality) {\n                if (quality && CanvasPrototype.toDataURL && dataURLtoBlob) {\n                    callback(dataURLtoBlob(this.toDataURL(type, quality)));\n                } else {\n                    callback(this.mozGetAsFile('blob', type));\n                }\n            };\n        } else if (CanvasPrototype.toDataURL && dataURLtoBlob) {\n            CanvasPrototype.toBlob = function (callback, type, quality) {\n                callback(dataURLtoBlob(this.toDataURL(type, quality)));\n            };\n        }\n    }\n    if (typeof define === 'function' && define.amd) {\n        define(function () {\n            return dataURLtoBlob;\n        });\n    } else {\n        window.dataURLtoBlob = dataURLtoBlob;\n    }\n}(window));\n"
  },
  {
    "path": "resources/assets/bootstrap-fileinput/js/plugins/piexif.js",
    "content": "/* piexifjs\n\nThe MIT License (MIT)\n\nCopyright (c) 2014, 2015 hMatoba(https://github.com/hMatoba)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n*/\n\n(function () {\n    \"use strict\";\n    var that = {};\n    that.version = \"1.03\";\n\n    that.remove = function (jpeg) {\n        var b64 = false;\n        if (jpeg.slice(0, 2) == \"\\xff\\xd8\") {\n        } else if (jpeg.slice(0, 23) == \"data:image/jpeg;base64,\" || jpeg.slice(0, 22) == \"data:image/jpg;base64,\") {\n            jpeg = atob(jpeg.split(\",\")[1]);\n            b64 = true;\n        } else {\n            throw (\"Given data is not jpeg.\");\n        }\n        \n        var segments = splitIntoSegments(jpeg);\n        if (segments[1].slice(0, 2) == \"\\xff\\xe1\" && \n               segments[1].slice(4, 10) == \"Exif\\x00\\x00\") {\n            segments = [segments[0]].concat(segments.slice(2));\n        } else if (segments[2].slice(0, 2) == \"\\xff\\xe1\" &&\n                   segments[2].slice(4, 10) == \"Exif\\x00\\x00\") {\n            segments = segments.slice(0, 2).concat(segments.slice(3));\n        } else {\n            throw(\"Exif not found.\");\n        }\n        \n        var new_data = segments.join(\"\");\n        if (b64) {\n            new_data = \"data:image/jpeg;base64,\" + btoa(new_data);\n        }\n\n        return new_data;\n    };\n\n\n    that.insert = function (exif, jpeg) {\n        var b64 = false;\n        if (exif.slice(0, 6) != \"\\x45\\x78\\x69\\x66\\x00\\x00\") {\n            throw (\"Given data is not exif.\");\n        }\n        if (jpeg.slice(0, 2) == \"\\xff\\xd8\") {\n        } else if (jpeg.slice(0, 23) == \"data:image/jpeg;base64,\" || jpeg.slice(0, 22) == \"data:image/jpg;base64,\") {\n            jpeg = atob(jpeg.split(\",\")[1]);\n            b64 = true;\n        } else {\n            throw (\"Given data is not jpeg.\");\n        }\n\n        var exifStr = \"\\xff\\xe1\" + pack(\">H\", [exif.length + 2]) + exif;\n        var segments = splitIntoSegments(jpeg);\n        var new_data = mergeSegments(segments, exifStr);\n        if (b64) {\n            new_data = \"data:image/jpeg;base64,\" + btoa(new_data);\n        }\n\n        return new_data;\n    };\n\n\n    that.load = function (data) {\n        var input_data;\n        if (typeof (data) == \"string\") {\n            if (data.slice(0, 2) == \"\\xff\\xd8\") {\n                input_data = data;\n            } else if (data.slice(0, 23) == \"data:image/jpeg;base64,\" || data.slice(0, 22) == \"data:image/jpg;base64,\") {\n                input_data = atob(data.split(\",\")[1]);\n            } else if (data.slice(0, 4) == \"Exif\") {\n                input_data = data.slice(6);\n            } else {\n                throw (\"'load' gots invalid file data.\");\n            }\n        } else {\n            throw (\"'load' gots invalid type argument.\");\n        }\n\n        var exifDict = {};\n        var exif_dict = {\n            \"0th\": {},\n            \"Exif\": {},\n            \"GPS\": {},\n            \"Interop\": {},\n            \"1st\": {},\n            \"thumbnail\": null\n        };\n        var exifReader = new ExifReader(input_data);\n        if (exifReader.tiftag === null) {\n            return exif_dict;\n        }\n\n        if (exifReader.tiftag.slice(0, 2) == \"\\x49\\x49\") {\n            exifReader.endian_mark = \"<\";\n        } else {\n            exifReader.endian_mark = \">\";\n        }\n\n        var pointer = unpack(exifReader.endian_mark + \"L\",\n            exifReader.tiftag.slice(4, 8))[0];\n        exif_dict[\"0th\"] = exifReader.get_ifd(pointer, \"0th\");\n\n        var first_ifd_pointer = exif_dict[\"0th\"][\"first_ifd_pointer\"];\n        delete exif_dict[\"0th\"][\"first_ifd_pointer\"];\n\n        if (34665 in exif_dict[\"0th\"]) {\n            pointer = exif_dict[\"0th\"][34665];\n            exif_dict[\"Exif\"] = exifReader.get_ifd(pointer, \"Exif\");\n        }\n        if (34853 in exif_dict[\"0th\"]) {\n            pointer = exif_dict[\"0th\"][34853];\n            exif_dict[\"GPS\"] = exifReader.get_ifd(pointer, \"GPS\");\n        }\n        if (40965 in exif_dict[\"Exif\"]) {\n            pointer = exif_dict[\"Exif\"][40965];\n            exif_dict[\"Interop\"] = exifReader.get_ifd(pointer, \"Interop\");\n        }\n        if (first_ifd_pointer != \"\\x00\\x00\\x00\\x00\") {\n            pointer = unpack(exifReader.endian_mark + \"L\",\n                first_ifd_pointer)[0];\n            exif_dict[\"1st\"] = exifReader.get_ifd(pointer, \"1st\");\n            if ((513 in exif_dict[\"1st\"]) && (514 in exif_dict[\"1st\"])) {\n                var end = exif_dict[\"1st\"][513] + exif_dict[\"1st\"][514];\n                var thumb = exifReader.tiftag.slice(exif_dict[\"1st\"][513], end);\n                exif_dict[\"thumbnail\"] = thumb;\n            }\n        }\n\n        return exif_dict;\n    };\n\n\n    that.dump = function (exif_dict_original) {\n        var TIFF_HEADER_LENGTH = 8;\n\n        var exif_dict = copy(exif_dict_original);\n        var header = \"Exif\\x00\\x00\\x4d\\x4d\\x00\\x2a\\x00\\x00\\x00\\x08\";\n        var exif_is = false;\n        var gps_is = false;\n        var interop_is = false;\n        var first_is = false;\n\n        var zeroth_ifd,\n            exif_ifd,\n            interop_ifd,\n            gps_ifd,\n            first_ifd;\n        \n        if (\"0th\" in exif_dict) {\n            zeroth_ifd = exif_dict[\"0th\"];\n        } else {\n            zeroth_ifd = {};\n        }\n        \n        if (((\"Exif\" in exif_dict) && (Object.keys(exif_dict[\"Exif\"]).length)) ||\n            ((\"Interop\" in exif_dict) && (Object.keys(exif_dict[\"Interop\"]).length))) {\n            zeroth_ifd[34665] = 1;\n            exif_is = true;\n            exif_ifd = exif_dict[\"Exif\"];\n            if ((\"Interop\" in exif_dict) && Object.keys(exif_dict[\"Interop\"]).length) {\n                exif_ifd[40965] = 1;\n                interop_is = true;\n                interop_ifd = exif_dict[\"Interop\"];\n            } else if (Object.keys(exif_ifd).indexOf(that.ExifIFD.InteroperabilityTag.toString()) > -1) {\n                delete exif_ifd[40965];\n            }\n        } else if (Object.keys(zeroth_ifd).indexOf(that.ImageIFD.ExifTag.toString()) > -1) {\n            delete zeroth_ifd[34665];\n        }\n\n        if ((\"GPS\" in exif_dict) && (Object.keys(exif_dict[\"GPS\"]).length)) {\n            zeroth_ifd[that.ImageIFD.GPSTag] = 1;\n            gps_is = true;\n            gps_ifd = exif_dict[\"GPS\"];\n        } else if (Object.keys(zeroth_ifd).indexOf(that.ImageIFD.GPSTag.toString()) > -1) {\n            delete zeroth_ifd[that.ImageIFD.GPSTag];\n        }\n        \n        if ((\"1st\" in exif_dict) &&\n            (\"thumbnail\" in exif_dict) &&\n            (exif_dict[\"thumbnail\"] != null)) {\n            first_is = true;\n            exif_dict[\"1st\"][513] = 1;\n            exif_dict[\"1st\"][514] = 1;\n            first_ifd = exif_dict[\"1st\"];\n        }\n        \n        var zeroth_set = _dict_to_bytes(zeroth_ifd, \"0th\", 0);\n        var zeroth_length = (zeroth_set[0].length + exif_is * 12 + gps_is * 12 + 4 +\n            zeroth_set[1].length);\n\n        var exif_set,\n            exif_bytes = \"\",\n            exif_length = 0,\n            gps_set,\n            gps_bytes = \"\",\n            gps_length = 0,\n            interop_set,\n            interop_bytes = \"\",\n            interop_length = 0,\n            first_set,\n            first_bytes = \"\",\n            thumbnail;\n        if (exif_is) {\n            exif_set = _dict_to_bytes(exif_ifd, \"Exif\", zeroth_length);\n            exif_length = exif_set[0].length + interop_is * 12 + exif_set[1].length;\n        }\n        if (gps_is) {\n            gps_set = _dict_to_bytes(gps_ifd, \"GPS\", zeroth_length + exif_length);\n            gps_bytes = gps_set.join(\"\");\n            gps_length = gps_bytes.length;\n        }\n        if (interop_is) {\n            var offset = zeroth_length + exif_length + gps_length;\n            interop_set = _dict_to_bytes(interop_ifd, \"Interop\", offset);\n            interop_bytes = interop_set.join(\"\");\n            interop_length = interop_bytes.length;\n        }\n        if (first_is) {\n            var offset = zeroth_length + exif_length + gps_length + interop_length;\n            first_set = _dict_to_bytes(first_ifd, \"1st\", offset);\n            thumbnail = _get_thumbnail(exif_dict[\"thumbnail\"]);\n            if (thumbnail.length > 64000) {\n                throw (\"Given thumbnail is too large. max 64kB\");\n            }\n        }\n\n        var exif_pointer = \"\",\n            gps_pointer = \"\",\n            interop_pointer = \"\",\n            first_ifd_pointer = \"\\x00\\x00\\x00\\x00\";\n        if (exif_is) {\n            var pointer_value = TIFF_HEADER_LENGTH + zeroth_length;\n            var pointer_str = pack(\">L\", [pointer_value]);\n            var key = 34665;\n            var key_str = pack(\">H\", [key]);\n            var type_str = pack(\">H\", [TYPES[\"Long\"]]);\n            var length_str = pack(\">L\", [1]);\n            exif_pointer = key_str + type_str + length_str + pointer_str;\n        }\n        if (gps_is) {\n            var pointer_value = TIFF_HEADER_LENGTH + zeroth_length + exif_length;\n            var pointer_str = pack(\">L\", [pointer_value]);\n            var key = 34853;\n            var key_str = pack(\">H\", [key]);\n            var type_str = pack(\">H\", [TYPES[\"Long\"]]);\n            var length_str = pack(\">L\", [1]);\n            gps_pointer = key_str + type_str + length_str + pointer_str;\n        }\n        if (interop_is) {\n            var pointer_value = (TIFF_HEADER_LENGTH +\n                zeroth_length + exif_length + gps_length);\n            var pointer_str = pack(\">L\", [pointer_value]);\n            var key = 40965;\n            var key_str = pack(\">H\", [key]);\n            var type_str = pack(\">H\", [TYPES[\"Long\"]]);\n            var length_str = pack(\">L\", [1]);\n            interop_pointer = key_str + type_str + length_str + pointer_str;\n        }\n        if (first_is) {\n            var pointer_value = (TIFF_HEADER_LENGTH + zeroth_length +\n                exif_length + gps_length + interop_length);\n            first_ifd_pointer = pack(\">L\", [pointer_value]);\n            var thumbnail_pointer = (pointer_value + first_set[0].length + 24 +\n                4 + first_set[1].length);\n            var thumbnail_p_bytes = (\"\\x02\\x01\\x00\\x04\\x00\\x00\\x00\\x01\" +\n                pack(\">L\", [thumbnail_pointer]));\n            var thumbnail_length_bytes = (\"\\x02\\x02\\x00\\x04\\x00\\x00\\x00\\x01\" +\n                pack(\">L\", [thumbnail.length]));\n            first_bytes = (first_set[0] + thumbnail_p_bytes +\n                thumbnail_length_bytes + \"\\x00\\x00\\x00\\x00\" +\n                first_set[1] + thumbnail);\n        }\n\n        var zeroth_bytes = (zeroth_set[0] + exif_pointer + gps_pointer +\n            first_ifd_pointer + zeroth_set[1]);\n        if (exif_is) {\n            exif_bytes = exif_set[0] + interop_pointer + exif_set[1];\n        }\n\n        return (header + zeroth_bytes + exif_bytes + gps_bytes +\n            interop_bytes + first_bytes);\n    };\n\n\n    function copy(obj) {\n        return JSON.parse(JSON.stringify(obj));\n    }\n\n\n    function _get_thumbnail(jpeg) {\n        var segments = splitIntoSegments(jpeg);\n        while ((\"\\xff\\xe0\" <= segments[1].slice(0, 2)) && (segments[1].slice(0, 2) <= \"\\xff\\xef\")) {\n            segments = [segments[0]].concat(segments.slice(2));\n        }\n        return segments.join(\"\");\n    }\n\n\n    function _pack_byte(array) {\n        return pack(\">\" + nStr(\"B\", array.length), array);\n    }\n\n\n    function _pack_short(array) {\n        return pack(\">\" + nStr(\"H\", array.length), array);\n    }\n\n\n    function _pack_long(array) {\n        return pack(\">\" + nStr(\"L\", array.length), array);\n    }\n\n\n    function _value_to_bytes(raw_value, value_type, offset) {\n        var four_bytes_over = \"\";\n        var value_str = \"\";\n        var length,\n            new_value,\n            num,\n            den;\n\n        if (value_type == \"Byte\") {\n            length = raw_value.length;\n            if (length <= 4) {\n                value_str = (_pack_byte(raw_value) +\n                    nStr(\"\\x00\", 4 - length));\n            } else {\n                value_str = pack(\">L\", [offset]);\n                four_bytes_over = _pack_byte(raw_value);\n            }\n        } else if (value_type == \"Short\") {\n            length = raw_value.length;\n            if (length <= 2) {\n                value_str = (_pack_short(raw_value) +\n                    nStr(\"\\x00\\x00\", 2 - length));\n            } else {\n                value_str = pack(\">L\", [offset]);\n                four_bytes_over = _pack_short(raw_value);\n            }\n        } else if (value_type == \"Long\") {\n            length = raw_value.length;\n            if (length <= 1) {\n                value_str = _pack_long(raw_value);\n            } else {\n                value_str = pack(\">L\", [offset]);\n                four_bytes_over = _pack_long(raw_value);\n            }\n        } else if (value_type == \"Ascii\") {\n            new_value = raw_value + \"\\x00\";\n            length = new_value.length;\n            if (length > 4) {\n                value_str = pack(\">L\", [offset]);\n                four_bytes_over = new_value;\n            } else {\n                value_str = new_value + nStr(\"\\x00\", 4 - length);\n            }\n        } else if (value_type == \"Rational\") {\n            if (typeof (raw_value[0]) == \"number\") {\n                length = 1;\n                num = raw_value[0];\n                den = raw_value[1];\n                new_value = pack(\">L\", [num]) + pack(\">L\", [den]);\n            } else {\n                length = raw_value.length;\n                new_value = \"\";\n                for (var n = 0; n < length; n++) {\n                    num = raw_value[n][0];\n                    den = raw_value[n][1];\n                    new_value += (pack(\">L\", [num]) +\n                        pack(\">L\", [den]));\n                }\n            }\n            value_str = pack(\">L\", [offset]);\n            four_bytes_over = new_value;\n        } else if (value_type == \"SRational\") {\n            if (typeof (raw_value[0]) == \"number\") {\n                length = 1;\n                num = raw_value[0];\n                den = raw_value[1];\n                new_value = pack(\">l\", [num]) + pack(\">l\", [den]);\n            } else {\n                length = raw_value.length;\n                new_value = \"\";\n                for (var n = 0; n < length; n++) {\n                    num = raw_value[n][0];\n                    den = raw_value[n][1];\n                    new_value += (pack(\">l\", [num]) +\n                        pack(\">l\", [den]));\n                }\n            }\n            value_str = pack(\">L\", [offset]);\n            four_bytes_over = new_value;\n        } else if (value_type == \"Undefined\") {\n            length = raw_value.length;\n            if (length > 4) {\n                value_str = pack(\">L\", [offset]);\n                four_bytes_over = raw_value;\n            } else {\n                value_str = raw_value + nStr(\"\\x00\", 4 - length);\n            }\n        }\n\n        var length_str = pack(\">L\", [length]);\n\n        return [length_str, value_str, four_bytes_over];\n    }\n\n    function _dict_to_bytes(ifd_dict, ifd, ifd_offset) {\n        var TIFF_HEADER_LENGTH = 8;\n        var tag_count = Object.keys(ifd_dict).length;\n        var entry_header = pack(\">H\", [tag_count]);\n        var entries_length;\n        if ([\"0th\", \"1st\"].indexOf(ifd) > -1) {\n            entries_length = 2 + tag_count * 12 + 4;\n        } else {\n            entries_length = 2 + tag_count * 12;\n        }\n        var entries = \"\";\n        var values = \"\";\n        var key;\n\n        for (var key in ifd_dict) {\n            if (typeof (key) == \"string\") {\n                key = parseInt(key);\n            }\n            if ((ifd == \"0th\") && ([34665, 34853].indexOf(key) > -1)) {\n                continue;\n            } else if ((ifd == \"Exif\") && (key == 40965)) {\n                continue;\n            } else if ((ifd == \"1st\") && ([513, 514].indexOf(key) > -1)) {\n                continue;\n            }\n\n            var raw_value = ifd_dict[key];\n            var key_str = pack(\">H\", [key]);\n            var value_type = TAGS[ifd][key][\"type\"];\n            var type_str = pack(\">H\", [TYPES[value_type]]);\n\n            if (typeof (raw_value) == \"number\") {\n                raw_value = [raw_value];\n            }\n            var offset = TIFF_HEADER_LENGTH + entries_length + ifd_offset + values.length;\n            var b = _value_to_bytes(raw_value, value_type, offset);\n            var length_str = b[0];\n            var value_str = b[1];\n            var four_bytes_over = b[2];\n\n            entries += key_str + type_str + length_str + value_str;\n            values += four_bytes_over;\n        }\n\n        return [entry_header + entries, values];\n    }\n\n\n\n    function ExifReader(data) {\n        var segments,\n            app1;\n        if (data.slice(0, 2) == \"\\xff\\xd8\") { // JPEG\n            segments = splitIntoSegments(data);\n            app1 = getExifSeg(segments);\n            if (app1) {\n                this.tiftag = app1.slice(10);\n            } else {\n                this.tiftag = null;\n            }\n        } else if ([\"\\x49\\x49\", \"\\x4d\\x4d\"].indexOf(data.slice(0, 2)) > -1) { // TIFF\n            this.tiftag = data;\n        } else if (data.slice(0, 4) == \"Exif\") { // Exif\n            this.tiftag = data.slice(6);\n        } else {\n            throw (\"Given file is neither JPEG nor TIFF.\");\n        }\n    }\n\n    ExifReader.prototype = {\n        get_ifd: function (pointer, ifd_name) {\n            var ifd_dict = {};\n            var tag_count = unpack(this.endian_mark + \"H\",\n                this.tiftag.slice(pointer, pointer + 2))[0];\n            var offset = pointer + 2;\n            var t;\n            if ([\"0th\", \"1st\"].indexOf(ifd_name) > -1) {\n                t = \"Image\";\n            } else {\n                t = ifd_name;\n            }\n\n            for (var x = 0; x < tag_count; x++) {\n                pointer = offset + 12 * x;\n                var tag = unpack(this.endian_mark + \"H\",\n                    this.tiftag.slice(pointer, pointer + 2))[0];\n                var value_type = unpack(this.endian_mark + \"H\",\n                    this.tiftag.slice(pointer + 2, pointer + 4))[0];\n                var value_num = unpack(this.endian_mark + \"L\",\n                    this.tiftag.slice(pointer + 4, pointer + 8))[0];\n                var value = this.tiftag.slice(pointer + 8, pointer + 12);\n\n                var v_set = [value_type, value_num, value];\n                if (tag in TAGS[t]) {\n                    ifd_dict[tag] = this.convert_value(v_set);\n                }\n            }\n\n            if (ifd_name == \"0th\") {\n                pointer = offset + 12 * tag_count;\n                ifd_dict[\"first_ifd_pointer\"] = this.tiftag.slice(pointer, pointer + 4);\n            }\n\n            return ifd_dict;\n        },\n\n        convert_value: function (val) {\n            var data = null;\n            var t = val[0];\n            var length = val[1];\n            var value = val[2];\n            var pointer;\n\n            if (t == 1) { // BYTE\n                if (length > 4) {\n                    pointer = unpack(this.endian_mark + \"L\", value)[0];\n                    data = unpack(this.endian_mark + nStr(\"B\", length),\n                        this.tiftag.slice(pointer, pointer + length));\n                } else {\n                    data = unpack(this.endian_mark + nStr(\"B\", length), value.slice(0, length));\n                }\n            } else if (t == 2) { // ASCII\n                if (length > 4) {\n                    pointer = unpack(this.endian_mark + \"L\", value)[0];\n                    data = this.tiftag.slice(pointer, pointer + length - 1);\n                } else {\n                    data = value.slice(0, length - 1);\n                }\n            } else if (t == 3) { // SHORT\n                if (length > 2) {\n                    pointer = unpack(this.endian_mark + \"L\", value)[0];\n                    data = unpack(this.endian_mark + nStr(\"H\", length),\n                        this.tiftag.slice(pointer, pointer + length * 2));\n                } else {\n                    data = unpack(this.endian_mark + nStr(\"H\", length),\n                        value.slice(0, length * 2));\n                }\n            } else if (t == 4) { // LONG\n                if (length > 1) {\n                    pointer = unpack(this.endian_mark + \"L\", value)[0];\n                    data = unpack(this.endian_mark + nStr(\"L\", length),\n                        this.tiftag.slice(pointer, pointer + length * 4));\n                } else {\n                    data = unpack(this.endian_mark + nStr(\"L\", length),\n                        value);\n                }\n            } else if (t == 5) { // RATIONAL\n                pointer = unpack(this.endian_mark + \"L\", value)[0];\n                if (length > 1) {\n                    data = [];\n                    for (var x = 0; x < length; x++) {\n                        data.push([unpack(this.endian_mark + \"L\",\n                                this.tiftag.slice(pointer + x * 8, pointer + 4 + x * 8))[0],\n                                   unpack(this.endian_mark + \"L\",\n                                this.tiftag.slice(pointer + 4 + x * 8, pointer + 8 + x * 8))[0]\n                                   ]);\n                    }\n                } else {\n                    data = [unpack(this.endian_mark + \"L\",\n                            this.tiftag.slice(pointer, pointer + 4))[0],\n                            unpack(this.endian_mark + \"L\",\n                            this.tiftag.slice(pointer + 4, pointer + 8))[0]\n                            ];\n                }\n            } else if (t == 7) { // UNDEFINED BYTES\n                if (length > 4) {\n                    pointer = unpack(this.endian_mark + \"L\", value)[0];\n                    data = this.tiftag.slice(pointer, pointer + length);\n                } else {\n                    data = value.slice(0, length);\n                }\n            } else if (t == 10) { // SRATIONAL\n                pointer = unpack(this.endian_mark + \"L\", value)[0];\n                if (length > 1) {\n                    data = [];\n                    for (var x = 0; x < length; x++) {\n                        data.push([unpack(this.endian_mark + \"l\",\n                                this.tiftag.slice(pointer + x * 8, pointer + 4 + x * 8))[0],\n                                   unpack(this.endian_mark + \"l\",\n                                this.tiftag.slice(pointer + 4 + x * 8, pointer + 8 + x * 8))[0]\n                                  ]);\n                    }\n                } else {\n                    data = [unpack(this.endian_mark + \"l\",\n                            this.tiftag.slice(pointer, pointer + 4))[0],\n                            unpack(this.endian_mark + \"l\",\n                            this.tiftag.slice(pointer + 4, pointer + 8))[0]\n                           ];\n                }\n            } else {\n                throw (\"Exif might be wrong. Got incorrect value \" +\n                    \"type to decode. type:\" + t);\n            }\n\n            if ((data instanceof Array) && (data.length == 1)) {\n                return data[0];\n            } else {\n                return data;\n            }\n        },\n    };\n\n\n    if (typeof window !== \"undefined\" && typeof window.btoa === \"function\") {\n        var btoa = window.btoa;\n    }\n    if (typeof btoa === \"undefined\") {\n        var btoa = function (input) {        var output = \"\";\n            var chr1, chr2, chr3, enc1, enc2, enc3, enc4;\n            var i = 0;\n            var keyStr = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";\n\n            while (i < input.length) {\n\n                chr1 = input.charCodeAt(i++);\n                chr2 = input.charCodeAt(i++);\n                chr3 = input.charCodeAt(i++);\n\n                enc1 = chr1 >> 2;\n                enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);\n                enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);\n                enc4 = chr3 & 63;\n\n                if (isNaN(chr2)) {\n                    enc3 = enc4 = 64;\n                } else if (isNaN(chr3)) {\n                    enc4 = 64;\n                }\n\n                output = output +\n                keyStr.charAt(enc1) + keyStr.charAt(enc2) +\n                keyStr.charAt(enc3) + keyStr.charAt(enc4);\n\n            }\n\n            return output;\n        };\n    }\n    \n    \n    if (typeof window !== \"undefined\" && typeof window.atob === \"function\") {\n        var atob = window.atob;\n    }\n    if (typeof atob === \"undefined\") {\n        var atob = function (input) {\n            var output = \"\";\n            var chr1, chr2, chr3;\n            var enc1, enc2, enc3, enc4;\n            var i = 0;\n            var keyStr = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";\n\n            input = input.replace(/[^A-Za-z0-9\\+\\/\\=]/g, \"\");\n\n            while (i < input.length) {\n\n                enc1 = keyStr.indexOf(input.charAt(i++));\n                enc2 = keyStr.indexOf(input.charAt(i++));\n                enc3 = keyStr.indexOf(input.charAt(i++));\n                enc4 = keyStr.indexOf(input.charAt(i++));\n\n                chr1 = (enc1 << 2) | (enc2 >> 4);\n                chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);\n                chr3 = ((enc3 & 3) << 6) | enc4;\n\n                output = output + String.fromCharCode(chr1);\n\n                if (enc3 != 64) {\n                    output = output + String.fromCharCode(chr2);\n                }\n                if (enc4 != 64) {\n                    output = output + String.fromCharCode(chr3);\n                }\n\n            }\n\n            return output;\n        };\n    }\n\n\n    function getImageSize(imageArray) {\n        var segments = slice2Segments(imageArray);\n        var seg,\n            width,\n            height,\n            SOF = [192, 193, 194, 195, 197, 198, 199, 201, 202, 203, 205, 206, 207];\n\n        for (var x = 0; x < segments.length; x++) {\n            seg = segments[x];\n            if (SOF.indexOf(seg[1]) >= 0) {\n                height = seg[5] * 256 + seg[6];\n                width = seg[7] * 256 + seg[8];\n                break;\n            }\n        }\n        return [width, height];\n    }\n\n\n    function pack(mark, array) {\n        if (!(array instanceof Array)) {\n            throw (\"'pack' error. Got invalid type argument.\");\n        }\n        if ((mark.length - 1) != array.length) {\n            throw (\"'pack' error. \" + (mark.length - 1) + \" marks, \" + array.length + \" elements.\");\n        }\n\n        var littleEndian;\n        if (mark[0] == \"<\") {\n            littleEndian = true;\n        } else if (mark[0] == \">\") {\n            littleEndian = false;\n        } else {\n            throw (\"\");\n        }\n        var packed = \"\";\n        var p = 1;\n        var val = null;\n        var c = null;\n        var valStr = null;\n\n        while (c = mark[p]) {\n            if (c.toLowerCase() == \"b\") {\n                val = array[p - 1];\n                if ((c == \"b\") && (val < 0)) {\n                    val += 0x100;\n                }\n                if ((val > 0xff) || (val < 0)) {\n                    throw (\"'pack' error.\");\n                } else {\n                    valStr = String.fromCharCode(val);\n                }\n            } else if (c == \"H\") {\n                val = array[p - 1];\n                if ((val > 0xffff) || (val < 0)) {\n                    throw (\"'pack' error.\");\n                } else {\n                    valStr = String.fromCharCode(Math.floor((val % 0x10000) / 0x100)) +\n                        String.fromCharCode(val % 0x100);\n                    if (littleEndian) {\n                        valStr = valStr.split(\"\").reverse().join(\"\");\n                    }\n                }\n            } else if (c.toLowerCase() == \"l\") {\n                val = array[p - 1];\n                if ((c == \"l\") && (val < 0)) {\n                    val += 0x100000000;\n                }\n                if ((val > 0xffffffff) || (val < 0)) {\n                    throw (\"'pack' error.\");\n                } else {\n                    valStr = String.fromCharCode(Math.floor(val / 0x1000000)) +\n                        String.fromCharCode(Math.floor((val % 0x1000000) / 0x10000)) +\n                        String.fromCharCode(Math.floor((val % 0x10000) / 0x100)) +\n                        String.fromCharCode(val % 0x100);\n                    if (littleEndian) {\n                        valStr = valStr.split(\"\").reverse().join(\"\");\n                    }\n                }\n            } else {\n                throw (\"'pack' error.\");\n            }\n\n            packed += valStr;\n            p += 1;\n        }\n\n        return packed;\n    }\n\n    function unpack(mark, str) {\n        if (typeof (str) != \"string\") {\n            throw (\"'unpack' error. Got invalid type argument.\");\n        }\n        var l = 0;\n        for (var markPointer = 1; markPointer < mark.length; markPointer++) {\n            if (mark[markPointer].toLowerCase() == \"b\") {\n                l += 1;\n            } else if (mark[markPointer].toLowerCase() == \"h\") {\n                l += 2;\n            } else if (mark[markPointer].toLowerCase() == \"l\") {\n                l += 4;\n            } else {\n                throw (\"'unpack' error. Got invalid mark.\");\n            }\n        }\n\n        if (l != str.length) {\n            throw (\"'unpack' error. Mismatch between symbol and string length. \" + l + \":\" + str.length);\n        }\n\n        var littleEndian;\n        if (mark[0] == \"<\") {\n            littleEndian = true;\n        } else if (mark[0] == \">\") {\n            littleEndian = false;\n        } else {\n            throw (\"'unpack' error.\");\n        }\n        var unpacked = [];\n        var strPointer = 0;\n        var p = 1;\n        var val = null;\n        var c = null;\n        var length = null;\n        var sliced = \"\";\n\n        while (c = mark[p]) {\n            if (c.toLowerCase() == \"b\") {\n                length = 1;\n                sliced = str.slice(strPointer, strPointer + length);\n                val = sliced.charCodeAt(0);\n                if ((c == \"b\") && (val >= 0x80)) {\n                    val -= 0x100;\n                }\n            } else if (c == \"H\") {\n                length = 2;\n                sliced = str.slice(strPointer, strPointer + length);\n                if (littleEndian) {\n                    sliced = sliced.split(\"\").reverse().join(\"\");\n                }\n                val = sliced.charCodeAt(0) * 0x100 +\n                    sliced.charCodeAt(1);\n            } else if (c.toLowerCase() == \"l\") {\n                length = 4;\n                sliced = str.slice(strPointer, strPointer + length);\n                if (littleEndian) {\n                    sliced = sliced.split(\"\").reverse().join(\"\");\n                }\n                val = sliced.charCodeAt(0) * 0x1000000 +\n                    sliced.charCodeAt(1) * 0x10000 +\n                    sliced.charCodeAt(2) * 0x100 +\n                    sliced.charCodeAt(3);\n                if ((c == \"l\") && (val >= 0x80000000)) {\n                    val -= 0x100000000;\n                }\n            } else {\n                throw (\"'unpack' error. \" + c);\n            }\n\n            unpacked.push(val);\n            strPointer += length;\n            p += 1;\n        }\n\n        return unpacked;\n    }\n\n    function nStr(ch, num) {\n        var str = \"\";\n        for (var i = 0; i < num; i++) {\n            str += ch;\n        }\n        return str;\n    }\n\n    function splitIntoSegments(data) {\n        if (data.slice(0, 2) != \"\\xff\\xd8\") {\n            throw (\"Given data isn't JPEG.\");\n        }\n\n        var head = 2;\n        var segments = [\"\\xff\\xd8\"];\n        while (true) {\n            if (data.slice(head, head + 2) == \"\\xff\\xda\") {\n                segments.push(data.slice(head));\n                break;\n            } else {\n                var length = unpack(\">H\", data.slice(head + 2, head + 4))[0];\n                var endPoint = head + length + 2;\n                segments.push(data.slice(head, endPoint));\n                head = endPoint;\n            }\n\n            if (head >= data.length) {\n                throw (\"Wrong JPEG data.\");\n            }\n        }\n        return segments;\n    }\n\n\n    function getExifSeg(segments) {\n        var seg;\n        for (var i = 0; i < segments.length; i++) {\n            seg = segments[i];\n            if (seg.slice(0, 2) == \"\\xff\\xe1\" &&\n                   seg.slice(4, 10) == \"Exif\\x00\\x00\") {\n                return seg;\n            }\n        }\n        return null;\n    }\n\n\n    function mergeSegments(segments, exif) {\n        \n        if (segments[1].slice(0, 2) == \"\\xff\\xe0\" &&\n            (segments[2].slice(0, 2) == \"\\xff\\xe1\" &&\n             segments[2].slice(4, 10) == \"Exif\\x00\\x00\")) {\n            if (exif) {\n                segments[2] = exif;\n                segments = [\"\\xff\\xd8\"].concat(segments.slice(2));\n            } else if (exif == null) {\n                segments = segments.slice(0, 2).concat(segments.slice(3));\n            } else {\n                segments = segments.slice(0).concat(segments.slice(2));\n            }\n        } else if (segments[1].slice(0, 2) == \"\\xff\\xe0\") {\n            if (exif) {\n                segments[1] = exif;\n            }\n        } else if (segments[1].slice(0, 2) == \"\\xff\\xe1\" &&\n                   segments[1].slice(4, 10) == \"Exif\\x00\\x00\") {\n            if (exif) {\n                segments[1] = exif;\n            } else if (exif == null) {\n                segments = segments.slice(0).concat(segments.slice(2));\n            }\n        } else {\n            if (exif) {\n                segments = [segments[0], exif].concat(segments.slice(1));\n            }\n        }\n        \n        return segments.join(\"\");\n    }\n\n\n    function toHex(str) {\n        var hexStr = \"\";\n        for (var i = 0; i < str.length; i++) {\n            var h = str.charCodeAt(i);\n            var hex = ((h < 10) ? \"0\" : \"\") + h.toString(16);\n            hexStr += hex + \" \";\n        }\n        return hexStr;\n    }\n\n\n    var TYPES = {\n        \"Byte\": 1,\n        \"Ascii\": 2,\n        \"Short\": 3,\n        \"Long\": 4,\n        \"Rational\": 5,\n        \"Undefined\": 7,\n        \"SLong\": 9,\n        \"SRational\": 10\n    };\n\n\n    var TAGS = {\n        'Image': {\n            11: {\n                'name': 'ProcessingSoftware',\n                'type': 'Ascii'\n            },\n            254: {\n                'name': 'NewSubfileType',\n                'type': 'Long'\n            },\n            255: {\n                'name': 'SubfileType',\n                'type': 'Short'\n            },\n            256: {\n                'name': 'ImageWidth',\n                'type': 'Long'\n            },\n            257: {\n                'name': 'ImageLength',\n                'type': 'Long'\n            },\n            258: {\n                'name': 'BitsPerSample',\n                'type': 'Short'\n            },\n            259: {\n                'name': 'Compression',\n                'type': 'Short'\n            },\n            262: {\n                'name': 'PhotometricInterpretation',\n                'type': 'Short'\n            },\n            263: {\n                'name': 'Threshholding',\n                'type': 'Short'\n            },\n            264: {\n                'name': 'CellWidth',\n                'type': 'Short'\n            },\n            265: {\n                'name': 'CellLength',\n                'type': 'Short'\n            },\n            266: {\n                'name': 'FillOrder',\n                'type': 'Short'\n            },\n            269: {\n                'name': 'DocumentName',\n                'type': 'Ascii'\n            },\n            270: {\n                'name': 'ImageDescription',\n                'type': 'Ascii'\n            },\n            271: {\n                'name': 'Make',\n                'type': 'Ascii'\n            },\n            272: {\n                'name': 'Model',\n                'type': 'Ascii'\n            },\n            273: {\n                'name': 'StripOffsets',\n                'type': 'Long'\n            },\n            274: {\n                'name': 'Orientation',\n                'type': 'Short'\n            },\n            277: {\n                'name': 'SamplesPerPixel',\n                'type': 'Short'\n            },\n            278: {\n                'name': 'RowsPerStrip',\n                'type': 'Long'\n            },\n            279: {\n                'name': 'StripByteCounts',\n                'type': 'Long'\n            },\n            282: {\n                'name': 'XResolution',\n                'type': 'Rational'\n            },\n            283: {\n                'name': 'YResolution',\n                'type': 'Rational'\n            },\n            284: {\n                'name': 'PlanarConfiguration',\n                'type': 'Short'\n            },\n            290: {\n                'name': 'GrayResponseUnit',\n                'type': 'Short'\n            },\n            291: {\n                'name': 'GrayResponseCurve',\n                'type': 'Short'\n            },\n            292: {\n                'name': 'T4Options',\n                'type': 'Long'\n            },\n            293: {\n                'name': 'T6Options',\n                'type': 'Long'\n            },\n            296: {\n                'name': 'ResolutionUnit',\n                'type': 'Short'\n            },\n            301: {\n                'name': 'TransferFunction',\n                'type': 'Short'\n            },\n            305: {\n                'name': 'Software',\n                'type': 'Ascii'\n            },\n            306: {\n                'name': 'DateTime',\n                'type': 'Ascii'\n            },\n            315: {\n                'name': 'Artist',\n                'type': 'Ascii'\n            },\n            316: {\n                'name': 'HostComputer',\n                'type': 'Ascii'\n            },\n            317: {\n                'name': 'Predictor',\n                'type': 'Short'\n            },\n            318: {\n                'name': 'WhitePoint',\n                'type': 'Rational'\n            },\n            319: {\n                'name': 'PrimaryChromaticities',\n                'type': 'Rational'\n            },\n            320: {\n                'name': 'ColorMap',\n                'type': 'Short'\n            },\n            321: {\n                'name': 'HalftoneHints',\n                'type': 'Short'\n            },\n            322: {\n                'name': 'TileWidth',\n                'type': 'Short'\n            },\n            323: {\n                'name': 'TileLength',\n                'type': 'Short'\n            },\n            324: {\n                'name': 'TileOffsets',\n                'type': 'Short'\n            },\n            325: {\n                'name': 'TileByteCounts',\n                'type': 'Short'\n            },\n            330: {\n                'name': 'SubIFDs',\n                'type': 'Long'\n            },\n            332: {\n                'name': 'InkSet',\n                'type': 'Short'\n            },\n            333: {\n                'name': 'InkNames',\n                'type': 'Ascii'\n            },\n            334: {\n                'name': 'NumberOfInks',\n                'type': 'Short'\n            },\n            336: {\n                'name': 'DotRange',\n                'type': 'Byte'\n            },\n            337: {\n                'name': 'TargetPrinter',\n                'type': 'Ascii'\n            },\n            338: {\n                'name': 'ExtraSamples',\n                'type': 'Short'\n            },\n            339: {\n                'name': 'SampleFormat',\n                'type': 'Short'\n            },\n            340: {\n                'name': 'SMinSampleValue',\n                'type': 'Short'\n            },\n            341: {\n                'name': 'SMaxSampleValue',\n                'type': 'Short'\n            },\n            342: {\n                'name': 'TransferRange',\n                'type': 'Short'\n            },\n            343: {\n                'name': 'ClipPath',\n                'type': 'Byte'\n            },\n            344: {\n                'name': 'XClipPathUnits',\n                'type': 'Long'\n            },\n            345: {\n                'name': 'YClipPathUnits',\n                'type': 'Long'\n            },\n            346: {\n                'name': 'Indexed',\n                'type': 'Short'\n            },\n            347: {\n                'name': 'JPEGTables',\n                'type': 'Undefined'\n            },\n            351: {\n                'name': 'OPIProxy',\n                'type': 'Short'\n            },\n            512: {\n                'name': 'JPEGProc',\n                'type': 'Long'\n            },\n            513: {\n                'name': 'JPEGInterchangeFormat',\n                'type': 'Long'\n            },\n            514: {\n                'name': 'JPEGInterchangeFormatLength',\n                'type': 'Long'\n            },\n            515: {\n                'name': 'JPEGRestartInterval',\n                'type': 'Short'\n            },\n            517: {\n                'name': 'JPEGLosslessPredictors',\n                'type': 'Short'\n            },\n            518: {\n                'name': 'JPEGPointTransforms',\n                'type': 'Short'\n            },\n            519: {\n                'name': 'JPEGQTables',\n                'type': 'Long'\n            },\n            520: {\n                'name': 'JPEGDCTables',\n                'type': 'Long'\n            },\n            521: {\n                'name': 'JPEGACTables',\n                'type': 'Long'\n            },\n            529: {\n                'name': 'YCbCrCoefficients',\n                'type': 'Rational'\n            },\n            530: {\n                'name': 'YCbCrSubSampling',\n                'type': 'Short'\n            },\n            531: {\n                'name': 'YCbCrPositioning',\n                'type': 'Short'\n            },\n            532: {\n                'name': 'ReferenceBlackWhite',\n                'type': 'Rational'\n            },\n            700: {\n                'name': 'XMLPacket',\n                'type': 'Byte'\n            },\n            18246: {\n                'name': 'Rating',\n                'type': 'Short'\n            },\n            18249: {\n                'name': 'RatingPercent',\n                'type': 'Short'\n            },\n            32781: {\n                'name': 'ImageID',\n                'type': 'Ascii'\n            },\n            33421: {\n                'name': 'CFARepeatPatternDim',\n                'type': 'Short'\n            },\n            33422: {\n                'name': 'CFAPattern',\n                'type': 'Byte'\n            },\n            33423: {\n                'name': 'BatteryLevel',\n                'type': 'Rational'\n            },\n            33432: {\n                'name': 'Copyright',\n                'type': 'Ascii'\n            },\n            33434: {\n                'name': 'ExposureTime',\n                'type': 'Rational'\n            },\n            34377: {\n                'name': 'ImageResources',\n                'type': 'Byte'\n            },\n            34665: {\n                'name': 'ExifTag',\n                'type': 'Long'\n            },\n            34675: {\n                'name': 'InterColorProfile',\n                'type': 'Undefined'\n            },\n            34853: {\n                'name': 'GPSTag',\n                'type': 'Long'\n            },\n            34857: {\n                'name': 'Interlace',\n                'type': 'Short'\n            },\n            34858: {\n                'name': 'TimeZoneOffset',\n                'type': 'Long'\n            },\n            34859: {\n                'name': 'SelfTimerMode',\n                'type': 'Short'\n            },\n            37387: {\n                'name': 'FlashEnergy',\n                'type': 'Rational'\n            },\n            37388: {\n                'name': 'SpatialFrequencyResponse',\n                'type': 'Undefined'\n            },\n            37389: {\n                'name': 'Noise',\n                'type': 'Undefined'\n            },\n            37390: {\n                'name': 'FocalPlaneXResolution',\n                'type': 'Rational'\n            },\n            37391: {\n                'name': 'FocalPlaneYResolution',\n                'type': 'Rational'\n            },\n            37392: {\n                'name': 'FocalPlaneResolutionUnit',\n                'type': 'Short'\n            },\n            37393: {\n                'name': 'ImageNumber',\n                'type': 'Long'\n            },\n            37394: {\n                'name': 'SecurityClassification',\n                'type': 'Ascii'\n            },\n            37395: {\n                'name': 'ImageHistory',\n                'type': 'Ascii'\n            },\n            37397: {\n                'name': 'ExposureIndex',\n                'type': 'Rational'\n            },\n            37398: {\n                'name': 'TIFFEPStandardID',\n                'type': 'Byte'\n            },\n            37399: {\n                'name': 'SensingMethod',\n                'type': 'Short'\n            },\n            40091: {\n                'name': 'XPTitle',\n                'type': 'Byte'\n            },\n            40092: {\n                'name': 'XPComment',\n                'type': 'Byte'\n            },\n            40093: {\n                'name': 'XPAuthor',\n                'type': 'Byte'\n            },\n            40094: {\n                'name': 'XPKeywords',\n                'type': 'Byte'\n            },\n            40095: {\n                'name': 'XPSubject',\n                'type': 'Byte'\n            },\n            50341: {\n                'name': 'PrintImageMatching',\n                'type': 'Undefined'\n            },\n            50706: {\n                'name': 'DNGVersion',\n                'type': 'Byte'\n            },\n            50707: {\n                'name': 'DNGBackwardVersion',\n                'type': 'Byte'\n            },\n            50708: {\n                'name': 'UniqueCameraModel',\n                'type': 'Ascii'\n            },\n            50709: {\n                'name': 'LocalizedCameraModel',\n                'type': 'Byte'\n            },\n            50710: {\n                'name': 'CFAPlaneColor',\n                'type': 'Byte'\n            },\n            50711: {\n                'name': 'CFALayout',\n                'type': 'Short'\n            },\n            50712: {\n                'name': 'LinearizationTable',\n                'type': 'Short'\n            },\n            50713: {\n                'name': 'BlackLevelRepeatDim',\n                'type': 'Short'\n            },\n            50714: {\n                'name': 'BlackLevel',\n                'type': 'Rational'\n            },\n            50715: {\n                'name': 'BlackLevelDeltaH',\n                'type': 'SRational'\n            },\n            50716: {\n                'name': 'BlackLevelDeltaV',\n                'type': 'SRational'\n            },\n            50717: {\n                'name': 'WhiteLevel',\n                'type': 'Short'\n            },\n            50718: {\n                'name': 'DefaultScale',\n                'type': 'Rational'\n            },\n            50719: {\n                'name': 'DefaultCropOrigin',\n                'type': 'Short'\n            },\n            50720: {\n                'name': 'DefaultCropSize',\n                'type': 'Short'\n            },\n            50721: {\n                'name': 'ColorMatrix1',\n                'type': 'SRational'\n            },\n            50722: {\n                'name': 'ColorMatrix2',\n                'type': 'SRational'\n            },\n            50723: {\n                'name': 'CameraCalibration1',\n                'type': 'SRational'\n            },\n            50724: {\n                'name': 'CameraCalibration2',\n                'type': 'SRational'\n            },\n            50725: {\n                'name': 'ReductionMatrix1',\n                'type': 'SRational'\n            },\n            50726: {\n                'name': 'ReductionMatrix2',\n                'type': 'SRational'\n            },\n            50727: {\n                'name': 'AnalogBalance',\n                'type': 'Rational'\n            },\n            50728: {\n                'name': 'AsShotNeutral',\n                'type': 'Short'\n            },\n            50729: {\n                'name': 'AsShotWhiteXY',\n                'type': 'Rational'\n            },\n            50730: {\n                'name': 'BaselineExposure',\n                'type': 'SRational'\n            },\n            50731: {\n                'name': 'BaselineNoise',\n                'type': 'Rational'\n            },\n            50732: {\n                'name': 'BaselineSharpness',\n                'type': 'Rational'\n            },\n            50733: {\n                'name': 'BayerGreenSplit',\n                'type': 'Long'\n            },\n            50734: {\n                'name': 'LinearResponseLimit',\n                'type': 'Rational'\n            },\n            50735: {\n                'name': 'CameraSerialNumber',\n                'type': 'Ascii'\n            },\n            50736: {\n                'name': 'LensInfo',\n                'type': 'Rational'\n            },\n            50737: {\n                'name': 'ChromaBlurRadius',\n                'type': 'Rational'\n            },\n            50738: {\n                'name': 'AntiAliasStrength',\n                'type': 'Rational'\n            },\n            50739: {\n                'name': 'ShadowScale',\n                'type': 'SRational'\n            },\n            50740: {\n                'name': 'DNGPrivateData',\n                'type': 'Byte'\n            },\n            50741: {\n                'name': 'MakerNoteSafety',\n                'type': 'Short'\n            },\n            50778: {\n                'name': 'CalibrationIlluminant1',\n                'type': 'Short'\n            },\n            50779: {\n                'name': 'CalibrationIlluminant2',\n                'type': 'Short'\n            },\n            50780: {\n                'name': 'BestQualityScale',\n                'type': 'Rational'\n            },\n            50781: {\n                'name': 'RawDataUniqueID',\n                'type': 'Byte'\n            },\n            50827: {\n                'name': 'OriginalRawFileName',\n                'type': 'Byte'\n            },\n            50828: {\n                'name': 'OriginalRawFileData',\n                'type': 'Undefined'\n            },\n            50829: {\n                'name': 'ActiveArea',\n                'type': 'Short'\n            },\n            50830: {\n                'name': 'MaskedAreas',\n                'type': 'Short'\n            },\n            50831: {\n                'name': 'AsShotICCProfile',\n                'type': 'Undefined'\n            },\n            50832: {\n                'name': 'AsShotPreProfileMatrix',\n                'type': 'SRational'\n            },\n            50833: {\n                'name': 'CurrentICCProfile',\n                'type': 'Undefined'\n            },\n            50834: {\n                'name': 'CurrentPreProfileMatrix',\n                'type': 'SRational'\n            },\n            50879: {\n                'name': 'ColorimetricReference',\n                'type': 'Short'\n            },\n            50931: {\n                'name': 'CameraCalibrationSignature',\n                'type': 'Byte'\n            },\n            50932: {\n                'name': 'ProfileCalibrationSignature',\n                'type': 'Byte'\n            },\n            50934: {\n                'name': 'AsShotProfileName',\n                'type': 'Byte'\n            },\n            50935: {\n                'name': 'NoiseReductionApplied',\n                'type': 'Rational'\n            },\n            50936: {\n                'name': 'ProfileName',\n                'type': 'Byte'\n            },\n            50937: {\n                'name': 'ProfileHueSatMapDims',\n                'type': 'Long'\n            },\n            50938: {\n                'name': 'ProfileHueSatMapData1',\n                'type': 'Float'\n            },\n            50939: {\n                'name': 'ProfileHueSatMapData2',\n                'type': 'Float'\n            },\n            50940: {\n                'name': 'ProfileToneCurve',\n                'type': 'Float'\n            },\n            50941: {\n                'name': 'ProfileEmbedPolicy',\n                'type': 'Long'\n            },\n            50942: {\n                'name': 'ProfileCopyright',\n                'type': 'Byte'\n            },\n            50964: {\n                'name': 'ForwardMatrix1',\n                'type': 'SRational'\n            },\n            50965: {\n                'name': 'ForwardMatrix2',\n                'type': 'SRational'\n            },\n            50966: {\n                'name': 'PreviewApplicationName',\n                'type': 'Byte'\n            },\n            50967: {\n                'name': 'PreviewApplicationVersion',\n                'type': 'Byte'\n            },\n            50968: {\n                'name': 'PreviewSettingsName',\n                'type': 'Byte'\n            },\n            50969: {\n                'name': 'PreviewSettingsDigest',\n                'type': 'Byte'\n            },\n            50970: {\n                'name': 'PreviewColorSpace',\n                'type': 'Long'\n            },\n            50971: {\n                'name': 'PreviewDateTime',\n                'type': 'Ascii'\n            },\n            50972: {\n                'name': 'RawImageDigest',\n                'type': 'Undefined'\n            },\n            50973: {\n                'name': 'OriginalRawFileDigest',\n                'type': 'Undefined'\n            },\n            50974: {\n                'name': 'SubTileBlockSize',\n                'type': 'Long'\n            },\n            50975: {\n                'name': 'RowInterleaveFactor',\n                'type': 'Long'\n            },\n            50981: {\n                'name': 'ProfileLookTableDims',\n                'type': 'Long'\n            },\n            50982: {\n                'name': 'ProfileLookTableData',\n                'type': 'Float'\n            },\n            51008: {\n                'name': 'OpcodeList1',\n                'type': 'Undefined'\n            },\n            51009: {\n                'name': 'OpcodeList2',\n                'type': 'Undefined'\n            },\n            51022: {\n                'name': 'OpcodeList3',\n                'type': 'Undefined'\n            }\n        },\n        'Exif': {\n            33434: {\n                'name': 'ExposureTime',\n                'type': 'Rational'\n            },\n            33437: {\n                'name': 'FNumber',\n                'type': 'Rational'\n            },\n            34850: {\n                'name': 'ExposureProgram',\n                'type': 'Short'\n            },\n            34852: {\n                'name': 'SpectralSensitivity',\n                'type': 'Ascii'\n            },\n            34855: {\n                'name': 'ISOSpeedRatings',\n                'type': 'Short'\n            },\n            34856: {\n                'name': 'OECF',\n                'type': 'Undefined'\n            },\n            34864: {\n                'name': 'SensitivityType',\n                'type': 'Short'\n            },\n            34865: {\n                'name': 'StandardOutputSensitivity',\n                'type': 'Long'\n            },\n            34866: {\n                'name': 'RecommendedExposureIndex',\n                'type': 'Long'\n            },\n            34867: {\n                'name': 'ISOSpeed',\n                'type': 'Long'\n            },\n            34868: {\n                'name': 'ISOSpeedLatitudeyyy',\n                'type': 'Long'\n            },\n            34869: {\n                'name': 'ISOSpeedLatitudezzz',\n                'type': 'Long'\n            },\n            36864: {\n                'name': 'ExifVersion',\n                'type': 'Undefined'\n            },\n            36867: {\n                'name': 'DateTimeOriginal',\n                'type': 'Ascii'\n            },\n            36868: {\n                'name': 'DateTimeDigitized',\n                'type': 'Ascii'\n            },\n            37121: {\n                'name': 'ComponentsConfiguration',\n                'type': 'Undefined'\n            },\n            37122: {\n                'name': 'CompressedBitsPerPixel',\n                'type': 'Rational'\n            },\n            37377: {\n                'name': 'ShutterSpeedValue',\n                'type': 'SRational'\n            },\n            37378: {\n                'name': 'ApertureValue',\n                'type': 'Rational'\n            },\n            37379: {\n                'name': 'BrightnessValue',\n                'type': 'SRational'\n            },\n            37380: {\n                'name': 'ExposureBiasValue',\n                'type': 'SRational'\n            },\n            37381: {\n                'name': 'MaxApertureValue',\n                'type': 'Rational'\n            },\n            37382: {\n                'name': 'SubjectDistance',\n                'type': 'Rational'\n            },\n            37383: {\n                'name': 'MeteringMode',\n                'type': 'Short'\n            },\n            37384: {\n                'name': 'LightSource',\n                'type': 'Short'\n            },\n            37385: {\n                'name': 'Flash',\n                'type': 'Short'\n            },\n            37386: {\n                'name': 'FocalLength',\n                'type': 'Rational'\n            },\n            37396: {\n                'name': 'SubjectArea',\n                'type': 'Short'\n            },\n            37500: {\n                'name': 'MakerNote',\n                'type': 'Undefined'\n            },\n            37510: {\n                'name': 'UserComment',\n                'type': 'Ascii'\n            },\n            37520: {\n                'name': 'SubSecTime',\n                'type': 'Ascii'\n            },\n            37521: {\n                'name': 'SubSecTimeOriginal',\n                'type': 'Ascii'\n            },\n            37522: {\n                'name': 'SubSecTimeDigitized',\n                'type': 'Ascii'\n            },\n            40960: {\n                'name': 'FlashpixVersion',\n                'type': 'Undefined'\n            },\n            40961: {\n                'name': 'ColorSpace',\n                'type': 'Short'\n            },\n            40962: {\n                'name': 'PixelXDimension',\n                'type': 'Long'\n            },\n            40963: {\n                'name': 'PixelYDimension',\n                'type': 'Long'\n            },\n            40964: {\n                'name': 'RelatedSoundFile',\n                'type': 'Ascii'\n            },\n            40965: {\n                'name': 'InteroperabilityTag',\n                'type': 'Long'\n            },\n            41483: {\n                'name': 'FlashEnergy',\n                'type': 'Rational'\n            },\n            41484: {\n                'name': 'SpatialFrequencyResponse',\n                'type': 'Undefined'\n            },\n            41486: {\n                'name': 'FocalPlaneXResolution',\n                'type': 'Rational'\n            },\n            41487: {\n                'name': 'FocalPlaneYResolution',\n                'type': 'Rational'\n            },\n            41488: {\n                'name': 'FocalPlaneResolutionUnit',\n                'type': 'Short'\n            },\n            41492: {\n                'name': 'SubjectLocation',\n                'type': 'Short'\n            },\n            41493: {\n                'name': 'ExposureIndex',\n                'type': 'Rational'\n            },\n            41495: {\n                'name': 'SensingMethod',\n                'type': 'Short'\n            },\n            41728: {\n                'name': 'FileSource',\n                'type': 'Undefined'\n            },\n            41729: {\n                'name': 'SceneType',\n                'type': 'Undefined'\n            },\n            41730: {\n                'name': 'CFAPattern',\n                'type': 'Undefined'\n            },\n            41985: {\n                'name': 'CustomRendered',\n                'type': 'Short'\n            },\n            41986: {\n                'name': 'ExposureMode',\n                'type': 'Short'\n            },\n            41987: {\n                'name': 'WhiteBalance',\n                'type': 'Short'\n            },\n            41988: {\n                'name': 'DigitalZoomRatio',\n                'type': 'Rational'\n            },\n            41989: {\n                'name': 'FocalLengthIn35mmFilm',\n                'type': 'Short'\n            },\n            41990: {\n                'name': 'SceneCaptureType',\n                'type': 'Short'\n            },\n            41991: {\n                'name': 'GainControl',\n                'type': 'Short'\n            },\n            41992: {\n                'name': 'Contrast',\n                'type': 'Short'\n            },\n            41993: {\n                'name': 'Saturation',\n                'type': 'Short'\n            },\n            41994: {\n                'name': 'Sharpness',\n                'type': 'Short'\n            },\n            41995: {\n                'name': 'DeviceSettingDescription',\n                'type': 'Undefined'\n            },\n            41996: {\n                'name': 'SubjectDistanceRange',\n                'type': 'Short'\n            },\n            42016: {\n                'name': 'ImageUniqueID',\n                'type': 'Ascii'\n            },\n            42032: {\n                'name': 'CameraOwnerName',\n                'type': 'Ascii'\n            },\n            42033: {\n                'name': 'BodySerialNumber',\n                'type': 'Ascii'\n            },\n            42034: {\n                'name': 'LensSpecification',\n                'type': 'Rational'\n            },\n            42035: {\n                'name': 'LensMake',\n                'type': 'Ascii'\n            },\n            42036: {\n                'name': 'LensModel',\n                'type': 'Ascii'\n            },\n            42037: {\n                'name': 'LensSerialNumber',\n                'type': 'Ascii'\n            },\n            42240: {\n                'name': 'Gamma',\n                'type': 'Rational'\n            }\n        },\n        'GPS': {\n            0: {\n                'name': 'GPSVersionID',\n                'type': 'Byte'\n            },\n            1: {\n                'name': 'GPSLatitudeRef',\n                'type': 'Ascii'\n            },\n            2: {\n                'name': 'GPSLatitude',\n                'type': 'Rational'\n            },\n            3: {\n                'name': 'GPSLongitudeRef',\n                'type': 'Ascii'\n            },\n            4: {\n                'name': 'GPSLongitude',\n                'type': 'Rational'\n            },\n            5: {\n                'name': 'GPSAltitudeRef',\n                'type': 'Byte'\n            },\n            6: {\n                'name': 'GPSAltitude',\n                'type': 'Rational'\n            },\n            7: {\n                'name': 'GPSTimeStamp',\n                'type': 'Rational'\n            },\n            8: {\n                'name': 'GPSSatellites',\n                'type': 'Ascii'\n            },\n            9: {\n                'name': 'GPSStatus',\n                'type': 'Ascii'\n            },\n            10: {\n                'name': 'GPSMeasureMode',\n                'type': 'Ascii'\n            },\n            11: {\n                'name': 'GPSDOP',\n                'type': 'Rational'\n            },\n            12: {\n                'name': 'GPSSpeedRef',\n                'type': 'Ascii'\n            },\n            13: {\n                'name': 'GPSSpeed',\n                'type': 'Rational'\n            },\n            14: {\n                'name': 'GPSTrackRef',\n                'type': 'Ascii'\n            },\n            15: {\n                'name': 'GPSTrack',\n                'type': 'Rational'\n            },\n            16: {\n                'name': 'GPSImgDirectionRef',\n                'type': 'Ascii'\n            },\n            17: {\n                'name': 'GPSImgDirection',\n                'type': 'Rational'\n            },\n            18: {\n                'name': 'GPSMapDatum',\n                'type': 'Ascii'\n            },\n            19: {\n                'name': 'GPSDestLatitudeRef',\n                'type': 'Ascii'\n            },\n            20: {\n                'name': 'GPSDestLatitude',\n                'type': 'Rational'\n            },\n            21: {\n                'name': 'GPSDestLongitudeRef',\n                'type': 'Ascii'\n            },\n            22: {\n                'name': 'GPSDestLongitude',\n                'type': 'Rational'\n            },\n            23: {\n                'name': 'GPSDestBearingRef',\n                'type': 'Ascii'\n            },\n            24: {\n                'name': 'GPSDestBearing',\n                'type': 'Rational'\n            },\n            25: {\n                'name': 'GPSDestDistanceRef',\n                'type': 'Ascii'\n            },\n            26: {\n                'name': 'GPSDestDistance',\n                'type': 'Rational'\n            },\n            27: {\n                'name': 'GPSProcessingMethod',\n                'type': 'Undefined'\n            },\n            28: {\n                'name': 'GPSAreaInformation',\n                'type': 'Undefined'\n            },\n            29: {\n                'name': 'GPSDateStamp',\n                'type': 'Ascii'\n            },\n            30: {\n                'name': 'GPSDifferential',\n                'type': 'Short'\n            },\n            31: {\n                'name': 'GPSHPositioningError',\n                'type': 'Rational'\n            }\n        },\n        'Interop': {\n            1: {\n                'name': 'InteroperabilityIndex',\n                'type': 'Ascii'\n            }\n        },\n    };\n    TAGS[\"0th\"] = TAGS[\"Image\"];\n    TAGS[\"1st\"] = TAGS[\"Image\"];\n    that.TAGS = TAGS;\n\n    \n    that.ImageIFD = {\n        ProcessingSoftware:11,\n        NewSubfileType:254,\n        SubfileType:255,\n        ImageWidth:256,\n        ImageLength:257,\n        BitsPerSample:258,\n        Compression:259,\n        PhotometricInterpretation:262,\n        Threshholding:263,\n        CellWidth:264,\n        CellLength:265,\n        FillOrder:266,\n        DocumentName:269,\n        ImageDescription:270,\n        Make:271,\n        Model:272,\n        StripOffsets:273,\n        Orientation:274,\n        SamplesPerPixel:277,\n        RowsPerStrip:278,\n        StripByteCounts:279,\n        XResolution:282,\n        YResolution:283,\n        PlanarConfiguration:284,\n        GrayResponseUnit:290,\n        GrayResponseCurve:291,\n        T4Options:292,\n        T6Options:293,\n        ResolutionUnit:296,\n        TransferFunction:301,\n        Software:305,\n        DateTime:306,\n        Artist:315,\n        HostComputer:316,\n        Predictor:317,\n        WhitePoint:318,\n        PrimaryChromaticities:319,\n        ColorMap:320,\n        HalftoneHints:321,\n        TileWidth:322,\n        TileLength:323,\n        TileOffsets:324,\n        TileByteCounts:325,\n        SubIFDs:330,\n        InkSet:332,\n        InkNames:333,\n        NumberOfInks:334,\n        DotRange:336,\n        TargetPrinter:337,\n        ExtraSamples:338,\n        SampleFormat:339,\n        SMinSampleValue:340,\n        SMaxSampleValue:341,\n        TransferRange:342,\n        ClipPath:343,\n        XClipPathUnits:344,\n        YClipPathUnits:345,\n        Indexed:346,\n        JPEGTables:347,\n        OPIProxy:351,\n        JPEGProc:512,\n        JPEGInterchangeFormat:513,\n        JPEGInterchangeFormatLength:514,\n        JPEGRestartInterval:515,\n        JPEGLosslessPredictors:517,\n        JPEGPointTransforms:518,\n        JPEGQTables:519,\n        JPEGDCTables:520,\n        JPEGACTables:521,\n        YCbCrCoefficients:529,\n        YCbCrSubSampling:530,\n        YCbCrPositioning:531,\n        ReferenceBlackWhite:532,\n        XMLPacket:700,\n        Rating:18246,\n        RatingPercent:18249,\n        ImageID:32781,\n        CFARepeatPatternDim:33421,\n        CFAPattern:33422,\n        BatteryLevel:33423,\n        Copyright:33432,\n        ExposureTime:33434,\n        ImageResources:34377,\n        ExifTag:34665,\n        InterColorProfile:34675,\n        GPSTag:34853,\n        Interlace:34857,\n        TimeZoneOffset:34858,\n        SelfTimerMode:34859,\n        FlashEnergy:37387,\n        SpatialFrequencyResponse:37388,\n        Noise:37389,\n        FocalPlaneXResolution:37390,\n        FocalPlaneYResolution:37391,\n        FocalPlaneResolutionUnit:37392,\n        ImageNumber:37393,\n        SecurityClassification:37394,\n        ImageHistory:37395,\n        ExposureIndex:37397,\n        TIFFEPStandardID:37398,\n        SensingMethod:37399,\n        XPTitle:40091,\n        XPComment:40092,\n        XPAuthor:40093,\n        XPKeywords:40094,\n        XPSubject:40095,\n        PrintImageMatching:50341,\n        DNGVersion:50706,\n        DNGBackwardVersion:50707,\n        UniqueCameraModel:50708,\n        LocalizedCameraModel:50709,\n        CFAPlaneColor:50710,\n        CFALayout:50711,\n        LinearizationTable:50712,\n        BlackLevelRepeatDim:50713,\n        BlackLevel:50714,\n        BlackLevelDeltaH:50715,\n        BlackLevelDeltaV:50716,\n        WhiteLevel:50717,\n        DefaultScale:50718,\n        DefaultCropOrigin:50719,\n        DefaultCropSize:50720,\n        ColorMatrix1:50721,\n        ColorMatrix2:50722,\n        CameraCalibration1:50723,\n        CameraCalibration2:50724,\n        ReductionMatrix1:50725,\n        ReductionMatrix2:50726,\n        AnalogBalance:50727,\n        AsShotNeutral:50728,\n        AsShotWhiteXY:50729,\n        BaselineExposure:50730,\n        BaselineNoise:50731,\n        BaselineSharpness:50732,\n        BayerGreenSplit:50733,\n        LinearResponseLimit:50734,\n        CameraSerialNumber:50735,\n        LensInfo:50736,\n        ChromaBlurRadius:50737,\n        AntiAliasStrength:50738,\n        ShadowScale:50739,\n        DNGPrivateData:50740,\n        MakerNoteSafety:50741,\n        CalibrationIlluminant1:50778,\n        CalibrationIlluminant2:50779,\n        BestQualityScale:50780,\n        RawDataUniqueID:50781,\n        OriginalRawFileName:50827,\n        OriginalRawFileData:50828,\n        ActiveArea:50829,\n        MaskedAreas:50830,\n        AsShotICCProfile:50831,\n        AsShotPreProfileMatrix:50832,\n        CurrentICCProfile:50833,\n        CurrentPreProfileMatrix:50834,\n        ColorimetricReference:50879,\n        CameraCalibrationSignature:50931,\n        ProfileCalibrationSignature:50932,\n        AsShotProfileName:50934,\n        NoiseReductionApplied:50935,\n        ProfileName:50936,\n        ProfileHueSatMapDims:50937,\n        ProfileHueSatMapData1:50938,\n        ProfileHueSatMapData2:50939,\n        ProfileToneCurve:50940,\n        ProfileEmbedPolicy:50941,\n        ProfileCopyright:50942,\n        ForwardMatrix1:50964,\n        ForwardMatrix2:50965,\n        PreviewApplicationName:50966,\n        PreviewApplicationVersion:50967,\n        PreviewSettingsName:50968,\n        PreviewSettingsDigest:50969,\n        PreviewColorSpace:50970,\n        PreviewDateTime:50971,\n        RawImageDigest:50972,\n        OriginalRawFileDigest:50973,\n        SubTileBlockSize:50974,\n        RowInterleaveFactor:50975,\n        ProfileLookTableDims:50981,\n        ProfileLookTableData:50982,\n        OpcodeList1:51008,\n        OpcodeList2:51009,\n        OpcodeList3:51022,\n        NoiseProfile:51041,\n    };\n\n    \n    that.ExifIFD = {\n        ExposureTime:33434,\n        FNumber:33437,\n        ExposureProgram:34850,\n        SpectralSensitivity:34852,\n        ISOSpeedRatings:34855,\n        OECF:34856,\n        SensitivityType:34864,\n        StandardOutputSensitivity:34865,\n        RecommendedExposureIndex:34866,\n        ISOSpeed:34867,\n        ISOSpeedLatitudeyyy:34868,\n        ISOSpeedLatitudezzz:34869,\n        ExifVersion:36864,\n        DateTimeOriginal:36867,\n        DateTimeDigitized:36868,\n        ComponentsConfiguration:37121,\n        CompressedBitsPerPixel:37122,\n        ShutterSpeedValue:37377,\n        ApertureValue:37378,\n        BrightnessValue:37379,\n        ExposureBiasValue:37380,\n        MaxApertureValue:37381,\n        SubjectDistance:37382,\n        MeteringMode:37383,\n        LightSource:37384,\n        Flash:37385,\n        FocalLength:37386,\n        SubjectArea:37396,\n        MakerNote:37500,\n        UserComment:37510,\n        SubSecTime:37520,\n        SubSecTimeOriginal:37521,\n        SubSecTimeDigitized:37522,\n        FlashpixVersion:40960,\n        ColorSpace:40961,\n        PixelXDimension:40962,\n        PixelYDimension:40963,\n        RelatedSoundFile:40964,\n        InteroperabilityTag:40965,\n        FlashEnergy:41483,\n        SpatialFrequencyResponse:41484,\n        FocalPlaneXResolution:41486,\n        FocalPlaneYResolution:41487,\n        FocalPlaneResolutionUnit:41488,\n        SubjectLocation:41492,\n        ExposureIndex:41493,\n        SensingMethod:41495,\n        FileSource:41728,\n        SceneType:41729,\n        CFAPattern:41730,\n        CustomRendered:41985,\n        ExposureMode:41986,\n        WhiteBalance:41987,\n        DigitalZoomRatio:41988,\n        FocalLengthIn35mmFilm:41989,\n        SceneCaptureType:41990,\n        GainControl:41991,\n        Contrast:41992,\n        Saturation:41993,\n        Sharpness:41994,\n        DeviceSettingDescription:41995,\n        SubjectDistanceRange:41996,\n        ImageUniqueID:42016,\n        CameraOwnerName:42032,\n        BodySerialNumber:42033,\n        LensSpecification:42034,\n        LensMake:42035,\n        LensModel:42036,\n        LensSerialNumber:42037,\n        Gamma:42240,\n    };\n\n\n    that.GPSIFD = {\n        GPSVersionID:0,\n        GPSLatitudeRef:1,\n        GPSLatitude:2,\n        GPSLongitudeRef:3,\n        GPSLongitude:4,\n        GPSAltitudeRef:5,\n        GPSAltitude:6,\n        GPSTimeStamp:7,\n        GPSSatellites:8,\n        GPSStatus:9,\n        GPSMeasureMode:10,\n        GPSDOP:11,\n        GPSSpeedRef:12,\n        GPSSpeed:13,\n        GPSTrackRef:14,\n        GPSTrack:15,\n        GPSImgDirectionRef:16,\n        GPSImgDirection:17,\n        GPSMapDatum:18,\n        GPSDestLatitudeRef:19,\n        GPSDestLatitude:20,\n        GPSDestLongitudeRef:21,\n        GPSDestLongitude:22,\n        GPSDestBearingRef:23,\n        GPSDestBearing:24,\n        GPSDestDistanceRef:25,\n        GPSDestDistance:26,\n        GPSProcessingMethod:27,\n        GPSAreaInformation:28,\n        GPSDateStamp:29,\n        GPSDifferential:30,\n        GPSHPositioningError:31,\n    };\n\n\n    that.InteropIFD = {\n        InteroperabilityIndex:1,\n    };\n\n    that.GPSHelper = {\n        degToDmsRational:function (degFloat) {\n            var minFloat = degFloat % 1 * 60;\n            var secFloat = minFloat % 1 * 60;\n            var deg = Math.floor(degFloat);\n            var min = Math.floor(minFloat);\n            var sec = Math.round(secFloat * 100);\n\n            return [[deg, 1], [min, 1], [sec, 100]];\n        }\n    };\n    \n    \n    if (typeof exports !== 'undefined') {\n        if (typeof module !== 'undefined' && module.exports) {\n            exports = module.exports = that;\n        }\n        exports.piexif = that;\n    } else {\n        window.piexif = that;\n    }\n\n})();\n"
  },
  {
    "path": "resources/assets/bootstrap-fileinput/js/plugins/purify.js",
    "content": "(function (global, factory) {\n\ttypeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :\n\ttypeof define === 'function' && define.amd ? define(factory) :\n\t(global.DOMPurify = factory());\n}(this, (function () { 'use strict';\n\nvar html = ['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'section', 'select', 'shadow', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr'];\n\n// SVG\nvar svg = ['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'audio', 'canvas', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'video', 'view', 'vkern'];\n\nvar svgFilters = ['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence'];\n\nvar mathMl = ['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmuliscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mpspace', 'msqrt', 'mystyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover'];\n\nvar text = ['#text'];\n\nvar html$1 = ['accept', 'action', 'align', 'alt', 'autocomplete', 'background', 'bgcolor', 'border', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'coords', 'crossorigin', 'datetime', 'default', 'dir', 'disabled', 'download', 'enctype', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'integrity', 'ismap', 'label', 'lang', 'list', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'multiple', 'name', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'pattern', 'placeholder', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'type', 'usemap', 'valign', 'value', 'width', 'xmlns'];\n\nvar svg$1 = ['accent-height', 'accumulate', 'additivive', 'alignment-baseline', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'specularconstant', 'specularexponent', 'spreadmethod', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'tabindex', 'targetx', 'targety', 'transform', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan'];\n\nvar mathMl$1 = ['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnsalign', 'columnlines', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lspace', 'lquote', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns'];\n\nvar xml = ['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink'];\n\n/* Add properties to a lookup table */\nfunction addToSet(set, array) {\n  var l = array.length;\n  while (l--) {\n    if (typeof array[l] === 'string') {\n      array[l] = array[l].toLowerCase();\n    }\n    set[array[l]] = true;\n  }\n  return set;\n}\n\n/* Shallow clone an object */\nfunction clone(object) {\n  var newObject = {};\n  var property = void 0;\n  for (property in object) {\n    if (Object.prototype.hasOwnProperty.call(object, property)) {\n      newObject[property] = object[property];\n    }\n  }\n  return newObject;\n}\n\nvar MUSTACHE_EXPR = /\\{\\{[\\s\\S]*|[\\s\\S]*\\}\\}/gm; // Specify template detection regex for SAFE_FOR_TEMPLATES mode\nvar ERB_EXPR = /<%[\\s\\S]*|[\\s\\S]*%>/gm;\nvar DATA_ATTR = /^data-[\\-\\w.\\u00B7-\\uFFFF]/; // eslint-disable-line no-useless-escape\nvar ARIA_ATTR = /^aria-[\\-\\w]+$/; // eslint-disable-line no-useless-escape\nvar IS_ALLOWED_URI = /^(?:(?:(?:f|ht)tps?|mailto|tel|callto|cid|xmpp):|[^a-z]|[a-z+.\\-]+(?:[^a-z+.\\-:]|$))/i; // eslint-disable-line no-useless-escape\nvar IS_SCRIPT_OR_DATA = /^(?:\\w+script|data):/i;\nvar ATTR_WHITESPACE = /[\\u0000-\\u0020\\u00A0\\u1680\\u180E\\u2000-\\u2029\\u205f\\u3000]/g; // eslint-disable-line no-control-regex\n\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\nfunction _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }\n\nvar getGlobal = function getGlobal() {\n  return typeof window === 'undefined' ? null : window;\n};\n\nfunction createDOMPurify() {\n  var window = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : getGlobal();\n\n  var DOMPurify = function DOMPurify(root) {\n    return createDOMPurify(root);\n  };\n\n  /**\n   * Version label, exposed for easier checks\n   * if DOMPurify is up to date or not\n   */\n  DOMPurify.version = '1.0.7';\n\n  /**\n   * Array of elements that DOMPurify removed during sanitation.\n   * Empty if nothing was removed.\n   */\n  DOMPurify.removed = [];\n\n  if (!window || !window.document || window.document.nodeType !== 9) {\n    // Not running in a browser, provide a factory function\n    // so that you can pass your own Window\n    DOMPurify.isSupported = false;\n\n    return DOMPurify;\n  }\n\n  var originalDocument = window.document;\n  var useDOMParser = false; // See comment below\n  var removeTitle = false; // See comment below\n\n  var document = window.document;\n  var DocumentFragment = window.DocumentFragment,\n      HTMLTemplateElement = window.HTMLTemplateElement,\n      Node = window.Node,\n      NodeFilter = window.NodeFilter,\n      _window$NamedNodeMap = window.NamedNodeMap,\n      NamedNodeMap = _window$NamedNodeMap === undefined ? window.NamedNodeMap || window.MozNamedAttrMap : _window$NamedNodeMap,\n      Text = window.Text,\n      Comment = window.Comment,\n      DOMParser = window.DOMParser;\n\n  // As per issue #47, the web-components registry is inherited by a\n  // new document created via createHTMLDocument. As per the spec\n  // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)\n  // a new empty registry is used when creating a template contents owner\n  // document, so we use that as our parent document to ensure nothing\n  // is inherited.\n\n  if (typeof HTMLTemplateElement === 'function') {\n    var template = document.createElement('template');\n    if (template.content && template.content.ownerDocument) {\n      document = template.content.ownerDocument;\n    }\n  }\n\n  var _document = document,\n      implementation = _document.implementation,\n      createNodeIterator = _document.createNodeIterator,\n      getElementsByTagName = _document.getElementsByTagName,\n      createDocumentFragment = _document.createDocumentFragment;\n  var importNode = originalDocument.importNode;\n\n\n  var hooks = {};\n\n  /**\n   * Expose whether this browser supports running the full DOMPurify.\n   */\n  DOMPurify.isSupported = implementation && typeof implementation.createHTMLDocument !== 'undefined' && document.documentMode !== 9;\n\n  var MUSTACHE_EXPR$$1 = MUSTACHE_EXPR,\n      ERB_EXPR$$1 = ERB_EXPR,\n      DATA_ATTR$$1 = DATA_ATTR,\n      ARIA_ATTR$$1 = ARIA_ATTR,\n      IS_SCRIPT_OR_DATA$$1 = IS_SCRIPT_OR_DATA,\n      ATTR_WHITESPACE$$1 = ATTR_WHITESPACE;\n  var IS_ALLOWED_URI$$1 = IS_ALLOWED_URI;\n  /**\n   * We consider the elements and attributes below to be safe. Ideally\n   * don't add any new ones but feel free to remove unwanted ones.\n   */\n\n  /* allowed element names */\n\n  var ALLOWED_TAGS = null;\n  var DEFAULT_ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(html), _toConsumableArray(svg), _toConsumableArray(svgFilters), _toConsumableArray(mathMl), _toConsumableArray(text)));\n\n  /* Allowed attribute names */\n  var ALLOWED_ATTR = null;\n  var DEFAULT_ALLOWED_ATTR = addToSet({}, [].concat(_toConsumableArray(html$1), _toConsumableArray(svg$1), _toConsumableArray(mathMl$1), _toConsumableArray(xml)));\n\n  /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */\n  var FORBID_TAGS = null;\n\n  /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */\n  var FORBID_ATTR = null;\n\n  /* Decide if ARIA attributes are okay */\n  var ALLOW_ARIA_ATTR = true;\n\n  /* Decide if custom data attributes are okay */\n  var ALLOW_DATA_ATTR = true;\n\n  /* Decide if unknown protocols are okay */\n  var ALLOW_UNKNOWN_PROTOCOLS = false;\n\n  /* Output should be safe for jQuery's $() factory? */\n  var SAFE_FOR_JQUERY = false;\n\n  /* Output should be safe for common template engines.\n   * This means, DOMPurify removes data attributes, mustaches and ERB\n   */\n  var SAFE_FOR_TEMPLATES = false;\n\n  /* Decide if document with <html>... should be returned */\n  var WHOLE_DOCUMENT = false;\n\n  /* Track whether config is already set on this instance of DOMPurify. */\n  var SET_CONFIG = false;\n\n  /* Decide if all elements (e.g. style, script) must be children of\n   * document.body. By default, browsers might move them to document.head */\n  var FORCE_BODY = false;\n\n  /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html string.\n   * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead\n   */\n  var RETURN_DOM = false;\n\n  /* Decide if a DOM `DocumentFragment` should be returned, instead of a html string */\n  var RETURN_DOM_FRAGMENT = false;\n\n  /* If `RETURN_DOM` or `RETURN_DOM_FRAGMENT` is enabled, decide if the returned DOM\n   * `Node` is imported into the current `Document`. If this flag is not enabled the\n   * `Node` will belong (its ownerDocument) to a fresh `HTMLDocument`, created by\n   * DOMPurify. */\n  var RETURN_DOM_IMPORT = false;\n\n  /* Output should be free from DOM clobbering attacks? */\n  var SANITIZE_DOM = true;\n\n  /* Keep element content when removing element? */\n  var KEEP_CONTENT = true;\n\n  /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead\n   * of importing it into a new Document and returning a sanitized copy */\n  var IN_PLACE = false;\n\n  /* Allow usage of profiles like html, svg and mathMl */\n  var USE_PROFILES = {};\n\n  /* Tags to ignore content of when KEEP_CONTENT is true */\n  var FORBID_CONTENTS = addToSet({}, ['audio', 'head', 'math', 'script', 'style', 'template', 'svg', 'video']);\n\n  /* Tags that are safe for data: URIs */\n  var DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image']);\n\n  /* Attributes safe for values like \"javascript:\" */\n  var URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'summary', 'title', 'value', 'style', 'xmlns']);\n\n  /* Keep a reference to config to pass to hooks */\n  var CONFIG = null;\n\n  /* Ideally, do not touch anything below this line */\n  /* ______________________________________________ */\n\n  var formElement = document.createElement('form');\n\n  /**\n   * _parseConfig\n   *\n   * @param  {Object} cfg optional config literal\n   */\n  // eslint-disable-next-line complexity\n  var _parseConfig = function _parseConfig(cfg) {\n    /* Shield configuration object from tampering */\n    if ((typeof cfg === 'undefined' ? 'undefined' : _typeof(cfg)) !== 'object') {\n      cfg = {};\n    }\n    /* Set configuration parameters */\n    ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ? addToSet({}, cfg.ALLOWED_TAGS) : DEFAULT_ALLOWED_TAGS;\n    ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ? addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;\n    FORBID_TAGS = 'FORBID_TAGS' in cfg ? addToSet({}, cfg.FORBID_TAGS) : {};\n    FORBID_ATTR = 'FORBID_ATTR' in cfg ? addToSet({}, cfg.FORBID_ATTR) : {};\n    USE_PROFILES = 'USE_PROFILES' in cfg ? cfg.USE_PROFILES : false;\n    ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true\n    ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true\n    ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false\n    SAFE_FOR_JQUERY = cfg.SAFE_FOR_JQUERY || false; // Default false\n    SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false\n    WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false\n    RETURN_DOM = cfg.RETURN_DOM || false; // Default false\n    RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false\n    RETURN_DOM_IMPORT = cfg.RETURN_DOM_IMPORT || false; // Default false\n    FORCE_BODY = cfg.FORCE_BODY || false; // Default false\n    SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true\n    KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true\n    IN_PLACE = cfg.IN_PLACE || false; // Default false\n\n    IS_ALLOWED_URI$$1 = cfg.ALLOWED_URI_REGEXP || IS_ALLOWED_URI$$1;\n\n    if (SAFE_FOR_TEMPLATES) {\n      ALLOW_DATA_ATTR = false;\n    }\n\n    if (RETURN_DOM_FRAGMENT) {\n      RETURN_DOM = true;\n    }\n\n    /* Parse profile info */\n    if (USE_PROFILES) {\n      ALLOWED_TAGS = addToSet({}, [].concat(_toConsumableArray(text)));\n      ALLOWED_ATTR = [];\n      if (USE_PROFILES.html === true) {\n        addToSet(ALLOWED_TAGS, html);\n        addToSet(ALLOWED_ATTR, html$1);\n      }\n      if (USE_PROFILES.svg === true) {\n        addToSet(ALLOWED_TAGS, svg);\n        addToSet(ALLOWED_ATTR, svg$1);\n        addToSet(ALLOWED_ATTR, xml);\n      }\n      if (USE_PROFILES.svgFilters === true) {\n        addToSet(ALLOWED_TAGS, svgFilters);\n        addToSet(ALLOWED_ATTR, svg$1);\n        addToSet(ALLOWED_ATTR, xml);\n      }\n      if (USE_PROFILES.mathMl === true) {\n        addToSet(ALLOWED_TAGS, mathMl);\n        addToSet(ALLOWED_ATTR, mathMl$1);\n        addToSet(ALLOWED_ATTR, xml);\n      }\n    }\n\n    /* Merge configuration parameters */\n    if (cfg.ADD_TAGS) {\n      if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {\n        ALLOWED_TAGS = clone(ALLOWED_TAGS);\n      }\n      addToSet(ALLOWED_TAGS, cfg.ADD_TAGS);\n    }\n    if (cfg.ADD_ATTR) {\n      if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {\n        ALLOWED_ATTR = clone(ALLOWED_ATTR);\n      }\n      addToSet(ALLOWED_ATTR, cfg.ADD_ATTR);\n    }\n    if (cfg.ADD_URI_SAFE_ATTR) {\n      addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR);\n    }\n\n    /* Add #text in case KEEP_CONTENT is set to true */\n    if (KEEP_CONTENT) {\n      ALLOWED_TAGS['#text'] = true;\n    }\n\n    /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */\n    if (WHOLE_DOCUMENT) {\n      addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);\n    }\n\n    /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286 */\n    if (ALLOWED_TAGS.table) {\n      addToSet(ALLOWED_TAGS, ['tbody']);\n    }\n\n    // Prevent further manipulation of configuration.\n    // Not available in IE8, Safari 5, etc.\n    if (Object && 'freeze' in Object) {\n      Object.freeze(cfg);\n    }\n\n    CONFIG = cfg;\n  };\n\n  /**\n   * _forceRemove\n   *\n   * @param  {Node} node a DOM node\n   */\n  var _forceRemove = function _forceRemove(node) {\n    DOMPurify.removed.push({ element: node });\n    try {\n      node.parentNode.removeChild(node);\n    } catch (err) {\n      node.outerHTML = '';\n    }\n  };\n\n  /**\n   * _removeAttribute\n   *\n   * @param  {String} name an Attribute name\n   * @param  {Node} node a DOM node\n   */\n  var _removeAttribute = function _removeAttribute(name, node) {\n    try {\n      DOMPurify.removed.push({\n        attribute: node.getAttributeNode(name),\n        from: node\n      });\n    } catch (err) {\n      DOMPurify.removed.push({\n        attribute: null,\n        from: node\n      });\n    }\n    node.removeAttribute(name);\n  };\n\n  /**\n   * _initDocument\n   *\n   * @param  {String} dirty a string of dirty markup\n   * @return {Document} a DOM, filled with the dirty markup\n   */\n  var _initDocument = function _initDocument(dirty) {\n    /* Create a HTML document */\n    var doc = void 0;\n\n    if (FORCE_BODY) {\n      dirty = '<remove></remove>' + dirty;\n    }\n\n    /* Use DOMParser to workaround Firefox bug (see comment below) */\n    if (useDOMParser) {\n      try {\n        doc = new DOMParser().parseFromString(dirty, 'text/html');\n      } catch (err) {}\n    }\n\n    /* Remove title to fix an mXSS bug in older MS Edge */\n    if (removeTitle) {\n      addToSet(FORBID_TAGS, ['title']);\n    }\n\n    /* Otherwise use createHTMLDocument, because DOMParser is unsafe in\n    Safari (see comment below) */\n    if (!doc || !doc.documentElement) {\n      doc = implementation.createHTMLDocument('');\n      var _doc = doc,\n          body = _doc.body;\n\n      body.parentNode.removeChild(body.parentNode.firstElementChild);\n      body.outerHTML = dirty;\n    }\n\n    /* Work on whole document or just its body */\n    return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];\n  };\n\n  // Firefox uses a different parser for innerHTML rather than\n  // DOMParser (see https://bugzilla.mozilla.org/show_bug.cgi?id=1205631)\n  // which means that you *must* use DOMParser, otherwise the output may\n  // not be safe if used in a document.write context later.\n  //\n  // So we feature detect the Firefox bug and use the DOMParser if necessary.\n  //\n  // MS Edge, in older versions, is affected by an mXSS behavior. The second\n  // check tests for the behavior and fixes it if necessary.\n  if (DOMPurify.isSupported) {\n    (function () {\n      try {\n        var doc = _initDocument('<svg><p><style><img src=\"</style><img src=x onerror=alert(1)//\">');\n        if (doc.querySelector('svg img')) {\n          useDOMParser = true;\n        }\n      } catch (err) {}\n    })();\n    (function () {\n      try {\n        var doc = _initDocument('<x/><title>&lt;/title&gt;&lt;img&gt;');\n        if (doc.querySelector('title').textContent.match(/<\\/title/)) {\n          removeTitle = true;\n        }\n      } catch (err) {}\n    })();\n  }\n\n  /**\n   * _createIterator\n   *\n   * @param  {Document} root document/fragment to create iterator for\n   * @return {Iterator} iterator instance\n   */\n  var _createIterator = function _createIterator(root) {\n    return createNodeIterator.call(root.ownerDocument || root, root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT, function () {\n      return NodeFilter.FILTER_ACCEPT;\n    }, false);\n  };\n\n  /**\n   * _isClobbered\n   *\n   * @param  {Node} elm element to check for clobbering attacks\n   * @return {Boolean} true if clobbered, false if safe\n   */\n  var _isClobbered = function _isClobbered(elm) {\n    if (elm instanceof Text || elm instanceof Comment) {\n      return false;\n    }\n    if (typeof elm.nodeName !== 'string' || typeof elm.textContent !== 'string' || typeof elm.removeChild !== 'function' || !(elm.attributes instanceof NamedNodeMap) || typeof elm.removeAttribute !== 'function' || typeof elm.setAttribute !== 'function') {\n      return true;\n    }\n    return false;\n  };\n\n  /**\n   * _isNode\n   *\n   * @param  {Node} obj object to check whether it's a DOM node\n   * @return {Boolean} true is object is a DOM node\n   */\n  var _isNode = function _isNode(obj) {\n    return (typeof Node === 'undefined' ? 'undefined' : _typeof(Node)) === 'object' ? obj instanceof Node : obj && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object' && typeof obj.nodeType === 'number' && typeof obj.nodeName === 'string';\n  };\n\n  /**\n   * _executeHook\n   * Execute user configurable hooks\n   *\n   * @param  {String} entryPoint  Name of the hook's entry point\n   * @param  {Node} currentNode node to work on with the hook\n   * @param  {Object} data additional hook parameters\n   */\n  var _executeHook = function _executeHook(entryPoint, currentNode, data) {\n    if (!hooks[entryPoint]) {\n      return;\n    }\n\n    hooks[entryPoint].forEach(function (hook) {\n      hook.call(DOMPurify, currentNode, data, CONFIG);\n    });\n  };\n\n  /**\n   * _sanitizeElements\n   *\n   * @protect nodeName\n   * @protect textContent\n   * @protect removeChild\n   *\n   * @param   {Node} currentNode to check for permission to exist\n   * @return  {Boolean} true if node was killed, false if left alive\n   */\n  var _sanitizeElements = function _sanitizeElements(currentNode) {\n    var content = void 0;\n\n    /* Execute a hook if present */\n    _executeHook('beforeSanitizeElements', currentNode, null);\n\n    /* Check if element is clobbered or can clobber */\n    if (_isClobbered(currentNode)) {\n      _forceRemove(currentNode);\n      return true;\n    }\n\n    /* Now let's check the element's type and name */\n    var tagName = currentNode.nodeName.toLowerCase();\n\n    /* Execute a hook if present */\n    _executeHook('uponSanitizeElement', currentNode, {\n      tagName: tagName,\n      allowedTags: ALLOWED_TAGS\n    });\n\n    /* Remove element if anything forbids its presence */\n    if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {\n      /* Keep content except for black-listed elements */\n      if (KEEP_CONTENT && !FORBID_CONTENTS[tagName] && typeof currentNode.insertAdjacentHTML === 'function') {\n        try {\n          currentNode.insertAdjacentHTML('AfterEnd', currentNode.innerHTML);\n        } catch (err) {}\n      }\n      _forceRemove(currentNode);\n      return true;\n    }\n\n    /* Convert markup to cover jQuery behavior */\n    if (SAFE_FOR_JQUERY && !currentNode.firstElementChild && (!currentNode.content || !currentNode.content.firstElementChild) && /</g.test(currentNode.textContent)) {\n      DOMPurify.removed.push({ element: currentNode.cloneNode() });\n      if (currentNode.innerHTML) {\n        currentNode.innerHTML = currentNode.innerHTML.replace(/</g, '&lt;');\n      } else {\n        currentNode.innerHTML = currentNode.textContent.replace(/</g, '&lt;');\n      }\n    }\n\n    /* Sanitize element content to be template-safe */\n    if (SAFE_FOR_TEMPLATES && currentNode.nodeType === 3) {\n      /* Get the element's text content */\n      content = currentNode.textContent;\n      content = content.replace(MUSTACHE_EXPR$$1, ' ');\n      content = content.replace(ERB_EXPR$$1, ' ');\n      if (currentNode.textContent !== content) {\n        DOMPurify.removed.push({ element: currentNode.cloneNode() });\n        currentNode.textContent = content;\n      }\n    }\n\n    /* Execute a hook if present */\n    _executeHook('afterSanitizeElements', currentNode, null);\n\n    return false;\n  };\n\n  /**\n   * _isValidAttribute\n   *\n   * @param  {string} lcTag Lowercase tag name of containing element.\n   * @param  {string} lcName Lowercase attribute name.\n   * @param  {string} value Attribute value.\n   * @return {Boolean} Returns true if `value` is valid, otherwise false.\n   */\n  var _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {\n    /* Make sure attribute cannot clobber */\n    if (SANITIZE_DOM && (lcName === 'id' || lcName === 'name') && (value in document || value in formElement)) {\n      return false;\n    }\n\n    /* Sanitize attribute content to be template-safe */\n    if (SAFE_FOR_TEMPLATES) {\n      value = value.replace(MUSTACHE_EXPR$$1, ' ');\n      value = value.replace(ERB_EXPR$$1, ' ');\n    }\n\n    /* Allow valid data-* attributes: At least one character after \"-\"\n        (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)\n        XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)\n        We don't need to check the value; it's always URI safe. */\n    if (ALLOW_DATA_ATTR && DATA_ATTR$$1.test(lcName)) {\n      // This attribute is safe\n    } else if (ALLOW_ARIA_ATTR && ARIA_ATTR$$1.test(lcName)) {\n      // This attribute is safe\n      /* Otherwise, check the name is permitted */\n    } else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {\n      return false;\n\n      /* Check value is safe. First, is attr inert? If so, is safe */\n    } else if (URI_SAFE_ATTRIBUTES[lcName]) {\n      // This attribute is safe\n      /* Check no script, data or unknown possibly unsafe URI\n        unless we know URI values are safe for that attribute */\n    } else if (IS_ALLOWED_URI$$1.test(value.replace(ATTR_WHITESPACE$$1, ''))) {\n      // This attribute is safe\n      /* Keep image data URIs alive if src/xlink:href is allowed */\n    } else if ((lcName === 'src' || lcName === 'xlink:href') && value.indexOf('data:') === 0 && DATA_URI_TAGS[lcTag]) {\n      // This attribute is safe\n      /* Allow unknown protocols: This provides support for links that\n        are handled by protocol handlers which may be unknown ahead of\n        time, e.g. fb:, spotify: */\n    } else if (ALLOW_UNKNOWN_PROTOCOLS && !IS_SCRIPT_OR_DATA$$1.test(value.replace(ATTR_WHITESPACE$$1, ''))) {\n      // This attribute is safe\n      /* Check for binary attributes */\n      // eslint-disable-next-line no-negated-condition\n    } else if (!value) {\n      // Binary attributes are safe at this point\n      /* Anything else, presume unsafe, do not add it back */\n    } else {\n      return false;\n    }\n    return true;\n  };\n\n  /**\n   * _sanitizeAttributes\n   *\n   * @protect attributes\n   * @protect nodeName\n   * @protect removeAttribute\n   * @protect setAttribute\n   *\n   * @param  {Node} node to sanitize\n   */\n  // eslint-disable-next-line complexity\n  var _sanitizeAttributes = function _sanitizeAttributes(currentNode) {\n    var attr = void 0;\n    var value = void 0;\n    var lcName = void 0;\n    var idAttr = void 0;\n    var l = void 0;\n    /* Execute a hook if present */\n    _executeHook('beforeSanitizeAttributes', currentNode, null);\n\n    var attributes = currentNode.attributes;\n\n    /* Check if we have attributes; if not we might have a text node */\n\n    if (!attributes) {\n      return;\n    }\n\n    var hookEvent = {\n      attrName: '',\n      attrValue: '',\n      keepAttr: true,\n      allowedAttributes: ALLOWED_ATTR\n    };\n    l = attributes.length;\n\n    /* Go backwards over all attributes; safely remove bad ones */\n    while (l--) {\n      attr = attributes[l];\n      var _attr = attr,\n          name = _attr.name;\n\n      value = attr.value.trim();\n      lcName = name.toLowerCase();\n\n      /* Execute a hook if present */\n      hookEvent.attrName = lcName;\n      hookEvent.attrValue = value;\n      hookEvent.keepAttr = true;\n      _executeHook('uponSanitizeAttribute', currentNode, hookEvent);\n      value = hookEvent.attrValue;\n\n      /* Remove attribute */\n      // Safari (iOS + Mac), last tested v8.0.5, crashes if you try to\n      // remove a \"name\" attribute from an <img> tag that has an \"id\"\n      // attribute at the time.\n      if (lcName === 'name' && currentNode.nodeName === 'IMG' && attributes.id) {\n        idAttr = attributes.id;\n        attributes = Array.prototype.slice.apply(attributes);\n        _removeAttribute('id', currentNode);\n        _removeAttribute(name, currentNode);\n        if (attributes.indexOf(idAttr) > l) {\n          currentNode.setAttribute('id', idAttr.value);\n        }\n      } else if (\n      // This works around a bug in Safari, where input[type=file]\n      // cannot be dynamically set after type has been removed\n      currentNode.nodeName === 'INPUT' && lcName === 'type' && value === 'file' && (ALLOWED_ATTR[lcName] || !FORBID_ATTR[lcName])) {\n        continue;\n      } else {\n        // This avoids a crash in Safari v9.0 with double-ids.\n        // The trick is to first set the id to be empty and then to\n        // remove the attribute\n        if (name === 'id') {\n          currentNode.setAttribute(name, '');\n        }\n        _removeAttribute(name, currentNode);\n      }\n\n      /* Did the hooks approve of the attribute? */\n      if (!hookEvent.keepAttr) {\n        continue;\n      }\n\n      /* Is `value` valid for this attribute? */\n      var lcTag = currentNode.nodeName.toLowerCase();\n      if (!_isValidAttribute(lcTag, lcName, value)) {\n        continue;\n      }\n\n      /* Handle invalid data-* attribute set by try-catching it */\n      try {\n        currentNode.setAttribute(name, value);\n        DOMPurify.removed.pop();\n      } catch (err) {}\n    }\n\n    /* Execute a hook if present */\n    _executeHook('afterSanitizeAttributes', currentNode, null);\n  };\n\n  /**\n   * _sanitizeShadowDOM\n   *\n   * @param  {DocumentFragment} fragment to iterate over recursively\n   */\n  var _sanitizeShadowDOM = function _sanitizeShadowDOM(fragment) {\n    var shadowNode = void 0;\n    var shadowIterator = _createIterator(fragment);\n\n    /* Execute a hook if present */\n    _executeHook('beforeSanitizeShadowDOM', fragment, null);\n\n    while (shadowNode = shadowIterator.nextNode()) {\n      /* Execute a hook if present */\n      _executeHook('uponSanitizeShadowNode', shadowNode, null);\n\n      /* Sanitize tags and elements */\n      if (_sanitizeElements(shadowNode)) {\n        continue;\n      }\n\n      /* Deep shadow DOM detected */\n      if (shadowNode.content instanceof DocumentFragment) {\n        _sanitizeShadowDOM(shadowNode.content);\n      }\n\n      /* Check attributes, sanitize if necessary */\n      _sanitizeAttributes(shadowNode);\n    }\n\n    /* Execute a hook if present */\n    _executeHook('afterSanitizeShadowDOM', fragment, null);\n  };\n\n  /**\n   * Sanitize\n   * Public method providing core sanitation functionality\n   *\n   * @param {String|Node} dirty string or DOM node\n   * @param {Object} configuration object\n   */\n  // eslint-disable-next-line complexity\n  DOMPurify.sanitize = function (dirty, cfg) {\n    var body = void 0;\n    var importedNode = void 0;\n    var currentNode = void 0;\n    var oldNode = void 0;\n    var returnNode = void 0;\n    /* Make sure we have a string to sanitize.\n      DO NOT return early, as this will return the wrong type if\n      the user has requested a DOM object rather than a string */\n    if (!dirty) {\n      dirty = '<!-->';\n    }\n\n    /* Stringify, in case dirty is an object */\n    if (typeof dirty !== 'string' && !_isNode(dirty)) {\n      // eslint-disable-next-line no-negated-condition\n      if (typeof dirty.toString !== 'function') {\n        throw new TypeError('toString is not a function');\n      } else {\n        dirty = dirty.toString();\n        if (typeof dirty !== 'string') {\n          throw new TypeError('dirty is not a string, aborting');\n        }\n      }\n    }\n\n    /* Check we can run. Otherwise fall back or ignore */\n    if (!DOMPurify.isSupported) {\n      if (_typeof(window.toStaticHTML) === 'object' || typeof window.toStaticHTML === 'function') {\n        if (typeof dirty === 'string') {\n          return window.toStaticHTML(dirty);\n        }\n        if (_isNode(dirty)) {\n          return window.toStaticHTML(dirty.outerHTML);\n        }\n      }\n      return dirty;\n    }\n\n    /* Assign config vars */\n    if (!SET_CONFIG) {\n      _parseConfig(cfg);\n    }\n\n    /* Clean up removed elements */\n    DOMPurify.removed = [];\n\n    if (IN_PLACE) {\n      /* No special handling necessary for in-place sanitization */\n    } else if (dirty instanceof Node) {\n      /* If dirty is a DOM element, append to an empty document to avoid\n         elements being stripped by the parser */\n      body = _initDocument('<!-->');\n      importedNode = body.ownerDocument.importNode(dirty, true);\n      if (importedNode.nodeType === 1 && importedNode.nodeName === 'BODY') {\n        /* Node is already a body, use as is */\n        body = importedNode;\n      } else {\n        body.appendChild(importedNode);\n      }\n    } else {\n      /* Exit directly if we have nothing to do */\n      if (!RETURN_DOM && !WHOLE_DOCUMENT && dirty.indexOf('<') === -1) {\n        return dirty;\n      }\n\n      /* Initialize the document to work on */\n      body = _initDocument(dirty);\n\n      /* Check we have a DOM node from the data */\n      if (!body) {\n        return RETURN_DOM ? null : '';\n      }\n    }\n\n    /* Remove first element node (ours) if FORCE_BODY is set */\n    if (body && FORCE_BODY) {\n      _forceRemove(body.firstChild);\n    }\n\n    /* Get node iterator */\n    var nodeIterator = _createIterator(IN_PLACE ? dirty : body);\n\n    /* Now start iterating over the created document */\n    while (currentNode = nodeIterator.nextNode()) {\n      /* Fix IE's strange behavior with manipulated textNodes #89 */\n      if (currentNode.nodeType === 3 && currentNode === oldNode) {\n        continue;\n      }\n\n      /* Sanitize tags and elements */\n      if (_sanitizeElements(currentNode)) {\n        continue;\n      }\n\n      /* Shadow DOM detected, sanitize it */\n      if (currentNode.content instanceof DocumentFragment) {\n        _sanitizeShadowDOM(currentNode.content);\n      }\n\n      /* Check attributes, sanitize if necessary */\n      _sanitizeAttributes(currentNode);\n\n      oldNode = currentNode;\n    }\n\n    /* If we sanitized `dirty` in-place, return it. */\n    if (IN_PLACE) {\n      return dirty;\n    }\n\n    /* Return sanitized string or DOM */\n    if (RETURN_DOM) {\n      if (RETURN_DOM_FRAGMENT) {\n        returnNode = createDocumentFragment.call(body.ownerDocument);\n\n        while (body.firstChild) {\n          returnNode.appendChild(body.firstChild);\n        }\n      } else {\n        returnNode = body;\n      }\n\n      if (RETURN_DOM_IMPORT) {\n        /* AdoptNode() is not used because internal state is not reset\n               (e.g. the past names map of a HTMLFormElement), this is safe\n               in theory but we would rather not risk another attack vector.\n               The state that is cloned by importNode() is explicitly defined\n               by the specs. */\n        returnNode = importNode.call(originalDocument, returnNode, true);\n      }\n\n      return returnNode;\n    }\n\n    return WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;\n  };\n\n  /**\n   * Public method to set the configuration once\n   * setConfig\n   *\n   * @param {Object} cfg configuration object\n   */\n  DOMPurify.setConfig = function (cfg) {\n    _parseConfig(cfg);\n    SET_CONFIG = true;\n  };\n\n  /**\n   * Public method to remove the configuration\n   * clearConfig\n   *\n   */\n  DOMPurify.clearConfig = function () {\n    CONFIG = null;\n    SET_CONFIG = false;\n  };\n\n  /**\n   * Public method to check if an attribute value is valid.\n   * Uses last set config, if any. Otherwise, uses config defaults.\n   * isValidAttribute\n   *\n   * @param  {string} tag Tag name of containing element.\n   * @param  {string} attr Attribute name.\n   * @param  {string} value Attribute value.\n   * @return {Boolean} Returns true if `value` is valid. Otherwise, returns false.\n   */\n  DOMPurify.isValidAttribute = function (tag, attr, value) {\n    /* Initialize shared config vars if necessary. */\n    if (!CONFIG) {\n      _parseConfig({});\n    }\n    var lcTag = tag.toLowerCase();\n    var lcName = attr.toLowerCase();\n    return _isValidAttribute(lcTag, lcName, value);\n  };\n\n  /**\n   * AddHook\n   * Public method to add DOMPurify hooks\n   *\n   * @param {String} entryPoint entry point for the hook to add\n   * @param {Function} hookFunction function to execute\n   */\n  DOMPurify.addHook = function (entryPoint, hookFunction) {\n    if (typeof hookFunction !== 'function') {\n      return;\n    }\n    hooks[entryPoint] = hooks[entryPoint] || [];\n    hooks[entryPoint].push(hookFunction);\n  };\n\n  /**\n   * RemoveHook\n   * Public method to remove a DOMPurify hook at a given entryPoint\n   * (pops it from the stack of hooks if more are present)\n   *\n   * @param {String} entryPoint entry point for the hook to remove\n   */\n  DOMPurify.removeHook = function (entryPoint) {\n    if (hooks[entryPoint]) {\n      hooks[entryPoint].pop();\n    }\n  };\n\n  /**\n   * RemoveHooks\n   * Public method to remove all DOMPurify hooks at a given entryPoint\n   *\n   * @param  {String} entryPoint entry point for the hooks to remove\n   */\n  DOMPurify.removeHooks = function (entryPoint) {\n    if (hooks[entryPoint]) {\n      hooks[entryPoint] = [];\n    }\n  };\n\n  /**\n   * RemoveAllHooks\n   * Public method to remove all DOMPurify hooks\n   *\n   */\n  DOMPurify.removeAllHooks = function () {\n    hooks = {};\n  };\n\n  return DOMPurify;\n}\n\nvar purify = createDOMPurify();\n\nreturn purify;\n\n})));"
  },
  {
    "path": "resources/assets/bootstrap-fileinput/js/plugins/sortable.js",
    "content": "/**!\n * KvSortable\n * @author\tRubaXa   <trash@rubaxa.org>\n * @license MIT\n *\n * Changed kvsortable plugin naming to prevent conflict with JQuery UI Sortable\n * @author Kartik Visweswaran\n */\n\n(function kvsortableModule(factory) {\n\t\"use strict\";\n\n\tif (typeof define === \"function\" && define.amd) {\n\t\tdefine(factory);\n\t}\n\telse if (typeof module != \"undefined\" && typeof module.exports != \"undefined\") {\n\t\tmodule.exports = factory();\n\t}\n\telse {\n\t\t/* jshint sub:true */\n\t\twindow[\"KvSortable\"] = factory();\n\t}\n})(function kvsortableFactory() {\n\t\"use strict\";\n\n\tif (typeof window === \"undefined\" || !window.document) {\n\t\treturn function kvsortableError() {\n\t\t\tthrow new Error(\"KvSortable.js requires a window with a document\");\n\t\t};\n\t}\n\n\tvar dragEl,\n\t\tparentEl,\n\t\tghostEl,\n\t\tcloneEl,\n\t\trootEl,\n\t\tnextEl,\n\t\tlastDownEl,\n\n\t\tscrollEl,\n\t\tscrollParentEl,\n\t\tscrollCustomFn,\n\n\t\tlastEl,\n\t\tlastCSS,\n\t\tlastParentCSS,\n\n\t\toldIndex,\n\t\tnewIndex,\n\n\t\tactiveGroup,\n\t\tputKvSortable,\n\n\t\tautoScroll = {},\n\n\t\ttapEvt,\n\t\ttouchEvt,\n\n\t\tmoved,\n\n\t\t/** @const */\n\t\tR_SPACE = /\\s+/g,\n\t\tR_FLOAT = /left|right|inline/,\n\n\t\texpando = 'KvSortable' + (new Date).getTime(),\n\n\t\twin = window,\n\t\tdocument = win.document,\n\t\tparseInt = win.parseInt,\n\t\tsetTimeout = win.setTimeout,\n\n\t\t$ = win.jQuery || win.Zepto,\n\t\tPolymer = win.Polymer,\n\n\t\tcaptureMode = false,\n\t\tpassiveMode = false,\n\n\t\tsupportDraggable = ('draggable' in document.createElement('div')),\n\t\tsupportCssPointerEvents = (function (el) {\n\t\t\t// false when IE11\n\t\t\tif (!!navigator.userAgent.match(/(?:Trident.*rv[ :]?11\\.|msie)/i)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tel = document.createElement('x');\n\t\t\tel.style.cssText = 'pointer-events:auto';\n\t\t\treturn el.style.pointerEvents === 'auto';\n\t\t})(),\n\n\t\t_silent = false,\n\n\t\tabs = Math.abs,\n\t\tmin = Math.min,\n\n\t\tsavedInputChecked = [],\n\t\ttouchDragOverListeners = [],\n\n\t\t_autoScroll = _throttle(function (/**Event*/evt, /**Object*/options, /**HTMLElement*/rootEl) {\n\t\t\t// Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521\n\t\t\tif (rootEl && options.scroll) {\n\t\t\t\tvar _this = rootEl[expando],\n\t\t\t\t\tel,\n\t\t\t\t\trect,\n\t\t\t\t\tsens = options.scrollSensitivity,\n\t\t\t\t\tspeed = options.scrollSpeed,\n\n\t\t\t\t\tx = evt.clientX,\n\t\t\t\t\ty = evt.clientY,\n\n\t\t\t\t\twinWidth = window.innerWidth,\n\t\t\t\t\twinHeight = window.innerHeight,\n\n\t\t\t\t\tvx,\n\t\t\t\t\tvy,\n\n\t\t\t\t\tscrollOffsetX,\n\t\t\t\t\tscrollOffsetY\n\t\t\t\t;\n\n\t\t\t\t// Delect scrollEl\n\t\t\t\tif (scrollParentEl !== rootEl) {\n\t\t\t\t\tscrollEl = options.scroll;\n\t\t\t\t\tscrollParentEl = rootEl;\n\t\t\t\t\tscrollCustomFn = options.scrollFn;\n\n\t\t\t\t\tif (scrollEl === true) {\n\t\t\t\t\t\tscrollEl = rootEl;\n\n\t\t\t\t\t\tdo {\n\t\t\t\t\t\t\tif ((scrollEl.offsetWidth < scrollEl.scrollWidth) ||\n\t\t\t\t\t\t\t\t(scrollEl.offsetHeight < scrollEl.scrollHeight)\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t/* jshint boss:true */\n\t\t\t\t\t\t} while (scrollEl = scrollEl.parentNode);\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (scrollEl) {\n\t\t\t\t\tel = scrollEl;\n\t\t\t\t\trect = scrollEl.getBoundingClientRect();\n\t\t\t\t\tvx = (abs(rect.right - x) <= sens) - (abs(rect.left - x) <= sens);\n\t\t\t\t\tvy = (abs(rect.bottom - y) <= sens) - (abs(rect.top - y) <= sens);\n\t\t\t\t}\n\n\n\t\t\t\tif (!(vx || vy)) {\n\t\t\t\t\tvx = (winWidth - x <= sens) - (x <= sens);\n\t\t\t\t\tvy = (winHeight - y <= sens) - (y <= sens);\n\n\t\t\t\t\t/* jshint expr:true */\n\t\t\t\t\t(vx || vy) && (el = win);\n\t\t\t\t}\n\n\n\t\t\t\tif (autoScroll.vx !== vx || autoScroll.vy !== vy || autoScroll.el !== el) {\n\t\t\t\t\tautoScroll.el = el;\n\t\t\t\t\tautoScroll.vx = vx;\n\t\t\t\t\tautoScroll.vy = vy;\n\n\t\t\t\t\tclearInterval(autoScroll.pid);\n\n\t\t\t\t\tif (el) {\n\t\t\t\t\t\tautoScroll.pid = setInterval(function () {\n\t\t\t\t\t\t\tscrollOffsetY = vy ? vy * speed : 0;\n\t\t\t\t\t\t\tscrollOffsetX = vx ? vx * speed : 0;\n\n\t\t\t\t\t\t\tif ('function' === typeof(scrollCustomFn)) {\n\t\t\t\t\t\t\t\treturn scrollCustomFn.call(_this, scrollOffsetX, scrollOffsetY, evt);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tif (el === win) {\n\t\t\t\t\t\t\t\twin.scrollTo(win.pageXOffset + scrollOffsetX, win.pageYOffset + scrollOffsetY);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tel.scrollTop += scrollOffsetY;\n\t\t\t\t\t\t\t\tel.scrollLeft += scrollOffsetX;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, 24);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}, 30),\n\n\t\t_prepareGroup = function (options) {\n\t\t\tfunction toFn(value, pull) {\n\t\t\t\tif (value === void 0 || value === true) {\n\t\t\t\t\tvalue = group.name;\n\t\t\t\t}\n\n\t\t\t\tif (typeof value === 'function') {\n\t\t\t\t\treturn value;\n\t\t\t\t} else {\n\t\t\t\t\treturn function (to, from) {\n\t\t\t\t\t\tvar fromGroup = from.options.group.name;\n\n\t\t\t\t\t\treturn pull\n\t\t\t\t\t\t\t? value\n\t\t\t\t\t\t\t: value && (value.join\n\t\t\t\t\t\t\t\t? value.indexOf(fromGroup) > -1\n\t\t\t\t\t\t\t\t: (fromGroup == value)\n\t\t\t\t\t\t\t);\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tvar group = {};\n\t\t\tvar originalGroup = options.group;\n\n\t\t\tif (!originalGroup || typeof originalGroup != 'object') {\n\t\t\t\toriginalGroup = {name: originalGroup};\n\t\t\t}\n\n\t\t\tgroup.name = originalGroup.name;\n\t\t\tgroup.checkPull = toFn(originalGroup.pull, true);\n\t\t\tgroup.checkPut = toFn(originalGroup.put);\n\t\t\tgroup.revertClone = originalGroup.revertClone;\n\n\t\t\toptions.group = group;\n\t\t}\n\t;\n\n\t// Detect support a passive mode\n\ttry {\n\t\twindow.addEventListener('test', null, Object.defineProperty({}, 'passive', {\n\t\t\tget: function () {\n\t\t\t\t// `false`, because everything starts to work incorrectly and instead of d'n'd,\n\t\t\t\t// begins the page has scrolled.\n\t\t\t\tpassiveMode = false;\n\t\t\t\tcaptureMode = {\n\t\t\t\t\tcapture: false,\n\t\t\t\t\tpassive: passiveMode\n\t\t\t\t};\n\t\t\t}\n\t\t}));\n\t} catch (err) {}\n\n\t/**\n\t * @class  KvSortable\n\t * @param  {HTMLElement}  el\n\t * @param  {Object}       [options]\n\t */\n\tfunction KvSortable(el, options) {\n\t\tif (!(el && el.nodeType && el.nodeType === 1)) {\n\t\t\tthrow 'KvSortable: `el` must be HTMLElement, and not ' + {}.toString.call(el);\n\t\t}\n\n\t\tthis.el = el; // root element\n\t\tthis.options = options = _extend({}, options);\n\n\n\t\t// Export instance\n\t\tel[expando] = this;\n\n\t\t// Default options\n\t\tvar defaults = {\n\t\t\tgroup: Math.random(),\n\t\t\tsort: true,\n\t\t\tdisabled: false,\n\t\t\tstore: null,\n\t\t\thandle: null,\n\t\t\tscroll: true,\n\t\t\tscrollSensitivity: 30,\n\t\t\tscrollSpeed: 10,\n\t\t\tdraggable: /[uo]l/i.test(el.nodeName) ? 'li' : '>*',\n\t\t\tghostClass: 'kvsortable-ghost',\n\t\t\tchosenClass: 'kvsortable-chosen',\n\t\t\tdragClass: 'kvsortable-drag',\n\t\t\tignore: 'a, img',\n\t\t\tfilter: null,\n\t\t\tpreventOnFilter: true,\n\t\t\tanimation: 0,\n\t\t\tsetData: function (dataTransfer, dragEl) {\n\t\t\t\tdataTransfer.setData('Text', dragEl.textContent);\n\t\t\t},\n\t\t\tdropBubble: false,\n\t\t\tdragoverBubble: false,\n\t\t\tdataIdAttr: 'data-id',\n\t\t\tdelay: 0,\n\t\t\tforceFallback: false,\n\t\t\tfallbackClass: 'kvsortable-fallback',\n\t\t\tfallbackOnBody: false,\n\t\t\tfallbackTolerance: 0,\n\t\t\tfallbackOffset: {x: 0, y: 0},\n\t\t\tsupportPointer: KvSortable.supportPointer !== false\n\t\t};\n\n\n\t\t// Set default options\n\t\tfor (var name in defaults) {\n\t\t\t!(name in options) && (options[name] = defaults[name]);\n\t\t}\n\n\t\t_prepareGroup(options);\n\n\t\t// Bind all private methods\n\t\tfor (var fn in this) {\n\t\t\tif (fn.charAt(0) === '_' && typeof this[fn] === 'function') {\n\t\t\t\tthis[fn] = this[fn].bind(this);\n\t\t\t}\n\t\t}\n\n\t\t// Setup drag mode\n\t\tthis.nativeDraggable = options.forceFallback ? false : supportDraggable;\n\n\t\t// Bind events\n\t\t_on(el, 'mousedown', this._onTapStart);\n\t\t_on(el, 'touchstart', this._onTapStart);\n\t\toptions.supportPointer && _on(el, 'pointerdown', this._onTapStart);\n\n\t\tif (this.nativeDraggable) {\n\t\t\t_on(el, 'dragover', this);\n\t\t\t_on(el, 'dragenter', this);\n\t\t}\n\n\t\ttouchDragOverListeners.push(this._onDragOver);\n\n\t\t// Restore sorting\n\t\toptions.store && this.sort(options.store.get(this));\n\t}\n\n\n\tKvSortable.prototype = /** @lends KvSortable.prototype */ {\n\t\tconstructor: KvSortable,\n\n\t\t_onTapStart: function (/** Event|TouchEvent */evt) {\n\t\t\tvar _this = this,\n\t\t\t\tel = this.el,\n\t\t\t\toptions = this.options,\n\t\t\t\tpreventOnFilter = options.preventOnFilter,\n\t\t\t\ttype = evt.type,\n\t\t\t\ttouch = evt.touches && evt.touches[0],\n\t\t\t\ttarget = (touch || evt).target,\n\t\t\t\toriginalTarget = evt.target.shadowRoot && (evt.path && evt.path[0]) || target,\n\t\t\t\tfilter = options.filter,\n\t\t\t\tstartIndex;\n\n\t\t\t_saveInputCheckedState(el);\n\n\n\t\t\t// Don't trigger start event when an element is been dragged, otherwise the evt.oldindex always wrong when set option.group.\n\t\t\tif (dragEl) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (/mousedown|pointerdown/.test(type) && evt.button !== 0 || options.disabled) {\n\t\t\t\treturn; // only left button or enabled\n\t\t\t}\n\n\t\t\t// cancel dnd if original target is content editable\n\t\t\tif (originalTarget.isContentEditable) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\ttarget = _closest(target, options.draggable, el);\n\n\t\t\tif (!target) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif (lastDownEl === target) {\n\t\t\t\t// Ignoring duplicate `down`\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Get the index of the dragged element within its parent\n\t\t\tstartIndex = _index(target, options.draggable);\n\n\t\t\t// Check filter\n\t\t\tif (typeof filter === 'function') {\n\t\t\t\tif (filter.call(this, evt, target, this)) {\n\t\t\t\t\t_dispatchEvent(_this, originalTarget, 'filter', target, el, el, startIndex);\n\t\t\t\t\tpreventOnFilter && evt.preventDefault();\n\t\t\t\t\treturn; // cancel dnd\n\t\t\t\t}\n\t\t\t}\n\t\t\telse if (filter) {\n\t\t\t\tfilter = filter.split(',').some(function (criteria) {\n\t\t\t\t\tcriteria = _closest(originalTarget, criteria.trim(), el);\n\n\t\t\t\t\tif (criteria) {\n\t\t\t\t\t\t_dispatchEvent(_this, criteria, 'filter', target, el, el, startIndex);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t});\n\n\t\t\t\tif (filter) {\n\t\t\t\t\tpreventOnFilter && evt.preventDefault();\n\t\t\t\t\treturn; // cancel dnd\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (options.handle && !_closest(originalTarget, options.handle, el)) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Prepare `dragstart`\n\t\t\tthis._prepareDragStart(evt, touch, target, startIndex);\n\t\t},\n\n\t\t_prepareDragStart: function (/** Event */evt, /** Touch */touch, /** HTMLElement */target, /** Number */startIndex) {\n\t\t\tvar _this = this,\n\t\t\t\tel = _this.el,\n\t\t\t\toptions = _this.options,\n\t\t\t\townerDocument = el.ownerDocument,\n\t\t\t\tdragStartFn;\n\n\t\t\tif (target && !dragEl && (target.parentNode === el)) {\n\t\t\t\ttapEvt = evt;\n\n\t\t\t\trootEl = el;\n\t\t\t\tdragEl = target;\n\t\t\t\tparentEl = dragEl.parentNode;\n\t\t\t\tnextEl = dragEl.nextSibling;\n\t\t\t\tlastDownEl = target;\n\t\t\t\tactiveGroup = options.group;\n\t\t\t\toldIndex = startIndex;\n\n\t\t\t\tthis._lastX = (touch || evt).clientX;\n\t\t\t\tthis._lastY = (touch || evt).clientY;\n\n\t\t\t\tdragEl.style['will-change'] = 'all';\n\n\t\t\t\tdragStartFn = function () {\n\t\t\t\t\t// Delayed drag has been triggered\n\t\t\t\t\t// we can re-enable the events: touchmove/mousemove\n\t\t\t\t\t_this._disableDelayedDrag();\n\n\t\t\t\t\t// Make the element draggable\n\t\t\t\t\tdragEl.draggable = _this.nativeDraggable;\n\n\t\t\t\t\t// Chosen item\n\t\t\t\t\t_toggleClass(dragEl, options.chosenClass, true);\n\n\t\t\t\t\t// Bind the events: dragstart/dragend\n\t\t\t\t\t_this._triggerDragStart(evt, touch);\n\n\t\t\t\t\t// Drag start event\n\t\t\t\t\t_dispatchEvent(_this, rootEl, 'choose', dragEl, rootEl, rootEl, oldIndex);\n\t\t\t\t};\n\n\t\t\t\t// Disable \"draggable\"\n\t\t\t\toptions.ignore.split(',').forEach(function (criteria) {\n\t\t\t\t\t_find(dragEl, criteria.trim(), _disableDraggable);\n\t\t\t\t});\n\n\t\t\t\t_on(ownerDocument, 'mouseup', _this._onDrop);\n\t\t\t\t_on(ownerDocument, 'touchend', _this._onDrop);\n\t\t\t\t_on(ownerDocument, 'touchcancel', _this._onDrop);\n\t\t\t\t_on(ownerDocument, 'selectstart', _this);\n\t\t\t\toptions.supportPointer && _on(ownerDocument, 'pointercancel', _this._onDrop);\n\n\t\t\t\tif (options.delay) {\n\t\t\t\t\t// If the user moves the pointer or let go the click or touch\n\t\t\t\t\t// before the delay has been reached:\n\t\t\t\t\t// disable the delayed drag\n\t\t\t\t\t_on(ownerDocument, 'mouseup', _this._disableDelayedDrag);\n\t\t\t\t\t_on(ownerDocument, 'touchend', _this._disableDelayedDrag);\n\t\t\t\t\t_on(ownerDocument, 'touchcancel', _this._disableDelayedDrag);\n\t\t\t\t\t_on(ownerDocument, 'mousemove', _this._disableDelayedDrag);\n\t\t\t\t\t_on(ownerDocument, 'touchmove', _this._disableDelayedDrag);\n\t\t\t\t\toptions.supportPointer && _on(ownerDocument, 'pointermove', _this._disableDelayedDrag);\n\n\t\t\t\t\t_this._dragStartTimer = setTimeout(dragStartFn, options.delay);\n\t\t\t\t} else {\n\t\t\t\t\tdragStartFn();\n\t\t\t\t}\n\n\n\t\t\t}\n\t\t},\n\n\t\t_disableDelayedDrag: function () {\n\t\t\tvar ownerDocument = this.el.ownerDocument;\n\n\t\t\tclearTimeout(this._dragStartTimer);\n\t\t\t_off(ownerDocument, 'mouseup', this._disableDelayedDrag);\n\t\t\t_off(ownerDocument, 'touchend', this._disableDelayedDrag);\n\t\t\t_off(ownerDocument, 'touchcancel', this._disableDelayedDrag);\n\t\t\t_off(ownerDocument, 'mousemove', this._disableDelayedDrag);\n\t\t\t_off(ownerDocument, 'touchmove', this._disableDelayedDrag);\n\t\t\t_off(ownerDocument, 'pointermove', this._disableDelayedDrag);\n\t\t},\n\n\t\t_triggerDragStart: function (/** Event */evt, /** Touch */touch) {\n\t\t\ttouch = touch || (evt.pointerType == 'touch' ? evt : null);\n\n\t\t\tif (touch) {\n\t\t\t\t// Touch device support\n\t\t\t\ttapEvt = {\n\t\t\t\t\ttarget: dragEl,\n\t\t\t\t\tclientX: touch.clientX,\n\t\t\t\t\tclientY: touch.clientY\n\t\t\t\t};\n\n\t\t\t\tthis._onDragStart(tapEvt, 'touch');\n\t\t\t}\n\t\t\telse if (!this.nativeDraggable) {\n\t\t\t\tthis._onDragStart(tapEvt, true);\n\t\t\t}\n\t\t\telse {\n\t\t\t\t_on(dragEl, 'dragend', this);\n\t\t\t\t_on(rootEl, 'dragstart', this._onDragStart);\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tif (document.selection) {\n\t\t\t\t\t// Timeout neccessary for IE9\n\t\t\t\t\t_nextTick(function () {\n\t\t\t\t\t\tdocument.selection.empty();\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\twindow.getSelection().removeAllRanges();\n\t\t\t\t}\n\t\t\t} catch (err) {\n\t\t\t}\n\t\t},\n\n\t\t_dragStarted: function () {\n\t\t\tif (rootEl && dragEl) {\n\t\t\t\tvar options = this.options;\n\n\t\t\t\t// Apply effect\n\t\t\t\t_toggleClass(dragEl, options.ghostClass, true);\n\t\t\t\t_toggleClass(dragEl, options.dragClass, false);\n\n\t\t\t\tKvSortable.active = this;\n\n\t\t\t\t// Drag start event\n\t\t\t\t_dispatchEvent(this, rootEl, 'start', dragEl, rootEl, rootEl, oldIndex);\n\t\t\t} else {\n\t\t\t\tthis._nulling();\n\t\t\t}\n\t\t},\n\n\t\t_emulateDragOver: function () {\n\t\t\tif (touchEvt) {\n\t\t\t\tif (this._lastX === touchEvt.clientX && this._lastY === touchEvt.clientY) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tthis._lastX = touchEvt.clientX;\n\t\t\t\tthis._lastY = touchEvt.clientY;\n\n\t\t\t\tif (!supportCssPointerEvents) {\n\t\t\t\t\t_css(ghostEl, 'display', 'none');\n\t\t\t\t}\n\n\t\t\t\tvar target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY);\n\t\t\t\tvar parent = target;\n\t\t\t\tvar i = touchDragOverListeners.length;\n\n\t\t\t\tif (target && target.shadowRoot) {\n\t\t\t\t\ttarget = target.shadowRoot.elementFromPoint(touchEvt.clientX, touchEvt.clientY);\n\t\t\t\t\tparent = target;\n\t\t\t\t}\n\n\t\t\t\tif (parent) {\n\t\t\t\t\tdo {\n\t\t\t\t\t\tif (parent[expando]) {\n\t\t\t\t\t\t\twhile (i--) {\n\t\t\t\t\t\t\t\ttouchDragOverListeners[i]({\n\t\t\t\t\t\t\t\t\tclientX: touchEvt.clientX,\n\t\t\t\t\t\t\t\t\tclientY: touchEvt.clientY,\n\t\t\t\t\t\t\t\t\ttarget: target,\n\t\t\t\t\t\t\t\t\trootEl: parent\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttarget = parent; // store last element\n\t\t\t\t\t}\n\t\t\t\t\t/* jshint boss:true */\n\t\t\t\t\twhile (parent = parent.parentNode);\n\t\t\t\t}\n\n\t\t\t\tif (!supportCssPointerEvents) {\n\t\t\t\t\t_css(ghostEl, 'display', '');\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\n\t\t_onTouchMove: function (/**TouchEvent*/evt) {\n\t\t\tif (tapEvt) {\n\t\t\t\tvar\toptions = this.options,\n\t\t\t\t\tfallbackTolerance = options.fallbackTolerance,\n\t\t\t\t\tfallbackOffset = options.fallbackOffset,\n\t\t\t\t\ttouch = evt.touches ? evt.touches[0] : evt,\n\t\t\t\t\tdx = (touch.clientX - tapEvt.clientX) + fallbackOffset.x,\n\t\t\t\t\tdy = (touch.clientY - tapEvt.clientY) + fallbackOffset.y,\n\t\t\t\t\ttranslate3d = evt.touches ? 'translate3d(' + dx + 'px,' + dy + 'px,0)' : 'translate(' + dx + 'px,' + dy + 'px)';\n\n\t\t\t\t// only set the status to dragging, when we are actually dragging\n\t\t\t\tif (!KvSortable.active) {\n\t\t\t\t\tif (fallbackTolerance &&\n\t\t\t\t\t\tmin(abs(touch.clientX - this._lastX), abs(touch.clientY - this._lastY)) < fallbackTolerance\n\t\t\t\t\t) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tthis._dragStarted();\n\t\t\t\t}\n\n\t\t\t\t// as well as creating the ghost element on the document body\n\t\t\t\tthis._appendGhost();\n\n\t\t\t\tmoved = true;\n\t\t\t\ttouchEvt = touch;\n\n\t\t\t\t_css(ghostEl, 'webkitTransform', translate3d);\n\t\t\t\t_css(ghostEl, 'mozTransform', translate3d);\n\t\t\t\t_css(ghostEl, 'msTransform', translate3d);\n\t\t\t\t_css(ghostEl, 'transform', translate3d);\n\n\t\t\t\tevt.preventDefault();\n\t\t\t}\n\t\t},\n\n\t\t_appendGhost: function () {\n\t\t\tif (!ghostEl) {\n\t\t\t\tvar rect = dragEl.getBoundingClientRect(),\n\t\t\t\t\tcss = _css(dragEl),\n\t\t\t\t\toptions = this.options,\n\t\t\t\t\tghostRect;\n\n\t\t\t\tghostEl = dragEl.cloneNode(true);\n\n\t\t\t\t_toggleClass(ghostEl, options.ghostClass, false);\n\t\t\t\t_toggleClass(ghostEl, options.fallbackClass, true);\n\t\t\t\t_toggleClass(ghostEl, options.dragClass, true);\n\n\t\t\t\t_css(ghostEl, 'top', rect.top - parseInt(css.marginTop, 10));\n\t\t\t\t_css(ghostEl, 'left', rect.left - parseInt(css.marginLeft, 10));\n\t\t\t\t_css(ghostEl, 'width', rect.width);\n\t\t\t\t_css(ghostEl, 'height', rect.height);\n\t\t\t\t_css(ghostEl, 'opacity', '0.8');\n\t\t\t\t_css(ghostEl, 'position', 'fixed');\n\t\t\t\t_css(ghostEl, 'zIndex', '100000');\n\t\t\t\t_css(ghostEl, 'pointerEvents', 'none');\n\n\t\t\t\toptions.fallbackOnBody && document.body.appendChild(ghostEl) || rootEl.appendChild(ghostEl);\n\n\t\t\t\t// Fixing dimensions.\n\t\t\t\tghostRect = ghostEl.getBoundingClientRect();\n\t\t\t\t_css(ghostEl, 'width', rect.width * 2 - ghostRect.width);\n\t\t\t\t_css(ghostEl, 'height', rect.height * 2 - ghostRect.height);\n\t\t\t}\n\t\t},\n\n\t\t_onDragStart: function (/**Event*/evt, /**boolean*/useFallback) {\n\t\t\tvar _this = this;\n\t\t\tvar dataTransfer = evt.dataTransfer;\n\t\t\tvar options = _this.options;\n\n\t\t\t_this._offUpEvents();\n\n\t\t\tif (activeGroup.checkPull(_this, _this, dragEl, evt)) {\n\t\t\t\tcloneEl = _clone(dragEl);\n\n\t\t\t\tcloneEl.draggable = false;\n\t\t\t\tcloneEl.style['will-change'] = '';\n\n\t\t\t\t_css(cloneEl, 'display', 'none');\n\t\t\t\t_toggleClass(cloneEl, _this.options.chosenClass, false);\n\n\t\t\t\t// #1143: IFrame support workaround\n\t\t\t\t_this._cloneId = _nextTick(function () {\n\t\t\t\t\trootEl.insertBefore(cloneEl, dragEl);\n\t\t\t\t\t_dispatchEvent(_this, rootEl, 'clone', dragEl);\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t_toggleClass(dragEl, options.dragClass, true);\n\n\t\t\tif (useFallback) {\n\t\t\t\tif (useFallback === 'touch') {\n\t\t\t\t\t// Bind touch events\n\t\t\t\t\t_on(document, 'touchmove', _this._onTouchMove);\n\t\t\t\t\t_on(document, 'touchend', _this._onDrop);\n\t\t\t\t\t_on(document, 'touchcancel', _this._onDrop);\n\n\t\t\t\t\tif (options.supportPointer) {\n\t\t\t\t\t\t_on(document, 'pointermove', _this._onTouchMove);\n\t\t\t\t\t\t_on(document, 'pointerup', _this._onDrop);\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Old brwoser\n\t\t\t\t\t_on(document, 'mousemove', _this._onTouchMove);\n\t\t\t\t\t_on(document, 'mouseup', _this._onDrop);\n\t\t\t\t}\n\n\t\t\t\t_this._loopId = setInterval(_this._emulateDragOver, 50);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif (dataTransfer) {\n\t\t\t\t\tdataTransfer.effectAllowed = 'move';\n\t\t\t\t\toptions.setData && options.setData.call(_this, dataTransfer, dragEl);\n\t\t\t\t}\n\n\t\t\t\t_on(document, 'drop', _this);\n\n\t\t\t\t// #1143: Бывает элемент с IFrame внутри блокирует `drop`,\n\t\t\t\t// поэтому если вызвался `mouseover`, значит надо отменять весь d'n'd.\n\t\t\t\t// Breaking Chrome 62+\n\t\t\t\t// _on(document, 'mouseover', _this);\n\n\t\t\t\t_this._dragStartId = _nextTick(_this._dragStarted);\n\t\t\t}\n\t\t},\n\n\t\t_onDragOver: function (/**Event*/evt) {\n\t\t\tvar el = this.el,\n\t\t\t\ttarget,\n\t\t\t\tdragRect,\n\t\t\t\ttargetRect,\n\t\t\t\trevert,\n\t\t\t\toptions = this.options,\n\t\t\t\tgroup = options.group,\n\t\t\t\tactiveKvSortable = KvSortable.active,\n\t\t\t\tisOwner = (activeGroup === group),\n\t\t\t\tisMovingBetweenKvSortable = false,\n\t\t\t\tcanSort = options.sort;\n\n\t\t\tif (evt.preventDefault !== void 0) {\n\t\t\t\tevt.preventDefault();\n\t\t\t\t!options.dragoverBubble && evt.stopPropagation();\n\t\t\t}\n\n\t\t\tif (dragEl.animated) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tmoved = true;\n\n\t\t\tif (activeKvSortable && !options.disabled &&\n\t\t\t\t(isOwner\n\t\t\t\t\t? canSort || (revert = !rootEl.contains(dragEl)) // Reverting item into the original list\n\t\t\t\t\t: (\n\t\t\t\t\t\tputKvSortable === this ||\n\t\t\t\t\t\t(\n\t\t\t\t\t\t\t(activeKvSortable.lastPullMode = activeGroup.checkPull(this, activeKvSortable, dragEl, evt)) &&\n\t\t\t\t\t\t\tgroup.checkPut(this, activeKvSortable, dragEl, evt)\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t) &&\n\t\t\t\t(evt.rootEl === void 0 || evt.rootEl === this.el) // touch fallback\n\t\t\t) {\n\t\t\t\t// Smart auto-scrolling\n\t\t\t\t_autoScroll(evt, options, this.el);\n\n\t\t\t\tif (_silent) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\ttarget = _closest(evt.target, options.draggable, el);\n\t\t\t\tdragRect = dragEl.getBoundingClientRect();\n\n\t\t\t\tif (putKvSortable !== this) {\n\t\t\t\t\tputKvSortable = this;\n\t\t\t\t\tisMovingBetweenKvSortable = true;\n\t\t\t\t}\n\n\t\t\t\tif (revert) {\n\t\t\t\t\t_cloneHide(activeKvSortable, true);\n\t\t\t\t\tparentEl = rootEl; // actualization\n\n\t\t\t\t\tif (cloneEl || nextEl) {\n\t\t\t\t\t\trootEl.insertBefore(dragEl, cloneEl || nextEl);\n\t\t\t\t\t}\n\t\t\t\t\telse if (!canSort) {\n\t\t\t\t\t\trootEl.appendChild(dragEl);\n\t\t\t\t\t}\n\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\n\t\t\t\tif ((el.children.length === 0) || (el.children[0] === ghostEl) ||\n\t\t\t\t\t(el === evt.target) && (_ghostIsLast(el, evt))\n\t\t\t\t) {\n\t\t\t\t\t//assign target only if condition is true\n\t\t\t\t\tif (el.children.length !== 0 && el.children[0] !== ghostEl && el === evt.target) {\n\t\t\t\t\t\ttarget = el.lastElementChild;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (target) {\n\t\t\t\t\t\tif (target.animated) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttargetRect = target.getBoundingClientRect();\n\t\t\t\t\t}\n\n\t\t\t\t\t_cloneHide(activeKvSortable, isOwner);\n\n\t\t\t\t\tif (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt) !== false) {\n\t\t\t\t\t\tif (!dragEl.contains(el)) {\n\t\t\t\t\t\t\tel.appendChild(dragEl);\n\t\t\t\t\t\t\tparentEl = el; // actualization\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tthis._animate(dragRect, dragEl);\n\t\t\t\t\t\ttarget && this._animate(targetRect, target);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\telse if (target && !target.animated && target !== dragEl && (target.parentNode[expando] !== void 0)) {\n\t\t\t\t\tif (lastEl !== target) {\n\t\t\t\t\t\tlastEl = target;\n\t\t\t\t\t\tlastCSS = _css(target);\n\t\t\t\t\t\tlastParentCSS = _css(target.parentNode);\n\t\t\t\t\t}\n\n\t\t\t\t\ttargetRect = target.getBoundingClientRect();\n\n\t\t\t\t\tvar width = targetRect.right - targetRect.left,\n\t\t\t\t\t\theight = targetRect.bottom - targetRect.top,\n\t\t\t\t\t\tfloating = R_FLOAT.test(lastCSS.cssFloat + lastCSS.display)\n\t\t\t\t\t\t\t|| (lastParentCSS.display == 'flex' && lastParentCSS['flex-direction'].indexOf('row') === 0),\n\t\t\t\t\t\tisWide = (target.offsetWidth > dragEl.offsetWidth),\n\t\t\t\t\t\tisLong = (target.offsetHeight > dragEl.offsetHeight),\n\t\t\t\t\t\thalfway = (floating ? (evt.clientX - targetRect.left) / width : (evt.clientY - targetRect.top) / height) > 0.5,\n\t\t\t\t\t\tnextSibling = target.nextElementSibling,\n\t\t\t\t\t\tafter = false\n\t\t\t\t\t;\n\n\t\t\t\t\tif (floating) {\n\t\t\t\t\t\tvar elTop = dragEl.offsetTop,\n\t\t\t\t\t\t\ttgTop = target.offsetTop;\n\n\t\t\t\t\t\tif (elTop === tgTop) {\n\t\t\t\t\t\t\tafter = (target.previousElementSibling === dragEl) && !isWide || halfway && isWide;\n\t\t\t\t\t\t}\n\t\t\t\t\t\telse if (target.previousElementSibling === dragEl || dragEl.previousElementSibling === target) {\n\t\t\t\t\t\t\tafter = (evt.clientY - targetRect.top) / height > 0.5;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tafter = tgTop > elTop;\n\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if (!isMovingBetweenKvSortable) {\n\t\t\t\t\t\tafter = (nextSibling !== dragEl) && !isLong || halfway && isLong;\n\t\t\t\t\t}\n\n\t\t\t\t\tvar moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, after);\n\n\t\t\t\t\tif (moveVector !== false) {\n\t\t\t\t\t\tif (moveVector === 1 || moveVector === -1) {\n\t\t\t\t\t\t\tafter = (moveVector === 1);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t_silent = true;\n\t\t\t\t\t\tsetTimeout(_unsilent, 30);\n\n\t\t\t\t\t\t_cloneHide(activeKvSortable, isOwner);\n\n\t\t\t\t\t\tif (!dragEl.contains(el)) {\n\t\t\t\t\t\t\tif (after && !nextSibling) {\n\t\t\t\t\t\t\t\tel.appendChild(dragEl);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\ttarget.parentNode.insertBefore(dragEl, after ? nextSibling : target);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tparentEl = dragEl.parentNode; // actualization\n\n\t\t\t\t\t\tthis._animate(dragRect, dragEl);\n\t\t\t\t\t\tthis._animate(targetRect, target);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t_animate: function (prevRect, target) {\n\t\t\tvar ms = this.options.animation;\n\n\t\t\tif (ms) {\n\t\t\t\tvar currentRect = target.getBoundingClientRect();\n\n\t\t\t\tif (prevRect.nodeType === 1) {\n\t\t\t\t\tprevRect = prevRect.getBoundingClientRect();\n\t\t\t\t}\n\n\t\t\t\t_css(target, 'transition', 'none');\n\t\t\t\t_css(target, 'transform', 'translate3d('\n\t\t\t\t\t+ (prevRect.left - currentRect.left) + 'px,'\n\t\t\t\t\t+ (prevRect.top - currentRect.top) + 'px,0)'\n\t\t\t\t);\n\n\t\t\t\ttarget.offsetWidth; // repaint\n\n\t\t\t\t_css(target, 'transition', 'all ' + ms + 'ms');\n\t\t\t\t_css(target, 'transform', 'translate3d(0,0,0)');\n\n\t\t\t\tclearTimeout(target.animated);\n\t\t\t\ttarget.animated = setTimeout(function () {\n\t\t\t\t\t_css(target, 'transition', '');\n\t\t\t\t\t_css(target, 'transform', '');\n\t\t\t\t\ttarget.animated = false;\n\t\t\t\t}, ms);\n\t\t\t}\n\t\t},\n\n\t\t_offUpEvents: function () {\n\t\t\tvar ownerDocument = this.el.ownerDocument;\n\n\t\t\t_off(document, 'touchmove', this._onTouchMove);\n\t\t\t_off(document, 'pointermove', this._onTouchMove);\n\t\t\t_off(ownerDocument, 'mouseup', this._onDrop);\n\t\t\t_off(ownerDocument, 'touchend', this._onDrop);\n\t\t\t_off(ownerDocument, 'pointerup', this._onDrop);\n\t\t\t_off(ownerDocument, 'touchcancel', this._onDrop);\n\t\t\t_off(ownerDocument, 'pointercancel', this._onDrop);\n\t\t\t_off(ownerDocument, 'selectstart', this);\n\t\t},\n\n\t\t_onDrop: function (/**Event*/evt) {\n\t\t\tvar el = this.el,\n\t\t\t\toptions = this.options;\n\n\t\t\tclearInterval(this._loopId);\n\t\t\tclearInterval(autoScroll.pid);\n\t\t\tclearTimeout(this._dragStartTimer);\n\n\t\t\t_cancelNextTick(this._cloneId);\n\t\t\t_cancelNextTick(this._dragStartId);\n\n\t\t\t// Unbind events\n\t\t\t_off(document, 'mouseover', this);\n\t\t\t_off(document, 'mousemove', this._onTouchMove);\n\n\t\t\tif (this.nativeDraggable) {\n\t\t\t\t_off(document, 'drop', this);\n\t\t\t\t_off(el, 'dragstart', this._onDragStart);\n\t\t\t}\n\n\t\t\tthis._offUpEvents();\n\n\t\t\tif (evt) {\n\t\t\t\tif (moved) {\n\t\t\t\t\tevt.preventDefault();\n\t\t\t\t\t!options.dropBubble && evt.stopPropagation();\n\t\t\t\t}\n\n\t\t\t\tghostEl && ghostEl.parentNode && ghostEl.parentNode.removeChild(ghostEl);\n\n\t\t\t\tif (rootEl === parentEl || KvSortable.active.lastPullMode !== 'clone') {\n\t\t\t\t\t// Remove clone\n\t\t\t\t\tcloneEl && cloneEl.parentNode && cloneEl.parentNode.removeChild(cloneEl);\n\t\t\t\t}\n\n\t\t\t\tif (dragEl) {\n\t\t\t\t\tif (this.nativeDraggable) {\n\t\t\t\t\t\t_off(dragEl, 'dragend', this);\n\t\t\t\t\t}\n\n\t\t\t\t\t_disableDraggable(dragEl);\n\t\t\t\t\tdragEl.style['will-change'] = '';\n\n\t\t\t\t\t// Remove class's\n\t\t\t\t\t_toggleClass(dragEl, this.options.ghostClass, false);\n\t\t\t\t\t_toggleClass(dragEl, this.options.chosenClass, false);\n\n\t\t\t\t\t// Drag stop event\n\t\t\t\t\t_dispatchEvent(this, rootEl, 'unchoose', dragEl, parentEl, rootEl, oldIndex);\n\n\t\t\t\t\tif (rootEl !== parentEl) {\n\t\t\t\t\t\tnewIndex = _index(dragEl, options.draggable);\n\n\t\t\t\t\t\tif (newIndex >= 0) {\n\t\t\t\t\t\t\t// Add event\n\t\t\t\t\t\t\t_dispatchEvent(null, parentEl, 'add', dragEl, parentEl, rootEl, oldIndex, newIndex);\n\n\t\t\t\t\t\t\t// Remove event\n\t\t\t\t\t\t\t_dispatchEvent(this, rootEl, 'remove', dragEl, parentEl, rootEl, oldIndex, newIndex);\n\n\t\t\t\t\t\t\t// drag from one list and drop into another\n\t\t\t\t\t\t\t_dispatchEvent(null, parentEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex);\n\t\t\t\t\t\t\t_dispatchEvent(this, rootEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\telse {\n\t\t\t\t\t\tif (dragEl.nextSibling !== nextEl) {\n\t\t\t\t\t\t\t// Get the index of the dragged element within its parent\n\t\t\t\t\t\t\tnewIndex = _index(dragEl, options.draggable);\n\n\t\t\t\t\t\t\tif (newIndex >= 0) {\n\t\t\t\t\t\t\t\t// drag & drop within the same list\n\t\t\t\t\t\t\t\t_dispatchEvent(this, rootEl, 'update', dragEl, parentEl, rootEl, oldIndex, newIndex);\n\t\t\t\t\t\t\t\t_dispatchEvent(this, rootEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (KvSortable.active) {\n\t\t\t\t\t\t/* jshint eqnull:true */\n\t\t\t\t\t\tif (newIndex == null || newIndex === -1) {\n\t\t\t\t\t\t\tnewIndex = oldIndex;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t_dispatchEvent(this, rootEl, 'end', dragEl, parentEl, rootEl, oldIndex, newIndex);\n\n\t\t\t\t\t\t// Save sorting\n\t\t\t\t\t\tthis.save();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t}\n\n\t\t\tthis._nulling();\n\t\t},\n\n\t\t_nulling: function() {\n\t\t\trootEl =\n\t\t\tdragEl =\n\t\t\tparentEl =\n\t\t\tghostEl =\n\t\t\tnextEl =\n\t\t\tcloneEl =\n\t\t\tlastDownEl =\n\n\t\t\tscrollEl =\n\t\t\tscrollParentEl =\n\n\t\t\ttapEvt =\n\t\t\ttouchEvt =\n\n\t\t\tmoved =\n\t\t\tnewIndex =\n\n\t\t\tlastEl =\n\t\t\tlastCSS =\n\n\t\t\tputKvSortable =\n\t\t\tactiveGroup =\n\t\t\tKvSortable.active = null;\n\n\t\t\tsavedInputChecked.forEach(function (el) {\n\t\t\t\tel.checked = true;\n\t\t\t});\n\t\t\tsavedInputChecked.length = 0;\n\t\t},\n\n\t\thandleEvent: function (/**Event*/evt) {\n\t\t\tswitch (evt.type) {\n\t\t\t\tcase 'drop':\n\t\t\t\tcase 'dragend':\n\t\t\t\t\tthis._onDrop(evt);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'dragover':\n\t\t\t\tcase 'dragenter':\n\t\t\t\t\tif (dragEl) {\n\t\t\t\t\t\tthis._onDragOver(evt);\n\t\t\t\t\t\t_globalDragOver(evt);\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'mouseover':\n\t\t\t\t\tthis._onDrop(evt);\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase 'selectstart':\n\t\t\t\t\tevt.preventDefault();\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t},\n\n\n\t\t/**\n\t\t * Serializes the item into an array of string.\n\t\t * @returns {String[]}\n\t\t */\n\t\ttoArray: function () {\n\t\t\tvar order = [],\n\t\t\t\tel,\n\t\t\t\tchildren = this.el.children,\n\t\t\t\ti = 0,\n\t\t\t\tn = children.length,\n\t\t\t\toptions = this.options;\n\n\t\t\tfor (; i < n; i++) {\n\t\t\t\tel = children[i];\n\t\t\t\tif (_closest(el, options.draggable, this.el)) {\n\t\t\t\t\torder.push(el.getAttribute(options.dataIdAttr) || _generateId(el));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn order;\n\t\t},\n\n\n\t\t/**\n\t\t * Sorts the elements according to the array.\n\t\t * @param  {String[]}  order  order of the items\n\t\t */\n\t\tsort: function (order) {\n\t\t\tvar items = {}, rootEl = this.el;\n\n\t\t\tthis.toArray().forEach(function (id, i) {\n\t\t\t\tvar el = rootEl.children[i];\n\n\t\t\t\tif (_closest(el, this.options.draggable, rootEl)) {\n\t\t\t\t\titems[id] = el;\n\t\t\t\t}\n\t\t\t}, this);\n\n\t\t\torder.forEach(function (id) {\n\t\t\t\tif (items[id]) {\n\t\t\t\t\trootEl.removeChild(items[id]);\n\t\t\t\t\trootEl.appendChild(items[id]);\n\t\t\t\t}\n\t\t\t});\n\t\t},\n\n\n\t\t/**\n\t\t * Save the current sorting\n\t\t */\n\t\tsave: function () {\n\t\t\tvar store = this.options.store;\n\t\t\tstore && store.set(this);\n\t\t},\n\n\n\t\t/**\n\t\t * For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.\n\t\t * @param   {HTMLElement}  el\n\t\t * @param   {String}       [selector]  default: `options.draggable`\n\t\t * @returns {HTMLElement|null}\n\t\t */\n\t\tclosest: function (el, selector) {\n\t\t\treturn _closest(el, selector || this.options.draggable, this.el);\n\t\t},\n\n\n\t\t/**\n\t\t * Set/get option\n\t\t * @param   {string} name\n\t\t * @param   {*}      [value]\n\t\t * @returns {*}\n\t\t */\n\t\toption: function (name, value) {\n\t\t\tvar options = this.options;\n\n\t\t\tif (value === void 0) {\n\t\t\t\treturn options[name];\n\t\t\t} else {\n\t\t\t\toptions[name] = value;\n\n\t\t\t\tif (name === 'group') {\n\t\t\t\t\t_prepareGroup(options);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\n\t\t/**\n\t\t * Destroy\n\t\t */\n\t\tdestroy: function () {\n\t\t\tvar el = this.el;\n\n\t\t\tel[expando] = null;\n\n\t\t\t_off(el, 'mousedown', this._onTapStart);\n\t\t\t_off(el, 'touchstart', this._onTapStart);\n\t\t\t_off(el, 'pointerdown', this._onTapStart);\n\n\t\t\tif (this.nativeDraggable) {\n\t\t\t\t_off(el, 'dragover', this);\n\t\t\t\t_off(el, 'dragenter', this);\n\t\t\t}\n\n\t\t\t// Remove draggable attributes\n\t\t\tArray.prototype.forEach.call(el.querySelectorAll('[draggable]'), function (el) {\n\t\t\t\tel.removeAttribute('draggable');\n\t\t\t});\n\n\t\t\ttouchDragOverListeners.splice(touchDragOverListeners.indexOf(this._onDragOver), 1);\n\n\t\t\tthis._onDrop();\n\n\t\t\tthis.el = el = null;\n\t\t}\n\t};\n\n\n\tfunction _cloneHide(kvsortable, state) {\n\t\tif (kvsortable.lastPullMode !== 'clone') {\n\t\t\tstate = true;\n\t\t}\n\n\t\tif (cloneEl && (cloneEl.state !== state)) {\n\t\t\t_css(cloneEl, 'display', state ? 'none' : '');\n\n\t\t\tif (!state) {\n\t\t\t\tif (cloneEl.state) {\n\t\t\t\t\tif (kvsortable.options.group.revertClone) {\n\t\t\t\t\t\trootEl.insertBefore(cloneEl, nextEl);\n\t\t\t\t\t\tkvsortable._animate(dragEl, cloneEl);\n\t\t\t\t\t} else {\n\t\t\t\t\t\trootEl.insertBefore(cloneEl, dragEl);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcloneEl.state = state;\n\t\t}\n\t}\n\n\n\tfunction _closest(/**HTMLElement*/el, /**String*/selector, /**HTMLElement*/ctx) {\n\t\tif (el) {\n\t\t\tctx = ctx || document;\n\n\t\t\tdo {\n\t\t\t\tif ((selector === '>*' && el.parentNode === ctx) || _matches(el, selector)) {\n\t\t\t\t\treturn el;\n\t\t\t\t}\n\t\t\t\t/* jshint boss:true */\n\t\t\t} while (el = _getParentOrHost(el));\n\t\t}\n\n\t\treturn null;\n\t}\n\n\n\tfunction _getParentOrHost(el) {\n\t\tvar parent = el.host;\n\n\t\treturn (parent && parent.nodeType) ? parent : el.parentNode;\n\t}\n\n\n\tfunction _globalDragOver(/**Event*/evt) {\n\t\tif (evt.dataTransfer) {\n\t\t\tevt.dataTransfer.dropEffect = 'move';\n\t\t}\n\t\tevt.preventDefault();\n\t}\n\n\n\tfunction _on(el, event, fn) {\n\t\tel.addEventListener(event, fn, captureMode);\n\t}\n\n\n\tfunction _off(el, event, fn) {\n\t\tel.removeEventListener(event, fn, captureMode);\n\t}\n\n\n\tfunction _toggleClass(el, name, state) {\n\t\tif (el) {\n\t\t\tif (el.classList) {\n\t\t\t\tel.classList[state ? 'add' : 'remove'](name);\n\t\t\t}\n\t\t\telse {\n\t\t\t\tvar className = (' ' + el.className + ' ').replace(R_SPACE, ' ').replace(' ' + name + ' ', ' ');\n\t\t\t\tel.className = (className + (state ? ' ' + name : '')).replace(R_SPACE, ' ');\n\t\t\t}\n\t\t}\n\t}\n\n\n\tfunction _css(el, prop, val) {\n\t\tvar style = el && el.style;\n\n\t\tif (style) {\n\t\t\tif (val === void 0) {\n\t\t\t\tif (document.defaultView && document.defaultView.getComputedStyle) {\n\t\t\t\t\tval = document.defaultView.getComputedStyle(el, '');\n\t\t\t\t}\n\t\t\t\telse if (el.currentStyle) {\n\t\t\t\t\tval = el.currentStyle;\n\t\t\t\t}\n\n\t\t\t\treturn prop === void 0 ? val : val[prop];\n\t\t\t}\n\t\t\telse {\n\t\t\t\tif (!(prop in style)) {\n\t\t\t\t\tprop = '-webkit-' + prop;\n\t\t\t\t}\n\n\t\t\t\tstyle[prop] = val + (typeof val === 'string' ? '' : 'px');\n\t\t\t}\n\t\t}\n\t}\n\n\n\tfunction _find(ctx, tagName, iterator) {\n\t\tif (ctx) {\n\t\t\tvar list = ctx.getElementsByTagName(tagName), i = 0, n = list.length;\n\n\t\t\tif (iterator) {\n\t\t\t\tfor (; i < n; i++) {\n\t\t\t\t\titerator(list[i], i);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn list;\n\t\t}\n\n\t\treturn [];\n\t}\n\n\n\n\tfunction _dispatchEvent(kvsortable, rootEl, name, targetEl, toEl, fromEl, startIndex, newIndex) {\n\t\tkvsortable = (kvsortable || rootEl[expando]);\n\n\t\tvar evt = document.createEvent('Event'),\n\t\t\toptions = kvsortable.options,\n\t\t\tonName = 'on' + name.charAt(0).toUpperCase() + name.substr(1);\n\n\t\tevt.initEvent(name, true, true);\n\n\t\tevt.to = toEl || rootEl;\n\t\tevt.from = fromEl || rootEl;\n\t\tevt.item = targetEl || rootEl;\n\t\tevt.clone = cloneEl;\n\n\t\tevt.oldIndex = startIndex;\n\t\tevt.newIndex = newIndex;\n\n\t\trootEl.dispatchEvent(evt);\n\n\t\tif (options[onName]) {\n\t\t\toptions[onName].call(kvsortable, evt);\n\t\t}\n\t}\n\n\n\tfunction _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect, originalEvt, willInsertAfter) {\n\t\tvar evt,\n\t\t\tkvsortable = fromEl[expando],\n\t\t\tonMoveFn = kvsortable.options.onMove,\n\t\t\tretVal;\n\n\t\tevt = document.createEvent('Event');\n\t\tevt.initEvent('move', true, true);\n\n\t\tevt.to = toEl;\n\t\tevt.from = fromEl;\n\t\tevt.dragged = dragEl;\n\t\tevt.draggedRect = dragRect;\n\t\tevt.related = targetEl || toEl;\n\t\tevt.relatedRect = targetRect || toEl.getBoundingClientRect();\n\t\tevt.willInsertAfter = willInsertAfter;\n\n\t\tfromEl.dispatchEvent(evt);\n\n\t\tif (onMoveFn) {\n\t\t\tretVal = onMoveFn.call(kvsortable, evt, originalEvt);\n\t\t}\n\n\t\treturn retVal;\n\t}\n\n\n\tfunction _disableDraggable(el) {\n\t\tel.draggable = false;\n\t}\n\n\n\tfunction _unsilent() {\n\t\t_silent = false;\n\t}\n\n\n\t/** @returns {HTMLElement|false} */\n\tfunction _ghostIsLast(el, evt) {\n\t\tvar lastEl = el.lastElementChild,\n\t\t\trect = lastEl.getBoundingClientRect();\n\n\t\t// 5 — min delta\n\t\t// abs — нельзя добавлять, а то глюки при наведении сверху\n\t\treturn (evt.clientY - (rect.top + rect.height) > 5) ||\n\t\t\t(evt.clientX - (rect.left + rect.width) > 5);\n\t}\n\n\n\t/**\n\t * Generate id\n\t * @param   {HTMLElement} el\n\t * @returns {String}\n\t * @private\n\t */\n\tfunction _generateId(el) {\n\t\tvar str = el.tagName + el.className + el.src + el.href + el.textContent,\n\t\t\ti = str.length,\n\t\t\tsum = 0;\n\n\t\twhile (i--) {\n\t\t\tsum += str.charCodeAt(i);\n\t\t}\n\n\t\treturn sum.toString(36);\n\t}\n\n\t/**\n\t * Returns the index of an element within its parent for a selected set of\n\t * elements\n\t * @param  {HTMLElement} el\n\t * @param  {selector} selector\n\t * @return {number}\n\t */\n\tfunction _index(el, selector) {\n\t\tvar index = 0;\n\n\t\tif (!el || !el.parentNode) {\n\t\t\treturn -1;\n\t\t}\n\n\t\twhile (el && (el = el.previousElementSibling)) {\n\t\t\tif ((el.nodeName.toUpperCase() !== 'TEMPLATE') && (selector === '>*' || _matches(el, selector))) {\n\t\t\t\tindex++;\n\t\t\t}\n\t\t}\n\n\t\treturn index;\n\t}\n\n\tfunction _matches(/**HTMLElement*/el, /**String*/selector) {\n\t\tif (el) {\n\t\t\tselector = selector.split('.');\n\n\t\t\tvar tag = selector.shift().toUpperCase(),\n\t\t\t\tre = new RegExp('\\\\s(' + selector.join('|') + ')(?=\\\\s)', 'g');\n\n\t\t\treturn (\n\t\t\t\t(tag === '' || el.nodeName.toUpperCase() == tag) &&\n\t\t\t\t(!selector.length || ((' ' + el.className + ' ').match(re) || []).length == selector.length)\n\t\t\t);\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tfunction _throttle(callback, ms) {\n\t\tvar args, _this;\n\n\t\treturn function () {\n\t\t\tif (args === void 0) {\n\t\t\t\targs = arguments;\n\t\t\t\t_this = this;\n\n\t\t\t\tsetTimeout(function () {\n\t\t\t\t\tif (args.length === 1) {\n\t\t\t\t\t\tcallback.call(_this, args[0]);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcallback.apply(_this, args);\n\t\t\t\t\t}\n\n\t\t\t\t\targs = void 0;\n\t\t\t\t}, ms);\n\t\t\t}\n\t\t};\n\t}\n\n\tfunction _extend(dst, src) {\n\t\tif (dst && src) {\n\t\t\tfor (var key in src) {\n\t\t\t\tif (src.hasOwnProperty(key)) {\n\t\t\t\t\tdst[key] = src[key];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn dst;\n\t}\n\n\tfunction _clone(el) {\n\t\tif (Polymer && Polymer.dom) {\n\t\t\treturn Polymer.dom(el).cloneNode(true);\n\t\t}\n\t\telse if ($) {\n\t\t\treturn $(el).clone(true)[0];\n\t\t}\n\t\telse {\n\t\t\treturn el.cloneNode(true);\n\t\t}\n\t}\n\n\tfunction _saveInputCheckedState(root) {\n\t\tvar inputs = root.getElementsByTagName('input');\n\t\tvar idx = inputs.length;\n\n\t\twhile (idx--) {\n\t\t\tvar el = inputs[idx];\n\t\t\tel.checked && savedInputChecked.push(el);\n\t\t}\n\t}\n\n\tfunction _nextTick(fn) {\n\t\treturn setTimeout(fn, 0);\n\t}\n\n\tfunction _cancelNextTick(id) {\n\t\treturn clearTimeout(id);\n\t}\n\n\t// Fixed #973:\n\t_on(document, 'touchmove', function (evt) {\n\t\tif (KvSortable.active) {\n\t\t\tevt.preventDefault();\n\t\t}\n\t});\n\n\t// Export utils\n\tKvSortable.utils = {\n\t\ton: _on,\n\t\toff: _off,\n\t\tcss: _css,\n\t\tfind: _find,\n\t\tis: function (el, selector) {\n\t\t\treturn !!_closest(el, selector, el);\n\t\t},\n\t\textend: _extend,\n\t\tthrottle: _throttle,\n\t\tclosest: _closest,\n\t\ttoggleClass: _toggleClass,\n\t\tclone: _clone,\n\t\tindex: _index,\n\t\tnextTick: _nextTick,\n\t\tcancelNextTick: _cancelNextTick\n\t};\n\n\n\t/**\n\t * Create kvsortable instance\n\t * @param {HTMLElement}  el\n\t * @param {Object}      [options]\n\t */\n\tKvSortable.create = function (el, options) {\n\t\treturn new KvSortable(el, options);\n\t};\n\n\n\t// Export\n\tKvSortable.version = '1.7.0';\n\treturn KvSortable;\n});\n/**\n * jQuery plugin for KvSortable\n */\n(function (factory) {\n    \"use strict\";\n\n    if (typeof define === \"function\" && define.amd) {\n        define([\"jquery\"], factory);\n    }\n    else {\n        /* jshint sub:true */\n        factory(jQuery);\n    }\n})(function ($) {\n    \"use strict\";\n    $.fn.kvsortable = function (options) {\n        var retVal,\n            args = arguments;\n\n        this.each(function () {\n            var $el = $(this), kvsortable = $el.data('kvsortable');\n\n            if (!kvsortable && (options instanceof Object || !options)) {\n                kvsortable = new KvSortable(this, options);\n                $el.data('kvsortable', kvsortable);\n            }\n\n            if (kvsortable) {\n                if (options === 'widget') {\n                    retVal = kvsortable;\n                }\n                else if (options === 'destroy') {\n                    kvsortable.destroy();\n                    $el.removeData('kvsortable');\n                }\n                else if (typeof kvsortable[options] === 'function') {\n                    retVal = kvsortable[options].apply(kvsortable, [].slice.call(args, 1));\n                }\n                else if (options in kvsortable.options) {\n                    retVal = kvsortable.option.apply(kvsortable, args);\n                }\n            }\n        });\n\n        return (retVal === void 0) ? this : retVal;\n    };\n});"
  },
  {
    "path": "resources/assets/bootstrap3-editable/css/bootstrap-editable.css",
    "content": "/*! X-editable - v1.5.1 \n* In-place editing with Twitter Bootstrap, jQuery UI or pure jQuery\n* http://github.com/vitalets/x-editable\n* Copyright (c) 2013 Vitaliy Potapov; Licensed MIT */\n.editableform {\n    margin-bottom: 0; /* overwrites bootstrap margin */\n}\n\n.editableform .control-group {\n    margin-bottom: 0; /* overwrites bootstrap margin */\n    white-space: nowrap; /* prevent wrapping buttons on new line */\n    line-height: 20px; /* overwriting bootstrap line-height. See #133 */\n}\n\n/* \n  BS3 width:1005 for inputs breaks editable form in popup \n  See: https://github.com/vitalets/x-editable/issues/393\n*/\n.editableform .form-control {\n    width: auto;\n}\n\n.editable-buttons {\n   display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */\n   vertical-align: top;\n   margin-left: 7px;\n   /* inline-block emulation for IE7*/\n   zoom: 1; \n   *display: inline;\n}\n\n.editable-buttons.editable-buttons-bottom {\n   display: block; \n   margin-top: 7px;\n   margin-left: 0;\n}\n\n.editable-input {\n    vertical-align: top; \n    display: inline-block; /* should be inline to take effect of parent's white-space: nowrap */\n    width: auto; /* bootstrap-responsive has width: 100% that breakes layout */\n    white-space: normal; /* reset white-space decalred in parent*/\n   /* display-inline emulation for IE7*/\n   zoom: 1; \n   *display: inline;   \n}\n\n.editable-buttons .editable-cancel {\n   margin-left: 7px; \n}\n\n/*for jquery-ui buttons need set height to look more pretty*/\n.editable-buttons button.ui-button-icon-only {\n   height: 24px; \n   width: 30px;\n}\n\n.editableform-loading {\n    background: url('../img/loading.gif') center center no-repeat;  \n    height: 25px;\n    width: auto; \n    min-width: 25px; \n}\n\n.editable-inline .editableform-loading {\n    background-position: left 5px;      \n}\n\n .editable-error-block {\n    max-width: 300px;\n    margin: 5px 0 0 0;\n    width: auto;\n    white-space: normal;\n}\n\n/*add padding for jquery ui*/\n.editable-error-block.ui-state-error {\n    padding: 3px;  \n}  \n\n.editable-error {\n   color: red;  \n}\n\n/* ---- For specific types ---- */\n\n.editableform .editable-date {\n    padding: 0; \n    margin: 0;\n    float: left;\n}\n\n/* move datepicker icon to center of add-on button. See https://github.com/vitalets/x-editable/issues/183 */\n.editable-inline .add-on .icon-th {\n   margin-top: 3px;\n   margin-left: 1px; \n}\n\n\n/* checklist vertical alignment */\n.editable-checklist label input[type=\"checkbox\"], \n.editable-checklist label span {\n    vertical-align: middle;\n    margin: 0;\n}\n\n.editable-checklist label {\n    white-space: nowrap; \n}\n\n/* set exact width of textarea to fit buttons toolbar */\n.editable-wysihtml5 {\n    width: 566px; \n    height: 250px; \n}\n\n/* clear button shown as link in date inputs */\n.editable-clear {\n   clear: both;\n   font-size: 0.9em;\n   text-decoration: none;\n   text-align: right;\n}\n\n/* IOS-style clear button for text inputs */\n.editable-clear-x {\n   background: url('../img/clear.png') center center no-repeat;\n   display: block;\n   width: 13px;    \n   height: 13px;\n   position: absolute;\n   opacity: 0.6;\n   z-index: 100;\n   \n   top: 50%;\n   right: 6px;\n   margin-top: -6px;\n   \n}\n\n.editable-clear-x:hover {\n   opacity: 1;\n}\n\n.editable-pre-wrapped {\n   white-space: pre-wrap;\n}\n.editable-container.editable-popup {\n    max-width: none !important; /* without this rule poshytip/tooltip does not stretch */\n}  \n\n.editable-container.popover {\n    width: auto; /* without this rule popover does not stretch */\n}\n\n.editable-container.editable-inline {\n    display: inline-block; \n    vertical-align: middle;\n    width: auto;\n    /* inline-block emulation for IE7*/\n    zoom: 1; \n    *display: inline;    \n}\n\n.editable-container.ui-widget {\n   font-size: inherit;  /* jqueryui widget font 1.1em too big, overwrite it */\n   z-index: 9990; /* should be less than select2 dropdown z-index to close dropdown first when click */\n}\n.editable-click, \na.editable-click, \na.editable-click:hover {\n    text-decoration: none;\n    border-bottom: dashed 1px #0088cc;\n}\n\n.editable-click.editable-disabled, \na.editable-click.editable-disabled, \na.editable-click.editable-disabled:hover {\n   color: #585858;  \n   cursor: default;\n   border-bottom: none;\n}\n\n.editable-empty, .editable-empty:hover, .editable-empty:focus{\n  font-style: italic; \n  color: #DD1144;  \n  /* border-bottom: none; */\n  text-decoration: none;\n}\n\n.editable-unsaved {\n  font-weight: bold; \n}\n\n.editable-unsaved:after {\n/*    content: '*'*/\n}\n\n.editable-bg-transition {\n  -webkit-transition: background-color 1400ms ease-out;\n  -moz-transition: background-color 1400ms ease-out;\n  -o-transition: background-color 1400ms ease-out;\n  -ms-transition: background-color 1400ms ease-out;\n  transition: background-color 1400ms ease-out;  \n}\n\n/*see https://github.com/vitalets/x-editable/issues/139 */\n.form-horizontal .editable\n{ \n    padding-top: 5px;\n    display:inline-block;\n}\n\n\n/*!\n * Datepicker for Bootstrap\n *\n * Copyright 2012 Stefan Petre\n * Improvements by Andrew Rowls\n * Licensed under the Apache License v2.0\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n */\n.datepicker {\n  padding: 4px;\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n  direction: ltr;\n  /*.dow {\n\t\tborder-top: 1px solid #ddd !important;\n\t}*/\n\n}\n.datepicker-inline {\n  width: 220px;\n}\n.datepicker.datepicker-rtl {\n  direction: rtl;\n}\n.datepicker.datepicker-rtl table tr td span {\n  float: right;\n}\n.datepicker-dropdown {\n  top: 0;\n  left: 0;\n}\n.datepicker-dropdown:before {\n  content: '';\n  display: inline-block;\n  border-left: 7px solid transparent;\n  border-right: 7px solid transparent;\n  border-bottom: 7px solid #ccc;\n  border-bottom-color: rgba(0, 0, 0, 0.2);\n  position: absolute;\n  top: -7px;\n  left: 6px;\n}\n.datepicker-dropdown:after {\n  content: '';\n  display: inline-block;\n  border-left: 6px solid transparent;\n  border-right: 6px solid transparent;\n  border-bottom: 6px solid #ffffff;\n  position: absolute;\n  top: -6px;\n  left: 7px;\n}\n.datepicker > div {\n  display: none;\n}\n.datepicker.days div.datepicker-days {\n  display: block;\n}\n.datepicker.months div.datepicker-months {\n  display: block;\n}\n.datepicker.years div.datepicker-years {\n  display: block;\n}\n.datepicker table {\n  margin: 0;\n}\n.datepicker td,\n.datepicker th {\n  text-align: center;\n  width: 20px;\n  height: 20px;\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n  border: none;\n}\n.table-striped .datepicker table tr td,\n.table-striped .datepicker table tr th {\n  background-color: transparent;\n}\n.datepicker table tr td.day:hover {\n  background: #eeeeee;\n  cursor: pointer;\n}\n.datepicker table tr td.old,\n.datepicker table tr td.new {\n  color: #999999;\n}\n.datepicker table tr td.disabled,\n.datepicker table tr td.disabled:hover {\n  background: none;\n  color: #999999;\n  cursor: default;\n}\n.datepicker table tr td.today,\n.datepicker table tr td.today:hover,\n.datepicker table tr td.today.disabled,\n.datepicker table tr td.today.disabled:hover {\n  background-color: #fde19a;\n  background-image: -moz-linear-gradient(top, #fdd49a, #fdf59a);\n  background-image: -ms-linear-gradient(top, #fdd49a, #fdf59a);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#fdd49a), to(#fdf59a));\n  background-image: -webkit-linear-gradient(top, #fdd49a, #fdf59a);\n  background-image: -o-linear-gradient(top, #fdd49a, #fdf59a);\n  background-image: linear-gradient(top, #fdd49a, #fdf59a);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fdd49a', endColorstr='#fdf59a', GradientType=0);\n  border-color: #fdf59a #fdf59a #fbed50;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  color: #000;\n}\n.datepicker table tr td.today:hover,\n.datepicker table tr td.today:hover:hover,\n.datepicker table tr td.today.disabled:hover,\n.datepicker table tr td.today.disabled:hover:hover,\n.datepicker table tr td.today:active,\n.datepicker table tr td.today:hover:active,\n.datepicker table tr td.today.disabled:active,\n.datepicker table tr td.today.disabled:hover:active,\n.datepicker table tr td.today.active,\n.datepicker table tr td.today:hover.active,\n.datepicker table tr td.today.disabled.active,\n.datepicker table tr td.today.disabled:hover.active,\n.datepicker table tr td.today.disabled,\n.datepicker table tr td.today:hover.disabled,\n.datepicker table tr td.today.disabled.disabled,\n.datepicker table tr td.today.disabled:hover.disabled,\n.datepicker table tr td.today[disabled],\n.datepicker table tr td.today:hover[disabled],\n.datepicker table tr td.today.disabled[disabled],\n.datepicker table tr td.today.disabled:hover[disabled] {\n  background-color: #fdf59a;\n}\n.datepicker table tr td.today:active,\n.datepicker table tr td.today:hover:active,\n.datepicker table tr td.today.disabled:active,\n.datepicker table tr td.today.disabled:hover:active,\n.datepicker table tr td.today.active,\n.datepicker table tr td.today:hover.active,\n.datepicker table tr td.today.disabled.active,\n.datepicker table tr td.today.disabled:hover.active {\n  background-color: #fbf069 \\9;\n}\n.datepicker table tr td.today:hover:hover {\n  color: #000;\n}\n.datepicker table tr td.today.active:hover {\n  color: #fff;\n}\n.datepicker table tr td.range,\n.datepicker table tr td.range:hover,\n.datepicker table tr td.range.disabled,\n.datepicker table tr td.range.disabled:hover {\n  background: #eeeeee;\n  -webkit-border-radius: 0;\n  -moz-border-radius: 0;\n  border-radius: 0;\n}\n.datepicker table tr td.range.today,\n.datepicker table tr td.range.today:hover,\n.datepicker table tr td.range.today.disabled,\n.datepicker table tr td.range.today.disabled:hover {\n  background-color: #f3d17a;\n  background-image: -moz-linear-gradient(top, #f3c17a, #f3e97a);\n  background-image: -ms-linear-gradient(top, #f3c17a, #f3e97a);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#f3c17a), to(#f3e97a));\n  background-image: -webkit-linear-gradient(top, #f3c17a, #f3e97a);\n  background-image: -o-linear-gradient(top, #f3c17a, #f3e97a);\n  background-image: linear-gradient(top, #f3c17a, #f3e97a);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f3c17a', endColorstr='#f3e97a', GradientType=0);\n  border-color: #f3e97a #f3e97a #edde34;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  -webkit-border-radius: 0;\n  -moz-border-radius: 0;\n  border-radius: 0;\n}\n.datepicker table tr td.range.today:hover,\n.datepicker table tr td.range.today:hover:hover,\n.datepicker table tr td.range.today.disabled:hover,\n.datepicker table tr td.range.today.disabled:hover:hover,\n.datepicker table tr td.range.today:active,\n.datepicker table tr td.range.today:hover:active,\n.datepicker table tr td.range.today.disabled:active,\n.datepicker table tr td.range.today.disabled:hover:active,\n.datepicker table tr td.range.today.active,\n.datepicker table tr td.range.today:hover.active,\n.datepicker table tr td.range.today.disabled.active,\n.datepicker table tr td.range.today.disabled:hover.active,\n.datepicker table tr td.range.today.disabled,\n.datepicker table tr td.range.today:hover.disabled,\n.datepicker table tr td.range.today.disabled.disabled,\n.datepicker table tr td.range.today.disabled:hover.disabled,\n.datepicker table tr td.range.today[disabled],\n.datepicker table tr td.range.today:hover[disabled],\n.datepicker table tr td.range.today.disabled[disabled],\n.datepicker table tr td.range.today.disabled:hover[disabled] {\n  background-color: #f3e97a;\n}\n.datepicker table tr td.range.today:active,\n.datepicker table tr td.range.today:hover:active,\n.datepicker table tr td.range.today.disabled:active,\n.datepicker table tr td.range.today.disabled:hover:active,\n.datepicker table tr td.range.today.active,\n.datepicker table tr td.range.today:hover.active,\n.datepicker table tr td.range.today.disabled.active,\n.datepicker table tr td.range.today.disabled:hover.active {\n  background-color: #efe24b \\9;\n}\n.datepicker table tr td.selected,\n.datepicker table tr td.selected:hover,\n.datepicker table tr td.selected.disabled,\n.datepicker table tr td.selected.disabled:hover {\n  background-color: #9e9e9e;\n  background-image: -moz-linear-gradient(top, #b3b3b3, #808080);\n  background-image: -ms-linear-gradient(top, #b3b3b3, #808080);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#b3b3b3), to(#808080));\n  background-image: -webkit-linear-gradient(top, #b3b3b3, #808080);\n  background-image: -o-linear-gradient(top, #b3b3b3, #808080);\n  background-image: linear-gradient(top, #b3b3b3, #808080);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#b3b3b3', endColorstr='#808080', GradientType=0);\n  border-color: #808080 #808080 #595959;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  color: #fff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n.datepicker table tr td.selected:hover,\n.datepicker table tr td.selected:hover:hover,\n.datepicker table tr td.selected.disabled:hover,\n.datepicker table tr td.selected.disabled:hover:hover,\n.datepicker table tr td.selected:active,\n.datepicker table tr td.selected:hover:active,\n.datepicker table tr td.selected.disabled:active,\n.datepicker table tr td.selected.disabled:hover:active,\n.datepicker table tr td.selected.active,\n.datepicker table tr td.selected:hover.active,\n.datepicker table tr td.selected.disabled.active,\n.datepicker table tr td.selected.disabled:hover.active,\n.datepicker table tr td.selected.disabled,\n.datepicker table tr td.selected:hover.disabled,\n.datepicker table tr td.selected.disabled.disabled,\n.datepicker table tr td.selected.disabled:hover.disabled,\n.datepicker table tr td.selected[disabled],\n.datepicker table tr td.selected:hover[disabled],\n.datepicker table tr td.selected.disabled[disabled],\n.datepicker table tr td.selected.disabled:hover[disabled] {\n  background-color: #808080;\n}\n.datepicker table tr td.selected:active,\n.datepicker table tr td.selected:hover:active,\n.datepicker table tr td.selected.disabled:active,\n.datepicker table tr td.selected.disabled:hover:active,\n.datepicker table tr td.selected.active,\n.datepicker table tr td.selected:hover.active,\n.datepicker table tr td.selected.disabled.active,\n.datepicker table tr td.selected.disabled:hover.active {\n  background-color: #666666 \\9;\n}\n.datepicker table tr td.active,\n.datepicker table tr td.active:hover,\n.datepicker table tr td.active.disabled,\n.datepicker table tr td.active.disabled:hover {\n  background-color: #006dcc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -ms-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(top, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  color: #fff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n.datepicker table tr td.active:hover,\n.datepicker table tr td.active:hover:hover,\n.datepicker table tr td.active.disabled:hover,\n.datepicker table tr td.active.disabled:hover:hover,\n.datepicker table tr td.active:active,\n.datepicker table tr td.active:hover:active,\n.datepicker table tr td.active.disabled:active,\n.datepicker table tr td.active.disabled:hover:active,\n.datepicker table tr td.active.active,\n.datepicker table tr td.active:hover.active,\n.datepicker table tr td.active.disabled.active,\n.datepicker table tr td.active.disabled:hover.active,\n.datepicker table tr td.active.disabled,\n.datepicker table tr td.active:hover.disabled,\n.datepicker table tr td.active.disabled.disabled,\n.datepicker table tr td.active.disabled:hover.disabled,\n.datepicker table tr td.active[disabled],\n.datepicker table tr td.active:hover[disabled],\n.datepicker table tr td.active.disabled[disabled],\n.datepicker table tr td.active.disabled:hover[disabled] {\n  background-color: #0044cc;\n}\n.datepicker table tr td.active:active,\n.datepicker table tr td.active:hover:active,\n.datepicker table tr td.active.disabled:active,\n.datepicker table tr td.active.disabled:hover:active,\n.datepicker table tr td.active.active,\n.datepicker table tr td.active:hover.active,\n.datepicker table tr td.active.disabled.active,\n.datepicker table tr td.active.disabled:hover.active {\n  background-color: #003399 \\9;\n}\n.datepicker table tr td span {\n  display: block;\n  width: 23%;\n  height: 54px;\n  line-height: 54px;\n  float: left;\n  margin: 1%;\n  cursor: pointer;\n  -webkit-border-radius: 4px;\n  -moz-border-radius: 4px;\n  border-radius: 4px;\n}\n.datepicker table tr td span:hover {\n  background: #eeeeee;\n}\n.datepicker table tr td span.disabled,\n.datepicker table tr td span.disabled:hover {\n  background: none;\n  color: #999999;\n  cursor: default;\n}\n.datepicker table tr td span.active,\n.datepicker table tr td span.active:hover,\n.datepicker table tr td span.active.disabled,\n.datepicker table tr td span.active.disabled:hover {\n  background-color: #006dcc;\n  background-image: -moz-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -ms-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -webkit-gradient(linear, 0 0, 0 100%, from(#0088cc), to(#0044cc));\n  background-image: -webkit-linear-gradient(top, #0088cc, #0044cc);\n  background-image: -o-linear-gradient(top, #0088cc, #0044cc);\n  background-image: linear-gradient(top, #0088cc, #0044cc);\n  background-repeat: repeat-x;\n  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#0088cc', endColorstr='#0044cc', GradientType=0);\n  border-color: #0044cc #0044cc #002a80;\n  border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);\n  filter: progid:DXImageTransform.Microsoft.gradient(enabled=false);\n  color: #fff;\n  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);\n}\n.datepicker table tr td span.active:hover,\n.datepicker table tr td span.active:hover:hover,\n.datepicker table tr td span.active.disabled:hover,\n.datepicker table tr td span.active.disabled:hover:hover,\n.datepicker table tr td span.active:active,\n.datepicker table tr td span.active:hover:active,\n.datepicker table tr td span.active.disabled:active,\n.datepicker table tr td span.active.disabled:hover:active,\n.datepicker table tr td span.active.active,\n.datepicker table tr td span.active:hover.active,\n.datepicker table tr td span.active.disabled.active,\n.datepicker table tr td span.active.disabled:hover.active,\n.datepicker table tr td span.active.disabled,\n.datepicker table tr td span.active:hover.disabled,\n.datepicker table tr td span.active.disabled.disabled,\n.datepicker table tr td span.active.disabled:hover.disabled,\n.datepicker table tr td span.active[disabled],\n.datepicker table tr td span.active:hover[disabled],\n.datepicker table tr td span.active.disabled[disabled],\n.datepicker table tr td span.active.disabled:hover[disabled] {\n  background-color: #0044cc;\n}\n.datepicker table tr td span.active:active,\n.datepicker table tr td span.active:hover:active,\n.datepicker table tr td span.active.disabled:active,\n.datepicker table tr td span.active.disabled:hover:active,\n.datepicker table tr td span.active.active,\n.datepicker table tr td span.active:hover.active,\n.datepicker table tr td span.active.disabled.active,\n.datepicker table tr td span.active.disabled:hover.active {\n  background-color: #003399 \\9;\n}\n.datepicker table tr td span.old,\n.datepicker table tr td span.new {\n  color: #999999;\n}\n.datepicker th.datepicker-switch {\n  width: 145px;\n}\n.datepicker thead tr:first-child th,\n.datepicker tfoot tr th {\n  cursor: pointer;\n}\n.datepicker thead tr:first-child th:hover,\n.datepicker tfoot tr th:hover {\n  background: #eeeeee;\n}\n.datepicker .cw {\n  font-size: 10px;\n  width: 12px;\n  padding: 0 2px 0 5px;\n  vertical-align: middle;\n}\n.datepicker thead tr:first-child th.cw {\n  cursor: default;\n  background-color: transparent;\n}\n.input-append.date .add-on i,\n.input-prepend.date .add-on i {\n  display: block;\n  cursor: pointer;\n  width: 16px;\n  height: 16px;\n}\n.input-daterange input {\n  text-align: center;\n}\n.input-daterange input:first-child {\n  -webkit-border-radius: 3px 0 0 3px;\n  -moz-border-radius: 3px 0 0 3px;\n  border-radius: 3px 0 0 3px;\n}\n.input-daterange input:last-child {\n  -webkit-border-radius: 0 3px 3px 0;\n  -moz-border-radius: 0 3px 3px 0;\n  border-radius: 0 3px 3px 0;\n}\n.input-daterange .add-on {\n  display: inline-block;\n  width: auto;\n  min-width: 16px;\n  height: 18px;\n  padding: 4px 5px;\n  font-weight: normal;\n  line-height: 18px;\n  text-align: center;\n  text-shadow: 0 1px 0 #ffffff;\n  vertical-align: middle;\n  background-color: #eeeeee;\n  border: 1px solid #ccc;\n  margin-left: -5px;\n  margin-right: -5px;\n}\n"
  },
  {
    "path": "resources/assets/flatpickr/dist/flatpickr.js",
    "content": "/* flatpickr v4.6.13,, @license MIT */\n!function(e,n){\"object\"==typeof exports&&\"undefined\"!=typeof module?module.exports=n():\"function\"==typeof define&&define.amd?define(n):(e=\"undefined\"!=typeof globalThis?globalThis:e||self).flatpickr=n()}(this,(function(){\"use strict\";var e=function(){return(e=Object.assign||function(e){for(var n,t=1,a=arguments.length;t<a;t++)for(var i in n=arguments[t])Object.prototype.hasOwnProperty.call(n,i)&&(e[i]=n[i]);return e}).apply(this,arguments)};function n(){for(var e=0,n=0,t=arguments.length;n<t;n++)e+=arguments[n].length;var a=Array(e),i=0;for(n=0;n<t;n++)for(var o=arguments[n],r=0,l=o.length;r<l;r++,i++)a[i]=o[r];return a}var t=[\"onChange\",\"onClose\",\"onDayCreate\",\"onDestroy\",\"onKeyDown\",\"onMonthChange\",\"onOpen\",\"onParseConfig\",\"onReady\",\"onValueUpdate\",\"onYearChange\",\"onPreCalendarPosition\"],a={_disable:[],allowInput:!1,allowInvalidPreload:!1,altFormat:\"F j, Y\",altInput:!1,altInputClass:\"form-control input\",animate:\"object\"==typeof window&&-1===window.navigator.userAgent.indexOf(\"MSIE\"),ariaDateFormat:\"F j, Y\",autoFillDefaultTime:!0,clickOpens:!0,closeOnSelect:!0,conjunction:\", \",dateFormat:\"Y-m-d\",defaultHour:12,defaultMinute:0,defaultSeconds:0,disable:[],disableMobile:!1,enableSeconds:!1,enableTime:!1,errorHandler:function(e){return\"undefined\"!=typeof console&&console.warn(e)},getWeek:function(e){var n=new Date(e.getTime());n.setHours(0,0,0,0),n.setDate(n.getDate()+3-(n.getDay()+6)%7);var t=new Date(n.getFullYear(),0,4);return 1+Math.round(((n.getTime()-t.getTime())/864e5-3+(t.getDay()+6)%7)/7)},hourIncrement:1,ignoredFocusElements:[],inline:!1,locale:\"default\",minuteIncrement:5,mode:\"single\",monthSelectorType:\"dropdown\",nextArrow:\"<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 17 17'><g></g><path d='M13.207 8.472l-7.854 7.854-0.707-0.707 7.146-7.146-7.146-7.148 0.707-0.707 7.854 7.854z' /></svg>\",noCalendar:!1,now:new Date,onChange:[],onClose:[],onDayCreate:[],onDestroy:[],onKeyDown:[],onMonthChange:[],onOpen:[],onParseConfig:[],onReady:[],onValueUpdate:[],onYearChange:[],onPreCalendarPosition:[],plugins:[],position:\"auto\",positionElement:void 0,prevArrow:\"<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 17 17'><g></g><path d='M5.207 8.471l7.146 7.147-0.707 0.707-7.853-7.854 7.854-7.853 0.707 0.707-7.147 7.146z' /></svg>\",shorthandCurrentMonth:!1,showMonths:1,static:!1,time_24hr:!1,weekNumbers:!1,wrap:!1},i={weekdays:{shorthand:[\"Sun\",\"Mon\",\"Tue\",\"Wed\",\"Thu\",\"Fri\",\"Sat\"],longhand:[\"Sunday\",\"Monday\",\"Tuesday\",\"Wednesday\",\"Thursday\",\"Friday\",\"Saturday\"]},months:{shorthand:[\"Jan\",\"Feb\",\"Mar\",\"Apr\",\"May\",\"Jun\",\"Jul\",\"Aug\",\"Sep\",\"Oct\",\"Nov\",\"Dec\"],longhand:[\"January\",\"February\",\"March\",\"April\",\"May\",\"June\",\"July\",\"August\",\"September\",\"October\",\"November\",\"December\"]},daysInMonth:[31,28,31,30,31,30,31,31,30,31,30,31],firstDayOfWeek:0,ordinal:function(e){var n=e%100;if(n>3&&n<21)return\"th\";switch(n%10){case 1:return\"st\";case 2:return\"nd\";case 3:return\"rd\";default:return\"th\"}},rangeSeparator:\" to \",weekAbbreviation:\"Wk\",scrollTitle:\"Scroll to increment\",toggleTitle:\"Click to toggle\",amPM:[\"AM\",\"PM\"],yearAriaLabel:\"Year\",monthAriaLabel:\"Month\",hourAriaLabel:\"Hour\",minuteAriaLabel:\"Minute\",time_24hr:!1},o=function(e,n){return void 0===n&&(n=2),(\"000\"+e).slice(-1*n)},r=function(e){return!0===e?1:0};function l(e,n){var t;return function(){var a=this,i=arguments;clearTimeout(t),t=setTimeout((function(){return e.apply(a,i)}),n)}}var c=function(e){return e instanceof Array?e:[e]};function s(e,n,t){if(!0===t)return e.classList.add(n);e.classList.remove(n)}function d(e,n,t){var a=window.document.createElement(e);return n=n||\"\",t=t||\"\",a.className=n,void 0!==t&&(a.textContent=t),a}function u(e){for(;e.firstChild;)e.removeChild(e.firstChild)}function f(e,n){return n(e)?e:e.parentNode?f(e.parentNode,n):void 0}function m(e,n){var t=d(\"div\",\"numInputWrapper\"),a=d(\"input\",\"numInput \"+e),i=d(\"span\",\"arrowUp\"),o=d(\"span\",\"arrowDown\");if(-1===navigator.userAgent.indexOf(\"MSIE 9.0\")?a.type=\"number\":(a.type=\"text\",a.pattern=\"\\\\d*\"),void 0!==n)for(var r in n)a.setAttribute(r,n[r]);return t.appendChild(a),t.appendChild(i),t.appendChild(o),t}function g(e){try{return\"function\"==typeof e.composedPath?e.composedPath()[0]:e.target}catch(n){return e.target}}var p=function(){},h=function(e,n,t){return t.months[n?\"shorthand\":\"longhand\"][e]},v={D:p,F:function(e,n,t){e.setMonth(t.months.longhand.indexOf(n))},G:function(e,n){e.setHours((e.getHours()>=12?12:0)+parseFloat(n))},H:function(e,n){e.setHours(parseFloat(n))},J:function(e,n){e.setDate(parseFloat(n))},K:function(e,n,t){e.setHours(e.getHours()%12+12*r(new RegExp(t.amPM[1],\"i\").test(n)))},M:function(e,n,t){e.setMonth(t.months.shorthand.indexOf(n))},S:function(e,n){e.setSeconds(parseFloat(n))},U:function(e,n){return new Date(1e3*parseFloat(n))},W:function(e,n,t){var a=parseInt(n),i=new Date(e.getFullYear(),0,2+7*(a-1),0,0,0,0);return i.setDate(i.getDate()-i.getDay()+t.firstDayOfWeek),i},Y:function(e,n){e.setFullYear(parseFloat(n))},Z:function(e,n){return new Date(n)},d:function(e,n){e.setDate(parseFloat(n))},h:function(e,n){e.setHours((e.getHours()>=12?12:0)+parseFloat(n))},i:function(e,n){e.setMinutes(parseFloat(n))},j:function(e,n){e.setDate(parseFloat(n))},l:p,m:function(e,n){e.setMonth(parseFloat(n)-1)},n:function(e,n){e.setMonth(parseFloat(n)-1)},s:function(e,n){e.setSeconds(parseFloat(n))},u:function(e,n){return new Date(parseFloat(n))},w:p,y:function(e,n){e.setFullYear(2e3+parseFloat(n))}},D={D:\"\",F:\"\",G:\"(\\\\d\\\\d|\\\\d)\",H:\"(\\\\d\\\\d|\\\\d)\",J:\"(\\\\d\\\\d|\\\\d)\\\\w+\",K:\"\",M:\"\",S:\"(\\\\d\\\\d|\\\\d)\",U:\"(.+)\",W:\"(\\\\d\\\\d|\\\\d)\",Y:\"(\\\\d{4})\",Z:\"(.+)\",d:\"(\\\\d\\\\d|\\\\d)\",h:\"(\\\\d\\\\d|\\\\d)\",i:\"(\\\\d\\\\d|\\\\d)\",j:\"(\\\\d\\\\d|\\\\d)\",l:\"\",m:\"(\\\\d\\\\d|\\\\d)\",n:\"(\\\\d\\\\d|\\\\d)\",s:\"(\\\\d\\\\d|\\\\d)\",u:\"(.+)\",w:\"(\\\\d\\\\d|\\\\d)\",y:\"(\\\\d{2})\"},w={Z:function(e){return e.toISOString()},D:function(e,n,t){return n.weekdays.shorthand[w.w(e,n,t)]},F:function(e,n,t){return h(w.n(e,n,t)-1,!1,n)},G:function(e,n,t){return o(w.h(e,n,t))},H:function(e){return o(e.getHours())},J:function(e,n){return void 0!==n.ordinal?e.getDate()+n.ordinal(e.getDate()):e.getDate()},K:function(e,n){return n.amPM[r(e.getHours()>11)]},M:function(e,n){return h(e.getMonth(),!0,n)},S:function(e){return o(e.getSeconds())},U:function(e){return e.getTime()/1e3},W:function(e,n,t){return t.getWeek(e)},Y:function(e){return o(e.getFullYear(),4)},d:function(e){return o(e.getDate())},h:function(e){return e.getHours()%12?e.getHours()%12:12},i:function(e){return o(e.getMinutes())},j:function(e){return e.getDate()},l:function(e,n){return n.weekdays.longhand[e.getDay()]},m:function(e){return o(e.getMonth()+1)},n:function(e){return e.getMonth()+1},s:function(e){return e.getSeconds()},u:function(e){return e.getTime()},w:function(e){return e.getDay()},y:function(e){return String(e.getFullYear()).substring(2)}},b=function(e){var n=e.config,t=void 0===n?a:n,o=e.l10n,r=void 0===o?i:o,l=e.isMobile,c=void 0!==l&&l;return function(e,n,a){var i=a||r;return void 0===t.formatDate||c?n.split(\"\").map((function(n,a,o){return w[n]&&\"\\\\\"!==o[a-1]?w[n](e,i,t):\"\\\\\"!==n?n:\"\"})).join(\"\"):t.formatDate(e,n,i)}},C=function(e){var n=e.config,t=void 0===n?a:n,o=e.l10n,r=void 0===o?i:o;return function(e,n,i,o){if(0===e||e){var l,c=o||r,s=e;if(e instanceof Date)l=new Date(e.getTime());else if(\"string\"!=typeof e&&void 0!==e.toFixed)l=new Date(e);else if(\"string\"==typeof e){var d=n||(t||a).dateFormat,u=String(e).trim();if(\"today\"===u)l=new Date,i=!0;else if(t&&t.parseDate)l=t.parseDate(e,d);else if(/Z$/.test(u)||/GMT$/.test(u))l=new Date(e);else{for(var f=void 0,m=[],g=0,p=0,h=\"\";g<d.length;g++){var w=d[g],b=\"\\\\\"===w,C=\"\\\\\"===d[g-1]||b;if(D[w]&&!C){h+=D[w];var M=new RegExp(h).exec(e);M&&(f=!0)&&m[\"Y\"!==w?\"push\":\"unshift\"]({fn:v[w],val:M[++p]})}else b||(h+=\".\")}l=t&&t.noCalendar?new Date((new Date).setHours(0,0,0,0)):new Date((new Date).getFullYear(),0,1,0,0,0,0),m.forEach((function(e){var n=e.fn,t=e.val;return l=n(l,t,c)||l})),l=f?l:void 0}}if(l instanceof Date&&!isNaN(l.getTime()))return!0===i&&l.setHours(0,0,0,0),l;t.errorHandler(new Error(\"Invalid date provided: \"+s))}}};function M(e,n,t){return void 0===t&&(t=!0),!1!==t?new Date(e.getTime()).setHours(0,0,0,0)-new Date(n.getTime()).setHours(0,0,0,0):e.getTime()-n.getTime()}var y=function(e,n,t){return 3600*e+60*n+t},x=864e5;function E(e){var n=e.defaultHour,t=e.defaultMinute,a=e.defaultSeconds;if(void 0!==e.minDate){var i=e.minDate.getHours(),o=e.minDate.getMinutes(),r=e.minDate.getSeconds();n<i&&(n=i),n===i&&t<o&&(t=o),n===i&&t===o&&a<r&&(a=e.minDate.getSeconds())}if(void 0!==e.maxDate){var l=e.maxDate.getHours(),c=e.maxDate.getMinutes();(n=Math.min(n,l))===l&&(t=Math.min(c,t)),n===l&&t===c&&(a=e.maxDate.getSeconds())}return{hours:n,minutes:t,seconds:a}}\"function\"!=typeof Object.assign&&(Object.assign=function(e){for(var n=[],t=1;t<arguments.length;t++)n[t-1]=arguments[t];if(!e)throw TypeError(\"Cannot convert undefined or null to object\");for(var a=function(n){n&&Object.keys(n).forEach((function(t){return e[t]=n[t]}))},i=0,o=n;i<o.length;i++){var r=o[i];a(r)}return e});function k(p,v){var w={config:e(e({},a),I.defaultConfig),l10n:i};function k(){var e;return(null===(e=w.calendarContainer)||void 0===e?void 0:e.getRootNode()).activeElement||document.activeElement}function T(e){return e.bind(w)}function S(){var e=w.config;!1===e.weekNumbers&&1===e.showMonths||!0!==e.noCalendar&&window.requestAnimationFrame((function(){if(void 0!==w.calendarContainer&&(w.calendarContainer.style.visibility=\"hidden\",w.calendarContainer.style.display=\"block\"),void 0!==w.daysContainer){var n=(w.days.offsetWidth+1)*e.showMonths;w.daysContainer.style.width=n+\"px\",w.calendarContainer.style.width=n+(void 0!==w.weekWrapper?w.weekWrapper.offsetWidth:0)+\"px\",w.calendarContainer.style.removeProperty(\"visibility\"),w.calendarContainer.style.removeProperty(\"display\")}}))}function _(e){if(0===w.selectedDates.length){var n=void 0===w.config.minDate||M(new Date,w.config.minDate)>=0?new Date:new Date(w.config.minDate.getTime()),t=E(w.config);n.setHours(t.hours,t.minutes,t.seconds,n.getMilliseconds()),w.selectedDates=[n],w.latestSelectedDateObj=n}void 0!==e&&\"blur\"!==e.type&&function(e){e.preventDefault();var n=\"keydown\"===e.type,t=g(e),a=t;void 0!==w.amPM&&t===w.amPM&&(w.amPM.textContent=w.l10n.amPM[r(w.amPM.textContent===w.l10n.amPM[0])]);var i=parseFloat(a.getAttribute(\"min\")),l=parseFloat(a.getAttribute(\"max\")),c=parseFloat(a.getAttribute(\"step\")),s=parseInt(a.value,10),d=e.delta||(n?38===e.which?1:-1:0),u=s+c*d;if(void 0!==a.value&&2===a.value.length){var f=a===w.hourElement,m=a===w.minuteElement;u<i?(u=l+u+r(!f)+(r(f)&&r(!w.amPM)),m&&L(void 0,-1,w.hourElement)):u>l&&(u=a===w.hourElement?u-l-r(!w.amPM):i,m&&L(void 0,1,w.hourElement)),w.amPM&&f&&(1===c?u+s===23:Math.abs(u-s)>c)&&(w.amPM.textContent=w.l10n.amPM[r(w.amPM.textContent===w.l10n.amPM[0])]),a.value=o(u)}}(e);var a=w._input.value;O(),ye(),w._input.value!==a&&w._debouncedChange()}function O(){if(void 0!==w.hourElement&&void 0!==w.minuteElement){var e,n,t=(parseInt(w.hourElement.value.slice(-2),10)||0)%24,a=(parseInt(w.minuteElement.value,10)||0)%60,i=void 0!==w.secondElement?(parseInt(w.secondElement.value,10)||0)%60:0;void 0!==w.amPM&&(e=t,n=w.amPM.textContent,t=e%12+12*r(n===w.l10n.amPM[1]));var o=void 0!==w.config.minTime||w.config.minDate&&w.minDateHasTime&&w.latestSelectedDateObj&&0===M(w.latestSelectedDateObj,w.config.minDate,!0),l=void 0!==w.config.maxTime||w.config.maxDate&&w.maxDateHasTime&&w.latestSelectedDateObj&&0===M(w.latestSelectedDateObj,w.config.maxDate,!0);if(void 0!==w.config.maxTime&&void 0!==w.config.minTime&&w.config.minTime>w.config.maxTime){var c=y(w.config.minTime.getHours(),w.config.minTime.getMinutes(),w.config.minTime.getSeconds()),s=y(w.config.maxTime.getHours(),w.config.maxTime.getMinutes(),w.config.maxTime.getSeconds()),d=y(t,a,i);if(d>s&&d<c){var u=function(e){var n=Math.floor(e/3600),t=(e-3600*n)/60;return[n,t,e-3600*n-60*t]}(c);t=u[0],a=u[1],i=u[2]}}else{if(l){var f=void 0!==w.config.maxTime?w.config.maxTime:w.config.maxDate;(t=Math.min(t,f.getHours()))===f.getHours()&&(a=Math.min(a,f.getMinutes())),a===f.getMinutes()&&(i=Math.min(i,f.getSeconds()))}if(o){var m=void 0!==w.config.minTime?w.config.minTime:w.config.minDate;(t=Math.max(t,m.getHours()))===m.getHours()&&a<m.getMinutes()&&(a=m.getMinutes()),a===m.getMinutes()&&(i=Math.max(i,m.getSeconds()))}}A(t,a,i)}}function F(e){var n=e||w.latestSelectedDateObj;n&&n instanceof Date&&A(n.getHours(),n.getMinutes(),n.getSeconds())}function A(e,n,t){void 0!==w.latestSelectedDateObj&&w.latestSelectedDateObj.setHours(e%24,n,t||0,0),w.hourElement&&w.minuteElement&&!w.isMobile&&(w.hourElement.value=o(w.config.time_24hr?e:(12+e)%12+12*r(e%12==0)),w.minuteElement.value=o(n),void 0!==w.amPM&&(w.amPM.textContent=w.l10n.amPM[r(e>=12)]),void 0!==w.secondElement&&(w.secondElement.value=o(t)))}function N(e){var n=g(e),t=parseInt(n.value)+(e.delta||0);(t/1e3>1||\"Enter\"===e.key&&!/[^\\d]/.test(t.toString()))&&ee(t)}function P(e,n,t,a){return n instanceof Array?n.forEach((function(n){return P(e,n,t,a)})):e instanceof Array?e.forEach((function(e){return P(e,n,t,a)})):(e.addEventListener(n,t,a),void w._handlers.push({remove:function(){return e.removeEventListener(n,t,a)}}))}function Y(){De(\"onChange\")}function j(e,n){var t=void 0!==e?w.parseDate(e):w.latestSelectedDateObj||(w.config.minDate&&w.config.minDate>w.now?w.config.minDate:w.config.maxDate&&w.config.maxDate<w.now?w.config.maxDate:w.now),a=w.currentYear,i=w.currentMonth;try{void 0!==t&&(w.currentYear=t.getFullYear(),w.currentMonth=t.getMonth())}catch(e){e.message=\"Invalid date supplied: \"+t,w.config.errorHandler(e)}n&&w.currentYear!==a&&(De(\"onYearChange\"),q()),!n||w.currentYear===a&&w.currentMonth===i||De(\"onMonthChange\"),w.redraw()}function H(e){var n=g(e);~n.className.indexOf(\"arrow\")&&L(e,n.classList.contains(\"arrowUp\")?1:-1)}function L(e,n,t){var a=e&&g(e),i=t||a&&a.parentNode&&a.parentNode.firstChild,o=we(\"increment\");o.delta=n,i&&i.dispatchEvent(o)}function R(e,n,t,a){var i=ne(n,!0),o=d(\"span\",e,n.getDate().toString());return o.dateObj=n,o.$i=a,o.setAttribute(\"aria-label\",w.formatDate(n,w.config.ariaDateFormat)),-1===e.indexOf(\"hidden\")&&0===M(n,w.now)&&(w.todayDateElem=o,o.classList.add(\"today\"),o.setAttribute(\"aria-current\",\"date\")),i?(o.tabIndex=-1,be(n)&&(o.classList.add(\"selected\"),w.selectedDateElem=o,\"range\"===w.config.mode&&(s(o,\"startRange\",w.selectedDates[0]&&0===M(n,w.selectedDates[0],!0)),s(o,\"endRange\",w.selectedDates[1]&&0===M(n,w.selectedDates[1],!0)),\"nextMonthDay\"===e&&o.classList.add(\"inRange\")))):o.classList.add(\"flatpickr-disabled\"),\"range\"===w.config.mode&&function(e){return!(\"range\"!==w.config.mode||w.selectedDates.length<2)&&(M(e,w.selectedDates[0])>=0&&M(e,w.selectedDates[1])<=0)}(n)&&!be(n)&&o.classList.add(\"inRange\"),w.weekNumbers&&1===w.config.showMonths&&\"prevMonthDay\"!==e&&a%7==6&&w.weekNumbers.insertAdjacentHTML(\"beforeend\",\"<span class='flatpickr-day'>\"+w.config.getWeek(n)+\"</span>\"),De(\"onDayCreate\",o),o}function W(e){e.focus(),\"range\"===w.config.mode&&oe(e)}function B(e){for(var n=e>0?0:w.config.showMonths-1,t=e>0?w.config.showMonths:-1,a=n;a!=t;a+=e)for(var i=w.daysContainer.children[a],o=e>0?0:i.children.length-1,r=e>0?i.children.length:-1,l=o;l!=r;l+=e){var c=i.children[l];if(-1===c.className.indexOf(\"hidden\")&&ne(c.dateObj))return c}}function J(e,n){var t=k(),a=te(t||document.body),i=void 0!==e?e:a?t:void 0!==w.selectedDateElem&&te(w.selectedDateElem)?w.selectedDateElem:void 0!==w.todayDateElem&&te(w.todayDateElem)?w.todayDateElem:B(n>0?1:-1);void 0===i?w._input.focus():a?function(e,n){for(var t=-1===e.className.indexOf(\"Month\")?e.dateObj.getMonth():w.currentMonth,a=n>0?w.config.showMonths:-1,i=n>0?1:-1,o=t-w.currentMonth;o!=a;o+=i)for(var r=w.daysContainer.children[o],l=t-w.currentMonth===o?e.$i+n:n<0?r.children.length-1:0,c=r.children.length,s=l;s>=0&&s<c&&s!=(n>0?c:-1);s+=i){var d=r.children[s];if(-1===d.className.indexOf(\"hidden\")&&ne(d.dateObj)&&Math.abs(e.$i-s)>=Math.abs(n))return W(d)}w.changeMonth(i),J(B(i),0)}(i,n):W(i)}function K(e,n){for(var t=(new Date(e,n,1).getDay()-w.l10n.firstDayOfWeek+7)%7,a=w.utils.getDaysInMonth((n-1+12)%12,e),i=w.utils.getDaysInMonth(n,e),o=window.document.createDocumentFragment(),r=w.config.showMonths>1,l=r?\"prevMonthDay hidden\":\"prevMonthDay\",c=r?\"nextMonthDay hidden\":\"nextMonthDay\",s=a+1-t,u=0;s<=a;s++,u++)o.appendChild(R(\"flatpickr-day \"+l,new Date(e,n-1,s),0,u));for(s=1;s<=i;s++,u++)o.appendChild(R(\"flatpickr-day\",new Date(e,n,s),0,u));for(var f=i+1;f<=42-t&&(1===w.config.showMonths||u%7!=0);f++,u++)o.appendChild(R(\"flatpickr-day \"+c,new Date(e,n+1,f%i),0,u));var m=d(\"div\",\"dayContainer\");return m.appendChild(o),m}function U(){if(void 0!==w.daysContainer){u(w.daysContainer),w.weekNumbers&&u(w.weekNumbers);for(var e=document.createDocumentFragment(),n=0;n<w.config.showMonths;n++){var t=new Date(w.currentYear,w.currentMonth,1);t.setMonth(w.currentMonth+n),e.appendChild(K(t.getFullYear(),t.getMonth()))}w.daysContainer.appendChild(e),w.days=w.daysContainer.firstChild,\"range\"===w.config.mode&&1===w.selectedDates.length&&oe()}}function q(){if(!(w.config.showMonths>1||\"dropdown\"!==w.config.monthSelectorType)){var e=function(e){return!(void 0!==w.config.minDate&&w.currentYear===w.config.minDate.getFullYear()&&e<w.config.minDate.getMonth())&&!(void 0!==w.config.maxDate&&w.currentYear===w.config.maxDate.getFullYear()&&e>w.config.maxDate.getMonth())};w.monthsDropdownContainer.tabIndex=-1,w.monthsDropdownContainer.innerHTML=\"\";for(var n=0;n<12;n++)if(e(n)){var t=d(\"option\",\"flatpickr-monthDropdown-month\");t.value=new Date(w.currentYear,n).getMonth().toString(),t.textContent=h(n,w.config.shorthandCurrentMonth,w.l10n),t.tabIndex=-1,w.currentMonth===n&&(t.selected=!0),w.monthsDropdownContainer.appendChild(t)}}}function $(){var e,n=d(\"div\",\"flatpickr-month\"),t=window.document.createDocumentFragment();w.config.showMonths>1||\"static\"===w.config.monthSelectorType?e=d(\"span\",\"cur-month\"):(w.monthsDropdownContainer=d(\"select\",\"flatpickr-monthDropdown-months\"),w.monthsDropdownContainer.setAttribute(\"aria-label\",w.l10n.monthAriaLabel),P(w.monthsDropdownContainer,\"change\",(function(e){var n=g(e),t=parseInt(n.value,10);w.changeMonth(t-w.currentMonth),De(\"onMonthChange\")})),q(),e=w.monthsDropdownContainer);var a=m(\"cur-year\",{tabindex:\"-1\"}),i=a.getElementsByTagName(\"input\")[0];i.setAttribute(\"aria-label\",w.l10n.yearAriaLabel),w.config.minDate&&i.setAttribute(\"min\",w.config.minDate.getFullYear().toString()),w.config.maxDate&&(i.setAttribute(\"max\",w.config.maxDate.getFullYear().toString()),i.disabled=!!w.config.minDate&&w.config.minDate.getFullYear()===w.config.maxDate.getFullYear());var o=d(\"div\",\"flatpickr-current-month\");return o.appendChild(e),o.appendChild(a),t.appendChild(o),n.appendChild(t),{container:n,yearElement:i,monthElement:e}}function V(){u(w.monthNav),w.monthNav.appendChild(w.prevMonthNav),w.config.showMonths&&(w.yearElements=[],w.monthElements=[]);for(var e=w.config.showMonths;e--;){var n=$();w.yearElements.push(n.yearElement),w.monthElements.push(n.monthElement),w.monthNav.appendChild(n.container)}w.monthNav.appendChild(w.nextMonthNav)}function z(){w.weekdayContainer?u(w.weekdayContainer):w.weekdayContainer=d(\"div\",\"flatpickr-weekdays\");for(var e=w.config.showMonths;e--;){var n=d(\"div\",\"flatpickr-weekdaycontainer\");w.weekdayContainer.appendChild(n)}return G(),w.weekdayContainer}function G(){if(w.weekdayContainer){var e=w.l10n.firstDayOfWeek,t=n(w.l10n.weekdays.shorthand);e>0&&e<t.length&&(t=n(t.splice(e,t.length),t.splice(0,e)));for(var a=w.config.showMonths;a--;)w.weekdayContainer.children[a].innerHTML=\"\\n      <span class='flatpickr-weekday'>\\n        \"+t.join(\"</span><span class='flatpickr-weekday'>\")+\"\\n      </span>\\n      \"}}function Z(e,n){void 0===n&&(n=!0);var t=n?e:e-w.currentMonth;t<0&&!0===w._hidePrevMonthArrow||t>0&&!0===w._hideNextMonthArrow||(w.currentMonth+=t,(w.currentMonth<0||w.currentMonth>11)&&(w.currentYear+=w.currentMonth>11?1:-1,w.currentMonth=(w.currentMonth+12)%12,De(\"onYearChange\"),q()),U(),De(\"onMonthChange\"),Ce())}function Q(e){return w.calendarContainer.contains(e)}function X(e){if(w.isOpen&&!w.config.inline){var n=g(e),t=Q(n),a=!(n===w.input||n===w.altInput||w.element.contains(n)||e.path&&e.path.indexOf&&(~e.path.indexOf(w.input)||~e.path.indexOf(w.altInput)))&&!t&&!Q(e.relatedTarget),i=!w.config.ignoredFocusElements.some((function(e){return e.contains(n)}));a&&i&&(w.config.allowInput&&w.setDate(w._input.value,!1,w.config.altInput?w.config.altFormat:w.config.dateFormat),void 0!==w.timeContainer&&void 0!==w.minuteElement&&void 0!==w.hourElement&&\"\"!==w.input.value&&void 0!==w.input.value&&_(),w.close(),w.config&&\"range\"===w.config.mode&&1===w.selectedDates.length&&w.clear(!1))}}function ee(e){if(!(!e||w.config.minDate&&e<w.config.minDate.getFullYear()||w.config.maxDate&&e>w.config.maxDate.getFullYear())){var n=e,t=w.currentYear!==n;w.currentYear=n||w.currentYear,w.config.maxDate&&w.currentYear===w.config.maxDate.getFullYear()?w.currentMonth=Math.min(w.config.maxDate.getMonth(),w.currentMonth):w.config.minDate&&w.currentYear===w.config.minDate.getFullYear()&&(w.currentMonth=Math.max(w.config.minDate.getMonth(),w.currentMonth)),t&&(w.redraw(),De(\"onYearChange\"),q())}}function ne(e,n){var t;void 0===n&&(n=!0);var a=w.parseDate(e,void 0,n);if(w.config.minDate&&a&&M(a,w.config.minDate,void 0!==n?n:!w.minDateHasTime)<0||w.config.maxDate&&a&&M(a,w.config.maxDate,void 0!==n?n:!w.maxDateHasTime)>0)return!1;if(!w.config.enable&&0===w.config.disable.length)return!0;if(void 0===a)return!1;for(var i=!!w.config.enable,o=null!==(t=w.config.enable)&&void 0!==t?t:w.config.disable,r=0,l=void 0;r<o.length;r++){if(\"function\"==typeof(l=o[r])&&l(a))return i;if(l instanceof Date&&void 0!==a&&l.getTime()===a.getTime())return i;if(\"string\"==typeof l){var c=w.parseDate(l,void 0,!0);return c&&c.getTime()===a.getTime()?i:!i}if(\"object\"==typeof l&&void 0!==a&&l.from&&l.to&&a.getTime()>=l.from.getTime()&&a.getTime()<=l.to.getTime())return i}return!i}function te(e){return void 0!==w.daysContainer&&(-1===e.className.indexOf(\"hidden\")&&-1===e.className.indexOf(\"flatpickr-disabled\")&&w.daysContainer.contains(e))}function ae(e){var n=e.target===w._input,t=w._input.value.trimEnd()!==Me();!n||!t||e.relatedTarget&&Q(e.relatedTarget)||w.setDate(w._input.value,!0,e.target===w.altInput?w.config.altFormat:w.config.dateFormat)}function ie(e){var n=g(e),t=w.config.wrap?p.contains(n):n===w._input,a=w.config.allowInput,i=w.isOpen&&(!a||!t),o=w.config.inline&&t&&!a;if(13===e.keyCode&&t){if(a)return w.setDate(w._input.value,!0,n===w.altInput?w.config.altFormat:w.config.dateFormat),w.close(),n.blur();w.open()}else if(Q(n)||i||o){var r=!!w.timeContainer&&w.timeContainer.contains(n);switch(e.keyCode){case 13:r?(e.preventDefault(),_(),fe()):me(e);break;case 27:e.preventDefault(),fe();break;case 8:case 46:t&&!w.config.allowInput&&(e.preventDefault(),w.clear());break;case 37:case 39:if(r||t)w.hourElement&&w.hourElement.focus();else{e.preventDefault();var l=k();if(void 0!==w.daysContainer&&(!1===a||l&&te(l))){var c=39===e.keyCode?1:-1;e.ctrlKey?(e.stopPropagation(),Z(c),J(B(1),0)):J(void 0,c)}}break;case 38:case 40:e.preventDefault();var s=40===e.keyCode?1:-1;w.daysContainer&&void 0!==n.$i||n===w.input||n===w.altInput?e.ctrlKey?(e.stopPropagation(),ee(w.currentYear-s),J(B(1),0)):r||J(void 0,7*s):n===w.currentYearElement?ee(w.currentYear-s):w.config.enableTime&&(!r&&w.hourElement&&w.hourElement.focus(),_(e),w._debouncedChange());break;case 9:if(r){var d=[w.hourElement,w.minuteElement,w.secondElement,w.amPM].concat(w.pluginElements).filter((function(e){return e})),u=d.indexOf(n);if(-1!==u){var f=d[u+(e.shiftKey?-1:1)];e.preventDefault(),(f||w._input).focus()}}else!w.config.noCalendar&&w.daysContainer&&w.daysContainer.contains(n)&&e.shiftKey&&(e.preventDefault(),w._input.focus())}}if(void 0!==w.amPM&&n===w.amPM)switch(e.key){case w.l10n.amPM[0].charAt(0):case w.l10n.amPM[0].charAt(0).toLowerCase():w.amPM.textContent=w.l10n.amPM[0],O(),ye();break;case w.l10n.amPM[1].charAt(0):case w.l10n.amPM[1].charAt(0).toLowerCase():w.amPM.textContent=w.l10n.amPM[1],O(),ye()}(t||Q(n))&&De(\"onKeyDown\",e)}function oe(e,n){if(void 0===n&&(n=\"flatpickr-day\"),1===w.selectedDates.length&&(!e||e.classList.contains(n)&&!e.classList.contains(\"flatpickr-disabled\"))){for(var t=e?e.dateObj.getTime():w.days.firstElementChild.dateObj.getTime(),a=w.parseDate(w.selectedDates[0],void 0,!0).getTime(),i=Math.min(t,w.selectedDates[0].getTime()),o=Math.max(t,w.selectedDates[0].getTime()),r=!1,l=0,c=0,s=i;s<o;s+=x)ne(new Date(s),!0)||(r=r||s>i&&s<o,s<a&&(!l||s>l)?l=s:s>a&&(!c||s<c)&&(c=s));Array.from(w.rContainer.querySelectorAll(\"*:nth-child(-n+\"+w.config.showMonths+\") > .\"+n)).forEach((function(n){var i,o,s,d=n.dateObj.getTime(),u=l>0&&d<l||c>0&&d>c;if(u)return n.classList.add(\"notAllowed\"),void[\"inRange\",\"startRange\",\"endRange\"].forEach((function(e){n.classList.remove(e)}));r&&!u||([\"startRange\",\"inRange\",\"endRange\",\"notAllowed\"].forEach((function(e){n.classList.remove(e)})),void 0!==e&&(e.classList.add(t<=w.selectedDates[0].getTime()?\"startRange\":\"endRange\"),a<t&&d===a?n.classList.add(\"startRange\"):a>t&&d===a&&n.classList.add(\"endRange\"),d>=l&&(0===c||d<=c)&&(o=a,s=t,(i=d)>Math.min(o,s)&&i<Math.max(o,s))&&n.classList.add(\"inRange\")))}))}}function re(){!w.isOpen||w.config.static||w.config.inline||de()}function le(e){return function(n){var t=w.config[\"_\"+e+\"Date\"]=w.parseDate(n,w.config.dateFormat),a=w.config[\"_\"+(\"min\"===e?\"max\":\"min\")+\"Date\"];void 0!==t&&(w[\"min\"===e?\"minDateHasTime\":\"maxDateHasTime\"]=t.getHours()>0||t.getMinutes()>0||t.getSeconds()>0),w.selectedDates&&(w.selectedDates=w.selectedDates.filter((function(e){return ne(e)})),w.selectedDates.length||\"min\"!==e||F(t),ye()),w.daysContainer&&(ue(),void 0!==t?w.currentYearElement[e]=t.getFullYear().toString():w.currentYearElement.removeAttribute(e),w.currentYearElement.disabled=!!a&&void 0!==t&&a.getFullYear()===t.getFullYear())}}function ce(){return w.config.wrap?p.querySelector(\"[data-input]\"):p}function se(){\"object\"!=typeof w.config.locale&&void 0===I.l10ns[w.config.locale]&&w.config.errorHandler(new Error(\"flatpickr: invalid locale \"+w.config.locale)),w.l10n=e(e({},I.l10ns.default),\"object\"==typeof w.config.locale?w.config.locale:\"default\"!==w.config.locale?I.l10ns[w.config.locale]:void 0),D.D=\"(\"+w.l10n.weekdays.shorthand.join(\"|\")+\")\",D.l=\"(\"+w.l10n.weekdays.longhand.join(\"|\")+\")\",D.M=\"(\"+w.l10n.months.shorthand.join(\"|\")+\")\",D.F=\"(\"+w.l10n.months.longhand.join(\"|\")+\")\",D.K=\"(\"+w.l10n.amPM[0]+\"|\"+w.l10n.amPM[1]+\"|\"+w.l10n.amPM[0].toLowerCase()+\"|\"+w.l10n.amPM[1].toLowerCase()+\")\",void 0===e(e({},v),JSON.parse(JSON.stringify(p.dataset||{}))).time_24hr&&void 0===I.defaultConfig.time_24hr&&(w.config.time_24hr=w.l10n.time_24hr),w.formatDate=b(w),w.parseDate=C({config:w.config,l10n:w.l10n})}function de(e){if(\"function\"!=typeof w.config.position){if(void 0!==w.calendarContainer){De(\"onPreCalendarPosition\");var n=e||w._positionElement,t=Array.prototype.reduce.call(w.calendarContainer.children,(function(e,n){return e+n.offsetHeight}),0),a=w.calendarContainer.offsetWidth,i=w.config.position.split(\" \"),o=i[0],r=i.length>1?i[1]:null,l=n.getBoundingClientRect(),c=window.innerHeight-l.bottom,d=\"above\"===o||\"below\"!==o&&c<t&&l.top>t,u=window.pageYOffset+l.top+(d?-t-2:n.offsetHeight+2);if(s(w.calendarContainer,\"arrowTop\",!d),s(w.calendarContainer,\"arrowBottom\",d),!w.config.inline){var f=window.pageXOffset+l.left,m=!1,g=!1;\"center\"===r?(f-=(a-l.width)/2,m=!0):\"right\"===r&&(f-=a-l.width,g=!0),s(w.calendarContainer,\"arrowLeft\",!m&&!g),s(w.calendarContainer,\"arrowCenter\",m),s(w.calendarContainer,\"arrowRight\",g);var p=window.document.body.offsetWidth-(window.pageXOffset+l.right),h=f+a>window.document.body.offsetWidth,v=p+a>window.document.body.offsetWidth;if(s(w.calendarContainer,\"rightMost\",h),!w.config.static)if(w.calendarContainer.style.top=u+\"px\",h)if(v){var D=function(){for(var e=null,n=0;n<document.styleSheets.length;n++){var t=document.styleSheets[n];if(t.cssRules){try{t.cssRules}catch(e){continue}e=t;break}}return null!=e?e:(a=document.createElement(\"style\"),document.head.appendChild(a),a.sheet);var a}();if(void 0===D)return;var b=window.document.body.offsetWidth,C=Math.max(0,b/2-a/2),M=D.cssRules.length,y=\"{left:\"+l.left+\"px;right:auto;}\";s(w.calendarContainer,\"rightMost\",!1),s(w.calendarContainer,\"centerMost\",!0),D.insertRule(\".flatpickr-calendar.centerMost:before,.flatpickr-calendar.centerMost:after\"+y,M),w.calendarContainer.style.left=C+\"px\",w.calendarContainer.style.right=\"auto\"}else w.calendarContainer.style.left=\"auto\",w.calendarContainer.style.right=p+\"px\";else w.calendarContainer.style.left=f+\"px\",w.calendarContainer.style.right=\"auto\"}}}else w.config.position(w,e)}function ue(){w.config.noCalendar||w.isMobile||(q(),Ce(),U())}function fe(){w._input.focus(),-1!==window.navigator.userAgent.indexOf(\"MSIE\")||void 0!==navigator.msMaxTouchPoints?setTimeout(w.close,0):w.close()}function me(e){e.preventDefault(),e.stopPropagation();var n=f(g(e),(function(e){return e.classList&&e.classList.contains(\"flatpickr-day\")&&!e.classList.contains(\"flatpickr-disabled\")&&!e.classList.contains(\"notAllowed\")}));if(void 0!==n){var t=n,a=w.latestSelectedDateObj=new Date(t.dateObj.getTime()),i=(a.getMonth()<w.currentMonth||a.getMonth()>w.currentMonth+w.config.showMonths-1)&&\"range\"!==w.config.mode;if(w.selectedDateElem=t,\"single\"===w.config.mode)w.selectedDates=[a];else if(\"multiple\"===w.config.mode){var o=be(a);o?w.selectedDates.splice(parseInt(o),1):w.selectedDates.push(a)}else\"range\"===w.config.mode&&(2===w.selectedDates.length&&w.clear(!1,!1),w.latestSelectedDateObj=a,w.selectedDates.push(a),0!==M(a,w.selectedDates[0],!0)&&w.selectedDates.sort((function(e,n){return e.getTime()-n.getTime()})));if(O(),i){var r=w.currentYear!==a.getFullYear();w.currentYear=a.getFullYear(),w.currentMonth=a.getMonth(),r&&(De(\"onYearChange\"),q()),De(\"onMonthChange\")}if(Ce(),U(),ye(),i||\"range\"===w.config.mode||1!==w.config.showMonths?void 0!==w.selectedDateElem&&void 0===w.hourElement&&w.selectedDateElem&&w.selectedDateElem.focus():W(t),void 0!==w.hourElement&&void 0!==w.hourElement&&w.hourElement.focus(),w.config.closeOnSelect){var l=\"single\"===w.config.mode&&!w.config.enableTime,c=\"range\"===w.config.mode&&2===w.selectedDates.length&&!w.config.enableTime;(l||c)&&fe()}Y()}}w.parseDate=C({config:w.config,l10n:w.l10n}),w._handlers=[],w.pluginElements=[],w.loadedPlugins=[],w._bind=P,w._setHoursFromDate=F,w._positionCalendar=de,w.changeMonth=Z,w.changeYear=ee,w.clear=function(e,n){void 0===e&&(e=!0);void 0===n&&(n=!0);w.input.value=\"\",void 0!==w.altInput&&(w.altInput.value=\"\");void 0!==w.mobileInput&&(w.mobileInput.value=\"\");w.selectedDates=[],w.latestSelectedDateObj=void 0,!0===n&&(w.currentYear=w._initialDate.getFullYear(),w.currentMonth=w._initialDate.getMonth());if(!0===w.config.enableTime){var t=E(w.config),a=t.hours,i=t.minutes,o=t.seconds;A(a,i,o)}w.redraw(),e&&De(\"onChange\")},w.close=function(){w.isOpen=!1,w.isMobile||(void 0!==w.calendarContainer&&w.calendarContainer.classList.remove(\"open\"),void 0!==w._input&&w._input.classList.remove(\"active\"));De(\"onClose\")},w.onMouseOver=oe,w._createElement=d,w.createDay=R,w.destroy=function(){void 0!==w.config&&De(\"onDestroy\");for(var e=w._handlers.length;e--;)w._handlers[e].remove();if(w._handlers=[],w.mobileInput)w.mobileInput.parentNode&&w.mobileInput.parentNode.removeChild(w.mobileInput),w.mobileInput=void 0;else if(w.calendarContainer&&w.calendarContainer.parentNode)if(w.config.static&&w.calendarContainer.parentNode){var n=w.calendarContainer.parentNode;if(n.lastChild&&n.removeChild(n.lastChild),n.parentNode){for(;n.firstChild;)n.parentNode.insertBefore(n.firstChild,n);n.parentNode.removeChild(n)}}else w.calendarContainer.parentNode.removeChild(w.calendarContainer);w.altInput&&(w.input.type=\"text\",w.altInput.parentNode&&w.altInput.parentNode.removeChild(w.altInput),delete w.altInput);w.input&&(w.input.type=w.input._type,w.input.classList.remove(\"flatpickr-input\"),w.input.removeAttribute(\"readonly\"));[\"_showTimeInput\",\"latestSelectedDateObj\",\"_hideNextMonthArrow\",\"_hidePrevMonthArrow\",\"__hideNextMonthArrow\",\"__hidePrevMonthArrow\",\"isMobile\",\"isOpen\",\"selectedDateElem\",\"minDateHasTime\",\"maxDateHasTime\",\"days\",\"daysContainer\",\"_input\",\"_positionElement\",\"innerContainer\",\"rContainer\",\"monthNav\",\"todayDateElem\",\"calendarContainer\",\"weekdayContainer\",\"prevMonthNav\",\"nextMonthNav\",\"monthsDropdownContainer\",\"currentMonthElement\",\"currentYearElement\",\"navigationCurrentMonth\",\"selectedDateElem\",\"config\"].forEach((function(e){try{delete w[e]}catch(e){}}))},w.isEnabled=ne,w.jumpToDate=j,w.updateValue=ye,w.open=function(e,n){void 0===n&&(n=w._positionElement);if(!0===w.isMobile){if(e){e.preventDefault();var t=g(e);t&&t.blur()}return void 0!==w.mobileInput&&(w.mobileInput.focus(),w.mobileInput.click()),void De(\"onOpen\")}if(w._input.disabled||w.config.inline)return;var a=w.isOpen;w.isOpen=!0,a||(w.calendarContainer.classList.add(\"open\"),w._input.classList.add(\"active\"),De(\"onOpen\"),de(n));!0===w.config.enableTime&&!0===w.config.noCalendar&&(!1!==w.config.allowInput||void 0!==e&&w.timeContainer.contains(e.relatedTarget)||setTimeout((function(){return w.hourElement.select()}),50))},w.redraw=ue,w.set=function(e,n){if(null!==e&&\"object\"==typeof e)for(var a in Object.assign(w.config,e),e)void 0!==ge[a]&&ge[a].forEach((function(e){return e()}));else w.config[e]=n,void 0!==ge[e]?ge[e].forEach((function(e){return e()})):t.indexOf(e)>-1&&(w.config[e]=c(n));w.redraw(),ye(!0)},w.setDate=function(e,n,t){void 0===n&&(n=!1);void 0===t&&(t=w.config.dateFormat);if(0!==e&&!e||e instanceof Array&&0===e.length)return w.clear(n);pe(e,t),w.latestSelectedDateObj=w.selectedDates[w.selectedDates.length-1],w.redraw(),j(void 0,n),F(),0===w.selectedDates.length&&w.clear(!1);ye(n),n&&De(\"onChange\")},w.toggle=function(e){if(!0===w.isOpen)return w.close();w.open(e)};var ge={locale:[se,G],showMonths:[V,S,z],minDate:[j],maxDate:[j],positionElement:[ve],clickOpens:[function(){!0===w.config.clickOpens?(P(w._input,\"focus\",w.open),P(w._input,\"click\",w.open)):(w._input.removeEventListener(\"focus\",w.open),w._input.removeEventListener(\"click\",w.open))}]};function pe(e,n){var t=[];if(e instanceof Array)t=e.map((function(e){return w.parseDate(e,n)}));else if(e instanceof Date||\"number\"==typeof e)t=[w.parseDate(e,n)];else if(\"string\"==typeof e)switch(w.config.mode){case\"single\":case\"time\":t=[w.parseDate(e,n)];break;case\"multiple\":t=e.split(w.config.conjunction).map((function(e){return w.parseDate(e,n)}));break;case\"range\":t=e.split(w.l10n.rangeSeparator).map((function(e){return w.parseDate(e,n)}))}else w.config.errorHandler(new Error(\"Invalid date supplied: \"+JSON.stringify(e)));w.selectedDates=w.config.allowInvalidPreload?t:t.filter((function(e){return e instanceof Date&&ne(e,!1)})),\"range\"===w.config.mode&&w.selectedDates.sort((function(e,n){return e.getTime()-n.getTime()}))}function he(e){return e.slice().map((function(e){return\"string\"==typeof e||\"number\"==typeof e||e instanceof Date?w.parseDate(e,void 0,!0):e&&\"object\"==typeof e&&e.from&&e.to?{from:w.parseDate(e.from,void 0),to:w.parseDate(e.to,void 0)}:e})).filter((function(e){return e}))}function ve(){w._positionElement=w.config.positionElement||w._input}function De(e,n){if(void 0!==w.config){var t=w.config[e];if(void 0!==t&&t.length>0)for(var a=0;t[a]&&a<t.length;a++)t[a](w.selectedDates,w.input.value,w,n);\"onChange\"===e&&(w.input.dispatchEvent(we(\"change\")),w.input.dispatchEvent(we(\"input\")))}}function we(e){var n=document.createEvent(\"Event\");return n.initEvent(e,!0,!0),n}function be(e){for(var n=0;n<w.selectedDates.length;n++){var t=w.selectedDates[n];if(t instanceof Date&&0===M(t,e))return\"\"+n}return!1}function Ce(){w.config.noCalendar||w.isMobile||!w.monthNav||(w.yearElements.forEach((function(e,n){var t=new Date(w.currentYear,w.currentMonth,1);t.setMonth(w.currentMonth+n),w.config.showMonths>1||\"static\"===w.config.monthSelectorType?w.monthElements[n].textContent=h(t.getMonth(),w.config.shorthandCurrentMonth,w.l10n)+\" \":w.monthsDropdownContainer.value=t.getMonth().toString(),e.value=t.getFullYear().toString()})),w._hidePrevMonthArrow=void 0!==w.config.minDate&&(w.currentYear===w.config.minDate.getFullYear()?w.currentMonth<=w.config.minDate.getMonth():w.currentYear<w.config.minDate.getFullYear()),w._hideNextMonthArrow=void 0!==w.config.maxDate&&(w.currentYear===w.config.maxDate.getFullYear()?w.currentMonth+1>w.config.maxDate.getMonth():w.currentYear>w.config.maxDate.getFullYear()))}function Me(e){var n=e||(w.config.altInput?w.config.altFormat:w.config.dateFormat);return w.selectedDates.map((function(e){return w.formatDate(e,n)})).filter((function(e,n,t){return\"range\"!==w.config.mode||w.config.enableTime||t.indexOf(e)===n})).join(\"range\"!==w.config.mode?w.config.conjunction:w.l10n.rangeSeparator)}function ye(e){void 0===e&&(e=!0),void 0!==w.mobileInput&&w.mobileFormatStr&&(w.mobileInput.value=void 0!==w.latestSelectedDateObj?w.formatDate(w.latestSelectedDateObj,w.mobileFormatStr):\"\"),w.input.value=Me(w.config.dateFormat),void 0!==w.altInput&&(w.altInput.value=Me(w.config.altFormat)),!1!==e&&De(\"onValueUpdate\")}function xe(e){var n=g(e),t=w.prevMonthNav.contains(n),a=w.nextMonthNav.contains(n);t||a?Z(t?-1:1):w.yearElements.indexOf(n)>=0?n.select():n.classList.contains(\"arrowUp\")?w.changeYear(w.currentYear+1):n.classList.contains(\"arrowDown\")&&w.changeYear(w.currentYear-1)}return function(){w.element=w.input=p,w.isOpen=!1,function(){var n=[\"wrap\",\"weekNumbers\",\"allowInput\",\"allowInvalidPreload\",\"clickOpens\",\"time_24hr\",\"enableTime\",\"noCalendar\",\"altInput\",\"shorthandCurrentMonth\",\"inline\",\"static\",\"enableSeconds\",\"disableMobile\"],i=e(e({},JSON.parse(JSON.stringify(p.dataset||{}))),v),o={};w.config.parseDate=i.parseDate,w.config.formatDate=i.formatDate,Object.defineProperty(w.config,\"enable\",{get:function(){return w.config._enable},set:function(e){w.config._enable=he(e)}}),Object.defineProperty(w.config,\"disable\",{get:function(){return w.config._disable},set:function(e){w.config._disable=he(e)}});var r=\"time\"===i.mode;if(!i.dateFormat&&(i.enableTime||r)){var l=I.defaultConfig.dateFormat||a.dateFormat;o.dateFormat=i.noCalendar||r?\"H:i\"+(i.enableSeconds?\":S\":\"\"):l+\" H:i\"+(i.enableSeconds?\":S\":\"\")}if(i.altInput&&(i.enableTime||r)&&!i.altFormat){var s=I.defaultConfig.altFormat||a.altFormat;o.altFormat=i.noCalendar||r?\"h:i\"+(i.enableSeconds?\":S K\":\" K\"):s+\" h:i\"+(i.enableSeconds?\":S\":\"\")+\" K\"}Object.defineProperty(w.config,\"minDate\",{get:function(){return w.config._minDate},set:le(\"min\")}),Object.defineProperty(w.config,\"maxDate\",{get:function(){return w.config._maxDate},set:le(\"max\")});var d=function(e){return function(n){w.config[\"min\"===e?\"_minTime\":\"_maxTime\"]=w.parseDate(n,\"H:i:S\")}};Object.defineProperty(w.config,\"minTime\",{get:function(){return w.config._minTime},set:d(\"min\")}),Object.defineProperty(w.config,\"maxTime\",{get:function(){return w.config._maxTime},set:d(\"max\")}),\"time\"===i.mode&&(w.config.noCalendar=!0,w.config.enableTime=!0);Object.assign(w.config,o,i);for(var u=0;u<n.length;u++)w.config[n[u]]=!0===w.config[n[u]]||\"true\"===w.config[n[u]];t.filter((function(e){return void 0!==w.config[e]})).forEach((function(e){w.config[e]=c(w.config[e]||[]).map(T)})),w.isMobile=!w.config.disableMobile&&!w.config.inline&&\"single\"===w.config.mode&&!w.config.disable.length&&!w.config.enable&&!w.config.weekNumbers&&/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);for(u=0;u<w.config.plugins.length;u++){var f=w.config.plugins[u](w)||{};for(var m in f)t.indexOf(m)>-1?w.config[m]=c(f[m]).map(T).concat(w.config[m]):void 0===i[m]&&(w.config[m]=f[m])}i.altInputClass||(w.config.altInputClass=ce().className+\" \"+w.config.altInputClass);De(\"onParseConfig\")}(),se(),function(){if(w.input=ce(),!w.input)return void w.config.errorHandler(new Error(\"Invalid input element specified\"));w.input._type=w.input.type,w.input.type=\"text\",w.input.classList.add(\"flatpickr-input\"),w._input=w.input,w.config.altInput&&(w.altInput=d(w.input.nodeName,w.config.altInputClass),w._input=w.altInput,w.altInput.placeholder=w.input.placeholder,w.altInput.disabled=w.input.disabled,w.altInput.required=w.input.required,w.altInput.tabIndex=w.input.tabIndex,w.altInput.type=\"text\",w.input.setAttribute(\"type\",\"hidden\"),!w.config.static&&w.input.parentNode&&w.input.parentNode.insertBefore(w.altInput,w.input.nextSibling));w.config.allowInput||w._input.setAttribute(\"readonly\",\"readonly\");ve()}(),function(){w.selectedDates=[],w.now=w.parseDate(w.config.now)||new Date;var e=w.config.defaultDate||(\"INPUT\"!==w.input.nodeName&&\"TEXTAREA\"!==w.input.nodeName||!w.input.placeholder||w.input.value!==w.input.placeholder?w.input.value:null);e&&pe(e,w.config.dateFormat);w._initialDate=w.selectedDates.length>0?w.selectedDates[0]:w.config.minDate&&w.config.minDate.getTime()>w.now.getTime()?w.config.minDate:w.config.maxDate&&w.config.maxDate.getTime()<w.now.getTime()?w.config.maxDate:w.now,w.currentYear=w._initialDate.getFullYear(),w.currentMonth=w._initialDate.getMonth(),w.selectedDates.length>0&&(w.latestSelectedDateObj=w.selectedDates[0]);void 0!==w.config.minTime&&(w.config.minTime=w.parseDate(w.config.minTime,\"H:i\"));void 0!==w.config.maxTime&&(w.config.maxTime=w.parseDate(w.config.maxTime,\"H:i\"));w.minDateHasTime=!!w.config.minDate&&(w.config.minDate.getHours()>0||w.config.minDate.getMinutes()>0||w.config.minDate.getSeconds()>0),w.maxDateHasTime=!!w.config.maxDate&&(w.config.maxDate.getHours()>0||w.config.maxDate.getMinutes()>0||w.config.maxDate.getSeconds()>0)}(),w.utils={getDaysInMonth:function(e,n){return void 0===e&&(e=w.currentMonth),void 0===n&&(n=w.currentYear),1===e&&(n%4==0&&n%100!=0||n%400==0)?29:w.l10n.daysInMonth[e]}},w.isMobile||function(){var e=window.document.createDocumentFragment();if(w.calendarContainer=d(\"div\",\"flatpickr-calendar\"),w.calendarContainer.tabIndex=-1,!w.config.noCalendar){if(e.appendChild((w.monthNav=d(\"div\",\"flatpickr-months\"),w.yearElements=[],w.monthElements=[],w.prevMonthNav=d(\"span\",\"flatpickr-prev-month\"),w.prevMonthNav.innerHTML=w.config.prevArrow,w.nextMonthNav=d(\"span\",\"flatpickr-next-month\"),w.nextMonthNav.innerHTML=w.config.nextArrow,V(),Object.defineProperty(w,\"_hidePrevMonthArrow\",{get:function(){return w.__hidePrevMonthArrow},set:function(e){w.__hidePrevMonthArrow!==e&&(s(w.prevMonthNav,\"flatpickr-disabled\",e),w.__hidePrevMonthArrow=e)}}),Object.defineProperty(w,\"_hideNextMonthArrow\",{get:function(){return w.__hideNextMonthArrow},set:function(e){w.__hideNextMonthArrow!==e&&(s(w.nextMonthNav,\"flatpickr-disabled\",e),w.__hideNextMonthArrow=e)}}),w.currentYearElement=w.yearElements[0],Ce(),w.monthNav)),w.innerContainer=d(\"div\",\"flatpickr-innerContainer\"),w.config.weekNumbers){var n=function(){w.calendarContainer.classList.add(\"hasWeeks\");var e=d(\"div\",\"flatpickr-weekwrapper\");e.appendChild(d(\"span\",\"flatpickr-weekday\",w.l10n.weekAbbreviation));var n=d(\"div\",\"flatpickr-weeks\");return e.appendChild(n),{weekWrapper:e,weekNumbers:n}}(),t=n.weekWrapper,a=n.weekNumbers;w.innerContainer.appendChild(t),w.weekNumbers=a,w.weekWrapper=t}w.rContainer=d(\"div\",\"flatpickr-rContainer\"),w.rContainer.appendChild(z()),w.daysContainer||(w.daysContainer=d(\"div\",\"flatpickr-days\"),w.daysContainer.tabIndex=-1),U(),w.rContainer.appendChild(w.daysContainer),w.innerContainer.appendChild(w.rContainer),e.appendChild(w.innerContainer)}w.config.enableTime&&e.appendChild(function(){w.calendarContainer.classList.add(\"hasTime\"),w.config.noCalendar&&w.calendarContainer.classList.add(\"noCalendar\");var e=E(w.config);w.timeContainer=d(\"div\",\"flatpickr-time\"),w.timeContainer.tabIndex=-1;var n=d(\"span\",\"flatpickr-time-separator\",\":\"),t=m(\"flatpickr-hour\",{\"aria-label\":w.l10n.hourAriaLabel});w.hourElement=t.getElementsByTagName(\"input\")[0];var a=m(\"flatpickr-minute\",{\"aria-label\":w.l10n.minuteAriaLabel});w.minuteElement=a.getElementsByTagName(\"input\")[0],w.hourElement.tabIndex=w.minuteElement.tabIndex=-1,w.hourElement.value=o(w.latestSelectedDateObj?w.latestSelectedDateObj.getHours():w.config.time_24hr?e.hours:function(e){switch(e%24){case 0:case 12:return 12;default:return e%12}}(e.hours)),w.minuteElement.value=o(w.latestSelectedDateObj?w.latestSelectedDateObj.getMinutes():e.minutes),w.hourElement.setAttribute(\"step\",w.config.hourIncrement.toString()),w.minuteElement.setAttribute(\"step\",w.config.minuteIncrement.toString()),w.hourElement.setAttribute(\"min\",w.config.time_24hr?\"0\":\"1\"),w.hourElement.setAttribute(\"max\",w.config.time_24hr?\"23\":\"12\"),w.hourElement.setAttribute(\"maxlength\",\"2\"),w.minuteElement.setAttribute(\"min\",\"0\"),w.minuteElement.setAttribute(\"max\",\"59\"),w.minuteElement.setAttribute(\"maxlength\",\"2\"),w.timeContainer.appendChild(t),w.timeContainer.appendChild(n),w.timeContainer.appendChild(a),w.config.time_24hr&&w.timeContainer.classList.add(\"time24hr\");if(w.config.enableSeconds){w.timeContainer.classList.add(\"hasSeconds\");var i=m(\"flatpickr-second\");w.secondElement=i.getElementsByTagName(\"input\")[0],w.secondElement.value=o(w.latestSelectedDateObj?w.latestSelectedDateObj.getSeconds():e.seconds),w.secondElement.setAttribute(\"step\",w.minuteElement.getAttribute(\"step\")),w.secondElement.setAttribute(\"min\",\"0\"),w.secondElement.setAttribute(\"max\",\"59\"),w.secondElement.setAttribute(\"maxlength\",\"2\"),w.timeContainer.appendChild(d(\"span\",\"flatpickr-time-separator\",\":\")),w.timeContainer.appendChild(i)}w.config.time_24hr||(w.amPM=d(\"span\",\"flatpickr-am-pm\",w.l10n.amPM[r((w.latestSelectedDateObj?w.hourElement.value:w.config.defaultHour)>11)]),w.amPM.title=w.l10n.toggleTitle,w.amPM.tabIndex=-1,w.timeContainer.appendChild(w.amPM));return w.timeContainer}());s(w.calendarContainer,\"rangeMode\",\"range\"===w.config.mode),s(w.calendarContainer,\"animate\",!0===w.config.animate),s(w.calendarContainer,\"multiMonth\",w.config.showMonths>1),w.calendarContainer.appendChild(e);var i=void 0!==w.config.appendTo&&void 0!==w.config.appendTo.nodeType;if((w.config.inline||w.config.static)&&(w.calendarContainer.classList.add(w.config.inline?\"inline\":\"static\"),w.config.inline&&(!i&&w.element.parentNode?w.element.parentNode.insertBefore(w.calendarContainer,w._input.nextSibling):void 0!==w.config.appendTo&&w.config.appendTo.appendChild(w.calendarContainer)),w.config.static)){var l=d(\"div\",\"flatpickr-wrapper\");w.element.parentNode&&w.element.parentNode.insertBefore(l,w.element),l.appendChild(w.element),w.altInput&&l.appendChild(w.altInput),l.appendChild(w.calendarContainer)}w.config.static||w.config.inline||(void 0!==w.config.appendTo?w.config.appendTo:window.document.body).appendChild(w.calendarContainer)}(),function(){w.config.wrap&&[\"open\",\"close\",\"toggle\",\"clear\"].forEach((function(e){Array.prototype.forEach.call(w.element.querySelectorAll(\"[data-\"+e+\"]\"),(function(n){return P(n,\"click\",w[e])}))}));if(w.isMobile)return void function(){var e=w.config.enableTime?w.config.noCalendar?\"time\":\"datetime-local\":\"date\";w.mobileInput=d(\"input\",w.input.className+\" flatpickr-mobile\"),w.mobileInput.tabIndex=1,w.mobileInput.type=e,w.mobileInput.disabled=w.input.disabled,w.mobileInput.required=w.input.required,w.mobileInput.placeholder=w.input.placeholder,w.mobileFormatStr=\"datetime-local\"===e?\"Y-m-d\\\\TH:i:S\":\"date\"===e?\"Y-m-d\":\"H:i:S\",w.selectedDates.length>0&&(w.mobileInput.defaultValue=w.mobileInput.value=w.formatDate(w.selectedDates[0],w.mobileFormatStr));w.config.minDate&&(w.mobileInput.min=w.formatDate(w.config.minDate,\"Y-m-d\"));w.config.maxDate&&(w.mobileInput.max=w.formatDate(w.config.maxDate,\"Y-m-d\"));w.input.getAttribute(\"step\")&&(w.mobileInput.step=String(w.input.getAttribute(\"step\")));w.input.type=\"hidden\",void 0!==w.altInput&&(w.altInput.type=\"hidden\");try{w.input.parentNode&&w.input.parentNode.insertBefore(w.mobileInput,w.input.nextSibling)}catch(e){}P(w.mobileInput,\"change\",(function(e){w.setDate(g(e).value,!1,w.mobileFormatStr),De(\"onChange\"),De(\"onClose\")}))}();var e=l(re,50);w._debouncedChange=l(Y,300),w.daysContainer&&!/iPhone|iPad|iPod/i.test(navigator.userAgent)&&P(w.daysContainer,\"mouseover\",(function(e){\"range\"===w.config.mode&&oe(g(e))}));P(w._input,\"keydown\",ie),void 0!==w.calendarContainer&&P(w.calendarContainer,\"keydown\",ie);w.config.inline||w.config.static||P(window,\"resize\",e);void 0!==window.ontouchstart?P(window.document,\"touchstart\",X):P(window.document,\"mousedown\",X);P(window.document,\"focus\",X,{capture:!0}),!0===w.config.clickOpens&&(P(w._input,\"focus\",w.open),P(w._input,\"click\",w.open));void 0!==w.daysContainer&&(P(w.monthNav,\"click\",xe),P(w.monthNav,[\"keyup\",\"increment\"],N),P(w.daysContainer,\"click\",me));if(void 0!==w.timeContainer&&void 0!==w.minuteElement&&void 0!==w.hourElement){var n=function(e){return g(e).select()};P(w.timeContainer,[\"increment\"],_),P(w.timeContainer,\"blur\",_,{capture:!0}),P(w.timeContainer,\"click\",H),P([w.hourElement,w.minuteElement],[\"focus\",\"click\"],n),void 0!==w.secondElement&&P(w.secondElement,\"focus\",(function(){return w.secondElement&&w.secondElement.select()})),void 0!==w.amPM&&P(w.amPM,\"click\",(function(e){_(e)}))}w.config.allowInput&&P(w._input,\"blur\",ae)}(),(w.selectedDates.length||w.config.noCalendar)&&(w.config.enableTime&&F(w.config.noCalendar?w.latestSelectedDateObj:void 0),ye(!1)),S();var n=/^((?!chrome|android).)*safari/i.test(navigator.userAgent);!w.isMobile&&n&&de(),De(\"onReady\")}(),w}function T(e,n){for(var t=Array.prototype.slice.call(e).filter((function(e){return e instanceof HTMLElement})),a=[],i=0;i<t.length;i++){var o=t[i];try{if(null!==o.getAttribute(\"data-fp-omit\"))continue;void 0!==o._flatpickr&&(o._flatpickr.destroy(),o._flatpickr=void 0),o._flatpickr=k(o,n||{}),a.push(o._flatpickr)}catch(e){console.error(e)}}return 1===a.length?a[0]:a}\"undefined\"!=typeof HTMLElement&&\"undefined\"!=typeof HTMLCollection&&\"undefined\"!=typeof NodeList&&(HTMLCollection.prototype.flatpickr=NodeList.prototype.flatpickr=function(e){return T(this,e)},HTMLElement.prototype.flatpickr=function(e){return T([this],e)});var I=function(e,n){return\"string\"==typeof e?T(window.document.querySelectorAll(e),n):e instanceof Node?T([e],n):T(e,n)};return I.defaultConfig={},I.l10ns={en:e({},i),default:e({},i)},I.localize=function(n){I.l10ns.default=e(e({},I.l10ns.default),n)},I.setDefaults=function(n){I.defaultConfig=e(e({},I.defaultConfig),n)},I.parseDate=C({}),I.formatDate=b({}),I.compareDates=M,\"undefined\"!=typeof jQuery&&void 0!==jQuery.fn&&(jQuery.fn.flatpickr=function(e){return T(this,e)}),Date.prototype.fp_incr=function(e){return new Date(this.getFullYear(),this.getMonth(),this.getDate()+(\"string\"==typeof e?parseInt(e,10):e))},\"undefined\"!=typeof window&&(window.flatpickr=I),I}));"
  },
  {
    "path": "resources/assets/flatpickr/dist/l10n/zh.js",
    "content": "(function (global, factory) {\n  typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :\n  typeof define === 'function' && define.amd ? define(['exports'], factory) :\n  (global = global || self, factory(global.zh = {}));\n}(this, (function (exports) { 'use strict';\n\n  var fp = typeof window !== \"undefined\" && window.flatpickr !== undefined\n      ? window.flatpickr\n      : {\n          l10ns: {},\n      };\n  var Mandarin = {\n      weekdays: {\n          shorthand: [\"周日\", \"周一\", \"周二\", \"周三\", \"周四\", \"周五\", \"周六\"],\n          longhand: [\n              \"星期日\",\n              \"星期一\",\n              \"星期二\",\n              \"星期三\",\n              \"星期四\",\n              \"星期五\",\n              \"星期六\",\n          ],\n      },\n      months: {\n          shorthand: [\n              \"一月\",\n              \"二月\",\n              \"三月\",\n              \"四月\",\n              \"五月\",\n              \"六月\",\n              \"七月\",\n              \"八月\",\n              \"九月\",\n              \"十月\",\n              \"十一月\",\n              \"十二月\",\n          ],\n          longhand: [\n              \"一月\",\n              \"二月\",\n              \"三月\",\n              \"四月\",\n              \"五月\",\n              \"六月\",\n              \"七月\",\n              \"八月\",\n              \"九月\",\n              \"十月\",\n              \"十一月\",\n              \"十二月\",\n          ],\n      },\n      rangeSeparator: \" 至 \",\n      weekAbbreviation: \"周\",\n      scrollTitle: \"滚动切换\",\n      toggleTitle: \"点击切换 12/24 小时时制\",\n  };\n  fp.l10ns.zh = Mandarin;\n  var zh = fp.l10ns;\n\n  exports.Mandarin = Mandarin;\n  exports.default = zh;\n\n  Object.defineProperty(exports, '__esModule', { value: true });\n\n})));\n"
  },
  {
    "path": "resources/assets/google-fonts/fonts.css",
    "content": "@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: normal;\n  font-weight: 300;\n  src: local('Source Sans Pro Light'), local('SourceSansPro-Light'), url(fonts/Source-Sans-Pro-Light.woff2) format('woff2'), url(fonts/Source-Sans-Pro-Light.ttf) format('truetype'), url(fonts/Source-Sans-Pro-Light.woff) format('woff');\n}\n\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: normal;\n  font-weight: 400;\n  src: url(fonts/Source-Sans-Pro.eot);\n  src: local('Source Sans Pro'), local('SourceSansPro-Regular'), url(fonts/Source-Sans-Pro.woff2) format('woff2'), url(fonts/Source-Sans-Pro.ttf) format('truetype'), url(fonts/Source-Sans-Pro.svg#SourceSansPro) format('svg'), url(fonts/Source-Sans-Pro.eot?#iefix) format('embedded-opentype'), url(fonts/Source-Sans-Pro.woff) format('woff');\n}\n\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: normal;\n  font-weight: 600;\n  src: local('Source Sans Pro Semibold'), local('SourceSansPro-Semibold'), url(fonts/Source-Sans-Pro-Semibold.woff2) format('woff2'), url(fonts/Source-Sans-Pro-Semibold.ttf) format('truetype'), url(fonts/Source-Sans-Pro-Semibold.woff) format('woff');\n}\n\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: normal;\n  font-weight: 700;\n  src: local('Source Sans Pro Bold'), local('SourceSansPro-Bold'), url(fonts/Source-Sans-Pro-Bold.woff2) format('woff2'), url(fonts/Source-Sans-Pro-Bold.ttf) format('truetype'), url(fonts/Source-Sans-Pro-Bold.woff) format('woff');\n}\n\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: italic;\n  font-weight: 300;\n  src: local('Source Sans Pro Light Italic'), local('SourceSansPro-LightIt'), url(fonts/Source-Sans-Pro-Light-Italic.woff2) format('woff2'), url(fonts/Source-Sans-Pro-Light-Italic.ttf) format('truetype'), url(fonts/Source-Sans-Pro-Light-Italic.woff) format('woff');\n}\n\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: italic;\n  font-weight: 400;\n  src: local('Source Sans Pro Italic'), local('SourceSansPro-It'), url(fonts/Source-Sans-Pro-Italic.woff2) format('woff2'), url(fonts/Source-Sans-Pro-Italic.ttf) format('truetype'), url(fonts/Source-Sans-Pro-Italic.woff) format('woff');\n}\n\n@font-face {\n  font-family: 'Source Sans Pro';\n  font-style: italic;\n  font-weight: 600;\n  src: local('Source Sans Pro Semibold Italic'), local('SourceSansPro-SemiboldIt'), url(fonts/Source-Sans-Pro-Semibold-Italic.woff2) format('woff2'), url(fonts/Source-Sans-Pro-Semibold-Italic.ttf) format('truetype'), url(fonts/Source-Sans-Pro-Semibold-Italic.woff) format('woff');\n}\n\n"
  },
  {
    "path": "resources/assets/jquery-pjax/jquery.pjax.js",
    "content": "/*!\n * Copyright 2012, Chris Wanstrath\n * Released under the MIT License\n * https://github.com/defunkt/jquery-pjax\n */\n\n(function($){\n\n// When called on a container with a selector, fetches the href with\n// ajax into the container or with the data-pjax attribute on the link\n// itself.\n//\n// Tries to make sure the back button and ctrl+click work the way\n// you'd expect.\n//\n// Exported as $.fn.pjax\n//\n// Accepts a jQuery ajax options object that may include these\n// pjax specific options:\n//\n//\n// container - Where to stick the response body. Usually a String selector.\n//             $(container).html(xhr.responseBody)\n//             (default: current jquery context)\n//      push - Whether to pushState the URL. Defaults to true (of course).\n//   replace - Want to use replaceState instead? That's cool.\n//\n// For convenience the second parameter can be either the container or\n// the options object.\n//\n// Returns the jQuery object\nfunction fnPjax(selector, container, options) {\n  var context = this\n  return this.on('click.pjax', selector, function(event) {\n    var opts = $.extend({}, optionsFor(container, options))\n    if (!opts.container)\n      opts.container = $(this).attr('data-pjax') || context\n    handleClick(event, opts)\n  })\n}\n\n// Public: pjax on click handler\n//\n// Exported as $.pjax.click.\n//\n// event   - \"click\" jQuery.Event\n// options - pjax options\n//\n// Examples\n//\n//   $(document).on('click', 'a', $.pjax.click)\n//   // is the same as\n//   $(document).pjax('a')\n//\n//  $(document).on('click', 'a', function(event) {\n//    var container = $(this).closest('[data-pjax-container]')\n//    $.pjax.click(event, container)\n//  })\n//\n// Returns nothing.\nfunction handleClick(event, container, options) {\n  options = optionsFor(container, options)\n\n  var link = event.currentTarget\n\n  if (link.tagName.toUpperCase() !== 'A')\n    throw \"$.fn.pjax or $.pjax.click requires an anchor element\"\n\n  // Middle click, cmd click, and ctrl click should open\n  // links in a new tab as normal.\n  if ( event.which > 1 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey )\n    return\n\n  // Ignore cross origin links\n  if ( location.protocol !== link.protocol || location.hostname !== link.hostname )\n    return\n\n  // Ignore case when a hash is being tacked on the current URL\n  if ( link.href.indexOf('#') > -1 && stripHash(link) == stripHash(location) )\n    return\n\n  // Ignore event with default prevented\n  if (event.isDefaultPrevented())\n    return\n\n  var defaults = {\n    url: link.href,\n    container: $(link).attr('data-pjax'),\n    target: link\n  }\n\n  var opts = $.extend({}, defaults, options)\n  var clickEvent = $.Event('pjax:click')\n  $(link).trigger(clickEvent, [opts])\n\n  if (!clickEvent.isDefaultPrevented()) {\n    pjax(opts)\n    event.preventDefault()\n    $(link).trigger('pjax:clicked', [opts])\n  }\n}\n\n// Public: pjax on form submit handler\n//\n// Exported as $.pjax.submit\n//\n// event   - \"click\" jQuery.Event\n// options - pjax options\n//\n// Examples\n//\n//  $(document).on('submit', 'form', function(event) {\n//    var container = $(this).closest('[data-pjax-container]')\n//    $.pjax.submit(event, container)\n//  })\n//\n// Returns nothing.\nfunction handleSubmit(event, container, options) {\n  options = optionsFor(container, options)\n\n  var form = event.currentTarget\n  var $form = $(form)\n\n  if (form.tagName.toUpperCase() !== 'FORM')\n    throw \"$.pjax.submit requires a form element\"\n\n  var defaults = {\n    type: ($form.attr('method') || 'GET').toUpperCase(),\n    url: $form.attr('action'),\n    container: $form.attr('data-pjax'),\n    target: form\n  }\n\n  if (defaults.type !== 'GET' && window.FormData !== undefined) {\n    defaults.data = new FormData(form);\n    defaults.processData = false;\n    defaults.contentType = false;\n  } else {\n    // Can't handle file uploads, exit\n    if ($(form).find(':file').length) {\n      return;\n    }\n\n    // Fallback to manually serializing the fields\n    defaults.data = $(form).serializeArray();\n  }\n\n  pjax($.extend({}, defaults, options))\n\n  event.preventDefault()\n}\n\n// Loads a URL with ajax, puts the response body inside a container,\n// then pushState()'s the loaded URL.\n//\n// Works just like $.ajax in that it accepts a jQuery ajax\n// settings object (with keys like url, type, data, etc).\n//\n// Accepts these extra keys:\n//\n// container - Where to stick the response body.\n//             $(container).html(xhr.responseBody)\n//      push - Whether to pushState the URL. Defaults to true (of course).\n//   replace - Want to use replaceState instead? That's cool.\n//\n// Use it just like $.ajax:\n//\n//   var xhr = $.pjax({ url: this.href, container: '#main' })\n//   console.log( xhr.readyState )\n//\n// Returns whatever $.ajax returns.\nfunction pjax(options) {\n  options = $.extend(true, {}, $.ajaxSettings, pjax.defaults, options)\n\n  if ($.isFunction(options.url)) {\n    options.url = options.url()\n  }\n\n  var target = options.target\n\n  var hash = parseURL(options.url).hash\n\n  var context = options.context = findContainerFor(options.container)\n\n  // We want the browser to maintain two separate internal caches: one\n  // for pjax'd partial page loads and one for normal page loads.\n  // Without adding this secret parameter, some browsers will often\n  // confuse the two.\n  if (!options.data) options.data = {}\n  if ($.isArray(options.data)) {\n    options.data.push({name: '_pjax', value: context.selector})\n  } else {\n    options.data._pjax = context.selector\n  }\n\n  function fire(type, args, props) {\n    if (!props) props = {}\n    props.relatedTarget = target\n    var event = $.Event(type, props)\n    context.trigger(event, args)\n    return !event.isDefaultPrevented()\n  }\n\n  var timeoutTimer\n\n  options.beforeSend = function(xhr, settings) {\n    // No timeout for non-GET requests\n    // Its not safe to request the resource again with a fallback method.\n    if (settings.type !== 'GET') {\n      settings.timeout = 0\n    }\n\n    xhr.setRequestHeader('X-PJAX', 'true')\n    xhr.setRequestHeader('X-PJAX-Container', context.selector)\n\n    if (!fire('pjax:beforeSend', [xhr, settings]))\n      return false\n\n    if (settings.timeout > 0) {\n      timeoutTimer = setTimeout(function() {\n        if (fire('pjax:timeout', [xhr, options]))\n          xhr.abort('timeout')\n      }, settings.timeout)\n\n      // Clear timeout setting so jquerys internal timeout isn't invoked\n      settings.timeout = 0\n    }\n\n    var url = parseURL(settings.url)\n    if (hash) url.hash = hash\n    options.requestUrl = stripInternalParams(url)\n  }\n\n  options.complete = function(xhr, textStatus) {\n    if (timeoutTimer)\n      clearTimeout(timeoutTimer)\n\n    fire('pjax:complete', [xhr, textStatus, options])\n\n    fire('pjax:end', [xhr, options])\n  }\n\n  options.error = function(xhr, textStatus, errorThrown) {\n    var container = extractContainer(\"\", xhr, options)\n\n    var allowed = fire('pjax:error', [xhr, textStatus, errorThrown, options])\n    if (options.type == 'GET' && textStatus !== 'abort' && allowed) {\n      locationReplace(container.url)\n    }\n  }\n\n  options.success = function(data, status, xhr) {\n    var previousState = pjax.state;\n\n    // If $.pjax.defaults.version is a function, invoke it first.\n    // Otherwise it can be a static string.\n    var currentVersion = (typeof $.pjax.defaults.version === 'function') ?\n      $.pjax.defaults.version() :\n      $.pjax.defaults.version\n\n    var latestVersion = xhr.getResponseHeader('X-PJAX-Version')\n\n    var container = extractContainer(data, xhr, options)\n\n    var url = parseURL(container.url)\n    if (hash) {\n      url.hash = hash\n      container.url = url.href\n    }\n\n    // If there is a layout version mismatch, hard load the new url\n    if (currentVersion && latestVersion && currentVersion !== latestVersion) {\n      locationReplace(container.url)\n      return\n    }\n\n    // If the new response is missing a body, hard load the page\n    if (!container.contents) {\n      locationReplace(container.url)\n      return\n    }\n\n    pjax.state = {\n      id: options.id || uniqueId(),\n      url: container.url,\n      title: container.title,\n      container: context.selector,\n      fragment: options.fragment,\n      timeout: options.timeout\n    }\n\n    if (options.push || options.replace) {\n      window.history.replaceState(pjax.state, container.title, container.url)\n    }\n\n    // Only blur the focus if the focused element is within the container.\n    var blurFocus = $.contains(options.container, document.activeElement)\n\n    // Clear out any focused controls before inserting new page contents.\n    if (blurFocus) {\n      try {\n        document.activeElement.blur()\n      } catch (e) { }\n    }\n\n    if (container.title) document.title = container.title\n\n    fire('pjax:beforeReplace', [container.contents, options], {\n      state: pjax.state,\n      previousState: previousState\n    })\n    context.html(container.contents)\n\n    // FF bug: Won't autofocus fields that are inserted via JS.\n    // This behavior is incorrect. So if theres no current focus, autofocus\n    // the last field.\n    //\n    // http://www.w3.org/html/wg/drafts/html/master/forms.html\n    var autofocusEl = context.find('input[autofocus], textarea[autofocus]').last()[0]\n    if (autofocusEl && document.activeElement !== autofocusEl) {\n      autofocusEl.focus();\n    }\n\n    executeScriptTags(container.scripts, context)\n\n    var scrollTo = options.scrollTo\n\n    // Ensure browser scrolls to the element referenced by the URL anchor\n    if (hash) {\n      var name = decodeURIComponent(hash.slice(1))\n      var target = document.getElementById(name) || document.getElementsByName(name)[0]\n      if (target) scrollTo = $(target).offset().top\n    }\n\n    if (typeof scrollTo == 'number') $(window).scrollTop(scrollTo)\n\n    fire('pjax:success', [data, status, xhr, options])\n  }\n\n\n  // Initialize pjax.state for the initial page load. Assume we're\n  // using the container and options of the link we're loading for the\n  // back button to the initial page. This ensures good back button\n  // behavior.\n  if (!pjax.state) {\n    pjax.state = {\n      id: uniqueId(),\n      url: window.location.href,\n      title: document.title,\n      container: context.selector,\n      fragment: options.fragment,\n      timeout: options.timeout\n    }\n    window.history.replaceState(pjax.state, document.title)\n  }\n\n  // Cancel the current request if we're already pjaxing\n  abortXHR(pjax.xhr)\n\n  pjax.options = options\n  var xhr = pjax.xhr = $.ajax(options)\n\n  if (xhr.readyState > 0) {\n    if (options.push && !options.replace) {\n      // Cache current container element before replacing it\n      cachePush(pjax.state.id, cloneContents(context))\n\n      window.history.pushState(null, \"\", options.requestUrl)\n    }\n\n    fire('pjax:start', [xhr, options])\n    fire('pjax:send', [xhr, options])\n  }\n\n  return pjax.xhr\n}\n\n// Public: Reload current page with pjax.\n//\n// Returns whatever $.pjax returns.\nfunction pjaxReload(container, options) {\n  var defaults = {\n    url: window.location.href,\n    push: false,\n    replace: true,\n    scrollTo: false\n  }\n\n  return pjax($.extend(defaults, optionsFor(container, options)))\n}\n\n// Internal: Hard replace current state with url.\n//\n// Work for around WebKit\n//   https://bugs.webkit.org/show_bug.cgi?id=93506\n//\n// Returns nothing.\nfunction locationReplace(url) {\n  window.history.replaceState(null, \"\", pjax.state.url)\n  window.location.replace(url)\n}\n\n\nvar initialPop = true\nvar initialURL = window.location.href\nvar initialState = window.history.state\n\n// Initialize $.pjax.state if possible\n// Happens when reloading a page and coming forward from a different\n// session history.\nif (initialState && initialState.container) {\n  pjax.state = initialState\n}\n\n// Non-webkit browsers don't fire an initial popstate event\nif ('state' in window.history) {\n  initialPop = false\n}\n\n// popstate handler takes care of the back and forward buttons\n//\n// You probably shouldn't use pjax on pages with other pushState\n// stuff yet.\nfunction onPjaxPopstate(event) {\n\n  // Hitting back or forward should override any pending PJAX request.\n  if (!initialPop) {\n    abortXHR(pjax.xhr)\n  }\n\n  var previousState = pjax.state\n  var state = event.state\n  var direction\n\n  if (state && state.container) {\n    // When coming forward from a separate history session, will get an\n    // initial pop with a state we are already at. Skip reloading the current\n    // page.\n    if (initialPop && initialURL == state.url) return\n\n    if (previousState) {\n      // If popping back to the same state, just skip.\n      // Could be clicking back from hashchange rather than a pushState.\n      if (previousState.id === state.id) return\n\n      // Since state IDs always increase, we can deduce the navigation direction\n      direction = previousState.id < state.id ? 'forward' : 'back'\n    }\n\n    var cache = cacheMapping[state.id] || []\n    var container = $(cache[0] || state.container), contents = cache[1]\n\n    if (container.length) {\n      if (previousState) {\n        // Cache current container before replacement and inform the\n        // cache which direction the history shifted.\n        cachePop(direction, previousState.id, cloneContents(container))\n      }\n\n      var popstateEvent = $.Event('pjax:popstate', {\n        state: state,\n        direction: direction\n      })\n      container.trigger(popstateEvent)\n\n      var options = {\n        id: state.id,\n        url: state.url,\n        container: container,\n        push: false,\n        fragment: state.fragment,\n        timeout: state.timeout,\n        scrollTo: false\n      }\n\n      if (contents) {\n        container.trigger('pjax:start', [null, options])\n\n        pjax.state = state\n        if (state.title) document.title = state.title\n        var beforeReplaceEvent = $.Event('pjax:beforeReplace', {\n          state: state,\n          previousState: previousState\n        })\n        container.trigger(beforeReplaceEvent, [contents, options])\n        container.html(contents)\n\n        container.trigger('pjax:end', [null, options])\n      } else {\n        pjax(options)\n      }\n\n      // Force reflow/relayout before the browser tries to restore the\n      // scroll position.\n      container[0].offsetHeight\n    } else {\n      locationReplace(location.href)\n    }\n  }\n  initialPop = false\n}\n\n// Fallback version of main pjax function for browsers that don't\n// support pushState.\n//\n// Returns nothing since it retriggers a hard form submission.\nfunction fallbackPjax(options) {\n  var url = $.isFunction(options.url) ? options.url() : options.url,\n      method = options.type ? options.type.toUpperCase() : 'GET'\n\n  var form = $('<form>', {\n    method: method === 'GET' ? 'GET' : 'POST',\n    action: url,\n    style: 'display:none'\n  })\n\n  if (method !== 'GET' && method !== 'POST') {\n    form.append($('<input>', {\n      type: 'hidden',\n      name: '_method',\n      value: method.toLowerCase()\n    }))\n  }\n\n  var data = options.data\n  if (typeof data === 'string') {\n    $.each(data.split('&'), function(index, value) {\n      var pair = value.split('=')\n      form.append($('<input>', {type: 'hidden', name: pair[0], value: pair[1]}))\n    })\n  } else if ($.isArray(data)) {\n    $.each(data, function(index, value) {\n      form.append($('<input>', {type: 'hidden', name: value.name, value: value.value}))\n    })\n  } else if (typeof data === 'object') {\n    var key\n    for (key in data)\n      form.append($('<input>', {type: 'hidden', name: key, value: data[key]}))\n  }\n\n  $(document.body).append(form)\n  form.submit()\n}\n\n// Internal: Abort an XmlHttpRequest if it hasn't been completed,\n// also removing its event handlers.\nfunction abortXHR(xhr) {\n  if ( xhr && xhr.readyState < 4) {\n    xhr.onreadystatechange = $.noop\n    xhr.abort()\n  }\n}\n\n// Internal: Generate unique id for state object.\n//\n// Use a timestamp instead of a counter since ids should still be\n// unique across page loads.\n//\n// Returns Number.\nfunction uniqueId() {\n  return (new Date).getTime()\n}\n\nfunction cloneContents(container) {\n  var cloned = container.clone()\n  // Unmark script tags as already being eval'd so they can get executed again\n  // when restored from cache. HAXX: Uses jQuery internal method.\n  cloned.find('script').each(function(){\n    if (!this.src) jQuery._data(this, 'globalEval', false)\n  })\n  return [container.selector, cloned.contents()]\n}\n\n// Internal: Strip internal query params from parsed URL.\n//\n// Returns sanitized url.href String.\nfunction stripInternalParams(url) {\n  url.search = url.search.replace(/([?&])(_pjax|_)=[^&]*/g, '')\n  return url.href.replace(/\\?($|#)/, '$1')\n}\n\n// Internal: Parse URL components and returns a Locationish object.\n//\n// url - String URL\n//\n// Returns HTMLAnchorElement that acts like Location.\nfunction parseURL(url) {\n  var a = document.createElement('a')\n  a.href = url\n  return a\n}\n\n// Internal: Return the `href` component of given URL object with the hash\n// portion removed.\n//\n// location - Location or HTMLAnchorElement\n//\n// Returns String\nfunction stripHash(location) {\n  return location.href.replace(/#.*/, '')\n}\n\n// Internal: Build options Object for arguments.\n//\n// For convenience the first parameter can be either the container or\n// the options object.\n//\n// Examples\n//\n//   optionsFor('#container')\n//   // => {container: '#container'}\n//\n//   optionsFor('#container', {push: true})\n//   // => {container: '#container', push: true}\n//\n//   optionsFor({container: '#container', push: true})\n//   // => {container: '#container', push: true}\n//\n// Returns options Object.\nfunction optionsFor(container, options) {\n  // Both container and options\n  if ( container && options )\n    options.container = container\n\n  // First argument is options Object\n  else if ( $.isPlainObject(container) )\n    options = container\n\n  // Only container\n  else\n    options = {container: container}\n\n  // Find and validate container\n  if (options.container)\n    options.container = findContainerFor(options.container)\n\n  return options\n}\n\n// Internal: Find container element for a variety of inputs.\n//\n// Because we can't persist elements using the history API, we must be\n// able to find a String selector that will consistently find the Element.\n//\n// container - A selector String, jQuery object, or DOM Element.\n//\n// Returns a jQuery object whose context is `document` and has a selector.\nfunction findContainerFor(container) {\n  container = $(container)\n\n  if ( !container.length ) {\n    throw \"no pjax container for \" + container.selector\n  } else if ( container.selector !== '' && container.context === document ) {\n    return container\n  } else if ( container.attr('id') ) {\n    return $('#' + container.attr('id'))\n  } else {\n    throw \"cant get selector for pjax container!\"\n  }\n}\n\n// Internal: Filter and find all elements matching the selector.\n//\n// Where $.fn.find only matches descendants, findAll will test all the\n// top level elements in the jQuery object as well.\n//\n// elems    - jQuery object of Elements\n// selector - String selector to match\n//\n// Returns a jQuery object.\nfunction findAll(elems, selector) {\n  return elems.filter(selector).add(elems.find(selector));\n}\n\nfunction parseHTML(html) {\n  return $.parseHTML(html, document, true)\n}\n\n// Internal: Extracts container and metadata from response.\n//\n// 1. Extracts X-PJAX-URL header if set\n// 2. Extracts inline <title> tags\n// 3. Builds response Element and extracts fragment if set\n//\n// data    - String response data\n// xhr     - XHR response\n// options - pjax options Object\n//\n// Returns an Object with url, title, and contents keys.\nfunction extractContainer(data, xhr, options) {\n  var obj = {}, fullDocument = /<html/i.test(data)\n\n  // Prefer X-PJAX-URL header if it was set, otherwise fallback to\n  // using the original requested url.\n  var serverUrl = xhr.getResponseHeader('X-PJAX-URL')\n  obj.url = serverUrl ? stripInternalParams(parseURL(serverUrl)) : options.requestUrl\n\n  // Attempt to parse response html into elements\n  if (fullDocument) {\n    var $head = $(parseHTML(data.match(/<head[^>]*>([\\s\\S.]*)<\\/head>/i)[0]))\n    var $body = $(parseHTML(data.match(/<body[^>]*>([\\s\\S.]*)<\\/body>/i)[0]))\n  } else {\n    var $head = $body = $(parseHTML(data))\n  }\n\n  // If response data is empty, return fast\n  if ($body.length === 0)\n    return obj\n\n  // If there's a <title> tag in the header, use it as\n  // the page's title.\n  obj.title = findAll($head, 'title').last().text()\n\n  if (options.fragment) {\n    // If they specified a fragment, look for it in the response\n    // and pull it out.\n    if (options.fragment === 'body') {\n      var $fragment = $body\n    } else {\n      var $fragment = findAll($body, options.fragment).first()\n    }\n\n    if ($fragment.length) {\n      obj.contents = options.fragment === 'body' ? $fragment : $fragment.contents()\n\n      // If there's no title, look for data-title and title attributes\n      // on the fragment\n      if (!obj.title)\n        obj.title = $fragment.attr('title') || $fragment.data('title')\n    }\n\n  } else if (!fullDocument) {\n    obj.contents = $body\n  }\n\n  // Clean up any <title> tags\n  if (obj.contents) {\n    // Remove any parent title elements\n    obj.contents = obj.contents.not(function() { return $(this).is('title') })\n\n    // Then scrub any titles from their descendants\n    obj.contents.find('title').remove()\n\n    // Gather all script[src] elements\n    obj.scripts = findAll(obj.contents, 'script').remove()\n    obj.contents = obj.contents.not(obj.scripts)\n  }\n\n  // Trim any whitespace off the title\n  if (obj.title) obj.title = $.trim(obj.title)\n\n  return obj\n}\n\n// Load an execute scripts using standard script request.\n//\n// Avoids jQuery's traditional $.getScript which does a XHR request and\n// globalEval.\n//\n// scripts - jQuery object of script Elements\n// context - jQuery object whose context is `document` and has a selector\n//\n// Returns nothing.\nfunction executeScriptTags(scripts, context) {\n  if (!scripts) return\n\n  var existingScripts = $('script[src]')\n\n  var cb = function (next) {\n    var src = this.src\n    var matchedScripts = existingScripts.filter(function () {\n      return this.src === src\n    })\n\n      if (matchedScripts.length) {\n          next()\n          return\n      }\n      if (this.src) {\n          var script = document.createElement('script')\n          var type = $(this).attr('type')\n          if (type) script.type = type\n          var done = function () {\n              script.onload = null;\n              script.onerror = null;\n              next()\n          }\n          script.onload = script.onerror = done\n          script.src = $(this).attr('src')\n          document.head.appendChild(script)\n      } else {\n          context.append(this)\n          next()\n      }\n  }\n    var i = 0;\n    var next = function () {\n        if (i >= scripts.length) {\n            return\n        }\n        var script = scripts[i]\n        i++\n        cb.call(script, next)\n    }\n    next()\n}\n\n// Internal: History DOM caching class.\nvar cacheMapping      = {}\nvar cacheForwardStack = []\nvar cacheBackStack    = []\n\n// Push previous state id and container contents into the history\n// cache. Should be called in conjunction with `pushState` to save the\n// previous container contents.\n//\n// id    - State ID Number\n// value - DOM Element to cache\n//\n// Returns nothing.\nfunction cachePush(id, value) {\n  cacheMapping[id] = value\n  cacheBackStack.push(id)\n\n  // Remove all entries in forward history stack after pushing a new page.\n  trimCacheStack(cacheForwardStack, 0)\n\n  // Trim back history stack to max cache length.\n  trimCacheStack(cacheBackStack, pjax.defaults.maxCacheLength)\n}\n\n// Shifts cache from directional history cache. Should be\n// called on `popstate` with the previous state id and container\n// contents.\n//\n// direction - \"forward\" or \"back\" String\n// id        - State ID Number\n// value     - DOM Element to cache\n//\n// Returns nothing.\nfunction cachePop(direction, id, value) {\n  var pushStack, popStack\n  cacheMapping[id] = value\n\n  if (direction === 'forward') {\n    pushStack = cacheBackStack\n    popStack  = cacheForwardStack\n  } else {\n    pushStack = cacheForwardStack\n    popStack  = cacheBackStack\n  }\n\n  pushStack.push(id)\n  if (id = popStack.pop())\n    delete cacheMapping[id]\n\n  // Trim whichever stack we just pushed to to max cache length.\n  trimCacheStack(pushStack, pjax.defaults.maxCacheLength)\n}\n\n// Trim a cache stack (either cacheBackStack or cacheForwardStack) to be no\n// longer than the specified length, deleting cached DOM elements as necessary.\n//\n// stack  - Array of state IDs\n// length - Maximum length to trim to\n//\n// Returns nothing.\nfunction trimCacheStack(stack, length) {\n  while (stack.length > length)\n    delete cacheMapping[stack.shift()]\n}\n\n// Public: Find version identifier for the initial page load.\n//\n// Returns String version or undefined.\nfunction findVersion() {\n  return $('meta').filter(function() {\n    var name = $(this).attr('http-equiv')\n    return name && name.toUpperCase() === 'X-PJAX-VERSION'\n  }).attr('content')\n}\n\n// Install pjax functions on $.pjax to enable pushState behavior.\n//\n// Does nothing if already enabled.\n//\n// Examples\n//\n//     $.pjax.enable()\n//\n// Returns nothing.\nfunction enable() {\n  $.fn.pjax = fnPjax\n  $.pjax = pjax\n  $.pjax.enable = $.noop\n  $.pjax.disable = disable\n  $.pjax.click = handleClick\n  $.pjax.submit = handleSubmit\n  $.pjax.reload = pjaxReload\n  $.pjax.defaults = {\n    timeout: 650,\n    push: true,\n    replace: false,\n    type: 'GET',\n    dataType: 'html',\n    scrollTo: 0,\n    maxCacheLength: 20,\n    version: findVersion\n  }\n  $(window).on('popstate.pjax', onPjaxPopstate)\n}\n\n// Disable pushState behavior.\n//\n// This is the case when a browser doesn't support pushState. It is\n// sometimes useful to disable pushState for debugging on a modern\n// browser.\n//\n// Examples\n//\n//     $.pjax.disable()\n//\n// Returns nothing.\nfunction disable() {\n  $.fn.pjax = function() { return this }\n  $.pjax = fallbackPjax\n  $.pjax.enable = enable\n  $.pjax.disable = $.noop\n  $.pjax.click = $.noop\n  $.pjax.submit = $.noop\n  $.pjax.reload = function() { window.location.reload() }\n\n  $(window).off('popstate.pjax', onPjaxPopstate)\n}\n\n\n// Add the state property to jQuery's event object so we can use it in\n// $(window).bind('popstate')\nif ( $.inArray('state', $.event.props) < 0 )\n  $.event.props.push('state')\n\n// Is pjax supported by this browser?\n$.support.pjax =\n  window.history && window.history.pushState && window.history.replaceState &&\n  // pushState isn't reliable on iOS until 5.\n  !navigator.userAgent.match(/((iPod|iPhone|iPad).+\\bOS\\s+[1-4]\\D|WebApps\\/.+CFNetwork)/)\n\n$.support.pjax ? enable() : disable()\n\n})(jQuery);\n"
  },
  {
    "path": "resources/assets/laravel-admin/laravel-admin.css",
    "content": "input.content {\n    min-height: 0 !important;\n    padding: 6px 12px !important;\n    margin: 0 !important;\n}\n\ninput.label:empty {\n    display: inherit !important;\n}\n\ninput.label {\n    display: inherit !important;\n    padding: 6px 12px !important;\n    font-size: 14px !important;\n    font-weight: inherit !important;\n    line-height: 1.42857143 !important;\n    color: #555 !important;\n    text-align: inherit !important;\n    white-space: inherit !important;\n    vertical-align: inherit !important;\n    border-radius: inherit !important;\n}\n\n.box-show {\n    border-radius: 0 !important;\n    box-shadow: none !important;\n}\n\na.editable-empty {\n    color: #3c8dbc;\n    border-bottom: none !important;\n}\n\n.form-group > label.asterisk:before {\n    content: \"* \";\n    color: red;\n}\n\n.mailbox-attachments li {\n    width: 300px !important;\n}\n\n.table-has-many .form-group {\n    margin-bottom: 0 !important;\n}\n\n\n.table-has-many label.control-label[for=inputError] {\n    position: absolute;\n    z-index: 100;\n    background-color: #fff;\n    border: 1px solid #dd4b39;\n    border-radius: 5px;\n    text-align: left;\n    top: 34px;\n    padding: 8px;\n    line-height: 1.2;\n}\n\n.table-has-many label.control-label[for=inputError]+br {\n    display: none;\n}\n\n#totop {\n    display: none;\n    position: fixed;\n    bottom: 40px;\n    right: 20px;\n    z-index: 99999;\n    outline: none;\n    background-color: rgb(34, 45, 50);\n    color: rgb(238, 238, 238);\n    cursor: pointer;\n    padding: 10px 15px;\n    border-radius: 4px;\n    opacity: 0.5;\n}\n\n#totop:hover {\n    opacity: 1;\n}\n\n.file-input .glyphicon-folder-open {\n    display: inline;\n}\n"
  },
  {
    "path": "resources/assets/laravel-admin/laravel-admin.js",
    "content": "$.fn.editable.defaults.params = function (params) {\n    params._token = LA.token;\n    params._editable = 1;\n    params._method = 'PUT';\n    return params;\n};\n\n$.fn.editable.defaults.error = function (data) {\n    var msg = '';\n    if (data.responseJSON.errors) {\n        $.each(data.responseJSON.errors, function (k, v) {\n            msg += v + \"\\n\";\n        });\n    }\n    return msg\n};\n\ntoastr.options = {\n    closeButton: true,\n    progressBar: true,\n    showMethod: 'slideDown',\n    timeOut: 4000\n};\n\n$.pjax.defaults.timeout = 5000;\n$.pjax.defaults.maxCacheLength = 0;\n$(document).pjax('a:not(a[target=\"_blank\"])', {\n    container: '#pjax-container'\n});\n\nNProgress.configure({parent: '#app'});\n\n$(document).on('pjax:timeout', function (event) {\n    event.preventDefault();\n})\n\n$(document).on('submit', 'form[pjax-container]', function (event) {\n    $.pjax.submit(event, '#pjax-container')\n});\n\n$(document).on(\"pjax:popstate\", function () {\n\n    $(document).one(\"pjax:end\", function (event) {\n        $(event.target).find(\"script[data-exec-on-popstate]\").each(function () {\n            $.globalEval(this.text || this.textContent || this.innerHTML || '');\n        });\n    });\n});\n\n$(document).on('pjax:send', function (xhr) {\n    if (xhr.relatedTarget && xhr.relatedTarget.tagName && xhr.relatedTarget.tagName.toLowerCase() === 'form') {\n        $submit_btn = $('form[pjax-container] :submit');\n        if ($submit_btn) {\n            $submit_btn.button('loading')\n        }\n    }\n    NProgress.start();\n});\n\n$(document).on('pjax:complete', function (xhr) {\n    if (xhr.relatedTarget && xhr.relatedTarget.tagName && xhr.relatedTarget.tagName.toLowerCase() === 'form') {\n        $submit_btn = $('form[pjax-container] :submit');\n        if ($submit_btn) {\n            $submit_btn.button('reset')\n        }\n    }\n    NProgress.done();\n    $.admin.grid.selects = {};\n});\n\n$(document).click(function () {\n    $('.sidebar-form .dropdown-menu').hide();\n});\n\n$(function () {\n    $('.sidebar-menu li:not(.treeview) > a').on('click', function () {\n        var $parent = $(this).parent().addClass('active');\n        $parent.siblings('.treeview.active').find('> a').trigger('click');\n        $parent.siblings().removeClass('active').find('li').removeClass('active');\n    });\n    var menu = $('.sidebar-menu li > a[href$=\"' + (location.pathname + location.search + location.hash) + '\"]').parent().addClass('active');\n    menu.parents('ul.treeview-menu').addClass('menu-open');\n    menu.parents('li.treeview').addClass('active');\n\n    $('[data-toggle=\"popover\"]').popover();\n\n    // Sidebar form autocomplete\n    $('.sidebar-form .autocomplete').on('keyup focus', function () {\n        var $menu = $('.sidebar-form .dropdown-menu');\n        var text = $(this).val();\n\n        if (text === '') {\n            $menu.hide();\n            return;\n        }\n\n        var regex = new RegExp(text, 'i');\n        var matched = false;\n\n        $menu.find('li').each(function () {\n            if (!regex.test($(this).find('a').text())) {\n                $(this).hide();\n            } else {\n                $(this).show();\n                matched = true;\n            }\n        });\n\n        if (matched) {\n            $menu.show();\n        }\n    }).click(function(event){\n        event.stopPropagation();\n    });\n\n    $('.sidebar-form .dropdown-menu li a').click(function (){\n        $('.sidebar-form .autocomplete').val($(this).text());\n    });\n});\n\n$(window).scroll(function() {\n    if (document.body.scrollTop > 100 || document.documentElement.scrollTop > 100) {\n        $('#totop').fadeIn(500);\n    } else {\n        $('#totop').fadeOut(500);\n    }\n});\n\n$('#totop').on('click', function (e) {\n    e.preventDefault();\n    $('html,body').animate({scrollTop: 0}, 500);\n});\n\n(function ($) {\n\n    var Grid = function () {\n        this.selects = {};\n    };\n\n    Grid.prototype.select = function (id) {\n        this.selects[id] = id;\n    };\n\n    Grid.prototype.unselect = function (id) {\n        delete this.selects[id];\n    };\n\n    Grid.prototype.selected = function () {\n        var rows = [];\n        $.each(this.selects, function (key, val) {\n            rows.push(key);\n        });\n\n        return rows;\n    };\n\n    $.fn.admin = LA;\n    $.admin = LA;\n    $.admin.swal = swal;\n    $.admin.toastr = toastr;\n    $.admin.grid = new Grid();\n\n    $.admin.reload = function () {\n        $.pjax.reload('#pjax-container');\n        $.admin.grid = new Grid();\n    };\n\n    $.admin.redirect = function (url) {\n        $.pjax({container:'#pjax-container', url: url });\n        $.admin.grid = new Grid();\n    };\n\n    $.admin.getToken = function () {\n        return $('meta[name=\"csrf-token\"]').attr('content');\n    };\n\n    $.admin.loadedScripts = [];\n\n    $.admin.loadScripts = function(arr) {\n        var _arr = $.map(arr, function(src) {\n\n            if ($.inArray(src, $.admin.loadedScripts)) {\n                return;\n            }\n\n            $.admin.loadedScripts.push(src);\n\n            return $.getScript(src);\n        });\n\n        _arr.push($.Deferred(function(deferred){\n            $(deferred.resolve);\n        }));\n\n        return $.when.apply($, _arr);\n    }\n\n})(jQuery);\n"
  },
  {
    "path": "resources/assets/nestable/jquery.nestable.js",
    "content": "/*!\n * Nestable jQuery Plugin - Copyright (c) 2012 David Bushell - http://dbushell.com/\n * Dual-licensed under the BSD or MIT licenses\n */\n;(function($, window, document, undefined)\n{\n    var hasTouch = 'ontouchstart' in document;\n\n    /**\n     * Detect CSS pointer-events property\n     * events are normally disabled on the dragging element to avoid conflicts\n     * https://github.com/ausi/Feature-detection-technique-for-pointer-events/blob/master/modernizr-pointerevents.js\n     */\n    var hasPointerEvents = (function()\n    {\n        var el    = document.createElement('div'),\n            docEl = document.documentElement;\n        if (!('pointerEvents' in el.style)) {\n            return false;\n        }\n        el.style.pointerEvents = 'auto';\n        el.style.pointerEvents = 'x';\n        docEl.appendChild(el);\n        var supports = window.getComputedStyle && window.getComputedStyle(el, '').pointerEvents === 'auto';\n        docEl.removeChild(el);\n        return !!supports;\n    })();\n\n    var defaults = {\n            listNodeName    : 'ol',\n            itemNodeName    : 'li',\n            rootClass       : 'dd',\n            listClass       : 'dd-list',\n            itemClass       : 'dd-item',\n            dragClass       : 'dd-dragel',\n            handleClass     : 'dd-handle',\n            collapsedClass  : 'dd-collapsed',\n            placeClass      : 'dd-placeholder',\n            noDragClass     : 'dd-nodrag',\n            emptyClass      : 'dd-empty',\n            expandBtnHTML   : '<button data-action=\"expand\" type=\"button\">Expand</button>',\n            collapseBtnHTML : '<button data-action=\"collapse\" type=\"button\">Collapse</button>',\n            group           : 0,\n            maxDepth        : 5,\n            threshold       : 20\n        };\n\n    function Plugin(element, options)\n    {\n        this.w  = $(document);\n        this.el = $(element);\n        this.options = $.extend({}, defaults, options);\n        this.init();\n    }\n\n    Plugin.prototype = {\n\n        init: function()\n        {\n            var list = this;\n\n            list.reset();\n\n            list.el.data('nestable-group', this.options.group);\n\n            list.placeEl = $('<div class=\"' + list.options.placeClass + '\"/>');\n\n            $.each(this.el.find(list.options.itemNodeName), function(k, el) {\n                list.setParent($(el));\n            });\n\n            list.el.on('click', 'button', function(e) {\n                if (list.dragEl) {\n                    return;\n                }\n                var target = $(e.currentTarget),\n                    action = target.data('action'),\n                    item   = target.parent(list.options.itemNodeName);\n                if (action === 'collapse') {\n                    list.collapseItem(item);\n                }\n                if (action === 'expand') {\n                    list.expandItem(item);\n                }\n            });\n\n            var onStartEvent = function(e)\n            {\n                var handle = $(e.target);\n                if (!handle.hasClass(list.options.handleClass)) {\n                    if (handle.closest('.' + list.options.noDragClass).length) {\n                        return;\n                    }\n                    handle = handle.closest('.' + list.options.handleClass);\n                }\n\n                if (!handle.length || list.dragEl) {\n                    return;\n                }\n\n                list.isTouch = /^touch/.test(e.type);\n                if (list.isTouch && e.touches.length !== 1) {\n                    return;\n                }\n\n                e.preventDefault();\n                list.dragStart(e.touches ? e.touches[0] : e);\n            };\n\n            var onMoveEvent = function(e)\n            {\n                if (list.dragEl) {\n                    e.preventDefault();\n                    list.dragMove(e.touches ? e.touches[0] : e);\n                }\n            };\n\n            var onEndEvent = function(e)\n            {\n                if (list.dragEl) {\n                    e.preventDefault();\n                    list.dragStop(e.touches ? e.touches[0] : e);\n                }\n            };\n\n            if (hasTouch) {\n                list.el[0].addEventListener('touchstart', onStartEvent, false);\n                window.addEventListener('touchmove', onMoveEvent, false);\n                window.addEventListener('touchend', onEndEvent, false);\n                window.addEventListener('touchcancel', onEndEvent, false);\n            }\n\n            list.el.on('mousedown', onStartEvent);\n            list.w.on('mousemove', onMoveEvent);\n            list.w.on('mouseup', onEndEvent);\n\n        },\n\n        serialize: function()\n        {\n            var data,\n                depth = 0,\n                list  = this;\n                step  = function(level, depth)\n                {\n                    var array = [ ],\n                        items = level.children(list.options.itemNodeName);\n                    items.each(function()\n                    {\n                        var li   = $(this),\n                            item = $.extend({}, li.data()),\n                            sub  = li.children(list.options.listNodeName);\n                        if (sub.length) {\n                            item.children = step(sub, depth + 1);\n                        }\n                        array.push(item);\n                    });\n                    return array;\n                };\n            data = step(list.el.find(list.options.listNodeName).first(), depth);\n            return data;\n        },\n\n        serialise: function()\n        {\n            return this.serialize();\n        },\n\n        reset: function()\n        {\n            this.mouse = {\n                offsetX   : 0,\n                offsetY   : 0,\n                startX    : 0,\n                startY    : 0,\n                lastX     : 0,\n                lastY     : 0,\n                nowX      : 0,\n                nowY      : 0,\n                distX     : 0,\n                distY     : 0,\n                dirAx     : 0,\n                dirX      : 0,\n                dirY      : 0,\n                lastDirX  : 0,\n                lastDirY  : 0,\n                distAxX   : 0,\n                distAxY   : 0\n            };\n            this.isTouch    = false;\n            this.moving     = false;\n            this.dragEl     = null;\n            this.dragRootEl = null;\n            this.dragDepth  = 0;\n            this.hasNewRoot = false;\n            this.pointEl    = null;\n        },\n\n        expandItem: function(li)\n        {\n            li.removeClass(this.options.collapsedClass);\n            li.children('[data-action=\"expand\"]').hide();\n            li.children('[data-action=\"collapse\"]').show();\n            li.children(this.options.listNodeName).show();\n        },\n\n        collapseItem: function(li)\n        {\n            var lists = li.children(this.options.listNodeName);\n            if (lists.length) {\n                li.addClass(this.options.collapsedClass);\n                li.children('[data-action=\"collapse\"]').hide();\n                li.children('[data-action=\"expand\"]').show();\n                li.children(this.options.listNodeName).hide();\n            }\n        },\n\n        expandAll: function()\n        {\n            var list = this;\n            list.el.find(list.options.itemNodeName).each(function() {\n                list.expandItem($(this));\n            });\n        },\n\n        collapseAll: function()\n        {\n            var list = this;\n            list.el.find(list.options.itemNodeName).each(function() {\n                list.collapseItem($(this));\n            });\n        },\n\n        setParent: function(li)\n        {\n            if (li.children(this.options.listNodeName).length) {\n                li.prepend($(this.options.expandBtnHTML));\n                li.prepend($(this.options.collapseBtnHTML));\n            }\n            li.children('[data-action=\"expand\"]').hide();\n        },\n\n        unsetParent: function(li)\n        {\n            li.removeClass(this.options.collapsedClass);\n            li.children('[data-action]').remove();\n            li.children(this.options.listNodeName).remove();\n        },\n\n        dragStart: function(e)\n        {\n            var mouse    = this.mouse,\n                target   = $(e.target),\n                dragItem = target.closest(this.options.itemNodeName);\n\n            this.placeEl.css('height', dragItem.height());\n\n            mouse.offsetX = e.offsetX !== undefined ? e.offsetX : e.pageX - target.offset().left;\n            mouse.offsetY = e.offsetY !== undefined ? e.offsetY : e.pageY - target.offset().top;\n            mouse.startX = mouse.lastX = e.pageX;\n            mouse.startY = mouse.lastY = e.pageY;\n\n            this.dragRootEl = this.el;\n\n            this.dragEl = $(document.createElement(this.options.listNodeName)).addClass(this.options.listClass + ' ' + this.options.dragClass);\n            this.dragEl.css('width', dragItem.width());\n\n            dragItem.after(this.placeEl);\n            dragItem[0].parentNode.removeChild(dragItem[0]);\n            dragItem.appendTo(this.dragEl);\n\n            $(document.body).append(this.dragEl);\n            this.dragEl.css({\n                'left' : e.pageX - mouse.offsetX,\n                'top'  : e.pageY - mouse.offsetY\n            });\n            // total depth of dragging item\n            var i, depth,\n                items = this.dragEl.find(this.options.itemNodeName);\n            for (i = 0; i < items.length; i++) {\n                depth = $(items[i]).parents(this.options.listNodeName).length;\n                if (depth > this.dragDepth) {\n                    this.dragDepth = depth;\n                }\n            }\n        },\n\n        dragStop: function(e)\n        {\n            var el = this.dragEl.children(this.options.itemNodeName).first();\n            el[0].parentNode.removeChild(el[0]);\n            this.placeEl.replaceWith(el);\n\n            this.dragEl.remove();\n            this.el.trigger('change');\n            if (this.hasNewRoot) {\n                this.dragRootEl.trigger('change');\n            }\n            this.reset();\n        },\n\n        dragMove: function(e)\n        {\n            var list, parent, prev, next, depth,\n                opt   = this.options,\n                mouse = this.mouse;\n\n            this.dragEl.css({\n                'left' : e.pageX - mouse.offsetX,\n                'top'  : e.pageY - mouse.offsetY\n            });\n\n            // mouse position last events\n            mouse.lastX = mouse.nowX;\n            mouse.lastY = mouse.nowY;\n            // mouse position this events\n            mouse.nowX  = e.pageX;\n            mouse.nowY  = e.pageY;\n            // distance mouse moved between events\n            mouse.distX = mouse.nowX - mouse.lastX;\n            mouse.distY = mouse.nowY - mouse.lastY;\n            // direction mouse was moving\n            mouse.lastDirX = mouse.dirX;\n            mouse.lastDirY = mouse.dirY;\n            // direction mouse is now moving (on both axis)\n            mouse.dirX = mouse.distX === 0 ? 0 : mouse.distX > 0 ? 1 : -1;\n            mouse.dirY = mouse.distY === 0 ? 0 : mouse.distY > 0 ? 1 : -1;\n            // axis mouse is now moving on\n            var newAx   = Math.abs(mouse.distX) > Math.abs(mouse.distY) ? 1 : 0;\n\n            // do nothing on first move\n            if (!mouse.moving) {\n                mouse.dirAx  = newAx;\n                mouse.moving = true;\n                return;\n            }\n\n            // calc distance moved on this axis (and direction)\n            if (mouse.dirAx !== newAx) {\n                mouse.distAxX = 0;\n                mouse.distAxY = 0;\n            } else {\n                mouse.distAxX += Math.abs(mouse.distX);\n                if (mouse.dirX !== 0 && mouse.dirX !== mouse.lastDirX) {\n                    mouse.distAxX = 0;\n                }\n                mouse.distAxY += Math.abs(mouse.distY);\n                if (mouse.dirY !== 0 && mouse.dirY !== mouse.lastDirY) {\n                    mouse.distAxY = 0;\n                }\n            }\n            mouse.dirAx = newAx;\n\n            /**\n             * move horizontal\n             */\n            if (mouse.dirAx && mouse.distAxX >= opt.threshold) {\n                // reset move distance on x-axis for new phase\n                mouse.distAxX = 0;\n                prev = this.placeEl.prev(opt.itemNodeName);\n                // increase horizontal level if previous sibling exists and is not collapsed\n                if (mouse.distX > 0 && prev.length && !prev.hasClass(opt.collapsedClass)) {\n                    // cannot increase level when item above is collapsed\n                    list = prev.find(opt.listNodeName).last();\n                    // check if depth limit has reached\n                    depth = this.placeEl.parents(opt.listNodeName).length;\n                    if (depth + this.dragDepth <= opt.maxDepth) {\n                        // create new sub-level if one doesn't exist\n                        if (!list.length) {\n                            list = $('<' + opt.listNodeName + '/>').addClass(opt.listClass);\n                            list.append(this.placeEl);\n                            prev.append(list);\n                            this.setParent(prev);\n                        } else {\n                            // else append to next level up\n                            list = prev.children(opt.listNodeName).last();\n                            list.append(this.placeEl);\n                        }\n                    }\n                }\n                // decrease horizontal level\n                if (mouse.distX < 0) {\n                    // we can't decrease a level if an item preceeds the current one\n                    next = this.placeEl.next(opt.itemNodeName);\n                    if (!next.length) {\n                        parent = this.placeEl.parent();\n                        this.placeEl.closest(opt.itemNodeName).after(this.placeEl);\n                        if (!parent.children().length) {\n                            this.unsetParent(parent.parent());\n                        }\n                    }\n                }\n            }\n\n            var isEmpty = false;\n\n            // find list item under cursor\n            if (!hasPointerEvents) {\n                this.dragEl[0].style.visibility = 'hidden';\n            }\n            this.pointEl = $(document.elementFromPoint(e.pageX - document.body.scrollLeft, e.pageY - (window.pageYOffset || document.documentElement.scrollTop)));\n            if (!hasPointerEvents) {\n                this.dragEl[0].style.visibility = 'visible';\n            }\n            if (this.pointEl.hasClass(opt.handleClass)) {\n                this.pointEl = this.pointEl.parent(opt.itemNodeName);\n            }\n            if (this.pointEl.hasClass(opt.emptyClass)) {\n                isEmpty = true;\n            }\n            else if (!this.pointEl.length || !this.pointEl.hasClass(opt.itemClass)) {\n                return;\n            }\n\n            // find parent list of item under cursor\n            var pointElRoot = this.pointEl.closest('.' + opt.rootClass),\n                isNewRoot   = this.dragRootEl.data('nestable-id') !== pointElRoot.data('nestable-id');\n\n            /**\n             * move vertical\n             */\n            if (!mouse.dirAx || isNewRoot || isEmpty) {\n                // check if groups match if dragging over new root\n                if (isNewRoot && opt.group !== pointElRoot.data('nestable-group')) {\n                    return;\n                }\n                // check depth limit\n                depth = this.dragDepth - 1 + this.pointEl.parents(opt.listNodeName).length;\n                if (depth > opt.maxDepth) {\n                    return;\n                }\n                var before = e.pageY < (this.pointEl.offset().top + this.pointEl.height() / 2);\n                    parent = this.placeEl.parent();\n                // if empty create new list to replace empty placeholder\n                if (isEmpty) {\n                    list = $(document.createElement(opt.listNodeName)).addClass(opt.listClass);\n                    list.append(this.placeEl);\n                    this.pointEl.replaceWith(list);\n                }\n                else if (before) {\n                    this.pointEl.before(this.placeEl);\n                }\n                else {\n                    this.pointEl.after(this.placeEl);\n                }\n                if (!parent.children().length) {\n                    this.unsetParent(parent.parent());\n                }\n                if (!this.dragRootEl.find(opt.itemNodeName).length) {\n                    this.dragRootEl.append('<div class=\"' + opt.emptyClass + '\"/>');\n                }\n                // parent root list has changed\n                if (isNewRoot) {\n                    this.dragRootEl = pointElRoot;\n                    this.hasNewRoot = this.el[0] !== this.dragRootEl[0];\n                }\n            }\n        }\n\n    };\n\n    $.fn.nestable = function(params)\n    {\n        var lists  = this,\n            retval = this;\n\n        lists.each(function()\n        {\n            var plugin = $(this).data(\"nestable\");\n\n            if (!plugin) {\n                $(this).data(\"nestable\", new Plugin(this, params));\n                $(this).data(\"nestable-id\", new Date().getTime());\n            } else {\n                if (typeof params === 'string' && typeof plugin[params] === 'function') {\n                    retval = plugin[params]();\n                }\n            }\n        });\n\n        return retval || lists;\n    };\n\n})(window.jQuery || window.Zepto, window, document);\n"
  },
  {
    "path": "resources/assets/nestable/nestable.css",
    "content": ".dd { position: relative; display: block; margin: 10px; padding: 0; list-style: none; font-size: 13px; line-height: 20px; }\n\n.dd-list { display: block; position: relative; margin: 0; padding: 0; list-style: none; }\n.dd-list .dd-list { padding-left: 30px; }\n.dd-collapsed .dd-list { display: none; }\n\n.dd-item,\n.dd-empty,\n.dd-placeholder { display: block; position: relative; margin: 0; padding: 0;}\n\n.dd-handle {\n    display: block;\n\n    margin: 1px 0;\n    padding: 8px 10px;\n    color: #333;\n    text-decoration: none;\n    border: 1px solid #ddd;\n    background: #fff;\n}\n.dd-handle:hover { color: #2ea8e5; background: #fff; }\n\n.dd-item > button { display: block; position: relative; cursor: pointer; float: left; width: 25px; height: 20px; margin: 5px 0; padding: 0; text-indent: 100%; white-space: nowrap; overflow: hidden; border: 0; background: transparent; font-size: 12px; line-height: 1; text-align: center; font-weight: bold; }\n.dd-item > button:before { content: '+'; display: block; position: absolute; width: 100%; text-align: center; text-indent: 0; }\n.dd-item > button[data-action=\"collapse\"]:before { content: '-'; }\n\n.dd-placeholder { margin: 5px 0; padding: 0; min-height: 30px; background: #f2fbff; border: 1px dashed #b6bcbf; box-sizing: border-box; -moz-box-sizing: border-box; }\n\n.dd-dragel { position: absolute; pointer-events: none; z-index: 9999; }\n.dd-dragel > .dd-item .dd-handle { margin-top: 0; }\n.dd-dragel .dd-handle {\n-webkit-box-shadow: 2px 4px 6px 0 rgba(0,0,0,.1);\nbox-shadow: 2px 4px 6px 0 rgba(0,0,0,.1);\n}"
  },
  {
    "path": "resources/assets/nprogress/nprogress.css",
    "content": "/* Make clicks pass-through */\n#nprogress {\n  pointer-events: none;\n}\n\n#nprogress .bar {\n  background: #dd441f;\n\n  position: fixed;\n  z-index: 1031;\n  top: 0;\n  left: 0;\n\n  width: 100%;\n  height: 2px;\n}\n\n/* Fancy blur effect */\n#nprogress .peg {\n  display: block;\n  position: absolute;\n  right: 0px;\n  width: 100px;\n  height: 100%;\n  box-shadow: 0 0 10px #29d, 0 0 5px #29d;\n  opacity: 1.0;\n\n  -webkit-transform: rotate(3deg) translate(0px, -4px);\n      -ms-transform: rotate(3deg) translate(0px, -4px);\n          transform: rotate(3deg) translate(0px, -4px);\n}\n\n/* Remove these to get rid of the spinner */\n#nprogress .spinner {\n  display: block;\n  position: fixed;\n  z-index: 1031;\n  top: 15px;\n  right: 15px;\n}\n\n#nprogress .spinner-icon {\n  width: 18px;\n  height: 18px;\n  box-sizing: border-box;\n\n  border: solid 2px transparent;\n  border-top-color: #29d;\n  border-left-color: #29d;\n  border-radius: 50%;\n\n  -webkit-animation: nprogress-spinner 400ms linear infinite;\n          animation: nprogress-spinner 400ms linear infinite;\n}\n\n.nprogress-custom-parent {\n  overflow: hidden;\n  position: relative;\n}\n\n.nprogress-custom-parent #nprogress .spinner,\n.nprogress-custom-parent #nprogress .bar {\n  position: absolute;\n}\n\n@-webkit-keyframes nprogress-spinner {\n  0%   { -webkit-transform: rotate(0deg); }\n  100% { -webkit-transform: rotate(360deg); }\n}\n@keyframes nprogress-spinner {\n  0%   { transform: rotate(0deg); }\n  100% { transform: rotate(360deg); }\n}\n\n"
  },
  {
    "path": "resources/assets/nprogress/nprogress.js",
    "content": "/* NProgress, (c) 2013, 2014 Rico Sta. Cruz - http://ricostacruz.com/nprogress\n * @license MIT */\n\n;(function(root, factory) {\n\n  if (typeof define === 'function' && define.amd) {\n    define(factory);\n  } else if (typeof exports === 'object') {\n    module.exports = factory();\n  } else {\n    root.NProgress = factory();\n  }\n\n})(this, function() {\n  var NProgress = {};\n\n  NProgress.version = '0.2.0';\n\n  var Settings = NProgress.settings = {\n    minimum: 0.08,\n    easing: 'ease',\n    positionUsing: '',\n    speed: 200,\n    trickle: true,\n    trickleRate: 0.02,\n    trickleSpeed: 800,\n    showSpinner: true,\n    barSelector: '[role=\"bar\"]',\n    spinnerSelector: '[role=\"spinner\"]',\n    parent: 'body',\n    template: '<div class=\"bar\" role=\"bar\"><div class=\"peg\"></div></div><div class=\"spinner\" role=\"spinner\"><div class=\"spinner-icon\"></div></div>'\n  };\n\n  /**\n   * Updates configuration.\n   *\n   *     NProgress.configure({\n   *       minimum: 0.1\n   *     });\n   */\n  NProgress.configure = function(options) {\n    var key, value;\n    for (key in options) {\n      value = options[key];\n      if (value !== undefined && options.hasOwnProperty(key)) Settings[key] = value;\n    }\n\n    return this;\n  };\n\n  /**\n   * Last number.\n   */\n\n  NProgress.status = null;\n\n  /**\n   * Sets the progress bar status, where `n` is a number from `0.0` to `1.0`.\n   *\n   *     NProgress.set(0.4);\n   *     NProgress.set(1.0);\n   */\n\n  NProgress.set = function(n) {\n    var started = NProgress.isStarted();\n\n    n = clamp(n, Settings.minimum, 1);\n    NProgress.status = (n === 1 ? null : n);\n\n    var progress = NProgress.render(!started),\n        bar      = progress.querySelector(Settings.barSelector),\n        speed    = Settings.speed,\n        ease     = Settings.easing;\n\n    progress.offsetWidth; /* Repaint */\n\n    queue(function(next) {\n      // Set positionUsing if it hasn't already been set\n      if (Settings.positionUsing === '') Settings.positionUsing = NProgress.getPositioningCSS();\n\n      // Add transition\n      css(bar, barPositionCSS(n, speed, ease));\n\n      if (n === 1) {\n        // Fade out\n        css(progress, { \n          transition: 'none', \n          opacity: 1 \n        });\n        progress.offsetWidth; /* Repaint */\n\n        setTimeout(function() {\n          css(progress, { \n            transition: 'all ' + speed + 'ms linear', \n            opacity: 0 \n          });\n          setTimeout(function() {\n            NProgress.remove();\n            next();\n          }, speed);\n        }, speed);\n      } else {\n        setTimeout(next, speed);\n      }\n    });\n\n    return this;\n  };\n\n  NProgress.isStarted = function() {\n    return typeof NProgress.status === 'number';\n  };\n\n  /**\n   * Shows the progress bar.\n   * This is the same as setting the status to 0%, except that it doesn't go backwards.\n   *\n   *     NProgress.start();\n   *\n   */\n  NProgress.start = function() {\n    if (!NProgress.status) NProgress.set(0);\n\n    var work = function() {\n      setTimeout(function() {\n        if (!NProgress.status) return;\n        NProgress.trickle();\n        work();\n      }, Settings.trickleSpeed);\n    };\n\n    if (Settings.trickle) work();\n\n    return this;\n  };\n\n  /**\n   * Hides the progress bar.\n   * This is the *sort of* the same as setting the status to 100%, with the\n   * difference being `done()` makes some placebo effect of some realistic motion.\n   *\n   *     NProgress.done();\n   *\n   * If `true` is passed, it will show the progress bar even if its hidden.\n   *\n   *     NProgress.done(true);\n   */\n\n  NProgress.done = function(force) {\n    if (!force && !NProgress.status) return this;\n\n    return NProgress.inc(0.3 + 0.5 * Math.random()).set(1);\n  };\n\n  /**\n   * Increments by a random amount.\n   */\n\n  NProgress.inc = function(amount) {\n    var n = NProgress.status;\n\n    if (!n) {\n      return NProgress.start();\n    } else {\n      if (typeof amount !== 'number') {\n        amount = (1 - n) * clamp(Math.random() * n, 0.1, 0.95);\n      }\n\n      n = clamp(n + amount, 0, 0.994);\n      return NProgress.set(n);\n    }\n  };\n\n  NProgress.trickle = function() {\n    return NProgress.inc(Math.random() * Settings.trickleRate);\n  };\n\n  /**\n   * Waits for all supplied jQuery promises and\n   * increases the progress as the promises resolve.\n   *\n   * @param $promise jQUery Promise\n   */\n  (function() {\n    var initial = 0, current = 0;\n\n    NProgress.promise = function($promise) {\n      if (!$promise || $promise.state() === \"resolved\") {\n        return this;\n      }\n\n      if (current === 0) {\n        NProgress.start();\n      }\n\n      initial++;\n      current++;\n\n      $promise.always(function() {\n        current--;\n        if (current === 0) {\n            initial = 0;\n            NProgress.done();\n        } else {\n            NProgress.set((initial - current) / initial);\n        }\n      });\n\n      return this;\n    };\n\n  })();\n\n  /**\n   * (Internal) renders the progress bar markup based on the `template`\n   * setting.\n   */\n\n  NProgress.render = function(fromStart) {\n    if (NProgress.isRendered()) return document.getElementById('nprogress');\n\n    addClass(document.documentElement, 'nprogress-busy');\n    \n    var progress = document.createElement('div');\n    progress.id = 'nprogress';\n    progress.innerHTML = Settings.template;\n\n    var bar      = progress.querySelector(Settings.barSelector),\n        perc     = fromStart ? '-100' : toBarPerc(NProgress.status || 0),\n        parent   = document.querySelector(Settings.parent),\n        spinner;\n    \n    css(bar, {\n      transition: 'all 0 linear',\n      transform: 'translate3d(' + perc + '%,0,0)'\n    });\n\n    if (!Settings.showSpinner) {\n      spinner = progress.querySelector(Settings.spinnerSelector);\n      spinner && removeElement(spinner);\n    }\n\n    if (parent != document.body) {\n      addClass(parent, 'nprogress-custom-parent');\n    }\n\n    parent.appendChild(progress);\n    return progress;\n  };\n\n  /**\n   * Removes the element. Opposite of render().\n   */\n\n  NProgress.remove = function() {\n    removeClass(document.documentElement, 'nprogress-busy');\n    removeClass(document.querySelector(Settings.parent), 'nprogress-custom-parent');\n    var progress = document.getElementById('nprogress');\n    progress && removeElement(progress);\n  };\n\n  /**\n   * Checks if the progress bar is rendered.\n   */\n\n  NProgress.isRendered = function() {\n    return !!document.getElementById('nprogress');\n  };\n\n  /**\n   * Determine which positioning CSS rule to use.\n   */\n\n  NProgress.getPositioningCSS = function() {\n    // Sniff on document.body.style\n    var bodyStyle = document.body.style;\n\n    // Sniff prefixes\n    var vendorPrefix = ('WebkitTransform' in bodyStyle) ? 'Webkit' :\n                       ('MozTransform' in bodyStyle) ? 'Moz' :\n                       ('msTransform' in bodyStyle) ? 'ms' :\n                       ('OTransform' in bodyStyle) ? 'O' : '';\n\n    if (vendorPrefix + 'Perspective' in bodyStyle) {\n      // Modern browsers with 3D support, e.g. Webkit, IE10\n      return 'translate3d';\n    } else if (vendorPrefix + 'Transform' in bodyStyle) {\n      // Browsers without 3D support, e.g. IE9\n      return 'translate';\n    } else {\n      // Browsers without translate() support, e.g. IE7-8\n      return 'margin';\n    }\n  };\n\n  /**\n   * Helpers\n   */\n\n  function clamp(n, min, max) {\n    if (n < min) return min;\n    if (n > max) return max;\n    return n;\n  }\n\n  /**\n   * (Internal) converts a percentage (`0..1`) to a bar translateX\n   * percentage (`-100%..0%`).\n   */\n\n  function toBarPerc(n) {\n    return (-1 + n) * 100;\n  }\n\n\n  /**\n   * (Internal) returns the correct CSS for changing the bar's\n   * position given an n percentage, and speed and ease from Settings\n   */\n\n  function barPositionCSS(n, speed, ease) {\n    var barCSS;\n\n    if (Settings.positionUsing === 'translate3d') {\n      barCSS = { transform: 'translate3d('+toBarPerc(n)+'%,0,0)' };\n    } else if (Settings.positionUsing === 'translate') {\n      barCSS = { transform: 'translate('+toBarPerc(n)+'%,0)' };\n    } else {\n      barCSS = { 'margin-left': toBarPerc(n)+'%' };\n    }\n\n    barCSS.transition = 'all '+speed+'ms '+ease;\n\n    return barCSS;\n  }\n\n  /**\n   * (Internal) Queues a function to be executed.\n   */\n\n  var queue = (function() {\n    var pending = [];\n    \n    function next() {\n      var fn = pending.shift();\n      if (fn) {\n        fn(next);\n      }\n    }\n\n    return function(fn) {\n      pending.push(fn);\n      if (pending.length == 1) next();\n    };\n  })();\n\n  /**\n   * (Internal) Applies css properties to an element, similar to the jQuery \n   * css method.\n   *\n   * While this helper does assist with vendor prefixed property names, it \n   * does not perform any manipulation of values prior to setting styles.\n   */\n\n  var css = (function() {\n    var cssPrefixes = [ 'Webkit', 'O', 'Moz', 'ms' ],\n        cssProps    = {};\n\n    function camelCase(string) {\n      return string.replace(/^-ms-/, 'ms-').replace(/-([\\da-z])/gi, function(match, letter) {\n        return letter.toUpperCase();\n      });\n    }\n\n    function getVendorProp(name) {\n      var style = document.body.style;\n      if (name in style) return name;\n\n      var i = cssPrefixes.length,\n          capName = name.charAt(0).toUpperCase() + name.slice(1),\n          vendorName;\n      while (i--) {\n        vendorName = cssPrefixes[i] + capName;\n        if (vendorName in style) return vendorName;\n      }\n\n      return name;\n    }\n\n    function getStyleProp(name) {\n      name = camelCase(name);\n      return cssProps[name] || (cssProps[name] = getVendorProp(name));\n    }\n\n    function applyCss(element, prop, value) {\n      prop = getStyleProp(prop);\n      element.style[prop] = value;\n    }\n\n    return function(element, properties) {\n      var args = arguments,\n          prop, \n          value;\n\n      if (args.length == 2) {\n        for (prop in properties) {\n          value = properties[prop];\n          if (value !== undefined && properties.hasOwnProperty(prop)) applyCss(element, prop, value);\n        }\n      } else {\n        applyCss(element, args[1], args[2]);\n      }\n    }\n  })();\n\n  /**\n   * (Internal) Determines if an element or space separated list of class names contains a class name.\n   */\n\n  function hasClass(element, name) {\n    var list = typeof element == 'string' ? element : classList(element);\n    return list.indexOf(' ' + name + ' ') >= 0;\n  }\n\n  /**\n   * (Internal) Adds a class to an element.\n   */\n\n  function addClass(element, name) {\n    var oldList = classList(element),\n        newList = oldList + name;\n\n    if (hasClass(oldList, name)) return; \n\n    // Trim the opening space.\n    element.className = newList.substring(1);\n  }\n\n  /**\n   * (Internal) Removes a class from an element.\n   */\n\n  function removeClass(element, name) {\n    var oldList = classList(element),\n        newList;\n\n    if (!hasClass(element, name)) return;\n\n    // Replace the class name.\n    newList = oldList.replace(' ' + name + ' ', ' ');\n\n    // Trim the opening and closing spaces.\n    element.className = newList.substring(1, newList.length - 1);\n  }\n\n  /**\n   * (Internal) Gets a space separated list of the class names on the element. \n   * The list is wrapped with a single space on each end to facilitate finding \n   * matches within the list.\n   */\n\n  function classList(element) {\n    return (' ' + (element.className || '') + ' ').replace(/\\s+/gi, ' ');\n  }\n\n  /**\n   * (Internal) Removes an element from the DOM.\n   */\n\n  function removeElement(element) {\n    element && element.parentNode && element.parentNode.removeChild(element);\n  }\n\n  return NProgress;\n});\n\n"
  },
  {
    "path": "resources/assets/number-input/bootstrap-number-input.js",
    "content": "/* ========================================================================\n * bootstrap-spin - v1.0\n * https://github.com/wpic/bootstrap-spin\n * ========================================================================\n * Copyright 2014 WPIC, Hamed Abdollahpour\n *\n * ========================================================================\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n * ========================================================================\n */\n\n(function($) {\n\n    $.fn.bootstrapNumber = function(options) {\n\n        var settings = $.extend({\n            upClass: 'default',\n            downClass: 'default',\n            center: true\n        }, options);\n\n        return this.each(function(e) {\n            var self = $(this);\n            var clone = self.clone();\n\n            var min = self.attr('min');\n            var max = self.attr('max');\n\n            function setText(n) {\n                n = isNaN(n) ? 0 : n;\n                if ((min && n < min)) {\n                    n = min;\n                } else if (max && n > max) {\n                    n = max;\n                }\n                clone.val(n);\n            }\n\n            var group = $(\"<div class='input-group'></div>\");\n            var down = $(\"<button type='button'>-</button>\").attr('class', 'btn btn-' + settings.downClass).click(function() {\n                setText(parseInt(clone.val(), 10) - 1);\n                clone.focus().trigger('change');\n            });\n            var up = $(\"<button type='button'>+</button>\").attr('class', 'btn btn-' + settings.upClass).click(function() {\n                setText(parseInt(clone.val(), 10) + 1);\n                clone.focus().trigger('change');\n            });\n            $(\"<span class='input-group-btn'></span>\").append(down).appendTo(group);\n            clone.appendTo(group);\n            if (clone) {\n                clone.css('text-align', 'center');\n            }\n            $(\"<span class='input-group-btn'></span>\").append(up).appendTo(group);\n\n            // remove spins from original\n            clone.prop('type', 'text').keydown(function(e) {\n                if ($.inArray(e.keyCode, [46, 8, 9, 27, 13, 110, 190]) !== -1 || (e.keyCode == 65 && e.ctrlKey === true) || (e.keyCode >= 35 && e.keyCode <= 39)) {\n                    return;\n                }\n                if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {\n                    e.preventDefault();\n                }\n            }).keyup(function(event) {\n                var n = clone.val().match(/\\-?\\d+/) || [0];\n                setText(n[0]);\n                clone.trigger('change');\n            }).blur(function(e) {\n                var c = String.fromCharCode(e.which);\n                var n = parseInt(clone.val() + c, 10);\n                setText(n);\n                clone.trigger('change');\n            });\n\n\n            self.replaceWith(group);\n        });\n    };\n}(jQuery));\n"
  },
  {
    "path": "resources/assets/sweetalert2/dist/sweetalert2.css",
    "content": "@-webkit-keyframes swal2-show {\n  0% {\n    -webkit-transform: scale(0.7);\n            transform: scale(0.7); }\n  45% {\n    -webkit-transform: scale(1.05);\n            transform: scale(1.05); }\n  80% {\n    -webkit-transform: scale(0.95);\n            transform: scale(0.95); }\n  100% {\n    -webkit-transform: scale(1);\n            transform: scale(1); } }\n\n@keyframes swal2-show {\n  0% {\n    -webkit-transform: scale(0.7);\n            transform: scale(0.7); }\n  45% {\n    -webkit-transform: scale(1.05);\n            transform: scale(1.05); }\n  80% {\n    -webkit-transform: scale(0.95);\n            transform: scale(0.95); }\n  100% {\n    -webkit-transform: scale(1);\n            transform: scale(1); } }\n\n@-webkit-keyframes swal2-hide {\n  0% {\n    -webkit-transform: scale(1);\n            transform: scale(1);\n    opacity: 1; }\n  100% {\n    -webkit-transform: scale(0.5);\n            transform: scale(0.5);\n    opacity: 0; } }\n\n@keyframes swal2-hide {\n  0% {\n    -webkit-transform: scale(1);\n            transform: scale(1);\n    opacity: 1; }\n  100% {\n    -webkit-transform: scale(0.5);\n            transform: scale(0.5);\n    opacity: 0; } }\n\n@-webkit-keyframes swal2-animate-success-line-tip {\n  0% {\n    top: 1.1875em;\n    left: .0625em;\n    width: 0; }\n  54% {\n    top: 1.0625em;\n    left: .125em;\n    width: 0; }\n  70% {\n    top: 2.1875em;\n    left: -.375em;\n    width: 3.125em; }\n  84% {\n    top: 3em;\n    left: 1.3125em;\n    width: 1.0625em; }\n  100% {\n    top: 2.8125em;\n    left: .875em;\n    width: 1.5625em; } }\n\n@keyframes swal2-animate-success-line-tip {\n  0% {\n    top: 1.1875em;\n    left: .0625em;\n    width: 0; }\n  54% {\n    top: 1.0625em;\n    left: .125em;\n    width: 0; }\n  70% {\n    top: 2.1875em;\n    left: -.375em;\n    width: 3.125em; }\n  84% {\n    top: 3em;\n    left: 1.3125em;\n    width: 1.0625em; }\n  100% {\n    top: 2.8125em;\n    left: .875em;\n    width: 1.5625em; } }\n\n@-webkit-keyframes swal2-animate-success-line-long {\n  0% {\n    top: 3.375em;\n    right: 2.875em;\n    width: 0; }\n  65% {\n    top: 3.375em;\n    right: 2.875em;\n    width: 0; }\n  84% {\n    top: 2.1875em;\n    right: 0;\n    width: 3.4375em; }\n  100% {\n    top: 2.375em;\n    right: .5em;\n    width: 2.9375em; } }\n\n@keyframes swal2-animate-success-line-long {\n  0% {\n    top: 3.375em;\n    right: 2.875em;\n    width: 0; }\n  65% {\n    top: 3.375em;\n    right: 2.875em;\n    width: 0; }\n  84% {\n    top: 2.1875em;\n    right: 0;\n    width: 3.4375em; }\n  100% {\n    top: 2.375em;\n    right: .5em;\n    width: 2.9375em; } }\n\n@-webkit-keyframes swal2-rotate-success-circular-line {\n  0% {\n    -webkit-transform: rotate(-45deg);\n            transform: rotate(-45deg); }\n  5% {\n    -webkit-transform: rotate(-45deg);\n            transform: rotate(-45deg); }\n  12% {\n    -webkit-transform: rotate(-405deg);\n            transform: rotate(-405deg); }\n  100% {\n    -webkit-transform: rotate(-405deg);\n            transform: rotate(-405deg); } }\n\n@keyframes swal2-rotate-success-circular-line {\n  0% {\n    -webkit-transform: rotate(-45deg);\n            transform: rotate(-45deg); }\n  5% {\n    -webkit-transform: rotate(-45deg);\n            transform: rotate(-45deg); }\n  12% {\n    -webkit-transform: rotate(-405deg);\n            transform: rotate(-405deg); }\n  100% {\n    -webkit-transform: rotate(-405deg);\n            transform: rotate(-405deg); } }\n\n@-webkit-keyframes swal2-animate-error-x-mark {\n  0% {\n    margin-top: 1.625em;\n    -webkit-transform: scale(0.4);\n            transform: scale(0.4);\n    opacity: 0; }\n  50% {\n    margin-top: 1.625em;\n    -webkit-transform: scale(0.4);\n            transform: scale(0.4);\n    opacity: 0; }\n  80% {\n    margin-top: -.375em;\n    -webkit-transform: scale(1.15);\n            transform: scale(1.15); }\n  100% {\n    margin-top: 0;\n    -webkit-transform: scale(1);\n            transform: scale(1);\n    opacity: 1; } }\n\n@keyframes swal2-animate-error-x-mark {\n  0% {\n    margin-top: 1.625em;\n    -webkit-transform: scale(0.4);\n            transform: scale(0.4);\n    opacity: 0; }\n  50% {\n    margin-top: 1.625em;\n    -webkit-transform: scale(0.4);\n            transform: scale(0.4);\n    opacity: 0; }\n  80% {\n    margin-top: -.375em;\n    -webkit-transform: scale(1.15);\n            transform: scale(1.15); }\n  100% {\n    margin-top: 0;\n    -webkit-transform: scale(1);\n            transform: scale(1);\n    opacity: 1; } }\n\n@-webkit-keyframes swal2-animate-error-icon {\n  0% {\n    -webkit-transform: rotateX(100deg);\n            transform: rotateX(100deg);\n    opacity: 0; }\n  100% {\n    -webkit-transform: rotateX(0deg);\n            transform: rotateX(0deg);\n    opacity: 1; } }\n\n@keyframes swal2-animate-error-icon {\n  0% {\n    -webkit-transform: rotateX(100deg);\n            transform: rotateX(100deg);\n    opacity: 0; }\n  100% {\n    -webkit-transform: rotateX(0deg);\n            transform: rotateX(0deg);\n    opacity: 1; } }\n\nbody.swal2-toast-shown .swal2-container {\n  position: fixed;\n  background-color: transparent; }\n  body.swal2-toast-shown .swal2-container.swal2-shown {\n    background-color: transparent; }\n  body.swal2-toast-shown .swal2-container.swal2-top {\n    top: 0;\n    right: auto;\n    bottom: auto;\n    left: 50%;\n    -webkit-transform: translateX(-50%);\n            transform: translateX(-50%); }\n  body.swal2-toast-shown .swal2-container.swal2-top-end, body.swal2-toast-shown .swal2-container.swal2-top-right {\n    top: 0;\n    right: 0;\n    bottom: auto;\n    left: auto; }\n  body.swal2-toast-shown .swal2-container.swal2-top-start, body.swal2-toast-shown .swal2-container.swal2-top-left {\n    top: 0;\n    right: auto;\n    bottom: auto;\n    left: 0; }\n  body.swal2-toast-shown .swal2-container.swal2-center-start, body.swal2-toast-shown .swal2-container.swal2-center-left {\n    top: 50%;\n    right: auto;\n    bottom: auto;\n    left: 0;\n    -webkit-transform: translateY(-50%);\n            transform: translateY(-50%); }\n  body.swal2-toast-shown .swal2-container.swal2-center {\n    top: 50%;\n    right: auto;\n    bottom: auto;\n    left: 50%;\n    -webkit-transform: translate(-50%, -50%);\n            transform: translate(-50%, -50%); }\n  body.swal2-toast-shown .swal2-container.swal2-center-end, body.swal2-toast-shown .swal2-container.swal2-center-right {\n    top: 50%;\n    right: 0;\n    bottom: auto;\n    left: auto;\n    -webkit-transform: translateY(-50%);\n            transform: translateY(-50%); }\n  body.swal2-toast-shown .swal2-container.swal2-bottom-start, body.swal2-toast-shown .swal2-container.swal2-bottom-left {\n    top: auto;\n    right: auto;\n    bottom: 0;\n    left: 0; }\n  body.swal2-toast-shown .swal2-container.swal2-bottom {\n    top: auto;\n    right: auto;\n    bottom: 0;\n    left: 50%;\n    -webkit-transform: translateX(-50%);\n            transform: translateX(-50%); }\n  body.swal2-toast-shown .swal2-container.swal2-bottom-end, body.swal2-toast-shown .swal2-container.swal2-bottom-right {\n    top: auto;\n    right: 0;\n    bottom: 0;\n    left: auto; }\n\nbody.swal2-toast-column .swal2-toast {\n  flex-direction: column;\n  align-items: stretch; }\n  body.swal2-toast-column .swal2-toast .swal2-actions {\n    flex: 1;\n    align-self: stretch;\n    height: 2.2em;\n    margin-top: .3125em; }\n  body.swal2-toast-column .swal2-toast .swal2-loading {\n    justify-content: center; }\n  body.swal2-toast-column .swal2-toast .swal2-input {\n    height: 2em;\n    margin: .3125em auto;\n    font-size: 1em; }\n  body.swal2-toast-column .swal2-toast .swal2-validationerror {\n    font-size: 1em; }\n\n.swal2-popup.swal2-toast {\n  flex-direction: row;\n  align-items: center;\n  width: auto;\n  padding: 0.625em;\n  box-shadow: 0 0 0.625em #d9d9d9;\n  overflow-y: hidden; }\n  .swal2-popup.swal2-toast .swal2-header {\n    flex-direction: row; }\n  .swal2-popup.swal2-toast .swal2-title {\n    flex-grow: 1;\n    justify-content: flex-start;\n    margin: 0 .6em;\n    font-size: 1em; }\n  .swal2-popup.swal2-toast .swal2-footer {\n    margin: 0.5em 0 0;\n    padding: 0.5em 0 0;\n    font-size: 0.8em; }\n  .swal2-popup.swal2-toast .swal2-close {\n    position: initial;\n    width: 0.8em;\n    height: 0.8em;\n    line-height: 0.8; }\n  .swal2-popup.swal2-toast .swal2-content {\n    justify-content: flex-start;\n    font-size: 1em; }\n  .swal2-popup.swal2-toast .swal2-icon {\n    width: 2em;\n    min-width: 2em;\n    height: 2em;\n    margin: 0; }\n    .swal2-popup.swal2-toast .swal2-icon-text {\n      font-size: 2em;\n      font-weight: bold;\n      line-height: 1em; }\n    .swal2-popup.swal2-toast .swal2-icon.swal2-success .swal2-success-ring {\n      width: 2em;\n      height: 2em; }\n    .swal2-popup.swal2-toast .swal2-icon.swal2-error [class^='swal2-x-mark-line'] {\n      top: .875em;\n      width: 1.375em; }\n      .swal2-popup.swal2-toast .swal2-icon.swal2-error [class^='swal2-x-mark-line'][class$='left'] {\n        left: .3125em; }\n      .swal2-popup.swal2-toast .swal2-icon.swal2-error [class^='swal2-x-mark-line'][class$='right'] {\n        right: .3125em; }\n  .swal2-popup.swal2-toast .swal2-actions {\n    height: auto;\n    margin: 0 .3125em; }\n  .swal2-popup.swal2-toast .swal2-styled {\n    margin: 0 .3125em;\n    padding: .3125em .625em;\n    font-size: 1em; }\n    .swal2-popup.swal2-toast .swal2-styled:focus {\n      box-shadow: 0 0 0 0.0625em #fff, 0 0 0 0.125em rgba(50, 100, 150, 0.4); }\n  .swal2-popup.swal2-toast .swal2-success {\n    border-color: #a5dc86; }\n    .swal2-popup.swal2-toast .swal2-success [class^='swal2-success-circular-line'] {\n      position: absolute;\n      width: 2em;\n      height: 2.8125em;\n      -webkit-transform: rotate(45deg);\n              transform: rotate(45deg);\n      border-radius: 50%; }\n      .swal2-popup.swal2-toast .swal2-success [class^='swal2-success-circular-line'][class$='left'] {\n        top: -.25em;\n        left: -.9375em;\n        -webkit-transform: rotate(-45deg);\n                transform: rotate(-45deg);\n        -webkit-transform-origin: 2em 2em;\n                transform-origin: 2em 2em;\n        border-radius: 4em 0 0 4em; }\n      .swal2-popup.swal2-toast .swal2-success [class^='swal2-success-circular-line'][class$='right'] {\n        top: -.25em;\n        left: .9375em;\n        -webkit-transform-origin: 0 2em;\n                transform-origin: 0 2em;\n        border-radius: 0 4em 4em 0; }\n    .swal2-popup.swal2-toast .swal2-success .swal2-success-ring {\n      width: 2em;\n      height: 2em; }\n    .swal2-popup.swal2-toast .swal2-success .swal2-success-fix {\n      top: 0;\n      left: .4375em;\n      width: .4375em;\n      height: 2.6875em; }\n    .swal2-popup.swal2-toast .swal2-success [class^='swal2-success-line'] {\n      height: .3125em; }\n      .swal2-popup.swal2-toast .swal2-success [class^='swal2-success-line'][class$='tip'] {\n        top: 1.125em;\n        left: .1875em;\n        width: .75em; }\n      .swal2-popup.swal2-toast .swal2-success [class^='swal2-success-line'][class$='long'] {\n        top: .9375em;\n        right: .1875em;\n        width: 1.375em; }\n  .swal2-popup.swal2-toast.swal2-show {\n    -webkit-animation: showSweetToast .5s;\n            animation: showSweetToast .5s; }\n  .swal2-popup.swal2-toast.swal2-hide {\n    -webkit-animation: hideSweetToast .2s forwards;\n            animation: hideSweetToast .2s forwards; }\n  .swal2-popup.swal2-toast .swal2-animate-success-icon .swal2-success-line-tip {\n    -webkit-animation: animate-toast-success-tip .75s;\n            animation: animate-toast-success-tip .75s; }\n  .swal2-popup.swal2-toast .swal2-animate-success-icon .swal2-success-line-long {\n    -webkit-animation: animate-toast-success-long .75s;\n            animation: animate-toast-success-long .75s; }\n\n@-webkit-keyframes showSweetToast {\n  0% {\n    -webkit-transform: translateY(-0.625em) rotateZ(2deg);\n            transform: translateY(-0.625em) rotateZ(2deg);\n    opacity: 0; }\n  33% {\n    -webkit-transform: translateY(0) rotateZ(-2deg);\n            transform: translateY(0) rotateZ(-2deg);\n    opacity: .5; }\n  66% {\n    -webkit-transform: translateY(0.3125em) rotateZ(2deg);\n            transform: translateY(0.3125em) rotateZ(2deg);\n    opacity: .7; }\n  100% {\n    -webkit-transform: translateY(0) rotateZ(0);\n            transform: translateY(0) rotateZ(0);\n    opacity: 1; } }\n\n@keyframes showSweetToast {\n  0% {\n    -webkit-transform: translateY(-0.625em) rotateZ(2deg);\n            transform: translateY(-0.625em) rotateZ(2deg);\n    opacity: 0; }\n  33% {\n    -webkit-transform: translateY(0) rotateZ(-2deg);\n            transform: translateY(0) rotateZ(-2deg);\n    opacity: .5; }\n  66% {\n    -webkit-transform: translateY(0.3125em) rotateZ(2deg);\n            transform: translateY(0.3125em) rotateZ(2deg);\n    opacity: .7; }\n  100% {\n    -webkit-transform: translateY(0) rotateZ(0);\n            transform: translateY(0) rotateZ(0);\n    opacity: 1; } }\n\n@-webkit-keyframes hideSweetToast {\n  0% {\n    opacity: 1; }\n  33% {\n    opacity: .5; }\n  100% {\n    -webkit-transform: rotateZ(1deg);\n            transform: rotateZ(1deg);\n    opacity: 0; } }\n\n@keyframes hideSweetToast {\n  0% {\n    opacity: 1; }\n  33% {\n    opacity: .5; }\n  100% {\n    -webkit-transform: rotateZ(1deg);\n            transform: rotateZ(1deg);\n    opacity: 0; } }\n\n@-webkit-keyframes animate-toast-success-tip {\n  0% {\n    top: .5625em;\n    left: .0625em;\n    width: 0; }\n  54% {\n    top: .125em;\n    left: .125em;\n    width: 0; }\n  70% {\n    top: .625em;\n    left: -.25em;\n    width: 1.625em; }\n  84% {\n    top: 1.0625em;\n    left: .75em;\n    width: .5em; }\n  100% {\n    top: 1.125em;\n    left: .1875em;\n    width: .75em; } }\n\n@keyframes animate-toast-success-tip {\n  0% {\n    top: .5625em;\n    left: .0625em;\n    width: 0; }\n  54% {\n    top: .125em;\n    left: .125em;\n    width: 0; }\n  70% {\n    top: .625em;\n    left: -.25em;\n    width: 1.625em; }\n  84% {\n    top: 1.0625em;\n    left: .75em;\n    width: .5em; }\n  100% {\n    top: 1.125em;\n    left: .1875em;\n    width: .75em; } }\n\n@-webkit-keyframes animate-toast-success-long {\n  0% {\n    top: 1.625em;\n    right: 1.375em;\n    width: 0; }\n  65% {\n    top: 1.25em;\n    right: .9375em;\n    width: 0; }\n  84% {\n    top: .9375em;\n    right: 0;\n    width: 1.125em; }\n  100% {\n    top: .9375em;\n    right: .1875em;\n    width: 1.375em; } }\n\n@keyframes animate-toast-success-long {\n  0% {\n    top: 1.625em;\n    right: 1.375em;\n    width: 0; }\n  65% {\n    top: 1.25em;\n    right: .9375em;\n    width: 0; }\n  84% {\n    top: .9375em;\n    right: 0;\n    width: 1.125em; }\n  100% {\n    top: .9375em;\n    right: .1875em;\n    width: 1.375em; } }\n\nbody.swal2-shown:not(.swal2-no-backdrop):not(.swal2-toast-shown) {\n  overflow-y: hidden; }\n\nbody.swal2-height-auto {\n  height: auto !important; }\n\nbody.swal2-no-backdrop .swal2-shown {\n  top: auto;\n  right: auto;\n  bottom: auto;\n  left: auto;\n  background-color: transparent; }\n  body.swal2-no-backdrop .swal2-shown > .swal2-modal {\n    box-shadow: 0 0 10px rgba(0, 0, 0, 0.4); }\n  body.swal2-no-backdrop .swal2-shown.swal2-top {\n    top: 0;\n    left: 50%;\n    -webkit-transform: translateX(-50%);\n            transform: translateX(-50%); }\n  body.swal2-no-backdrop .swal2-shown.swal2-top-start, body.swal2-no-backdrop .swal2-shown.swal2-top-left {\n    top: 0;\n    left: 0; }\n  body.swal2-no-backdrop .swal2-shown.swal2-top-end, body.swal2-no-backdrop .swal2-shown.swal2-top-right {\n    top: 0;\n    right: 0; }\n  body.swal2-no-backdrop .swal2-shown.swal2-center {\n    top: 50%;\n    left: 50%;\n    -webkit-transform: translate(-50%, -50%);\n            transform: translate(-50%, -50%); }\n  body.swal2-no-backdrop .swal2-shown.swal2-center-start, body.swal2-no-backdrop .swal2-shown.swal2-center-left {\n    top: 50%;\n    left: 0;\n    -webkit-transform: translateY(-50%);\n            transform: translateY(-50%); }\n  body.swal2-no-backdrop .swal2-shown.swal2-center-end, body.swal2-no-backdrop .swal2-shown.swal2-center-right {\n    top: 50%;\n    right: 0;\n    -webkit-transform: translateY(-50%);\n            transform: translateY(-50%); }\n  body.swal2-no-backdrop .swal2-shown.swal2-bottom {\n    bottom: 0;\n    left: 50%;\n    -webkit-transform: translateX(-50%);\n            transform: translateX(-50%); }\n  body.swal2-no-backdrop .swal2-shown.swal2-bottom-start, body.swal2-no-backdrop .swal2-shown.swal2-bottom-left {\n    bottom: 0;\n    left: 0; }\n  body.swal2-no-backdrop .swal2-shown.swal2-bottom-end, body.swal2-no-backdrop .swal2-shown.swal2-bottom-right {\n    right: 0;\n    bottom: 0; }\n\n.swal2-container {\n  display: flex;\n  position: fixed;\n  top: 0;\n  right: 0;\n  bottom: 0;\n  left: 0;\n  flex-direction: row;\n  align-items: center;\n  justify-content: center;\n  padding: 10px;\n  background-color: transparent;\n  z-index: 1060;\n  overflow-x: hidden;\n  -webkit-overflow-scrolling: touch; }\n  .swal2-container.swal2-top {\n    align-items: flex-start; }\n  .swal2-container.swal2-top-start, .swal2-container.swal2-top-left {\n    align-items: flex-start;\n    justify-content: flex-start; }\n  .swal2-container.swal2-top-end, .swal2-container.swal2-top-right {\n    align-items: flex-start;\n    justify-content: flex-end; }\n  .swal2-container.swal2-center {\n    align-items: center; }\n  .swal2-container.swal2-center-start, .swal2-container.swal2-center-left {\n    align-items: center;\n    justify-content: flex-start; }\n  .swal2-container.swal2-center-end, .swal2-container.swal2-center-right {\n    align-items: center;\n    justify-content: flex-end; }\n  .swal2-container.swal2-bottom {\n    align-items: flex-end; }\n  .swal2-container.swal2-bottom-start, .swal2-container.swal2-bottom-left {\n    align-items: flex-end;\n    justify-content: flex-start; }\n  .swal2-container.swal2-bottom-end, .swal2-container.swal2-bottom-right {\n    align-items: flex-end;\n    justify-content: flex-end; }\n  .swal2-container.swal2-grow-fullscreen > .swal2-modal {\n    display: flex !important;\n    flex: 1;\n    align-self: stretch;\n    justify-content: center; }\n  .swal2-container.swal2-grow-row > .swal2-modal {\n    display: flex !important;\n    flex: 1;\n    align-content: center;\n    justify-content: center; }\n  .swal2-container.swal2-grow-column {\n    flex: 1;\n    flex-direction: column; }\n    .swal2-container.swal2-grow-column.swal2-top, .swal2-container.swal2-grow-column.swal2-center, .swal2-container.swal2-grow-column.swal2-bottom {\n      align-items: center; }\n    .swal2-container.swal2-grow-column.swal2-top-start, .swal2-container.swal2-grow-column.swal2-center-start, .swal2-container.swal2-grow-column.swal2-bottom-start, .swal2-container.swal2-grow-column.swal2-top-left, .swal2-container.swal2-grow-column.swal2-center-left, .swal2-container.swal2-grow-column.swal2-bottom-left {\n      align-items: flex-start; }\n    .swal2-container.swal2-grow-column.swal2-top-end, .swal2-container.swal2-grow-column.swal2-center-end, .swal2-container.swal2-grow-column.swal2-bottom-end, .swal2-container.swal2-grow-column.swal2-top-right, .swal2-container.swal2-grow-column.swal2-center-right, .swal2-container.swal2-grow-column.swal2-bottom-right {\n      align-items: flex-end; }\n    .swal2-container.swal2-grow-column > .swal2-modal {\n      display: flex !important;\n      flex: 1;\n      align-content: center;\n      justify-content: center; }\n  .swal2-container:not(.swal2-top):not(.swal2-top-start):not(.swal2-top-end):not(.swal2-top-left):not(.swal2-top-right):not(.swal2-center-start):not(.swal2-center-end):not(.swal2-center-left):not(.swal2-center-right):not(.swal2-bottom):not(.swal2-bottom-start):not(.swal2-bottom-end):not(.swal2-bottom-left):not(.swal2-bottom-right):not(.swal2-grow-fullscreen) > .swal2-modal {\n    margin: auto; }\n  @media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {\n    .swal2-container .swal2-modal {\n      margin: 0 !important; } }\n  .swal2-container.swal2-fade {\n    transition: background-color .1s; }\n  .swal2-container.swal2-shown {\n    background-color: rgba(0, 0, 0, 0.4); }\n\n.swal2-popup {\n  display: none;\n  position: relative;\n  flex-direction: column;\n  justify-content: center;\n  width: 32em;\n  max-width: 100%;\n  padding: 1.25em;\n  border-radius: 0.3125em;\n  background: #fff;\n  font-family: inherit;\n  font-size: 1rem;\n  box-sizing: border-box; }\n  .swal2-popup:focus {\n    outline: none; }\n  .swal2-popup.swal2-loading {\n    overflow-y: hidden; }\n  .swal2-popup .swal2-header {\n    display: flex;\n    flex-direction: column;\n    align-items: center; }\n  .swal2-popup .swal2-title {\n    display: block;\n    position: relative;\n    max-width: 100%;\n    margin: 0 0 0.4em;\n    padding: 0;\n    color: #595959;\n    font-size: 1.875em;\n    font-weight: 600;\n    text-align: center;\n    text-transform: none;\n    word-wrap: break-word; }\n  .swal2-popup .swal2-actions {\n    align-items: center;\n    justify-content: center;\n    margin: 1.25em auto 0;\n    z-index: 1; }\n    .swal2-popup .swal2-actions:not(.swal2-loading) .swal2-styled[disabled] {\n      opacity: .4; }\n    .swal2-popup .swal2-actions:not(.swal2-loading) .swal2-styled:hover {\n      background-image: linear-gradient(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.1)); }\n    .swal2-popup .swal2-actions:not(.swal2-loading) .swal2-styled:active {\n      background-image: linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.2)); }\n    .swal2-popup .swal2-actions.swal2-loading .swal2-styled.swal2-confirm {\n      width: 2.5em;\n      height: 2.5em;\n      margin: .46875em;\n      padding: 0;\n      border: .25em solid transparent;\n      border-radius: 100%;\n      border-color: transparent;\n      background-color: transparent !important;\n      color: transparent;\n      cursor: default;\n      box-sizing: border-box;\n      -webkit-animation: swal2-rotate-loading 1.5s linear 0s infinite normal;\n              animation: swal2-rotate-loading 1.5s linear 0s infinite normal;\n      -webkit-user-select: none;\n         -moz-user-select: none;\n          -ms-user-select: none;\n              user-select: none; }\n    .swal2-popup .swal2-actions.swal2-loading .swal2-styled.swal2-cancel {\n      margin-right: 30px;\n      margin-left: 30px; }\n    .swal2-popup .swal2-actions.swal2-loading :not(.swal2-styled).swal2-confirm::after {\n      display: inline-block;\n      width: 15px;\n      height: 15px;\n      margin-left: 5px;\n      border: 3px solid #999999;\n      border-radius: 50%;\n      border-right-color: transparent;\n      box-shadow: 1px 1px 1px #fff;\n      content: '';\n      -webkit-animation: swal2-rotate-loading 1.5s linear 0s infinite normal;\n              animation: swal2-rotate-loading 1.5s linear 0s infinite normal; }\n  .swal2-popup .swal2-styled {\n    margin: 0 .3125em;\n    padding: .625em 2em;\n    font-weight: 500;\n    box-shadow: none; }\n    .swal2-popup .swal2-styled:not([disabled]) {\n      cursor: pointer; }\n    .swal2-popup .swal2-styled.swal2-confirm {\n      border: 0;\n      border-radius: 0.25em;\n      background: initial;\n      background-color: #3085d6;\n      color: #fff;\n      font-size: 1.0625em; }\n    .swal2-popup .swal2-styled.swal2-cancel {\n      border: 0;\n      border-radius: 0.25em;\n      background: initial;\n      background-color: #aaa;\n      color: #fff;\n      font-size: 1.0625em; }\n    .swal2-popup .swal2-styled:focus {\n      outline: none;\n      box-shadow: 0 0 0 2px #fff, 0 0 0 4px rgba(50, 100, 150, 0.4); }\n    .swal2-popup .swal2-styled::-moz-focus-inner {\n      border: 0; }\n  .swal2-popup .swal2-footer {\n    justify-content: center;\n    margin: 1.25em 0 0;\n    padding: 1em 0 0;\n    border-top: 1px solid #eee;\n    color: #545454;\n    font-size: 1em; }\n  .swal2-popup .swal2-image {\n    max-width: 100%;\n    margin: 1.25em auto; }\n  .swal2-popup .swal2-close {\n    position: absolute;\n    top: 0;\n    right: 0;\n    justify-content: center;\n    width: 1.2em;\n    height: 1.2em;\n    padding: 0;\n    transition: color 0.1s ease-out;\n    border: none;\n    border-radius: 0;\n    background: transparent;\n    color: #cccccc;\n    font-family: serif;\n    font-size: 2.5em;\n    line-height: 1.2;\n    cursor: pointer;\n    overflow: hidden; }\n    .swal2-popup .swal2-close:hover {\n      -webkit-transform: none;\n              transform: none;\n      color: #f27474; }\n  .swal2-popup > .swal2-input,\n  .swal2-popup > .swal2-file,\n  .swal2-popup > .swal2-textarea,\n  .swal2-popup > .swal2-select,\n  .swal2-popup > .swal2-radio,\n  .swal2-popup > .swal2-checkbox {\n    display: none; }\n  .swal2-popup .swal2-content {\n    justify-content: center;\n    margin: 0;\n    padding: 0;\n    color: #545454;\n    font-size: 1.125em;\n    font-weight: 300;\n    line-height: normal;\n    z-index: 1;\n    word-wrap: break-word; }\n  .swal2-popup #swal2-content {\n    text-align: center; }\n  .swal2-popup .swal2-input,\n  .swal2-popup .swal2-file,\n  .swal2-popup .swal2-textarea,\n  .swal2-popup .swal2-select,\n  .swal2-popup .swal2-radio,\n  .swal2-popup .swal2-checkbox {\n    margin: 1em auto; }\n  .swal2-popup .swal2-input,\n  .swal2-popup .swal2-file,\n  .swal2-popup .swal2-textarea {\n    width: 100%;\n    transition: border-color .3s, box-shadow .3s;\n    border: 1px solid #d9d9d9;\n    border-radius: 0.1875em;\n    font-size: 1.125em;\n    box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.06);\n    box-sizing: border-box; }\n    .swal2-popup .swal2-input.swal2-inputerror,\n    .swal2-popup .swal2-file.swal2-inputerror,\n    .swal2-popup .swal2-textarea.swal2-inputerror {\n      border-color: #f27474 !important;\n      box-shadow: 0 0 2px #f27474 !important; }\n    .swal2-popup .swal2-input:focus,\n    .swal2-popup .swal2-file:focus,\n    .swal2-popup .swal2-textarea:focus {\n      border: 1px solid #b4dbed;\n      outline: none;\n      box-shadow: 0 0 3px #c4e6f5; }\n    .swal2-popup .swal2-input::-webkit-input-placeholder,\n    .swal2-popup .swal2-file::-webkit-input-placeholder,\n    .swal2-popup .swal2-textarea::-webkit-input-placeholder {\n      color: #cccccc; }\n    .swal2-popup .swal2-input:-ms-input-placeholder,\n    .swal2-popup .swal2-file:-ms-input-placeholder,\n    .swal2-popup .swal2-textarea:-ms-input-placeholder {\n      color: #cccccc; }\n    .swal2-popup .swal2-input::-ms-input-placeholder,\n    .swal2-popup .swal2-file::-ms-input-placeholder,\n    .swal2-popup .swal2-textarea::-ms-input-placeholder {\n      color: #cccccc; }\n    .swal2-popup .swal2-input::placeholder,\n    .swal2-popup .swal2-file::placeholder,\n    .swal2-popup .swal2-textarea::placeholder {\n      color: #cccccc; }\n  .swal2-popup .swal2-range input {\n    width: 80%; }\n  .swal2-popup .swal2-range output {\n    width: 20%;\n    font-weight: 600;\n    text-align: center; }\n  .swal2-popup .swal2-range input,\n  .swal2-popup .swal2-range output {\n    height: 2.625em;\n    margin: 1em auto;\n    padding: 0;\n    font-size: 1.125em;\n    line-height: 2.625em; }\n  .swal2-popup .swal2-input {\n    height: 2.625em;\n    padding: 0.75em; }\n    .swal2-popup .swal2-input[type='number'] {\n      max-width: 10em; }\n  .swal2-popup .swal2-file {\n    font-size: 1.125em; }\n  .swal2-popup .swal2-textarea {\n    height: 6.75em;\n    padding: 0.75em; }\n  .swal2-popup .swal2-select {\n    min-width: 50%;\n    max-width: 100%;\n    padding: .375em .625em;\n    color: #545454;\n    font-size: 1.125em; }\n  .swal2-popup .swal2-radio,\n  .swal2-popup .swal2-checkbox {\n    align-items: center;\n    justify-content: center; }\n    .swal2-popup .swal2-radio label,\n    .swal2-popup .swal2-checkbox label {\n      margin: 0 .6em;\n      font-size: 1.125em; }\n    .swal2-popup .swal2-radio input,\n    .swal2-popup .swal2-checkbox input {\n      margin: 0 .4em; }\n  .swal2-popup .swal2-validationerror {\n    display: none;\n    align-items: center;\n    justify-content: center;\n    padding: 0.625em;\n    background: #f0f0f0;\n    color: #666666;\n    font-size: 1em;\n    font-weight: 300;\n    overflow: hidden; }\n    .swal2-popup .swal2-validationerror::before {\n      display: inline-block;\n      width: 1.5em;\n      min-width: 1.5em;\n      height: 1.5em;\n      margin: 0 .625em;\n      border-radius: 50%;\n      background-color: #f27474;\n      color: #fff;\n      font-weight: 600;\n      line-height: 1.5em;\n      text-align: center;\n      content: '!';\n      zoom: normal; }\n\n@supports (-ms-accelerator: true) {\n  .swal2-range input {\n    width: 100% !important; }\n  .swal2-range output {\n    display: none; } }\n\n@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {\n  .swal2-range input {\n    width: 100% !important; }\n  .swal2-range output {\n    display: none; } }\n\n@-moz-document url-prefix() {\n  .swal2-close:focus {\n    outline: 2px solid rgba(50, 100, 150, 0.4); } }\n\n.swal2-icon {\n  position: relative;\n  justify-content: center;\n  width: 5em;\n  height: 5em;\n  margin: 1.25em auto 1.875em;\n  border: .25em solid transparent;\n  border-radius: 50%;\n  line-height: 5em;\n  cursor: default;\n  box-sizing: content-box;\n  -webkit-user-select: none;\n     -moz-user-select: none;\n      -ms-user-select: none;\n          user-select: none;\n  zoom: normal; }\n  .swal2-icon-text {\n    font-size: 3.75em; }\n  .swal2-icon.swal2-error {\n    border-color: #f27474; }\n    .swal2-icon.swal2-error .swal2-x-mark {\n      position: relative;\n      flex-grow: 1; }\n    .swal2-icon.swal2-error [class^='swal2-x-mark-line'] {\n      display: block;\n      position: absolute;\n      top: 2.3125em;\n      width: 2.9375em;\n      height: .3125em;\n      border-radius: .125em;\n      background-color: #f27474; }\n      .swal2-icon.swal2-error [class^='swal2-x-mark-line'][class$='left'] {\n        left: 1.0625em;\n        -webkit-transform: rotate(45deg);\n                transform: rotate(45deg); }\n      .swal2-icon.swal2-error [class^='swal2-x-mark-line'][class$='right'] {\n        right: 1em;\n        -webkit-transform: rotate(-45deg);\n                transform: rotate(-45deg); }\n  .swal2-icon.swal2-warning {\n    border-color: #facea8;\n    color: #f8bb86; }\n  .swal2-icon.swal2-info {\n    border-color: #9de0f6;\n    color: #3fc3ee; }\n  .swal2-icon.swal2-question {\n    border-color: #c9dae1;\n    color: #87adbd; }\n  .swal2-icon.swal2-success {\n    border-color: #a5dc86; }\n    .swal2-icon.swal2-success [class^='swal2-success-circular-line'] {\n      position: absolute;\n      width: 3.75em;\n      height: 7.5em;\n      -webkit-transform: rotate(45deg);\n              transform: rotate(45deg);\n      border-radius: 50%; }\n      .swal2-icon.swal2-success [class^='swal2-success-circular-line'][class$='left'] {\n        top: -.4375em;\n        left: -2.0635em;\n        -webkit-transform: rotate(-45deg);\n                transform: rotate(-45deg);\n        -webkit-transform-origin: 3.75em 3.75em;\n                transform-origin: 3.75em 3.75em;\n        border-radius: 7.5em 0 0 7.5em; }\n      .swal2-icon.swal2-success [class^='swal2-success-circular-line'][class$='right'] {\n        top: -.6875em;\n        left: 1.875em;\n        -webkit-transform: rotate(-45deg);\n                transform: rotate(-45deg);\n        -webkit-transform-origin: 0 3.75em;\n                transform-origin: 0 3.75em;\n        border-radius: 0 7.5em 7.5em 0; }\n    .swal2-icon.swal2-success .swal2-success-ring {\n      position: absolute;\n      top: -.25em;\n      left: -.25em;\n      width: 100%;\n      height: 100%;\n      border: 0.25em solid rgba(165, 220, 134, 0.3);\n      border-radius: 50%;\n      z-index: 2;\n      box-sizing: content-box; }\n    .swal2-icon.swal2-success .swal2-success-fix {\n      position: absolute;\n      top: .5em;\n      left: 1.625em;\n      width: .4375em;\n      height: 5.625em;\n      -webkit-transform: rotate(-45deg);\n              transform: rotate(-45deg);\n      z-index: 1; }\n    .swal2-icon.swal2-success [class^='swal2-success-line'] {\n      display: block;\n      position: absolute;\n      height: .3125em;\n      border-radius: .125em;\n      background-color: #a5dc86;\n      z-index: 2; }\n      .swal2-icon.swal2-success [class^='swal2-success-line'][class$='tip'] {\n        top: 2.875em;\n        left: .875em;\n        width: 1.5625em;\n        -webkit-transform: rotate(45deg);\n                transform: rotate(45deg); }\n      .swal2-icon.swal2-success [class^='swal2-success-line'][class$='long'] {\n        top: 2.375em;\n        right: .5em;\n        width: 2.9375em;\n        -webkit-transform: rotate(-45deg);\n                transform: rotate(-45deg); }\n\n.swal2-progresssteps {\n  align-items: center;\n  margin: 0 0 1.25em;\n  padding: 0;\n  font-weight: 600; }\n  .swal2-progresssteps li {\n    display: inline-block;\n    position: relative; }\n  .swal2-progresssteps .swal2-progresscircle {\n    width: 2em;\n    height: 2em;\n    border-radius: 2em;\n    background: #3085d6;\n    color: #fff;\n    line-height: 2em;\n    text-align: center;\n    z-index: 20; }\n    .swal2-progresssteps .swal2-progresscircle:first-child {\n      margin-left: 0; }\n    .swal2-progresssteps .swal2-progresscircle:last-child {\n      margin-right: 0; }\n    .swal2-progresssteps .swal2-progresscircle.swal2-activeprogressstep {\n      background: #3085d6; }\n      .swal2-progresssteps .swal2-progresscircle.swal2-activeprogressstep ~ .swal2-progresscircle {\n        background: #add8e6; }\n      .swal2-progresssteps .swal2-progresscircle.swal2-activeprogressstep ~ .swal2-progressline {\n        background: #add8e6; }\n  .swal2-progresssteps .swal2-progressline {\n    width: 2.5em;\n    height: .4em;\n    margin: 0 -1px;\n    background: #3085d6;\n    z-index: 10; }\n\n[class^='swal2'] {\n  -webkit-tap-highlight-color: transparent; }\n\n.swal2-show {\n  -webkit-animation: swal2-show 0.3s;\n          animation: swal2-show 0.3s; }\n  .swal2-show.swal2-noanimation {\n    -webkit-animation: none;\n            animation: none; }\n\n.swal2-hide {\n  -webkit-animation: swal2-hide 0.15s forwards;\n          animation: swal2-hide 0.15s forwards; }\n  .swal2-hide.swal2-noanimation {\n    -webkit-animation: none;\n            animation: none; }\n\n[dir='rtl'] .swal2-close {\n  right: auto;\n  left: 0; }\n\n.swal2-animate-success-icon .swal2-success-line-tip {\n  -webkit-animation: swal2-animate-success-line-tip 0.75s;\n          animation: swal2-animate-success-line-tip 0.75s; }\n\n.swal2-animate-success-icon .swal2-success-line-long {\n  -webkit-animation: swal2-animate-success-line-long 0.75s;\n          animation: swal2-animate-success-line-long 0.75s; }\n\n.swal2-animate-success-icon .swal2-success-circular-line-right {\n  -webkit-animation: swal2-rotate-success-circular-line 4.25s ease-in;\n          animation: swal2-rotate-success-circular-line 4.25s ease-in; }\n\n.swal2-animate-error-icon {\n  -webkit-animation: swal2-animate-error-icon 0.5s;\n          animation: swal2-animate-error-icon 0.5s; }\n  .swal2-animate-error-icon .swal2-x-mark {\n    -webkit-animation: swal2-animate-error-x-mark 0.5s;\n            animation: swal2-animate-error-x-mark 0.5s; }\n\n@-webkit-keyframes swal2-rotate-loading {\n  0% {\n    -webkit-transform: rotate(0deg);\n            transform: rotate(0deg); }\n  100% {\n    -webkit-transform: rotate(360deg);\n            transform: rotate(360deg); } }\n\n@keyframes swal2-rotate-loading {\n  0% {\n    -webkit-transform: rotate(0deg);\n            transform: rotate(0deg); }\n  100% {\n    -webkit-transform: rotate(360deg);\n            transform: rotate(360deg); } }\n"
  },
  {
    "path": "resources/lang/ar/admin.php",
    "content": "<?php\n\nreturn [\n    'online'                => 'متصل',\n    'login'                 => 'تسجيل الدخول',\n    'logout'                => 'تسجيل الخروج',\n    'setting'               => 'الضبط',\n    'name'                  => 'الاسم',\n    'username'              => 'اسم المستخدم',\n    'password'              => 'الرقم السري',\n    'password_confirmation' => 'تأكيد الرقم السري',\n    'remember_me'           => 'تذكرني',\n    'user_setting'          => 'ضبط المستخدم',\n    'avatar'                => 'الصورة',\n    'list'                  => 'القائمة',\n    'new'                   => 'جديد',\n    'create'                => 'انشاء',\n    'delete'                => 'مسح',\n    'remove'                => 'حذف',\n    'edit'                  => 'تعديل',\n    'view'                  => 'عرض',\n    'continue_editing'      => 'مواصلة التحرير',\n    'continue_creating'     => 'تواصل خلق',\n    'detail'                => 'التفاصيل',\n    'browse'                => 'تصفح',\n    'reset'                 => 'تفريغ',\n    'export'                => 'تصدير',\n    'batch_delete'          => 'مسح بالجملة',\n    'save'                  => 'حفظ',\n    'refresh'               => 'تحديث',\n    'order'                 => 'ترتيب',\n    'expand'                => 'تكبير',\n    'collapse'              => 'تصغير',\n    'filter'                => 'تصنيف',\n    'search'                => 'بحث',\n    'close'                 => 'اغلاق',\n    'show'                  => 'عرض',\n    'entries'               => 'المدخلات',\n    'captcha'               => 'كود التحقق',\n    'action'                => 'الحدث',\n    'title'                 => 'العنوان',\n    'description'           => 'الوصف',\n    'back'                  => 'عودة',\n    'back_to_list'          => 'العودة الى القائمة',\n    'submit'                => 'ارسال',\n    'menu'                  => 'القائمة',\n    'input'                 => 'المدخل',\n    'succeeded'             => 'تمت بنجاح',\n    'failed'                => 'فشل',\n    'delete_confirm'        => 'هل انت متاكد من مسح هذا العنصر ',\n    'delete_succeeded'      => 'تم الحذف بنجاح ! ',\n    'delete_failed'         => 'فشل الحذف !',\n    'update_succeeded'      => 'تم التعديل بنجاح !',\n    'save_succeeded'        => 'تم الحفظ !',\n    'refresh_succeeded'     => 'تم التحديث !',\n    'login_successful'      => 'تم تسجيل الدخول بنجاح',\n    'choose'                => 'اختر',\n    'choose_file'           => 'اختر الملف',\n    'choose_image'          => 'اختر الصورة',\n    'more'                  => 'المزيد',\n    'deny'                  => 'ليس لديك الاذن',\n    'administrator'         => 'مسئول',\n    'roles'                 => 'القواعد',\n    'permissions'           => 'الصلاحيات',\n    'slug'                  => 'المعرف',\n    'created_at'            => 'تاريخ الانشاء',\n    'updated_at'            => 'تاريخ التعديل',\n    'alert'                 => 'تحذير',\n    'parent_id'             => 'الاصل',\n    'icon'                  => 'الرمز',\n    'uri'                   => 'URI',\n    'operation_log'         => 'سجل التشغيل',\n    'parent_select_error'   => 'خطأ في تحديد الاصل',\n    'pagination'            => [\n        'range' => 'عرض :first الى :last من :total المدخلات',\n    ],\n    'role'                  => 'القاعدة',\n    'permission'            => 'الصلاحية',\n    'route'                 => 'المسار',\n    'confirm'               => 'تأكيد',\n    'cancel'                => 'إلغاء',\n    'http'                  => [\n        'method' => 'HTTP method',\n        'path'   => 'HTTP path',\n    ],\n    'all_methods_if_empty'  => 'كل الوسائل فارغة',\n    'all'                   => 'الكل',\n    'current_page'          => 'الصفحة الحالية',\n    'selected_rows'         => 'الصفوف المختارة',\n    'upload'                => 'رفع',\n    'new_folder'            => 'مجلد جديد',\n    'time'                  => 'الوقت',\n    'size'                  => 'الحجم',\n    'listbox'               => [\n        'text_total'         => 'عرض الكل {0}',\n        'text_empty'         => 'قائمة فارغة',\n        'filtered'           => '{0} / {1}',\n        'filter_clear'       => 'عرض الكل',\n        'filter_placeholder' => 'تنقية',\n    ],\n    'menu_titles'            => [],\n    'prev'                   => 'السابق',\n    'next'                   => 'التالي',\n    'quick_create'           => 'إضافة سريعة',\n];\n"
  },
  {
    "path": "resources/lang/az/admin.php",
    "content": "<?php\n\nreturn [\n    'online'                => 'Aktiv',\n    'login'                 => 'Giriş',\n    'logout'                => 'Çıxış',\n    'setting'               => 'Ayarlar',\n    'name'                  => 'Ad',\n    'username'              => 'İstifadəçi adı',\n    'password'              => 'Şifrə',\n    'password_confirmation' => 'Şifrənin tekrarı',\n    'remember_me'           => 'Məni xatırla',\n    'user_setting'          => 'İstifadəçi ayarları',\n    'avatar'                => 'Profil şəkli',\n    'list'                  => 'List',\n    'new'                   => 'Yeni',\n    'create'                => 'Yarat',\n    'delete'                => 'Sil',\n    'remove'                => 'Kənarlaşdırın',\n    'edit'                  => 'Yenilə',\n    'view'                  => 'Bax',\n    'detail'                => 'Detallar',\n    'browse'                => 'Göz atın',\n    'reset'                 => 'Təmizlə',\n    'export'                => 'İxrac edin',\n    'batch_delete'          => 'Hamısını sil',\n    'save'                  => 'Yaddaşa ver',\n    'refresh'               => 'Yenile',\n    'order'                 => 'Sırala',\n    'expand'                => 'Genişlət',\n    'collapse'              => 'Daralt',\n    'filter'                => 'Filtrlə',\n    'search'                => 'axtarış',\n    'close'                 => 'Bağla',\n    'show'                  => 'Göstər',\n    'entries'               => 'qeydlər',\n    'captcha'               => 'Doğrulama',\n    'action'                => 'Fəaliyyət',\n    'title'                 => 'Başlıq',\n    'description'           => 'Açıqlama',\n    'back'                  => 'Geri',\n    'back_to_list'          => 'Listə geri qayıt',\n    'submit'                => 'Göndər',\n    'continue_editing'      => 'Redaktəyə davam et',\n    'continue_creating'     => 'Yaratmağa davam et',\n    'menu'                  => 'Menyu',\n    'input'                 => 'Giriş',\n    'succeeded'             => 'Uğurlu',\n    'failed'                => 'Xəta baş verdi',\n    'delete_confirm'        => 'Silmək istədiyinizə əminsiniz?',\n    'delete_succeeded'      => 'Uğurla silindi!',\n    'delete_failed'         => 'Silinərkən xəta baş verdi!',\n    'update_succeeded'      => 'Uğurla yeniləndi!',\n    'save_succeeded'        => 'Uğurla yadda saxlanıldı!',\n    'refresh_succeeded'     => 'Uğurla yeniləndi!',\n    'login_successful'      => 'Giriş uğurlu oldu',\n    'choose'                => 'Seçin',\n    'choose_file'           => 'Fayl seçin',\n    'choose_image'          => 'Şəkil seçin',\n    'more'                  => 'Daha çox',\n    'deny'                  => 'İcazə yoxdur',\n    'administrator'         => 'Rəhbər',\n    'roles'                 => 'Rollar',\n    'permissions'           => 'İcazələr',\n    'slug'                  => 'Qalıcı link',\n    'created_at'            => 'Yaradılma tarixi',\n    'updated_at'            => 'Yenilənmə tarixi',\n    'alert'                 => 'Xəbərdarlıq',\n    'parent_id'             => 'Valideyn',\n    'icon'                  => 'İkon',\n    'uri'                   => 'URL',\n    'operation_log'         => 'Əməliyyat tarixçəsi',\n    'parent_select_error'   => 'Üst xəta',\n    'pagination'            => [\n        'range' => ':total qeyd içindən :first dən :last -ə kimi',\n    ],\n    'role'                  => 'Rol',\n    'permission'            => 'İcazə',\n    'route'                 => 'Yol',\n    'confirm'               => 'Təsdiqlə',\n    'cancel'                => 'Ləğv',\n    'http'                  => [\n        'method' => 'HTTP methodu',\n        'path'   => 'HTTP qovluğu',\n    ],\n    'all_methods_if_empty'  => 'Bütün metodlar boşdursa',\n    'all'                   => 'Hamısı',\n    'current_page'          => 'Cari səhifə',\n    'selected_rows'         => 'Seçilənlər',\n    'upload'                => 'Yüklə',\n    'new_folder'            => 'Yeni qovluq',\n    'time'                  => 'Zaman',\n    'size'                  => 'Ölçü',\n    'listbox'               => [\n        'text_total'         => 'Ümumi {0} qeyd',\n        'text_empty'         => 'Boş list',\n        'filtered'           => '{0} / {1}',\n        'filter_clear'       => 'Hamısını göstər',\n        'filter_placeholder' => 'Filtrlə',\n    ],\n    'menu_titles'           => [],\n];\n"
  },
  {
    "path": "resources/lang/bn/admin.php",
    "content": "<?php\n\nreturn [\n    'online'                => 'অনলাইন',\n    'login'                 => 'লগিন',\n    'logout'                => 'লগ আউট',\n    'setting'               => 'সেটিংস',\n    'name'                  => 'নাম',\n    'username'              => 'ব্যবহারকারীর নাম',\n    'password'              => 'পাসওয়ার্ড',\n    'password_confirmation' => 'পাসওয়ার্ড নিশ্চিতকরণ',\n    'remember_me'           => 'আমাকে মনে রাখুন',\n    'user_setting'          => 'ব্যবহারকারীর সেটিংস',\n    'avatar'                => 'ছবি',\n    'list'                  => 'তালিকা',\n    'new'                   => 'নতুন',\n    'create'                => 'তৈরি করুন',\n    'delete'                => 'মুছে ফেলুন',\n    'remove'                => 'সরান',\n    'edit'                  => 'সম্পাদনা',\n    'view'                  => 'দেখুন',\n    'continue_editing'      => 'সম্পাদনা অব্যাহত রাখুন',\n    'continue_creating'     => 'তৈরি অব্যাহত রাখুন',\n    'detail'                => 'বিস্তারিত',\n    'browse'                => 'ব্রাউজ করুন',\n    'reset'                 => 'রিসেট',\n    'export'                => 'এক্সপোর্ট',\n    'batch_delete'          => 'গুচ্ছ আকারে মুছুন',\n    'save'                  => 'সংরক্ষণ',\n    'refresh'               => 'রিফ্রেশ',\n    'order'                 => 'ক্রম',\n    'expand'                => 'বর্ধিত',\n    'collapse'              => 'বন্ধ',\n    'filter'                => 'ফিল্টার',\n    'search'                => 'খুঁজুন',\n    'close'                 => 'বন্ধ',\n    'show'                  => 'দেখান',\n    'entries'               => 'অন্তর্ভুক্তিগুলি',\n    'captcha'               => 'ক্যাপচা',\n    'action'                => 'একশন',\n    'title'                 => 'শিরোনাম',\n    'description'           => 'বর্ণনা',\n    'back'                  => 'ফিরে যান',\n    'back_to_list'          => 'তালিকায় ফিরে যান',\n    'submit'                => 'সাবমিট করন',\n    'menu'                  => 'মেন্যু',\n    'input'                 => 'ইনপুট',\n    'succeeded'             => 'সফল হয়েছে',\n    'failed'                => 'ব্যর্থ হয়েছে',\n    'delete_confirm'        => 'আপনি কি এই আইটেমটি মুছে ফেলার বিষয়ে নিশ্চিত?',\n    'delete_succeeded'      => 'মুছে ফেলতে সক্ষম হয়েছে।',\n    'delete_failed'         => 'মুছে ফেলতে ব্যর্থ হয়েছে',\n    'update_succeeded'      => 'সফলভবে আপডেট হয়েছে।',\n    'save_succeeded'        => 'সফলভবে সংরক্ষণ হয়েছে।',\n    'refresh_succeeded'     => 'সফলভবে রিফ্রেশ হয়েছে।',\n    'login_successful'      => 'লগিন সফল হয়ছে',\n    'choose'                => 'বাছাই করুন',\n    'choose_file'           => 'ফাইল নির্বাচন করুন',\n    'choose_image'          => 'ছবি সফলভবে সংরক্ষণ হয়েছে।',\n    'more'                  => 'আরও',\n    'deny'                  => 'অনুমতি অগ্রাহ্য হয়েছে',\n    'administrator'         => 'এডমিনিস্ট্রেটর',\n    'roles'                 => 'রোলসমূহ',\n    'permissions'           => 'পারমিশন সমূহ',\n    'slug'                  => 'স্লাগ',\n    'created_at'            => 'তৈরি করা হয়েছে',\n    'updated_at'            => 'আপডেট করা হয়েছে',\n    'alert'                 => 'সতর্কীকরণ',\n    'parent_id'             => 'প্যারেন্ট',\n    'icon'                  => 'আইকন',\n    'uri'                   => 'URI',\n    'operation_log'         => 'অপারেশন লগ',\n    'parent_select_error'   => 'প্যারেন্ট নির্বাচন ভুল',\n    'pagination'            => [\n        'range' => ':total টি রেকর্ডের মধ্যে :first থেকে :last টি দেখানো হচ্ছে',\n    ],\n    'role'                  => 'রোল',\n    'permission'            => 'পারমিশন',\n    'route'                 => 'রাউট',\n    'confirm'               => 'নিশ্চিত করুন',\n    'cancel'                => 'বাতিল',\n    'http'                  => [\n        'method' => 'HTTP method',\n        'path'   => 'HTTP path',\n    ],\n    'all_methods_if_empty'  => 'All methods if empty',\n    'all'                   => 'সকল',\n    'current_page'          => 'বর্তমান পৃষ্ঠা',\n    'selected_rows'         => 'নির্বাচিত সারিগুলি',\n    'upload'                => 'আপলোড',\n    'new_folder'            => 'নতুন ফোল্ডার',\n    'time'                  => 'স্ময়',\n    'size'                  => 'সাইজ',\n    'listbox'               => [\n        'text_total'         => 'সবগুলি দেখানো হচ্ছে {0}',\n        'text_empty'         => 'খালি তালিকা',\n        'filtered'           => '{0} / {1}',\n        'filter_clear'       => 'সবগুলি দেখান',\n        'filter_placeholder' => 'ফিল্টার',\n    ],\n    'grid_items_selected'    => '{n} টি আইটেম নির্বাচিত হয়েছে',\n\n    'menu_titles'            => [],\n    'prev'                   => 'পূর্ববর্তী',\n    'next'                   => 'পরবর্তী',\n    'quick_create'           => 'দ্রুত তৈরি করুন',\n];\n"
  },
  {
    "path": "resources/lang/de/admin.php",
    "content": "<?php\n\nreturn [\n    'online'                => 'Online',\n    'login'                 => 'Anmelden',\n    'logout'                => 'Abmelden',\n    'setting'               => 'Einstellungen',\n    'name'                  => 'Name',\n    'username'              => 'Benutzername',\n    'password'              => 'Passwort',\n    'password_confirmation' => 'Passwort bestätigung',\n    'remember_me'           => 'Remember me',\n    'user_setting'          => 'Benutzer Einstellungen',\n    'avatar'                => 'Avatar',\n    'list'                  => 'Liste',\n    'new'                   => 'Neu',\n    'create'                => 'Erstellen',\n    'delete'                => 'Löschen',\n    'remove'                => 'Entfernen',\n    'edit'                  => 'Bearbeiten',\n    'view'                  => 'Ansehen',\n    'continue_editing'      => 'Weiter bearbeiten',\n    'continue_creating'     => 'Weitere erstellen',\n    'detail'                => 'Details',\n    'browse'                => 'Auswählen',\n    'reset'                 => 'Zurücksetzen',\n    'export'                => 'Exportieren',\n    'batch_delete'          => 'Chargenlöschung',\n    'save'                  => 'Speichern',\n    'refresh'               => 'Aktualisieren',\n    'order'                 => 'Order',\n    'expand'                => 'Aufklappen',\n    'collapse'              => 'Zuklappen',\n    'filter'                => 'Filter',\n    'search'                => 'Suche',\n    'close'                 => 'Schließen',\n    'show'                  => 'Anzeigen',\n    'entries'               => 'Einträge',\n    'captcha'               => 'Captcha',\n    'action'                => 'Aktion',\n    'title'                 => 'Titel',\n    'description'           => 'Beschreibung',\n    'back'                  => 'Zurück',\n    'back_to_list'          => 'Zurück zur Liste',\n    'submit'                => 'Absenden',\n    'menu'                  => 'Menü',\n    'input'                 => 'Eingabe',\n    'succeeded'             => 'Erfolgreich',\n    'failed'                => 'Gescheitert',\n    'delete_confirm'        => 'Wollen Sie diesen Eintrag wirklich löschen?',\n    'delete_succeeded'      => 'Löschen erfolgreich!',\n    'delete_failed'         => 'Löschen gescheitert!',\n    'update_succeeded'      => 'Aktualisierung erfolgreich!',\n    'save_succeeded'        => 'Speichern erfolgreich!',\n    'refresh_succeeded'     => 'Aktualisierung erfolgreich!',\n    'login_successful'      => 'Anmeldung erfolgreich',\n    'choose'                => 'Auswählen',\n    'choose_file'           => 'Datei auswählen',\n    'choose_image'          => 'Bild auswählen',\n    'more'                  => 'Mehr',\n    'deny'                  => 'Zugriff verweigert',\n    'administrator'         => 'Administrator',\n    'roles'                 => 'Rollen',\n    'permissions'           => 'Rechte',\n    'slug'                  => 'Schlagwort',\n    'created_at'            => 'Erstellt am',\n    'updated_at'            => 'Aktualisiert am',\n    'alert'                 => 'Warnung',\n    'parent_id'             => 'Übergeordnete ID',\n    'icon'                  => 'Icon',\n    'uri'                   => 'URL',\n    'operation_log'         => 'Betriebs Log',\n    'parent_select_error'   => 'Fehler bei der Parent Auswahl',\n    'pagination'            => [\n        'range' => 'Zeigt :first bis :last von gesamt :total Einträgen',\n    ],\n    'role'                  => 'Rolle',\n    'permission'            => 'Rechte',\n    'route'                 => 'Route',\n    'confirm'               => 'Bestätigen',\n    'cancel'                => 'Abbrechen',\n    'http'                  => [\n        'method' => 'HTTP Methode',\n        'path'   => 'HTTP Pfad',\n    ],\n    'all_methods_if_empty'  => 'Alle Methoden wenn leer',\n    'all'                   => 'Alle',\n    'current_page'          => 'Aktuelle Seite',\n    'selected_rows'         => 'Ausgewählte Zeilen',\n    'upload'                => 'Hochladen',\n    'new_folder'            => 'Neuer Ordner',\n    'time'                  => 'Zeit',\n    'size'                  => 'Größe',\n    'listbox'               => [\n        'text_total'         => 'Zeige alle {0}',\n        'text_empty'         => 'Leere Liste',\n        'filtered'           => '{0} / {1}',\n        'filter_clear'       => 'Filter zurücksetzen',\n        'filter_placeholder' => 'Filtern',\n    ],\n    'grid_items_selected'    => '{n} Einträge ausgewählt',\n\n    'menu_titles'            => [],\n    'prev'                   => 'Vorherige',\n    'next'                   => 'Nächste',\n    'quick_create'           => 'Schnellerstellung',\n];\n"
  },
  {
    "path": "resources/lang/en/admin.php",
    "content": "<?php\n\nreturn [\n    'online'                => 'Online',\n    'login'                 => 'Login',\n    'logout'                => 'Logout',\n    'setting'               => 'Setting',\n    'name'                  => 'Name',\n    'username'              => 'Username',\n    'password'              => 'Password',\n    'password_confirmation' => 'Password confirmation',\n    'remember_me'           => 'Remember me',\n    'user_setting'          => 'User setting',\n    'avatar'                => 'Avatar',\n    'list'                  => 'List',\n    'new'                   => 'New',\n    'create'                => 'Create',\n    'delete'                => 'Delete',\n    'remove'                => 'Remove',\n    'edit'                  => 'Edit',\n    'view'                  => 'View',\n    'continue_editing'      => 'Continue editing',\n    'continue_creating'     => 'Continue creating',\n    'detail'                => 'Detail',\n    'browse'                => 'Browse',\n    'reset'                 => 'Reset',\n    'export'                => 'Export',\n    'batch_delete'          => 'Batch delete',\n    'save'                  => 'Save',\n    'refresh'               => 'Refresh',\n    'order'                 => 'Order',\n    'expand'                => 'Expand',\n    'collapse'              => 'Collapse',\n    'filter'                => 'Filter',\n    'search'                => 'Search',\n    'close'                 => 'Close',\n    'show'                  => 'Show',\n    'entries'               => 'entries',\n    'captcha'               => 'Captcha',\n    'action'                => 'Action',\n    'title'                 => 'Title',\n    'description'           => 'Description',\n    'back'                  => 'Back',\n    'back_to_list'          => 'Back to List',\n    'submit'                => 'Submit',\n    'menu'                  => 'Menu',\n    'input'                 => 'Input',\n    'succeeded'             => 'Succeeded',\n    'failed'                => 'Failed',\n    'delete_confirm'        => 'Are you sure to delete this item ?',\n    'delete_succeeded'      => 'Delete succeeded !',\n    'delete_failed'         => 'Delete failed !',\n    'update_succeeded'      => 'Update succeeded !',\n    'save_succeeded'        => 'Save succeeded !',\n    'refresh_succeeded'     => 'Refresh succeeded !',\n    'login_successful'      => 'Login successful',\n    'choose'                => 'Choose',\n    'choose_file'           => 'Select file',\n    'choose_image'          => 'Select image',\n    'more'                  => 'More',\n    'deny'                  => 'Permission denied',\n    'administrator'         => 'Administrator',\n    'roles'                 => 'Roles',\n    'permissions'           => 'Permissions',\n    'slug'                  => 'Slug',\n    'created_at'            => 'Created At',\n    'updated_at'            => 'Updated At',\n    'alert'                 => 'Alert',\n    'parent_id'             => 'Parent',\n    'icon'                  => 'Icon',\n    'uri'                   => 'URI',\n    'operation_log'         => 'Operation log',\n    'parent_select_error'   => 'Parent select error',\n    'pagination'            => [\n        'range' => 'Showing :first to :last of :total entries',\n    ],\n    'role'                  => 'Role',\n    'permission'            => 'Permission',\n    'route'                 => 'Route',\n    'confirm'               => 'Confirm',\n    'cancel'                => 'Cancel',\n    'http'                  => [\n        'method' => 'HTTP method',\n        'path'   => 'HTTP path',\n    ],\n    'all_methods_if_empty'  => 'All methods if empty',\n    'all'                   => 'All',\n    'current_page'          => 'Current page',\n    'selected_rows'         => 'Selected rows',\n    'upload'                => 'Upload',\n    'new_folder'            => 'New folder',\n    'time'                  => 'Time',\n    'size'                  => 'Size',\n    'listbox'               => [\n        'text_total'         => 'Showing all {0}',\n        'text_empty'         => 'Empty list',\n        'filtered'           => '{0} / {1}',\n        'filter_clear'       => 'Show all',\n        'filter_placeholder' => 'Filter',\n    ],\n    'grid_items_selected'    => '{n} items selected',\n\n    'menu_titles'            => [],\n    'prev'                   => 'Prev',\n    'next'                   => 'Next',\n    'quick_create'           => 'Quick create',\n];\n"
  },
  {
    "path": "resources/lang/es/admin.php",
    "content": "<?php\n\nreturn [\n    'online'                => 'en línea',\n    'login'                 => 'Iniciar sesión',\n    'logout'                => 'Cerrar sesión',\n    'setting'               => 'Ajustes',\n    'name'                  => 'Nombre',\n    'username'              => 'Nombre de usuario',\n    'password'              => 'Contraseña',\n    'password_confirmation' => 'Confirmación de contraseña',\n    'remember_me'           => 'Recordarme',\n    'user_setting'          => 'Configuración del usuario',\n    'avatar'                => 'Avatar',\n    'list'                  => 'Lista',\n    'new'                   => 'Nuevo',\n    'create'                => 'Crear',\n    'delete'                => 'Eliminar',\n    'remove'                => 'Retirar',\n    'edit'                  => 'Editar',\n    'view'                  => 'Ver',\n    'continue_editing'      => 'Continua editando',\n    'continue_creating'     => 'Sigue creando',\n    'detail'                => 'Detalle',\n    'browse'                => 'vistazo',\n    'reset'                 => 'Restablecer',\n    'export'                => 'Exportar',\n    'batch_delete'          => 'Eliminar por lotes',\n    'save'                  => 'Guardar',\n    'refresh'               => 'Refrescar',\n    'order'                 => 'Ordenar',\n    'expand'                => 'Expandir',\n    'collapse'              => 'Colapsar',\n    'filter'                => 'Filtrar',\n    'search'                => 'Buscar',\n    'close'                 => 'Cerrar',\n    'show'                  => 'Mostrar',\n    'entries'               => 'Entradas',\n    'captcha'               => 'Captcha',\n    'action'                => 'Acción',\n    'title'                 => 'Título',\n    'description'           => 'Descripción',\n    'back'                  => 'Volver',\n    'back_to_list'          => 'Volver a la lista',\n    'submit'                => 'Enviar',\n    'menu'                  => 'Menú',\n    'input'                 => 'Entrada',\n    'succeeded'             => 'Exitoso',\n    'failed'                => 'Fallido',\n    'delete_confirm'        => '¿ Esta seguro de eliminar este elemento ?',\n    'delete_succeeded'      => '¡ Eliminación exitosa !',\n    'delete_failed'         => '¡ Eliminación fallida !',\n    'update_succeeded'      => '¡ Actualización correcta !',\n    'save_succeeded'        => '¡ Guardar con éxito !',\n    'refresh_succeeded'     => '¡ Actualizar correctamente !',\n    'login_successful'      => 'Inicio de sesión correcto',\n    'choose'                => 'Elegir',\n    'choose_file'           => 'Elegir archivo',\n    'choose_image'          => 'Elegir imagen',\n    'more'                  => 'Más',\n    'deny'                  => 'Permiso denegado',\n    'administrator'         => 'Administrador',\n    'roles'                 => 'Roles',\n    'permissions'           => 'Permisos',\n    'slug'                  => 'Slug',\n    'created_at'            => 'Creado el',\n    'updated_at'            => 'Actualizado el',\n    'alert'                 => 'Alerta',\n    'parent_id'             => 'Padre',\n    'icon'                  => 'Icono',\n    'uri'                   => 'URI',\n    'operation_log'         => 'Registro',\n    'parent_select_error'   => 'Error al seleccionar el elemento padre',\n    'pagination'            => [\n        'range' => 'Mostrando :first a :last de :total elementos',\n    ],\n    'role'                  => 'Rol',\n    'permission'            => 'Permiso',\n    'route'                 => 'Route',\n    'confirm'               => 'Confirmar',\n    'cancel'                => 'Cancelar',\n    'http'                  => [\n        'method' => 'HTTP method',\n        'path'   => 'HTTP path',\n    ],\n    'all'                   => 'Todas',\n    'current_page'          => 'Página actual',\n    'selected_rows'         => 'Filas seleccionadas',\n    'menu_titles'           => [],\n];\n"
  },
  {
    "path": "resources/lang/fa/admin.php",
    "content": "<?php\n\nreturn [\n    'online'                => 'آنلاین',\n    'login'                 => 'ورود',\n    'logout'                => 'خروج',\n    'setting'               => 'تنظیمات',\n    'name'                  => 'نام',\n    'username'              => 'نام کاربری',\n    'password'              => 'کلمه عبور',\n    'password_confirmation' => 'تایید کلمه عبور',\n    'remember_me'           => 'من را به خاطر بسپار',\n    'user_setting'          => 'تنظیمات کاربر',\n    'avatar'                => 'آواتار',\n    'list'                  => 'لیست',\n    'new'                   => 'جدید',\n    'create'                => 'جدید',\n    'delete'                => 'حذف کردن',\n    'remove'                => 'پاک کردن',\n    'edit'                  => 'ویرایش کردن',\n    'view'                  => 'نمایش',\n    'continue_editing'      => 'ادامه ویرایش',\n    'continue_creating'     => 'ادامه را ایجاد کنید',\n    'detail'                => 'جزئیات',\n    'browse'                => 'پیمایش',\n    'reset'                 => 'نوسازی',\n    'export'                => 'خروجی',\n    'batch_delete'          => 'حذف گروهی',\n    'save'                  => 'ثبت کردن',\n    'refresh'               => 'بروز سازی',\n    'order'                 => 'اولویت',\n    'expand'                => 'گسترش',\n    'collapse'              => 'بازکردن',\n    'filter'                => 'فیلتر کردن',\n    'search'                => 'جستجو کردن',\n    'close'                 => 'بستن',\n    'show'                  => 'نمایش',\n    'entries'               => 'ورودی',\n    'captcha'               => 'کپچا',\n    'action'                => 'عملیات',\n    'title'                 => 'عنوان',\n    'description'           => 'توضیحات',\n    'back'                  => 'بازگشت',\n    'back_to_list'          => 'بازگشت به لیست',\n    'submit'                => 'ثبت',\n    'menu'                  => 'منو',\n    'input'                 => 'ورودی',\n    'succeeded'             => 'با موفقیت انجام شد',\n    'failed'                => 'نا موفق',\n    'delete_confirm'        => 'آیا از حذف این مورد اطمینان دارید؟',\n    'delete_succeeded'      => 'حذف موفقیت آمیز انجام شد !',\n    'delete_failed'         => 'حذف نا موفق بود !',\n    'update_succeeded'      => 'ویرایش با موفقیت انجام شد !',\n    'save_succeeded'        => 'ثبت با موفقیت انجام شد !',\n    'refresh_succeeded'     => 'بروزسانی با موفقیت انجام شد !',\n    'login_successful'      => 'ورود با موفقیت انجام شد',\n    'choose'                => 'انتخاب کردن',\n    'choose_file'           => 'انتخاب فایل',\n    'choose_image'          => 'انتخاب عکس',\n    'more'                  => 'بیشتر',\n    'deny'                  => 'دسترسی غیر مجاز',\n    'administrator'         => 'ادمین',\n    'roles'                 => 'دسترسی ها',\n    'permissions'           => 'اجازه ها',\n    'slug'                  => 'نامک',\n    'created_at'            => 'ساخته شده در',\n    'updated_at'            => 'ویرایش شده در',\n    'alert'                 => 'هشدار',\n    'parent_id'             => 'والد',\n    'icon'                  => 'آیکون',\n    'uri'                   => 'آدرس',\n    'operation_log'         => 'لاگ عملیاتی',\n    'parent_select_error'   => 'انتخاب والد با خطا مواجه شد',\n    'pagination'            => [\n        'range' => 'نمایش از :first تا :last از کل :total',\n    ],\n    'role'                  => 'دسترسی ها',\n    'permission'            => 'اجازه ها',\n    'route'                 => 'مسیرها',\n    'confirm'               => 'تایید',\n    'cancel'                => 'لغو',\n    'http'                  => [\n        'method' => 'HTTP متد',\n        'path'   => 'HTTP مسیر',\n    ],\n    'all_methods_if_empty'  => 'همه متدها خالی است',\n    'all'                   => 'همه',\n    'current_page'          => 'همین صفحه',\n    'selected_rows'         => 'انتخاب سطر',\n    'upload'                => 'آپلود',\n    'new_folder'            => 'پوشه جدید',\n    'time'                  => 'زمان',\n    'size'                  => 'حجم',\n    'listbox'               => [\n        'text_total'         => 'درحال نمایش همه {0}',\n        'text_empty'         => 'لیست خالی است',\n        'filtered'           => '{0} / {1}',\n        'filter_clear'       => 'نمایش همه',\n        'filter_placeholder' => 'فیلتر کردن',\n    ],\n    'menu_titles'           => [\n        'dashboard'          => 'داشبورد',\n        'admin'              => 'ادمین',\n        'users'              => 'کاربران',\n        'roles'              => 'نقش ها',\n        'permission'         => 'دسترسی ها',\n        'menu'               => 'منو',\n        'operation_log'      => 'گزارش عملیات',\n    ],\n];\n"
  },
  {
    "path": "resources/lang/fr/admin.php",
    "content": "<?php\n\nreturn [\n    'online'                => 'En ligne',\n    'login'                 => 'Connexion',\n    'logout'                => 'Déconnexion',\n    'setting'               => 'Paramètres',\n    'name'                  => 'Nom',\n    'username'              => 'Nom d\\'utilisateur',\n    'password'              => 'Mot de passe',\n    'password_confirmation' => 'Confirmez votre mot de passe',\n    'remember_me'           => 'Rester connecté',\n    'user_setting'          => 'Paramètres',\n    'avatar'                => 'Avatar',\n    'list'                  => 'Liste',\n    'new'                   => 'Nouveau',\n    'create'                => 'Créer',\n    'delete'                => 'Supprimer',\n    'remove'                => 'Enlèver',\n    'edit'                  => 'Editer',\n    'view'                  => 'Voir',\n    'continue_editing'      => 'Continuer l\\'édition',\n    'continue_creating'     => 'Continuer à créer',\n    'detail'                => 'Détail',\n    'browse'                => 'Naviguer',\n    'reset'                 => 'Réinitialiser',\n    'export'                => 'Exporter',\n    'batch_delete'          => 'Supprimer en masse',\n    'save'                  => 'Sauvegarder',\n    'refresh'               => 'Rafraîchir',\n    'order'                 => 'Commander',\n    'expand'                => 'Déplier',\n    'collapse'              => 'Replier',\n    'filter'                => 'Filtre',\n    'search'                => 'Chercher',\n    'close'                 => 'Fermer',\n    'show'                  => 'Affiche',\n    'entries'               => 'lignes',\n    'captcha'               => 'Captcha',\n    'action'                => 'Action',\n    'title'                 => 'Titre',\n    'description'           => 'Description',\n    'back'                  => 'Retourner',\n    'back_to_list'          => 'Retourne à la liste',\n    'submit'                => 'Soumettre',\n    'menu'                  => 'Menu',\n    'input'                 => 'Entrée',\n    'succeeded'             => 'Réussi',\n    'failed'                => 'Failli',\n    'delete_confirm'        => 'Êtes vous bien certain de vouloir supprimer cet élement ?',\n    'delete_succeeded'      => 'L\\'élement a bien été supprimé !',\n    'delete_failed'         => 'L\\'effacement a échoué !',\n    'update_succeeded'      => 'Changements sont bien mis à jour !',\n    'save_succeeded'        => 'Changements sauvés !',\n    'refresh_succeeded'     => 'Rafraîchissement réussi !',\n    'login_successful'      => 'Connexion réussie',\n    'choose'                => 'Choisissez',\n    'choose_file'           => 'Choisissez un fichier',\n    'choose_image'          => 'Choisissez une image',\n    'more'                  => 'Plus',\n    'deny'                  => 'Permission refusée',\n    'administrator'         => 'Administrateur',\n    'roles'                 => 'Rôles',\n    'permissions'           => 'Droits',\n    'slug'                  => 'Slug',\n    'created_at'            => 'Créé à',\n    'updated_at'            => 'Mis à jour à',\n    'alert'                 => 'Alerte',\n    'parent_id'             => 'Parent',\n    'icon'                  => 'Icône',\n    'uri'                   => 'URI',\n    'operation_log'         => 'Journal des opérations',\n    'parent_select_error'   => 'Parent select erreur',\n    'pagination'            => [\n        'range' => ':first à :last de :total lignes',\n    ],\n    'role'                  => 'Rôle',\n    'permission'            => 'Permission',\n    'route'                 => 'Route',\n    'confirm'               => 'Confirmer',\n    'cancel'                => 'Annuler',\n    'http'                  => [\n        'method' => 'HTTP méthode',\n        'path'   => 'HTTP chemin',\n    ],\n    'all_methods_if_empty'  => 'Toutes méthodes si vide',\n    'all'                   => 'Tous',\n    'current_page'          => 'La page actuelle',\n    'selected_rows'         => 'Les lignes sélectionnées',\n    'upload'                => 'Téléverser',\n    'new_folder'            => 'Nouveau dossier',\n    'time'                  => 'Temps',\n    'size'                  => 'Taille',\n    'listbox'               => [\n        'text_total'         => 'Affichant toutes {0}',\n        'text_empty'         => 'Liste vide',\n        'filtered'           => '{0} / {1}',\n        'filter_clear'       => 'Affichez tous',\n        'filter_placeholder' => 'Filtre',\n    ],\n    'menu_titles'           => [],\n];\n"
  },
  {
    "path": "resources/lang/he/admin.php",
    "content": "<?php\n\nreturn [\n    'online'                => 'און ליין',\n    'login'                 => 'כניסה',\n    'logout'                => 'יציאה',\n    'setting'               => 'הגדרות',\n    'name'                  => 'שם',\n    'username'              => 'שם משתמש',\n    'password'              => 'סיסמא',\n    'password_confirmation' => 'שוב סיסמא',\n    'remember_me'           => 'זכור אותי',\n    'user_setting'          => 'הגדרות משתמש',\n    'avatar'                => 'תמונה',\n    'list'                  => 'רשימה',\n    'new'                   => 'חדש',\n    'create'                => 'יצירה',\n    'delete'                => 'מחיקה',\n    'remove'                => 'הסרה',\n    'edit'                  => 'עריכה',\n    'view'                  => 'צפייה',\n    'continue_editing'      => 'המשך בעריכה',\n    'continue_creating'     => 'המשך ליצור',\n    'detail'                => 'פרט',\n    'browse'                => 'דפדוף',\n    'reset'                 => 'אתחול',\n    'export'                => 'ייצוא',\n    'batch_delete'          => 'מחק מסומנים',\n    'save'                  => 'שמור',\n    'refresh'               => 'רענן',\n    'order'                 => 'סדר',\n    'expand'                => 'הרחב',\n    'collapse'              => 'פתח',\n    'filter'                => 'חיפוש',\n    'search'                => 'לחפש',\n    'close'                 => 'סגור',\n    'show'                  => 'צפה',\n    'entries'               => 'רשומות',\n    'captcha'               => 'קאפצ\\'ה',\n    'action'                => 'פעולה',\n    'title'                 => 'כותרת',\n    'description'           => 'תאור',\n    'back'                  => 'חזרה',\n    'back_to_list'          => 'חזרה לרשימה',\n    'submit'                => 'שלח',\n    'menu'                  => 'תפריט',\n    'input'                 => 'קלט',\n    'succeeded'             => 'הצלחה',\n    'failed'                => 'כשלון',\n    'delete_confirm'        => 'אתה בטוח שאתה רוצה למחוק?',\n    'delete_succeeded'      => 'מחיקה הצליחה',\n    'delete_failed'         => 'מחיקה נכשלה',\n    'update_succeeded'      => 'עודכן בהצלחה',\n    'save_succeeded'        => 'נשמר בהצלחה',\n    'refresh_succeeded'     => 'רענון הצליחה',\n    'login_successful'      => 'כניסה הצליחה',\n    'choose'                => 'בחר',\n    'choose_file'           => 'בחר קובץ',\n    'choose_image'          => 'בחר תמונה',\n    'more'                  => 'עוד',\n    'deny'                  => 'אין הרשאות',\n    'administrator'         => 'מנהל מערכת',\n    'roles'                 => 'תפקידים',\n    'permissions'           => 'הרשאות',\n    'slug'                  => 'טקסט',\n    'created_at'            => 'נוצר ב',\n    'updated_at'            => 'עודכן ב',\n    'alert'                 => 'אזהרה',\n    'parent_id'             => 'אב',\n    'icon'                  => 'אייקון',\n    'uri'                   => 'כתובת',\n    'operation_log'         => 'לוג מערכת',\n    'parent_select_error'   => 'בעייה בבחירת האב',\n    'pagination'            => [\n        'range' => ':last מ :total תוצאות',\n    ],\n\n    'menu_titles' => [],\n];\n"
  },
  {
    "path": "resources/lang/id/admin.php",
    "content": "<?php\n\nreturn [\n    'online'                => 'Daring',\n    'login'                 => 'Masuk',\n    'logout'                => 'Keluar',\n    'setting'               => 'Pengaturan',\n    'name'                  => 'Nama',\n    'username'              => 'Username',\n    'password'              => 'Sandi',\n    'password_confirmation' => 'Konfirmasi Sandi',\n    'remember_me'           => 'Ingatkan saya',\n    'user_setting'          => 'Pengaturan Pengguna',\n    'avatar'                => 'Avatar',\n    'list'                  => 'Daftar',\n    'new'                   => 'Baru',\n    'create'                => 'Buat',\n    'delete'                => 'Hapus',\n    'remove'                => 'Hapus',\n    'edit'                  => 'Ubah',\n    'view'                  => 'Lihat',\n    'continue_editing'      => 'Lanjutkan Pengubahan',\n    'continue_creating'     => 'Terus ciptakan',\n    'detail'                => 'Detail',\n    'browse'                => 'Jelajahi',\n    'reset'                 => 'Reset',\n    'export'                => 'Ekspor',\n    'batch_delete'          => 'Hapus massal',\n    'save'                  => 'Simpan',\n    'refresh'               => 'Segarkan',\n    'order'                 => 'Urutan',\n    'expand'                => 'Bentangkan',\n    'collapse'              => 'Ciutkan',\n    'filter'                => 'Saringan',\n    'search'                => 'Cari',\n    'close'                 => 'Tutup',\n    'show'                  => 'Perlihatkan',\n    'entries'               => 'Masukan',\n    'captcha'               => 'Captcha',\n    'action'                => 'Aksi',\n    'title'                 => 'Judul',\n    'description'           => 'Deskripsi',\n    'back'                  => 'Kembali',\n    'back_to_list'          => 'Kembali ke daftar',\n    'submit'                => 'Submit',\n    'menu'                  => 'Menu',\n    'input'                 => 'Masukan',\n    'succeeded'             => 'Berhasil',\n    'failed'                => 'Gagal',\n    'delete_confirm'        => 'Anda yakin ingin menghapus ini ?',\n    'delete_succeeded'      => 'Berhasil menghapus !',\n    'delete_failed'         => 'Gagal menghapus !',\n    'update_succeeded'      => 'Berhasil mengubah !',\n    'save_succeeded'        => 'Berhasil menyimpan !',\n    'refresh_succeeded'     => 'Berhasil menyegarkan!',\n    'login_successful'      => 'Berhasil masuk',\n    'choose'                => 'Pilih',\n    'choose_file'           => 'Pilih berkas',\n    'choose_image'          => 'Pilih gambar',\n    'more'                  => 'Lebih banyak',\n    'deny'                  => 'Akses ditolak',\n    'administrator'         => 'Administrator',\n    'roles'                 => 'Aturan',\n    'permissions'           => 'Hak Akses',\n    'slug'                  => 'Slug',\n    'created_at'            => 'Dibuat pada',\n    'updated_at'            => 'Diubah pada',\n    'alert'                 => 'Peringatan',\n    'parent_id'             => 'Induk',\n    'icon'                  => 'Ikon',\n    'uri'                   => 'URI',\n    'operation_log'         => 'Riwayat Kegiatan',\n    'parent_select_error'   => 'Kesalahan pemilihan induk',\n    'pagination'            => [\n        'range' => 'Menampilkan :first dari :last dari :total masukan',\n    ],\n    'role'                  => 'Aturan',\n    'permission'            => 'Hak akses',\n    'route'                 => 'Rute',\n    'confirm'               => 'Konfirmasi',\n    'cancel'                => 'Batalkan',\n    'http'                  => [\n        'method' => 'HTTP method',\n        'path'   => 'HTTP path',\n    ],\n    'all_methods_if_empty'  => 'Semua metode kosong',\n    'all'                   => 'Semua',\n    'current_page'          => 'Halaman ini',\n    'selected_rows'         => 'Baris terpilih',\n    'upload'                => 'Unggah',\n    'new_folder'            => 'Folder Baru',\n    'time'                  => 'Waktu',\n    'size'                  => 'Ukuran',\n    'listbox'               => [\n        'text_total'         => 'Semua {0}',\n        'text_empty'         => 'Daftar kosong',\n        'filtered'           => '{0} / {1}',\n        'filter_clear'       => 'Lihat semua',\n        'filter_placeholder' => 'Saringan',\n    ],\n    'grid_items_selected'    => '{n} Item dipilih',\n\n    'menu_titles'            => [],\n    'prev'                   => 'Sebelumnya',\n    'next'                   => 'Selanjutnya',\n];\n"
  },
  {
    "path": "resources/lang/ja/admin.php",
    "content": "<?php\n\nreturn [\n    'online'                => 'オンライン',\n    'login'                 => 'ログイン',\n    'logout'                => 'ログアウト',\n    'setting'               => '設定',\n    'name'                  => '名称',\n    'username'              => 'ユーザーID',\n    'password'              => 'パスワード',\n    'password_confirmation' => '確認用パスワード',\n    'remember_me'           => 'ログイン状態を記憶',\n    'user_setting'          => 'ユーザー設定',\n    'avatar'                => 'アバター',\n    'list'                  => '一覧',\n    'new'                   => '新規',\n    'create'                => '作成',\n    'delete'                => '削除',\n    'remove'                => '消去',\n    'edit'                  => '編集',\n    'view'                  => '表示',\n    'continue_editing'      => '編集を続ける',\n    'continue_creating'     => '作成を続行する',\n    'detail'                => '詳細',\n    'browse'                => '参照',\n    'reset'                 => 'リセット',\n    'export'                => '出力',\n    'batch_delete'          => '一括削除',\n    'save'                  => '保存',\n    'refresh'               => '再読込',\n    'order'                 => '順序',\n    'expand'                => '展開',\n    'collapse'              => '縮小',\n    'filter'                => 'フィルタ',\n    'search'                => 'サーチ',\n    'close'                 => '閉じる',\n    'show'                  => '表示',\n    'entries'               => '件',\n    'captcha'               => 'Captcha',\n    'action'                => '操作',\n    'title'                 => 'タイトル',\n    'description'           => '概要',\n    'back'                  => '戻る',\n    'back_to_list'          => '一覧へ戻る',\n    'submit'                => '送信',\n    'menu'                  => 'メニュー',\n    'input'                 => '入力',\n    'succeeded'             => '成功',\n    'failed'                => '失敗',\n    'delete_confirm'        => '本当に削除しますか？',\n    'delete_succeeded'      => '削除しました！',\n    'delete_failed'         => '削除に失敗しました！',\n    'update_succeeded'      => '更新しました！',\n    'save_succeeded'        => '保存しました！',\n    'refresh_succeeded'     => '更新しました！',\n    'login_successful'      => 'ログインしました！',\n    'choose'                => '選択',\n    'choose_file'           => 'ファイルを選択',\n    'choose_image'          => '画像を選択',\n    'more'                  => '続き',\n    'deny'                  => '権限がありません。',\n    'administrator'         => '管理者',\n    'roles'                 => '役割',\n    'permissions'           => '権限',\n    'slug'                  => 'スラッグ',\n    'created_at'            => '作成日時',\n    'updated_at'            => '更新日時',\n    'alert'                 => '注意',\n    'parent_id'             => '親ID',\n    'icon'                  => 'アイコン',\n    'uri'                   => 'URI',\n    'operation_log'         => '操作ログ',\n    'parent_select_error'   => '親ID選択エラー',\n    'pagination'            => [\n        'range' => '全 :total 件中 :first - :last 件目',\n    ],\n    'role'                  => '役割',\n    'permission'            => '権限',\n    'route'                 => 'Route',\n    'confirm'               => '確認',\n    'cancel'                => '取消',\n    'http'                  => [\n        'method' => 'HTTP method',\n        'path'   => 'HTTP path',\n    ],\n    'all_methods_if_empty'  => '空欄の場合は全て',\n    'all'                   => '全て',\n    'current_page'          => '現在のページ',\n    'selected_rows'         => '選択行のみ',\n    'upload'                => 'アップロード',\n    'new_folder'            => '新規フォルダ',\n    'time'                  => '日時',\n    'size'                  => 'サイズ',\n    'listbox'               => [\n        'text_total'         => '計 {0} 個のアイテム',\n        'text_empty'         => '空のリスト',\n        'filtered'           => '{0} / {1}',\n        'filter_clear'       => '全て表示',\n        'filter_placeholder' => 'フィルタ',\n    ],\n    'menu_titles'           => [],\n];\n"
  },
  {
    "path": "resources/lang/ko/admin.php",
    "content": "<?php\n\nreturn [\n    'online'                => '온라인',\n    'login'                 => '로그인',\n    'logout'                => '로그아웃',\n    'setting'               => '설정',\n    'name'                  => '이름',\n    'username'              => '아이디',\n    'password'              => '비밀번호',\n    'password_confirmation' => '비밀번호 확인',\n    'remember_me'           => '자동로그인',\n    'user_setting'          => '사용자 설정',\n    'avatar'                => '프로필',\n    'list'                  => '목록',\n    'new'                   => '만들기',\n    'create'                => '생성',\n    'delete'                => '삭제',\n    'remove'                => '제거',\n    'edit'                  => '편집',\n    'view'                  => '보기',\n    'continue_editing'      => '편집',\n    'continue_creating'     => '계속 생성하기',\n    'detail'                => '세부 사항',\n    'browse'                => '찾아보기',\n    'reset'                 => '초기화',\n    'export'                => '내보내기',\n    'batch_delete'          => '일괄 삭제',\n    'save'                  => '저장',\n    'refresh'               => '새로고침',\n    'order'                 => '정렬',\n    'expand'                => '확대',\n    'collapse'              => '축소',\n    'filter'                => '필터',\n    'search'                => '검색',\n    'close'                 => '닫기',\n    'show'                  => '보기',\n    'entries'               => '항목',\n    'captcha'               => '캡차',\n    'action'                => '동작',\n    'title'                 => '제목',\n    'description'           => '설명',\n    'back'                  => '돌아가기',\n    'back_to_list'          => '목록으로 돌아가기',\n    'submit'                => '전송',\n    'menu'                  => '메뉴',\n    'input'                 => '입력',\n    'succeeded'             => '성공',\n    'failed'                => '실패',\n    'delete_confirm'        => '이 항목을 삭제하시겠습니까?',\n    'delete_succeeded'      => '삭제 성공 !',\n    'delete_failed'         => '삭제 실패 !',\n    'update_succeeded'      => '수정 성공 !',\n    'save_succeeded'        => '저장 성공 !',\n    'refresh_succeeded'     => '새로고침 성공 !',\n    'login_successful'      => '로그인 성공',\n    'choose'                => '선택',\n    'choose_file'           => '파일 선택',\n    'choose_image'          => '이미지 선택',\n    'more'                  => '더 보기',\n    'deny'                  => '권한 거부',\n    'administrator'         => '관리자',\n    'roles'                 => '역할',\n    'permissions'           => '권한',\n    'slug'                  => '',\n    'created_at'            => '생성일',\n    'updated_at'            => '수정일',\n    'alert'                 => '경계경보',\n    'parent_id'             => '상위',\n    'icon'                  => '아이콘',\n    'uri'                   => 'URI',\n    'operation_log'         => '작업 로그',\n    'parent_select_error'   => '상위 선택 오류',\n    'pagination'            => [\n        'range' => '전체 :total, :first 에서 :last 항목',\n    ],\n    'role'                  => '역할',\n    'permission'            => '권한',\n    'route'                 => '경로',\n    'confirm'               => '확인',\n    'cancel'                => '취소',\n    'http'                  => [\n        'method' => 'HTTP 방법',\n        'path'   => 'HTTP 경로',\n    ],\n    'all_methods_if_empty'  => '비어 있는 경우 모든 방법',\n    'all'                   => '전체',\n    'current_page'          => '현재 페이지',\n    'selected_rows'         => '선택된 행',\n    'upload'                => '업로드',\n    'new_folder'            => '새 폴더',\n    'time'                  => '시간',\n    'size'                  => '크기',\n    'listbox'               => [\n        'text_total'         => '전체 {0}',\n        'text_empty'         => '빈 목록',\n        'filtered'           => '{0} / {1}',\n        'filter_clear'       => '전체 보기',\n        'filter_placeholder' => '필터',\n    ],\n    'grid_items_selected' => '{n} 선택한 항목',\n\n    'menu_titles' => [],\n];\n"
  },
  {
    "path": "resources/lang/ms/admin.php",
    "content": "<?php\n\nreturn [\n    'online'                => 'Online',\n    'login'                 => 'Masuk',\n    'logout'                => 'Log keluar',\n    'setting'               => 'Menetapkan',\n    'name'                  => 'Nama',\n    'username'              => 'Nama pengguna',\n    'password'              => 'Kata laluan',\n    'password_confirmation' => 'Sahkan kata laluan',\n    'remember_me'           => 'Ingat saya',\n    'user_setting'          => 'Tetapan pengguna',\n    'avatar'                => 'Avatar',\n    'list'                  => 'Senarai',\n    'new'                   => 'Tambah',\n    'create'                => 'Buat',\n    'delete'                => 'Padam',\n    'remove'                => 'Keluarkan',\n    'edit'                  => 'Edit',\n    'continue_editing'      => 'Teruskan mengedit',\n    'continue_creating'     => 'Terus mencipta',\n    'view'                  => 'Lihat',\n    'detail'                => 'Terperinci',\n    'browse'                => 'Semak imbas',\n    'reset'                 => 'Tetapkan semula',\n    'export'                => 'Eksport',\n    'batch_delete'          => 'Padam tanggal',\n    'save'                  => 'Simpan',\n    'refresh'               => 'Muat semula',\n    'order'                 => 'Isih',\n    'expand'                => 'Perluas',\n    'collapse'              => 'Runtuh',\n    'filter'                => 'Pemeriksaan',\n    'search'                => 'Carian',\n    'close'                 => 'Tutup',\n    'show'                  => 'Paparan',\n    'entries'               => 'Perkara',\n    'captcha'               => 'Kod pengesahan',\n    'action'                => 'Operasi',\n    'title'                 => 'Tajuk',\n    'description'           => 'Pengenalan',\n    'back'                  => 'Kembali',\n    'back_to_list'          => 'Senarai pemulangan',\n    'submit'                => 'Hantar',\n    'menu'                  => 'Menu',\n    'input'                 => 'Input',\n    'succeeded'             => 'Kejayaan',\n    'failed'                => 'Kegagalan',\n    'delete_confirm'        => 'Sahkan pemadaman?',\n    'delete_succeeded'      => 'Dihapuskan berjaya!',\n    'delete_failed'         => 'Padam gagal!',\n    'update_succeeded'      => 'Berjaya dikemas kini!',\n    'save_succeeded'        => 'Disimpan berjaya!',\n    'refresh_succeeded'     => 'Segarkan semula!',\n    'login_successful'      => 'Log masuk yang berjaya!',\n    'choose'                => 'Pilih',\n    'choose_file'           => 'Pilih fail',\n    'choose_image'          => 'Pilih gambar',\n    'more'                  => 'Lebih banyak',\n    'deny'                  => 'Tiada akses',\n    'administrator'         => 'Pentadbir',\n    'roles'                 => 'Peranan',\n    'permissions'           => 'Kebenaran',\n    'slug'                  => 'Pengenalan',\n    'created_at'            => 'Dicipta pada',\n    'updated_at'            => 'Dikemaskini pada',\n    'alert'                 => 'Perhatian',\n    'parent_id'             => 'Menu ibu bapa',\n    'icon'                  => 'Ikon',\n    'uri'                   => 'Jalan',\n    'operation_log'         => 'Log operasi',\n    'parent_select_error'   => 'Ralat pemilihan ibu bapa',\n    'pagination'            => [\n        'range' => 'Dari :first Untuk :last ，Jumlah :total Perkara',\n    ],\n    'role'       => 'Peranan',\n    'permission' => 'Kebenaran',\n    'route'      => 'Routing',\n    'confirm'    => 'Sahkan',\n    'cancel'     => 'Batalkan',\n    'http'       => [\n        'method' => 'Kaedah HTTP',\n        'path'   => 'Laluan HTTP',\n    ],\n    'all_methods_if_empty' => 'Kosongkan mungkir kepada semua kaedah',\n    'all'                  => 'Semua',\n    'current_page'         => 'Halaman semasa',\n    'selected_rows'        => 'Barisan terpilih',\n    'upload'               => 'Muat naik',\n    'new_folder'           => 'Folder baru',\n    'time'                 => 'Masa',\n    'size'                 => 'Saiz',\n    'listbox'              => [\n        'text_total'         => 'Jumlah {0} Perkara',\n        'text_empty'         => 'Senarai kosong',\n        'filtered'           => '{0} / {1}',\n        'filter_clear'       => 'Tunjukkan semua',\n        'filter_placeholder' => 'Penapis',\n    ],\n    'menu_titles' => [],\n];\n"
  },
  {
    "path": "resources/lang/nl/admin.php",
    "content": "<?php\n\nreturn [\n    'online'                => 'Online',\n    'login'                 => 'Aanmelden',\n    'logout'                => 'Afmelden',\n    'setting'               => 'Instellingen',\n    'name'                  => 'Naam',\n    'username'              => 'Gebruikersnaam',\n    'password'              => 'Wachtwoord',\n    'password_confirmation' => 'Wachtwoord bevestigen',\n    'remember_me'           => 'Ingelogd blijven',\n    'user_setting'          => 'Instellingen',\n    'avatar'                => 'Profielfoto',\n    'list'                  => 'Lijst',\n    'new'                   => 'Nieuw',\n    'create'                => 'Maak',\n    'delete'                => 'Wissen',\n    'remove'                => 'Verwijder',\n    'edit'                  => 'Wijzigen',\n    'view'                  => 'Toon',\n    'continue_editing'      => 'Verder editeren',\n    'continue_creating'     => 'Doorgaan met maken',\n    'detail'                => 'Gedetailleerd',\n    'browse'                => 'Selecteer',\n    'reset'                 => 'Reset',\n    'export'                => 'Exporteer',\n    'batch_delete'          => 'Verwijder meerdere',\n    'save'                  => 'Opslaan',\n    'refresh'               => 'Vernieuw',\n    'order'                 => 'Sorteer',\n    'expand'                => 'Openklappen',\n    'collapse'              => 'Dichtklappen',\n    'filter'                => 'Filter',\n    'search'                => 'Zoeken',\n    'close'                 => 'Sluit',\n    'show'                  => 'Toon',\n    'entries'               => 'rijen',\n    'captcha'               => 'captcha',\n    'action'                => 'Actie',\n    'title'                 => 'Titel',\n    'description'           => 'Omschrijving',\n    'back'                  => 'Terug',\n    'back_to_list'          => 'Terug naar lijst',\n    'submit'                => 'Bevestig',\n    'menu'                  => 'Menu',\n    'input'                 => 'Input',\n    'succeeded'             => 'Gelukt',\n    'failed'                => 'Mislukt',\n    'delete_confirm'        => 'Bent u zeker dat u dit item wilt verwijderen ?',\n    'delete_succeeded'      => 'Verwijderd !',\n    'delete_failed'         => 'Kon niet verwijderen !',\n    'update_succeeded'      => 'Bijgewerkt !',\n    'save_succeeded'        => 'Opgeslaan !',\n    'refresh_succeeded'     => 'Vernieuwd !',\n    'login_successful'      => 'Ingelogd',\n    'choose'                => 'Kies',\n    'choose_file'           => 'Kies een bestand',\n    'choose_image'          => 'Kies een afbeelding',\n    'more'                  => 'Meer',\n    'deny'                  => 'Toegang geweigerd',\n    'administrator'         => 'Beheerder',\n    'roles'                 => 'Rollen',\n    'permissions'           => 'Rechten',\n    'slug'                  => 'Slug',\n    'created_at'            => 'Gemaakt op',\n    'updated_at'            => 'Gewijzigd op',\n    'alert'                 => 'Alert',\n    'parent_id'             => 'Parent',\n    'icon'                  => 'Icoon',\n    'uri'                   => 'URI',\n    'operation_log'         => 'Bewerkingslog',\n    'parent_select_error'   => '\\'Parent select\\' fout',\n    'pagination'            => [\n        'range' => ':first tot :last van :total rijen',\n    ],\n    'role'                  => 'Rol',\n    'permission'            => 'Permissie',\n    'route'                 => 'Route',\n    'confirm'               => 'Bevestig',\n    'cancel'                => 'Annuleer',\n    'http'                  => [\n        'method' => 'HTTP methode',\n        'path'   => 'HTTP pad',\n    ],\n    'all_methods_if_empty'  => 'Alle methodes indien geen geselecteerd',\n    'all'                   => 'Alle',\n    'current_page'          => 'Huidige pagina',\n    'selected_rows'         => 'Geselecteerde rijen',\n    'upload'                => 'Uploaden',\n    'new_folder'            => 'Nieuwe map',\n    'time'                  => 'Tijd',\n    'size'                  => 'Grootte',\n    'listbox'               => [\n        'text_total'         => 'Alle {0} getoond',\n        'text_empty'         => 'Lege lijst',\n        'filtered'           => '{0} / {1}',\n        'filter_clear'       => 'Toon alle',\n        'filter_placeholder' => 'Filter',\n    ],\n    'grid_items_selected'    => '{n} items geselecteerd',\n\n    'prev'                   => 'Vorige',\n    'next'                   => 'Volgende',\n    'quick_create'           => 'Snel aanmaken',\n    'menu_titles'            => [],\n];\n"
  },
  {
    "path": "resources/lang/pl/admin.php",
    "content": "<?php\n\nreturn [\n    'online'                => 'Online',\n    'login'                 => 'Login',\n    'logout'                => 'Logout',\n    'setting'               => 'Ustawienia',\n    'name'                  => 'Nazwa',\n    'username'              => 'Użytkownik',\n    'password'              => 'Hasło',\n    'password_confirmation' => 'Powtórz hasło',\n    'remember_me'           => 'Zapamiętaj mnie',\n    'user_setting'          => 'Ustawienia użytkownika',\n    'avatar'                => 'Avatar',\n    'list'                  => 'Lista',\n    'new'                   => 'Nowy',\n    'create'                => 'Utwórz',\n    'delete'                => 'Usuń',\n    'remove'                => 'Usuń',\n    'edit'                  => 'Edytuj',\n    'view'                  => 'Zobacz',\n    'continue_editing'      => 'Kontynuuj edycję',\n    'continue_creating'     => 'Kontynuuj tworzenie',\n    'detail'                => 'Szczegół',\n    'reset'                 => 'Resetuj',\n    'export'                => 'Eksportuj',\n    'batch_delete'          => 'Usuń wsadowo',\n    'save'                  => 'Zapisz',\n    'refresh'               => 'Odśwież',\n    'order'                 => 'Sortuj',\n    'expand'                => 'Rozwiń',\n    'collapse'              => 'Zwiń',\n    'filter'                => 'Filtruj',\n    'search'                => 'Szukaj',\n    'close'                 => 'Zamknij',\n    'show'                  => 'Wyświetl',\n    'items'                 => 'element',\n    'entries'               => 'wpisy',\n    'captcha'               => 'Captcha',\n    'action'                => 'Akcja',\n    'title'                 => 'Tytuł',\n    'description'           => 'Opis',\n    'back'                  => 'Wróć',\n    'back_to_list'          => 'Wróć do listy',\n    'submit'                => 'Wyślij',\n    'menu'                  => 'Menu',\n    'input'                 => 'Pole',\n    'succeeded'             => 'Sukces',\n    'failed'                => 'Błąd',\n    'delete_confirm'        => 'Czy na pewno chcesz usunąć?',\n    'delete_succeeded'      => 'Pomyślnie usunięto!',\n    'delete_failed'         => 'Usuwawnie nie powiodło się!',\n    'update_succeeded'      => 'Pomyślnie zmieniono!',\n    'save_succeeded'        => 'Pomyślnie zapisano!',\n    'refresh_succeeded'     => 'Pomyślnie odświeżono!',\n    'login_successful'      => 'Pomyślnie zalogowano',\n    'choose'                => 'Wybierz',\n    'choose_file'           => 'Wybierz plik',\n    'choose_image'          => 'Wybierz obraz',\n    'more'                  => 'Więcej',\n    'deny'                  => 'Brak dostępu',\n    'administrator'         => 'Administrator',\n    'roles'                 => 'Role',\n    'permissions'           => 'Uprawnienia',\n    'slug'                  => 'skrót',\n    'created_at'            => 'Utworzono',\n    'updated_at'            => 'zmieniono',\n    'alert'                 => 'Alarm',\n    'parent_id'             => 'Rodzic',\n    'icon'                  => 'Ikona',\n    'uri'                   => 'URI',\n    'operation_log'         => 'Dziennik operacji',\n    'parent_select_error'   => 'Wybór rodzica nie powiódł się',\n    'pagination'            => [\n        'range' => 'Wyświetlono :first do :last z wszystkich :total',\n    ],\n    'menu_titles'           => [],\n];\n"
  },
  {
    "path": "resources/lang/pt/admin.php",
    "content": "<?php\n\nreturn [\n    'online'                => 'Online',\n    'login'                 => 'Login',\n    'logout'                => 'Logout',\n    'setting'               => 'Configurações',\n    'name'                  => 'Nome',\n    'username'              => 'Nome de Utilizador',\n    'password'              => 'Palavra-Passe',\n    'password_confirmation' => 'Confirmação de Palavra-Passe',\n    'remember_me'           => 'Lembrar',\n    'user_setting'          => 'Configurações de Utilizador',\n    'avatar'                => 'Avatar',\n    'list'                  => 'Lista',\n    'new'                   => 'Novo',\n    'create'                => 'Criar',\n    'delete'                => 'Apagar',\n    'remove'                => 'Remover',\n    'edit'                  => 'Editar',\n    'view'                  => 'Visualizar',\n    'continue_editing'      => 'Continuar edição',\n    'continue_creating'     => 'Continue criando',\n    'detail'                => 'Detalhe',\n    'browse'                => 'Escolher',\n    'reset'                 => 'Reset',\n    'export'                => 'Exportar',\n    'batch_delete'          => 'Apagar vários',\n    'save'                  => 'Guardar',\n    'refresh'               => 'Actualizar',\n    'order'                 => 'Ordenar',\n    'expand'                => 'Expandir',\n    'collapse'              => 'Diminuir',\n    'filter'                => 'Filtrar',\n    'search'                => 'Pesquisa',\n    'close'                 => 'Fechar',\n    'show'                  => 'Mostrar',\n    'entries'               => 'Entradas',\n    'captcha'               => 'Captcha',\n    'action'                => 'Acção',\n    'title'                 => 'Título',\n    'description'           => 'Descrição',\n    'back'                  => 'Voltar',\n    'back_to_list'          => 'Voltar para Listagem',\n    'submit'                => 'Submeter',\n    'menu'                  => 'Menu',\n    'input'                 => 'Entrada',\n    'succeeded'             => 'Completado com Êxito',\n    'failed'                => 'Falhou',\n    'delete_confirm'        => 'Tem a certeza que deseja apagar este item?',\n    'delete_succeeded'      => 'Remoção completada com sucesso!',\n    'delete_failed'         => 'Remoção falhou!',\n    'update_succeeded'      => 'Actualização completada com sucesso!',\n    'save_succeeded'        => 'Gravação completada com sucesso!',\n    'refresh_succeeded'     => 'Actualizado com sucesso!',\n    'login_successful'      => 'Login com sucesso',\n    'choose'                => 'Escolher',\n    'choose_file'           => 'Selecionar ficheiro',\n    'choose_image'          => 'Selecionar imagem',\n    'more'                  => 'Mais',\n    'deny'                  => 'Permissão Negada',\n    'administrator'         => 'Administrador',\n    'roles'                 => 'Papéis',\n    'permissions'           => 'Permissões',\n    'slug'                  => 'Slug',\n    'created_at'            => 'Criado em',\n    'updated_at'            => 'Actualizado em',\n    'alert'                 => 'Alerta',\n    'parent_id'             => 'Pai',\n    'icon'                  => 'Icone',\n    'uri'                   => 'URI',\n    'operation_log'         => 'Registo de Operações',\n    'parent_select_error'   => 'Erro ao selecionar o pai',\n    'pagination'            => [\n        'range' => 'Mostrando :first até :last de :total entradas',\n    ],\n    'role'                  => 'Papel',\n    'permission'            => 'Permissão',\n    'route'                 => 'Rota',\n    'confirm'               => 'Confirmar',\n    'cancel'                => 'Cancelar',\n    'http'                  => [\n        'method' => 'Método HTTP',\n        'path'   => 'Caminho HTTP',\n    ],\n    'all_methods_if_empty'  => 'Todos os métodos por defeito caso vazio.',\n    'all'                   => 'Tudo',\n    'current_page'          => 'Página Actual',\n    'selected_rows'         => 'Linhas Selecionadas',\n    'upload'                => 'Upload',\n    'new_folder'            => 'Nova Pasta',\n    'time'                  => 'Tempo',\n    'size'                  => 'Tamanho',\n    'listbox'               => [\n        'text_total'         => 'Mostrando todos {0}',\n        'text_empty'         => 'Listagem Vazia',\n        'filtered'           => '{0} / {1}',\n        'filter_clear'       => 'Mostrar tudo',\n        'filter_placeholder' => 'Filtrar',\n    ],\n    'menu_titles'           => [],\n];\n"
  },
  {
    "path": "resources/lang/pt-BR/admin.php",
    "content": "<?php\n\nreturn [\n    'online'                => 'Online',\n    'login'                 => 'Login',\n    'logout'                => 'Logout',\n    'setting'               => 'Configurações',\n    'name'                  => 'Nome',\n    'username'              => 'Usuário',\n    'password'              => 'Senha',\n    'password_confirmation' => 'Confirmação da Senha',\n    'remember_me'           => 'Lembrar-me',\n    'user_setting'          => 'Configurações do Usuário',\n    'avatar'                => 'Avatar',\n    'list'                  => 'Lista',\n    'new'                   => 'Novo',\n    'create'                => 'Criar',\n    'delete'                => 'Apagar',\n    'remove'                => 'Remover',\n    'edit'                  => 'Editar',\n    'view'                  => 'Visualizar',\n    'continue_editing'      => 'Continuar editando',\n    'continue_creating'     => 'Continue criando',\n    'detail'                => 'Detalhe',\n    'browse'                => 'Escolher',\n    'reset'                 => 'Resetar',\n    'export'                => 'Exportar',\n    'batch_delete'          => 'Apagar vários',\n    'save'                  => 'Salvar',\n    'refresh'               => 'Atualizar',\n    'order'                 => 'Ordenar',\n    'expand'                => 'Expandir',\n    'collapse'              => 'Diminuir',\n    'filter'                => 'Filtrar',\n    'search'                => 'Pesquisa',\n    'close'                 => 'Fechar',\n    'show'                  => 'Mostrar',\n    'entries'               => 'Entradas',\n    'captcha'               => 'Captcha',\n    'action'                => 'Ação',\n    'title'                 => 'Título',\n    'description'           => 'Descrição',\n    'back'                  => 'Voltar',\n    'back_to_list'          => 'Voltar para Listagem',\n    'submit'                => 'Submeter',\n    'menu'                  => 'Menu',\n    'input'                 => 'Entrada',\n    'succeeded'             => 'Completado com Êxito',\n    'failed'                => 'Falhou',\n    'delete_confirm'        => 'Tem a certeza que deseja apagar este item?',\n    'delete_succeeded'      => 'Remoção completada com sucesso!',\n    'delete_failed'         => 'Remoção falhou!',\n    'update_succeeded'      => 'Atualização completada com sucesso!',\n    'save_succeeded'        => 'Gravação completada com sucesso!',\n    'refresh_succeeded'     => 'Atualizado com sucesso!',\n    'login_successful'      => 'Login com sucesso',\n    'choose'                => 'Escolher',\n    'choose_file'           => 'Selecionar pasta',\n    'choose_image'          => 'Selecionar imagem',\n    'more'                  => 'Mais',\n    'deny'                  => 'Permissão Negada',\n    'administrator'         => 'Administrador',\n    'roles'                 => 'Papéis',\n    'permissions'           => 'Permissões',\n    'slug'                  => 'Slug',\n    'created_at'            => 'Criado em',\n    'updated_at'            => 'Atualizado em',\n    'alert'                 => 'Alerta',\n    'parent_id'             => 'Pai',\n    'icon'                  => 'Ícone',\n    'uri'                   => 'URI',\n    'operation_log'         => 'Registo de Operações',\n    'parent_select_error'   => 'Erro ao selecionar o pai',\n    'pagination'            => [\n        'range' => 'Mostrando :first até :last de :total registros',\n    ],\n    'role'                  => 'Papel',\n    'permission'            => 'Permissão',\n    'route'                 => 'Rota',\n    'confirm'               => 'Confirmar',\n    'cancel'                => 'Cancelar',\n    'http'                  => [\n        'method' => 'Método HTTP',\n        'path'   => 'Caminho HTTP',\n    ],\n    'all_methods_if_empty'  => 'Todos os métodos por defeito caso vazio.',\n    'all'                   => 'Tudo',\n    'current_page'          => 'Página Atual',\n    'selected_rows'         => 'Linhas Selecionadas',\n    'upload'                => 'Upload',\n    'new_folder'            => 'Nova Pasta',\n    'time'                  => 'Tempo',\n    'size'                  => 'Tamanho',\n    'listbox'               => [\n        'text_total'         => 'Mostrando todos {0}',\n        'text_empty'         => 'Listagem Vazia',\n        'filtered'           => '{0} / {1}',\n        'filter_clear'       => 'Mostrar tudo',\n        'filter_placeholder' => 'Filtrar',\n    ],\n    'menu_titles'           => [],\n];\n"
  },
  {
    "path": "resources/lang/ru/admin.php",
    "content": "<?php\n\nreturn [\n    'online'                => 'Онлайн',\n    'login'                 => 'Войти',\n    'logout'                => 'Выйти',\n    'setting'               => 'Настройка',\n    'name'                  => 'Имя',\n    'username'              => 'Логин',\n    'password'              => 'Пароль',\n    'password_confirmation' => 'Подтверждение пароля',\n    'remember_me'           => 'Запомнить',\n    'user_setting'          => 'Настройки пользователя',\n    'avatar'                => 'Аватар',\n    'list'                  => 'Список',\n    'new'                   => 'Добавить',\n    'create'                => 'Новая запись',\n    'delete'                => 'Удалить',\n    'remove'                => 'Удалить',\n    'edit'                  => 'Редактировать',\n    'view'                  => 'Посмотреть',\n    'continue_editing'      => 'Продолжить редактировать',\n    'continue_creating'     => 'Продолжить создание',\n    'detail'                => 'Подробно',\n    'browse'                => 'Выбор файла',\n    'reset'                 => 'Сбросить',\n    'export'                => 'Экспорт',\n    'batch_delete'          => 'Пакетное удаление',\n    'save'                  => 'Сохранить',\n    'refresh'               => 'Обновить',\n    'order'                 => 'Сортировка',\n    'expand'                => 'Развернуть',\n    'collapse'              => 'Свернуть',\n    'filter'                => 'Фильтр',\n    'search'                => 'Поиск',\n    'close'                 => 'Закрыть',\n    'show'                  => 'Показать',\n    'entries'               => 'записей',\n    'captcha'               => 'Защитный код',\n    'action'                => 'Опции',\n    'title'                 => 'Название',\n    'description'           => 'Описание',\n    'back'                  => 'Назад',\n    'back_to_list'          => 'Вернуться к списку',\n    'submit'                => 'Отправить',\n    'menu'                  => 'Меню',\n    'input'                 => 'Ввод',\n    'succeeded'             => 'Завершена',\n    'failed'                => 'Ошибка',\n    'delete_confirm'        => 'Вы уверены, что хотите удалить эту запись?',\n    'delete_succeeded'      => 'Успешно удалено!',\n    'delete_failed'         => 'Ошибка при удалении!',\n    'update_succeeded'      => 'Успешно изменено!',\n    'save_succeeded'        => 'Успешно сохранено!',\n    'refresh_succeeded'     => 'Успешно обновлено!',\n    'login_successful'      => 'Авторизация успешна',\n    'choose'                => 'Выбрать',\n    'choose_file'           => 'Выбор файла',\n    'choose_image'          => 'Выбор изображения',\n    'more'                  => 'Еще',\n    'deny'                  => 'Доступ запрещен',\n    'administrator'         => 'Администратор',\n    'roles'                 => 'Роли',\n    'permissions'           => 'Доступ',\n    'slug'                  => 'Слаг',\n    'created_at'            => 'Дата создания',\n    'updated_at'            => 'Дата обновления',\n    'alert'                 => 'Ошибка',\n    'parent_id'             => 'Родитель',\n    'icon'                  => 'Иконка',\n    'uri'                   => 'URI',\n    'operation_log'         => 'Журнал событий',\n    'parent_select_error'   => 'Ошибка при выборе родителя',\n    'pagination'            => [\n        'range' => 'Записи с :first по :last из :total',\n    ],\n    'role'                  => 'Роль',\n    'permission'            => 'Доступ',\n    'route'                 => 'Путь',\n    'confirm'               => 'Подтвердить',\n    'cancel'                => 'Отмена',\n    'http'                  => [\n        'method' => 'HTTP метод',\n        'path'   => 'HTTP путь',\n    ],\n    'all_methods_if_empty'  => 'Все методы, если не указано',\n    'all'                   => 'Все',\n    'current_page'          => 'Текущая страница',\n    'selected_rows'         => 'Выбранные строки',\n    'upload'                => 'Загрузить',\n    'new_folder'            => 'Новая папка',\n    'time'                  => 'Время',\n    'size'                  => 'Размер',\n    'listbox'               => [\n        'text_total'         => 'Все: {0}',\n        'text_empty'         => 'Пустой список',\n        'filtered'           => '{0} / {1}',\n        'filter_clear'       => 'Показать все',\n        'filter_placeholder' => 'Фильтр',\n    ],\n    'grid_items_selected'    => '{n} элементов выбрано',\n\n    'menu_titles'            => [],\n    'prev'                   => 'Предыдущая',\n    'next'                   => 'Следующая',\n    'quick_create'           => 'Быстрое добавление',\n];\n"
  },
  {
    "path": "resources/lang/tr/admin.php",
    "content": "<?php\n\nreturn [\n    'online'                => 'Aktif',\n    'login'                 => 'Giriş',\n    'logout'                => 'Çıkış',\n    'setting'               => 'Ayarlar',\n    'name'                  => 'İsim',\n    'username'              => 'Kullanıcı adı',\n    'password'              => 'Parola',\n    'password_confirmation' => 'Parola tekrar',\n    'remember_me'           => 'Beni hatırla',\n    'user_setting'          => 'Kullanıcı ayarları',\n    'avatar'                => 'Profil resmi',\n    'list'                  => 'Liste',\n    'new'                   => 'Yeni',\n    'create'                => 'Oluştur',\n    'delete'                => 'Sil',\n    'remove'                => 'Kaldır',\n    'edit'                  => 'Düzenle',\n    'view'                  => 'Gör',\n    'detail'                => 'Ayrıntılar',\n    'browse'                => 'Gözat',\n    'reset'                 => 'Temizle',\n    'export'                => 'Dışarı aktar',\n    'batch_delete'          => 'Toplu sil',\n    'save'                  => 'Kaydet',\n    'refresh'               => 'Yenile',\n    'order'                 => 'Sırala',\n    'expand'                => 'Genişlet',\n    'collapse'              => 'Daralt',\n    'filter'                => 'Filtrele',\n    'search'                => 'arama',\n    'close'                 => 'Kapat',\n    'show'                  => 'Göster',\n    'entries'               => 'kayıtlar',\n    'captcha'               => 'Doğrulama',\n    'action'                => 'İşlem',\n    'title'                 => 'Başlık',\n    'description'           => 'Açıklama',\n    'back'                  => 'Geri',\n    'back_to_list'          => 'Listeye dön',\n    'submit'                => 'Gönder',\n    'continue_editing'      => 'Düzenlemeye devam et',\n    'continue_creating'     => 'Oluşturmaya devam et',\n    'menu'                  => 'Menü',\n    'input'                 => 'Giriş',\n    'succeeded'             => 'Başarılı',\n    'failed'                => 'Hatalı',\n    'delete_confirm'        => 'Silmek istediğinize emin misiniz?',\n    'delete_succeeded'      => 'Silme başarılı!',\n    'delete_failed'         => 'Silme hatalı!',\n    'update_succeeded'      => 'Güncellemen başarılı!',\n    'save_succeeded'        => 'Kaydetme başarılı!',\n    'refresh_succeeded'     => 'Yenileme başarılı!',\n    'login_successful'      => 'Giriş başarılı',\n    'choose'                => 'Seçin',\n    'choose_file'           => 'Dosya seçin',\n    'choose_image'          => 'Resim seçin',\n    'more'                  => 'Daha',\n    'deny'                  => 'İzin yok',\n    'administrator'         => 'Yönetici',\n    'roles'                 => 'Roller',\n    'permissions'           => 'İzinler',\n    'slug'                  => 'Kalıcı link',\n    'created_at'            => 'Oluşturulma tarihi',\n    'updated_at'            => 'Güncellenme tarihi',\n    'alert'                 => 'Uyarı',\n    'parent_id'             => 'Ebeveyn',\n    'icon'                  => 'İkon',\n    'uri'                   => 'URL',\n    'operation_log'         => 'İşlem kayıtları',\n    'parent_select_error'   => 'Üst hata',\n    'pagination'            => [\n        'range' => ':total kayıt içinden :first den :last e kadar',\n    ],\n    'role'                  => 'Rol',\n    'permission'            => 'İzin',\n    'route'                 => 'Rota',\n    'confirm'               => 'Onayla',\n    'cancel'                => 'İptal',\n    'http'                  => [\n        'method' => 'HTTP metodu',\n        'path'   => 'HTTP dizini',\n    ],\n    'all_methods_if_empty'  => 'Tüm metodlar boş ise',\n    'all'                   => 'Tümü',\n    'current_page'          => 'Mevcut sayfa',\n    'selected_rows'         => 'Seçilen kayıtlar',\n    'upload'                => 'Yükle',\n    'new_folder'            => 'Yeni dizin',\n    'time'                  => 'Zaman',\n    'size'                  => 'Boyut',\n    'listbox'               => [\n        'text_total'         => 'Toplam {0} kayıt',\n        'text_empty'         => 'Boş liste',\n        'filtered'           => '{0} / {1}',\n        'filter_clear'       => 'Tümünü göster',\n        'filter_placeholder' => 'Filtrele',\n    ],\n    'menu_titles'            => [],\n    'grid_items_selected'    => '{n} öğe seçildi',\n    'menu_titles'            => [],\n    'prev'                   => 'Önceki',\n    'next'                   => 'Sonraki',\n    'quick_create'           => 'Hemen oluştur',\n];\n"
  },
  {
    "path": "resources/lang/uk/admin.php",
    "content": "<?php\n\nreturn [\n    'online'                => 'В мережі',\n    'login'                 => 'Увійти',\n    'logout'                => 'Вийти',\n    'setting'               => 'Налаштування',\n    'name'                  => 'Ім\\'я',\n    'username'              => 'Логін',\n    'password'              => 'Пароль',\n    'password_confirmation' => 'Підтвердження пароля',\n    'remember_me'           => 'Запам\\'ятати',\n    'user_setting'          => 'Налаштування користувача',\n    'avatar'                => 'Аватар',\n    'list'                  => 'Список',\n    'new'                   => 'Додати',\n    'create'                => 'Новий запис',\n    'delete'                => 'Видалити',\n    'remove'                => 'Видалити',\n    'edit'                  => 'Редагувати',\n    'view'                  => 'Переглянути',\n    'continue_editing'      => 'Продовжити редагувати',\n    'continue_creating'     => 'Продовжуйте створювати',\n    'detail'                => 'Детально',\n    'browse'                => 'Вибір файлу',\n    'reset'                 => 'Очистити',\n    'export'                => 'Експорт',\n    'batch_delete'          => 'Пакетне видалення',\n    'save'                  => 'Зберегти',\n    'refresh'               => 'Оновити',\n    'order'                 => 'Сортування',\n    'expand'                => 'Розгорнути',\n    'collapse'              => 'Згорнути',\n    'filter'                => 'Фільтр',\n    'search'                => 'Пошук',\n    'close'                 => 'Закрити',\n    'show'                  => 'Показати',\n    'entries'               => 'записи',\n    'captcha'               => 'Захисний код',\n    'action'                => 'Опції',\n    'title'                 => 'Назва',\n    'description'           => 'Опис',\n    'back'                  => 'Назад',\n    'back_to_list'          => 'Повернутися до списку',\n    'submit'                => 'Створити',\n    'menu'                  => 'Меню',\n    'input'                 => 'Введення',\n    'succeeded'             => 'Завершено',\n    'failed'                => 'Помилка',\n    'delete_confirm'        => 'Ви впевнені, що хочете видалити цей запис?',\n    'delete_succeeded'      => 'Запис успішно видалено!',\n    'delete_failed'         => 'Помилка при видаленні!',\n    'update_succeeded'      => 'Запис успішно змінено!',\n    'save_succeeded'        => 'Запис успішно створено!',\n    'refresh_succeeded'     => 'Запис успішно оновлено!',\n    'login_successful'      => 'Авторизація успішна',\n    'choose'                => 'Вибрати',\n    'choose_file'           => 'Вибір файлу',\n    'choose_image'          => 'Вибір зображення',\n    'more'                  => 'Ще',\n    'deny'                  => 'Доступ заборонено',\n    'administrator'         => 'Адміністратор',\n    'roles'                 => 'Ролі',\n    'permissions'           => 'Доступ',\n    'slug'                  => 'Посилання',\n    'created_at'            => 'Дата створення',\n    'updated_at'            => 'Дата оновлення',\n    'alert'                 => 'Помилка',\n    'parent_id'             => 'Батько',\n    'icon'                  => 'Іконка',\n    'uri'                   => 'URI',\n    'operation_log'         => 'Журнал подій',\n    'parent_select_error'   => 'Помилка при виборі батька',\n    'pagination'            => [\n        'range'             => 'Записи з :first по :last з :total',\n    ],\n    'role'                  => 'Роль',\n    'permission'            => 'Дозвіл',\n    'route'                 => 'Маршрут',\n    'confirm'               => 'Підтвердити',\n    'cancel'                => 'Скасувати',\n    'http'                  => [\n        'method'            => 'HTTP метод',\n        'path'              => 'шлях HTTP',\n    ],\n    'all_methods_if_empty'  => 'Усі методи, якщо це порожнє',\n    'all'                   => 'Усі',\n    'current_page'          => 'Поточна сторінка',\n    'selected_rows'         => 'Вибрані рядки',\n    'upload'                => 'Завантажити',\n    'new_folder'            => 'Нова папка',\n    'time'                  => 'Час',\n    'size'                  => 'Розмір',\n    'listbox'               => [\n        'text_total'        => 'Показано всі {0}',\n        'text_empty'        => 'Пустий список',\n        'filtered'          => '{0} / {1}',\n        'filter_clear'      => 'Показати все',\n        'filter_placeholder'=> 'Фільтр',\n    ],\n    'grid_items_selected'    => '{n} елементів вибрано',\n\n    'menu_titles'            => [],\n    'prev'                   => 'Попередня',\n    'next'                   => 'Наступна',\n];\n"
  },
  {
    "path": "resources/lang/ur/admin.php",
    "content": "<?php\n\nreturn [\n    'online'                => 'جڑا ہوا۔',\n    'login'                 => 'لاگ ان کریں۔',\n    'logout'                => 'سائن آؤٹ',\n    'setting'               => 'ترتیبات۔',\n    'name'                  => 'نام۔',\n    'username'              => 'صارف کا نام',\n    'password'              => 'پاس ورڈ',\n    'password_confirmation' => 'پاسورڈ کی تو ثیق',\n    'remember_me'           => 'مجھے پہچانتے ہو',\n    'user_setting'          => 'صارف کی ترتیب۔',\n    'avatar'                => 'اوتار۔',\n    'list'                  => 'فہرست۔',\n    'new'                   => 'نئی',\n    'create'                => 'بنانا',\n    'delete'                => 'حذف کریں۔',\n    'remove'                => 'دور',\n    'edit'                  => 'ترمیم',\n    'view'                  => 'دیکھیں',\n    'continue_editing'      => 'ترمیم جاری رکھیں۔',\n    'continue_creating'     => 'بنانا جاری رکھیں۔',\n    'detail'                => 'تفصیل',\n    'browse'                => 'براؤز کریں۔',\n    'reset'                 => 'ری سیٹ کریں۔',\n    'export'                => 'برآمد کریں۔',\n    'batch_delete'          => 'بیچ ڈیلیٹ۔',\n    'save'                  => 'محفوظ کریں',\n    'refresh'               => 'ریفریش',\n    'order'                 => 'ترتیب',\n    'expand'                => 'پھیلائیں۔',\n    'collapse'              => 'گرنے',\n    'filter'                => 'فلٹر',\n    'search'                => 'تلاش کریں۔',\n    'close'                 => 'بند کریں',\n    'show'                  => 'دکھائیں۔',\n    'entries'               => 'اندراجات',\n    'captcha'               => 'کیپچا۔',\n    'action'                => 'عمل',\n    'title'                 => 'عنوان',\n    'description'           => 'تفصیل',\n    'back'                  => 'پیچھے',\n    'back_to_list'          => 'فہرست پر واپس جائیں۔',\n    'submit'                => 'جمع کرائیں',\n    'menu'                  => 'مینو',\n    'input'                 => 'ان پٹ۔',\n    'succeeded'             => 'کامیاب ہوا۔',\n    'failed'                => 'ناکام ہوگیا۔',\n    'delete_confirm'        => 'کیا آپ واقعی اس آئٹم کو حذف کرنا چاہتے ہیں؟',\n    'delete_succeeded'      => 'حذف کرنے میں کامیاب!',\n    'delete_failed'         => 'حذف کرنے میں ناکام!',\n    'update_succeeded'      => 'اپ ڈیٹ کامیاب!',\n    'save_succeeded'        => 'محفوظ کریں کامیاب!',\n    'refresh_succeeded'     => 'ریفریش کامیاب!',\n    'login_successful'      => 'لاگ ان کامیاب۔',\n    'choose'                => 'منتخب کریں۔',\n    'choose_file'           => 'فائل منتخب کریں۔',\n    'choose_image'          => 'تصویر منتخب کریں۔',\n    'more'                  => 'مزید',\n    'deny'                  => 'اجازت نہیں دی گئی',\n    'administrator'         => 'ایڈمنسٹریٹر۔',\n    'roles'                 => 'کردار۔',\n    'permissions'           => 'اجازت',\n    'slug'                  => 'سلگ۔',\n    'created_at'            => 'ایٹ تیار کیا گیا',\n    'updated_at'            => 'تازہ کاری شدہ',\n    'alert'                 => 'انتباہ',\n    'parent_id'             => 'والدین',\n    'icon'                  => 'شبیہہ۔',\n    'uri'                   => 'URI',\n    'operation_log'         => 'آپریشن لاگ',\n    'parent_select_error'   => 'بنیادی انتخاب غلطی',\n    'pagination'            => [\n        'range' => 'دکھا رہا ہے۔ :first کرنے کے لئے :last کے :total اندراجات',\n    ],\n    'role'                  => 'کردار۔',\n    'permission'            => 'اجازت۔',\n    'route'                 => 'راسته',\n    'confirm'               => 'تصدیق کریں۔',\n    'cancel'                => 'منسوخ کریں',\n    'http'                  => [\n        'method' => 'HTTP method',\n        'path'   => 'HTTP path',\n    ],\n    'all_methods_if_empty'  => 'اگر تمام خالی ہیں تو',\n    'all'                   => 'سب',\n    'current_page'          => 'موجودہ صفحہ',\n    'selected_rows'         => 'قطاریں منتخب کی گئیں۔',\n    'upload'                => 'اپ لوڈ کریں۔',\n    'new_folder'            => 'نیا فولڈر',\n    'time'                  => 'وقت',\n    'size'                  => 'سائز',\n    'listbox'               => [\n        'text_total'         => 'سب دکھا رہا ہے۔ {0}',\n        'text_empty'         => 'خالی فہرست۔',\n        'filtered'           => '{0} / {1}',\n        'filter_clear'       => 'سارے دکھاو',\n        'filter_placeholder' => 'فلٹر',\n    ],\n    'grid_items_selected'    => '{n} آئٹمز منتخب',\n\n    'menu_titles'            => [],\n    'prev'                   => 'پچھلا',\n    'next'                   => 'اگلے',\n    'quick_create'           => 'فوری تخلیق کریں۔',\n];\n"
  },
  {
    "path": "resources/lang/zh-CN/admin.php",
    "content": "<?php\n\nreturn [\n    'online'                => '在线',\n    'login'                 => '登录',\n    'logout'                => '登出',\n    'setting'               => '设置',\n    'name'                  => '名称',\n    'username'              => '用户名',\n    'password'              => '密码',\n    'password_confirmation' => '确认密码',\n    'remember_me'           => '记住我',\n    'user_setting'          => '用户设置',\n    'avatar'                => '头像',\n    'list'                  => '列表',\n    'new'                   => '新增',\n    'create'                => '创建',\n    'delete'                => '删除',\n    'remove'                => '移除',\n    'edit'                  => '编辑',\n    'continue_editing'      => '继续编辑',\n    'continue_creating'     => '继续创建',\n    'view'                  => '查看',\n    'detail'                => '详细',\n    'browse'                => '浏览',\n    'reset'                 => '重置',\n    'export'                => '导出',\n    'batch_delete'          => '批量删除',\n    'save'                  => '保存',\n    'refresh'               => '刷新',\n    'order'                 => '排序',\n    'expand'                => '展开',\n    'collapse'              => '收起',\n    'filter'                => '筛选',\n    'search'                => '搜索',\n    'close'                 => '关闭',\n    'show'                  => '显示',\n    'entries'               => '条',\n    'captcha'               => '验证码',\n    'action'                => '操作',\n    'title'                 => '标题',\n    'description'           => '简介',\n    'back'                  => '返回',\n    'back_to_list'          => '返回列表',\n    'submit'                => '提交',\n    'menu'                  => '菜单',\n    'input'                 => '输入',\n    'succeeded'             => '成功',\n    'failed'                => '失败',\n    'delete_confirm'        => '确认删除?',\n    'delete_succeeded'      => '删除成功 !',\n    'delete_failed'         => '删除失败 !',\n    'update_succeeded'      => '更新成功 !',\n    'save_succeeded'        => '保存成功 !',\n    'refresh_succeeded'     => '刷新成功 !',\n    'login_successful'      => '登录成功 !',\n    'choose'                => '选择',\n    'choose_file'           => '选择文件',\n    'choose_image'          => '选择图片',\n    'more'                  => '更多',\n    'deny'                  => '无权访问',\n    'administrator'         => '管理员',\n    'roles'                 => '角色',\n    'permissions'           => '权限',\n    'slug'                  => '标识',\n    'created_at'            => '创建时间',\n    'updated_at'            => '更新时间',\n    'alert'                 => '注意',\n    'parent_id'             => '父级菜单',\n    'icon'                  => '图标',\n    'uri'                   => '路径',\n    'operation_log'         => '操作日志',\n    'parent_select_error'   => '父级选择错误',\n    'pagination'            => [\n        'range' => '从 :first 到 :last ，总共 :total 条',\n    ],\n    'role'                  => '角色',\n    'permission'            => '权限',\n    'route'                 => '路由',\n    'confirm'               => '确认',\n    'cancel'                => '取消',\n    'http'                  => [\n        'method' => 'HTTP方法',\n        'path'   => 'HTTP路径',\n    ],\n    'all_methods_if_empty'  => '为空默认为所有方法',\n    'all'                   => '全部',\n    'current_page'          => '当前页',\n    'selected_rows'         => '选择的行',\n    'upload'                => '上传',\n    'new_folder'            => '新建文件夹',\n    'time'                  => '时间',\n    'size'                  => '大小',\n    'listbox'               => [\n        'text_total'         => '总共 {0} 项',\n        'text_empty'         => '空列表',\n        'filtered'           => '{0} / {1}',\n        'filter_clear'       => '显示全部',\n        'filter_placeholder' => '过滤',\n    ],\n    'grid_items_selected'    => '已选择 {n} 项',\n    'menu_titles'            => [],\n    'prev'                   => '上一步',\n    'next'                   => '下一步',\n    'quick_create'           => '快速创建',\n];\n"
  },
  {
    "path": "resources/lang/zh-TW/admin.php",
    "content": "<?php\n\nreturn [\n    'online'                => '在線',\n    'login'                 => '登錄',\n    'logout'                => '登出',\n    'setting'               => '設置',\n    'name'                  => '名稱',\n    'username'              => '用戶名',\n    'password'              => '密碼',\n    'password_confirmation' => '確認密碼',\n    'remember_me'           => '記住我',\n    'user_setting'          => '用戶設置',\n    'avatar'                => '頭像',\n    'list'                  => '列表',\n    'new'                   => '新增',\n    'create'                => '創建',\n    'delete'                => '刪除',\n    'remove'                => '移除',\n    'edit'                  => '編輯',\n    'view'                  => '查看',\n    'continue_editing'      => '繼續編輯',\n    'continue_creating'     => '繼續創建',\n    'detail'                => '詳細',\n    'browse'                => '瀏覽',\n    'reset'                 => '重置',\n    'export'                => '匯出',\n    'batch_delete'          => '批次刪除',\n    'save'                  => '儲存',\n    'refresh'               => '重新整理',\n    'order'                 => '排序',\n    'expand'                => '展開',\n    'collapse'              => '收起',\n    'filter'                => '篩選',\n    'search'                => '搜索',\n    'close'                 => '關閉',\n    'show'                  => '顯示',\n    'entries'               => '條',\n    'captcha'               => '驗證碼',\n    'action'                => '操作',\n    'title'                 => '標題',\n    'description'           => '簡介',\n    'back'                  => '返回',\n    'back_to_list'          => '返回列表',\n    'submit'                => '送出',\n    'menu'                  => '目錄',\n    'input'                 => '輸入',\n    'succeeded'             => '成功',\n    'failed'                => '失敗',\n    'delete_confirm'        => '確認刪除？',\n    'delete_succeeded'      => '刪除成功！',\n    'delete_failed'         => '刪除失敗！',\n    'update_succeeded'      => '更新成功！',\n    'save_succeeded'        => '儲存成功！',\n    'refresh_succeeded'     => '成功重新整理！',\n    'login_successful'      => '成功登入！',\n    'choose'                => '選擇',\n    'choose_file'           => '選擇檔案',\n    'choose_image'          => '選擇圖片',\n    'more'                  => '更多',\n    'deny'                  => '權限不足',\n    'administrator'         => '管理員',\n    'roles'                 => '角色',\n    'permissions'           => '權限',\n    'slug'                  => '標誌',\n    'created_at'            => '建立時間',\n    'updated_at'            => '更新時間',\n    'alert'                 => '警告',\n    'parent_id'             => '父目錄',\n    'icon'                  => '圖示',\n    'uri'                   => '路徑',\n    'operation_log'         => '操作記錄',\n    'parent_select_error'   => '父級選擇錯誤',\n    'pagination'            => [\n        'range' => '從 :first 到 :last ，總共 :total 條',\n    ],\n    'role'                  => '角色',\n    'permission'            => '權限',\n    'route'                 => '路由',\n    'confirm'               => '確認',\n    'cancel'                => '取消',\n    'http'                  => [\n        'method' => 'HTTP方法',\n        'path'   => 'HTTP路徑',\n    ],\n    'all_methods_if_empty'  => '為空默認為所有方法',\n    'all'                   => '全部',\n    'current_page'          => '現在頁面',\n    'selected_rows'         => '選擇的行',\n    'upload'                => '上傳',\n    'new_folder'            => '新建資料夾',\n    'time'                  => '時間',\n    'size'                  => '大小',\n    'listbox'               => [\n        'text_total'         => '總共 {0} 項',\n        'text_empty'         => '空列表',\n        'filtered'           => '{0} / {1}',\n        'filter_clear'       => '顯示全部',\n        'filter_placeholder' => '過濾',\n    ],\n    'menu_titles'            => [],\n    'prev'                   => '上一步',\n    'next'                   => '下一步',\n    'quick_create'           => '快速創建',\n];\n"
  },
  {
    "path": "resources/views/actions/form/checkbox.blade.php",
    "content": "<div class=\"form-group\">\n    <label>{{ $label }}</label>\n    <div>\n    @foreach($options as $option => $label)\n        <span class=\"icheck\">\n            <label class=\"checkbox-inline\">\n                <input type=\"checkbox\" name=\"{{$name}}[]\" value=\"{{$option}}\" class=\"{{$class}}\" {{ in_array($option, (array)old($column, $value)) || ($value === null && in_array($label, $checked)) ?'checked':'' }} {!! $attributes !!} />&nbsp;{{$label}}&nbsp;&nbsp;\n            </label>\n        </span>\n    @endforeach\n    </div>\n    <input type=\"hidden\" name=\"{{$name}}[]\">\n    @include('admin::actions.form.help-block')\n</div>\n"
  },
  {
    "path": "resources/views/actions/form/date.blade.php",
    "content": "<div class=\"form-group\">\n    <label>{{ $label }}</label>\n    <input style=\"width: 100%\" {!! $attributes !!} />\n    @include('admin::actions.form.help-block')\n</div>"
  },
  {
    "path": "resources/views/actions/form/file.blade.php",
    "content": "<div class=\"form-group\">\n    <label>{{ $label }}</label>\n    <input type=\"file\" class=\"{{$class}}\" name=\"{{$name}}\" {!! $attributes !!} />\n    @include('admin::actions.form.help-block')\n</div>\n"
  },
  {
    "path": "resources/views/actions/form/help-block.blade.php",
    "content": "@if($help)\n<span class=\"help-block\">\n    <i class=\"fa {{ \\Illuminate\\Support\\Arr::get($help, 'icon') }}\"></i>&nbsp;{!! \\Illuminate\\Support\\Arr::get($help, 'text') !!}\n</span>\n@endif"
  },
  {
    "path": "resources/views/actions/form/hidden.blade.php",
    "content": "<input type=\"hidden\" name=\"{{$name}}\" value=\"{{$value}}\" class=\"{{$class}}\" {!! $attributes !!} />\n"
  },
  {
    "path": "resources/views/actions/form/modal.blade.php",
    "content": "<div class=\"modal\" tabindex=\"-1\" role=\"dialog\" id=\"{{ $modal_id }}\">\n    <div class=\"modal-dialog {{ $modal_size }}\" role=\"document\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\n                <h4 class=\"modal-title\">{{ $title }}</h4>\n            </div>\n            <form>\n            <div class=\"modal-body\">\n                @foreach($fields as $field)\n                    {!! $field->render() !!}\n                @endforeach\n            </div>\n            <div class=\"modal-footer\">\n                <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\">{{ __('admin.close') }}</button>\n                <button type=\"submit\" class=\"btn btn-primary\">{{ __('admin.submit') }}</button>\n            </div>\n            </form>\n        </div><!-- /.modal-content -->\n    </div><!-- /.modal-dialog -->\n</div><!-- /.modal -->"
  },
  {
    "path": "resources/views/actions/form/muitplefile.blade.php",
    "content": "<div class=\"form-group\">\n    <label>{{ $label }}</label>\n    <input type=\"file\" class=\"{{$class}}\" name=\"{{$name}}[]\" {!! $attributes !!} multiple/>\n    @include('admin::actions.form.help-block')\n</div>\n"
  },
  {
    "path": "resources/views/actions/form/multipleselect.blade.php",
    "content": "<div class=\"form-group\">\n    <label>{{ $label }}</label>\n    <select class=\"form-control {{$class}}\" style=\"width: 100%;\" name=\"{{$name}}[]\" {!! $attributes !!} multiple data-placeholder=\"{{ $label }}\">\n\n        <option value=\"\"></option>\n        @foreach($options as $select => $option)\n            <option value=\"{{$select}}\" {{ in_array($select, old($column, $value) ?: []) ? 'selected' : '' }}>{{$option}}</option>\n        @endforeach\n    </select>\n    @include('admin::actions.form.help-block')\n</div>\n\n"
  },
  {
    "path": "resources/views/actions/form/radio.blade.php",
    "content": "<div class=\"form-group\">\n    <label>{{ $label }}</label>\n    <div>\n    @foreach($options as $option => $label)\n        <span class=\"icheck\">\n            <label class=\"radio-inline\">\n                <input type=\"radio\" name=\"{{$name}}\" value=\"{{$option}}\" class=\"minimal {{$class}}\" {{ ($option == old($column, $value)) || ($value === null && in_array($label, $checked)) ?'checked':'' }} {!! $attributes !!} />&nbsp;{{$label}}&nbsp;&nbsp;\n            </label>\n        </span>\n    @endforeach\n    </div>\n    @include('admin::actions.form.help-block')\n</div>\n"
  },
  {
    "path": "resources/views/actions/form/select.blade.php",
    "content": "<div class=\"form-group\">\n    <label>{{ $label }}</label>\n\n    <select class=\"form-control {{$class}}\" style=\"width: 100%;\" name=\"{{$name}}\" {!! $attributes !!} >\n\n        <option value=\"\"></option>\n        @foreach($options as $select => $option)\n            <option value=\"{{$select}}\" {{ $select == old($column, $value) ?'selected':'' }}>{{$option}}</option>\n        @endforeach\n    </select>\n    @include('admin::actions.form.help-block')\n</div>\n\n"
  },
  {
    "path": "resources/views/actions/form/text.blade.php",
    "content": "<div class=\"form-group\">\n    <label>{{ $label }}</label>\n    <input {!! $attributes !!}>\n    @include('admin::actions.form.help-block')\n</div>"
  },
  {
    "path": "resources/views/actions/form/textarea.blade.php",
    "content": "<div class=\"form-group\">\n    <label>{{ $label }}</label>\n    <textarea name=\"{{$name}}\" class=\"form-control {{$class}}\" rows=\"{{ $rows }}\" placeholder=\"{{ $placeholder }}\" {!! $attributes !!} >{{ old($column, $value) }}</textarea>\n    @include('admin::actions.form.help-block')\n</div>"
  },
  {
    "path": "resources/views/components/column-expand.blade.php",
    "content": "<div>\n    <span class=\"{{ $elementClass }}\" data-inserted=\"0\" data-key=\"{{ $key }}\" data-name=\"{{ $name }}\"\n          data-toggle=\"collapse\" data-target=\"#grid-collapse-{{ $name }}\">\n        <a href=\"javascript:void(0)\"><i class=\"fa fa-angle-double-down\"></i>&nbsp;&nbsp;{{ $value }}</a>\n    </span>\n    <template class=\"grid-expand-{{ $name }}\">\n        <tr style='background-color: #ecf0f5;'>\n            <td colspan='100%' style='padding:0 !important; border:0;'>\n                <div id=\"grid-collapse-{{ $name }}\" class=\"collapse\">\n                    <div style=\"padding: 10px 10px 0 10px;\" class=\"html\">\n                        @if($html)\n                            {!! $html !!}\n                        @else\n                            <div class=\"loading text-center\" style=\"padding: 20px 0px;\">\n                                <i class=\"fa fa-spinner fa-pulse fa-3x fa-fw\"></i>\n                            </div>\n                        @endif\n                    </div>\n                </div>\n            </td>\n        </tr>\n    </template>\n</div>\n\n<script>\n    var expand = $('.{{ $elementClass }}');\n\n    @if($async)\n\n    var load = function (url, target) {\n        $.get(url, function (data) {\n            target.find('.html').html(data);\n        });\n    };\n\n    expand.on('click', function (e) {\n        var target = $(this);\n        if (target.data('inserted') == '0') {\n            var key  = target.data('key');\n            var name = $(this).data('name');\n            var row = $(this).closest('tr');\n\n            row.after($('template.grid-expand-'+name).html());\n\n            $(this).data('inserted', 1);\n\n            load('{{ $url }}'+'&key='+key, $('#grid-collapse-'+name));\n        }\n\n        $(\"i\", this).toggleClass(\"fa-angle-double-down fa-angle-double-up\");\n    });\n\n    $(document).on('pjax:click', '.collapse a.pjax, .collapse a.pjax', function (e) {\n        console.log(11111);\n        // load($(this).attr('href'), $(this).parent('.collapse'));\n        e.preventDefault();\n        return false;\n    }).on('pjax:submit', '.collapse .box-header form', function (e) {\n        // load($(this).attr('action')+'&'+$(this).serialize(), $(this).parent('.collapse'));\n        return false;\n    });\n\n    @else\n\n    expand.on('click', function () {\n\n        if ($(this).data('inserted') == '0') {\n\n            var name = $(this).data('name');\n            var row = $(this).closest('tr');\n\n            row.after($('template.grid-expand-'+name).html());\n\n            $(this).data('inserted', 1);\n        }\n\n        $(\"i\", this).toggleClass(\"fa-angle-double-down fa-angle-double-up\");\n    });\n\n    @endif\n\n    @if ($expand)\n        expand.trigger('click');\n    @endif\n</script>\n\n@if($loadGrid)\n<style>\n    .collapse .grid-box .box-header:first-child {\n        display: none;\n    }\n</style>\n@endif"
  },
  {
    "path": "resources/views/components/column-modal.blade.php",
    "content": "<span data-toggle=\"modal\" data-target=\"#grid-modal-{{ $name }}\" data-key=\"{{ $key }}\">\n   <a href=\"javascript:void(0)\"><i class=\"fa fa-clone\"></i>&nbsp;&nbsp;{{ $value }}</a>\n</span>\n\n<div class=\"modal grid-modal fade\" id=\"grid-modal-{{ $name }}\" tabindex=\"-1\" role=\"dialog\">\n    <div class=\"modal-dialog modal-lg\" role=\"document\">\n        <div class=\"modal-content\" style=\"border-radius: 5px;\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\"><span aria-hidden=\"true\">&times;</span></button>\n                <h4 class=\"modal-title\">{{ $title }}</h4>\n            </div>\n            <div class=\"modal-body\">\n                {!! $html !!}\n            </div>\n        </div>\n    </div>\n</div>\n\n@if($grid)\n<style>\n    .box.grid-box {\n        box-shadow: none;\n        border-top: none;\n    }\n\n    .grid-box .box-header:first-child {\n        display: none;\n    }\n</style>\n@endif\n\n@if($async)\n<script>\n    var modal = $('#grid-modal-{{ $name }}');\n    var modalBody = modal.find('.modal-body');\n\n    var load = function (url) {\n\n        modalBody.html(\"<div class='loading text-center' style='height:200px;'>\\\n                <i class='fa fa-spinner fa-pulse fa-3x fa-fw' style='margin-top: 80px;'></i>\\\n            </div>\");\n\n        $.get(url, function (data) {\n            modalBody.html(data);\n        });\n    };\n\n    modal.on('show.bs.modal', function (e) {\n        var key = $(e.relatedTarget).data('key');\n        load('{{ $url }}'+'&key='+key);\n    }).on('click', '.page-item a, .filter-box a', function (e) {\n        load($(this).attr('href'));\n        e.preventDefault();\n    }).on('submit', '.box-header form', function (e) {\n        load($(this).attr('action')+'&'+$(this).serialize());\n        return false;\n    });\n</script>\n@endif\n"
  },
  {
    "path": "resources/views/components/filepicker.blade.php",
    "content": "\n<template>\n    <div class=\"modal fade picker\" id=\"{{ $modal }}\" tabindex=\"-1\" role=\"dialog\">\n        <div class=\"modal-dialog modal-lg\" role=\"document\">\n            <div class=\"modal-content\" style=\"border-radius: 5px;\">\n                <div class=\"modal-header\">\n                    <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\">\n                        <span aria-hidden=\"true\">&times;</span>\n                    </button>\n                    <h4 class=\"modal-title\">{{ admin_trans('admin.choose') }}</h4>\n                </div>\n                <div class=\"modal-body\">\n                    <div class=\"loading text-center\">\n                        <i class=\"fa fa-spinner fa-pulse fa-3x fa-fw\"></i>\n                    </div>\n                </div>\n                <div class=\"modal-footer\">\n                    <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\">{{ admin_trans('admin.cancel') }}</button>\n                    <button type=\"button\" class=\"btn btn-primary submit\">{{ admin_trans('admin.submit') }}</button>\n                </div>\n            </div>\n        </div>\n    </div>\n</template>\n\n<script>\n\nvar pickInput = $(\"{{ $selector }}\");\nvar separator = '{{ $separator }}';\nvar modal = $('#{{ $modal }}');\nvar value;\nvar refresh = function () {};\n\nmodal.on('show.bs.modal', function (e) {\n    load(\"{!! $url !!}\");\n}).on('click', '.page-item a, .filter-box a', function (e) {\n    load($(this).attr('href'));\n    e.preventDefault();\n}).on('click', 'tr', function (e) {\n    $(this).find('input.select').iCheck('toggle');\n    e.preventDefault();\n}).on('submit', '.box-header form', function (e) {\n    load($(this).attr('action')+'&'+$(this).serialize());\n    return false;\n})\n\n@if($multiple)\n\n    var updateValue = function () {\n        value = pickInput.val().split(separator).filter(function (val) {\n            return val != '';\n        });\n    };\n\n    var load = function (url) {\n        $.get(url, function (data) {\n            modal.find('.modal-body').html(data);\n            modal.find('input.select').iCheck({\n                radioClass:'iradio_minimal-blue',\n                checkboxClass:'icheckbox_minimal-blue'\n            });\n            modal.find('.box-header:first').hide();\n\n            modal.find('input.select').each(function (index, el) {\n                if ($.inArray($(el).val().toString(), value) >=0 ) {\n                    $(el).iCheck('toggle');\n                }\n            });\n        });\n    };\n\n    modal.on('ifChecked', 'input.select', function (e) {\n        if ($(this).val().length == 0) {\n            return;\n        }\n\n        if (value.indexOf($(this).val()) < 0) {\n            value.push($(this).val());\n        }\n    }).on('ifUnchecked', 'input.select', function (e) {\n        var val = $(this).val();\n        var index = value.indexOf(val);\n        if (index !== -1) {\n            value.splice(index, 1);\n        }\n    }).find('.modal-footer .submit').click(function () {\n        pickInput.val(value.join(separator));\n        modal.modal('toggle');\n\n        refresh();\n    });\n\n@else\n\n    var updateValue = function () {\n        value = pickInput.val();\n    };\n\n    var load = function (url) {\n        $.get(url, function (data) {\n            modal.find('.modal-body').html(data);\n            modal.find('input.select').iCheck({\n                radioClass:'iradio_minimal-blue',\n                checkboxClass:'icheckbox_minimal-blue'\n            });\n            modal.find('.box-header:first').hide();\n\n            modal.find('input.select').each(function (index, el) {\n                if ($(el).val() == value) {\n                    $(el).iCheck('toggle');\n                }\n            });\n        });\n    };\n\n    modal.on('ifChecked', 'input.select', function (e) {\n        value = $(this).val();\n    }).find('.modal-footer .submit').click(function () {\n        pickInput.val(value);\n        modal.modal('toggle');\n\n        refresh();\n    });\n\n@endif\n\nupdateValue();\n\n$('.picker-file-preview').on('click', 'a.remove', function () {\n    var preview = $(this).parents('.file-preview-frame');\n    var current = preview.data('val');\n\n    preview.addClass('hide');\n\n    var input = pickInput.val().split(separator);\n\n    var index = input.indexOf(current);value\n    if (index !== -1) {\n        input.splice(index, 1);\n    }\n\n    pickInput.val(input.join(separator));\n\n    updateValue();\n\n    if (input.length === 0) {\n        $(this).parents('.picker-file-preview').addClass('hide');\n    }\n});\n\n@if($is_file)\nrefresh = function () {\n\n    var values = (typeof value == 'string') ? [value] : value;\n    var preview = pickInput.parent().siblings('.picker-file-preview');\n    var url_tpl = '{{ $url_tpl }}';\n\n    @if($is_image)\n    var template = $('template#image-preview')\n    @else\n    var template = $('template#file-preview')\n    @endif\n\n    preview.empty();\n\n    values.forEach(function (item) {\n        var url = url_tpl.replace('__URL__', item);\n        preview.append(\n            template.html()\n                .replace(/_url_/g, url)\n                .replace(/_val_/g, item)\n                .replace(/_name_/g, url.split('/').pop())\n        );\n    });\n\n    if (values.length > 0) {\n        preview.removeClass('hide');\n    }\n};\n@endif\n\n</script>\n\n<style>\n    .picker.modal tr {\n        cursor: pointer;\n    }\n\n    .picker.modal .box {\n        border-top: none;\n        margin-bottom: 0;\n        box-shadow: none;\n    }\n\n    @if($is_file)\n    .picker-file-preview {\n        overflow: hidden;\n        border-radius: 5px;\n        border: 1px solid #ddd;\n        padding: 8px;\n        width: 100%;\n        margin-bottom: 5px;\n    }\n\n    .picker-file-preview .file-preview-frame {\n        margin: 8px;\n        border: 1px solid rgba(0, 0, 0, .2);\n        box-shadow: 0 0 10px 0 rgba(0, 0, 0, .2);\n        padding: 6px;\n        float: left;\n        text-align: center;\n        width: 213px;\n    }\n\n    .picker-file-preview .file-content {\n        font-size: 6em;\n    }\n\n    .picker-file-preview .file-caption-info {\n        display: block;\n        white-space: nowrap;\n        overflow: hidden;\n        text-overflow: ellipsis;\n        width: 160px;\n        height: 20px;\n        margin: auto;\n        font-size: 11px;\n        color: #777;\n    }\n\n    .picker-file-preview .file-actions {\n        text-align: right;\n        margin-top: 20px;\n    }\n\n    .picker-file-preview img {\n        max-width: 160px;\n        max-height: 160px;\n    }\n    @endif\n</style>\n\n"
  },
  {
    "path": "resources/views/components/fullscreen.blade.php",
    "content": "<li>\n    <a href=\"javascript:void(0);\" class=\"nav-fullscreen\">\n        <i class=\"fa fa-arrows-alt\"></i>\n    </a>\n</li>\n\n<script>\n    function launchFullscreen(element) {\n        if(element.requestFullscreen) {\n            element.requestFullscreen();\n        } else if(element.mozRequestFullScreen) {\n            element.mozRequestFullScreen();\n        } else if(element.msRequestFullscreen){\n            element.msRequestFullscreen();\n        } else if(element.webkitRequestFullscreen) {\n            element.webkitRequestFullScreen();\n        }\n    }\n\n    function exitFullscreen() {\n        if (document.exitFullscreen) {\n            document.exitFullscreen();\n        } else if (document.msExitFullscreen) {\n            document.msExitFullscreen();\n        } else if (document.mozCancelFullScreen) {\n            document.mozCancelFullScreen();\n        } else if (document.webkitExitFullscreen) {\n            document.webkitExitFullscreen();\n        }\n    }\n\n    $('.nav-fullscreen').click(function () {\n        if (document.fullscreenElement) {\n            exitFullscreen();\n        } else {\n            launchFullscreen(document.body)\n        }\n    });\n</script>\n"
  },
  {
    "path": "resources/views/components/grid-column-selector.blade.php",
    "content": "<div class=\"dropdown pull-right column-selector\">\n    <button type=\"button\" class=\"btn btn-sm btn-instagram dropdown-toggle\" data-toggle=\"dropdown\">\n        <i class=\"fa fa-table\"></i>\n        &nbsp;\n        <span class=\"caret\"></span>\n    </button>\n    <ul class=\"dropdown-menu\" role=\"menu\">\n        <li>\n            <ul>\n                @foreach($columns as $key => $label)\n                @php\n                if (empty($visible)) {\n                    $checked = 'checked';\n                } else {\n                    $checked = in_array($key, $visible) ? 'checked' : '';\n                }\n                @endphp\n\n                <li class=\"checkbox icheck\">\n                    <label>\n                        <input type=\"checkbox\" class=\"column-select-item\" value=\"{{ $key }}\" {{ $checked }}/>&nbsp;&nbsp;&nbsp;{{ $label }}\n                    </label>\n                </li>\n                @endforeach\n            </ul>\n        </li>\n        <li class=\"divider\"></li>\n        <li class=\"text-right\">\n            <button class=\"btn btn-sm btn-default column-select-all\">{{ __('admin.all') }}</button>&nbsp;&nbsp;\n            <button class=\"btn btn-sm btn-primary column-select-submit\">{{ __('admin.submit') }}</button>\n        </li>\n    </ul>\n</div>\n\n<style>\n.column-selector {\n    margin-right: 10px;\n}\n\n.column-selector .dropdown-menu {\n    padding: 10px;\n    height: auto;\n    max-height: 500px;\n    overflow-x: hidden;\n}\n\n.column-selector .dropdown-menu ul {\n    padding: 0;\n}\n\n.column-selector .dropdown-menu ul li {\n    margin: 0;\n}\n\n.column-selector .dropdown-menu label {\n    width: 100%;\n    padding: 3px;\n}\n</style>\n\n<script>\n$('.column-select-submit').on('click', function () {\n\n    var defaults = @json($defaults);\n    var selected = [];\n\n    $('.column-select-item:checked').each(function () {\n        selected.push($(this).val());\n    });\n\n    if (selected.length == 0) {\n        return;\n    }\n\n    var url = new URL(location);\n\n    if (selected.sort().toString() == defaults.sort().toString()) {\n        url.searchParams.delete('_columns_');\n    } else {\n        url.searchParams.set('_columns_', selected.join());\n    }\n\n    $.pjax({container:'#pjax-container', url: url.toString()});\n});\n\n$('.column-select-all').on('click', function () {\n    $('.column-select-item').iCheck('check');\n    return false;\n});\n\n$('.column-select-item').iCheck({\n    checkboxClass:'icheckbox_minimal-blue'\n});\n</script>\n"
  },
  {
    "path": "resources/views/components/refresh-btn.blade.php",
    "content": "<li>\n    <a href=\"javascript:void(0);\" class=\"container-refresh\">\n        <i class=\"fa fa-refresh\"></i>\n    </a>\n</li>\n<script>\n    $('.container-refresh').off('click').on('click', function() {\n        $.admin.reload();\n        $.admin.toastr.success('{{ __('admin.refresh_succeeded') }}', '', {positionClass:\"toast-top-center\"});\n    });\n</script>\n"
  },
  {
    "path": "resources/views/content.blade.php",
    "content": "@extends('admin::index', ['header' => strip_tags($header)])\n\n@section('content')\n    <section class=\"content-header\">\n        <h1>\n            {!! $header ?: trans('admin.title') !!}\n            <small>{!! $description ?: trans('admin.description') !!}</small>\n        </h1>\n\n        <!-- breadcrumb start -->\n        @if ($breadcrumb)\n        <ol class=\"breadcrumb\" style=\"margin-right: 30px;\">\n            <li><a href=\"{{ admin_url('/') }}\"><i class=\"fa fa-dashboard\"></i> {{__('Home')}}</a></li>\n            @foreach($breadcrumb as $item)\n                @if($loop->last)\n                    <li class=\"active\">\n                        @if (\\Illuminate\\Support\\Arr::has($item, 'icon'))\n                            <i class=\"fa fa-{{ $item['icon'] }}\"></i>\n                        @endif\n                        {{ $item['text'] }}\n                    </li>\n                @else\n                <li>\n                    @if (\\Illuminate\\Support\\Arr::has($item, 'url'))\n                        <a href=\"{{ admin_url(\\Illuminate\\Support\\Arr::get($item, 'url')) }}\">\n                            @if (\\Illuminate\\Support\\Arr::has($item, 'icon'))\n                                <i class=\"fa fa-{{ $item['icon'] }}\"></i>\n                            @endif\n                            {{ $item['text'] }}\n                        </a>\n                    @else\n                        @if (\\Illuminate\\Support\\Arr::has($item, 'icon'))\n                            <i class=\"fa fa-{{ $item['icon'] }}\"></i>\n                        @endif\n                        {{ $item['text'] }}\n                    @endif\n                </li>\n                @endif\n            @endforeach\n        </ol>\n        @elseif(config('admin.enable_default_breadcrumb'))\n        <ol class=\"breadcrumb\" style=\"margin-right: 30px;\">\n            <li><a href=\"{{ admin_url('/') }}\"><i class=\"fa fa-dashboard\"></i> {{__('Home')}}</a></li>\n            @for($i = 2; $i <= count(Request::segments()); $i++)\n                <li>\n                {{ucfirst(Request::segment($i))}}\n                </li>\n            @endfor\n        </ol>\n        @endif\n\n        <!-- breadcrumb end -->\n\n    </section>\n\n    <section class=\"content\">\n\n        @include('admin::partials.alerts')\n        @include('admin::partials.exception')\n        @include('admin::partials.toastr')\n\n        @if($_view_)\n            @include($_view_['view'], $_view_['data'])\n        @else\n            {!! $_content_ !!}\n        @endif\n\n    </section>\n@endsection\n"
  },
  {
    "path": "resources/views/dashboard/dependencies.blade.php",
    "content": "<div class=\"box box-default\">\n    <div class=\"box-header with-border\">\n        <h3 class=\"box-title\">Dependencies</h3>\n\n        <div class=\"box-tools pull-right\">\n            <button type=\"button\" class=\"btn btn-box-tool\" data-widget=\"collapse\"><i class=\"fa fa-minus\"></i>\n            </button>\n            <button type=\"button\" class=\"btn btn-box-tool\" data-widget=\"remove\"><i class=\"fa fa-times\"></i></button>\n        </div>\n    </div>\n\n    <!-- /.box-header -->\n    <div class=\"box-body dependencies\">\n        <div class=\"table-responsive\">\n            <table class=\"table table-striped\">\n                @foreach($dependencies as $dependency => $version)\n                <tr>\n                    <td width=\"240px\">{{ $dependency }}</td>\n                    <td><span class=\"label label-primary\">{{ $version }}</span></td>\n                </tr>\n                @endforeach\n            </table>\n        </div>\n        <!-- /.table-responsive -->\n    </div>\n    <!-- /.box-body -->\n</div>\n\n<script>\n    $('.dependencies').slimscroll({height:'510px',size:'3px'});\n</script>\n"
  },
  {
    "path": "resources/views/dashboard/environment.blade.php",
    "content": "<div class=\"box box-default\">\n    <div class=\"box-header with-border\">\n        <h3 class=\"box-title\">Environment</h3>\n\n        <div class=\"box-tools pull-right\">\n            <button type=\"button\" class=\"btn btn-box-tool\" data-widget=\"collapse\"><i class=\"fa fa-minus\"></i>\n            </button>\n            <button type=\"button\" class=\"btn btn-box-tool\" data-widget=\"remove\"><i class=\"fa fa-times\"></i></button>\n        </div>\n    </div>\n\n    <!-- /.box-header -->\n    <div class=\"box-body\">\n        <div class=\"table-responsive\">\n            <table class=\"table table-striped\">\n\n                @foreach($envs as $env)\n                <tr>\n                    <td width=\"120px\">{{ $env['name'] }}</td>\n                    <td>{{ $env['value'] }}</td>\n                </tr>\n                @endforeach\n            </table>\n        </div>\n        <!-- /.table-responsive -->\n    </div>\n    <!-- /.box-body -->\n</div>"
  },
  {
    "path": "resources/views/dashboard/extensions.blade.php",
    "content": "<style>\n    .ext-icon {\n        color: rgba(0,0,0,0.5);\n        margin-left: 10px;\n    }\n    .installed {\n        color: #00a65a;\n        margin-right: 10px;\n    }\n</style>\n<div class=\"box box-default\">\n    <div class=\"box-header with-border\">\n        <h3 class=\"box-title\">Available extensions</h3>\n\n        <div class=\"box-tools pull-right\">\n            <button type=\"button\" class=\"btn btn-box-tool\" data-widget=\"collapse\"><i class=\"fa fa-minus\"></i>\n            </button>\n            <button type=\"button\" class=\"btn btn-box-tool\" data-widget=\"remove\"><i class=\"fa fa-times\"></i></button>\n        </div>\n    </div>\n    <!-- /.box-header -->\n    <div class=\"box-body\">\n        <ul class=\"products-list product-list-in-box\">\n\n            @foreach($extensions as $extension)\n            <li class=\"item\">\n                <div class=\"product-img\">\n                    <i class=\"fa fa-{{$extension['icon']}} fa-2x ext-icon\"></i>\n                </div>\n                <div class=\"product-info\">\n                    <a href=\"{{ $extension['link'] }}\" target=\"_blank\" class=\"product-title\">\n                        {{ $extension['name'] }}\n                    </a>\n                    @if($extension['installed'])\n                        <span class=\"pull-right installed\"><i class=\"fa fa-check\"></i></span>\n                    @endif\n                </div>\n            </li>\n            @endforeach\n\n            <!-- /.item -->\n        </ul>\n    </div>\n    <!-- /.box-body -->\n    <div class=\"box-footer text-center\">\n        <a href=\"https://github.com/laravel-admin-extensions\" target=\"_blank\" class=\"uppercase\">View All Extensions</a>\n    </div>\n    <!-- /.box-footer -->\n</div>"
  },
  {
    "path": "resources/views/dashboard/title.blade.php",
    "content": "<style>\n    .title {\n        font-size: 50px;\n        color: #636b6f;\n        font-family: 'Raleway', sans-serif;\n        font-weight: 100;\n        display: block;\n        text-align: center;\n        margin: 20px 0 10px 0px;\n    }\n\n    .links {\n        text-align: center;\n        margin-bottom: 20px;\n    }\n\n    .links > a {\n        color: #636b6f;\n        padding: 0 25px;\n        font-size: 12px;\n        font-weight: 600;\n        letter-spacing: .1rem;\n        text-decoration: none;\n        text-transform: uppercase;\n    }\n</style>\n\n<div class=\"title\">\n    Laravel-admin\n</div>\n<div class=\"links\">\n    <a href=\"https://github.com/z-song/laravel-admin\" target=\"_blank\">Github</a>\n    <a href=\"http://laravel-admin.org/docs\"  target=\"_blank\">Documentation</a>\n    <a href=\"http://laravel-admin.org/demo\"  target=\"_blank\">Demo</a>\n</div>"
  },
  {
    "path": "resources/views/filter/between.blade.php",
    "content": "<div class=\"form-group\">\n    <label class=\"col-sm-2 control-label\">{{$label}}</label>\n    <div class=\"col-sm-8\" >\n        <div class=\"input-group input-group-sm\">\n            <input type=\"text\" class=\"form-control {{$id['start']}}\" placeholder=\"{{$label}}\" name=\"{{$name['start']}}\" value=\"{{ request()->input(\"{$column}.start\", \\Illuminate\\Support\\Arr::get($value, 'start')) }}\">\n            <span class=\"input-group-addon\" style=\"border-left: 0; border-right: 0;\">-</span>\n            <input type=\"text\" class=\"form-control {{$id['end']}}\" placeholder=\"{{$label}}\" name=\"{{$name['end']}}\" value=\"{{ request()->input(\"{$column}.end\", \\Illuminate\\Support\\Arr::get($value, 'end')) }}\">\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "resources/views/filter/betweenDatetime.blade.php",
    "content": "<div class=\"form-group\">\n    <label class=\"col-sm-2 control-label\">{{$label}}</label>\n    <div class=\"col-sm-8\" >\n        <div class=\"input-group input-group-sm\">\n            <div class=\"input-group-addon\">\n                <i class=\"fa fa-calendar\"></i>\n            </div>\n            <input type=\"text\"\n                   class=\"form-control\"\n                   id=\"{{$id['start']}}\"\n                   placeholder=\"{{$label}}\"\n                   name=\"{{$name['start']}}\"\n                   value=\"{{ request()->input(\"{$column}.start\", \\Illuminate\\Support\\Arr::get($value, 'start')) }}\"\n                   autocomplete=\"off\"\n            />\n\n            <span class=\"input-group-addon\" style=\"border-left: 0; border-right: 0;\">-</span>\n\n            <input type=\"text\"\n                   class=\"form-control\"\n                   id=\"{{$id['end']}}\"\n                   placeholder=\"{{$label}}\"\n                   name=\"{{$name['end']}}\"\n                   value=\"{{ request()->input(\"{$column}.end\", \\Illuminate\\Support\\Arr::get($value, 'end')) }}\"\n                   autocomplete=\"off\"\n            />\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "resources/views/filter/button.blade.php",
    "content": "<div class=\"btn-group\" style=\"margin-right: 5px\" data-toggle=\"buttons\">\n    <label class=\"btn btn-sm btn-dropbox {{ $btn_class }} {{ $expand ? 'active' : '' }}\" title=\"{{ trans('admin.filter') }}\">\n        <input type=\"checkbox\"><i class=\"fa fa-filter\"></i><span class=\"hidden-xs\">&nbsp;&nbsp;{{ trans('admin.filter') }}</span>\n    </label>\n\n    @if($scopes->isNotEmpty())\n    <button type=\"button\" class=\"btn btn-sm btn-dropbox dropdown-toggle\" data-toggle=\"dropdown\">\n\n        <span>{{ $label }}</span>\n        <span class=\"caret\"></span>\n        <span class=\"sr-only\">Toggle Dropdown</span>\n    </button>\n    <ul class=\"dropdown-menu\" role=\"menu\">\n        @foreach($scopes as $scope)\n            {!! $scope->render() !!}\n        @endforeach\n        <li role=\"separator\" class=\"divider\"></li>\n        <li><a href=\"{{ $cancel }}\">{{ trans('admin.cancel') }}</a></li>\n    </ul>\n    @endif\n</div>\n\n<script>\nvar $btn = $('.{{ $btn_class }}');\nvar $filter = $('#{{ $filter_id }}');\n\n$btn.unbind('click').click(function (e) {\n    if ($filter.is(':visible')) {\n        $filter.addClass('hide');\n    } else {\n        $filter.removeClass('hide');\n    }\n});\n</script>\n"
  },
  {
    "path": "resources/views/filter/checkbox.blade.php",
    "content": "<div class=\"input-group input-group-sm\">\n    @foreach($options as $option => $label)\n\n        {!! $inline ? '<span class=\"icheck\">' : '<div class=\"checkbox icheck\">' !!}\n\n        <label @if($inline)class=\"checkbox-inline\"@endif>\n            <input type=\"checkbox\" class=\"{{$id}}\" name=\"{{$name}}[]\" value=\"{{$option}}\" class=\"minimal\" {{ in_array((string)$option, request($name, is_null($value) ? [] : $value)) ? 'checked' : '' }} />&nbsp;{{$label}}&nbsp;&nbsp;\n        </label>\n\n        {!! $inline ? '</span>' :  '</div>' !!}\n\n    @endforeach\n</div>"
  },
  {
    "path": "resources/views/filter/container.blade.php",
    "content": "<div class=\"box-header with-border {{ $expand?'':'hide' }} filter-box\" id=\"{{ $filterID }}\">\n    <form action=\"{!! $action !!}\" class=\"form-horizontal\" pjax-container method=\"get\">\n\n        <div class=\"row\">\n            @foreach($layout->columns() as $column)\n            <div class=\"col-md-{{ $column->width() }}\">\n                <div class=\"box-body\">\n                    <div class=\"fields-group\">\n                        @foreach($column->filters() as $filter)\n                            {!! $filter->render() !!}\n                        @endforeach\n                    </div>\n                </div>\n            </div>\n            @endforeach\n        </div>\n        <!-- /.box-body -->\n\n        <div class=\"box-footer\">\n            <div class=\"row\">\n                <div class=\"col-md-{{ $layout->columns()->first()->width() }}\">\n                    <div class=\"col-md-2\"></div>\n                    <div class=\"col-md-8\">\n                        <div class=\"btn-group pull-left\">\n                            <button class=\"btn btn-info submit btn-sm\"><i\n                                        class=\"fa fa-search\"></i>&nbsp;&nbsp;{{ trans('admin.search') }}</button>\n                        </div>\n                        <div class=\"btn-group pull-left \" style=\"margin-left: 10px;\">\n                            <a href=\"{!! $action !!}\" class=\"btn btn-default btn-sm\"><i\n                                        class=\"fa fa-undo\"></i>&nbsp;&nbsp;{{ trans('admin.reset') }}</a>\n                        </div>\n                    </div>\n                </div>\n            </div>\n        </div>\n\n    </form>\n</div>\n"
  },
  {
    "path": "resources/views/filter/datetime.blade.php",
    "content": "<div class=\"input-group input-group-sm\">\n    @if($group)\n        <div class=\"input-group-btn\">\n            <input type=\"hidden\" name=\"{{ $id }}_group\" class=\"{{ $group_name }}-operation\" value=\"0\"/>\n            <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\" style=\"min-width: 32px;\">\n                <span class=\"{{ $group_name }}-label\">{{ $default['label'] }}</span>\n                &nbsp;&nbsp;\n                <span class=\"fa fa-caret-down\"></span>\n            </button>\n            <ul class=\"dropdown-menu {{ $group_name }}\">\n                @foreach($group as $index => $item)\n                    <li><a href=\"#\" data-index=\"{{ $index }}\"> {{ $item['label'] }} </a></li>\n                @endforeach\n            </ul>\n        </div>\n    @endif\n    <div class=\"input-group-addon\">\n        <i class=\"fa fa-calendar\"></i>\n    </div>\n    <input class=\"form-control\" id=\"{{$id}}\" placeholder=\"{{$label}}\" name=\"{{$name}}\" value=\"{{ request($name, $value) }}\">\n</div>"
  },
  {
    "path": "resources/views/filter/gt.blade.php",
    "content": "<div class=\"form-group\">\n    <label class=\"col-sm-2 control-label\">{{$label}}&nbsp;(&gt;)</label>\n    <div class=\"col-sm-8\">\n        @include($presenter->view())\n    </div>\n</div>"
  },
  {
    "path": "resources/views/filter/lt.blade.php",
    "content": "<div class=\"form-group\">\n    <label class=\"col-sm-2 control-label\">{{$label}}&nbsp;(&lt;)</label>\n    <div class=\"col-sm-8\">\n        @include($presenter->view())\n    </div>\n</div>"
  },
  {
    "path": "resources/views/filter/modal.blade.php",
    "content": "<div class=\"btn-group pull-right\" style=\"margin-right: 10px\">\n    <a href=\"\" class=\"btn btn-sm btn-primary\" data-toggle=\"modal\" data-target=\"#{{ $modalID }}\"><i class=\"fa fa-filter\"></i>&nbsp;&nbsp;{{ trans('admin.filter') }}</a>\n    <a href=\"{!! $action !!}\" class=\"btn btn-sm btn-facebook\"><i class=\"fa fa-undo\"></i>&nbsp;&nbsp;{{ trans('admin.reset') }}</a>\n</div>\n\n<div class=\"modal fade\" id=\"{{ $modalID }}\" role=\"dialog\" aria-labelledby=\"myModalLabel\" aria-hidden=\"true\">\n    <div class=\"modal-dialog\" role=\"document\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">\n                <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\">\n                    <span aria-hidden=\"true\">&times;</span>\n                    <span class=\"sr-only\">Close</span>\n                </button>\n                <h4 class=\"modal-title\" id=\"myModalLabel\">{{ trans('admin.filter') }}</h4>\n            </div>\n            <form action=\"{!! $action !!}\" method=\"get\" pjax-container>\n                <div class=\"modal-body\">\n                    <div class=\"form\">\n                        @foreach($filters as $filter)\n                            <div class=\"form-group\">\n                                {!! $filter->render() !!}\n                            </div>\n                        @endforeach\n                    </div>\n                </div>\n                <div class=\"modal-footer\">\n                    <button type=\"submit\" class=\"btn btn-primary submit\">{{ trans('admin.submit') }}</button>\n                    <button type=\"reset\" class=\"btn btn-warning pull-left\">{{ trans('admin.reset') }}</button>\n                </div>\n            </form>\n        </div>\n    </div>\n</div>"
  },
  {
    "path": "resources/views/filter/multipleselect.blade.php",
    "content": "<select class=\"form-control {{ $class }}\" name=\"{{$name}}[]\" multiple style=\"width: 100%;\">\n    <option></option>\n    @foreach($options as $select => $option)\n        <option value=\"{{$select}}\" {{ in_array((string)$select, (array)$value) ?'selected':'' }}>{{$option}}</option>\n    @endforeach\n</select>"
  },
  {
    "path": "resources/views/filter/radio.blade.php",
    "content": "<div class=\"input-group input-group-sm\">\n    @foreach($options as $option => $label)\n\n        {!! $inline ? '<span class=\"icheck\">' : '<div class=\"radio icheck\">'  !!}\n\n            <label @if($inline)class=\"radio-inline\"@endif>\n                <input type=\"radio\" class=\"{{$id}}\" name=\"{{$name}}\" value=\"{{$option}}\" class=\"minimal\" {{ ((string)$option === request($name, is_null($value) ? '' : $value)) ? 'checked' : '' }} />&nbsp;{{$label}}&nbsp;&nbsp;\n            </label>\n\n        {!! $inline ? '</span>' :  '</div>' !!}\n\n    @endforeach\n</div>"
  },
  {
    "path": "resources/views/filter/select.blade.php",
    "content": "<select class=\"form-control {{ $class }}\" name=\"{{$name}}\" style=\"width: 100%;\">\n    <option></option>\n    @foreach($options as $select => $option)\n        <option value=\"{{$select}}\" {{ (string)$select === (string)request($name, $value) ?'selected':'' }}>{{$option}}</option>\n    @endforeach\n</select>"
  },
  {
    "path": "resources/views/filter/text.blade.php",
    "content": "<div class=\"input-group input-group-sm\">\n    @if($group)\n    <div class=\"input-group-btn\">\n        <input type=\"hidden\" name=\"{{ $id }}_group\" class=\"{{ $group_name }}-operation\" value=\"0\"/>\n        <button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\" style=\"min-width: 32px;\">\n            <span class=\"{{ $group_name }}-label\">{{ $default['label'] }}</span>\n            &nbsp;&nbsp;\n            <span class=\"fa fa-caret-down\"></span>\n        </button>\n        <ul class=\"dropdown-menu {{ $group_name }}\">\n            @foreach($group as $index => $item)\n            <li><a href=\"#\" data-index=\"{{ $index }}\"> {{ $item['label'] }} </a></li>\n            @endforeach\n        </ul>\n    </div>\n    @endif\n        <div class=\"input-group-addon\">\n            <i class=\"fa fa-{{ $icon }}\"></i>\n        </div>\n\n    <input type=\"{{ $type }}\" class=\"form-control {{ $id }}\" placeholder=\"{{$placeholder}}\" name=\"{{$name}}\" value=\"{{ request($name, $value) }}\">\n</div>"
  },
  {
    "path": "resources/views/filter/where.blade.php",
    "content": "<div class=\"form-group\">\n    <label class=\"col-sm-2 control-label\"> {{$label}}</label>\n    <div class=\"col-sm-8\">\n        @include($presenter->view())\n    </div>\n</div>"
  },
  {
    "path": "resources/views/form/belongsto.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}} {!! !$errors->has($errorKey) ? '' : 'has-error' !!}\">\n\n<label for=\"{{$id}}\" class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\">\n\n        @include('admin::form.error')\n\n        <input type=\"hidden\" name=\"{{$name}}\"/>\n\n        <select class=\"form-control {{$class}} hide\" style=\"width: 100%;\" name=\"{{$name}}\" {!! $attributes !!} >\n            <option value=\"\"></option>\n            @foreach($options as $select => $option)\n                <option value=\"{{$select}}\" {{ $select == old($column, $value) ?'selected':'' }}>{{$option}}</option>\n            @endforeach\n        </select>\n\n        <div class=\"belongsto-{{ $class }}\">\n            {!! $grid->render() !!}\n            <template class=\"empty\">\n                @include('admin::grid.empty-grid')\n            </template>\n        </div>\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/form/belongstomany.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}} {!! !$errors->has($errorKey) ? '' : 'has-error' !!}\">\n\n<label for=\"{{$id}}\" class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\">\n\n        @include('admin::form.error')\n\n        <select class=\"form-control {{$class}} hide\" style=\"width: 100%;\" name=\"{{$name}}[]\" multiple=\"multiple\" data-placeholder=\"{{ $placeholder }}\" {!! $attributes !!} >\n            @foreach($options as $select => $option)\n                <option value=\"{{$select}}\" {{  in_array($select, (array)old($column, $value)) ?'selected':'' }}>{{$option}}</option>\n            @endforeach\n        </select>\n        <input type=\"hidden\" name=\"{{$name}}[]\" />\n\n        <div class=\"belongstomany-{{ $class }}\">\n            {!! $grid->render() !!}\n            <template class=\"empty\">\n                @include('admin::grid.empty-grid')\n            </template>\n        </div>\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/form/button.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}}\">\n\n    <label class=\"{{$viewClass['label']}} control-label\"></label>\n\n    <div class=\"{{$viewClass['field']}}\">\n        <input type='button' value='{{$label}}' class=\"btn {{ $class }}\" {!! $attributes !!} />\n    </div>\n</div>"
  },
  {
    "path": "resources/views/form/captcha.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}} {!! !$errors->has($errorKey) ? '' : 'has-error' !!}\">\n\n    <label for=\"{{$id}}\" class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\">\n\n        @include('admin::form.error')\n\n        <div class=\"input-group\" style=\"width: 250px;\">\n\n            <input {!! $attributes !!} />\n\n            <span class=\"input-group-addon clearfix\" style=\"padding: 1px;\"><img id=\"{{$column}}-captcha\" src=\"{{ captcha_src() }}\" style=\"height:30px;cursor: pointer;\"  title=\"Click to refresh\"/></span>\n\n        </div>\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>"
  },
  {
    "path": "resources/views/form/checkbox.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}} {!! !$errors->has($column) ?: 'has-error' !!}\">\n\n    <label for=\"{{$id}}\" class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\" id=\"{{$id}}\">\n\n        @if($canCheckAll)\n            <span class=\"icheck\">\n            <label class=\"checkbox-inline\">\n                <input type=\"checkbox\" class=\"{{ $checkAllClass }}\"/>&nbsp;{{ __('admin.all') }}\n            </label>\n            </span>\n            <hr style=\"margin-top: 10px;margin-bottom: 0;\">\n        @endif\n\n        @include('admin::form.error')\n\n        @if($groups)\n\n        @foreach($groups as $group => $options)\n\n            <p style=\"{{ $canCheckAll ? 'margin: 15px 0 0 0;' : 'margin: 7px 0 0 0;' }}padding-bottom: 5px;border-bottom: 1px solid #eee;display: inline-block;\">{{ $group }}</p>\n\n            @foreach($options as $option => $label)\n\n            <div class=\"checkbox icheck\">\n\n                <label>\n                    <input type=\"checkbox\" name=\"{{$name}}[]\" value=\"{{$option}}\" class=\"{{$class}}\" {{ false !== array_search($option, array_filter(old($column, $value ?? []))) || ($value === null && in_array($option, $checked)) ?'checked':'' }} {!! $attributes !!} />&nbsp;{{$label}}&nbsp;&nbsp;\n                </label>\n\n            </div>\n\n            @endforeach\n\n        @endforeach\n\n        @else\n\n        @foreach($options as $option => $label)\n\n            {!! $inline ? '<span class=\"icheck\">' : '<div class=\"checkbox icheck\">' !!}\n\n                <label @if($inline)class=\"checkbox-inline\"@endif>\n                    <input type=\"checkbox\" name=\"{{$name}}[]\" value=\"{{$option}}\" class=\"{{$class}}\" {{ false !== array_search($option, array_filter(old($column, $value ?? []))) || ($value === null && in_array($option, $checked)) ?'checked':'' }} {!! $attributes !!} />&nbsp;{{$label}}&nbsp;&nbsp;\n                </label>\n\n            {!! $inline ? '</span>' :  '</div>' !!}\n\n        @endforeach\n\n        @endif\n\n        <input type=\"hidden\" name=\"{{$name}}[]\">\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/form/checkboxbutton.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}} {!! !$errors->has($column) ?: 'has-error' !!}\">\n\n    <label for=\"{{$id}}\" class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\" id=\"{{$id}}\">\n\n        @include('admin::form.error')\n\n        <div class=\"btn-group checkbox-group-toggle\">\n        @foreach($options as $option => $label)\n            <label class=\"btn btn-default {{ false !== array_search($option, array_filter(old($column, $value ?? []))) || ($value === null && in_array($option, $checked)) ?'active':'' }}\">\n                <input type=\"checkbox\" name=\"{{$name}}[]\" value=\"{{$option}}\" class=\"hide {{$class}}\" {{ false !== array_search($option, array_filter(old($column, $value ?? []))) || ($value === null && in_array($option, $checked)) ?'checked':'' }} {!! $attributes !!} />&nbsp;{{$label}}&nbsp;&nbsp;\n            </label>\n        @endforeach\n        </div>\n\n        <input type=\"hidden\" name=\"{{$name}}[]\">\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/form/checkboxcard.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}} {!! !$errors->has($column) ?: 'has-error' !!}\">\n\n    <label for=\"{{$id}}\" class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\" id=\"{{$id}}\">\n\n        @include('admin::form.error')\n\n        <div class=\"card-group checkbox-group-toggle\">\n        @foreach($options as $option => $label)\n            <label class=\"panel panel-default {{ false !== array_search($option, array_filter(old($column, $value ?? []))) || ($value === null && in_array($option, $checked)) ?'active':'' }}\">\n                <div class=\"panel-body\">\n                <input type=\"checkbox\" name=\"{{$name}}[]\" value=\"{{$option}}\" class=\"hide {{$class}}\" {{ false !== array_search($option, array_filter(old($column, $value ?? []))) || ($value === null && in_array($option, $checked)) ?'checked':'' }} {!! $attributes !!} />&nbsp;{{$label}}&nbsp;&nbsp;\n                </div>\n            </label>\n        @endforeach\n        </div>\n\n        <input type=\"hidden\" name=\"{{$name}}[]\">\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/form/daterange.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}} {!! ($errors->has($errorKey['start'].'start') || $errors->has($errorKey['end'].'end')) ? 'has-error' : ''  !!}\">\n\n    <label for=\"{{$id['start']}}\" class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\">\n\n        @include('admin::form.error')\n\n        <div class=\"row\" style=\"width: 370px\">\n            <div class=\"col-lg-6\">\n                <div class=\"input-group\">\n                    <span class=\"input-group-addon\"><i class=\"fa fa-calendar\"></i></span>\n                    <input type=\"text\" name=\"{{$name['start']}}\" value=\"{{ old($column['start'], $value['start'] ?? null) }}\" class=\"form-control {{$class['start']}}\" autocomplete=\"off\" style=\"width: 150px\" {!! $attributes !!} />\n                </div>\n            </div>\n\n            <div class=\"col-lg-6\">\n                <div class=\"input-group\">\n                    <span class=\"input-group-addon\"><i class=\"fa fa-calendar\"></i></span>\n                    <input type=\"text\" name=\"{{$name['end']}}\" value=\"{{ old($column['end'], $value['end'] ?? null) }}\" class=\"form-control {{$class['end']}}\" autocomplete=\"off\" style=\"width: 150px\" {!! $attributes !!} />\n                </div>\n            </div>\n        </div>\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/form/datetimerange.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}} {!! ($errors->has($errorKey['start']) || $errors->has($errorKey['end'])) ? 'has-error' : ''  !!}\">\n\n    <label for=\"{{$id['start']}}\" class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\">\n        <div class=\"row\">\n            <div class=\"col-lg-12\">\n                @if($errors->has($errorKey['start']))\n                    @foreach($errors->get($errorKey['start']) as $message)\n                        <label class=\"control-label\" for=\"inputError\"><i class=\"fa fa-times-circle-o\"></i> {{$message}}</label><br/>\n                    @endforeach\n                @endif\n\n                <div class=\"input-group\">\n                    <span class=\"input-group-addon\"><i class=\"fa fa-calendar\"></i></span>\n                    <input type=\"text\"\n                           name=\"{{$name['start']}}\"\n                           value=\"{{ old($column['start'], $value['start'] ?? null) }}\"\n                           class=\"form-control {{$class['start']}}\"\n                           style=\"width: 160px\"\n                           autocomplete=\"off\"\n                            {!! $attributes !!}\n                    />\n                </div>\n            </div>\n        </div>\n\n        <div class=\"row\" style=\"margin-top: 5px\">\n            <div class=\"col-lg-12\">\n                @if($errors->has($errorKey['end']))\n                    @foreach($errors->get($errorKey['end']) as $message)\n                        <label class=\"control-label\" for=\"inputError\"><i class=\"fa fa-times-circle-o\"></i> {{$message}}</label><br/>\n                    @endforeach\n                @endif\n\n                <div class=\"input-group\">\n                    <span class=\"input-group-addon\"><i class=\"fa fa-calendar\"></i></span>\n                    <input type=\"text\"\n                           name=\"{{$name['end']}}\"\n                           value=\"{{ old($column['end'], $value['end'] ?? null) }}\"\n                           class=\"form-control {{$class['end']}}\"\n                           style=\"width: 160px\"\n                           autocomplete=\"off\"\n                            {!! $attributes !!}\n                    />\n                </div>\n            </div>\n        </div>\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/form/display.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}}\">\n    <label class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n    <div class=\"{{$viewClass['field']}}\">\n        <div class=\"box box-solid box-default no-margin\">\n            <!-- /.box-header -->\n            <div class=\"box-body\">\n                {!! $value !!}&nbsp;\n            </div><!-- /.box-body -->\n        </div>\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>"
  },
  {
    "path": "resources/views/form/editor.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}} {!! !$errors->has($errorKey) ? '' : 'has-error' !!}\">\n\n    <label for=\"{{$id}}\" class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\">\n\n        @include('admin::form.error')\n\n        <textarea class=\"form-control {{$class}}\" id=\"{{$id}}\" name=\"{{$name}}\" placeholder=\"{{ $placeholder }}\" {!! $attributes !!} >{{ old($column, $value) }}</textarea>\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/form/embeds.blade.php",
    "content": "\n<div class=\"row\">\n    <div class=\"{{$viewClass['label']}}\"><h4 class=\"pull-right\">{{ $label }}</h4></div>\n    <div class=\"{{$viewClass['field']}}\"></div>\n</div>\n\n<hr style=\"margin-top: 0px;\">\n\n<div id=\"embed-{{$column}}\" class=\"embed-{{$column}}\">\n\n    <div class=\"embed-{{$column}}-forms\">\n\n        <div class=\"embed-{{$column}}-form fields-group\">\n\n            @foreach($form->fields() as $field)\n                {!! $field->render() !!}\n            @endforeach\n\n        </div>\n    </div>\n</div>\n\n<hr style=\"margin-top: 0px;\">"
  },
  {
    "path": "resources/views/form/error.blade.php",
    "content": "@if(is_array($errorKey))\n    @foreach($errorKey as $key => $col)\n        @if($errors->has($col.$key))\n            @foreach($errors->get($col.$key) as $message)\n                <label class=\"control-label\" for=\"inputError\"><i class=\"fa fa-times-circle-o\"></i> {{$message}}</label><br/>\n            @endforeach\n        @endif\n    @endforeach\n@else\n    @if($errors->has($errorKey))\n        @foreach($errors->get($errorKey) as $message)\n            <label class=\"control-label\" for=\"inputError\"><i class=\"fa fa-times-circle-o\"></i> {{$message}}</label><br/>\n        @endforeach\n    @endif\n@endif"
  },
  {
    "path": "resources/views/form/file.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}} {!! !$errors->has($errorKey) ? '' : 'has-error' !!}\">\n\n    <label for=\"{{$id}}\" class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\">\n\n        @include('admin::form.error')\n\n        <input type=\"file\" class=\"{{$class}}\" name=\"{{$name}}\" {!! $attributes !!} />\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/form/filepicker.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}} {!! !$errors->has($errorKey) ? '' : 'has-error' !!}\">\n\n    <label for=\"{{$id}}\" class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}} picker-{{ $column }}\">\n\n        @include('admin::form.error')\n\n        <div class=\"picker-file-preview {{ empty($preview) ? 'hide' : '' }}\">\n            @foreach($preview as $item)\n            <div class=\"file-preview-frame\" data-val=\"{!! $item['value'] !!}\">\n                <div class=\"file-content\">\n                    @if($item['is_file'])\n                        <i class=\"fa fa-file-text-o\"></i>\n                    @else\n                        <img src=\"{{ $item['url'] }}\"/>\n                    @endif\n                </div>\n                <div class=\"file-caption-info\">{{ basename($item['url']) }}</div>\n                <div class=\"file-actions\">\n                    <a class=\"btn btn-default btn-sm remove\">\n                        <i class=\"fa fa-trash\"></i>\n                    </a>\n                    <a class=\"btn btn-default btn-sm\" target=\"_blank\" download=\"{{ basename($item['url']) }}\" href=\"{{ $item['url'] }}\">\n                        <i class=\"fa fa-download\"></i>\n                    </a>\n                </div>\n            </div>\n            @endforeach\n        </div>\n\n        <div class=\"input-group\">\n            <input {!! $attributes !!} />\n            <span class=\"input-group-btn\">\n              {!! $btn !!}\n            </span>\n        </div>\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>\n\n<template>\n    <template id=\"file-preview\">\n        <div class=\"file-preview-frame\" data-val=\"_val_\">\n            <div class=\"file-content\">\n                <i class=\"fa fa-file-text-o\"></i>\n            </div>\n            <div class=\"file-caption-info\">_name_</div>\n            <div class=\"file-actions\">\n                <a class=\"btn btn-default btn-sm remove\">\n                    <i class=\"fa fa-trash\"></i>\n                </a>\n                <a class=\"btn btn-default btn-sm\" target=\"_blank\" download=\"_name_\" href=\"_url_\">\n                    <i class=\"fa fa-download\"></i>\n                </a>\n            </div>\n        </div>\n    </template>\n    <template id=\"image-preview\">\n        <div class=\"file-preview-frame\" data-val=\"_val_\">\n            <div class=\"file-content\">\n                <img src=\"_url_\">\n            </div>\n            <div class=\"file-caption-info\">_name_</div>\n            <div class=\"file-actions\">\n                <a class=\"btn btn-default btn-sm remove\">\n                    <i class=\"fa fa-trash\"></i>\n                </a>\n                <a class=\"btn btn-default btn-sm\" target=\"_blank\" download=\"_name_\" href=\"_url_\">\n                    <i class=\"fa fa-download\"></i>\n                </a>\n            </div>\n        </div>\n    </template>\n</template>\n"
  },
  {
    "path": "resources/views/form/footer.blade.php",
    "content": "<div class=\"box-footer\">\n\n    {{ csrf_field() }}\n\n    <div class=\"col-md-{{$width['label']}}\">\n    </div>\n\n    <div class=\"col-md-{{$width['field']}}\">\n\n        @if(in_array('submit', $buttons))\n        <div class=\"btn-group pull-right\">\n            <button type=\"submit\" class=\"btn btn-primary\">{{ trans('admin.submit') }}</button>\n        </div>\n\n        @foreach($submit_redirects as $value => $redirect)\n            @if(in_array($redirect, $checkboxes))\n            <label class=\"pull-right\" style=\"margin: 5px 10px 0 0;\">\n                <input type=\"checkbox\" class=\"after-submit\" name=\"after-save\" value=\"{{ $value }}\" {{ ($default_check == $redirect) ? 'checked' : '' }}> {{ trans(\"admin.{$redirect}\") }}\n            </label>\n            @endif\n        @endforeach\n\n        @endif\n\n        @if(in_array('reset', $buttons))\n        <div class=\"btn-group pull-left\">\n            <button type=\"reset\" class=\"btn btn-warning\">{{ trans('admin.reset') }}</button>\n        </div>\n        @endif\n    </div>\n</div>"
  },
  {
    "path": "resources/views/form/hasmany.blade.php",
    "content": "\n<div class=\"row\">\n    <div class=\"{{$viewClass['label']}}\"><h4 class=\"pull-right\">{{ $label }}</h4></div>\n    <div class=\"{{$viewClass['field']}}\"></div>\n</div>\n\n<hr style=\"margin-top: 0px;\">\n\n<div id=\"has-many-{{$column}}\" class=\"has-many-{{$column}}\">\n\n    <div class=\"has-many-{{$column}}-forms\">\n\n        @foreach($forms as $pk => $form)\n\n            <div class=\"has-many-{{$column}}-form fields-group\">\n\n                @foreach($form->fields() as $field)\n                    {!! $field->render() !!}\n                @endforeach\n\n                @if($options['allowDelete'])\n                <div class=\"form-group\">\n                    <label class=\"{{$viewClass['label']}} control-label\"></label>\n                    <div class=\"{{$viewClass['field']}}\">\n                        <div class=\"remove btn btn-warning btn-sm pull-right\"><i class=\"fa fa-trash\">&nbsp;</i>{{ trans('admin.remove') }}</div>\n                    </div>\n                </div>\n                @endif\n                <hr>\n            </div>\n\n        @endforeach\n    </div>\n    \n\n    <template class=\"{{$column}}-tpl\">\n        <div class=\"has-many-{{$column}}-form fields-group\">\n\n            {!! $template !!}\n\n            <div class=\"form-group\">\n                <label class=\"{{$viewClass['label']}} control-label\"></label>\n                <div class=\"{{$viewClass['field']}}\">\n                    <div class=\"remove btn btn-warning btn-sm pull-right\"><i class=\"fa fa-trash\"></i>&nbsp;{{ trans('admin.remove') }}</div>\n                </div>\n            </div>\n            <hr>\n        </div>\n    </template>\n\n    @if($options['allowCreate'])\n    <div class=\"form-group\">\n        <label class=\"{{$viewClass['label']}} control-label\"></label>\n        <div class=\"{{$viewClass['field']}}\">\n            <div class=\"add btn btn-success btn-sm\"><i class=\"fa fa-save\"></i>&nbsp;{{ trans('admin.new') }}</div>\n        </div>\n    </div>\n    @endif\n\n</div>"
  },
  {
    "path": "resources/views/form/hasmanytab.blade.php",
    "content": "<style>\n    .nav-tabs > li:hover > i{\n        display: inline;\n    }\n    .close-tab {\n        position: absolute;\n        font-size: 10px;\n        top: 2px;\n        right: 5px;\n        color: #94A6B0;\n        cursor: pointer;\n        display: none;\n    }\n</style>\n<div id=\"has-many-{{$column}}\" class=\"nav-tabs-custom has-many-{{$column}}\">\n    <div class=\"row header\">\n        <div class=\"col-md-2 {{$viewClass['label']}}\"><h4 class=\"pull-right\">{{ $label }}</h4></div>\n        <div class=\"col-md-8 {{$viewClass['field']}}\">\n            <button type=\"button\" class=\"btn btn-default btn-sm add\"><i class=\"fa fa-plus-circle\" style=\"font-size: large;\"></i></button>\n        </div>\n    </div>\n\n    <hr style=\"margin-top: 0px;\">\n\n    <ul class=\"nav nav-tabs\">\n        @foreach($forms as $pk => $form)\n            <li class=\"@if ($form == reset($forms)) active @endif \">\n                <a href=\"#{{ $relationName . '_' . $pk }}\" data-toggle=\"tab\">\n                    {{ $pk }} <i class=\"fa fa-exclamation-circle text-red hide\"></i>\n                </a>\n                <i class=\"close-tab fa fa-times\" ></i>\n            </li>\n        @endforeach\n\n    </ul>\n    \n    <div class=\"tab-content has-many-{{$column}}-forms\">\n\n        @foreach($forms as $pk => $form)\n            <div class=\"tab-pane fields-group has-many-{{$column}}-form @if ($form == reset($forms)) active @endif\" id=\"{{ $relationName . '_' . $pk }}\">\n                @foreach($form->fields() as $field)\n                    {!! $field->render() !!}\n                @endforeach\n            </div>\n        @endforeach\n    </div>\n\n    <template class=\"nav-tab-tpl\">\n        <li class=\"new\">\n            <a href=\"#{{ $relationName . '_new_' . \\Encore\\Admin\\Form\\NestedForm::DEFAULT_KEY_NAME }}\" data-toggle=\"tab\">\n                &nbsp;New {{ \\Encore\\Admin\\Form\\NestedForm::DEFAULT_KEY_NAME }} <i class=\"fa fa-exclamation-circle text-red hide\"></i>\n            </a>\n            <i class=\"close-tab fa fa-times\" ></i>\n        </li>\n    </template>\n    <template class=\"pane-tpl\">\n        <div class=\"tab-pane fields-group new\" id=\"{{ $relationName . '_new_' . \\Encore\\Admin\\Form\\NestedForm::DEFAULT_KEY_NAME }}\">\n            {!! $template !!}\n        </div>\n    </template>\n\n</div>\n"
  },
  {
    "path": "resources/views/form/hasmanytable.blade.php",
    "content": "<style>\n    td .form-group {\n        margin-bottom: 0 !important;\n    }\n</style>\n\n<div class=\"row\">\n    <div class=\"{{$viewClass['label']}}\"><h4 class=\"pull-right\">{{ $label }}</h4></div>\n    <div class=\"{{$viewClass['field']}}\">\n        <div id=\"has-many-{{$column}}\" style=\"margin-top: 15px;\">\n            <table class=\"table table-has-many has-many-{{$column}}\">\n                <thead>\n                <tr>\n                    @foreach($headers as $header)\n                        <th>{{ $header }}</th>\n                    @endforeach\n\n                    <th class=\"hidden\"></th>\n\n                    @if($options['allowDelete'])\n                        <th></th>\n                    @endif\n                </tr>\n                </thead>\n                <tbody class=\"has-many-{{$column}}-forms\">\n                @foreach($forms as $pk => $form)\n                    <tr class=\"has-many-{{$column}}-form fields-group\">\n\n                        <?php $hidden = ''; ?>\n\n                        @foreach($form->fields() as $field)\n\n                            @if (is_a($field, \\Encore\\Admin\\Form\\Field\\Hidden::class))\n                                <?php $hidden .= $field->render(); ?>\n                                @continue\n                            @endif\n\n                            <td>{!! $field->setLabelClass(['hidden'])->setWidth(12, 0)->render() !!}</td>\n                        @endforeach\n\n                        <td class=\"hidden\">{!! $hidden !!}</td>\n\n                        @if($options['allowDelete'])\n                            <td class=\"form-group\">\n                                <div>\n                                    <div class=\"remove btn btn-warning btn-sm pull-right\"><i class=\"fa fa-trash\">&nbsp;</i>{{ trans('admin.remove') }}</div>\n                                </div>\n                            </td>\n                        @endif\n                    </tr>\n                @endforeach\n                </tbody>\n            </table>\n\n            <template class=\"{{$column}}-tpl\">\n                <tr class=\"has-many-{{$column}}-form fields-group\">\n\n                    {!! $template !!}\n\n                    <td class=\"form-group\">\n                        <div>\n                            <div class=\"remove btn btn-warning btn-sm pull-right\"><i class=\"fa fa-trash\">&nbsp;</i>{{ trans('admin.remove') }}</div>\n                        </div>\n                    </td>\n                </tr>\n            </template>\n\n            @if($options['allowCreate'])\n                <div class=\"form-group\">\n                    <div class=\"{{$viewClass['field']}}\">\n                        <div class=\"add btn btn-success btn-sm\"><i class=\"fa fa-save\"></i>&nbsp;{{ trans('admin.new') }}</div>\n                    </div>\n                </div>\n            @endif\n        </div>\n    </div>\n</div>\n\n<hr style=\"margin-top: 0px;\">\n\n"
  },
  {
    "path": "resources/views/form/help-block.blade.php",
    "content": "@if($help)\n<span class=\"help-block\">\n    <i class=\"fa {{ \\Illuminate\\Support\\Arr::get($help, 'icon') }}\"></i>&nbsp;{!! \\Illuminate\\Support\\Arr::get($help, 'text') !!}\n</span>\n@endif"
  },
  {
    "path": "resources/views/form/hidden.blade.php",
    "content": "<input type=\"hidden\" name=\"{{$name}}\" value=\"{{$value}}\" class=\"{{$class}}\" {!! $attributes !!} />\n"
  },
  {
    "path": "resources/views/form/id.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}}\">\n    <label for=\"{{$id}}\" class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\">\n        <input type=\"text\" id=\"{{$id}}\" name=\"{{$name}}\" value=\"{{$value}}\" class=\"form-control\" readonly {!! $attributes !!} />\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>"
  },
  {
    "path": "resources/views/form/input.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}} {!! !$errors->has($errorKey) ? '' : 'has-error' !!}\">\n\n    <label for=\"{{$id}}\" class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\">\n\n        @include('admin::form.error')\n\n        <div class=\"input-group\">\n\n            @if ($prepend)\n            <span class=\"input-group-addon\">{!! $prepend !!}</span>\n            @endif\n\n            <input {!! $attributes !!} />\n\n            @if ($append)\n                <span class=\"input-group-addon clearfix\">{!! $append !!}</span>\n            @endif\n\n            @isset($btn)\n                <span class=\"input-group-btn\">\n                  {!! $btn !!}\n                </span>\n            @endisset\n\n        </div>\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/form/keyvalue.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}}\">\n\n    <label class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\">\n        <table class=\"table table-hover\">\n            <thead>\n            <tr>\n                <th>{{ __('Key') }}</th>\n                <th>{{ __('Value') }}</th>\n                <th style=\"width: 75px;\"></th>\n            </tr>\n            </thead>\n            <tbody class=\"kv-{{$column}}-table\">\n\n            @foreach(old(\"{$column}.keys\", ($value ?: [])) as $k => $v)\n\n                @php($keysErrorKey = \"{$column}.keys.{$loop->index}\")\n                @php($valsErrorKey = \"{$column}.values.{$loop->index}\")\n\n                <tr>\n                    <td>\n                        <div class=\"form-group {{ $errors->has($keysErrorKey) ? 'has-error' : '' }}\">\n                            <div class=\"col-sm-12\">\n                                <input name=\"{{ $name }}[keys][]\" value=\"{{ old(\"{$column}.keys.{$k}\", $k) }}\" class=\"form-control\" required/>\n\n                                @if($errors->has($keysErrorKey))\n                                    @foreach($errors->get($keysErrorKey) as $message)\n                                        <label class=\"control-label\" for=\"inputError\"><i class=\"fa fa-times-circle-o\"></i> {{$message}}</label><br/>\n                                    @endforeach\n                                @endif\n                            </div>\n                        </div>\n                    </td>\n                    <td>\n                        <div class=\"form-group {{ $errors->has($valsErrorKey) ? 'has-error' : '' }}\">\n                            <div class=\"col-sm-12\">\n                                <input name=\"{{ $name }}[values][]\" value=\"{{ old(\"{$column}.values.{$k}\", $v) }}\" class=\"form-control\" />\n                                @if($errors->has($valsErrorKey))\n                                    @foreach($errors->get($valsErrorKey) as $message)\n                                        <label class=\"control-label\" for=\"inputError\"><i class=\"fa fa-times-circle-o\"></i> {{$message}}</label><br/>\n                                    @endforeach\n                                @endif\n                            </div>\n                        </div>\n                    </td>\n\n                    <td class=\"form-group\">\n                        <div>\n                            <div class=\"{{$column}}-remove btn btn-warning btn-sm pull-right\">\n                                <i class=\"fa fa-trash\">&nbsp;</i>{{ __('admin.remove') }}\n                            </div>\n                        </div>\n                    </td>\n                </tr>\n            @endforeach\n            </tbody>\n            <tfoot>\n                <tr>\n                    <td></td>\n                    <td></td>\n                    <td>\n                        <div class=\"{{ $column }}-add btn btn-success btn-sm pull-right\">\n                            <i class=\"fa fa-save\"></i>&nbsp;{{ __('admin.new') }}\n                        </div>\n                    </td>\n                </tr>\n            </tfoot>\n        </table>\n    </div>\n    <template class=\"{{$column}}-tpl\">\n        <tr>\n            <td>\n                <div class=\"form-group  \">\n                    <div class=\"col-sm-12\">\n                        <input name=\"{{ $name }}[keys][]\" class=\"form-control\" required/>\n                    </div>\n                </div>\n            </td>\n            <td>\n                <div class=\"form-group  \">\n                    <div class=\"col-sm-12\">\n                        <input name=\"{{ $name }}[values][]\" class=\"form-control\" />\n                    </div>\n                </div>\n            </td>\n\n            <td class=\"form-group\">\n                <div>\n                    <div class=\"{{$column}}-remove btn btn-warning btn-sm pull-right\">\n                        <i class=\"fa fa-trash\">&nbsp;</i>{{ __('admin.remove') }}\n                    </div>\n                </div>\n            </td>\n        </tr>\n    </template>\n</div>\n"
  },
  {
    "path": "resources/views/form/listbox.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}} {!! !$errors->has($errorKey) ? '' : 'has-error' !!}\">\n\n    <label for=\"{{$id}}\" class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\">\n\n        @include('admin::form.error')\n\n        <select class=\"form-control {{$class}}\" style=\"width: 100%;\" name=\"{{$name}}[]\" multiple=\"multiple\" data-placeholder=\"{{ $placeholder }}\" {!! $attributes !!} >\n            @foreach($options as $select => $option)\n                <option value=\"{{$select}}\" {{  in_array($select, (array)old($column, $value)) ?'selected':'' }}>{{$option}}</option>\n            @endforeach\n        </select>\n        <input type=\"hidden\" name=\"{{$name}}[]\" />\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/form/listfield.blade.php",
    "content": "\n@php($listErrorKey = \"$column.values\")\n\n<div class=\"{{$viewClass['form-group']}} {{ $errors->has($listErrorKey) ? 'has-error' : '' }}\">\n\n    <label class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\">\n\n        @if($errors->has($listErrorKey))\n            @foreach($errors->get($listErrorKey) as $message)\n                <label class=\"control-label\" for=\"inputError\"><i class=\"fa fa-times-circle-o\"></i> {{$message}}</label><br/>\n            @endforeach\n        @endif\n\n        <table class=\"table table-hover\">\n\n            <tbody class=\"list-{{$column}}-table\">\n\n            @foreach(old(\"{$column}.values\", ($value ?: [])) as $k => $v)\n\n                @php($itemErrorKey = \"{$column}.values.{$loop->index}\")\n\n                <tr>\n                    <td>\n                        <div class=\"form-group {{ $errors->has($itemErrorKey) ? 'has-error' : '' }}\">\n                            <div class=\"col-sm-12\">\n                                <input name=\"{{ $column }}[values][]\" value=\"{{ old(\"{$column}.values.{$k}\", $v) }}\" class=\"form-control\" />\n                                @if($errors->has($itemErrorKey))\n                                    @foreach($errors->get($itemErrorKey) as $message)\n                                        <label class=\"control-label\" for=\"inputError\"><i class=\"fa fa-times-circle-o\"></i> {{$message}}</label><br/>\n                                    @endforeach\n                                @endif\n                            </div>\n                        </div>\n                    </td>\n\n                    <td style=\"width: 75px;\">\n                        <div class=\"{{$column}}-remove btn btn-warning btn-sm pull-right\">\n                            <i class=\"fa fa-trash\">&nbsp;</i>{{ __('admin.remove') }}\n                        </div>\n                    </td>\n                </tr>\n            @endforeach\n            </tbody>\n            <tfoot>\n                <tr>\n                    <td></td>\n                    <td>\n                        <div class=\"{{ $column }}-add btn btn-success btn-sm pull-right\">\n                            <i class=\"fa fa-save\"></i>&nbsp;{{ __('admin.new') }}\n                        </div>\n                    </td>\n                </tr>\n            </tfoot>\n        </table>\n    </div>\n    <template class=\"{{$column}}-tpl\">\n        <tr>\n            <td>\n                <div class=\"form-group\">\n                    <div class=\"col-sm-12\">\n                        <input name=\"{{ $column }}[values][]\" class=\"form-control\" />\n                    </div>\n                </div>\n            </td>\n\n            <td style=\"width: 75px;\">\n                <div class=\"{{$column}}-remove btn btn-warning btn-sm pull-right\">\n                    <i class=\"fa fa-trash\">&nbsp;</i>{{ __('admin.remove') }}\n                </div>\n            </td>\n        </tr>\n    </template>\n</div>\n"
  },
  {
    "path": "resources/views/form/map.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}} {!! !$errors->has($errorKey) ? '' : 'has-error' !!}\">\n\n    <label for=\"{{$id['lat']}}\" class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\">\n\n        @include('admin::form.error')\n\n        <div id=\"map_{{$id['lat'].$id['lng']}}\" style=\"width: 100%;height: 300px\"></div>\n        <input type=\"hidden\" id=\"{{$id['lat']}}\" name=\"{{$name['lat']}}\" value=\"{{ old($column['lat'], $value['lat']) }}\" {!! $attributes !!} />\n        <input type=\"hidden\" id=\"{{$id['lng']}}\" name=\"{{$name['lng']}}\" value=\"{{ old($column['lng'], $value['lng']) }}\" {!! $attributes !!} />\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/form/multiplefile.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}} {!! !$errors->has($errorKey) ? '' : 'has-error' !!}\">\n\n    <label for=\"{{$id}}\" class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\">\n\n        @include('admin::form.error')\n\n        <input type=\"file\" class=\"{{$class}}\" name=\"{{$name}}[]\" {!! $attributes !!} />\n        @isset($sortable)\n        <input type=\"hidden\" class=\"{{$class}}_sort\" name=\"{{ $sort_flag.\"[$name]\" }}\"/>\n        @endisset\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/form/multipleselect.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}} {!! !$errors->has($errorKey) ? '' : 'has-error' !!}\">\n\n    <label for=\"{{$id}}\" class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\">\n\n        @include('admin::form.error')\n\n        <select class=\"form-control {{$class}}\" style=\"width: 100%;\" name=\"{{$name}}[]\" multiple=\"multiple\" data-placeholder=\"{{ $placeholder }}\" {!! $attributes !!} >\n            @foreach($options as $select => $option)\n                <option value=\"{{$select}}\" {{  in_array($select, (array)old($column, $value)) ?'selected':'' }}>{{$option}}</option>\n            @endforeach\n        </select>\n        <input type=\"hidden\" name=\"{{$name}}[]\" />\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/form/radio.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}} {!! !$errors->has($errorKey) ? '' : 'has-error' !!}\">\n\n    <label for=\"{{$id}}\" class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\">\n\n        @include('admin::form.error')\n\n        @foreach($options as $option => $label)\n\n            {!! $inline ? '<span class=\"icheck\">' : '<div class=\"radio icheck\">'  !!}\n\n                <label @if($inline)class=\"radio-inline\"@endif>\n                    <input type=\"radio\" name=\"{{$name}}\" value=\"{{$option}}\" class=\"minimal {{$class}}\" {{ ($option == old($column, $value)) || ($value === null && in_array($label, $checked)) ?'checked':'' }} {!! $attributes !!} />&nbsp;{{$label}}&nbsp;&nbsp;\n                </label>\n\n            {!! $inline ? '</span>' :  '</div>' !!}\n\n        @endforeach\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/form/radiobutton.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}} {!! !$errors->has($errorKey) ? '' : 'has-error' !!}\">\n\n    <label for=\"{{$id}}\" class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\">\n\n        @include('admin::form.error')\n\n        <div class=\"btn-group radio-group-toggle\">\n            @foreach($options as $option => $label)\n                <label class=\"btn btn-default {{ ($option == old($column, $value)) || ($value === null && in_array($label, $checked)) ?'active':'' }}\">\n                    <input type=\"radio\" name=\"{{$name}}\" value=\"{{$option}}\" class=\"hide minimal {{$class}}\" {{ ($option == old($column, $value)) || ($value === null && in_array($label, $checked)) ?'checked':'' }} {!! $attributes !!} />&nbsp;{{$label}}&nbsp;&nbsp;\n                </label>\n            @endforeach\n        </div>\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/form/radiocard.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}} {!! !$errors->has($errorKey) ? '' : 'has-error' !!}\">\n\n    <label for=\"{{$id}}\" class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\">\n\n        @include('admin::form.error')\n\n        <div class=\"card-group radio-group-toggle\">\n            @foreach($options as $option => $label)\n                <label class=\"panel panel-default {{ ($option == old($column, $value)) || ($value === null && in_array($label, $checked)) ?'active':'' }}\">\n                    <div class=\"panel-body\">\n                    <input type=\"radio\" name=\"{{$name}}\" value=\"{{$option}}\" class=\"hide minimal {{$class}}\" {{ ($option == old($column, $value)) || ($value === null && in_array($label, $checked)) ?'checked':'' }} {!! $attributes !!} />&nbsp;{{$label}}&nbsp;&nbsp;\n                    </div>\n                </label>\n            @endforeach\n        </div>\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/form/rate.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}} {!! !$errors->has($errorKey) ? '' : 'has-error' !!}\">\n\n    <label for=\"{{$id}}\" class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\">\n\n        @include('admin::form.error')\n\n        <div class=\"input-group\" style=\"width: 150px\">\n            <input type=\"text\" id=\"{{$id}}\" name=\"{{$name}}\" value=\"{{ old($column, $value) }}\" class=\"form-control {{$class}}\" placeholder=\"0\" style=\"text-align:right;\" {!! $attributes !!} />\n            <span class=\"input-group-addon\">%</span>\n        </div>\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/form/row.blade.php",
    "content": "<div class=\"row\">\n    @foreach($fields as $field)\n    <div class=\"col-md-{{ $field['width'] }}\">\n        {!! $field['element']->render() !!}\n    </div>\n    @endforeach\n</div>"
  },
  {
    "path": "resources/views/form/select.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}} {!! !$errors->has($errorKey) ? '' : 'has-error' !!}\">\n\n<label for=\"{{$id}}\" class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\">\n\n        @include('admin::form.error')\n\n        <input type=\"hidden\" name=\"{{$name}}\"/>\n\n        <select class=\"form-control {{$class}}\" style=\"width: 100%;\" name=\"{{$name}}\" {!! $attributes !!} >\n            @if($groups)\n                @foreach($groups as $group)\n                    <optgroup label=\"{{ $group['label'] }}\">\n                        @foreach($group['options'] as $select => $option)\n                            <option value=\"{{$select}}\" {{ $select == old($column, $value) ?'selected':'' }}>{{$option}}</option>\n                        @endforeach\n                    </optgroup>\n                @endforeach\n             @else\n                <option value=\"\"></option>\n                @foreach($options as $select => $option)\n                    <option value=\"{{$select}}\" {{ $select == old($column, $value) ?'selected':'' }}>{{$option}}</option>\n                @endforeach\n            @endif\n        </select>\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/form/slider.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}} {!! !$errors->has($errorKey) ? '' : 'has-error' !!}\">\n\n    <label for=\"{{$id}}\" class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\">\n\n        @include('admin::form.error')\n\n        <input type=\"text\" class=\"{{$class}}\" name=\"{{$name}}\" data-from=\"{{ old($column, $value) }}\" {!! $attributes !!} />\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/form/switchfield.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}} {!! !$errors->has($errorKey) ? '' : 'has-error' !!}\">\n\n    <label for=\"{{$id}}\" class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\">\n\n        @include('admin::form.error')\n\n        <input type=\"checkbox\" class=\"{{$class}} la_checkbox\" {{ old($column, $value) == 'on' ? 'checked' : '' }} {!! $attributes !!} />\n        <input type=\"hidden\" class=\"{{$class}}\" name=\"{{$name}}\" value=\"{{ old($column, $value) }}\" />\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/form/tab.blade.php",
    "content": "<div class=\"nav-tabs-custom\">\n    <ul class=\"nav nav-tabs\">\n\n        @foreach($tabObj->getTabs() as $tab)\n            <li {{ $tab['active'] ? 'class=active' : '' }}>\n                <a href=\"#tab-{{ $tab['id'] }}\" data-toggle=\"tab\">\n                    {{ $tab['title'] }} <i class=\"fa fa-exclamation-circle text-red hide\"></i>\n                </a>\n            </li>\n        @endforeach\n\n    </ul>\n    <div class=\"tab-content fields-group\">\n\n        @foreach($tabObj->getTabs() as $tab)\n            <div class=\"tab-pane {{ $tab['active'] ? 'active' : '' }}\" id=\"tab-{{ $tab['id'] }}\">\n                @foreach($tab['fields'] as $field)\n                    {!! $field->render() !!}\n                @endforeach\n            </div>\n        @endforeach\n\n    </div>\n</div>"
  },
  {
    "path": "resources/views/form/tags.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}} {!! !$errors->has($errorKey) ? '' : 'has-error' !!}\">\n\n    <label for=\"{{$id}}\" class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\">\n\n        @include('admin::form.error')\n\n        <select class=\"form-control {{$class}}\" style=\"width: 100%;\" name=\"{{$name}}[]\" multiple=\"multiple\" data-placeholder=\"{{ $placeholder }}\" {!! $attributes !!} >\n\n            @foreach($options as $key => $option)\n                <option value=\"{{ $keyAsValue ? $key : $option}}\" {{ in_array($option, $value) ? 'selected' : '' }}>{{$option}}</option>\n            @endforeach\n\n        </select>\n        <input type=\"hidden\" name=\"{{$name}}[]\" />\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/form/textarea.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}} {!! !$errors->has($errorKey) ? '' : 'has-error' !!}\">\n\n    <label for=\"{{$id}}\" class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\">\n\n        @include('admin::form.error')\n\n        <textarea name=\"{{$name}}\" class=\"form-control {{$class}}\" rows=\"{{ $rows }}\" placeholder=\"{{ $placeholder }}\" {!! $attributes !!} >{{ old($column, $value) }}</textarea>\n\n        {!! $append !!}\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/form/timerange.blade.php",
    "content": "<div class=\"{{$viewClass['form-group']}} {!! ($errors->has($errorKey['start'].'start') || $errors->has($errorKey['end'].'end')) ? 'has-error' : ''  !!}\">\n\n    <label for=\"{{$id['start']}}\" class=\"{{$viewClass['label']}} control-label\">{{$label}}</label>\n\n    <div class=\"{{$viewClass['field']}}\">\n\n        @include('admin::form.error')\n\n        <div class=\"row\" style=\"width: 370px\">\n            <div class=\"col-lg-6\">\n                <div class=\"input-group\">\n                    <span class=\"input-group-addon\"><i class=\"fa fa-calendar\"></i></span>\n                    <input type=\"text\" name=\"{{$name['start']}}\" value=\"{{ old($column['start'], $value['start'] ?? null) }}\" class=\"form-control {{$class['start']}}\" autocomplete=\"off\" style=\"width: 150px\" {!! $attributes !!} />\n                </div>\n            </div>\n\n            <div class=\"col-lg-6\">\n                <div class=\"input-group\">\n                    <span class=\"input-group-addon\"><i class=\"fa fa-calendar\"></i></span>\n                    <input type=\"text\" name=\"{{$name['end']}}\" value=\"{{ old($column['end'], $value['end'] ?? null) }}\" class=\"form-control {{$class['end']}}\" autocomplete=\"off\" style=\"width: 150px\" {!! $attributes !!} />\n                </div>\n            </div>\n        </div>\n\n        @include('admin::form.help-block')\n\n    </div>\n</div>\n"
  },
  {
    "path": "resources/views/form.blade.php",
    "content": "<div class=\"box box-info\">\n    <div class=\"box-header with-border\">\n        <h3 class=\"box-title\">{{ $form->title() }}</h3>\n\n        <div class=\"box-tools\">\n            {!! $form->renderTools() !!}\n        </div>\n    </div>\n    <!-- /.box-header -->\n    <!-- form start -->\n    {!! $form->open() !!}\n\n    <div class=\"box-body\">\n\n        @if(!$tabObj->isEmpty())\n            @include('admin::form.tab', compact('tabObj'))\n        @else\n            <div class=\"fields-group\">\n\n                @if($form->hasRows())\n                    @foreach($form->getRows() as $row)\n                        {!! $row->render() !!}\n                    @endforeach\n                @else\n                    @foreach($layout->columns() as $column)\n                        <div class=\"col-md-{{ $column->width() }}\">\n                            @foreach($column->fields() as $field)\n                                {!! $field->render() !!}\n                            @endforeach\n                        </div>\n                    @endforeach\n                @endif\n            </div>\n        @endif\n\n    </div>\n    <!-- /.box-body -->\n\n    {!! $form->renderFooter() !!}\n\n    @foreach($form->getHiddenFields() as $field)\n        {!! $field->render() !!}\n    @endforeach\n\n<!-- /.box-footer -->\n    {!! $form->close() !!}\n</div>\n\n"
  },
  {
    "path": "resources/views/grid/actions/contextmenu.blade.php",
    "content": "@extends('admin::grid.actions.dropdown')\n\n@section('child')\n<script>\n    $(\"body\").on(\"contextmenu\", \"table.grid-table>tbody>tr\", function (e) {\n        $('#grid-context-menu .dropdown-menu').hide();\n\n        var menu = $(this).find('td.column-__actions__ .dropdown-menu');\n        var index = $(this).index();\n\n        if (menu.length) {\n            menu.attr('index', index).detach().appendTo('#grid-context-menu');\n        } else {\n            menu = $('#grid-context-menu .dropdown-menu[index=' + index + ']');\n        }\n\n        var height = 0;\n\n        if (menu.height() > (document.body.clientHeight - e.pageY)) {\n            menu.css({left: e.pageX + 10, top: e.pageY - menu.height()}).show();\n        } else {\n            menu.css({left: e.pageX + 10, top: e.pageY - 10}).show();\n        }\n\n        return false;\n    });\n\n    $(document).on('click', function () {\n        $('#grid-context-menu .dropdown-menu').hide();\n    });\n\n    $('#grid-context-menu').click('a', function () {\n        $('#grid-context-menu .dropdown-menu').hide();\n    });\n</script>\n\n<style>\n    .grid-table .column-__actions__ {\n        display: none !important;\n    }\n</style>\n\n<template>\n    <div id=\"grid-context-menu\"></div>\n</template>\n\n@endsection\n"
  },
  {
    "path": "resources/views/grid/actions/dropdown.blade.php",
    "content": "<div class=\"grid-dropdown-actions dropdown\">\n    <a href=\"#\" style=\"padding: 0 10px;\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">\n        <i class=\"fa fa-ellipsis-v\"></i>\n    </a>\n    <ul class=\"dropdown-menu\" style=\"min-width: 70px !important;box-shadow: 0 2px 3px 0 rgba(0,0,0,.2);border-radius:0;left: -65px;top: 5px;\">\n\n        @foreach($default as $action)\n            <li>{!! $action->render() !!}</li>\n        @endforeach\n\n        @if(!empty($custom))\n\n            @if(!empty($default))\n                <li class=\"divider\"></li>\n            @endif\n\n            @foreach($custom as $action)\n                <li>{!! $action->render() !!}</li>\n            @endforeach\n        @endif\n    </ul>\n</div>\n\n<script>\n    $('.table-responsive').on('shown.bs.dropdown', function(e) {\n        var t = $(this),\n            m = $(e.target).find('.dropdown-menu'),\n            tb = t.offset().top + t.height(),\n            mb = m.offset().top + m.outerHeight(true),\n            d = 20;\n        if (t[0].scrollWidth > t.innerWidth()) {\n            if (mb + d > tb) {\n                t.css('padding-bottom', ((mb + d) - tb));\n            }\n        } else {\n            t.css('overflow', 'visible');\n        }\n    }).on('hidden.bs.dropdown', function() {\n        $(this).css({\n            'padding-bottom': '',\n            'overflow': ''\n        });\n    });\n</script>\n\n@yield('child')\n"
  },
  {
    "path": "resources/views/grid/batch-actions.blade.php",
    "content": "@if(!$holdAll)\n<div class=\"btn-group {{ $all }}-btn\" style=\"display:none;margin-right: 5px;\">\n    <a class=\"btn btn-sm btn-default hidden-xs\"><span class=\"selected\"></span></a>\n    <button type=\"button\" class=\"btn btn-sm btn-default dropdown-toggle\" data-toggle=\"dropdown\">\n        <span class=\"caret\"></span>\n        <span class=\"sr-only\">Toggle Dropdown</span>\n    </button>\n    @if(!$actions->isEmpty())\n    <ul class=\"dropdown-menu\" role=\"menu\">\n        @foreach($actions as $action)\n            @if($action instanceof \\Encore\\Admin\\Actions\\BatchAction)\n                <li>{!! $action->render() !!}</li>\n            @else\n                <li><a href=\"#\" class=\"{{ $action->getElementClass(false) }}\">{!! $action->render() !!} </a></li>\n            @endif\n        @endforeach\n    </ul>\n    @endif\n</div>\n@endif\n\n<script>\n$('.{{ $all }}').iCheck({checkboxClass:'icheckbox_minimal-blue'});\n\n$('.{{ $all }}').on('ifChanged', function(event) {\n    if (this.checked) {\n        $('.{{ $row }}-checkbox').iCheck('check');\n    } else {\n        $('.{{ $row }}-checkbox').iCheck('uncheck');\n    }\n}).on('ifClicked', function () {\n    if (this.checked) {\n        $.admin.grid.selects = {};\n    } else {\n        $('.{{ $row }}-checkbox').each(function () {\n            var id = $(this).data('id');\n            $.admin.grid.select(id);\n        });\n    }\n\n    var selected = $.admin.grid.selected().length;\n\n    if (selected > 0) {\n        $('.{{ $all }}-btn').show();\n    } else {\n        $('.{{ $all }}-btn').hide();\n    }\n\n    $('.{{ $all }}-btn .selected')\n        .html(\"{{ trans('admin.grid_items_selected') }}\".replace('{n}', selected));\n});\n</script>\n"
  },
  {
    "path": "resources/views/grid/displayer/table.blade.php",
    "content": "<table class=\"table table-hover\" style=\"margin-bottom: 0;\">\n    <thead>\n    <tr>\n        @foreach($titles as $column => $title)\n        <th>{{ $title }}</th>\n        @endforeach\n    </tr>\n    </thead>\n    <tbody>\n    @foreach($data as $datum)\n    <tr>\n        @foreach($datum as $key => $value)\n            <td>{{ $value }}</td>\n        @endforeach\n    </tr>\n    @endforeach\n    </tbody>\n</table>"
  },
  {
    "path": "resources/views/grid/empty-grid.blade.php",
    "content": "<tr>\n    <td colspan=\"{{ $grid->visibleColumns()->count() }}\" class=\"empty-grid\" style=\"padding: 100px;text-align: center;color: #999999\">\n        <svg t=\"1562312016538\" class=\"icon\" viewBox=\"0 0 1024 1024\" version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\"\n             p-id=\"2076\" width=\"128\" height=\"128\" style=\"fill: #e9e9e9;\">\n            <path d=\"M512.8 198.5c12.2 0 22-9.8 22-22v-90c0-12.2-9.8-22-22-22s-22 9.8-22 22v90c0 12.2 9.9 22 22 22zM307 247.8c8.6 8.6 22.5 8.6 31.1 0 8.6-8.6 8.6-22.5 0-31.1L274.5 153c-8.6-8.6-22.5-8.6-31.1 0-8.6 8.6-8.6 22.5 0 31.1l63.6 63.7zM683.9 247.8c8.6 8.6 22.5 8.6 31.1 0l63.6-63.6c8.6-8.6 8.6-22.5 0-31.1-8.6-8.6-22.5-8.6-31.1 0l-63.6 63.6c-8.6 8.6-8.6 22.5 0 31.1zM927 679.9l-53.9-234.2c-2.8-9.9-4.9-20-6.9-30.1-3.7-18.2-19.9-31.9-39.2-31.9H197c-19.9 0-36.4 14.5-39.5 33.5-1 6.3-2.2 12.5-3.9 18.7L97 679.9v239.6c0 22.1 17.9 40 40 40h750c22.1 0 40-17.9 40-40V679.9z m-315-40c0 55.2-44.8 100-100 100s-100-44.8-100-100H149.6l42.5-193.3c2.4-8.5 3.8-16.7 4.8-22.9h630c2.2 11 4.5 21.8 7.6 32.7l39.8 183.5H612z\"\n                  p-id=\"2077\"></path>\n        </svg>\n    </td>\n</tr>\n"
  },
  {
    "path": "resources/views/grid/fixed-table.blade.php",
    "content": "<div class=\"box\">\n    @if(isset($title))\n    <div class=\"box-header with-border\">\n        <h3 class=\"box-title\"> {{ $title }}</h3>\n    </div>\n    @endif\n\n    @if ( $grid->showTools() || $grid->showExportBtn() || $grid->showCreateBtn() )\n    <div class=\"box-header with-border\">\n        <div class=\"pull-right\">\n            {!! $grid->renderColumnSelector() !!}\n            {!! $grid->renderExportButton() !!}\n            {!! $grid->renderCreateButton() !!}\n        </div>\n        @if ( $grid->showTools() )\n        <div class=\"pull-left\">\n            {!! $grid->renderHeaderTools() !!}\n        </div>\n        @endif\n    </div>\n    @endif\n\n    {!! $grid->renderFilter() !!}\n\n    {!! $grid->renderHeader() !!}\n\n    <!-- /.box-header -->\n    <div class=\"box-body table-responsive no-padding\">\n        <div class=\"tables-container\">\n            <div class=\"table-wrap table-main\">\n                <table class=\"table grid-table\" id=\"{{ $grid->tableID }}\">\n                    <thead>\n                        <tr>\n                            @foreach($grid->visibleColumns() as $column)\n                            <th {!! $column->formatHtmlAttributes() !!}>{{$column->getLabel()}}{!! $column->renderHeader() !!}</th>\n                            @endforeach\n                        </tr>\n                    </thead>\n\n                    <tbody>\n\n                        @foreach($grid->rows() as $row)\n                        <tr {!! $row->getRowAttributes() !!}>\n                            @foreach($grid->visibleColumnNames() as $name)\n                            <td {!! $row->getColumnAttributes($name) !!} class=\"column-{!! $name !!}\">\n                                {!! $row->column($name) !!}\n                            </td>\n                            @endforeach\n                        </tr>\n                        @endforeach\n                    </tbody>\n\n                    {!! $grid->renderTotalRow() !!}\n\n                </table>\n            </div>\n\n            @if($grid->leftVisibleColumns()->isNotEmpty())\n            <div class=\"table-wrap table-fixed table-fixed-left\">\n                <table class=\"table grid-table\">\n                    <thead>\n                    <tr>\n                        @foreach($grid->leftVisibleColumns() as $column)\n                            <th {!! $column->formatHtmlAttributes() !!}>{{$column->getLabel()}}{!! $column->renderHeader() !!}</th>\n                        @endforeach\n                    </tr>\n                    </thead>\n                    <tbody>\n\n                    @foreach($grid->rows() as $row)\n                        <tr {!! $row->getRowAttributes() !!}>\n                            @foreach($grid->leftVisibleColumns() as $column)\n                                @php\n                                    $name = $column->getName()\n                                @endphp\n                                <td {!! $row->getColumnAttributes($name) !!} class=\"column-{!! $name !!}\">\n                                    {!! $row->column($name) !!}\n                                </td>\n                            @endforeach\n                        </tr>\n                    @endforeach\n                    </tbody>\n\n                    {!! $grid->renderTotalRow($grid->leftVisibleColumns()) !!}\n\n                </table>\n            </div>\n            @endif\n\n            @if($grid->rightVisibleColumns()->isNotEmpty())\n            <div class=\"table-wrap table-fixed table-fixed-right\">\n                <table class=\"table grid-table\">\n                    <thead>\n                    <tr>\n                        @foreach($grid->rightVisibleColumns() as $column)\n                            <th {!! $column->formatHtmlAttributes() !!}>{{$column->getLabel()}}{!! $column->renderHeader() !!}</th>\n                        @endforeach\n                    </tr>\n                    </thead>\n\n                    <tbody>\n\n                    @foreach($grid->rows() as $row)\n                        <tr {!! $row->getRowAttributes() !!}>\n                            @foreach($grid->rightVisibleColumns() as $column)\n                                @php\n                                $name = $column->getName()\n                                @endphp\n                                <td {!! $row->getColumnAttributes($name) !!} class=\"column-{!! $name !!}\">\n                                    {!! $row->column($name) !!}\n                                </td>\n                            @endforeach\n                        </tr>\n                    @endforeach\n                    </tbody>\n\n                    {!! $grid->renderTotalRow($grid->rightVisibleColumns()) !!}\n\n                </table>\n            </div>\n            @endif\n        </div>\n    </div>\n\n    {!! $grid->renderFooter() !!}\n\n    <div class=\"box-footer clearfix\">\n        {!! $grid->paginator() !!}\n    </div>\n    <!-- /.box-body -->\n</div>\n\n\n<style>\n    .tables-container {\n        position:relative;\n    }\n\n    .tables-container table {\n        margin-bottom: 0px !important;\n    }\n\n    .tables-container table th, .tables-container table td {\n        white-space:nowrap;\n    }\n\n    .table-wrap table tr .active {\n        background: #f5f5f5;\n    }\n\n    .table-main {\n        overflow-x: auto;\n        width: 100%;\n    }\n\n    .table-fixed {\n        position:absolute;\n        top: 0px;\n        background:#ffffff;\n        z-index:10;\n    }\n\n    .table-fixed-left {\n        left:0;\n        box-shadow: 7px 0 5px -5px rgba(0,0,0,.12);\n    }\n\n    .table-fixed-right {\n        right:0;\n        box-shadow: -5px 0 5px -5px rgba(0,0,0,.12);\n    }\n</style>\n\n<script>\n    var theadHeight = $('.table-main thead tr')[0].getBoundingClientRect().height;\n    $('.table-fixed thead tr').outerHeight(theadHeight);\n\n    var tfootHeight = $('.table-main tfoot tr').outerHeight();\n    $('.table-fixed tfoot tr').outerHeight(tfootHeight);\n\n    $('.table-main tbody tr').each(function(i, obj) {\n        var height = obj.getBoundingClientRect().height;\n\n        $('.table-fixed-left tbody tr').eq(i).outerHeight(height);\n        $('.table-fixed-right tbody tr').eq(i).outerHeight(height);\n    });\n\n    if ($('.table-main').width() >= $('.table-main').prop('scrollWidth')) {\n        $('.table-fixed').hide();\n    }\n\n    $('.table-wrap tbody tr').on('mouseover', function () {\n        var index = $(this).index();\n\n        $('.table-main tbody tr').eq(index).addClass('active');\n        $('.table-fixed-left tbody tr').eq(index).addClass('active');\n        $('.table-fixed-right tbody tr').eq(index).addClass('active');\n    });\n\n    $('.table-wrap tbody tr').on('mouseout', function () {\n        var index = $(this).index();\n\n        $('.table-main tbody tr').eq(index).removeClass('active');\n        $('.table-fixed-left tbody tr').eq(index).removeClass('active');\n        $('.table-fixed-right tbody tr').eq(index).removeClass('active');\n    });\n\n    $('.{{ $rowName }}-checkbox').iCheck({checkboxClass:'icheckbox_minimal-blue'}).on('ifChanged', function () {\n\n        var id = $(this).data('id');\n        var index = $(this).closest('tr').index();\n\n        if (this.checked) {\n        $.admin.grid.select(id);\n            $('.table-main tbody tr').eq(index).css('background-color', '#ffffd5');\n            $('.table-fixed-left tbody tr').eq(index).css('background-color', '#ffffd5');\n            $('.table-fixed-right tbody tr').eq(index).css('background-color', '#ffffd5');\n        } else {\n        $.admin.grid.unselect(id);\n            $('.table-main tbody tr').eq(index).css('background-color', '');\n            $('.table-fixed-left tbody tr').eq(index).css('background-color', '');\n            $('.table-fixed-right tbody tr').eq(index).css('background-color', '');\n        }\n    }).on('ifClicked', function () {\n\n        var id = $(this).data('id');\n\n        if (this.checked) {\n            $.admin.grid.unselect(id);\n        } else {\n            $.admin.grid.select(id);\n        }\n\n        var selected = $.admin.grid.selected().length;\n\n        if (selected > 0) {\n            $('.{{ $allName }}-btn').show();\n        } else {\n            $('.{{ $allName }}-btn').hide();\n        }\n\n        $('.{{ $allName }}-btn .selected').html(\"{{ trans('admin.grid_items_selected') }}\".replace('{n}', selected));\n    });\n</script>\n"
  },
  {
    "path": "resources/views/grid/image.blade.php",
    "content": "<div class=\"box\">\n    <div class=\"box-header\"></div>\n\n    {!! $grid->renderFilter() !!}\n\n    <div class=\"box-body table-responsive no-padding\">\n        <ul class=\"image clearfix\">\n            @foreach($grid->rows() as $row)\n            <li>\n                <label>\n                    {!! $row->column($key) !!}\n                    {!! $row->column('__modal_selector__') !!}\n                </label>\n            </li>\n            @endforeach\n        </ul>\n    </div>\n\n    <div class=\"box-footer clearfix\">\n        {!! $grid->paginator() !!}\n    </div>\n    <!-- /.box-body -->\n</div>\n\n<style>\nul.image {\n    padding: 0px;\n}\n\n.image li {\n    float: left;\n    margin: 10px;\n    list-style-type:none;\n    position: relative;\n}\n\n.image label {\n    cursor: pointer;\n}\n\n.image .img-thumbnail {\n    padding-right: 15px;\n}\n\n.image .iradio_minimal-blue,.image .icheckbox_minimal-blue {\n    position: absolute;\n    bottom: 5px;\n    right: 1px;\n    background-color: #ffffff;\n}\n</style>\n"
  },
  {
    "path": "resources/views/grid/inline-edit/belongsto.blade.php",
    "content": "<span class=\"grid-selector\" data-toggle=\"modal\" data-target=\"#{{ $modal }}\" key=\"{{ $key }}\" data-val=\"{{ $original }}\">\n   <a href=\"javascript:void(0)\" class=\"text-muted\">\n       <i class=\"fa fa-check-square-o\"></i>&nbsp;&nbsp;\n       <span class=\"text\">{{ $value }}</span>\n   </a>\n</span>\n\n<style>\n    .belongsto.modal tr {\n        cursor: pointer;\n    }\n\n    .belongsto.modal .box {\n        border-top: none;\n        margin-bottom: 0;\n        box-shadow: none;\n    }\n    .belongsto.modal .loading {\n        margin: 50px;\n    }\n</style>\n\n<template>\n    <div class=\"modal fade belongsto\" id=\"{{ $modal }}\" tabindex=\"-1\" role=\"dialog\">\n        <div class=\"modal-dialog modal-lg\" role=\"document\">\n            <div class=\"modal-content\" style=\"border-radius: 5px;\">\n                <div class=\"modal-header\">\n                    <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\">\n                        <span aria-hidden=\"true\">&times;</span>\n                    </button>\n                    <h4 class=\"modal-title\">{{ admin_trans('admin.choose') }}</h4>\n                </div>\n                <div class=\"modal-body\">\n                    <div class=\"loading text-center\">\n                        <i class=\"fa fa-spinner fa-pulse fa-3x fa-fw\"></i>\n                    </div>\n                </div>\n                <div class=\"modal-footer\">\n                    <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\">{{ admin_trans('admin.cancel') }}</button>\n                    <button type=\"button\" class=\"btn btn-primary submit\">{{ admin_trans('admin.submit') }}</button>\n                </div>\n            </div>\n        </div>\n    </div>\n</template>\n\n<script>\n\n    var $modal = $('#{{ $modal }}');\n    var $related = null;\n\n    var update = function (callback) {\n        $.ajax({\n            url: \"{{ $resource }}/\" + $related.attr('key'),\n            type: \"POST\",\n            data: {\n                '{{ $name }}': selected.length ? selected : [''],\n                _token: LA.token,\n                _method: 'PUT'\n            },\n            success: function (data) {\n                callback(data);\n            }\n        });\n    };\n\n@if($relation == \\Encore\\Admin\\Grid\\Displayers\\BelongsTo::class)\n\n    var selected = null;\n\n    var load = function (url) {\n        $.get(url, function (data) {\n            $modal.find('.modal-body').html(data);\n            $modal.find('.select').iCheck({\n                radioClass:'iradio_minimal-blue',\n                checkboxClass:'icheckbox_minimal-blue'\n            });\n            $modal.find('.box-header:first').hide();\n\n            $modal.find('input.select').each(function (index,    el) {\n                if ($(el).val() == selected) {\n                    $(el).iCheck('toggle');\n                }\n            });\n        });\n    };\n\n    $modal.on('show.bs.modal', function (e) {\n        $related = $(e.relatedTarget);\n        selected = $related.data('val');\n        load(\"{!! $url !!}\");\n    }).on('ifChecked', 'input.select', function (e) {\n        selected = $(this).val();\n    }).find('.modal-footer .submit').click(function () {\n        update(function (data) {\n            $related.data('val', selected);\n            $related.find('.text').html(data.display[\"{{ $name }}\"]);\n            $related.find('a').toggleClass('text-green text-muted');\n\n            setTimeout(function () {\n                $related.find('a').toggleClass('text-green text-muted');\n            }, 2000);\n\n            $modal.modal('toggle');\n\n            toastr.success(data.message);\n        });\n    });\n\n@else\n\n    var selected = [];\n\n    var load = function (url) {\n        $.get(url, function (data) {\n            $modal.find('.modal-body').html(data);\n            $modal.find('.select').iCheck({\n                radioClass:'iradio_minimal-blue',\n                checkboxClass:'icheckbox_minimal-blue'\n            });\n            $modal.find('.box-header:first').hide();\n\n            $modal.find('input.select').each(function (index, el) {\n                if ($.inArray($(el).val().toString(), selected) >=0 ) {\n                    $(el).iCheck('toggle');\n                }\n            });\n        });\n    };\n\n    $modal.on('show.bs.modal', function (e) {\n        $related = $(e.relatedTarget);\n        selected = $related.data('val').map(function (value) {\n            return value.toString();\n        });\n\n        load(\"{!! $url !!}\");\n    }).on('ifChecked', 'input.select', function (e) {\n        var val = $(this).val().toString();\n        if (selected.indexOf(val) < 0) {\n            selected.push(val);\n        }\n    }).on('ifUnchecked', 'input.select', function (e) {\n        var val = $(this).val().toString();\n        var index = selected.indexOf(val);\n        if (index !== -1) {\n            selected.splice(index, 1);\n        }\n    }).find('.modal-footer .submit').click(function () {\n        update(function (data) {\n            $related.data('val', selected);\n            $related.find('.text').html(data.display[\"{{ $name }}\"]);\n            $related.find('a').toggleClass('text-green text-muted');\n\n            setTimeout(function () {\n                $related.find('a').toggleClass('text-green text-muted');\n            }, 2000);\n\n            $modal.modal('toggle');\n\n            toastr.success(data.message);\n        });\n    });\n@endif\n\n    $modal.on('click', '.page-item a, .filter-box a', function (e) {\n        load($(this).attr('href'));\n        e.preventDefault();\n    }).on('click', 'tr', function (e) {\n        $(this).find('input.select').iCheck('toggle');\n        e.preventDefault();\n    }).on('submit', '.box-header form', function (e) {\n        load($(this).attr('action')+'&'+$(this).serialize());\n        e.preventDefault();\n        return false;\n    })\n\n</script>\n"
  },
  {
    "path": "resources/views/grid/inline-edit/checkbox.blade.php",
    "content": "@extends('admin::grid.inline-edit.comm')\n\n@section('field')\n    @foreach($options as $option => $label)\n        <div class=\"checkbox icheck\">\n            <label>\n                <input type=\"checkbox\" name='radio-{{ $name }}[]' class=\"minimal ie-input\" value=\"{{ $option }}\" data-label=\"{{ $label }}\"/>&nbsp;{{$label}}&nbsp;&nbsp;\n            </label>\n        </div>\n    @endforeach\n@endsection\n\n@section('assert')\n    <style>\n        .icheck.checkbox {\n            margin: 5px 0 5px 20px;\n        }\n\n        .ie-content-{{ $name }} .ie-container  {\n            width: 150px;\n            position: relative;\n        }\n    </style>\n\n    <script>\n        @component('admin::grid.inline-edit.partials.popover', compact('trigger'))\n            @slot('content')\n            $template.find('input[type=checkbox]').each(function (index, checkbox) {\n                if($.inArray($(checkbox).attr('value'), $trigger.data('value')) >= 0) {\n                    $(checkbox).attr('checked', true);\n                }\n            });\n            @endslot\n        @endcomponent\n    </script>\n\n    <script>\n    @component('admin::grid.inline-edit.partials.submit', compact('resource', 'name'))\n\n        @slot('val')\n            var val = [];\n            var label = [];\n            $popover.find('.ie-input:checked').each(function(){\n                val.push($(this).val());\n                label.push($(this).data('label'));\n            });\n        @endslot\n\n        $popover.data('display').html(label.join(';'));\n\n    @endcomponent\n    </script>\n@endsection\n\n"
  },
  {
    "path": "resources/views/grid/inline-edit/comm.blade.php",
    "content": "{{--inline edit popover--}}\n\n<span class=\"ie-wrap\">\n    <a\n        href=\"javascript:void(0);\"\n        class=\"{{ $trigger }}\"\n        data-toggle=\"popover\"\n        data-target=\"{{ $target }}\"\n        data-value=\"{{ $value }}\"\n        data-original=\"{{ $value }}\"\n        data-key=\"{{ $key }}\"\n        data-name=\"{{ $name }}\"\n    >\n        <span class=\"ie-display\">{{ $display }}</span>\n\n        <i class=\"fa fa-edit\" style=\"visibility: hidden;\"></i>\n    </a>\n</span>\n\n<template>\n    <template id=\"{{ $target }}\">\n        <div class=\"ie-content ie-content-{{ $name }}\">\n            <div class=\"ie-container\">\n                @yield('field')\n                <div class=\"error\"></div>\n            </div>\n            <div class=\"ie-action\">\n                <button class=\"btn btn-primary btn-sm ie-submit\">{{ __('admin.submit') }}</button>\n                <button class=\"btn btn-default btn-sm ie-cancel\">{{ __('admin.cancel') }}</button>\n            </div>\n        </div>\n    </template>\n</template>\n\n<style>\n    .ie-wrap>a {\n        padding: 3px;\n        border-radius: 3px;\n        color:#777;\n    }\n\n    .ie-wrap>a:hover {\n        text-decoration: none;\n        background-color: #ddd;\n        color:#777;\n    }\n\n    .ie-wrap>a:hover i {\n        visibility: visible !important;\n    }\n\n    .ie-action button {\n        margin: 10px 0 10px 10px;\n        float: right;\n    }\n\n    .ie-container  {\n        width: 250px;\n        position: relative;\n    }\n\n    .ie-container .error {\n        color: #dd4b39;\n        font-weight: 700;\n    }\n</style>\n\n<script>\n    $(document).on('click', '.ie-action .ie-cancel', function () {\n        $('[data-toggle=\"popover\"]').popover('hide');\n    });\n\n    $('body').on('click', function (e) {\n        if ($(e.target).data('toggle') !== 'popover'\n            && $(e.target).parents('[data-toggle=\"popover\"]').length === 0\n            && $(e.target).parents('.popover.in').length === 0) {\n            $('[data-toggle=\"popover\"]').popover('hide');\n        }\n    });\n</script>\n\n@yield('assert')\n"
  },
  {
    "path": "resources/views/grid/inline-edit/datetime.blade.php",
    "content": "@extends('admin::grid.inline-edit.comm')\n\n@section('field')\n    <input class=\"form-control ie-input\"/>\n@endsection\n\n@section('assert')\n    <style>\n        .ie-content-{{ $name }} .ie-container  {\n            height: 290px;\n        }\n\n        .ie-content-{{ $name }} .ie-input {\n            display: none;\n        }\n    </style>\n\n    <script>\n        @component('admin::grid.inline-edit.partials.popover', compact('trigger'))\n            @slot('content')\n            $template.find('input').attr('value', $trigger.data('value'));\n            @endslot\n            @slot('shown')\n            var $input  = $popover.find('.ie-input');\n\n            $popover.find('.ie-container').datetimepicker({\n                inline: true,\n                format: '{{ $format }}',\n                date: $input.val(),\n                locale: '{{ $locale }}'\n            }).on('dp.change', function (event) {\n                var date = event.date.format('{{ $format }}');\n                $input.val(date);\n            });\n            @endslot\n        @endcomponent\n    </script>\n\n    {{--after submit--}}\n    <script>\n    @component('admin::grid.inline-edit.partials.submit', compact('resource', 'name'))\n        $popover.data('display').html(val);\n    @endcomponent\n    </script>\n\n@endsection\n\n\n"
  },
  {
    "path": "resources/views/grid/inline-edit/input.blade.php",
    "content": "@extends('admin::grid.inline-edit.comm')\n\n@section('field')\n    <input class=\"form-control ie-input\"/>\n@endsection\n\n@section('assert')\n    <script>\n        @component('admin::grid.inline-edit.partials.popover', compact('trigger'))\n            @slot('content')\n            $template.find('input').attr('value', $trigger.data('value'));\n            @endslot\n            @slot('shown')\n                $popover.find('.ie-input').focus();\n                @if($mask)\n                $popover.find('.ie-input').inputmask(@json($mask));\n                @endif\n            @endslot\n        @endcomponent\n    </script>\n\n    {{--after submit--}}\n    <script>\n    @component('admin::grid.inline-edit.partials.submit', compact('resource', 'name'))\n        $popover.data('display').html(val);\n    @endcomponent\n    </script>\n@endsection\n\n\n"
  },
  {
    "path": "resources/views/grid/inline-edit/multiple-select.blade.php",
    "content": "@extends('admin::grid.inline-edit.comm')\n\n@section('field')\n    <select name='multiple-select-{{ $name }}' class=\"form-control ie-input\" multiple>\n        @foreach($options as $option => $label)\n            <option name='multiple-select-{{ $name }}' value=\"{{ $option }}\" data-label=\"{{ $label }}\">&nbsp;{{$label}}&nbsp;&nbsp;</option>\n        @endforeach\n    </select>\n@endsection\n\n@section('assert')\n    <script>\n        @component('admin::grid.inline-edit.partials.popover', compact('trigger'))\n            @slot('content')\n            $template.find('select>option').each(function (index, option) {\n                if($.inArray($(option).attr('value'), $trigger.data('value')) >= 0) {\n                    $(option).attr('selected', true);\n                }\n            });\n            @endslot\n        @endcomponent\n    </script>\n\n    <script>\n    @component('admin::grid.inline-edit.partials.submit', compact('resource', 'name'))\n\n        @slot('val')\n            var val = [];\n            var label = [];\n            $popover.find('.ie-input>option:selected').each(function(){\n                val.push($(this).val());\n                label.push($(this).data('label'));\n            });\n        @endslot\n\n        $popover.data('display').html(label.join(';'));\n\n    @endcomponent\n    </script>\n@endsection\n\n"
  },
  {
    "path": "resources/views/grid/inline-edit/partials/popover.blade.php",
    "content": "$('.{{ $trigger }}').popover({\n    html: true,\n    container: 'body',\n    trigger: 'manual',\n    placement: function (context, source) {\n        var position = $(source).position();\n        if (position.left < 100) return \"right\";\n        if (position.top < 110) return \"bottom\";\n        if ($(window).height() - $(source).offset().top < 370) {\n            return 'top';\n        }\n        return \"bottom\";\n    },\n    content: function () {\n        var $trigger = $(this);\n        var $template = $($('template#'+$(this).data('target')).html());\n        {{ $content }}\n        return $template.prop(\"outerHTML\");\n    }\n}).on('shown.bs.popover', function (e) {\n\n    var $popover = $($(this).data('bs.popover').$tip[0]).find('.ie-content');\n    var $display = $(this).parents('.ie-wrap').find('.ie-display');\n    var $trigger = $(this);\n\n    $popover.data('display', $display);\n    $popover.data('trigger', $trigger);\n\n    {{ $shown ?? '' }}\n\n}).click(function () {\n    $('[data-toggle=\"popover\"]').popover('hide');\n    $(this).popover('toggle');\n});\n"
  },
  {
    "path": "resources/views/grid/inline-edit/partials/submit.blade.php",
    "content": "$(document).off('click', '.ie-content .ie-submit').on('click', '.ie-content .ie-submit', function () {\n\n    var $popover = $(this).closest('.ie-content');\n    var $trigger = $popover.data('trigger');\n\n    @isset($val)\n        {{ $val }}\n    @else\n        var val = $popover.find('.ie-input').val();\n    @endisset\n\n    var original = $trigger.data('original');\n\n    if (val == original) {\n        $('[data-toggle=\"popover\"]').popover('hide');\n        return;\n    }\n\n    var data = {\n        _token: LA.token,\n        _method: 'PUT',\n        _edit_inline: true,\n    };\n    data[$trigger.data('name')] = val;\n\n    $.ajax({\n        url: \"{{ $resource }}/\" + $trigger.data('key'),\n        type: \"POST\",\n        data: data,\n        success: function (data) {\n            toastr.success(data.message);\n\n            {{ $slot }}\n\n            $trigger.data('value', val)\n                .data('original', val);\n\n            $('[data-toggle=\"popover\"]').popover('hide');\n        },\n        statusCode: {\n            422: function(xhr) {\n                $popover.find('.error').empty();\n                var errors = xhr.responseJSON.errors;\n                for (var key in errors) {\n                    $popover.find('.error').append('<div><i class=\"fa fa-times-circle-o\"></i> '+errors[key]+'</div>')\n                }\n            }\n        }\n    });\n});\n"
  },
  {
    "path": "resources/views/grid/inline-edit/radio.blade.php",
    "content": "@extends('admin::grid.inline-edit.comm')\n\n@section('field')\n    @foreach($options as $option => $label)\n        <div class=\"radio icheck\">\n            <label>\n                <input type=\"radio\" name='radio-{{ $name }}' class=\"minimal ie-input\" value=\"{{ $option }}\" data-label=\"{{ $label }}\"/>&nbsp;{{$label}}&nbsp;&nbsp;\n            </label>\n        </div>\n    @endforeach\n@endsection\n\n@section('assert')\n    <style>\n        .icheck.radio {\n            margin: 5px 0 5px 20px;\n        }\n\n        .ie-content-{{ $name }} .ie-container  {\n            width: 150px;\n            position: relative;\n        }\n    </style>\n\n    <script>\n        @component('admin::grid.inline-edit.partials.popover', compact('trigger'))\n            @slot('content')\n                $template.find('input[type=radio]').each(function (index, radio) {\n                    if ($(radio).attr('value') == $trigger.data('value')) {\n                        $(radio).attr('checked', true);\n                    }\n                });\n            @endslot\n        @endcomponent\n    </script>\n\n    <script>\n    @component('admin::grid.inline-edit.partials.submit', compact('resource', 'name'))\n\n        @slot('val')\n            var val = $popover.find('.ie-input:checked').val();\n            var label = $popover.find('.ie-input:checked').data('label');\n        @endslot\n\n        $popover.data('display').html(label);\n\n    @endcomponent\n    </script>\n@endsection\n\n"
  },
  {
    "path": "resources/views/grid/inline-edit/select.blade.php",
    "content": "@extends('admin::grid.inline-edit.comm')\n\n@section('field')\n    <select name='select-{{ $name }}' class=\"form-control ie-input\">\n    @foreach($options as $option => $label)\n        <option name='select-{{ $name }}' value=\"{{ $option }}\" data-label=\"{{ $label }}\">&nbsp;{{$label}}&nbsp;&nbsp;</option>\n    @endforeach\n    </select>\n@endsection\n\n@section('assert')\n    <script>\n        @component('admin::grid.inline-edit.partials.popover', compact('trigger'))\n            @slot('content')\n            $template.find('select>option').each(function (index, option) {\n                if ($(option).attr('value') == $trigger.data('value')) {\n                    $(option).attr('selected', true);\n                }\n            });\n            @endslot\n        @endcomponent\n    </script>\n\n    <script>\n    @component('admin::grid.inline-edit.partials.submit', compact('resource', 'name'))\n\n        @slot('val')\n            var val = $popover.find('.ie-input').val();\n            var label = $popover.find('.ie-input>option:selected').data('label');\n        @endslot\n\n        $popover.data('display').html(label);\n\n    @endcomponent\n    </script>\n@endsection\n\n"
  },
  {
    "path": "resources/views/grid/inline-edit/switch-group.blade.php",
    "content": "\n<tr style=\"height: 28px;\">\n    <td><strong><small>{{ $label }}:</small></strong>&nbsp;&nbsp;&nbsp;</td>\n    <td><input type=\"checkbox\" class=\"{{ $class }}\" {{ $checked }} data-key=\"{{ $key }}\" /></td>\n</tr>\n\n<script>\n    $('.{{ $class }}').bootstrapSwitch({\n        size:'mini',\n        onText: '{{ $states['on']['text'] }}',\n        offText: '{{ $states['off']['text'] }}',\n        onColor: '{{ $states['on']['color'] }}',\n        offColor: '{{ $states['off']['color'] }}',\n        onSwitchChange: function(event, state){\n\n            $(this).val(state ? {{ $states['on']['value'] }} : {{ $states['off']['value'] }});\n\n            var key = $(this).data('key');\n            var value = $(this).val();\n            var _status = true;\n\n            $.ajax({\n                url: \"{{ $resource }}/\" + key,\n                type: \"POST\",\n                data: {\n                    \"{{ $name }}\": value,\n                    _token: LA.token,\n                    _method: 'PUT'\n                },\n                success: function (data) {\n                    if (data.status)\n                        toastr.success(data.message);\n                    else\n                        toastr.warning(data.message);\n                },\n                complete:function(xhr,status) {\n                    if (status == 'success')\n                        _status = xhr.responseJSON.status;\n                }\n            });\n\n            return _status;\n        }\n    });\n</script>\n"
  },
  {
    "path": "resources/views/grid/inline-edit/switch.blade.php",
    "content": "<input type=\"checkbox\" class=\"{{ $class }}\" {{ $checked }} data-key=\"{{ $key }}\" />\n\n<script>\n    $('.{{ $class }}').bootstrapSwitch({\n        size:'mini',\n        onText: '{{ $states['on']['text'] }}',\n        offText: '{{ $states['off']['text'] }}',\n        onColor: '{{ $states['on']['color'] }}',\n        offColor: '{{ $states['off']['color'] }}',\n        onSwitchChange: function(event, state){\n\n            $(this).val(state ? {{ $states['on']['value'] }} : {{ $states['off']['value'] }});\n\n            var key = $(this).data('key');\n            var value = $(this).val();\n            var _status = true;\n\n            $.ajax({\n                url: \"{{ $resource }}/\" + key,\n                type: \"POST\",\n                async:false,\n                data: {\n                    \"{{ $name }}\": value,\n                    _token: LA.token,\n                    _method: 'PUT',\n                    _edit_inline: true\n                },\n                success: function (data) {\n                    if (data.status)\n                        toastr.success(data.message);\n                    else\n                        toastr.warning(data.message);\n                },\n                error: function (xhr, textStatus, errorThrown) {\n                    _status = false;\n                    var data = xhr.responseJSON\n                    if (data['errors'] || data['message']) {\n                        var message = data['message'] || Object.values(data['errors']).join(\"\\n\");\n                        toastr.error(message);\n                    } else {\n                        toastr.error('Error: ' + errorThrown);\n                    }\n                },\n                complete:function(xhr,status) {\n                    if (status == 'success')\n                        _status = xhr.responseJSON.status;\n                }\n            });\n\n            return _status;\n        }\n    });\n</script>\n"
  },
  {
    "path": "resources/views/grid/inline-edit/textarea.blade.php",
    "content": "@extends('admin::grid.inline-edit.comm')\n\n@section('field')\n    <textarea class=\"form-control ie-input\" rows=\"{{ $rows }}\"></textarea>\n@endsection\n\n@section('assert')\n    <script>\n        @component('admin::grid.inline-edit.partials.popover', compact('trigger'))\n            @slot('content')\n                $template.find('textarea').text($trigger.data('value'));\n            @endslot\n            @slot('shown')\n                $popover.find('.ie-input').focus();\n            @endslot\n        @endcomponent\n    </script>\n\n    {{--after submit--}}\n    <script>\n    @component('admin::grid.inline-edit.partials.submit', compact('resource', 'name'))\n        $popover.data('display').html(val);\n    @endcomponent\n    </script>\n@endsection\n\n\n"
  },
  {
    "path": "resources/views/grid/inline-edit/upload.blade.php",
    "content": "<a href='javascript:void(0);' class='text-muted inline-upload-trigger' data-target=\"{{ $target }}\">\n    <i class=\"fa fa-upload\"></i>&nbsp;{!! $value !!}\n</a>\n<div class=\"hide\">\n  <input type=\"file\" class=\"inline-upload\" id=\"{{ $target }}\" data-key=\"{{ $key }}\" {{ $multiple ? 'multiple' : '' }}/>\n</div>\n\n<script>\n$('.inline-upload-trigger').click(function () {\n    $('#'+$(this).data('target')).trigger('click');\n});\n\n$('input.inline-upload').on('change', function () {\n\n    var formData = new FormData();\n\n    @if ($multiple)\n        event.target.files.forEach(function (file) {\n            formData.append(\"{{ $name }}[]\", file);\n        });\n    @else\n    formData.append(\"{{ $name }}\", event.target.files[0]);\n    @endif\n    formData.append('_token', LA.token);\n    formData.append('_method', 'PUT');\n\n    $.ajax({\n        url: \"{{ $resource }}/\" + $(this).data('key'),\n        type: \"POST\",\n        processData: false,\n        contentType: false,\n        enctype: 'multipart/form-data',\n        data: formData,\n        success: function (data) {\n            toastr.success(data.message);\n            $.admin.reload();\n        }\n    });\n});\n</script>\n"
  },
  {
    "path": "resources/views/grid/quick-create/date.blade.php",
    "content": "<div class=\"input-group input-group-sm\">\n    <input style=\"width: 125px;\" {!! $attributes !!} placeholder=\"{{ $label }}\" />\n</div>"
  },
  {
    "path": "resources/views/grid/quick-create/form.blade.php",
    "content": "<thead>\n<tr class=\"quick-create\">\n    <td colspan=\"{{ $columnCount }}\" style=\"height: 47px;padding-left: 57px;background-color: #f9f9f9; vertical-align: middle;\">\n\n        <span class=\"create\" style=\"color: #bdbdbd;cursor: pointer;display: block;\">\n             <i class=\"fa fa-plus\"></i>&nbsp;{{ __('admin.quick_create') }}\n        </span>\n\n        <form class=\"form-inline create-form\" style=\"display: none;\" method=\"post\">\n            @foreach($fields as $field)\n                &nbsp;{!! $field->render() !!}\n            @endforeach\n                &nbsp;\n            <button class=\"btn btn-primary btn-sm\">{{ __('admin.submit') }}</button>&nbsp;\n            <a href=\"javascript:void(0);\" class=\"cancel\">{{ __('admin.cancel') }}</a>\n            {{ csrf_field() }}\n        </form>\n    </td>\n</tr>\n</thead>"
  },
  {
    "path": "resources/views/grid/quick-create/multipleselect.blade.php",
    "content": "<style>\n    .quick-create .select2-selection--multiple {\n        padding: 0 !important;\n        height: 30px !important;\n        width: 200px !important;\n        min-height: 30px !important;\n    }\n</style>\n\n<div class=\"input-group input-group-sm\">\n    <select class=\"form-control {{$class}}\" style=\"width: 100%;\" name=\"{{$name}}\" {!! $attributes !!} multiple data-placeholder=\"{{ $label }}\">\n\n        <option value=\"\"></option>\n        @foreach($options as $select => $option)\n            <option value=\"{{$select}}\" {{ $select == old($column, $value) ?'selected':'' }}>{{$option}}</option>\n        @endforeach\n    </select>\n</div>\n\n"
  },
  {
    "path": "resources/views/grid/quick-create/select.blade.php",
    "content": "<style>\n    .quick-create .select2-selection--single {\n        padding: 3px 12px !important;\n        height: 30px !important;\n        width: 150px !important;\n    }\n</style>\n\n<div class=\"input-group input-group-sm\">\n    <select class=\"form-control {{$class}}\" style=\"width: 100%;\" name=\"{{$name}}\" {!! $attributes !!} >\n\n        <option value=\"\"></option>\n        @foreach($options as $select => $option)\n            <option value=\"{{$select}}\" {{ $select == old($column, $value) ?'selected':'' }}>{{$option}}</option>\n        @endforeach\n    </select>\n</div>\n\n"
  },
  {
    "path": "resources/views/grid/quick-create/text.blade.php",
    "content": "<div class=\"input-group input-group-sm\">\n    <input {!! $attributes !!} placeholder=\"{{ $label }}\"/>\n</div>"
  },
  {
    "path": "resources/views/grid/quick-search.blade.php",
    "content": "<form action=\"{!! $action !!}\" pjax-container style=\"display: inline-block;\">\n    <div class=\"input-group input-group-sm\" style=\"display: inline-block;\">\n        <input type=\"text\" name=\"{{ $key }}\" class=\"form-control grid-quick-search\" style=\"width: 200px;\" value=\"{{ $value }}\" placeholder=\"{{ $placeholder }}\">\n\n        <div class=\"input-group-btn\" style=\"display: inline-block;\">\n            <button type=\"submit\" class=\"btn btn-default\"><i class=\"fa fa-search\"></i></button>\n        </div>\n    </div>\n</form>"
  },
  {
    "path": "resources/views/grid/selector.blade.php",
    "content": "<style>\n\n    .grid-selector .wrap {\n        position: relative;\n        line-height: 34px;\n        border-bottom: 1px dashed #eee;\n        padding: 0 30px;\n        font-size: 13px;\n        overflow:auto;\n    }\n\n    .grid-selector .wrap:last-child {\n        border-bottom: none;\n    }\n\n    .grid-selector .select-label {\n        float: left;\n        width: 100px;\n        padding-left: 10px;\n        color: #999;\n    }\n\n    .grid-selector .select-options {\n        margin-left: 100px;\n    }\n\n    .grid-selector ul {\n        height: 25px;\n        list-style: none;\n    }\n\n    .grid-selector ul > li {\n        margin-right: 30px;\n        float: left;\n    }\n\n    .grid-selector ul > li a {\n        color: #666;\n        text-decoration: none;\n    }\n\n    .grid-selector .select-options a.active {\n        color: #dd4b39;\n        font-weight: 600;\n    }\n\n    .grid-selector li .add {\n        visibility: hidden;\n    }\n\n    .grid-selector li:hover .add {\n        visibility: visible;\n    }\n\n    .grid-selector ul .clear {\n        visibility: hidden;\n    }\n\n    .grid-selector ul:hover .clear {\n        color: #3c8dbc;\n        visibility: visible;\n    }\n</style>\n\n<div class=\"grid-selector\">\n    @foreach($selectors as $column => $selector)\n        <div class=\"wrap\">\n            <div class=\"select-label\">{{ $selector['label'] }}</div>\n            <div class=\"select-options\">\n                <ul>\n                    @foreach($selector['options'] as $value => $option)\n                        @php\n                            $active = in_array($value, \\Illuminate\\Support\\Arr::get($selected, $column, []));\n                        @endphp\n                        <li>\n                            <a href=\"{{ \\Encore\\Admin\\Grid\\Tools\\Selector::url($column, $value, true) }}\"\n                               class=\"{{$active ? 'active' : ''}}\">{{ $option }}</a>\n                            @if(!$active && $selector['type'] == 'many')\n                                &nbsp;\n                                <a href=\"{{ \\Encore\\Admin\\Grid\\Tools\\Selector::url($column, $value) }}\" class=\"add\"><i\n                                            class=\"fa fa-plus-square-o\"></i></a>\n                            @else\n                                <a style=\"visibility: hidden;\"><i class=\"fa fa-plus-square-o\"></i></a>\n                            @endif\n                        </li>\n                    @endforeach\n                    <li>\n                        <a href=\"{{ \\Encore\\Admin\\Grid\\Tools\\Selector::url($column) }}\" class=\"clear\"><i\n                                    class=\"fa fa-trash\"></i></a>\n                    </li>\n                </ul>\n            </div>\n        </div>\n    @endforeach\n</div>\n\n\n"
  },
  {
    "path": "resources/views/grid/table.blade.php",
    "content": "<div class=\"box grid-box\">\n    @if(isset($title))\n    <div class=\"box-header with-border\">\n        <h3 class=\"box-title\"> {{ $title }}</h3>\n    </div>\n    @endif\n\n    @if ( $grid->showTools() || $grid->showExportBtn() || $grid->showCreateBtn() )\n    <div class=\"box-header with-border\">\n        <div class=\"pull-right\">\n            {!! $grid->renderColumnSelector() !!}\n            {!! $grid->renderExportButton() !!}\n            {!! $grid->renderCreateButton() !!}\n        </div>\n        @if ( $grid->showTools() )\n        <div class=\"pull-left\">\n            {!! $grid->renderHeaderTools() !!}\n        </div>\n        @endif\n    </div>\n    @endif\n\n    {!! $grid->renderFilter() !!}\n\n    {!! $grid->renderHeader() !!}\n\n    <!-- /.box-header -->\n    <div class=\"box-body table-responsive no-padding\">\n        <table class=\"table table-hover grid-table\" id=\"{{ $grid->tableID }}\">\n            <thead>\n                <tr>\n                    @foreach($grid->visibleColumns() as $column)\n                    <th {!! $column->formatHtmlAttributes() !!}>{!! $column->getLabel() !!}{!! $column->renderHeader() !!}</th>\n                    @endforeach\n                </tr>\n            </thead>\n\n            @if ($grid->hasQuickCreate())\n                {!! $grid->renderQuickCreate() !!}\n            @endif\n\n            <tbody>\n\n                @if($grid->rows()->isEmpty() && $grid->showDefineEmptyPage())\n                    @include('admin::grid.empty-grid')\n                @endif\n\n                @foreach($grid->rows() as $row)\n                <tr {!! $row->getRowAttributes() !!}>\n                    @foreach($grid->visibleColumnNames() as $name)\n                    <td {!! $row->getColumnAttributes($name) !!}>\n                        {!! $row->column($name) !!}\n                    </td>\n                    @endforeach\n                </tr>\n                @endforeach\n            </tbody>\n\n            {!! $grid->renderTotalRow() !!}\n\n        </table>\n\n    </div>\n\n    {!! $grid->renderFooter() !!}\n\n    <div class=\"box-footer clearfix\">\n        {!! $grid->paginator() !!}\n    </div>\n    <!-- /.box-body -->\n</div>\n"
  },
  {
    "path": "resources/views/grid/total-row.blade.php",
    "content": "<tfoot>\n    <tr>\n        @foreach($columns as $column)\n            <td class=\"{{ $column['class'] }}\">{!! $column['value'] !!}</td>\n        @endforeach\n    </tr>\n</tfoot>\n\n\n"
  },
  {
    "path": "resources/views/index.blade.php",
    "content": "<!DOCTYPE html>\n<html lang=\"{{ config('app.locale') }}\">\n<head>\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge,chrome=1\">\n    <meta name=\"renderer\" content=\"webkit\">\n    <meta name=\"csrf-token\" content=\"{{ csrf_token() }}\">\n    <title>{{ Admin::title() }} @if($header) | {{ $header }}@endif</title>\n    <!-- Tell the browser to be responsive to screen width -->\n    <meta content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no\" name=\"viewport\">\n\n    @if(!is_null($favicon = Admin::favicon()))\n    <link rel=\"shortcut icon\" href=\"{{$favicon}}\">\n    @endif\n\n    {!! Admin::css() !!}\n\n    <script src=\"{{ Admin::jQuery() }}\"></script>\n    {!! Admin::headerJs() !!}\n    <!--[if lt IE 9]>\n    <script src=\"https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js\"></script>\n    <script src=\"https://oss.maxcdn.com/respond/1.4.2/respond.min.js\"></script>\n    <![endif]-->\n\n</head>\n\n<body class=\"hold-transition {{config('admin.skin')}} {{join(' ', config('admin.layout'))}}\">\n\n@if($alert = config('admin.top_alert'))\n    <div style=\"text-align: center;padding: 5px;font-size: 12px;background-color: #ffffd5;color: #ff0000;\">\n        {!! $alert !!}\n    </div>\n@endif\n\n<div class=\"wrapper\">\n\n    @include('admin::partials.header')\n\n    @include('admin::partials.sidebar')\n\n    <div class=\"content-wrapper\" id=\"pjax-container\">\n        {!! Admin::style() !!}\n        <div id=\"app\">\n        @yield('content')\n        </div>\n        {!! Admin::script() !!}\n        {!! Admin::html() !!}\n    </div>\n\n    @include('admin::partials.footer')\n\n</div>\n\n<button id=\"totop\" title=\"Go to top\" style=\"display: none;\"><i class=\"fa fa-chevron-up\"></i></button>\n\n<script>\n    function LA() {}\n    LA.token = \"{{ csrf_token() }}\";\n    LA.user = @json($_user_);\n</script>\n\n<!-- REQUIRED JS SCRIPTS -->\n{!! Admin::js() !!}\n\n</body>\n</html>\n"
  },
  {
    "path": "resources/views/login.blade.php",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n  <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n  <title>{{config('admin.title')}} | {{ trans('admin.login') }}</title>\n  <!-- Tell the browser to be responsive to screen width -->\n  <meta content=\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no\" name=\"viewport\">\n  \n  @if(!is_null($favicon = Admin::favicon()))\n  <link rel=\"shortcut icon\" href=\"{{$favicon}}\">\n  @endif\n\n  <!-- Bootstrap 3.3.5 -->\n  <link rel=\"stylesheet\" href=\"{{ admin_asset(\"vendor/laravel-admin/AdminLTE/bootstrap/css/bootstrap.min.css\") }}\">\n  <!-- Font Awesome -->\n  <link rel=\"stylesheet\" href=\"{{ admin_asset(\"vendor/laravel-admin/font-awesome/css/font-awesome.min.css\") }}\">\n  <!-- Theme style -->\n  <link rel=\"stylesheet\" href=\"{{ admin_asset(\"vendor/laravel-admin/AdminLTE/dist/css/AdminLTE.min.css\") }}\">\n  <!-- iCheck -->\n  <link rel=\"stylesheet\" href=\"{{ admin_asset(\"vendor/laravel-admin/AdminLTE/plugins/iCheck/square/blue.css\") }}\">\n\n  <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->\n  <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->\n  <!--[if lt IE 9]>\n  <script src=\"//oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js\"></script>\n  <script src=\"//oss.maxcdn.com/respond/1.4.2/respond.min.js\"></script>\n  <![endif]-->\n</head>\n<body class=\"hold-transition login-page\" @if(config('admin.login_background_image'))style=\"background: url({{config('admin.login_background_image')}}) no-repeat;background-size: cover;\"@endif>\n<div class=\"login-box\">\n  <div class=\"login-logo\">\n    <a href=\"{{ admin_url('/') }}\"><b>{{config('admin.name')}}</b></a>\n  </div>\n  <!-- /.login-logo -->\n  <div class=\"login-box-body\">\n    <p class=\"login-box-msg\">{{ trans('admin.login') }}</p>\n\n    <form action=\"{{ admin_url('auth/login') }}\" method=\"post\">\n      <div class=\"form-group has-feedback {!! !$errors->has('username') ?: 'has-error' !!}\">\n\n        @if($errors->has('username'))\n          @foreach($errors->get('username') as $message)\n            <label class=\"control-label\" for=\"inputError\"><i class=\"fa fa-times-circle-o\"></i>{{$message}}</label><br>\n          @endforeach\n        @endif\n\n        <input type=\"text\" class=\"form-control\" placeholder=\"{{ trans('admin.username') }}\" name=\"username\" value=\"{{ old('username') }}\">\n        <span class=\"glyphicon glyphicon-envelope form-control-feedback\"></span>\n      </div>\n      <div class=\"form-group has-feedback {!! !$errors->has('password') ?: 'has-error' !!}\">\n\n        @if($errors->has('password'))\n          @foreach($errors->get('password') as $message)\n            <label class=\"control-label\" for=\"inputError\"><i class=\"fa fa-times-circle-o\"></i>{{$message}}</label><br>\n          @endforeach\n        @endif\n\n        <input type=\"password\" class=\"form-control\" placeholder=\"{{ trans('admin.password') }}\" name=\"password\">\n        <span class=\"glyphicon glyphicon-lock form-control-feedback\"></span>\n      </div>\n      <div class=\"row\">\n        <div class=\"col-xs-8\">\n          @if(config('admin.auth.remember'))\n          <div class=\"checkbox icheck\">\n            <label>\n              <input type=\"checkbox\" name=\"remember\" value=\"1\" {{ (!old('username') || old('remember')) ? 'checked' : '' }}>\n              {{ trans('admin.remember_me') }}\n            </label>\n          </div>\n          @endif\n        </div>\n        <!-- /.col -->\n        <div class=\"col-xs-4\">\n          <input type=\"hidden\" name=\"_token\" value=\"{{ csrf_token() }}\">\n          <button type=\"submit\" class=\"btn btn-primary btn-block btn-flat\">{{ trans('admin.login') }}</button>\n        </div>\n        <!-- /.col -->\n      </div>\n    </form>\n\n  </div>\n  <!-- /.login-box-body -->\n</div>\n<!-- /.login-box -->\n\n<!-- jQuery 2.1.4 -->\n<script src=\"{{ admin_asset(\"vendor/laravel-admin/AdminLTE/plugins/jQuery/jQuery-2.1.4.min.js\")}}\"></script>\n<!-- Bootstrap 3.3.5 -->\n<script src=\"{{ admin_asset(\"vendor/laravel-admin/AdminLTE/bootstrap/js/bootstrap.min.js\")}}\"></script>\n<!-- iCheck -->\n<script src=\"{{ admin_asset(\"vendor/laravel-admin/AdminLTE/plugins/iCheck/icheck.min.js\")}}\"></script>\n<script>\n  $(function () {\n    $('input').iCheck({\n      checkboxClass: 'icheckbox_square-blue',\n      radioClass: 'iradio_square-blue',\n      increaseArea: '20%' // optional\n    });\n  });\n</script>\n</body>\n</html>\n"
  },
  {
    "path": "resources/views/pagination.blade.php",
    "content": "<ul class=\"pagination pagination-sm no-margin pull-right\">\n    <!-- Previous Page Link -->\n    @if ($paginator->onFirstPage())\n    <li class=\"page-item disabled\"><span class=\"page-link\">&laquo;</span></li>\n    @else\n    <li class=\"page-item\"><a class=\"page-link\" href=\"{{ $paginator->previousPageUrl() }}\" rel=\"prev\">&laquo;</a></li>\n    @endif\n\n    <!-- Pagination Elements -->\n    @foreach ($elements as $element)\n    <!-- \"Three Dots\" Separator -->\n    @if (is_string($element))\n    <li class=\"page-item disabled\"><span class=\"page-link\">{{ $element }}</span></li>\n    @endif\n\n    <!-- Array Of Links -->\n    @if (is_array($element))\n    @foreach ($element as $page => $url)\n    @if ($page == $paginator->currentPage())\n    <li class=\"page-item active\"><span class=\"page-link\">{{ $page }}</span></li>\n    @else\n    <li class=\"page-item\"><a class=\"page-link\" href=\"{{ $url }}\">{{ $page }}</a></li>\n    @endif\n    @endforeach\n    @endif\n    @endforeach\n\n    <!-- Next Page Link -->\n    @if ($paginator->hasMorePages())\n    <li class=\"page-item\"><a class=\"page-link\" href=\"{{ $paginator->nextPageUrl() }}\" rel=\"next\">&raquo;</a></li>\n    @else\n    <li class=\"page-item disabled\"><span class=\"page-link\">&raquo;</span></li>\n    @endif\n</ul>\n"
  },
  {
    "path": "resources/views/partials/alerts.blade.php",
    "content": "@if($error = session()->get('error'))\n    <div class=\"alert alert-danger alert-dismissable\">\n        <button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-hidden=\"true\">×</button>\n        <h4><i class=\"icon fa fa-ban\"></i>{{ \\Illuminate\\Support\\Arr::get($error->get('title'), 0) }}</h4>\n        <p>{!!  \\Illuminate\\Support\\Arr::get($error->get('message'), 0) !!}</p>\n    </div>\n@elseif ($errors = session()->get('errors'))\n    @if ($errors->hasBag('error'))\n      <div class=\"alert alert-danger alert-dismissable\">\n\n        <button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-hidden=\"true\">×</button>\n        @foreach($errors->getBag(\"error\")->toArray() as $message)\n            <p>{!!  \\Illuminate\\Support\\Arr::get($message, 0) !!}</p>\n        @endforeach\n      </div>\n    @endif\n@endif\n\n@if($success = session()->get('success'))\n    <div class=\"alert alert-success alert-dismissable\">\n        <button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-hidden=\"true\">×</button>\n        <h4><i class=\"icon fa fa-check\"></i>{{ \\Illuminate\\Support\\Arr::get($success->get('title'), 0) }}</h4>\n        <p>{!!  \\Illuminate\\Support\\Arr::get($success->get('message'), 0) !!}</p>\n    </div>\n@endif\n\n@if($info = session()->get('info'))\n    <div class=\"alert alert-info alert-dismissable\">\n        <button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-hidden=\"true\">×</button>\n        <h4><i class=\"icon fa fa-info\"></i>{{ \\Illuminate\\Support\\Arr::get($info->get('title'), 0) }}</h4>\n        <p>{!!  \\Illuminate\\Support\\Arr::get($info->get('message'), 0) !!}</p>\n    </div>\n@endif\n\n@if($warning = session()->get('warning'))\n    <div class=\"alert alert-warning alert-dismissable\">\n        <button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-hidden=\"true\">×</button>\n        <h4><i class=\"icon fa fa-warning\"></i>{{ \\Illuminate\\Support\\Arr::get($warning->get('title'), 0) }}</h4>\n        <p>{!!  \\Illuminate\\Support\\Arr::get($warning->get('message'), 0) !!}</p>\n    </div>\n@endif"
  },
  {
    "path": "resources/views/partials/css.blade.php",
    "content": "@foreach($css as $c)\n    <link rel=\"stylesheet\" href=\"{{ admin_asset(\"$c\") }}\">\n@endforeach"
  },
  {
    "path": "resources/views/partials/exception.blade.php",
    "content": "@if($errors->hasBag('exception') && config('app.debug') == true)\n    <?php $error = $errors->getBag('exception');?>\n    <div class=\"alert alert-warning alert-dismissable\">\n        <button type=\"button\" class=\"close\" data-dismiss=\"alert\" aria-hidden=\"true\">×</button>\n        <h4>\n            <i class=\"icon fa fa-warning\"></i>\n            <i style=\"border-bottom: 1px dotted #fff;cursor: pointer;\" title=\"{{ $error->first('type') }}\" ondblclick=\"var f=this.innerHTML;this.innerHTML=this.title;this.title=f;\">{{ class_basename($error->first('type')) }}</i>\n            In <i title=\"{{ $error->first('file') }} line {{ $error->first('line') }}\" style=\"border-bottom: 1px dotted #fff;cursor: pointer;\" ondblclick=\"var f=this.innerHTML;this.innerHTML=this.title;this.title=f;\">{{ basename($error->first('file')) }} line {{ $error->first('line') }}</i> :\n        </h4>\n        <p><a style=\"cursor: pointer;\" onclick=\"$('#laravel-admin-exception-trace').toggleClass('hidden');$('i', this).toggleClass('fa-angle-double-down fa-angle-double-up');\"><i class=\"fa fa-angle-double-down\"></i>&nbsp;&nbsp;{!! $error->first('message') !!}</a></p>\n\n        <p class=\"hidden\" id=\"laravel-admin-exception-trace\"><br>{!! nl2br($error->first('trace')) !!}</p>\n    </div>\n@endif\n"
  },
  {
    "path": "resources/views/partials/footer.blade.php",
    "content": "<!-- Main Footer -->\n<footer class=\"main-footer\">\n    <!-- To the right -->\n    <div class=\"pull-right hidden-xs\">\n        @if(config('admin.show_environment'))\n            <strong>Env</strong>&nbsp;&nbsp; {!! config('app.env') !!}\n        @endif\n\n        &nbsp;&nbsp;&nbsp;&nbsp;\n\n        @if(config('admin.show_version'))\n        <strong>Version</strong>&nbsp;&nbsp; {!! \\Encore\\Admin\\Admin::VERSION !!}\n        @endif\n\n    </div>\n    <!-- Default to the left -->\n    <strong>Powered by <a href=\"https://github.com/z-song/laravel-admin\" target=\"_blank\">laravel-admin</a></strong>\n</footer>"
  },
  {
    "path": "resources/views/partials/header.blade.php",
    "content": "<!-- Main Header -->\n<header class=\"main-header\">\n\n    <!-- Logo -->\n    <a href=\"{{ admin_url('/') }}\" class=\"logo\">\n        <!-- mini logo for sidebar mini 50x50 pixels -->\n        <span class=\"logo-mini\">{!! config('admin.logo-mini', config('admin.name')) !!}</span>\n        <!-- logo for regular state and mobile devices -->\n        <span class=\"logo-lg\">{!! config('admin.logo', config('admin.name')) !!}</span>\n    </a>\n\n    <!-- Header Navbar -->\n    <nav class=\"navbar navbar-static-top\" role=\"navigation\">\n        <!-- Sidebar toggle button-->\n        <a href=\"#\" class=\"sidebar-toggle\" data-toggle=\"offcanvas\" role=\"button\">\n            <span class=\"sr-only\">Toggle navigation</span>\n        </a>\n        <ul class=\"nav navbar-nav hidden-sm visible-lg-block\">\n        {!! Admin::getNavbar()->render('left') !!}\n        </ul>\n\n        <!-- Navbar Right Menu -->\n        <div class=\"navbar-custom-menu\">\n            <ul class=\"nav navbar-nav\">\n\n                {!! Admin::getNavbar()->render() !!}\n\n                <!-- User Account Menu -->\n                <li class=\"dropdown user user-menu\">\n                    <!-- Menu Toggle Button -->\n                    <a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">\n                        <!-- The user image in the navbar-->\n                        <img src=\"{{ Admin::user()->avatar }}\" class=\"user-image\" alt=\"User Image\">\n                        <!-- hidden-xs hides the username on small devices so only the image appears. -->\n                        <span class=\"hidden-xs\">{{ Admin::user()->name }}</span>\n                    </a>\n                    <ul class=\"dropdown-menu\">\n                        <!-- The user image in the menu -->\n                        <li class=\"user-header\">\n                            <img src=\"{{ Admin::user()->avatar }}\" class=\"img-circle\" alt=\"User Image\">\n\n                            <p>\n                                {{ Admin::user()->name }}\n                                <small>Member since admin {{ Admin::user()->created_at }}</small>\n                            </p>\n                        </li>\n                        <li class=\"user-footer\">\n                            <div class=\"pull-left\">\n                                <a href=\"{{ admin_url('auth/setting') }}\" class=\"btn btn-default btn-flat\">{{ trans('admin.setting') }}</a>\n                            </div>\n                            <div class=\"pull-right\">\n                                <a href=\"{{ admin_url('auth/logout') }}\" class=\"btn btn-default btn-flat\">{{ trans('admin.logout') }}</a>\n                            </div>\n                        </li>\n                    </ul>\n                </li>\n                <!-- Control Sidebar Toggle Button -->\n                {{--<li>--}}\n                    {{--<a href=\"#\" data-toggle=\"control-sidebar\"><i class=\"fa fa-gears\"></i></a>--}}\n                {{--</li>--}}\n            </ul>\n        </div>\n    </nav>\n</header>"
  },
  {
    "path": "resources/views/partials/html.blade.php",
    "content": "@foreach($html as $item)\n    {!! $item !!}\n@endforeach\n"
  },
  {
    "path": "resources/views/partials/js.blade.php",
    "content": "@foreach($js as $j)\n<script src=\"{{ admin_asset (\"$j\") }}\"></script>\n@endforeach"
  },
  {
    "path": "resources/views/partials/menu.blade.php",
    "content": "@if(Admin::user()->visible(\\Illuminate\\Support\\Arr::get($item, 'roles', [])) && Admin::user()->can(\\Illuminate\\Support\\Arr::get($item, 'permission')))\n    @if(!isset($item['children']))\n        <li>\n            @if(url()->isValidUrl($item['uri']))\n                <a href=\"{{ $item['uri'] }}\" target=\"_blank\">\n            @else\n                 <a href=\"{{ admin_url($item['uri']) }}\">\n            @endif\n                <i class=\"fa {{$item['icon']}}\"></i>\n                @if (Lang::has($titleTranslation = 'admin.menu_titles.' . trim(str_replace(' ', '_', strtolower($item['title'])))))\n                    <span>{{ __($titleTranslation) }}</span>\n                @else\n                    <span>{{ admin_trans($item['title']) }}</span>\n                @endif\n            </a>\n        </li>\n    @else\n        <li class=\"treeview\">\n            <a href=\"#\">\n                <i class=\"fa {{ $item['icon'] }}\"></i>\n                @if (Lang::has($titleTranslation = 'admin.menu_titles.' . trim(str_replace(' ', '_', strtolower($item['title'])))))\n                    <span>{{ __($titleTranslation) }}</span>\n                @else\n                    <span>{{ admin_trans($item['title']) }}</span>\n                @endif\n                <i class=\"fa fa-angle-left pull-right\"></i>\n            </a>\n            <ul class=\"treeview-menu\">\n                @foreach($item['children'] as $item)\n                    @include('admin::partials.menu', $item)\n                @endforeach\n            </ul>\n        </li>\n    @endif\n@endif"
  },
  {
    "path": "resources/views/partials/script.blade.php",
    "content": "<script data-exec-on-popstate>$(function () {@foreach($script as $s) {!! $s !!} @endforeach});</script>\n"
  },
  {
    "path": "resources/views/partials/sidebar.blade.php",
    "content": "<aside class=\"main-sidebar\">\n\n    <!-- sidebar: style can be found in sidebar.less -->\n    <section class=\"sidebar\">\n\n        <!-- Sidebar user panel (optional) -->\n        <div class=\"user-panel\">\n            <div class=\"pull-left image\">\n                <img src=\"{{ Admin::user()->avatar }}\" class=\"img-circle\" alt=\"User Image\">\n            </div>\n            <div class=\"pull-left info\">\n                <p>{{ Admin::user()->name }}</p>\n                <!-- Status -->\n                <a href=\"#\"><i class=\"fa fa-circle text-success\"></i> {{ trans('admin.online') }}</a>\n            </div>\n        </div>\n\n        @if(config('admin.enable_menu_search'))\n        <!-- search form (Optional) -->\n        <form class=\"sidebar-form\" style=\"overflow: initial;\" onsubmit=\"return false;\">\n            <div class=\"input-group\">\n                <input type=\"text\" autocomplete=\"off\" class=\"form-control autocomplete\" placeholder=\"Search...\">\n              <span class=\"input-group-btn\">\n                <button type=\"submit\" name=\"search\" id=\"search-btn\" class=\"btn btn-flat\"><i class=\"fa fa-search\"></i>\n                </button>\n              </span>\n                <ul class=\"dropdown-menu\" role=\"menu\" style=\"min-width: 210px;max-height: 300px;overflow: auto;\">\n                    @foreach(Admin::menuLinks() as $link)\n                    <li>\n                        <a href=\"{{ admin_url($link['uri']) }}\"><i class=\"fa {{ $link['icon'] }}\"></i>{{ admin_trans($link['title']) }}</a>\n                    </li>\n                    @endforeach\n                </ul>\n            </div>\n        </form>\n        <!-- /.search form -->\n        @endif\n\n        <!-- Sidebar Menu -->\n        <ul class=\"sidebar-menu\">\n            <li class=\"header\">{{ trans('admin.menu') }}</li>\n\n            @each('admin::partials.menu', Admin::menu(), 'item')\n\n        </ul>\n        <!-- /.sidebar-menu -->\n    </section>\n    <!-- /.sidebar -->\n</aside>"
  },
  {
    "path": "resources/views/partials/style.blade.php",
    "content": "<style type=\"text/css\">@foreach($style as $s){!! $s !!}@endforeach</style>\n"
  },
  {
    "path": "resources/views/partials/toastr.blade.php",
    "content": "@if(Session::has('toastr'))\n    @php\n        $toastr     = Session::pull('toastr');\n        $type       = \\Illuminate\\Support\\Arr::get($toastr->get('type'), 0, 'success');\n        $message    = \\Illuminate\\Support\\Arr::get($toastr->get('message'), 0, '');\n        $options    = json_encode($toastr->get('options', []));\n    @endphp\n    <script>\n        $(function () {\n            toastr.{{$type}}('{!!  $message  !!}', null, {!! $options !!});\n        });\n    </script>\n@endif"
  },
  {
    "path": "resources/views/show/field.blade.php",
    "content": "<div class=\"form-group \">\n    <label class=\"col-sm-{{$width['label']}} control-label\">{{ $label }}</label>\n    <div class=\"col-sm-{{$width['field']}}\">\n        @if($wrapped)\n        <div class=\"box box-solid box-default no-margin box-show\">\n            <!-- /.box-header -->\n            <div class=\"box-body\">\n                @if($escape)\n                    {{ $content }}&nbsp;\n                @else\n                    {!! $content !!}&nbsp;\n                @endif\n            </div><!-- /.box-body -->\n        </div>\n        @else\n            @if($escape)\n                {{ $content }}\n            @else\n                {!! $content !!}\n            @endif\n        @endif\n    </div>\n</div>"
  },
  {
    "path": "resources/views/show/panel.blade.php",
    "content": "<div class=\"box box-{{ $style }}\">\n    <div class=\"box-header with-border\">\n        <h3 class=\"box-title\">{{ $title }}</h3>\n\n        <div class=\"box-tools\">\n            {!! $tools !!}\n        </div>\n    </div>\n    <!-- /.box-header -->\n    <!-- form start -->\n    <div class=\"form-horizontal\">\n\n        <div class=\"box-body\">\n\n            <div class=\"fields-group\">\n\n                @foreach($fields as $field)\n                    {!! $field->render() !!}\n                @endforeach\n            </div>\n\n        </div>\n        <!-- /.box-body -->\n    </div>\n</div>"
  },
  {
    "path": "resources/views/show.blade.php",
    "content": "<div class=\"row\">\n    <div class=\"col-md-12\">\n        {!! $panel !!}\n    </div>\n\n    <div class=\"col-md-12\">\n        @foreach($relations as $relation)\n            {!!  $relation->render() !!}\n        @endforeach\n    </div>\n</div>"
  },
  {
    "path": "resources/views/tree/branch.blade.php",
    "content": "<li class=\"dd-item\" data-id=\"{{ $branch[$keyName] }}\">\n    <div class=\"dd-handle\">\n        {!! $branchCallback($branch) !!}\n        <span class=\"pull-right dd-nodrag\">\n            <a href=\"{{ url(\"$path/$branch[$keyName]/edit\") }}\"><i class=\"fa fa-edit\"></i></a>\n            <a href=\"javascript:void(0);\" data-id=\"{{ $branch[$keyName] }}\" class=\"tree_branch_delete\"><i class=\"fa fa-trash\"></i></a>\n        </span>\n    </div>\n    @if(isset($branch['children']))\n    <ol class=\"dd-list\">\n        @foreach($branch['children'] as $branch)\n            @include($branchView, $branch)\n        @endforeach\n    </ol>\n    @endif\n</li>"
  },
  {
    "path": "resources/views/tree.blade.php",
    "content": "<div class=\"box\">\n\n    <div class=\"box-header\">\n\n        <div class=\"btn-group\">\n            <a class=\"btn btn-primary btn-sm {{ $id }}-tree-tools\" data-action=\"expand\" title=\"{{ trans('admin.expand') }}\">\n                <i class=\"fa fa-plus-square-o\"></i>&nbsp;{{ trans('admin.expand') }}\n            </a>\n            <a class=\"btn btn-primary btn-sm {{ $id }}-tree-tools\" data-action=\"collapse\" title=\"{{ trans('admin.collapse') }}\">\n                <i class=\"fa fa-minus-square-o\"></i>&nbsp;{{ trans('admin.collapse') }}\n            </a>\n        </div>\n\n        @if($useSave)\n        <div class=\"btn-group\">\n            <a class=\"btn btn-info btn-sm {{ $id }}-save\" title=\"{{ trans('admin.save') }}\"><i class=\"fa fa-save\"></i><span class=\"hidden-xs\">&nbsp;{{ trans('admin.save') }}</span></a>\n        </div>\n        @endif\n\n        @if($useRefresh)\n        <div class=\"btn-group\">\n            <a class=\"btn btn-warning btn-sm {{ $id }}-refresh\" title=\"{{ trans('admin.refresh') }}\"><i class=\"fa fa-refresh\"></i><span class=\"hidden-xs\">&nbsp;{{ trans('admin.refresh') }}</span></a>\n        </div>\n        @endif\n\n        <div class=\"btn-group\">\n            {!! $tools !!}\n        </div>\n\n        @if($useCreate)\n        <div class=\"btn-group pull-right\">\n            <a class=\"btn btn-success btn-sm\" href=\"{{ url($path) }}/create\"><i class=\"fa fa-save\"></i><span class=\"hidden-xs\">&nbsp;{{ trans('admin.new') }}</span></a>\n        </div>\n        @endif\n\n    </div>\n    <!-- /.box-header -->\n    <div class=\"box-body table-responsive no-padding\">\n        <div class=\"dd\" id=\"{{ $id }}\">\n            <ol class=\"dd-list\">\n                @each($branchView, $items, 'branch')\n            </ol>\n        </div>\n    </div>\n    <!-- /.box-body -->\n</div>\n"
  },
  {
    "path": "resources/views/widgets/alert.blade.php",
    "content": "<div {!! $attributes !!} >\n    <button type=\"button\" class=\"close\" data-dismiss=\"alert\">×</button>\n    <h4><i class=\"icon fa fa-{{ $icon }}\"></i> {{ $title }}</h4>\n    {!! $content !!}\n</div>"
  },
  {
    "path": "resources/views/widgets/box.blade.php",
    "content": "<div {!! $attributes !!}>\n    @if($title || $tools)\n        <div class=\"box-header with-border\">\n            <h3 class=\"box-title\">{{ $title }}</h3>\n            <div class=\"box-tools pull-right\">\n                @foreach($tools as $tool)\n                    {!! $tool !!}\n                @endforeach\n            </div><!-- /.box-tools -->\n        </div><!-- /.box-header -->\n    @endif\n    <div class=\"box-body\" style=\"display: block;\">\n        {!! $content !!}\n    </div><!-- /.box-body -->\n    @if($footer)\n        <div class=\"box-footer\">\n            {!! $footer !!}\n        </div><!-- /.box-footer-->\n    @endif\n</div>\n{{-- 由于widget box 有可能会用于expand，加载完页面后还没有对应的html，导致script失败，故只能和html写在一起。 --}}\n<script>\n    {!! $script !!}\n</script>"
  },
  {
    "path": "resources/views/widgets/callout.blade.php",
    "content": "<div {!! $attributes !!} >\n    @if(isset($title))\n    <h4>{{ $title }}</h4>\n    @endif\n    {!! $content !!}\n</div>"
  },
  {
    "path": "resources/views/widgets/carousel.blade.php",
    "content": "<div {!! $attributes !!} style='padding: 5px;border: 1px solid #f4f4f4;background-color:white;width:{{ $width }}px;'>\n    <ol class=\"carousel-indicators\">\n\n        @foreach($items as $key => $item)\n        <li data-target=\"#{!! $id !!}\" data-slide-to=\"{{$key}}\" class=\"{{ $key == 0 ? 'active' : '' }}\"></li>\n        @endforeach\n\n    </ol>\n    <div class=\"carousel-inner\">\n\n        @foreach($items as $key => $item)\n        <div class=\"item {{ $key == 0 ? 'active' : '' }}\">\n            <img src=\"{{ url($item['image']) }}\" alt=\"{{$item['caption']}}\" style='max-width:{{ $width }}px;max-height:{{ $height }}px;display: block;margin-left: auto;margin-right: auto;'>\n            <div class=\"carousel-caption\">\n                {{$item['caption']}}\n            </div>\n        </div>\n        @endforeach\n\n    </div>\n    <a class=\"left carousel-control\" href=\"#{!! $id !!}\" data-slide=\"prev\">\n        <span class=\"fa fa-angle-left\"></span>\n    </a>\n    <a class=\"right carousel-control\" href=\"#{!! $id !!}\" data-slide=\"next\">\n        <span class=\"fa fa-angle-right\"></span>\n    </a>\n</div>\n"
  },
  {
    "path": "resources/views/widgets/collapse.blade.php",
    "content": "<div {!! $attributes !!}>\n    @foreach($items as $key => $item)\n    <div class=\"panel box box-primary\" style=\"margin-bottom: 0px\">\n        <div class=\"box-header with-border\">\n            <h4 class=\"box-title\">\n                <a data-toggle=\"collapse\" data-parent=\"#{{$id}}\" href=\"#collapse{{ $key }}\">\n                    {{ $item['title'] }}\n                </a>\n            </h4>\n        </div>\n        <div id=\"collapse{{ $key }}\" class=\"panel-collapse collapse {{ $key == 0 ? 'in' : '' }}\">\n            <div class=\"box-body\">\n                {!! $item['content'] !!}\n            </div>\n        </div>\n    </div>\n    @endforeach\n\n</div>\n"
  },
  {
    "path": "resources/views/widgets/form.blade.php",
    "content": "<form {!! $attributes !!}>\n    <div class=\"box-body fields-group\">\n\n        @foreach($fields as $field)\n            {!! $field->render() !!}\n        @endforeach\n\n    </div>\n\n    @if ($method != 'GET')\n        <input type=\"hidden\" name=\"_token\" value=\"{{ csrf_token() }}\">\n    @endif\n    \n    <!-- /.box-body -->\n    @if(count($buttons) > 0)\n    <div class=\"box-footer\">\n        <div class=\"col-md-{{$width['label']}}\"></div>\n\n        <div class=\"col-md-{{$width['field']}}\">\n            @if(in_array('reset', $buttons))\n            <div class=\"btn-group pull-left\">\n                <button type=\"reset\" class=\"btn btn-warning pull-right\">{{ trans('admin.reset') }}</button>\n            </div>\n            @endif\n\n            @if(in_array('submit', $buttons))\n            <div class=\"btn-group pull-right\">\n                <button type=\"submit\" class=\"btn btn-info pull-right\">{{ trans('admin.submit') }}</button>\n            </div>\n            @endif\n        </div>\n    </div>\n    @endif\n</form>\n"
  },
  {
    "path": "resources/views/widgets/info-box.blade.php",
    "content": "<div {!! $attributes !!}>\n    <div class=\"inner\">\n        <h3>{{ $info }}</h3>\n\n        <p>{{ $name }}</p>\n    </div>\n    <div class=\"icon\">\n        <i class=\"fa fa-{{ $icon }}\"></i>\n    </div>\n    <a href=\"{{ $link }}\" class=\"small-box-footer\">\n        {{ trans('admin.more') }}&nbsp;\n        <i class=\"fa fa-arrow-circle-right\"></i>\n    </a>\n</div>"
  },
  {
    "path": "resources/views/widgets/tab.blade.php",
    "content": "<div {!! $attributes !!}>\n    <ul class=\"nav nav-tabs nav-tabs\">\n\n        @foreach($tabs as $id => $tab)\n            @if($tab['type'] == \\Encore\\Admin\\Widgets\\Tab::TYPE_CONTENT)\n                <li {{ $id == $active ? 'class=active' : '' }}><a href=\"#tab_{{ $tab['id'] }}\" data-toggle=\"tab\">{{ $tab['title'] }}</a></li>\n            @elseif($tab['type'] == \\Encore\\Admin\\Widgets\\Tab::TYPE_LINK)\n                <li {{ $id == $active ? 'class=active' : '' }}><a href=\"{{ $tab['href'] }}\">{{ $tab['title'] }}</a></li>\n            @endif\n        @endforeach\n\n        @if (!empty($dropDown))\n        <li class=\"dropdown\">\n            <a class=\"dropdown-toggle\" data-toggle=\"dropdown\" href=\"#\">\n                Dropdown <span class=\"caret\"></span>\n            </a>\n            <ul class=\"dropdown-menu\">\n                @foreach($dropDown as $link)\n                <li role=\"presentation\"><a role=\"menuitem\" tabindex=\"-1\" href=\"{{ $link['href'] }}\">{{ $link['name'] }}</a></li>\n                @endforeach\n            </ul>\n        </li>\n        @endif\n        <li class=\"pull-right header\">{{ $title }}</li>\n    </ul>\n    <div class=\"tab-content\">\n        @foreach($tabs as $id => $tab)\n        <div class=\"tab-pane {{ $id == $active ? 'active' : '' }}\" id=\"tab_{{ $tab['id'] }}\">\n            @php($content = \\Illuminate\\Support\\Arr::get($tab, 'content'))\n                @if($content instanceof \\Illuminate\\Contracts\\Support\\Renderable)\n                    {!! $content->render() !!}\n                @else\n                    {!! $content !!}\n                @endif\n        </div>\n        @endforeach\n\n    </div>\n</div>"
  },
  {
    "path": "resources/views/widgets/table.blade.php",
    "content": "<table {!! $attributes !!}>\n    <thead>\n    <tr>\n        @foreach($headers as $header)\n            <th>{{ $header }}</th>\n        @endforeach\n    </tr>\n    </thead>\n    <tbody>\n    @foreach($rows as $row)\n    <tr>\n        @foreach($row as $item)\n        <td>{!! $item !!}</td>\n        @endforeach\n    </tr>\n    @endforeach\n    </tbody>\n</table>"
  },
  {
    "path": "src/Actions/Action.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Actions;\n\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Form\\Field;\nuse Illuminate\\Contracts\\Support\\Renderable;\nuse Illuminate\\Http\\Request;\n\n/**\n * @method $this                success($title, $text = '', $options = [])\n * @method $this                error($title, $text = '', $options = [])\n * @method $this                warning($title, $text = '', $options = [])\n * @method $this                info($title, $text = '', $options = [])\n * @method $this                question($title, $text = '', $options = [])\n * @method $this                confirm($title, $text = '', $options = [])\n * @method Field\\Text           text($column, $label = '')\n * @method Field\\Email          email($column, $label = '')\n * @method Field\\Integer        integer($column, $label = '')\n * @method Field\\Ip             ip($column, $label = '')\n * @method Field\\Url            url($column, $label = '')\n * @method Field\\Password       password($column, $label = '')\n * @method Field\\Mobile         mobile($column, $label = '')\n * @method Field\\Textarea       textarea($column, $label = '')\n * @method Field\\Select         select($column, $label = '')\n * @method Field\\MultipleSelect multipleSelect($column, $label = '')\n * @method Field\\Checkbox       checkbox($column, $label = '')\n * @method Field\\Radio          radio($column, $label = '')\n * @method Field\\File           file($column, $label = '')\n * @method Field\\Image          image($column, $label = '')\n * @method Field\\MultipleFile   multipleFile($column, $label = '')\n * @method Field\\MultipleImage  multipleImage($column, $label = '')\n * @method Field\\Date           date($column, $label = '')\n * @method Field\\Datetime       datetime($column, $label = '')\n * @method Field\\Time           time($column, $label = '')\n * @method Field\\Hidden         hidden($column, $label = '')\n * @method $this                modalLarge()\n * @method $this                modalSmall()\n */\nabstract class Action implements Renderable\n{\n    use Authorizable;\n\n    /**\n     * @var Response\n     */\n    protected $response;\n\n    /**\n     * @var string\n     */\n    protected $selector;\n\n    /**\n     * @var string\n     */\n    public $event = 'click';\n\n    /**\n     * @var string\n     */\n    protected $method = 'POST';\n\n    /**\n     * @var array\n     */\n    protected $attributes = [];\n\n    /**\n     * @var string\n     */\n    public $selectorPrefix = '.action-';\n\n    /**\n     * @var Interactor\\Interactor\n     */\n    protected $interactor;\n\n    /**\n     * @var array\n     */\n    protected static $selectors = [];\n\n    /**\n     * @var string\n     */\n    public $name;\n\n    /**\n     * Action constructor.\n     */\n    public function __construct()\n    {\n        $this->initInteractor();\n    }\n\n    /**\n     * @throws \\Exception\n     */\n    protected function initInteractor()\n    {\n        if ($hasForm = method_exists($this, 'form')) {\n            $this->interactor = new Interactor\\Form($this);\n        }\n\n        if ($hasDialog = method_exists($this, 'dialog')) {\n            $this->interactor = new Interactor\\Dialog($this);\n        }\n\n        if ($hasForm && $hasDialog) {\n            throw new \\Exception('Can only define one of the methods in `form` and `dialog`');\n        }\n    }\n\n    /**\n     * Get batch action title.\n     *\n     * @return string\n     */\n    public function name()\n    {\n        return $this->name;\n    }\n\n    /**\n     * @param string $prefix\n     *\n     * @return mixed|string\n     */\n    public function selector($prefix)\n    {\n        if (is_null($this->selector)) {\n            return static::makeSelector(get_called_class().spl_object_id($this), $prefix);\n        }\n\n        return $this->selector;\n    }\n\n    /**\n     * @param string $class\n     * @param string $prefix\n     *\n     * @return string\n     */\n    public static function makeSelector($class, $prefix)\n    {\n        if (!isset(static::$selectors[$class])) {\n            static::$selectors[$class] = uniqid($prefix).mt_rand(1000, 9999);\n        }\n\n        return static::$selectors[$class];\n    }\n\n    /**\n     * @param string $name\n     * @param string $value\n     *\n     * @return $this\n     */\n    public function attribute($name, $value)\n    {\n        $this->attributes[$name] = $value;\n\n        return $this;\n    }\n\n    /**\n     * Format the field attributes.\n     *\n     * @return string\n     */\n    protected function formatAttributes()\n    {\n        $html = [];\n\n        foreach ($this->attributes as $name => $value) {\n            $html[] = $name.'=\"'.e($value).'\"';\n        }\n\n        return implode(' ', $html);\n    }\n\n    /**\n     * @return string\n     */\n    protected function getElementClass()\n    {\n        return ltrim($this->selector($this->selectorPrefix), '.');\n    }\n\n    /**\n     * @return Response\n     */\n    public function response()\n    {\n        if (is_null($this->response)) {\n            $this->response = new Response();\n        }\n\n        if (method_exists($this, 'dialog')) {\n            $this->response->swal();\n        } else {\n            $this->response->toastr();\n        }\n\n        return $this->response;\n    }\n\n    /**\n     * @return string\n     */\n    public function getMethod()\n    {\n        return $this->method;\n    }\n\n    /**\n     * @return mixed\n     */\n    public function getCalledClass()\n    {\n        return str_replace('\\\\', '_', get_called_class());\n    }\n\n    /**\n     * @return string\n     */\n    public function getHandleRoute()\n    {\n        return admin_url('_handle_action_');\n    }\n\n    /**\n     * @return string\n     */\n    protected function getModelClass()\n    {\n        return '';\n    }\n\n    /**\n     * @return array\n     */\n    public function parameters()\n    {\n        return [];\n    }\n\n    /**\n     * @param Request $request\n     *\n     * @return $this\n     */\n    public function validate(Request $request)\n    {\n        if ($this->interactor instanceof Interactor\\Form) {\n            $this->interactor->validate($request);\n        }\n\n        return $this;\n    }\n\n    /**\n     * @return mixed\n     */\n    protected function addScript()\n    {\n        if (!is_null($this->interactor)) {\n            return $this->interactor->addScript();\n        }\n\n        $parameters = json_encode($this->parameters());\n\n        $script = <<<SCRIPT\n\n(function ($) {\n    $('{$this->selector($this->selectorPrefix)}').off('{$this->event}').on('{$this->event}', function() {\n        var data = $(this).data();\n        var target = $(this);\n        Object.assign(data, {$parameters});\n        {$this->actionScript()}\n        {$this->buildActionPromise()}\n        {$this->handleActionPromise()}\n    });\n})(jQuery);\n\nSCRIPT;\n\n        Admin::script($script);\n    }\n\n    /**\n     * @return string\n     */\n    public function actionScript()\n    {\n        return '';\n    }\n\n    /**\n     * @return string\n     */\n    protected function buildActionPromise()\n    {\n        return <<<SCRIPT\n        var process = new Promise(function (resolve,reject) {\n\n            Object.assign(data, {\n                _token: $.admin.token,\n                _action: '{$this->getCalledClass()}',\n            });\n\n            $.ajax({\n                method: '{$this->method}',\n                url: '{$this->getHandleRoute()}',\n                data: data,\n                success: function (data) {\n                    resolve([data, target]);\n                },\n                error:function(request){\n                    reject(request);\n                }\n            });\n        });\n\nSCRIPT;\n    }\n\n    /**\n     * @return string\n     */\n    public function handleActionPromise()\n    {\n        $resolve = <<<'SCRIPT'\nvar actionResolver = function (data) {\n\n            var response = data[0];\n            var target   = data[1];\n\n            if (typeof response !== 'object') {\n                return $.admin.swal({type: 'error', title: 'Oops!'});\n            }\n\n            var then = function (then) {\n                if (then.action == 'refresh') {\n                    $.admin.reload();\n                }\n\n                if (then.action == 'download') {\n                    window.open(then.value, '_blank');\n                }\n\n                if (then.action == 'redirect') {\n                    $.admin.redirect(then.value);\n                }\n\n                if (then.action == 'location') {\n                    window.location = then.value;\n                }\n\n                if (then.action == 'open') {\n                    window.open(then.value, '_blank');\n                }\n            };\n\n            if (typeof response.html === 'string') {\n                target.html(response.html);\n            }\n\n            if (typeof response.swal === 'object') {\n                $.admin.swal(response.swal);\n            }\n\n            if (typeof response.toastr === 'object' && response.toastr.type) {\n                $.admin.toastr[response.toastr.type](response.toastr.content, '', response.toastr.options);\n            }\n\n            if (response.then) {\n              then(response.then);\n            }\n        };\n\n        var actionCatcher = function (request) {\n            if (request && typeof request.responseJSON === 'object') {\n                $.admin.toastr.error(request.responseJSON.message, '', {positionClass:\"toast-bottom-center\", timeOut: 10000}).css(\"width\",\"500px\")\n            }\n        };\nSCRIPT;\n\n        Admin::script($resolve);\n\n        return <<<'SCRIPT'\nprocess.then(actionResolver).catch(actionCatcher);\nSCRIPT;\n    }\n\n    /**\n     * @param string $method\n     * @param array  $arguments\n     *\n     * @throws \\Exception\n     *\n     * @return mixed\n     */\n    public function __call($method, $arguments = [])\n    {\n        if (in_array($method, Interactor\\Interactor::$elements)) {\n            return $this->interactor->{$method}(...$arguments);\n        }\n\n        throw new \\BadMethodCallException(\"Method {$method} does not exist.\");\n    }\n\n    /**\n     * @return string\n     */\n    public function html()\n    {\n    }\n\n    /**\n     * @return mixed\n     */\n    public function render()\n    {\n        $this->addScript();\n\n        $content = $this->html();\n\n        if ($content && $this->interactor instanceof Interactor\\Form) {\n            return $this->interactor->addElementAttr($content, $this->selector);\n        }\n\n        return $this->html();\n    }\n}\n"
  },
  {
    "path": "src/Actions/Authorizable.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Actions;\n\nuse Encore\\Admin\\Facades\\Admin;\nuse Illuminate\\Database\\Eloquent\\Collection;\nuse Illuminate\\Database\\Eloquent\\Model;\n\n/**\n * @mixin Action\n */\ntrait Authorizable\n{\n    /**\n     * @param Model $model\n     *\n     * @return bool\n     */\n    public function passesAuthorization($model = null)\n    {\n        if (method_exists($this, 'authorize')) {\n            return $this->authorize(Admin::user(), $model) == true;\n        }\n\n        if ($model instanceof Collection) {\n            $model = $model->first();\n        }\n\n        if ($model && method_exists($model, 'actionAuthorize')) {\n            return $model->actionAuthorize(Admin::user(), get_called_class()) == true;\n        }\n\n        return true;\n    }\n\n    /**\n     * @return mixed\n     */\n    public function failedAuthorization()\n    {\n        return $this->response()->error(__('admin.deny'))->send();\n    }\n}\n"
  },
  {
    "path": "src/Actions/BatchAction.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Actions;\n\nuse Illuminate\\Http\\Request;\n\nabstract class BatchAction extends GridAction\n{\n    /**\n     * @var string\n     */\n    public $selectorPrefix = '.grid-batch-action-';\n\n    /**\n     * variable holding additional CSS classes for the button.\n     *\n     * @var array\n     */\n    private $cssClasses = [];\n\n    /**\n     * add a single CSS class string to the CSS-Classes array.\n     *\n     * @param string $cssClass\n     *\n     * @return $this\n     */\n    public function addCssClass(string $cssClass)\n    {\n        if (empty($cssClass)) {\n            return $this;\n        }\n        if (!is_string($cssClass)) {\n            throw new \\Exception(__METHOD__.': item is not a valid string');\n        }\n        $this->cssClasses[] = $cssClass;\n\n        return $this;\n    }\n\n    /**\n     * add multiple CSS class strings to the CSS-Classes array.\n     *\n     * @param array $cssClasses\n     *\n     * @return $this\n     */\n    public function addCssClasses(array $cssClasses)\n    {\n        if (empty($cssClasses)) {\n            return $this;\n        }\n        if (!is_array($cssClasses)) {\n            throw new \\Exception(__METHOD__.': parameter is not a valid array');\n        }\n        foreach ($cssClasses as $item) {\n            if (!is_string($item)) {\n                throw new \\Exception(__METHOD__.': item is not a valid string');\n            }\n            $this->cssClasses[] = $item;\n        }\n\n        return $this;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function actionScript()\n    {\n        $warning = __('No data selected!');\n\n        return <<<SCRIPT\n        var key = $.admin.grid.selected();\n\n        if (key.length === 0) {\n            $.admin.toastr.warning('{$warning}', '', {positionClass: 'toast-top-center'});\n            return ;\n        }\n\n        Object.assign(data, {_key:key});\nSCRIPT;\n    }\n\n    /**\n     * @param Request $request\n     *\n     * @return mixed\n     */\n    public function retrieveModel(Request $request)\n    {\n        if (!$key = $request->get('_key')) {\n            return false;\n        }\n\n        $modelClass = str_replace('_', '\\\\', $request->get('_model'));\n\n        if (is_string($key)) {\n            $key = explode(',', $key);\n        }\n\n        if ($this->modelUseSoftDeletes($modelClass)) {\n            return $modelClass::withTrashed()->findOrFail($key);\n        }\n\n        return $modelClass::findOrFail($key);\n    }\n\n    /**\n     * @return string\n     */\n    public function render()\n    {\n        $this->addScript();\n\n        $modalId = '';\n\n        if ($this->interactor instanceof Interactor\\Form) {\n            $modalId = $this->interactor->getModalId();\n\n            if ($content = $this->html()) {\n                return $this->interactor->addElementAttr($content, $this->selector);\n            }\n        }\n\n        return sprintf(\n            \"<a href='javascript:void(0);' class='%s %s' %s>%s</a>\",\n            $this->getElementClass(),\n            (!empty($this->cssClasses)) ? implode(' ', $this->cssClasses) : '',\n            $modalId ? \"modal='{$modalId}'\" : '',\n            $this->name()\n        );\n    }\n}\n"
  },
  {
    "path": "src/Actions/GridAction.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Actions;\n\nuse Encore\\Admin\\Grid;\nuse Illuminate\\Database\\Eloquent\\SoftDeletes;\nuse Illuminate\\Http\\Request;\n\n/**\n * Class GridAction.\n *\n * @method retrieveModel(Request $request)\n */\nabstract class GridAction extends Action\n{\n    /**\n     * @var Grid\n     */\n    protected $parent;\n\n    /**\n     * @var string\n     */\n    public $selectorPrefix = '.grid-action-';\n\n    /**\n     * @param Grid $grid\n     *\n     * @return $this\n     */\n    public function setGrid(Grid $grid)\n    {\n        $this->parent = $grid;\n\n        return $this;\n    }\n\n    /**\n     * Get url path of current resource.\n     *\n     * @return string\n     */\n    public function getResource()\n    {\n        return $this->parent->resource();\n    }\n\n    /**\n     * @return mixed\n     */\n    protected function getModelClass()\n    {\n        $model = $this->parent->model()->getOriginalModel();\n\n        return str_replace('\\\\', '_', get_class($model));\n    }\n\n    /**\n     * @return array\n     */\n    public function parameters()\n    {\n        return ['_model' => $this->getModelClass()];\n    }\n\n    /**\n     * Indicates if model uses soft-deletes.\n     *\n     * @param $modelClass\n     *\n     * @return bool\n     */\n    protected function modelUseSoftDeletes($modelClass)\n    {\n        return in_array(SoftDeletes::class, class_uses_deep($modelClass));\n    }\n}\n"
  },
  {
    "path": "src/Actions/Interactor/Dialog.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Actions\\Interactor;\n\nuse Encore\\Admin\\Admin;\n\nclass Dialog extends Interactor\n{\n    /**\n     * @var bool\n     */\n    protected $uploadFile = false;\n\n    /**\n     * @var array\n     */\n    protected $settings;\n\n    /**\n     * @param string $title\n     * @param string $text\n     * @param array  $options\n     *\n     * @return Dialog\n     */\n    public function success($title, $text = '', $options = [])\n    {\n        return $this->addSettings($title, __FUNCTION__, $text, $options);\n    }\n\n    /**\n     * @param string $title\n     * @param string $text\n     * @param array  $options\n     *\n     * @return Dialog\n     */\n    public function error($title, $text = '', $options = [])\n    {\n        return $this->addSettings($title, __FUNCTION__, $text, $options);\n    }\n\n    /**\n     * @param string $title\n     * @param string $text\n     * @param array  $options\n     *\n     * @return $this\n     */\n    public function warning($title, $text = '', $options = [])\n    {\n        return $this->addSettings($title, __FUNCTION__, $text, $options);\n    }\n\n    /**\n     * @param string $title\n     * @param string $text\n     * @param array  $options\n     *\n     * @return Dialog\n     */\n    public function info($title, $text = '', $options = [])\n    {\n        return $this->addSettings($title, __FUNCTION__, $text, $options);\n    }\n\n    /**\n     * @param string $title\n     * @param string $text\n     * @param array  $options\n     *\n     * @return Dialog\n     */\n    public function question($title, $text = '', $options = [])\n    {\n        return $this->addSettings($title, __FUNCTION__, $text, $options);\n    }\n\n    /**\n     * @param string $title\n     * @param string $text\n     * @param array  $options\n     *\n     * @return Dialog\n     */\n    public function confirm($title, $text = '', $options = [])\n    {\n        return $this->addSettings($title, 'question', $text, $options);\n    }\n\n    /**\n     * @param string $title\n     * @param string $type\n     * @param string $text\n     * @param array  $options\n     *\n     * @return $this\n     */\n    protected function addSettings($title, $type, $text = '', $options = [])\n    {\n        $this->settings = array_merge(\n            compact('title', 'text', 'type'),\n            $options\n        );\n\n        return $this;\n    }\n\n    /**\n     * @return array\n     */\n    protected function defaultSettings()\n    {\n        $trans = [\n            'cancel' => trans('admin.cancel'),\n            'submit' => trans('admin.submit'),\n        ];\n\n        return [\n            'type'                => 'question',\n            'showCancelButton'    => true,\n            'showLoaderOnConfirm' => true,\n            'confirmButtonText'   => $trans['submit'],\n            'cancelButtonText'    => $trans['cancel'],\n        ];\n    }\n\n    /**\n     * @return string\n     */\n    protected function formatSettings()\n    {\n        if (empty($this->settings)) {\n            return '';\n        }\n\n        $settings = array_merge($this->defaultSettings(), $this->settings);\n\n        return trim(substr(json_encode($settings, JSON_PRETTY_PRINT), 1, -1));\n    }\n\n    /**\n     * @return void\n     */\n    public function addScript()\n    {\n        $parameters = json_encode($this->action->parameters());\n\n        $script = <<<SCRIPT\n\n(function ($) {\n    $('{$this->action->selector($this->action->selectorPrefix)}').off('{$this->action->event}').on('{$this->action->event}', function() {\n        var data = $(this).data();\n        var target = $(this);\n        Object.assign(data, {$parameters});\n        {$this->action->actionScript()}\n        {$this->buildActionPromise()}\n        {$this->action->handleActionPromise()}\n    });\n})(jQuery);\n\nSCRIPT;\n\n        Admin::script($script);\n    }\n\n    /**\n     * @return string\n     */\n    protected function buildActionPromise()\n    {\n        call_user_func([$this->action, 'dialog']);\n\n        $route = $this->action->getHandleRoute();\n        $settings = $this->formatSettings();\n        $calledClass = $this->action->getCalledClass();\n\n        if ($this->uploadFile) {\n            return $this->buildUploadFileActionPromise($settings, $calledClass, $route);\n        }\n\n        return <<<PROMISE\n        var process = $.admin.swal({\n            {$settings},\n            preConfirm: function(input) {\n                return new Promise(function(resolve, reject) {\n                    Object.assign(data, {\n                        _token: $.admin.token,\n                        _action: '$calledClass',\n                        _input: input,\n                    });\n\n                    $.ajax({\n                        method: '{$this->action->getMethod()}',\n                        url: '$route',\n                        data: data,\n                        success: function (data) {\n                            resolve(data);\n                        },\n                        error:function(request){\n                            reject(request);\n                        }\n                    });\n                });\n            }\n        }).then(function(result) {\n            if (typeof result.dismiss !== 'undefined') {\n                return Promise.reject();\n            }\n            \n            if (typeof result.status === \"boolean\") {\n                var response = result;\n            } else {\n                var response = result.value;\n            }\n\n            return [response, target];\n        });\nPROMISE;\n    }\n\n    /**\n     * @param string $settings\n     * @param string $calledClass\n     * @param string $route\n     *\n     * @return string\n     */\n    protected function buildUploadFileActionPromise($settings, $calledClass, $route)\n    {\n        return <<<PROMISE\nvar process = $.admin.swal({\n    {$settings}\n}).then(function (file) {\n    return new Promise(function (resolve) {\n        var data = {\n            _token: $.admin.token,\n            _action: '$calledClass',\n        };\n\n        var formData = new FormData();\n        for ( var key in data ) {\n            formData.append(key, data[key]);\n        }\n\n        formData.append('_input', file.value, file.value.name);\n\n        $.ajax({\n            url: '{$route}',\n            type: 'POST',\n            data: formData,\n            processData: false,\n            contentType: false,\n            enctype: 'multipart/form-data',\n            success: function (data) {\n                resolve([response, target]);\n            },\n            error:function(request){\n                reject(request);\n            }\n        });\n    });\n})\nPROMISE;\n    }\n}\n"
  },
  {
    "path": "src/Actions/Interactor/Form.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Actions\\Interactor;\n\nuse Encore\\Admin\\Actions\\RowAction;\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Form\\Field;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\MessageBag;\nuse Illuminate\\Validation\\ValidationException;\nuse Illuminate\\Validation\\Validator;\nuse Symfony\\Component\\DomCrawler\\Crawler;\n\nclass Form extends Interactor\n{\n    /**\n     * @var array\n     */\n    protected $fields = [];\n\n    /**\n     * @var string\n     */\n    protected $modalId;\n\n    /**\n     * @var string\n     */\n    protected $modalSize = '';\n\n    /**\n     * @var string\n     */\n    protected $confirm = '';\n\n    /**\n     * @param string $label\n     *\n     * @return array\n     */\n    protected function formatLabel($label)\n    {\n        return array_filter((array) $label);\n    }\n\n    /**\n     * @param string $column\n     * @param string $label\n     *\n     * @return Field\\Text\n     */\n    public function text($column, $label = '')\n    {\n        $field = new Field\\Text($column, $this->formatLabel($label));\n\n        $this->addField($field);\n\n        return $field;\n    }\n\n    /**\n     * @param $column\n     * @param string   $label\n     * @param \\Closure $builder\n     *\n     * @return Field\\Table\n     */\n    public function table($column, $label = '', $builder = null)\n    {\n        $field = new Field\\Table($column, [$label, $builder]);\n\n        $this->addField($field);\n\n        return $field;\n    }\n\n    /**\n     * @param string $column\n     * @param string $label\n     *\n     * @return Field\\Text\n     */\n    public function email($column, $label = '')\n    {\n        $field = new Field\\Email($column, $this->formatLabel($label));\n\n        $this->addField($field)->setView('admin::actions.form.text');\n\n        return $field->inputmask(['alias' => 'email']);\n    }\n\n    /**\n     * @param string $column\n     * @param string $label\n     *\n     * @return Field\\Text\n     */\n    public function integer($column, $label = '')\n    {\n        return $this->text($column, $label)\n            ->width('200px')\n            ->inputmask(['alias' => 'integer']);\n    }\n\n    /**\n     * @param string $column\n     * @param string $label\n     *\n     * @return Field\\Text\n     */\n    public function ip($column, $label = '')\n    {\n        return $this->text($column, $label)\n            ->width('200px')\n            ->inputmask(['alias' => 'ip']);\n    }\n\n    /**\n     * @param string $column\n     * @param string $label\n     *\n     * @return Field\\Text\n     */\n    public function url($column, $label = '')\n    {\n        return $this->text($column, $label)\n            ->inputmask(['alias' => 'url'])\n            ->width('200px');\n    }\n\n    /**\n     * @param string $column\n     * @param string $label\n     *\n     * @return Field\\Text\n     */\n    public function password($column, $label = '')\n    {\n        return $this->text($column, $label)\n            ->attribute('type', 'password');\n    }\n\n    /**\n     * @param string $column\n     * @param string $label\n     *\n     * @return Field\\Text\n     */\n    public function mobile($column, $label = '')\n    {\n        return $this->text($column, $label)\n            ->inputmask(['mask' => '99999999999'])\n            ->width('100px');\n    }\n\n    /**\n     * @param string $column\n     * @param string $label\n     *\n     * @return Field\\Textarea\n     */\n    public function textarea($column, $label = '')\n    {\n        $field = new Field\\Textarea($column, $this->formatLabel($label));\n\n        $this->addField($field);\n\n        return $field;\n    }\n\n    /**\n     * @param string $column\n     * @param string $label\n     *\n     * @return Field\\Select\n     */\n    public function select($column, $label = '')\n    {\n        $field = new Field\\Select($column, $this->formatLabel($label));\n\n        $this->addField($field);\n\n        return $field;\n    }\n\n    /**\n     * @param string $column\n     * @param string $label\n     *\n     * @return Field\\MultipleSelect\n     */\n    public function multipleSelect($column, $label = '')\n    {\n        $field = new Field\\MultipleSelect($column, $this->formatLabel($label));\n\n        $this->addField($field);\n\n        return $field;\n    }\n\n    /**\n     * @param string $column\n     * @param string $label\n     *\n     * @return Field\\Checkbox\n     */\n    public function checkbox($column, $label = '')\n    {\n        $field = new Field\\Checkbox($column, $this->formatLabel($label));\n\n        $this->addField($field);\n\n        return $field;\n    }\n\n    /**\n     * @param string $column\n     * @param string $label\n     *\n     * @return Field\\Radio\n     */\n    public function radio($column, $label = '')\n    {\n        $field = new Field\\Radio($column, $this->formatLabel($label));\n\n        $this->addField($field);\n\n        return $field;\n    }\n\n    /**\n     * @param string $column\n     * @param string $label\n     *\n     * @return Field\\File\n     */\n    public function file($column, $label = '')\n    {\n        $field = new Field\\File($column, $this->formatLabel($label));\n\n        $this->addField($field);\n\n        return $field;\n    }\n\n    /**\n     * @param string $column\n     * @param string $label\n     *\n     * @return Field\\MultipleFile\n     */\n    public function multipleFile($column, $label = '')\n    {\n        $field = new Field\\MultipleFile($column, $this->formatLabel($label));\n\n        $this->addField($field);\n\n        return $field;\n    }\n\n    /**\n     * @param string $column\n     * @param string $label\n     *\n     * @return Field\\Image\n     */\n    public function image($column, $label = '')\n    {\n        $field = new Field\\Image($column, $this->formatLabel($label));\n\n        $this->addField($field)->setView('admin::actions.form.file');\n\n        return $field;\n    }\n\n    /**\n     * @param string $column\n     * @param string $label\n     *\n     * @return Field\\MultipleImage\n     */\n    public function multipleImage($column, $label = '')\n    {\n        $field = new Field\\MultipleImage($column, $this->formatLabel($label));\n\n        $this->addField($field)->setView('admin::actions.form.muitplefile');\n\n        return $field;\n    }\n\n    /**\n     * @param string $column\n     * @param string $label\n     *\n     * @return Field\\Date\n     */\n    public function date($column, $label = '')\n    {\n        $field = new Field\\Date($column, $this->formatLabel($label));\n\n        $this->addField($field);\n\n        return $field;\n    }\n\n    /**\n     * @param string $column\n     * @param string $label\n     *\n     * @return Field\\Date\n     */\n    public function datetime($column, $label = '')\n    {\n        return $this->date($column, $label)->format('YYYY-MM-DD HH:mm:ss');\n    }\n\n    /**\n     * @param string $column\n     * @param string $label\n     *\n     * @return Field\\Date\n     */\n    public function time($column, $label = '')\n    {\n        return $this->date($column, $label)->format('HH:mm:ss');\n    }\n\n    /**\n     * @param string $column\n     * @param string $label\n     *\n     * @return Field\\Hidden\n     */\n    public function hidden($column, $label = '')\n    {\n        $field = new Field\\Hidden($column, $this->formatLabel($label));\n\n        $this->addField($field);\n\n        return $field;\n    }\n\n    /**\n     * @param $message\n     *\n     * @return $this\n     */\n    public function confirm($message)\n    {\n        $this->confirm = $message;\n\n        return $this;\n    }\n\n    /**\n     * @return $this\n     */\n    public function modalLarge()\n    {\n        $this->modalSize = 'modal-lg';\n\n        return $this;\n    }\n\n    /**\n     * @return $this\n     */\n    public function modalSmall()\n    {\n        $this->modalSize = 'modal-sm';\n\n        return $this;\n    }\n\n    /**\n     * @param string $content\n     * @param string $selector\n     *\n     * @return string\n     */\n    public function addElementAttr($content, $selector)\n    {\n        $crawler = new Crawler($content);\n\n        $node = $crawler->filter($selector)->getNode(0);\n        $node->setAttribute('modal', $this->getModalId());\n\n        return $crawler->children()->html();\n    }\n\n    /**\n     * @param Field $field\n     *\n     * @return Field\n     */\n    protected function addField(Field $field)\n    {\n        $elementClass = array_merge(['action'], $field->getElementClass());\n\n        $field->addElementClass($elementClass);\n\n        $field->setView($this->resolveView(get_class($field)));\n\n        array_push($this->fields, $field);\n\n        return $field;\n    }\n\n    /**\n     * @param Request $request\n     *\n     * @throws ValidationException\n     * @throws \\Exception\n     *\n     * @return void\n     */\n    public function validate(Request $request)\n    {\n        if ($this->action instanceof RowAction) {\n            call_user_func([$this->action, 'form'], $this->action->getRow());\n        } else {\n            call_user_func([$this->action, 'form']);\n        }\n\n        $failedValidators = [];\n\n        /** @var Field $field */\n        foreach ($this->fields as $field) {\n            if (!$validator = $field->getValidator($request->all())) {\n                continue;\n            }\n\n            if (($validator instanceof Validator) && !$validator->passes()) {\n                $failedValidators[] = $validator;\n            }\n        }\n\n        $message = $this->mergeValidationMessages($failedValidators);\n\n        if ($message->any()) {\n            throw ValidationException::withMessages($message->toArray());\n        }\n    }\n\n    /**\n     * Merge validation messages from input validators.\n     *\n     * @param \\Illuminate\\Validation\\Validator[] $validators\n     *\n     * @return MessageBag\n     */\n    protected function mergeValidationMessages($validators)\n    {\n        $messageBag = new MessageBag();\n\n        foreach ($validators as $validator) {\n            $messageBag = $messageBag->merge($validator->messages());\n        }\n\n        return $messageBag;\n    }\n\n    /**\n     * @param string $class\n     *\n     * @return string\n     */\n    protected function resolveView($class)\n    {\n        $path = explode('\\\\', $class);\n\n        $name = strtolower(array_pop($path));\n\n        return \"admin::actions.form.{$name}\";\n    }\n\n    /**\n     * @return void\n     */\n    public function addModalHtml()\n    {\n        $data = [\n            'fields'     => $this->fields,\n            'title'      => $this->action->name(),\n            'modal_id'   => $this->getModalId(),\n            'modal_size' => $this->modalSize,\n        ];\n\n        $modal = view('admin::actions.form.modal', $data)->render();\n\n        Admin::html($modal);\n    }\n\n    /**\n     * @return string\n     */\n    public function getModalId()\n    {\n        if (!$this->modalId) {\n            if ($this->action instanceof RowAction) {\n                $this->modalId = uniqid('row-action-modal-').mt_rand(1000, 9999);\n            } else {\n                $this->modalId = strtolower(str_replace('\\\\', '-', get_class($this->action)));\n            }\n        }\n\n        return $this->modalId;\n    }\n\n    /**\n     * @return void\n     */\n    public function addScript()\n    {\n        $this->action->attribute('modal', $this->getModalId());\n\n        $parameters = json_encode($this->action->parameters());\n\n        $script = <<<SCRIPT\n\n(function ($) {\n    $('{$this->action->selector($this->action->selectorPrefix)}').off('{$this->action->event}').on('{$this->action->event}', function() {\n        var data = $(this).data();\n        var target = $(this);\n        var modalId = $(this).attr('modal');\n        Object.assign(data, {$parameters});\n        {$this->action->actionScript()}\n        $('#'+modalId).modal('show');\n        $(':submit', '#'+modalId).button('reset');\n        $('#'+modalId+' form').off('submit').on('submit', function (e) {\n            $(':submit', e.target).button('loading');\n            e.preventDefault();\n            var form = this;\n            {$this->buildActionPromise()}\n            {$this->action->handleActionPromise()}\n        });\n    });\n})(jQuery);\n\nSCRIPT;\n\n        Admin::script($script);\n    }\n\n    /**\n     * @return string\n     */\n    protected function buildConfirmActionPromise()\n    {\n        $trans = [\n            'cancel' => trans('admin.cancel'),\n            'submit' => trans('admin.submit'),\n        ];\n\n        $settings = [\n            'type'                => 'question',\n            'showCancelButton'    => true,\n            'showLoaderOnConfirm' => true,\n            'confirmButtonText'   => $trans['submit'],\n            'cancelButtonText'    => $trans['cancel'],\n            'title'               => $this->confirm,\n            'text'                => '',\n        ];\n\n        $settings = trim(substr(json_encode($settings, JSON_PRETTY_PRINT), 1, -1));\n\n        return <<<PROMISE\n        var process = $.admin.swal({\n            {$settings},\n            preConfirm: function() {\n                {$this->buildGeneralActionPromise()}\n\n                return process;\n            }\n        }).then(function(result) {\n\n            if (typeof result.dismiss !== 'undefined') {\n                return Promise.reject();\n            }\n\n            var result = result.value[0];\n\n            if (typeof result.status === \"boolean\") {\n                var response = result;\n            } else {\n                var response = result.value;\n            }\n\n            return [response, target];\n        });\nPROMISE;\n    }\n\n    protected function buildGeneralActionPromise()\n    {\n        return <<<SCRIPT\n        var process = new Promise(function (resolve,reject) {\n            Object.assign(data, {\n                _token: $.admin.token,\n                _action: '{$this->action->getCalledClass()}',\n            });\n\n            var formData = new FormData(form);\n            for (var key in data) {\n                formData.append(key, data[key]);\n            }\n\n            $.ajax({\n                method: '{$this->action->getMethod()}',\n                url: '{$this->action->getHandleRoute()}',\n                data: formData,\n                cache: false,\n                contentType: false,\n                processData: false,\n                success: function (data) {\n                    resolve([data, target]);\n                    if (data.status === true) {\n                        $('#'+modalId).modal('hide');\n                    }\n                    $(':submit', '#'+modalId).button('reset');\n                },\n                error:function(request){\n                    reject(request);\n                }\n            });\n        });\nSCRIPT;\n    }\n\n    /**\n     * @throws \\Exception\n     *\n     * @return string\n     */\n    protected function buildActionPromise()\n    {\n        if ($this->action instanceof RowAction) {\n            call_user_func([$this->action, 'form'], $this->action->getRow());\n        } else {\n            call_user_func([$this->action, 'form']);\n        }\n\n        $this->addModalHtml();\n\n        if (!empty($this->confirm)) {\n            return $this->buildConfirmActionPromise();\n        }\n\n        return $this->buildGeneralActionPromise();\n    }\n}\n"
  },
  {
    "path": "src/Actions/Interactor/Interactor.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Actions\\Interactor;\n\nuse Encore\\Admin\\Actions\\Action;\n\nabstract class Interactor\n{\n    /**\n     * @var Action\n     */\n    protected $action;\n\n    /**\n     * @var array\n     */\n    public static $elements = [\n        'success', 'error', 'warning', 'info', 'question', 'confirm',\n        'text', 'email', 'integer', 'ip', 'url', 'password', 'mobile',\n        'textarea', 'select', 'multipleSelect', 'checkbox', 'radio',\n        'file', 'image', 'date', 'datetime', 'time', 'hidden', 'multipleImage',\n        'multipleFile', 'modalLarge', 'modalSmall',\n    ];\n\n    /**\n     * Dialog constructor.\n     *\n     * @param Action $action\n     */\n    public function __construct(Action $action)\n    {\n        $this->action = $action;\n    }\n\n    /**\n     * @return mixed\n     */\n    abstract public function addScript();\n}\n"
  },
  {
    "path": "src/Actions/Response.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Actions;\n\nuse Illuminate\\Validation\\ValidationException;\n\n/**\n * Class Response.\n *\n * @method $this topCenter()\n * @method $this topLeft()\n * @method $this topRight()\n * @method $this bottomLeft()\n * @method $this bottomCenter()\n * @method $this bottomRight()\n * @method $this topFullWidth()\n * @method $this bottomFullWidth()\n * @method $this timeout($timeout = 5000)\n */\nclass Response\n{\n    /**\n     * @var bool\n     */\n    public $status = true;\n\n    /**\n     * @var \\Exception\n     */\n    public $exception;\n\n    /**\n     * @var array\n     */\n    public $toastrMethods = [\n        'topCenter', 'topLeft', 'topRight',\n        'bottomLeft', 'bottomCenter', 'bottomRight',\n        'topFullWidth', 'bottomFullWidth', 'timeout',\n    ];\n\n    /**\n     * @var\n     */\n    protected $plugin;\n\n    /**\n     * @var array\n     */\n    protected $then = [];\n\n    /**\n     * @var string\n     */\n    protected $html = '';\n\n    /**\n     * @return $this\n     */\n    public function toastr()\n    {\n        if (!$this->plugin instanceof Toastr) {\n            $this->plugin = new Toastr();\n        }\n\n        return $this;\n    }\n\n    /**\n     * @return $this\n     */\n    public function swal()\n    {\n        if (!$this->plugin instanceof SweatAlert2) {\n            $this->plugin = new SweatAlert2();\n        }\n\n        return $this;\n    }\n\n    /**\n     * @return SweatAlert2\n     */\n    public function getPlugin()\n    {\n        return $this->plugin;\n    }\n\n    /**\n     * @param string $message\n     *\n     * @return $this\n     */\n    public function success(string $message = '')\n    {\n        return $this->show('success', $message);\n    }\n\n    /**\n     * @param string $message\n     *\n     * @return $this\n     */\n    public function info(string $message = '')\n    {\n        return $this->show('info', $message);\n    }\n\n    /**\n     * @param string $message\n     *\n     * @return $this\n     */\n    public function warning(string $message = '')\n    {\n        return $this->show('warning', $message);\n    }\n\n    /**\n     * @param string $message\n     *\n     * @return $this\n     */\n    public function error(string $message = '')\n    {\n        return $this->show('error', $message);\n    }\n\n    /**\n     * @param string $type\n     * @param string $title\n     *\n     * @return $this\n     */\n    protected function show($type, $title = '')\n    {\n        $this->getPlugin()->show($type, $title);\n\n        return $this;\n    }\n\n    /**\n     * Send a redirect response.\n     *\n     * @param string $url\n     *\n     * @return $this\n     */\n    public function redirect(string $url)\n    {\n        $this->then = ['action' => 'redirect', 'value' => $url];\n\n        return $this;\n    }\n\n    /**\n     * Send a open new window response.\n     *\n     * @param string $url\n     */\n    public function open(string $url)\n    {\n        $this->then = ['action' => 'open', 'value' => $url];\n\n        return $this;\n    }\n\n    /**\n     * Send a location redirect response.\n     *\n     * @param string $location\n     *\n     * @return $this\n     */\n    public function location(string $location)\n    {\n        $this->then = ['action' => 'location', 'value' => $location];\n\n        return $this;\n    }\n\n    /**\n     * Send a download response.\n     *\n     * @param string $url\n     *\n     * @return $this\n     */\n    public function download($url)\n    {\n        $this->then = ['action' => 'download', 'value' => $url];\n\n        return $this;\n    }\n\n    /**\n     * Send a refresh response.\n     *\n     * @return $this\n     */\n    public function refresh()\n    {\n        $this->then = ['action' => 'refresh', 'value' => true];\n\n        return $this;\n    }\n\n    /**\n     * Send a html response.\n     *\n     * @param string $html\n     *\n     * @return $this\n     */\n    public function html($html = '')\n    {\n        $this->html = $html;\n\n        return $this;\n    }\n\n    /**\n     * @param \\Exception $exception\n     *\n     * @return mixed\n     */\n    public static function withException(\\Exception $exception)\n    {\n        $response = new static();\n\n        $response->status = false;\n\n        if ($exception instanceof ValidationException) {\n            $message = collect($exception->errors())->flatten()->implode(\"\\n\");\n        } else {\n            $message = $exception->getMessage();\n        }\n\n        return $response->toastr()->topCenter()->error($message);\n    }\n\n    /**\n     * @return \\Illuminate\\Http\\JsonResponse\n     */\n    public function send()\n    {\n        $data = array_merge(\n            ['status' => $this->status, 'then' => $this->then],\n            $this->getPlugin()->getOptions()\n        );\n\n        if ($this->html) {\n            $data['html'] = $this->html;\n        }\n\n        return response()->json($data);\n    }\n\n    /**\n     * @param string $method\n     * @param array  $arguments\n     *\n     * @return $this\n     */\n    public function __call($method, $arguments)\n    {\n        if (in_array($method, $this->toastrMethods)) {\n            $this->toastr();\n        }\n\n        $this->getPlugin()->{$method}(...$arguments);\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Actions/RowAction.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Actions;\n\nuse Encore\\Admin\\Grid\\Column;\nuse Illuminate\\Http\\Request;\n\nabstract class RowAction extends GridAction\n{\n    /**\n     * @var \\Illuminate\\Database\\Eloquent\\Model\n     */\n    protected $row;\n\n    /**\n     * @var Column\n     */\n    protected $column;\n\n    /**\n     * @var string\n     */\n    public $selectorPrefix = '.grid-row-action-';\n\n    /**\n     * @var bool\n     */\n    protected $asColumn = false;\n\n    /**\n     * Get primary key value of current row.\n     *\n     * @return mixed\n     */\n    protected function getKey()\n    {\n        return $this->row->getKey();\n    }\n\n    /**\n     * Set row model.\n     *\n     * @param mixed $key\n     *\n     * @return \\Illuminate\\Database\\Eloquent\\Model|mixed\n     */\n    public function row($key = null)\n    {\n        if (func_num_args() == 0) {\n            return $this->row;\n        }\n\n        return $this->row->getAttribute($key);\n    }\n\n    /**\n     * Set row model.\n     *\n     * @param \\Illuminate\\Database\\Eloquent\\Model $row\n     *\n     * @return $this\n     */\n    public function setRow($row)\n    {\n        $this->row = $row;\n\n        return $this;\n    }\n\n    public function getRow()\n    {\n        return $this->row;\n    }\n\n    /**\n     * @param Column $column\n     *\n     * @return $this\n     */\n    public function setColumn(Column $column)\n    {\n        $this->column = $column;\n\n        return $this;\n    }\n\n    /**\n     * Show this action as a column.\n     *\n     * @return $this\n     */\n    public function asColumn()\n    {\n        $this->asColumn = true;\n\n        return $this;\n    }\n\n    /**\n     * @return string\n     */\n    public function href()\n    {\n    }\n\n    /**\n     * @param Request $request\n     *\n     * @return mixed\n     */\n    public function retrieveModel(Request $request)\n    {\n        if (!$key = $request->get('_key')) {\n            return false;\n        }\n\n        $modelClass = str_replace('_', '\\\\', $request->get('_model'));\n\n        if ($this->modelUseSoftDeletes($modelClass)) {\n            return $modelClass::withTrashed()->findOrFail($key);\n        }\n\n        return $modelClass::findOrFail($key);\n    }\n\n    public function display($value)\n    {\n    }\n\n    /**\n     * Render row action.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        if ($href = $this->href()) {\n            return \"<a href='{$href}'>{$this->name()}</a>\";\n        }\n\n        $this->addScript();\n\n        $attributes = $this->formatAttributes();\n\n        return sprintf(\n            \"<a data-_key='%s' href='javascript:void(0);' class='%s' {$attributes}>%s</a>\",\n            $this->getKey(),\n            $this->getElementClass(),\n            $this->asColumn ? $this->display($this->row($this->column->getName())) : $this->name()\n        );\n    }\n}\n"
  },
  {
    "path": "src/Actions/SweatAlert2.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Actions;\n\nclass SweatAlert2\n{\n    /**\n     * @var string\n     */\n    protected $type;\n\n    /**\n     * @var string\n     */\n    protected $title;\n\n    /**\n     * @param string $type\n     * @param string $title\n     *\n     * @return $this\n     */\n    public function show($type, $title = '')\n    {\n        $this->type = $type;\n        $this->title = $title;\n\n        return $this;\n    }\n\n    /**\n     * @return array\n     */\n    public function getOptions()\n    {\n        return [\n            'swal' => [\n                'type'  => $this->type,\n                'title' => $this->title,\n            ],\n        ];\n    }\n}\n"
  },
  {
    "path": "src/Actions/Toastr.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Actions;\n\nuse Illuminate\\Support\\Arr;\n\nclass Toastr\n{\n    /**\n     * @var string\n     */\n    protected $type;\n\n    /**\n     * @var string\n     */\n    protected $content;\n\n    /**\n     * @var array\n     */\n    protected $options = [];\n\n    /**\n     * @param string $type\n     * @param string $content\n     *\n     * @return $this\n     */\n    public function show($type, $content = '')\n    {\n        $this->type = $type;\n        $this->content = $content;\n\n        return $this;\n    }\n\n    /**\n     * @param $option\n     * @param $value\n     *\n     * @return $this\n     */\n    protected function options($option, $value)\n    {\n        Arr::set($this->options, $option, $value);\n\n        return $this;\n    }\n\n    /**\n     * @param $position\n     *\n     * @return Toastr\n     */\n    protected function position($position)\n    {\n        return $this->options('positionClass', $position);\n    }\n\n    /**\n     * @return Toastr\n     */\n    public function topCenter()\n    {\n        return $this->position('toast-top-center');\n    }\n\n    /**\n     * @return Toastr\n     */\n    public function topLeft()\n    {\n        return $this->position('toast-top-left');\n    }\n\n    /**\n     * @return Toastr\n     */\n    public function topRight()\n    {\n        return $this->position('toast-top-right');\n    }\n\n    /**\n     * @return Toastr\n     */\n    public function bottomLeft()\n    {\n        return $this->position('toast-bottom-left');\n    }\n\n    /**\n     * @return Toastr\n     */\n    public function bottomCenter()\n    {\n        return $this->position('toast-bottom-center');\n    }\n\n    /**\n     * @return Toastr\n     */\n    public function bottomRight()\n    {\n        return $this->position('toast-bottom-right');\n    }\n\n    /**\n     * @return Toastr\n     */\n    public function topFullWidth()\n    {\n        return $this->position('toast-top-full-width');\n    }\n\n    /**\n     * @return Toastr\n     */\n    public function bottomFullWidth()\n    {\n        return $this->position('toast-bottom-full-width');\n    }\n\n    /**\n     * @return Toastr\n     */\n    public function timeout($timeout = 5000)\n    {\n        return $this->options('timeOut', $timeout);\n    }\n\n    /**\n     * @return array\n     */\n    public function getOptions()\n    {\n        if (!isset($this->options['positionClass'])) {\n            $this->topCenter();\n        }\n\n        return [\n            'toastr' => [\n                'type'    => $this->type,\n                'content' => $this->content,\n                'options' => $this->options,\n            ],\n        ];\n    }\n}\n"
  },
  {
    "path": "src/Admin.php",
    "content": "<?php\n\nnamespace Encore\\Admin;\n\nuse Closure;\nuse Encore\\Admin\\Auth\\Database\\Menu;\nuse Encore\\Admin\\Controllers\\AuthController;\nuse Encore\\Admin\\Layout\\Content;\nuse Encore\\Admin\\Traits\\HasAssets;\nuse Encore\\Admin\\Widgets\\Navbar;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Facades\\Auth;\nuse InvalidArgumentException;\n\n/**\n * Class Admin.\n */\nclass Admin\n{\n    use HasAssets;\n\n    /**\n     * The Laravel admin version.\n     *\n     * @var string\n     */\n    const VERSION = '1.8.17';\n\n    /**\n     * @var Navbar\n     */\n    protected $navbar;\n\n    /**\n     * @var array\n     */\n    protected $menu = [];\n\n    /**\n     * @var string\n     */\n    public static $metaTitle;\n\n    /**\n     * @var string\n     */\n    public static $favicon;\n\n    /**\n     * @var array\n     */\n    public static $extensions = [];\n\n    /**\n     * @var []Closure\n     */\n    protected static $bootingCallbacks = [];\n\n    /**\n     * @var []Closure\n     */\n    protected static $bootedCallbacks = [];\n\n    /**\n     * Returns the long version of Laravel-admin.\n     *\n     * @return string The long application version\n     */\n    public static function getLongVersion()\n    {\n        return sprintf('Laravel-admin <comment>version</comment> <info>%s</info>', self::VERSION);\n    }\n\n    /**\n     * @param $model\n     * @param Closure $callable\n     *\n     * @return \\Encore\\Admin\\Grid\n     *\n     * @deprecated since v1.6.1\n     */\n    public function grid($model, Closure $callable)\n    {\n        return new Grid($this->getModel($model), $callable);\n    }\n\n    /**\n     * @param $model\n     * @param Closure $callable\n     *\n     * @return \\Encore\\Admin\\Form\n     *\n     *  @deprecated since v1.6.1\n     */\n    public function form($model, Closure $callable)\n    {\n        return new Form($this->getModel($model), $callable);\n    }\n\n    /**\n     * Build a tree.\n     *\n     * @param $model\n     * @param Closure|null $callable\n     *\n     * @return \\Encore\\Admin\\Tree\n     */\n    public function tree($model, Closure $callable = null)\n    {\n        return new Tree($this->getModel($model), $callable);\n    }\n\n    /**\n     * Build show page.\n     *\n     * @param $model\n     * @param mixed $callable\n     *\n     * @return Show\n     *\n     * @deprecated since v1.6.1\n     */\n    public function show($model, $callable = null)\n    {\n        return new Show($this->getModel($model), $callable);\n    }\n\n    /**\n     * @param Closure $callable\n     *\n     * @return \\Encore\\Admin\\Layout\\Content\n     *\n     * @deprecated since v1.6.1\n     */\n    public function content(Closure $callable = null)\n    {\n        return new Content($callable);\n    }\n\n    /**\n     * @param $model\n     *\n     * @return mixed\n     */\n    public function getModel($model)\n    {\n        if ($model instanceof Model) {\n            return $model;\n        }\n\n        if (is_string($model) && class_exists($model)) {\n            return $this->getModel(new $model());\n        }\n\n        throw new InvalidArgumentException(\"$model is not a valid model\");\n    }\n\n    /**\n     * Left sider-bar menu.\n     *\n     * @return array\n     */\n    public function menu()\n    {\n        if (!empty($this->menu)) {\n            return $this->menu;\n        }\n\n        $menuClass = config('admin.database.menu_model');\n\n        /** @var Menu $menuModel */\n        $menuModel = new $menuClass();\n\n        return $this->menu = $menuModel->toTree();\n    }\n\n    /**\n     * @param array $menu\n     *\n     * @return array\n     */\n    public function menuLinks($menu = [])\n    {\n        if (empty($menu)) {\n            $menu = $this->menu();\n        }\n\n        $links = [];\n\n        foreach ($menu as $item) {\n            if (!empty($item['children'])) {\n                $links = array_merge($links, $this->menuLinks($item['children']));\n            } else {\n                $links[] = Arr::only($item, ['title', 'uri', 'icon']);\n            }\n        }\n\n        return $links;\n    }\n\n    /**\n     * Set admin title.\n     *\n     * @param string $title\n     *\n     * @return void\n     */\n    public static function setTitle($title)\n    {\n        self::$metaTitle = $title;\n    }\n\n    /**\n     * Get admin title.\n     *\n     * @return string\n     */\n    public function title()\n    {\n        return self::$metaTitle ? self::$metaTitle : config('admin.title');\n    }\n\n    /**\n     * @param null|string $favicon\n     *\n     * @return string|void\n     */\n    public static function favicon($favicon = null)\n    {\n        if (is_null($favicon)) {\n            return static::$favicon;\n        }\n\n        static::$favicon = $favicon;\n    }\n\n    /**\n     * Get the currently authenticated user.\n     *\n     * @return \\Illuminate\\Contracts\\Auth\\Authenticatable|null\n     */\n    public function user()\n    {\n        return $this->guard()->user();\n    }\n\n    /**\n     * Attempt to get the guard from the local cache.\n     *\n     * @return \\Illuminate\\Contracts\\Auth\\Guard|\\Illuminate\\Contracts\\Auth\\StatefulGuard\n     */\n    public function guard()\n    {\n        $guard = config('admin.auth.guard') ?: 'admin';\n\n        return Auth::guard($guard);\n    }\n\n    /**\n     * Set navbar.\n     *\n     * @param Closure|null $builder\n     *\n     * @return Navbar\n     */\n    public function navbar(Closure $builder = null)\n    {\n        if (is_null($builder)) {\n            return $this->getNavbar();\n        }\n\n        call_user_func($builder, $this->getNavbar());\n    }\n\n    /**\n     * Get navbar object.\n     *\n     * @return \\Encore\\Admin\\Widgets\\Navbar\n     */\n    public function getNavbar()\n    {\n        if (is_null($this->navbar)) {\n            $this->navbar = new Navbar();\n        }\n\n        return $this->navbar;\n    }\n\n    /**\n     * Register the laravel-admin builtin routes.\n     *\n     * @return void\n     *\n     * @deprecated Use Admin::routes() instead();\n     */\n    public function registerAuthRoutes()\n    {\n        $this->routes();\n    }\n\n    /**\n     * Register the laravel-admin builtin routes.\n     *\n     * @return void\n     */\n    public function routes()\n    {\n        $attributes = [\n            'prefix'     => config('admin.route.prefix'),\n            'middleware' => config('admin.route.middleware'),\n        ];\n\n        app('router')->group($attributes, function ($router) {\n\n            /* @var \\Illuminate\\Support\\Facades\\Route $router */\n            $router->namespace('\\Encore\\Admin\\Controllers')->group(function ($router) {\n\n                /* @var \\Illuminate\\Routing\\Router $router */\n                $router->resource('auth/users', 'UserController')->names('admin.auth.users');\n                $router->resource('auth/roles', 'RoleController')->names('admin.auth.roles');\n                $router->resource('auth/permissions', 'PermissionController')->names('admin.auth.permissions');\n                $router->resource('auth/menu', 'MenuController', ['except' => ['create']])->names('admin.auth.menu');\n                $router->resource('auth/logs', 'LogController', ['only' => ['index', 'destroy']])->names('admin.auth.logs');\n\n                $router->post('_handle_form_', 'HandleController@handleForm')->name('admin.handle-form');\n                $router->post('_handle_action_', 'HandleController@handleAction')->name('admin.handle-action');\n                $router->get('_handle_selectable_', 'HandleController@handleSelectable')->name('admin.handle-selectable');\n                $router->get('_handle_renderable_', 'HandleController@handleRenderable')->name('admin.handle-renderable');\n            });\n\n            $authController = config('admin.auth.controller', AuthController::class);\n\n            /* @var \\Illuminate\\Routing\\Router $router */\n            $router->get('auth/login', $authController.'@getLogin')->name('admin.login');\n            $router->post('auth/login', $authController.'@postLogin');\n            $router->get('auth/logout', $authController.'@getLogout')->name('admin.logout');\n            $router->get('auth/setting', $authController.'@getSetting')->name('admin.setting');\n            $router->put('auth/setting', $authController.'@putSetting');\n        });\n    }\n\n    /**\n     * Extend a extension.\n     *\n     * @param string $name\n     * @param string $class\n     *\n     * @return void\n     */\n    public static function extend($name, $class)\n    {\n        static::$extensions[$name] = $class;\n    }\n\n    /**\n     * @param callable $callback\n     */\n    public static function booting(callable $callback)\n    {\n        static::$bootingCallbacks[] = $callback;\n    }\n\n    /**\n     * @param callable $callback\n     */\n    public static function booted(callable $callback)\n    {\n        static::$bootedCallbacks[] = $callback;\n    }\n\n    /**\n     * Bootstrap the admin application.\n     */\n    public function bootstrap()\n    {\n        $this->fireBootingCallbacks();\n\n        require config('admin.bootstrap', admin_path('bootstrap.php'));\n\n        $this->addAdminAssets();\n\n        $this->fireBootedCallbacks();\n    }\n\n    /**\n     * Add JS & CSS assets to pages.\n     */\n    protected function addAdminAssets()\n    {\n        $assets = Form::collectFieldAssets();\n\n        self::css($assets['css']);\n        self::js($assets['js']);\n    }\n\n    /**\n     * Call the booting callbacks for the admin application.\n     */\n    protected function fireBootingCallbacks()\n    {\n        foreach (static::$bootingCallbacks as $callable) {\n            call_user_func($callable);\n        }\n    }\n\n    /**\n     * Call the booted callbacks for the admin application.\n     */\n    protected function fireBootedCallbacks()\n    {\n        foreach (static::$bootedCallbacks as $callable) {\n            call_user_func($callable);\n        }\n    }\n\n    /*\n     * Disable Pjax for current Request\n     *\n     * @return void\n     */\n    public function disablePjax()\n    {\n        if (request()->pjax()) {\n            request()->headers->set('X-PJAX', false);\n        }\n    }\n}\n"
  },
  {
    "path": "src/AdminServiceProvider.php",
    "content": "<?php\n\nnamespace Encore\\Admin;\n\nuse Encore\\Admin\\Layout\\Content;\nuse Illuminate\\Routing\\Router;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Facades\\Blade;\nuse Illuminate\\Support\\ServiceProvider;\nuse Illuminate\\Support\\Str;\n\nclass AdminServiceProvider extends ServiceProvider\n{\n    /**\n     * @var array\n     */\n    protected $commands = [\n        Console\\AdminCommand::class,\n        Console\\MakeCommand::class,\n        Console\\ControllerCommand::class,\n        Console\\MenuCommand::class,\n        Console\\InstallCommand::class,\n        Console\\PublishCommand::class,\n        Console\\UninstallCommand::class,\n        Console\\ImportCommand::class,\n        Console\\CreateUserCommand::class,\n        Console\\ResetPasswordCommand::class,\n        Console\\ExtendCommand::class,\n        Console\\ExportSeedCommand::class,\n        Console\\MinifyCommand::class,\n        Console\\FormCommand::class,\n        Console\\PermissionCommand::class,\n        Console\\ActionCommand::class,\n        Console\\GenerateMenuCommand::class,\n        Console\\ConfigCommand::class,\n    ];\n\n    /**\n     * The application's route middleware.\n     *\n     * @var array\n     */\n    protected $routeMiddleware = [\n        'admin.auth'       => Middleware\\Authenticate::class,\n        'admin.pjax'       => Middleware\\Pjax::class,\n        'admin.log'        => Middleware\\LogOperation::class,\n        'admin.permission' => Middleware\\Permission::class,\n        'admin.bootstrap'  => Middleware\\Bootstrap::class,\n        'admin.session'    => Middleware\\Session::class,\n    ];\n\n    /**\n     * The application's route middleware groups.\n     *\n     * @var array\n     */\n    protected $middlewareGroups = [\n        'admin' => [\n            'admin.auth',\n            'admin.pjax',\n            'admin.log',\n            'admin.bootstrap',\n            'admin.permission',\n            //            'admin.session',\n        ],\n    ];\n\n    /**\n     * Boot the service provider.\n     *\n     * @return void\n     */\n    public function boot()\n    {\n        $this->loadViewsFrom(__DIR__.'/../resources/views', 'admin');\n\n        $this->ensureHttps();\n\n        if (file_exists($routes = admin_path('routes.php'))) {\n            $this->loadRoutesFrom($routes);\n        }\n\n        $this->registerPublishing();\n\n        $this->compatibleBlade();\n\n        Blade::directive('box', function ($title) {\n            return \"<?php \\$box = new \\Encore\\Admin\\Widgets\\Box({$title}, '\";\n        });\n\n        Blade::directive('endbox', function ($expression) {\n            return \"'); echo \\$box->render(); ?>\";\n        });\n    }\n\n    /**\n     * Force to set https scheme if https enabled.\n     *\n     * @return void\n     */\n    protected function ensureHttps()\n    {\n        $is_admin = Str::startsWith(request()->getRequestUri(), '/'.ltrim(config('admin.route.prefix'), '/'));\n        if ((config('admin.https') || config('admin.secure')) && $is_admin) {\n            url()->forceScheme('https');\n            $this->app['request']->server->set('HTTPS', true);\n        }\n    }\n\n    /**\n     * Register the package's publishable resources.\n     *\n     * @return void\n     */\n    protected function registerPublishing()\n    {\n        if ($this->app->runningInConsole()) {\n            $this->publishes([__DIR__.'/../config' => config_path()], 'laravel-admin-config');\n            if (version_compare($this->app->version(), '9.0.0', '>=')) {\n                $this->publishes([__DIR__.'/../resources/lang' => base_path('lang')], 'laravel-admin-lang');\n            } else {\n                $this->publishes([__DIR__.'/../resources/lang' => resource_path('lang')], 'laravel-admin-lang');\n            }\n            $this->publishes([__DIR__.'/../database/migrations' => database_path('migrations')], 'laravel-admin-migrations');\n            $this->publishes([__DIR__.'/../resources/assets' => public_path('vendor/laravel-admin')], 'laravel-admin-assets');\n        }\n    }\n\n    /**\n     * Remove default feature of double encoding enable in laravel 5.6 or later.\n     *\n     * @return void\n     */\n    protected function compatibleBlade()\n    {\n        $reflectionClass = new \\ReflectionClass('\\Illuminate\\View\\Compilers\\BladeCompiler');\n\n        if ($reflectionClass->hasMethod('withoutDoubleEncoding')) {\n            Blade::withoutDoubleEncoding();\n        }\n    }\n\n    /**\n     * Extends laravel router.\n     */\n    protected function macroRouter()\n    {\n        Router::macro('content', function ($uri, $content, $options = []) {\n            return $this->match(['GET', 'HEAD'], $uri, function (Content $layout) use ($content, $options) {\n                return $layout\n                    ->title(Arr::get($options, 'title', ' '))\n                    ->description(Arr::get($options, 'desc', ' '))\n                    ->body($content);\n            });\n        });\n\n        Router::macro('component', function ($uri, $component, $data = [], $options = []) {\n            return $this->match(['GET', 'HEAD'], $uri, function (Content $layout) use ($component, $data, $options) {\n                return $layout\n                    ->title(Arr::get($options, 'title', ' '))\n                    ->description(Arr::get($options, 'desc', ' '))\n                    ->component($component, $data);\n            });\n        });\n    }\n\n    /**\n     * Register the service provider.\n     *\n     * @return void\n     */\n    public function register()\n    {\n        $this->loadAdminAuthConfig();\n\n        $this->registerRouteMiddleware();\n\n        $this->commands($this->commands);\n\n        $this->macroRouter();\n    }\n\n    /**\n     * Setup auth configuration.\n     *\n     * @return void\n     */\n    protected function loadAdminAuthConfig()\n    {\n        config(Arr::dot(config('admin.auth', []), 'auth.'));\n    }\n\n    /**\n     * Register the route middleware.\n     *\n     * @return void\n     */\n    protected function registerRouteMiddleware()\n    {\n        // register route middleware.\n        foreach ($this->routeMiddleware as $key => $middleware) {\n            app('router')->aliasMiddleware($key, $middleware);\n        }\n\n        // register middleware group.\n        foreach ($this->middlewareGroups as $key => $middleware) {\n            app('router')->middlewareGroup($key, $middleware);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Auth/Database/AdminTablesSeeder.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Auth\\Database;\n\nuse Illuminate\\Database\\Seeder;\nuse Illuminate\\Support\\Facades\\Hash;\n\nclass AdminTablesSeeder extends Seeder\n{\n    /**\n     * Run the database seeds.\n     *\n     * @return void\n     */\n    public function run()\n    {\n        // create a user.\n        Administrator::truncate();\n        Administrator::create([\n            'username' => 'admin',\n            'password' => Hash::make('admin'),\n            'name'     => 'Administrator',\n        ]);\n\n        // create a role.\n        Role::truncate();\n        Role::create([\n            'name' => 'Administrator',\n            'slug' => 'administrator',\n        ]);\n\n        // add role to user.\n        Administrator::first()->roles()->save(Role::first());\n\n        //create a permission\n        Permission::truncate();\n        Permission::insert([\n            [\n                'name'        => 'All permission',\n                'slug'        => '*',\n                'http_method' => '',\n                'http_path'   => '*',\n            ],\n            [\n                'name'        => 'Dashboard',\n                'slug'        => 'dashboard',\n                'http_method' => 'GET',\n                'http_path'   => '/',\n            ],\n            [\n                'name'        => 'Login',\n                'slug'        => 'auth.login',\n                'http_method' => '',\n                'http_path'   => \"/auth/login\\r\\n/auth/logout\",\n            ],\n            [\n                'name'        => 'User setting',\n                'slug'        => 'auth.setting',\n                'http_method' => 'GET,PUT',\n                'http_path'   => '/auth/setting',\n            ],\n            [\n                'name'        => 'Auth management',\n                'slug'        => 'auth.management',\n                'http_method' => '',\n                'http_path'   => \"/auth/roles\\r\\n/auth/permissions\\r\\n/auth/menu\\r\\n/auth/logs\",\n            ],\n        ]);\n\n        Role::first()->permissions()->save(Permission::first());\n\n        // add default menus.\n        Menu::truncate();\n        Menu::insert([\n            [\n                'parent_id' => 0,\n                'order'     => 1,\n                'title'     => 'Dashboard',\n                'icon'      => 'fa-bar-chart',\n                'uri'       => '/',\n            ],\n            [\n                'parent_id' => 0,\n                'order'     => 2,\n                'title'     => 'Admin',\n                'icon'      => 'fa-tasks',\n                'uri'       => '',\n            ],\n            [\n                'parent_id' => 2,\n                'order'     => 3,\n                'title'     => 'Users',\n                'icon'      => 'fa-users',\n                'uri'       => 'auth/users',\n            ],\n            [\n                'parent_id' => 2,\n                'order'     => 4,\n                'title'     => 'Roles',\n                'icon'      => 'fa-user',\n                'uri'       => 'auth/roles',\n            ],\n            [\n                'parent_id' => 2,\n                'order'     => 5,\n                'title'     => 'Permission',\n                'icon'      => 'fa-ban',\n                'uri'       => 'auth/permissions',\n            ],\n            [\n                'parent_id' => 2,\n                'order'     => 6,\n                'title'     => 'Menu',\n                'icon'      => 'fa-bars',\n                'uri'       => 'auth/menu',\n            ],\n            [\n                'parent_id' => 2,\n                'order'     => 7,\n                'title'     => 'Operation log',\n                'icon'      => 'fa-history',\n                'uri'       => 'auth/logs',\n            ],\n        ]);\n\n        // add role to menu.\n        Menu::find(2)->roles()->save(Role::first());\n    }\n}\n"
  },
  {
    "path": "src/Auth/Database/Administrator.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Auth\\Database;\n\nuse Encore\\Admin\\Traits\\DefaultDatetimeFormat;\nuse Illuminate\\Auth\\Authenticatable;\nuse Illuminate\\Contracts\\Auth\\Authenticatable as AuthenticatableContract;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsToMany;\nuse Illuminate\\Support\\Facades\\Storage;\n\n/**\n * Class Administrator.\n *\n * @property Role[] $roles\n */\nclass Administrator extends Model implements AuthenticatableContract\n{\n    use Authenticatable;\n    use HasPermissions;\n    use DefaultDatetimeFormat;\n\n    protected $fillable = ['username', 'password', 'name', 'avatar'];\n\n    /**\n     * Create a new Eloquent model instance.\n     *\n     * @param array $attributes\n     */\n    public function __construct(array $attributes = [])\n    {\n        $connection = config('admin.database.connection') ?: config('database.default');\n\n        $this->setConnection($connection);\n\n        $this->setTable(config('admin.database.users_table'));\n\n        parent::__construct($attributes);\n    }\n\n    /**\n     * Get avatar attribute.\n     *\n     * @param string $avatar\n     *\n     * @return string\n     */\n    public function getAvatarAttribute($avatar)\n    {\n        if ($avatar && url()->isValidUrl($avatar)) {\n            return $avatar;\n        }\n\n        $disk = config('admin.upload.disk');\n\n        if ($avatar && array_key_exists($disk, config('filesystems.disks'))) {\n            return Storage::disk(config('admin.upload.disk'))->url($avatar);\n        }\n\n        $default = config('admin.default_avatar') ?: '/vendor/laravel-admin/AdminLTE/dist/img/user2-160x160.jpg';\n\n        return admin_asset($default);\n    }\n\n    /**\n     * A user has and belongs to many roles.\n     *\n     * @return BelongsToMany\n     */\n    public function roles(): BelongsToMany\n    {\n        $pivotTable = config('admin.database.role_users_table');\n\n        $relatedModel = config('admin.database.roles_model');\n\n        return $this->belongsToMany($relatedModel, $pivotTable, 'user_id', 'role_id');\n    }\n\n    /**\n     * A User has and belongs to many permissions.\n     *\n     * @return BelongsToMany\n     */\n    public function permissions(): BelongsToMany\n    {\n        $pivotTable = config('admin.database.user_permissions_table');\n\n        $relatedModel = config('admin.database.permissions_model');\n\n        return $this->belongsToMany($relatedModel, $pivotTable, 'user_id', 'permission_id');\n    }\n}\n"
  },
  {
    "path": "src/Auth/Database/HasPermissions.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Auth\\Database;\n\nuse Illuminate\\Support\\Collection;\n\ntrait HasPermissions\n{\n    /**\n     * Get all permissions of user.\n     *\n     * @return mixed\n     */\n    public function allPermissions(): Collection\n    {\n        return $this->roles()->with('permissions')->get()->pluck('permissions')->flatten()->merge($this->permissions);\n    }\n\n    /**\n     * Check if user has permission.\n     *\n     * @param $ability\n     * @param array $arguments\n     *\n     * @return bool\n     */\n    public function can($ability, $arguments = []): bool\n    {\n        if (empty($ability)) {\n            return true;\n        }\n\n        if ($this->isAdministrator()) {\n            return true;\n        }\n\n        if ($this->permissions->pluck('slug')->contains($ability)) {\n            return true;\n        }\n\n        return $this->roles->pluck('permissions')->flatten()->pluck('slug')->contains($ability);\n    }\n\n    /**\n     * Check if user has no permission.\n     *\n     * @param $permission\n     *\n     * @return bool\n     */\n    public function cannot(string $permission): bool\n    {\n        return !$this->can($permission);\n    }\n\n    /**\n     * Check if user is administrator.\n     *\n     * @return mixed\n     */\n    public function isAdministrator(): bool\n    {\n        return $this->isRole('administrator');\n    }\n\n    /**\n     * Check if user is $role.\n     *\n     * @param string $role\n     *\n     * @return mixed\n     */\n    public function isRole(string $role): bool\n    {\n        return $this->roles->pluck('slug')->contains($role);\n    }\n\n    /**\n     * Check if user in $roles.\n     *\n     * @param array $roles\n     *\n     * @return mixed\n     */\n    public function inRoles(array $roles = []): bool\n    {\n        return $this->roles->pluck('slug')->intersect($roles)->isNotEmpty();\n    }\n\n    /**\n     * If visible for roles.\n     *\n     * @param $roles\n     *\n     * @return bool\n     */\n    public function visible(array $roles = []): bool\n    {\n        if (empty($roles)) {\n            return true;\n        }\n\n        $roles = array_column($roles, 'slug');\n\n        return $this->inRoles($roles) || $this->isAdministrator();\n    }\n\n    /**\n     * Detach models from the relationship.\n     *\n     * @return void\n     */\n    protected static function bootHasPermissions()\n    {\n        static::deleting(function ($model) {\n            $model->roles()->detach();\n\n            $model->permissions()->detach();\n        });\n    }\n}\n"
  },
  {
    "path": "src/Auth/Database/Menu.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Auth\\Database;\n\nuse Encore\\Admin\\Traits\\DefaultDatetimeFormat;\nuse Encore\\Admin\\Traits\\ModelTree;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsToMany;\nuse Illuminate\\Support\\Facades\\DB;\n\n/**\n * Class Menu.\n *\n * @property int $id\n *\n * @method where($parent_id, $id)\n */\nclass Menu extends Model\n{\n    use DefaultDatetimeFormat;\n    use ModelTree {\n        ModelTree::boot as treeBoot;\n    }\n\n    /**\n     * The attributes that are mass assignable.\n     *\n     * @var array\n     */\n    protected $fillable = ['parent_id', 'order', 'title', 'icon', 'uri', 'permission'];\n\n    /**\n     * Create a new Eloquent model instance.\n     *\n     * @param array $attributes\n     */\n    public function __construct(array $attributes = [])\n    {\n        $connection = config('admin.database.connection') ?: config('database.default');\n\n        $this->setConnection($connection);\n\n        $this->setTable(config('admin.database.menu_table'));\n\n        parent::__construct($attributes);\n    }\n\n    /**\n     * A Menu belongs to many roles.\n     *\n     * @return BelongsToMany\n     */\n    public function roles(): BelongsToMany\n    {\n        $pivotTable = config('admin.database.role_menu_table');\n\n        $relatedModel = config('admin.database.roles_model');\n\n        return $this->belongsToMany($relatedModel, $pivotTable, 'menu_id', 'role_id');\n    }\n\n    /**\n     * @return array\n     */\n    public function allNodes(): array\n    {\n        $connection = config('admin.database.connection') ?: config('database.default');\n        $orderColumn = DB::connection($connection)->getQueryGrammar()->wrap($this->orderColumn);\n\n        $byOrder = 'ROOT ASC,'.$orderColumn;\n\n        $query = static::query();\n\n        if (config('admin.check_menu_roles') !== false) {\n            $query->with('roles');\n        }\n\n        return $query->selectRaw('*, '.$orderColumn.' ROOT')->orderByRaw($byOrder)->get()->toArray();\n    }\n\n    /**\n     * determine if enable menu bind permission.\n     *\n     * @return bool\n     */\n    public function withPermission()\n    {\n        return (bool) config('admin.menu_bind_permission');\n    }\n\n    /**\n     * Detach models from the relationship.\n     *\n     * @return void\n     */\n    protected static function boot()\n    {\n        static::treeBoot();\n\n        static::deleting(function ($model) {\n            $model->roles()->detach();\n        });\n    }\n}\n"
  },
  {
    "path": "src/Auth/Database/OperationLog.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Auth\\Database;\n\nuse Encore\\Admin\\Traits\\DefaultDatetimeFormat;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsTo;\n\nclass OperationLog extends Model\n{\n    use DefaultDatetimeFormat;\n\n    protected $fillable = ['user_id', 'path', 'method', 'ip', 'input'];\n\n    public static $methodColors = [\n        'GET'    => 'green',\n        'POST'   => 'yellow',\n        'PUT'    => 'blue',\n        'DELETE' => 'red',\n    ];\n\n    public static $methods = [\n        'GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'PATCH',\n        'LINK', 'UNLINK', 'COPY', 'HEAD', 'PURGE',\n    ];\n\n    /**\n     * Create a new Eloquent model instance.\n     *\n     * @param array $attributes\n     */\n    public function __construct(array $attributes = [])\n    {\n        $connection = config('admin.database.connection') ?: config('database.default');\n\n        $this->setConnection($connection);\n\n        $this->setTable(config('admin.database.operation_log_table'));\n\n        parent::__construct($attributes);\n    }\n\n    /**\n     * Log belongs to users.\n     *\n     * @return BelongsTo\n     */\n    public function user(): BelongsTo\n    {\n        return $this->belongsTo(config('admin.database.users_model'));\n    }\n}\n"
  },
  {
    "path": "src/Auth/Database/Permission.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Auth\\Database;\n\nuse Encore\\Admin\\Traits\\DefaultDatetimeFormat;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsToMany;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Str;\n\nclass Permission extends Model\n{\n    use DefaultDatetimeFormat;\n\n    /**\n     * @var array\n     */\n    protected $fillable = ['name', 'slug', 'http_method', 'http_path'];\n\n    /**\n     * @var array\n     */\n    public static $httpMethods = [\n        'GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS', 'HEAD',\n    ];\n\n    /**\n     * Create a new Eloquent model instance.\n     *\n     * @param array $attributes\n     */\n    public function __construct(array $attributes = [])\n    {\n        $connection = config('admin.database.connection') ?: config('database.default');\n\n        $this->setConnection($connection);\n\n        $this->setTable(config('admin.database.permissions_table'));\n\n        parent::__construct($attributes);\n    }\n\n    /**\n     * Permission belongs to many roles.\n     *\n     * @return BelongsToMany\n     */\n    public function roles(): BelongsToMany\n    {\n        $pivotTable = config('admin.database.role_permissions_table');\n\n        $relatedModel = config('admin.database.roles_model');\n\n        return $this->belongsToMany($relatedModel, $pivotTable, 'permission_id', 'role_id');\n    }\n\n    /**\n     * If request should pass through the current permission.\n     *\n     * @param Request $request\n     *\n     * @return bool\n     */\n    public function shouldPassThrough(Request $request): bool\n    {\n        if (empty($this->http_method) && empty($this->http_path)) {\n            return true;\n        }\n\n        $method = $this->http_method;\n\n        $matches = array_map(function ($path) use ($method) {\n            $path = trim(config('admin.route.prefix'), '/').$path;\n\n            if (Str::contains($path, ':')) {\n                list($method, $path) = explode(':', $path);\n                $method = explode(',', $method);\n            }\n\n            return compact('method', 'path');\n        }, explode(\"\\n\", $this->http_path));\n\n        foreach ($matches as $match) {\n            if ($this->matchRequest($match, $request)) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * filter \\r.\n     *\n     * @param string $path\n     *\n     * @return mixed\n     */\n    public function getHttpPathAttribute($path)\n    {\n        return str_replace(\"\\r\\n\", \"\\n\", $path);\n    }\n\n    /**\n     * If a request match the specific HTTP method and path.\n     *\n     * @param array   $match\n     * @param Request $request\n     *\n     * @return bool\n     */\n    protected function matchRequest(array $match, Request $request): bool\n    {\n        if ($match['path'] == '/') {\n            $path = '/';\n        } else {\n            $path = trim($match['path'], '/');\n        }\n\n        if (!$request->is($path)) {\n            return false;\n        }\n\n        $method = collect($match['method'])->filter()->map(function ($method) {\n            return strtoupper($method);\n        });\n\n        return $method->isEmpty() || $method->contains($request->method());\n    }\n\n    /**\n     * @param $method\n     */\n    public function setHttpMethodAttribute($method)\n    {\n        if (is_array($method)) {\n            $this->attributes['http_method'] = implode(',', $method);\n        }\n    }\n\n    /**\n     * @param $method\n     *\n     * @return array\n     */\n    public function getHttpMethodAttribute($method)\n    {\n        if (is_string($method)) {\n            return array_filter(explode(',', $method));\n        }\n\n        return $method;\n    }\n\n    /**\n     * Detach models from the relationship.\n     *\n     * @return void\n     */\n    protected static function boot()\n    {\n        parent::boot();\n\n        static::deleting(function ($model) {\n            $model->roles()->detach();\n        });\n    }\n}\n"
  },
  {
    "path": "src/Auth/Database/Role.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Auth\\Database;\n\nuse Encore\\Admin\\Traits\\DefaultDatetimeFormat;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsToMany;\n\nclass Role extends Model\n{\n    use DefaultDatetimeFormat;\n\n    protected $fillable = ['name', 'slug'];\n\n    /**\n     * Create a new Eloquent model instance.\n     *\n     * @param array $attributes\n     */\n    public function __construct(array $attributes = [])\n    {\n        $connection = config('admin.database.connection') ?: config('database.default');\n\n        $this->setConnection($connection);\n\n        $this->setTable(config('admin.database.roles_table'));\n\n        parent::__construct($attributes);\n    }\n\n    /**\n     * A role belongs to many users.\n     *\n     * @return BelongsToMany\n     */\n    public function administrators(): BelongsToMany\n    {\n        $pivotTable = config('admin.database.role_users_table');\n\n        $relatedModel = config('admin.database.users_model');\n\n        return $this->belongsToMany($relatedModel, $pivotTable, 'role_id', 'user_id');\n    }\n\n    /**\n     * A role belongs to many permissions.\n     *\n     * @return BelongsToMany\n     */\n    public function permissions(): BelongsToMany\n    {\n        $pivotTable = config('admin.database.role_permissions_table');\n\n        $relatedModel = config('admin.database.permissions_model');\n\n        return $this->belongsToMany($relatedModel, $pivotTable, 'role_id', 'permission_id');\n    }\n\n    /**\n     * A role belongs to many menus.\n     *\n     * @return BelongsToMany\n     */\n    public function menus(): BelongsToMany\n    {\n        $pivotTable = config('admin.database.role_menu_table');\n\n        $relatedModel = config('admin.database.menu_model');\n\n        return $this->belongsToMany($relatedModel, $pivotTable, 'role_id', 'menu_id');\n    }\n\n    /**\n     * Check user has permission.\n     *\n     * @param $permission\n     *\n     * @return bool\n     */\n    public function can(string $permission): bool\n    {\n        return $this->permissions()->where('slug', $permission)->exists();\n    }\n\n    /**\n     * Check user has no permission.\n     *\n     * @param $permission\n     *\n     * @return bool\n     */\n    public function cannot(string $permission): bool\n    {\n        return !$this->can($permission);\n    }\n\n    /**\n     * Detach models from the relationship.\n     *\n     * @return void\n     */\n    protected static function boot()\n    {\n        parent::boot();\n\n        static::deleting(function ($model) {\n            $model->administrators()->detach();\n\n            $model->permissions()->detach();\n        });\n    }\n}\n"
  },
  {
    "path": "src/Auth/Permission.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Auth;\n\nuse Encore\\Admin\\Facades\\Admin;\nuse Encore\\Admin\\Middleware\\Pjax;\n\nclass Permission\n{\n    /**\n     * Check permission.\n     *\n     * @param $permission\n     *\n     * @return true\n     */\n    public static function check($permission)\n    {\n        if (static::isAdministrator()) {\n            return true;\n        }\n\n        if (is_array($permission)) {\n            collect($permission)->each(function ($permission) {\n                call_user_func([self::class, 'check'], $permission);\n            });\n\n            return;\n        }\n\n        if (Admin::user()->cannot($permission)) {\n            static::error();\n        }\n    }\n\n    /**\n     * Roles allowed to access.\n     *\n     * @param $roles\n     *\n     * @return true\n     */\n    public static function allow($roles)\n    {\n        if (static::isAdministrator()) {\n            return true;\n        }\n\n        if (!Admin::user()->inRoles($roles)) {\n            static::error();\n        }\n    }\n\n    /**\n     * Don't check permission.\n     *\n     * @return bool\n     */\n    public static function free()\n    {\n        return true;\n    }\n\n    /**\n     * Roles denied to access.\n     *\n     * @param $roles\n     *\n     * @return true\n     */\n    public static function deny($roles)\n    {\n        if (static::isAdministrator()) {\n            return true;\n        }\n\n        if (Admin::user()->inRoles($roles)) {\n            static::error();\n        }\n    }\n\n    /**\n     * Send error response page.\n     */\n    public static function error()\n    {\n        $response = response(Admin::content()->withError(trans('admin.deny')));\n\n        if (!request()->pjax() && request()->ajax()) {\n            abort(403, trans('admin.deny'));\n        }\n\n        Pjax::respond($response);\n    }\n\n    /**\n     * If current user is administrator.\n     *\n     * @return mixed\n     */\n    public static function isAdministrator()\n    {\n        return Admin::user()->isRole('administrator');\n    }\n}\n"
  },
  {
    "path": "src/Console/ActionCommand.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Console;\n\nuse Illuminate\\Console\\GeneratorCommand;\nuse Illuminate\\Support\\Str;\n\nclass ActionCommand extends GeneratorCommand\n{\n    /**\n     * The name and signature of the console command.\n     *\n     * @var string\n     */\n    protected $signature = 'admin:action {name}\n        {--grid-batch}\n        {--grid-row}\n        {--form}\n        {--dialog}\n        {--name=}\n        {--namespace=}';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = 'Make a admin action';\n\n    /**\n     * Replace the class name for the given stub.\n     *\n     * @param string $stub\n     * @param string $name\n     *\n     * @return string\n     */\n    protected function replaceClass($stub, $name)\n    {\n        $stub = parent::replaceClass($stub, $name);\n\n        return str_replace(\n            [\n                'DummyName',\n                'DummySelector',\n                'DummyInteractor',\n            ],\n            [\n                $this->option('name'),\n                Str::kebab(class_basename($this->argument('name'))),\n                $this->generateInteractor(),\n            ],\n            $stub\n        );\n    }\n\n    protected function generateInteractor()\n    {\n        if ($this->option('form')) {\n            return <<<'CODE'\n\n    public function form()\n    {\n        $this->text('name')->rules('required');\n        $this->email('email')->rules('email');\n        $this->datetime('created_at');\n    }\n\nCODE;\n        } elseif ($this->option('dialog')) {\n            return <<<'CODE'\n\n    public function dialog()\n    {\n        $this->confirm('Confirm message...');\n    }\n\nCODE;\n        }\n\n        return '';\n    }\n\n    /**\n     * Get the stub file for the generator.\n     *\n     * @return string\n     */\n    public function getStub()\n    {\n        if ($this->option('grid-batch')) {\n            return __DIR__.'/stubs/grid-batch-action.stub';\n        }\n\n        if ($this->option('grid-row')) {\n            return __DIR__.'/stubs/grid-row-action.stub';\n        }\n\n        return __DIR__.'/stubs/action.stub';\n    }\n\n    /**\n     * Get the default namespace for the class.\n     *\n     * @param string $rootNamespace\n     *\n     * @return string\n     */\n    protected function getDefaultNamespace($rootNamespace)\n    {\n        if ($namespace = $this->option('namespace')) {\n            return $namespace;\n        }\n\n        $segments = explode('\\\\', config('admin.route.namespace'));\n\n        array_pop($segments);\n\n        array_push($segments, 'Actions');\n\n        return implode('\\\\', $segments);\n    }\n\n    /**\n     * Get the desired class name from the input.\n     *\n     * @return string\n     */\n    protected function getNameInput()\n    {\n        $name = trim($this->argument('name'));\n\n        $this->type = $this->qualifyClass($name);\n\n        return $name;\n    }\n}\n"
  },
  {
    "path": "src/Console/AdminCommand.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Console;\n\nuse Encore\\Admin\\Admin;\nuse Illuminate\\Console\\Command;\nuse Illuminate\\Support\\Facades\\Artisan;\nuse Illuminate\\Support\\Str;\n\nclass AdminCommand extends Command\n{\n    /**\n     * The name and signature of the console command.\n     *\n     * @var string\n     */\n    protected $signature = 'admin';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = 'List all admin commands';\n\n    /**\n     * @var string\n     */\n    public static $logo = <<<LOGO\n    __                                __                __          _     \n   / /   ____ __________ __   _____  / /     ____ _____/ /___ ___  (_)___ \n  / /   / __ `/ ___/ __ `/ | / / _ \\/ /_____/ __ `/ __  / __ `__ \\/ / __ \\\n / /___/ /_/ / /  / /_/ /| |/ /  __/ /_____/ /_/ / /_/ / / / / / / / / / /\n/_____/\\__,_/_/   \\__,_/ |___/\\___/_/      \\__,_/\\__,_/_/ /_/ /_/_/_/ /_/ \n                                                                          \nLOGO;\n\n    /**\n     * Execute the console command.\n     */\n    public function handle()\n    {\n        $this->line(static::$logo);\n        $this->line(Admin::getLongVersion());\n\n        $this->comment('');\n        $this->comment('Available commands:');\n\n        $this->listAdminCommands();\n    }\n\n    /**\n     * List all admin commands.\n     *\n     * @return void\n     */\n    protected function listAdminCommands()\n    {\n        $commands = collect(Artisan::all())->mapWithKeys(function ($command, $key) {\n            if (Str::startsWith($key, 'admin:')) {\n                return [$key => $command];\n            }\n\n            return [];\n        })->toArray();\n\n        $width = $this->getColumnWidth($commands);\n\n        /** @var Command $command */\n        foreach ($commands as $command) {\n            $this->line(sprintf(\" %-{$width}s %s\", $command->getName(), $command->getDescription()));\n        }\n    }\n\n    /**\n     * @param (Command|string)[] $commands\n     *\n     * @return int\n     */\n    private function getColumnWidth(array $commands)\n    {\n        $widths = [];\n\n        foreach ($commands as $command) {\n            $widths[] = static::strlen($command->getName());\n            foreach ($command->getAliases() as $alias) {\n                $widths[] = static::strlen($alias);\n            }\n        }\n\n        return $widths ? max($widths) + 2 : 0;\n    }\n\n    /**\n     * Returns the length of a string, using mb_strwidth if it is available.\n     *\n     * @param string $string The string to check its length\n     *\n     * @return int The length of the string\n     */\n    public static function strlen($string)\n    {\n        if (false === $encoding = mb_detect_encoding($string, null, true)) {\n            return strlen($string);\n        }\n\n        return mb_strwidth($string, $encoding);\n    }\n}\n"
  },
  {
    "path": "src/Console/ConfigCommand.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Console;\n\nuse Illuminate\\Console\\Command;\nuse Illuminate\\Support\\Arr;\n\nclass ConfigCommand extends Command\n{\n    /**\n     * The console command name.\n     *\n     * @var string\n     */\n    protected $signature = 'admin:config {path?}';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = 'Compare the difference between the admin config file and the original';\n\n    /**\n     * {@inheritdoc}\n     */\n    public function handle()\n    {\n        $path = $this->argument('path') ?: 'config/admin.php';\n\n        $current = require $path;\n        $original = require __DIR__.'/../../config/admin.php';\n\n        $added = $this->diff($current, $original);\n        $removed = $this->diff($original, $current);\n\n        if ($added->isEmpty() && $removed->isEmpty()) {\n            $this->info('Configuration items have not been modified');\n\n            return;\n        }\n\n        $this->line(\"The admin config file `$path`:\");\n\n        $this->printDiff('Added', $added);\n        $this->printDiff('Removed', $removed, true);\n\n        $this->line('');\n        $this->comment('Please open `vendor/encore/laravel-admin/config/admin.php` to check the difference');\n    }\n\n    protected function diff(array $from, array $to)\n    {\n        return collect(Arr::dot($from))\n            ->keys()\n            ->reject(function ($key) use ($to) {\n                return Arr::has($to, $key);\n            });\n    }\n\n    protected function printDiff($title, $diff, $error = false)\n    {\n        if ($diff->isEmpty()) {\n            return;\n        }\n\n        $this->line('');\n        $this->comment(\"{$title}:\");\n\n        $diff->each(function ($key) use ($error) {\n            if ($error) {\n                $this->error(\"    {$key}\");\n            } else {\n                $this->info(\"    {$key}\");\n            }\n        });\n    }\n}\n"
  },
  {
    "path": "src/Console/ControllerCommand.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Console;\n\nclass ControllerCommand extends MakeCommand\n{\n    /**\n     * The console command name.\n     *\n     * @var string\n     */\n    protected $signature = 'admin:controller {model}\n        {--title=}\n        {--stub= : Path to the custom stub file. }\n        {--namespace=}\n        {--O|output}';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = 'Make admin controller from giving model';\n\n    /**\n     * @return array|string|null\n     */\n    protected function getModelName()\n    {\n        return $this->argument('model');\n    }\n\n    /**\n     * @throws \\ReflectionException\n     *\n     * @return string\n     */\n    protected function getControllerName()\n    {\n        $name = (new \\ReflectionClass($this->modelName))->getShortName();\n\n        return $name.'Controller';\n    }\n}\n"
  },
  {
    "path": "src/Console/CreateUserCommand.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Console;\n\nuse Illuminate\\Console\\Command;\nuse Illuminate\\Support\\Facades\\Hash;\n\nclass CreateUserCommand extends Command\n{\n    /**\n     * The name and signature of the console command.\n     *\n     * @var string\n     */\n    protected $signature = 'admin:create-user';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = 'Create a admin user';\n\n    /**\n     * Execute the console command.\n     */\n    public function handle()\n    {\n        $userModel = config('admin.database.users_model');\n        $roleModel = config('admin.database.roles_model');\n\n        $username = $this->ask('Please enter a username to login');\n\n        $password = Hash::make($this->secret('Please enter a password to login'));\n\n        $name = $this->ask('Please enter a name to display');\n\n        $roles = $roleModel::all();\n\n        /** @var array $selected */\n        $selectedOption = $roles->pluck('name')->toArray();\n\n        if (empty($selectedOption)) {\n            $selected = $this->choice('Please choose a role for the user', $selectedOption, null, null, true);\n\n            $roles = $roles->filter(function ($role) use ($selected) {\n                return in_array($role->name, $selected);\n            });\n        }\n\n        $user = new $userModel(compact('username', 'password', 'name'));\n\n        $user->save();\n\n        if (isset($roles)) {\n            $user->roles()->attach($roles);\n        }\n\n        $this->info(\"User [$name] created successfully.\");\n    }\n}\n"
  },
  {
    "path": "src/Console/ExportSeedCommand.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Console;\n\nuse Illuminate\\Console\\Command;\n\nclass ExportSeedCommand extends Command\n{\n    /**\n     * The console command name.\n     *\n     * @var string\n     */\n    protected $signature = 'admin:export-seed {classname=AdminTablesSeeder}\n                                              {--users : add to seed users tables}\n                                              {--except-fields=id,created_at,updated_at : except fields}';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = 'Export seed a Laravel-admin database tables menu, roles and permissions';\n\n    /**\n     * Execute the console command.\n     *\n     * @return void\n     */\n    public function handle()\n    {\n        $name = $this->argument('classname');\n        $exceptFields = explode(',', $this->option('except-fields'));\n        $exportUsers = $this->option('users');\n\n        $seedFile = $this->laravel->databasePath().'/seeders/'.$name.'.php';\n        $contents = $this->getStub('AdminTablesSeeder');\n\n        $replaces = [\n            'DummyClass' => $name,\n\n            'ClassMenu'       => config('admin.database.menu_model'),\n            'ClassPermission' => config('admin.database.permissions_model'),\n            'ClassRole'       => config('admin.database.roles_model'),\n\n            'TableRoleMenu'        => config('admin.database.role_menu_table'),\n            'TableRolePermissions' => config('admin.database.role_permissions_table'),\n\n            'ArrayMenu'       => $this->getTableDataArrayAsString(config('admin.database.menu_table'), $exceptFields),\n            'ArrayPermission' => $this->getTableDataArrayAsString(config('admin.database.permissions_table'), $exceptFields),\n            'ArrayRole'       => $this->getTableDataArrayAsString(config('admin.database.roles_table'), $exceptFields),\n\n            'ArrayPivotRoleMenu'        => $this->getTableDataArrayAsString(config('admin.database.role_menu_table'), $exceptFields),\n            'ArrayPivotRolePermissions' => $this->getTableDataArrayAsString(config('admin.database.role_permissions_table'), $exceptFields),\n        ];\n\n        if ($exportUsers) {\n            $replaces = array_merge($replaces, [\n                'ClassUsers'            => config('admin.database.users_model'),\n                'TableRoleUsers'        => config('admin.database.role_users_table'),\n                'TablePermissionsUsers' => config('admin.database.user_permissions_table'),\n\n                'ArrayUsers'                 => $this->getTableDataArrayAsString(config('admin.database.users_table'), $exceptFields),\n                'ArrayPivotRoleUsers'        => $this->getTableDataArrayAsString(config('admin.database.role_users_table'), $exceptFields),\n                'ArrayPivotPermissionsUsers' => $this->getTableDataArrayAsString(config('admin.database.user_permissions_table'), $exceptFields),\n            ]);\n        } else {\n            $contents = preg_replace('/\\/\\/ users tables[\\s\\S]*?(?=\\/\\/ finish)/mu', '', $contents);\n        }\n\n        $contents = str_replace(array_keys($replaces), array_values($replaces), $contents);\n\n        $this->laravel['files']->put($seedFile, $contents);\n\n        $this->line('<info>Admin tables seed file was created:</info> '.str_replace(base_path(), '', $seedFile));\n        $this->line(\"Use: <info>php artisan db:seed --class={$name}</info>\");\n    }\n\n    /**\n     * Get data array from table as string result var_export.\n     *\n     * @param string $table\n     * @param array  $exceptFields\n     *\n     * @return string\n     */\n    protected function getTableDataArrayAsString($table, $exceptFields = [])\n    {\n        $fields = \\DB::getSchemaBuilder()->getColumnListing($table);\n        $fields = array_diff($fields, $exceptFields);\n\n        $array = \\DB::table($table)->get($fields)->map(function ($item) {\n            return (array) $item;\n        })->all();\n\n        return $this->varExport($array, str_repeat(' ', 12));\n    }\n\n    /**\n     * Get stub contents.\n     *\n     * @param $name\n     *\n     * @return string\n     */\n    protected function getStub($name)\n    {\n        return $this->laravel['files']->get(__DIR__.\"/stubs/$name.stub\");\n    }\n\n    /**\n     * Custom var_export for correct work with \\r\\n.\n     *\n     * @param $var\n     * @param string $indent\n     *\n     * @return string\n     */\n    protected function varExport($var, $indent = '')\n    {\n        switch (gettype($var)) {\n\n            case 'string':\n                return '\"'.addcslashes($var, \"\\\\\\$\\\"\\r\\n\\t\\v\\f\").'\"';\n\n            case 'array':\n                $indexed = array_keys($var) === range(0, count($var) - 1);\n\n                $r = [];\n\n                foreach ($var as $key => $value) {\n                    $r[] = \"$indent    \"\n                        .($indexed ? '' : $this->varExport($key).' => ')\n                        .$this->varExport($value, \"{$indent}    \");\n                }\n\n                return \"[\\n\".implode(\",\\n\", $r).\"\\n\".$indent.']';\n\n            case 'boolean':\n                return $var ? 'true' : 'false';\n\n            case 'integer':\n            case 'double':\n                return $var;\n\n            default:\n                return var_export($var, true);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Console/ExtendCommand.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Console;\n\nuse Illuminate\\Console\\Command;\nuse Illuminate\\Filesystem\\Filesystem;\nuse Illuminate\\Support\\Str;\n\nclass ExtendCommand extends Command\n{\n    /**\n     * The console command name.\n     *\n     * @var string\n     */\n    protected $signature = 'admin:extend {extension} {--namespace=}';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = 'Build a Laravel-admin extension';\n\n    /**\n     * @var string\n     */\n    protected $basePath = '';\n\n    /**\n     * @var Filesystem\n     */\n    protected $filesystem;\n\n    /**\n     * @var string\n     */\n    protected $namespace;\n\n    /**\n     * @var string\n     */\n    protected $className;\n\n    /**\n     * @var string\n     */\n    protected $package;\n\n    /**\n     * @var string\n     */\n    protected $extensionDir;\n\n    /**\n     * @var array\n     */\n    protected $dirs = [\n        'database/migrations',\n        'database/seeds',\n        'resources/assets',\n        'resources/views',\n        'src/Http/Controllers',\n        'routes',\n    ];\n\n    /**\n     * Execute the console command.\n     *\n     * @return void\n     */\n    public function handle(Filesystem $filesystem)\n    {\n        $this->filesystem = $filesystem;\n\n        $this->extensionDir = config('admin.extension_dir');\n\n        InputExtensionDir:\n        if (empty($this->extensionDir)) {\n            $this->extensionDir = $this->ask('Please input a directory to store your extension:');\n        }\n\n        if (!file_exists($this->extensionDir)) {\n            $this->makeDir();\n        }\n\n        $this->package = $this->argument('extension');\n\n        InputExtensionName:\n        if (!$this->validateExtensionName($this->package)) {\n            $this->package = $this->ask(\"[$this->package] is not a valid package name, please input a name like (<vendor>/<name>)\");\n            goto InputExtensionName;\n        }\n\n        $this->makeDirs();\n        $this->makeFiles();\n\n        $this->info(\"The extension scaffolding generated successfully. \\r\\n\");\n        $this->showTree();\n    }\n\n    /**\n     * Show extension scaffolding with tree structure.\n     */\n    protected function showTree()\n    {\n        $tree = <<<TREE\n{$this->extensionPath()}\n    ├── LICENSE\n    ├── README.md\n    ├── composer.json\n    ├── database\n    │   ├── migrations\n    │   └── seeds\n    ├── resources\n    │   ├── assets\n    │   └── views\n    │       └── index.blade.php\n    ├── routes\n    │   └── web.php\n    └── src\n        ├── {$this->className}.php\n        ├── {$this->className}ServiceProvider.php\n        └── Http\n            └── Controllers\n                └── {$this->className}Controller.php\nTREE;\n\n        $this->info($tree);\n    }\n\n    /**\n     * Make extension files.\n     */\n    protected function makeFiles()\n    {\n        $this->namespace = $this->getRootNameSpace();\n\n        $this->className = $this->getClassName();\n\n        // copy files\n        $this->copy([\n            __DIR__.'/stubs/extension/view.stub'       => 'resources/views/index.blade.php',\n            __DIR__.'/stubs/extension/.gitignore.stub' => '.gitignore',\n            __DIR__.'/stubs/extension/README.md.stub'  => 'README.md',\n            __DIR__.'/stubs/extension/LICENSE.stub'    => 'LICENSE',\n        ]);\n\n        // make composer.json\n        $composerContents = str_replace(\n            [':package', ':namespace', ':class_name'],\n            [$this->package, str_replace('\\\\', '\\\\\\\\', $this->namespace).'\\\\\\\\', $this->className],\n            file_get_contents(__DIR__.'/stubs/extension/composer.json.stub')\n        );\n        $this->putFile('composer.json', $composerContents);\n\n        // make class\n        $classContents = str_replace(\n            [':namespace', ':class_name', ':title', ':path', ':base_package'],\n            [$this->namespace, $this->className, Str::title($this->className), basename($this->package), basename($this->package)],\n            file_get_contents(__DIR__.'/stubs/extension/extension.stub')\n        );\n        $this->putFile(\"src/{$this->className}.php\", $classContents);\n\n        // make service provider\n        $providerContents = str_replace(\n            [':namespace', ':class_name', ':base_package', ':package'],\n            [$this->namespace, $this->className, basename($this->package), $this->package],\n            file_get_contents(__DIR__.'/stubs/extension/service-provider.stub')\n        );\n        $this->putFile(\"src/{$this->className}ServiceProvider.php\", $providerContents);\n\n        // make controller\n        $controllerContent = str_replace(\n            [':namespace', ':class_name', ':base_package'],\n            [$this->namespace, $this->className, basename($this->package)],\n            file_get_contents(__DIR__.'/stubs/extension/controller.stub')\n        );\n        $this->putFile(\"src/Http/Controllers/{$this->className}Controller.php\", $controllerContent);\n\n        // make routes\n        $routesContent = str_replace(\n            [':namespace', ':class_name', ':path'],\n            [$this->namespace, $this->className, basename($this->package)],\n            file_get_contents(__DIR__.'/stubs/extension/routes.stub')\n        );\n        $this->putFile('routes/web.php', $routesContent);\n    }\n\n    /**\n     * Get root namespace for this package.\n     *\n     * @return array|null|string\n     */\n    protected function getRootNameSpace()\n    {\n        if (!$namespace = $this->option('namespace')) {\n            list($vendor, $name) = explode('/', $this->package);\n\n            $default = str_replace(['-', '-'], '', Str::title($vendor).'\\\\'.Str::title($name));\n\n            $namespace = $this->ask('Root namespace', $default);\n        }\n\n        return $namespace;\n    }\n\n    /**\n     * Get extension class name.\n     *\n     * @return string\n     */\n    protected function getClassName()\n    {\n        return class_basename($this->namespace);\n    }\n\n    /**\n     * Create package dirs.\n     */\n    protected function makeDirs()\n    {\n        $this->basePath = rtrim($this->extensionDir, '/').'/'.ltrim($this->package, '/');\n\n        $this->makeDir($this->dirs);\n    }\n\n    /**\n     * Validate extension name.\n     *\n     * @param string $name\n     *\n     * @return int\n     */\n    protected function validateExtensionName($name)\n    {\n        return preg_match('/^[\\w\\-_]+\\/[\\w\\-_]+$/', $name);\n    }\n\n    /**\n     * Extension path.\n     *\n     * @param string $path\n     *\n     * @return string\n     */\n    protected function extensionPath($path = '')\n    {\n        $path = rtrim($path, '/');\n\n        if (empty($path)) {\n            return rtrim($this->basePath, '/');\n        }\n\n        return rtrim($this->basePath, '/').'/'.ltrim($path, '/');\n    }\n\n    /**\n     * Put contents to file.\n     *\n     * @param string $to\n     * @param string $content\n     */\n    protected function putFile($to, $content)\n    {\n        $to = $this->extensionPath($to);\n\n        $this->filesystem->put($to, $content);\n    }\n\n    /**\n     * Copy files to extension path.\n     *\n     * @param string|array $from\n     * @param string|null  $to\n     */\n    protected function copy($from, $to = null)\n    {\n        if (is_array($from) && is_null($to)) {\n            foreach ($from as $key => $value) {\n                $this->copy($key, $value);\n            }\n\n            return;\n        }\n\n        if (!file_exists($from)) {\n            return;\n        }\n\n        $to = $this->extensionPath($to);\n\n        $this->filesystem->copy($from, $to);\n    }\n\n    /**\n     * Make new directory.\n     *\n     * @param array|string $paths\n     */\n    protected function makeDir($paths = '')\n    {\n        foreach ((array) $paths as $path) {\n            $path = $this->extensionPath($path);\n\n            $this->filesystem->makeDirectory($path, 0755, true, true);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Console/FormCommand.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Console;\n\nuse Illuminate\\Console\\GeneratorCommand;\n\nclass FormCommand extends GeneratorCommand\n{\n    /**\n     * The console command name.\n     *\n     * @var string\n     */\n    protected $signature = 'admin:form {name} \n        {--title=}\n        {--step}\n        {--namespace=}';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = 'Make admin form widget';\n\n    /**\n     * Replace the class name for the given stub.\n     *\n     * @param string $stub\n     * @param string $name\n     *\n     * @return string\n     */\n    protected function replaceClass($stub, $name)\n    {\n        $stub = parent::replaceClass($stub, $name);\n\n        return str_replace('DummyTitle', $this->option('title'), $stub);\n    }\n\n    /**\n     * Get the stub file for the generator.\n     *\n     * @return string\n     */\n    protected function getStub()\n    {\n        if ($this->option('step')) {\n            return __DIR__.'/stubs/step-form.stub';\n        }\n\n        return __DIR__.'/stubs/form.stub';\n    }\n\n    /**\n     * Get the default namespace for the class.\n     *\n     * @param string $rootNamespace\n     *\n     * @return string\n     */\n    protected function getDefaultNamespace($rootNamespace)\n    {\n        if ($namespace = $this->option('namespace')) {\n            return $namespace;\n        }\n\n        return str_replace('Controllers', 'Forms', config('admin.route.namespace'));\n    }\n\n    /**\n     * Get the desired class name from the input.\n     *\n     * @return string\n     */\n    protected function getNameInput()\n    {\n        $name = trim($this->argument('name'));\n\n        $this->type = $this->qualifyClass($name);\n\n        return $name;\n    }\n}\n"
  },
  {
    "path": "src/Console/GenerateMenuCommand.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Console;\n\nuse Encore\\Admin\\Auth\\Database\\Menu;\nuse Illuminate\\Console\\Command;\nuse Illuminate\\Routing\\Route;\nuse Illuminate\\Routing\\Router;\nuse Illuminate\\Support\\Str;\n\nclass GenerateMenuCommand extends Command\n{\n    /**\n     * @var Router\n     */\n    protected $router;\n\n    /**\n     * The name and signature of the console command.\n     *\n     * @var string\n     */\n    protected $signature = 'admin:generate-menu {--dry-run : Dry run}';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = 'Generate menu items based on registered routes.';\n\n    /**\n     * Create a new command instance.\n     *\n     * @param Router $router\n     */\n    public function __construct(Router $router)\n    {\n        parent::__construct();\n\n        $this->router = $router;\n    }\n\n    /**\n     * Execute the console command.\n     *\n     * @return mixed\n     */\n    public function handle()\n    {\n        $prefix = config('admin.route.prefix');\n        $routes = collect($this->router->getRoutes())->filter(function (Route $route) use ($prefix) {\n            $uri = $route->uri();\n            // built-in, parameterized and no-GET are ignored\n            return Str::startsWith($uri, \"{$prefix}/\")\n                && !Str::startsWith($uri, \"{$prefix}/auth/\")\n                && !Str::endsWith($uri, '/create')\n                && !Str::contains($uri, '{')\n                && in_array('GET', $route->methods())\n                && !in_array(substr($route->uri(), strlen(\"{$prefix}/\")), config('admin.menu_exclude'));\n        })\n            ->map(function (Route $route) use ($prefix) {\n                $uri = substr($route->uri(), strlen(\"{$prefix}/\"));\n\n                return [\n                    'title' => Str::ucfirst(\n                        Str::snake(str_replace('/', ' ', $uri), ' ')\n                    ),\n                    'uri' => $uri,\n                ];\n            })\n            ->pluck('title', 'uri');\n\n        $menus = Menu::all()->pluck('title', 'uri');\n        // exclude exist ones\n        $news = $routes->diffKeys($menus)->map(function ($item, $key) {\n            return [\n                'title' => $item,\n                'uri'   => $key,\n                'order' => 10,\n                'icon'  => 'fa-list',\n            ];\n        })->values()->toArray();\n\n        if (!$news) {\n            $this->error('No newly registered routes found.');\n        } else {\n            if ($this->hasOption('dry-run') && $this->option('dry-run')) {\n                $this->line('<info>The following menu items will be created</info>: ');\n                $this->table(['Title', 'Uri'], array_map(function ($item) {\n                    return [\n                        $item['title'],\n                        $item['uri'],\n                    ];\n                }, $news));\n            } else {\n                Menu::insert($news);\n                $this->line('<info>Done!</info>');\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "src/Console/ImportCommand.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Console;\n\nuse Encore\\Admin\\Admin;\nuse Illuminate\\Console\\Command;\nuse Illuminate\\Support\\Arr;\n\nclass ImportCommand extends Command\n{\n    /**\n     * The console command name.\n     *\n     * @var string\n     */\n    protected $signature = 'admin:import {extension?}';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = 'Import a Laravel-admin extension';\n\n    /**\n     * Execute the console command.\n     *\n     * @return void\n     */\n    public function handle()\n    {\n        $extension = $this->argument('extension');\n\n        if (empty($extension) || !Arr::has(Admin::$extensions, $extension)) {\n            $extension = $this->choice('Please choose a extension to import', array_keys(Admin::$extensions));\n        }\n\n        $className = Arr::get(Admin::$extensions, $extension);\n\n        if (!class_exists($className) || !method_exists($className, 'import')) {\n            $this->error(\"Invalid Extension [$className]\");\n\n            return;\n        }\n\n        call_user_func([$className, 'import'], $this);\n\n        $this->info(\"Extension [$className] imported\");\n    }\n}\n"
  },
  {
    "path": "src/Console/InstallCommand.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Console;\n\nuse Illuminate\\Console\\Command;\n\nclass InstallCommand extends Command\n{\n    /**\n     * The console command name.\n     *\n     * @var string\n     */\n    protected $signature = 'admin:install';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = 'Install the admin package';\n\n    /**\n     * Install directory.\n     *\n     * @var string\n     */\n    protected $directory = '';\n\n    /**\n     * Execute the console command.\n     *\n     * @return void\n     */\n    public function handle()\n    {\n        $this->initDatabase();\n\n        $this->initAdminDirectory();\n    }\n\n    /**\n     * Create tables and seed it.\n     *\n     * @return void\n     */\n    public function initDatabase()\n    {\n        $this->call('migrate');\n\n        $userModel = config('admin.database.users_model');\n\n        if ($userModel::count() == 0) {\n            $this->call('db:seed', ['--class' => \\Encore\\Admin\\Auth\\Database\\AdminTablesSeeder::class]);\n        }\n    }\n\n    /**\n     * Initialize the admAin directory.\n     *\n     * @return void\n     */\n    protected function initAdminDirectory()\n    {\n        $this->directory = config('admin.directory');\n\n        if (is_dir($this->directory)) {\n            $this->line(\"<error>{$this->directory} directory already exists !</error> \");\n\n            return;\n        }\n\n        $this->makeDir('/');\n        $this->line('<info>Admin directory was created:</info> '.str_replace(base_path(), '', $this->directory));\n\n        $this->makeDir('Controllers');\n\n        $this->createHomeController();\n        $this->createAuthController();\n        $this->createExampleController();\n\n        $this->createBootstrapFile();\n        $this->createRoutesFile();\n    }\n\n    /**\n     * Create HomeController.\n     *\n     * @return void\n     */\n    public function createHomeController()\n    {\n        $homeController = $this->directory.'/Controllers/HomeController.php';\n        $contents = $this->getStub('HomeController');\n\n        $this->laravel['files']->put(\n            $homeController,\n            str_replace('DummyNamespace', config('admin.route.namespace'), $contents)\n        );\n        $this->line('<info>HomeController file was created:</info> '.str_replace(base_path(), '', $homeController));\n    }\n\n    /**\n     * Create AuthController.\n     *\n     * @return void\n     */\n    public function createAuthController()\n    {\n        $authController = $this->directory.'/Controllers/AuthController.php';\n        $contents = $this->getStub('AuthController');\n\n        $this->laravel['files']->put(\n            $authController,\n            str_replace('DummyNamespace', config('admin.route.namespace'), $contents)\n        );\n        $this->line('<info>AuthController file was created:</info> '.str_replace(base_path(), '', $authController));\n    }\n\n    /**\n     * Create HomeController.\n     *\n     * @return void\n     */\n    public function createExampleController()\n    {\n        $exampleController = $this->directory.'/Controllers/ExampleController.php';\n        $contents = $this->getStub('ExampleController');\n\n        $this->laravel['files']->put(\n            $exampleController,\n            str_replace('DummyNamespace', config('admin.route.namespace'), $contents)\n        );\n        $this->line('<info>ExampleController file was created:</info> '.str_replace(base_path(), '', $exampleController));\n    }\n\n    /**\n     * Create routes file.\n     *\n     * @return void\n     */\n    protected function createBootstrapFile()\n    {\n        $file = $this->directory.'/bootstrap.php';\n\n        $contents = $this->getStub('bootstrap');\n        $this->laravel['files']->put($file, $contents);\n        $this->line('<info>Bootstrap file was created:</info> '.str_replace(base_path(), '', $file));\n    }\n\n    /**\n     * Create routes file.\n     *\n     * @return void\n     */\n    protected function createRoutesFile()\n    {\n        $file = $this->directory.'/routes.php';\n\n        $contents = $this->getStub('routes');\n        $this->laravel['files']->put($file, str_replace('DummyNamespace', config('admin.route.namespace'), $contents));\n        $this->line('<info>Routes file was created:</info> '.str_replace(base_path(), '', $file));\n    }\n\n    /**\n     * Get stub contents.\n     *\n     * @param $name\n     *\n     * @return string\n     */\n    protected function getStub($name)\n    {\n        return $this->laravel['files']->get(__DIR__.\"/stubs/$name.stub\");\n    }\n\n    /**\n     * Make new directory.\n     *\n     * @param string $path\n     */\n    protected function makeDir($path = '')\n    {\n        $this->laravel['files']->makeDirectory(\"{$this->directory}/$path\", 0755, true, true);\n    }\n}\n"
  },
  {
    "path": "src/Console/MakeCommand.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Console;\n\nuse Illuminate\\Console\\GeneratorCommand;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Support\\Str;\n\nclass MakeCommand extends GeneratorCommand\n{\n    /**\n     * The console command name.\n     *\n     * @var string\n     */\n    protected $signature = 'admin:make {name}\n        {--model=}\n        {--title=}\n        {--stub= : Path to the custom stub file. }\n        {--namespace=}\n        {--O|output}';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = 'Make admin controller';\n\n    /**\n     * @var ResourceGenerator\n     */\n    protected $generator;\n\n    /**\n     * @var string\n     */\n    protected $controllerName;\n\n    /**\n     * @var string\n     */\n    protected $modelName;\n\n    /**\n     * Execute the console command.\n     *\n     * @return void\n     */\n    public function handle()\n    {\n        $this->modelName = $this->getModelName();\n        $this->controllerName = $this->getControllerName();\n\n        if (!$this->modelExists()) {\n            $this->error('Model does not exists !');\n\n            return false;\n        }\n\n        $stub = $this->option('stub');\n\n        if ($stub and !is_file($stub)) {\n            $this->error('The stub file dose not exist.');\n\n            return false;\n        }\n\n        $this->generator = new ResourceGenerator($this->modelName);\n\n        if ($this->option('output')) {\n            return $this->output($this->modelName);\n        }\n\n        if (parent::handle() !== false) {\n            $path = Str::plural(Str::kebab(class_basename($this->modelName)));\n\n            $this->line('');\n            $this->comment('Add the following route to app/Admin/routes.php:');\n            $this->line('');\n            $this->info(\"    \\$router->resource('{$path}', {$this->controllerName}::class);\");\n            $this->line('');\n        }\n    }\n\n    /**\n     * @return array|string|null\n     */\n    protected function getControllerName()\n    {\n        return $this->argument('name');\n    }\n\n    /**\n     * @return array|string|null\n     */\n    protected function getModelName()\n    {\n        return $this->option('model');\n    }\n\n    /**\n     * @throws \\ReflectionException\n     *\n     * @return array|bool|string|null\n     */\n    protected function getTitle()\n    {\n        if ($title = $this->option('title')) {\n            return $title;\n        }\n\n        return __((new \\ReflectionClass($this->modelName))->getShortName());\n    }\n\n    /**\n     * @param string $modelName\n     */\n    protected function output($modelName)\n    {\n        $this->alert(\"laravel-admin controller code for model [{$modelName}]\");\n\n        $this->info($this->generator->generateGrid());\n        $this->info($this->generator->generateShow());\n        $this->info($this->generator->generateForm());\n    }\n\n    /**\n     * Determine if the model is exists.\n     *\n     * @return bool\n     */\n    protected function modelExists()\n    {\n        if (empty($this->modelName)) {\n            return true;\n        }\n\n        return class_exists($this->modelName) && is_subclass_of($this->modelName, Model::class);\n    }\n\n    /**\n     * Replace the class name for the given stub.\n     *\n     * @param string $stub\n     * @param string $name\n     *\n     * @return string\n     */\n    protected function replaceClass($stub, $name)\n    {\n        $stub = parent::replaceClass($stub, $name);\n\n        return str_replace(\n            [\n                'DummyModelNamespace',\n                'DummyTitle',\n                'DummyModel',\n                'DummyGrid',\n                'DummyShow',\n                'DummyForm',\n            ],\n            [\n                $this->modelName,\n                $this->getTitle(),\n                class_basename($this->modelName),\n                $this->indentCodes($this->generator->generateGrid()),\n                $this->indentCodes($this->generator->generateShow()),\n                $this->indentCodes($this->generator->generateForm()),\n            ],\n            $stub\n        );\n    }\n\n    /**\n     * @param string $code\n     *\n     * @return string\n     */\n    protected function indentCodes($code)\n    {\n        $indent = str_repeat(' ', 8);\n\n        return rtrim($indent.preg_replace(\"/\\r\\n/\", \"\\r\\n{$indent}\", $code));\n    }\n\n    /**\n     * Get the stub file for the generator.\n     *\n     * @return string\n     */\n    protected function getStub()\n    {\n        if ($stub = $this->option('stub')) {\n            return $stub;\n        }\n\n        if ($this->modelName) {\n            return __DIR__.'/stubs/controller.stub';\n        }\n\n        return __DIR__.'/stubs/blank.stub';\n    }\n\n    /**\n     * Get the default namespace for the class.\n     *\n     * @param string $rootNamespace\n     *\n     * @return string\n     */\n    protected function getDefaultNamespace($rootNamespace)\n    {\n        if ($namespace = $this->option('namespace')) {\n            return $namespace;\n        }\n\n        return config('admin.route.namespace');\n    }\n\n    /**\n     * Get the desired class name from the input.\n     *\n     * @return string\n     */\n    protected function getNameInput()\n    {\n        $this->type = $this->qualifyClass($this->controllerName);\n\n        return $this->controllerName;\n    }\n}\n"
  },
  {
    "path": "src/Console/MenuCommand.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Console;\n\nuse Encore\\Admin\\Facades\\Admin;\nuse Illuminate\\Console\\Command;\n\nclass MenuCommand extends Command\n{\n    /**\n     * The console command name.\n     *\n     * @var string\n     */\n    protected $signature = 'admin:menu';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = 'Show the admin menu';\n\n    /**\n     * Execute the console command.\n     *\n     * @return void\n     */\n    public function handle()\n    {\n        $menu = Admin::menu();\n\n        echo json_encode($menu, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE), \"\\r\\n\";\n    }\n}\n"
  },
  {
    "path": "src/Console/MinifyCommand.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Console;\n\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Facades\\Admin as AdminFacade;\nuse Illuminate\\Console\\Command;\nuse Illuminate\\Support\\Str;\nuse MatthiasMullie\\Minify;\n\nclass MinifyCommand extends Command\n{\n    /**\n     * The console command name.\n     *\n     * @var string\n     */\n    protected $signature = 'admin:minify {--clear}';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = 'Minify the CSS and JS';\n\n    /**\n     * @var array\n     */\n    protected $assets = [\n        'css' => [],\n        'js'  => [],\n    ];\n\n    /**\n     * @var array\n     */\n    protected $excepts = [];\n\n    /**\n     * Execute the console command.\n     */\n    public function handle()\n    {\n        if (!class_exists(Minify\\Minify::class)) {\n            $this->error('To use `admin:minify` command, please install [matthiasmullie/minify] first.');\n\n            return;\n        }\n\n        if ($this->option('clear')) {\n            return $this->clearMinifiedFiles();\n        }\n\n        AdminFacade::bootstrap();\n\n        $this->loadExcepts();\n\n        $this->minifyCSS();\n        $this->minifyJS();\n\n        $this->generateManifest();\n\n        $this->comment('JS and CSS are successfully minified:');\n        $this->line('  '.Admin::$min['js']);\n        $this->line('  '.Admin::$min['css']);\n\n        $this->line('');\n\n        $this->comment('Manifest successfully generated:');\n        $this->line('  '.Admin::$manifest);\n    }\n\n    protected function loadExcepts()\n    {\n        $excepts = config('admin.minify_assets.excepts', []);\n\n        $this->excepts = array_merge($excepts, Admin::$minifyIgnores);\n    }\n\n    protected function clearMinifiedFiles()\n    {\n        @unlink(public_path(Admin::$manifest));\n        @unlink(public_path(Admin::$min['js']));\n        @unlink(public_path(Admin::$min['css']));\n\n        $this->comment('Following files are cleared:');\n\n        $this->line('  '.Admin::$min['js']);\n        $this->line('  '.Admin::$min['css']);\n        $this->line('  '.Admin::$manifest);\n    }\n\n    protected function minifyCSS()\n    {\n        $css = collect(array_merge(Admin::$css, Admin::baseCss()))\n            ->unique()->map(function ($css) {\n                if (url()->isValidUrl($css)) {\n                    $this->assets['css'][] = $css;\n\n                    return;\n                }\n\n                if (in_array($css, $this->excepts)) {\n                    $this->assets['css'][] = $css;\n\n                    return;\n                }\n\n                if (Str::contains($css, '?')) {\n                    $css = substr($css, 0, strpos($css, '?'));\n                }\n\n                return public_path($css);\n            })->filter();\n\n        $minifier = new Minify\\CSS();\n\n        $minifier->add(...$css);\n\n        $minifier->minify(public_path(Admin::$min['css']));\n    }\n\n    protected function minifyJS()\n    {\n        $js = collect(array_merge(Admin::$js, Admin::baseJs()))\n            ->unique()->map(function ($js) {\n                if (url()->isValidUrl($js)) {\n                    $this->assets['js'][] = $js;\n\n                    return;\n                }\n\n                if (in_array($js, $this->excepts)) {\n                    $this->assets['js'][] = $js;\n\n                    return;\n                }\n\n                if (Str::contains($js, '?')) {\n                    $js = substr($js, 0, strpos($js, '?'));\n                }\n\n                return public_path($js);\n            })->filter();\n\n        $minifier = new Minify\\JS();\n\n        $minifier->add(...$js);\n\n        $minifier->minify(public_path(Admin::$min['js']));\n    }\n\n    protected function generateManifest()\n    {\n        $min = collect(Admin::$min)->mapWithKeys(function ($path, $type) {\n            return [$type => sprintf('%s?id=%s', $path, md5(uniqid()))];\n        });\n\n        array_unshift($this->assets['css'], $min['css']);\n        array_unshift($this->assets['js'], $min['js']);\n\n        $json = json_encode($this->assets, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);\n\n        file_put_contents(public_path(Admin::$manifest), $json);\n    }\n}\n"
  },
  {
    "path": "src/Console/PermissionCommand.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Console;\n\nuse Encore\\Admin\\Auth\\Database\\Permission;\nuse Illuminate\\Console\\Command;\nuse Illuminate\\Support\\Facades\\DB;\nuse Illuminate\\Support\\Str;\n\nclass PermissionCommand extends Command\n{\n    /**\n     * The name and signature of the console command.\n     *\n     * @var string\n     */\n    protected $signature = 'admin:permissions {--tables=}';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = 'generate admin permission base on table name';\n\n    /**\n     * Create a new command instance.\n     *\n     * @return void\n     */\n    public function __construct()\n    {\n        parent::__construct();\n    }\n\n    /**\n     * Execute the console command.\n     *\n     * @return mixed\n     */\n    public function handle()\n    {\n        $all_tables = $this->getAllTables();\n\n        $tables = $this->option('tables') ? explode(',', $this->option('tables')) : [];\n        if (empty($tables)) {\n            $ignore_tables = $this->getIgnoreTables();\n            $tables = array_diff($all_tables, $ignore_tables);\n        } else {\n            $tables = array_intersect($all_tables, $tables);\n        }\n\n        if (empty($tables)) {\n            $this->info('table is not existed');\n\n            return;\n        }\n\n        $permissions = $this->getPermissions();\n        foreach ($tables as $table) {\n            foreach ($permissions as $permission => $permission_lang) {\n                $http_method = $this->generateHttpMethod($permission);\n                $http_path = $this->generateHttpPath($table, $permission);\n                $slug = $this->generateSlug($table, $permission);\n                $name = $this->generateName($table, $permission_lang);\n                $exists = Permission::where('slug', $slug)->exists();\n                if (!$exists) {\n                    Permission::create([\n                        'name'        => $name,\n                        'slug'        => $slug,\n                        'http_method' => $http_method,\n                        'http_path'   => $http_path,\n                    ]);\n                    $this->info(\"$slug is generated\");\n                } else {\n                    $this->warn(\"$slug is existed\");\n                }\n            }\n        }\n    }\n\n    private function getAllTables()\n    {\n        return array_map('current', DB::select('SHOW TABLES'));\n    }\n\n    private function getIgnoreTables()\n    {\n        return [\n            config('admin.database.users_table'),\n            config('admin.database.roles_table'),\n            config('admin.database.permissions_table'),\n            config('admin.database.menu_table'),\n            config('admin.database.operation_log_table'),\n            config('admin.database.user_permissions_table'),\n            config('admin.database.role_users_table'),\n            config('admin.database.role_permissions_table'),\n            config('admin.database.role_menu_table'),\n        ];\n    }\n\n    private function getPermissions()\n    {\n        return [\n            'list'   => __('admin.list'),\n            'view'   => __('admin.view'),\n            'create' => __('admin.create'),\n            'edit'   => __('admin.edit'),\n            'delete' => __('admin.delete'),\n            'export' => __('admin.export'),\n            'filter' => __('admin.filter'),\n        ];\n    }\n\n    private function generateHttpMethod($permission)\n    {\n        switch ($permission) {\n            case 'create':\n                $http_method = ['POST'];\n                break;\n            case 'edit':\n                $http_method = ['PUT', 'PATCH'];\n                break;\n            case 'delete':\n                $http_method = ['DELETE'];\n                break;\n            default:\n                $http_method = ['GET'];\n        }\n\n        return $http_method;\n    }\n\n    private function generateHttpPath($table, $permission)\n    {\n        $resource = Str::kebab(Str::camel($table));\n        switch ($permission) {\n            case 'create':\n            case 'list':\n            case 'filter':\n                $http_path = '/'.$resource;\n                break;\n            case 'edit':\n            case 'delete':\n            case 'view':\n                $http_path = '/'.$resource.'/*';\n                break;\n            default:\n                $http_path = '';\n        }\n\n        return $http_path;\n    }\n\n    private function generateSlug($table, $permission)\n    {\n        return Str::kebab(Str::camel($table)).'.'.$permission;\n    }\n\n    private function generateName($table, $permission_lang)\n    {\n        return Str::upper(Str::kebab(Str::camel($table))).$permission_lang;\n    }\n}\n"
  },
  {
    "path": "src/Console/PublishCommand.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Console;\n\nuse Illuminate\\Console\\Command;\n\nclass PublishCommand extends Command\n{\n    /**\n     * The console command name.\n     *\n     * @var string\n     */\n    protected $signature = 'admin:publish {--force}';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = \"re-publish laravel-admin's assets, configuration, language and migration files. If you want overwrite the existing files, you can add the `--force` option\";\n\n    /**\n     * Execute the console command.\n     *\n     * @return void\n     */\n    public function handle()\n    {\n        $force = $this->option('force');\n        $options = ['--provider' => 'Encore\\Admin\\AdminServiceProvider'];\n        if ($force == true) {\n            $options['--force'] = true;\n        }\n        $this->call('vendor:publish', $options);\n        $this->call('view:clear');\n    }\n}\n"
  },
  {
    "path": "src/Console/ResetPasswordCommand.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Console;\n\nuse Illuminate\\Console\\Command;\nuse Illuminate\\Support\\Facades\\Hash;\n\nclass ResetPasswordCommand extends Command\n{\n    /**\n     * The name and signature of the console command.\n     *\n     * @var string\n     */\n    protected $signature = 'admin:reset-password';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = 'Reset password for a specific admin user';\n\n    /**\n     * Execute the console command.\n     */\n    public function handle()\n    {\n        $userModel = config('admin.database.users_model');\n\n        askForUserName:\n        $username = $this->ask('Please enter a username who needs to reset his password');\n\n        $user = $userModel::query()->where('username', $username)->first();\n\n        if (is_null($user)) {\n            $this->error('The user you entered is not exists');\n            goto askForUserName;\n        }\n\n        enterPassword:\n        $password = $this->secret('Please enter a password');\n\n        if ($password !== $this->secret('Please confirm the password')) {\n            $this->error('The passwords entered twice do not match, please re-enter');\n            goto enterPassword;\n        }\n\n        $user->password = Hash::make($password);\n\n        $user->save();\n\n        $this->info('User password reset successfully.');\n    }\n}\n"
  },
  {
    "path": "src/Console/ResourceGenerator.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Console;\n\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass ResourceGenerator\n{\n    /**\n     * @var Model\n     */\n    protected $model;\n\n    /**\n     * @var array\n     */\n    protected $formats = [\n        'form_field'  => \"\\$form->%s('%s', __('%s'))\",\n        'show_field'  => \"\\$show->field('%s', __('%s'))\",\n        'grid_column' => \"\\$grid->column('%s', __('%s'))\",\n    ];\n\n    /**\n     * @var array\n     */\n    private $doctrineTypeMapping = [\n        'string' => [\n            'enum', 'geometry', 'geometrycollection', 'linestring',\n            'polygon', 'multilinestring', 'multipoint', 'multipolygon',\n            'point',\n        ],\n    ];\n\n    /**\n     * @var array\n     */\n    protected $fieldTypeMapping = [\n        'ip'       => 'ip',\n        'email'    => 'email|mail',\n        'password' => 'password|pwd',\n        'url'      => 'url|link|src|href',\n        'mobile'   => 'mobile|phone',\n        'color'    => 'color|rgb',\n        'image'    => 'image|img|avatar|pic|picture|cover',\n        'file'     => 'file|attachment',\n    ];\n\n    /**\n     * ResourceGenerator constructor.\n     *\n     * @param mixed $model\n     */\n    public function __construct($model)\n    {\n        $this->model = $this->getModel($model);\n    }\n\n    /**\n     * @param mixed $model\n     *\n     * @return mixed\n     */\n    protected function getModel($model)\n    {\n        if ($model instanceof Model) {\n            return $model;\n        }\n\n        if (!class_exists($model) || !is_string($model) || !is_subclass_of($model, Model::class)) {\n            throw new \\InvalidArgumentException(\"Invalid model [$model] !\");\n        }\n\n        return new $model();\n    }\n\n    /**\n     * @return string\n     */\n    public function generateForm()\n    {\n        $reservedColumns = $this->getReservedColumns();\n\n        $output = '';\n\n        foreach ($this->getTableColumns() as $column) {\n            $name = $column->getName();\n            if (in_array($name, $reservedColumns)) {\n                continue;\n            }\n            $type = $column->getType()->getName();\n            $default = $column->getDefault();\n\n            $defaultValue = '';\n\n            // set column fieldType and defaultValue\n            switch ($type) {\n                case 'boolean':\n                case 'bool':\n                    $fieldType = 'switch';\n                    break;\n                case 'json':\n                case 'array':\n                case 'object':\n                    $fieldType = 'text';\n                    break;\n                case 'string':\n                    $fieldType = 'text';\n                    foreach ($this->fieldTypeMapping as $type => $regex) {\n                        if (preg_match(\"/^($regex)$/i\", $name) !== 0) {\n                            $fieldType = $type;\n                            break;\n                        }\n                    }\n                    $defaultValue = \"'{$default}'\";\n                    break;\n                case 'integer':\n                case 'bigint':\n                case 'smallint':\n                case 'timestamp':\n                    $fieldType = 'number';\n                    break;\n                case 'decimal':\n                case 'float':\n                case 'real':\n                    $fieldType = 'decimal';\n                    break;\n                case 'datetime':\n                    $fieldType = 'datetime';\n                    $defaultValue = \"date('Y-m-d H:i:s')\";\n                    break;\n                case 'date':\n                    $fieldType = 'date';\n                    $defaultValue = \"date('Y-m-d')\";\n                    break;\n                case 'time':\n                    $fieldType = 'time';\n                    $defaultValue = \"date('H:i:s')\";\n                    break;\n                case 'text':\n                case 'blob':\n                    $fieldType = 'textarea';\n                    break;\n                default:\n                    $fieldType = 'text';\n                    $defaultValue = \"'{$default}'\";\n            }\n\n            $defaultValue = $defaultValue ?: $default;\n\n            $label = $this->formatLabel($name);\n\n            $output .= sprintf($this->formats['form_field'], $fieldType, $name, $label);\n\n            if (trim($defaultValue, \"'\\\"\")) {\n                $output .= \"->default({$defaultValue})\";\n            }\n\n            $output .= \";\\r\\n\";\n        }\n\n        return $output;\n    }\n\n    public function generateShow()\n    {\n        $output = '';\n\n        foreach ($this->getTableColumns() as $column) {\n            $name = $column->getName();\n\n            // set column label\n            $label = $this->formatLabel($name);\n\n            $output .= sprintf($this->formats['show_field'], $name, $label);\n\n            $output .= \";\\r\\n\";\n        }\n\n        return $output;\n    }\n\n    public function generateGrid()\n    {\n        $output = '';\n\n        foreach ($this->getTableColumns() as $column) {\n            $name = $column->getName();\n            $label = $this->formatLabel($name);\n\n            $output .= sprintf($this->formats['grid_column'], $name, $label);\n            $output .= \";\\r\\n\";\n        }\n\n        return $output;\n    }\n\n    protected function getReservedColumns()\n    {\n        return [\n            $this->model->getKeyName(),\n            $this->model->getCreatedAtColumn(),\n            $this->model->getUpdatedAtColumn(),\n            'deleted_at',\n        ];\n    }\n\n    /**\n     * Get columns of a giving model.\n     *\n     * @throws \\Exception\n     *\n     * @return \\Doctrine\\DBAL\\Schema\\Column[]\n     */\n    protected function getTableColumns()\n    {\n        if (!$this->model->getConnection()->isDoctrineAvailable()) {\n            throw new \\Exception(\n                'You need to require doctrine/dbal: ~2.3 in your own composer.json to get database columns. '\n            );\n        }\n\n        $table = $this->model->getConnection()->getTablePrefix().$this->model->getTable();\n        /** @var \\Doctrine\\DBAL\\Schema\\MySqlSchemaManager $schema */\n        $schema = $this->model->getConnection()->getDoctrineSchemaManager($table);\n\n        // custom mapping the types that doctrine/dbal does not support\n        $databasePlatform = $schema->getDatabasePlatform();\n\n        foreach ($this->doctrineTypeMapping as $doctrineType => $dbTypes) {\n            foreach ($dbTypes as $dbType) {\n                $databasePlatform->registerDoctrineTypeMapping($dbType, $doctrineType);\n            }\n        }\n\n        $database = null;\n        if (strpos($table, '.')) {\n            list($database, $table) = explode('.', $table);\n        }\n\n        return $schema->listTableColumns($table, $database);\n    }\n\n    /**\n     * Format label.\n     *\n     * @param string $value\n     *\n     * @return string\n     */\n    protected function formatLabel($value)\n    {\n        return ucfirst(str_replace(['-', '_'], ' ', $value));\n    }\n}\n"
  },
  {
    "path": "src/Console/UninstallCommand.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Console;\n\nuse Illuminate\\Console\\Command;\n\nclass UninstallCommand extends Command\n{\n    /**\n     * The console command name.\n     *\n     * @var string\n     */\n    protected $signature = 'admin:uninstall';\n\n    /**\n     * The console command description.\n     *\n     * @var string\n     */\n    protected $description = 'Uninstall the admin package';\n\n    /**\n     * Execute the console command.\n     *\n     * @return void\n     */\n    public function handle()\n    {\n        if (!$this->confirm('Are you sure to uninstall laravel-admin?')) {\n            return;\n        }\n\n        $this->removeFilesAndDirectories();\n\n        $this->line('<info>Uninstalling laravel-admin!</info>');\n    }\n\n    /**\n     * Remove files and directories.\n     *\n     * @return void\n     */\n    protected function removeFilesAndDirectories()\n    {\n        $this->laravel['files']->deleteDirectory(config('admin.directory'));\n        $this->laravel['files']->deleteDirectory(public_path('vendor/laravel-admin/'));\n        $this->laravel['files']->delete(config_path('admin.php'));\n    }\n}\n"
  },
  {
    "path": "src/Console/stubs/AdminTablesSeeder.stub",
    "content": "<?php\n\nnamespace Database\\Seeders;\n\nuse DB;\nuse Illuminate\\Database\\Seeder;\n\nclass DummyClass extends Seeder\n{\n    /**\n     * Run the database seeds.\n     *\n     * @return void\n     */\n    public function run()\n    {\n        // base tables\n        \\ClassMenu::truncate();\n        \\ClassMenu::insert(\n            ArrayMenu\n        );\n\n        \\ClassPermission::truncate();\n        \\ClassPermission::insert(\n            ArrayPermission\n        );\n\n        \\ClassRole::truncate();\n        \\ClassRole::insert(\n            ArrayRole\n        );\n\n        // pivot tables\n        DB::table('TableRoleMenu')->truncate();\n        DB::table('TableRoleMenu')->insert(\n            ArrayPivotRoleMenu\n        );\n\n        DB::table('TableRolePermissions')->truncate();\n        DB::table('TableRolePermissions')->insert(\n            ArrayPivotRolePermissions\n        );\n\n        // users tables\n        \\ClassUsers::truncate();\n        \\ClassUsers::insert(\n            ArrayUsers\n        );\n\n        DB::table('TableRoleUsers')->truncate();\n        DB::table('TableRoleUsers')->insert(\n            ArrayPivotRoleUsers\n        );\n\n        DB::table('TablePermissionsUsers')->truncate();\n        DB::table('TablePermissionsUsers')->insert(\n            ArrayPivotPermissionsUsers\n        );\n\n        // finish\n    }\n}\n"
  },
  {
    "path": "src/Console/stubs/AuthController.stub",
    "content": "<?php\n\nnamespace DummyNamespace;\n\nuse Encore\\Admin\\Controllers\\AuthController as BaseAuthController;\n\nclass AuthController extends BaseAuthController\n{\n\n}\n"
  },
  {
    "path": "src/Console/stubs/ExampleController.stub",
    "content": "<?php\n\nnamespace DummyNamespace;\n\nuse Encore\\Admin\\Controllers\\AdminController;\nuse Encore\\Admin\\Form;\nuse Encore\\Admin\\Grid;\nuse Encore\\Admin\\Show;\n\nclass ExampleController extends AdminController\n{\n    /**\n     * Title for current resource.\n     *\n     * @var string\n     */\n    protected $title = 'Example controller';\n\n    /**\n     * Make a grid builder.\n     *\n     * @return Grid\n     */\n    protected function grid()\n    {\n        $grid = new Grid(new ExampleModel);\n\n        $grid->column('id', __('ID'))->sortable();\n        $grid->column('created_at', __('Created at'));\n        $grid->column('updated_at', __('Updated at'));\n\n        return $grid;\n    }\n\n    /**\n     * Make a show builder.\n     *\n     * @param mixed   $id\n     * @return Show\n     */\n    protected function detail($id)\n    {\n        $show = new Show(ExampleModel::findOrFail($id));\n\n        $show->field('id', __('ID'));\n        $show->field('created_at', __('Created at'));\n        $show->field('updated_at', __('Updated at'));\n\n        return $show;\n    }\n\n    /**\n     * Make a form builder.\n     *\n     * @return Form\n     */\n    protected function form()\n    {\n        $form = new Form(new ExampleModel);\n\n        $form->display('id', __('ID'));\n        $form->display('created_at', __('Created At'));\n        $form->display('updated_at', __('Updated At'));\n\n        return $form;\n    }\n}\n"
  },
  {
    "path": "src/Console/stubs/HomeController.stub",
    "content": "<?php\n\nnamespace DummyNamespace;\n\nuse App\\Http\\Controllers\\Controller;\nuse Encore\\Admin\\Controllers\\Dashboard;\nuse Encore\\Admin\\Layout\\Column;\nuse Encore\\Admin\\Layout\\Content;\nuse Encore\\Admin\\Layout\\Row;\n\nclass HomeController extends Controller\n{\n    public function index(Content $content)\n    {\n        return $content\n            ->title('Dashboard')\n            ->description('Description...')\n            ->row(Dashboard::title())\n            ->row(function (Row $row) {\n\n                $row->column(4, function (Column $column) {\n                    $column->append(Dashboard::environment());\n                });\n\n                $row->column(4, function (Column $column) {\n                    $column->append(Dashboard::extensions());\n                });\n\n                $row->column(4, function (Column $column) {\n                    $column->append(Dashboard::dependencies());\n                });\n            });\n    }\n}\n"
  },
  {
    "path": "src/Console/stubs/action.stub",
    "content": "<?php\n\nnamespace DummyNamespace;\n\nuse Encore\\Admin\\Actions\\Action;\nuse Illuminate\\Http\\Request;\n\nclass DummyClass extends Action\n{\n    protected $selector = '.DummySelector';\n\n    public function handle(Request $request)\n    {\n        // $request ...\n\n        return $this->response()->success('Success message...')->refresh();\n    }\nDummyInteractor\n    public function html()\n    {\n        return <<<HTML\n        <a class=\"btn btn-sm btn-default DummySelector\">DummyName</a>\nHTML;\n    }\n}"
  },
  {
    "path": "src/Console/stubs/blank.stub",
    "content": "<?php\n\nnamespace DummyNamespace;\n\nuse App\\Http\\Controllers\\Controller;\nuse Encore\\Admin\\Controllers\\HasResourceActions;\n\nclass DummyClass extends Controller\n{\n    use HasResourceActions;\n}\n"
  },
  {
    "path": "src/Console/stubs/bootstrap.stub",
    "content": "<?php\n\n/**\n * Laravel-admin - admin builder based on Laravel.\n * @author z-song <https://github.com/z-song>\n *\n * Bootstraper for Admin.\n *\n * Here you can remove builtin form field:\n * Encore\\Admin\\Form::forget(['map', 'editor']);\n *\n * Or extend custom form field:\n * Encore\\Admin\\Form::extend('php', PHPEditor::class);\n *\n * Or require js and css assets:\n * Admin::css('/packages/prettydocs/css/styles.css');\n * Admin::js('/packages/prettydocs/js/main.js');\n *\n */\n\nEncore\\Admin\\Form::forget(['map', 'editor']);\n"
  },
  {
    "path": "src/Console/stubs/controller.stub",
    "content": "<?php\n\nnamespace DummyNamespace;\n\nuse DummyModelNamespace;\nuse Encore\\Admin\\Controllers\\AdminController;\nuse Encore\\Admin\\Form;\nuse Encore\\Admin\\Grid;\nuse Encore\\Admin\\Show;\n\nclass DummyClass extends AdminController\n{\n    /**\n     * Title for current resource.\n     *\n     * @var string\n     */\n    protected $title = 'DummyTitle';\n\n    /**\n     * Make a grid builder.\n     *\n     * @return Grid\n     */\n    protected function grid()\n    {\n        $grid = new Grid(new DummyModel());\n\nDummyGrid\n\n        return $grid;\n    }\n\n    /**\n     * Make a show builder.\n     *\n     * @param mixed $id\n     * @return Show\n     */\n    protected function detail($id)\n    {\n        $show = new Show(DummyModel::findOrFail($id));\n\nDummyShow\n\n        return $show;\n    }\n\n    /**\n     * Make a form builder.\n     *\n     * @return Form\n     */\n    protected function form()\n    {\n        $form = new Form(new DummyModel());\n\nDummyForm\n\n        return $form;\n    }\n}\n"
  },
  {
    "path": "src/Console/stubs/extension/.gitignore.stub",
    "content": ".DS_Store\nphpunit.phar\n/vendor\ncomposer.phar\ncomposer.lock\n*.project\n.idea/"
  },
  {
    "path": "src/Console/stubs/extension/LICENSE.stub",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2015 Jens Segers\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "src/Console/stubs/extension/README.md.stub",
    "content": "laravel-admin extension\n======\n\n\n"
  },
  {
    "path": "src/Console/stubs/extension/composer.json.stub",
    "content": "{\n    \"name\": \":package\",\n    \"description\": \"description...\",\n    \"type\": \"library\",\n    \"keywords\": [\"laravel-admin\", \"extension\"],\n    \"homepage\": \"https://github.com/:package\",\n    \"license\": \"MIT\",\n    \"authors\": [\n        {\n            \"name\": \"your name\",\n            \"email\": \"your email\"\n        }\n    ],\n    \"require\": {\n        \"php\": \">=7.0.0\",\n        \"encore/laravel-admin\": \"~1.6\"\n    },\n    \"require-dev\": {\n        \"phpunit/phpunit\": \"~6.0\"\n    },\n    \"autoload\": {\n        \"psr-4\": {\n            \":namespace\": \"src/\"\n        }\n    },\n    \"extra\": {\n        \"laravel\": {\n            \"providers\": [\n                \":namespace:class_nameServiceProvider\"\n            ]\n        }\n    }\n}\n"
  },
  {
    "path": "src/Console/stubs/extension/controller.stub",
    "content": "<?php\n\nnamespace :namespace\\Http\\Controllers;\n\nuse Encore\\Admin\\Layout\\Content;\nuse Illuminate\\Routing\\Controller;\n\nclass :class_nameController extends Controller\n{\n    public function index(Content $content)\n    {\n        return $content\n            ->title('Title')\n            ->description('Description')\n            ->body(view(':base_package::index'));\n    }\n}"
  },
  {
    "path": "src/Console/stubs/extension/extension.stub",
    "content": "<?php\n\nnamespace :namespace;\n\nuse Encore\\Admin\\Extension;\n\nclass :class_name extends Extension\n{\n    public $name = ':base_package';\n\n    public $views = __DIR__.'/../resources/views';\n\n    public $assets = __DIR__.'/../resources/assets';\n\n    public $menu = [\n        'title' => ':title',\n        'path'  => ':path',\n        'icon'  => 'fa-gears',\n    ];\n}"
  },
  {
    "path": "src/Console/stubs/extension/routes.stub",
    "content": "<?php\n\nuse :namespace\\Http\\Controllers\\:class_nameController;\n\nRoute::get(':path', :class_nameController::class.'@index');"
  },
  {
    "path": "src/Console/stubs/extension/service-provider.stub",
    "content": "<?php\n\nnamespace :namespace;\n\nuse Illuminate\\Support\\ServiceProvider;\n\nclass :class_nameServiceProvider extends ServiceProvider\n{\n    /**\n     * {@inheritdoc}\n     */\n    public function boot(:class_name $extension)\n    {\n        if (! :class_name::boot()) {\n            return ;\n        }\n\n        if ($views = $extension->views()) {\n            $this->loadViewsFrom($views, ':base_package');\n        }\n\n        if ($this->app->runningInConsole() && $assets = $extension->assets()) {\n            $this->publishes(\n                [$assets => public_path('vendor/:package')],\n                ':base_package'\n            );\n        }\n\n        $this->app->booted(function () {\n            :class_name::routes(__DIR__.'/../routes/web.php');\n        });\n    }\n}"
  },
  {
    "path": "src/Console/stubs/extension/view.stub",
    "content": "Welcome to laravel-admin"
  },
  {
    "path": "src/Console/stubs/form.stub",
    "content": "<?php\n\nnamespace DummyNamespace;\n\nuse Encore\\Admin\\Widgets\\Form;\nuse Illuminate\\Http\\Request;\n\nclass DummyClass extends Form\n{\n    /**\n     * The form title.\n     *\n     * @var string\n     */\n    public $title = 'DummyTitle';\n\n    /**\n     * Handle the form request.\n     *\n     * @param Request $request\n     *\n     * @return \\Illuminate\\Http\\RedirectResponse\n     */\n    public function handle(Request $request)\n    {\n        //dump($request->all());\n\n        admin_success('Processed successfully.');\n\n        return back();\n    }\n\n    /**\n     * Build a form here.\n     */\n    public function form()\n    {\n        $this->text('name')->rules('required');\n        $this->email('email')->rules('email');\n        $this->datetime('created_at');\n    }\n\n    /**\n     * The data of the form.\n     *\n     * @return array $data\n     */\n    public function data()\n    {\n        return [\n            'name'       => 'John Doe',\n            'email'      => 'John.Doe@gmail.com',\n            'created_at' => now(),\n        ];\n    }\n}\n"
  },
  {
    "path": "src/Console/stubs/grid-batch-action.stub",
    "content": "<?php\n\nnamespace DummyNamespace;\n\nuse Encore\\Admin\\Actions\\BatchAction;\nuse Illuminate\\Database\\Eloquent\\Collection;\n\nclass DummyClass extends BatchAction\n{\n    public $name = 'DummyName';\n\n    public function handle(Collection $collection)\n    {\n        foreach ($collection as $model) {\n            // ...\n        }\n\n        return $this->response()->success('Success message...')->refresh();\n    }\nDummyInteractor\n}"
  },
  {
    "path": "src/Console/stubs/grid-row-action.stub",
    "content": "<?php\n\nnamespace DummyNamespace;\n\nuse Encore\\Admin\\Actions\\RowAction;\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass DummyClass extends RowAction\n{\n    public $name = 'DummyName';\n\n    public function handle(Model $model)\n    {\n        // $model ...\n\n        return $this->response()->success('Success message.')->refresh();\n    }\nDummyInteractor\n}"
  },
  {
    "path": "src/Console/stubs/routes.stub",
    "content": "<?php\n\nuse Illuminate\\Routing\\Router;\n\nAdmin::routes();\n\nRoute::group([\n    'prefix'        => config('admin.route.prefix'),\n    'namespace'     => config('admin.route.namespace'),\n    'middleware'    => config('admin.route.middleware'),\n    'as'            => config('admin.route.prefix') . '.',\n], function (Router $router) {\n\n    $router->get('/', 'HomeController@index')->name('home');\n\n});\n"
  },
  {
    "path": "src/Console/stubs/step-form.stub",
    "content": "<?php\n\nnamespace DummyNamespace;\n\nuse Encore\\Admin\\Widgets\\StepForm;\nuse Illuminate\\Http\\Request;\n\nclass DummyClass extends StepForm\n{\n    /**\n     * The form title.\n     *\n     * @var string\n     */\n    public $title = 'DummyTitle';\n\n    /**\n     * Handle the form request.\n     *\n     * @param Request $request\n     *\n     * @return \\Illuminate\\Http\\RedirectResponse\n     */\n    public function handle(Request $request)\n    {\n        //dump($request->all());\n\n        admin_success('Processed successfully.');\n\n        return $this->next($request->all());\n    }\n\n    /**\n     * Build a form here.\n     */\n    public function form()\n    {\n        $this->text('name')->rules('required');\n        $this->email('email')->rules('email');\n        $this->datetime('created_at');\n    }\n}\n"
  },
  {
    "path": "src/Controllers/AdminController.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Controllers;\n\nuse Encore\\Admin\\Layout\\Content;\nuse Illuminate\\Routing\\Controller;\n\nclass AdminController extends Controller\n{\n    use HasResourceActions;\n\n    /**\n     * Title for current resource.\n     *\n     * @var string\n     */\n    protected $title = 'Title';\n\n    /**\n     * Set description for following 4 action pages.\n     *\n     * @var array\n     */\n    protected $description = [\n        //        'index'  => 'Index',\n        //        'show'   => 'Show',\n        //        'edit'   => 'Edit',\n        //        'create' => 'Create',\n    ];\n\n    /**\n     * Get content title.\n     *\n     * @return string\n     */\n    protected function title()\n    {\n        return $this->title;\n    }\n\n    /**\n     * Index interface.\n     *\n     * @param Content $content\n     *\n     * @return Content\n     */\n    public function index(Content $content)\n    {\n        return $content\n            ->title($this->title())\n            ->description($this->description['index'] ?? trans('admin.list'))\n            ->body($this->grid());\n    }\n\n    /**\n     * Show interface.\n     *\n     * @param mixed   $id\n     * @param Content $content\n     *\n     * @return Content\n     */\n    public function show($id, Content $content)\n    {\n        return $content\n            ->title($this->title())\n            ->description($this->description['show'] ?? trans('admin.show'))\n            ->body($this->detail($id));\n    }\n\n    /**\n     * Edit interface.\n     *\n     * @param mixed   $id\n     * @param Content $content\n     *\n     * @return Content\n     */\n    public function edit($id, Content $content)\n    {\n        return $content\n            ->title($this->title())\n            ->description($this->description['edit'] ?? trans('admin.edit'))\n            ->body($this->form()->edit($id));\n    }\n\n    /**\n     * Create interface.\n     *\n     * @param Content $content\n     *\n     * @return Content\n     */\n    public function create(Content $content)\n    {\n        return $content\n            ->title($this->title())\n            ->description($this->description['create'] ?? trans('admin.create'))\n            ->body($this->form());\n    }\n}\n"
  },
  {
    "path": "src/Controllers/AuthController.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Controllers;\n\nuse Encore\\Admin\\Facades\\Admin;\nuse Encore\\Admin\\Form;\nuse Encore\\Admin\\Layout\\Content;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Routing\\Controller;\nuse Illuminate\\Support\\Facades\\Hash;\nuse Illuminate\\Support\\Facades\\Lang;\nuse Illuminate\\Support\\Facades\\Redirect;\nuse Illuminate\\Support\\Facades\\Validator;\n\nclass AuthController extends Controller\n{\n    /**\n     * @var string\n     */\n    protected $loginView = 'admin::login';\n\n    /**\n     * Show the login page.\n     *\n     * @return \\Illuminate\\Contracts\\View\\Factory|Redirect|\\Illuminate\\View\\View\n     */\n    public function getLogin()\n    {\n        if ($this->guard()->check()) {\n            return redirect($this->redirectPath());\n        }\n\n        return view($this->loginView);\n    }\n\n    /**\n     * Handle a login request.\n     *\n     * @param Request $request\n     *\n     * @return mixed\n     */\n    public function postLogin(Request $request)\n    {\n        $this->loginValidator($request->all())->validate();\n\n        $credentials = $request->only([$this->username(), 'password']);\n        $remember = $request->get('remember', false);\n\n        if ($this->guard()->attempt($credentials, $remember)) {\n            return $this->sendLoginResponse($request);\n        }\n\n        return back()->withInput()->withErrors([\n            $this->username() => $this->getFailedLoginMessage(),\n        ]);\n    }\n\n    /**\n     * Get a validator for an incoming login request.\n     *\n     * @param array $data\n     *\n     * @return \\Illuminate\\Contracts\\Validation\\Validator\n     */\n    protected function loginValidator(array $data)\n    {\n        return Validator::make($data, [\n            $this->username()   => 'required',\n            'password'          => 'required',\n        ]);\n    }\n\n    /**\n     * User logout.\n     *\n     * @return Redirect\n     */\n    public function getLogout(Request $request)\n    {\n        $this->guard()->logout();\n\n        $request->session()->invalidate();\n\n        return redirect(config('admin.route.prefix'));\n    }\n\n    /**\n     * User setting page.\n     *\n     * @param Content $content\n     *\n     * @return Content\n     */\n    public function getSetting(Content $content)\n    {\n        $form = $this->settingForm();\n        $form->tools(\n            function (Form\\Tools $tools) {\n                $tools->disableList();\n                $tools->disableDelete();\n                $tools->disableView();\n            }\n        );\n\n        return $content\n            ->title(trans('admin.user_setting'))\n            ->body($form->edit(Admin::user()->id));\n    }\n\n    /**\n     * Update user setting.\n     *\n     * @return \\Symfony\\Component\\HttpFoundation\\Response\n     */\n    public function putSetting()\n    {\n        return $this->settingForm()->update(Admin::user()->id);\n    }\n\n    /**\n     * Model-form for user setting.\n     *\n     * @return Form\n     */\n    protected function settingForm()\n    {\n        $class = config('admin.database.users_model');\n\n        $form = new Form(new $class());\n\n        $form->display('username', trans('admin.username'));\n        $form->text('name', trans('admin.name'))->rules('required');\n        $form->image('avatar', trans('admin.avatar'));\n        $form->password('password', trans('admin.password'))->rules('confirmed|required');\n        $form->password('password_confirmation', trans('admin.password_confirmation'))->rules('required')\n            ->default(function ($form) {\n                return $form->model()->password;\n            });\n\n        $form->setAction(admin_url('auth/setting'));\n\n        $form->ignore(['password_confirmation']);\n\n        $form->saving(function (Form $form) {\n            if ($form->password && $form->model()->password != $form->password) {\n                $form->password = Hash::make($form->password);\n            }\n        });\n\n        $form->saved(function () {\n            admin_toastr(trans('admin.update_succeeded'));\n\n            return redirect(admin_url('auth/setting'));\n        });\n\n        return $form;\n    }\n\n    /**\n     * @return string|\\Symfony\\Component\\Translation\\TranslatorInterface\n     */\n    protected function getFailedLoginMessage()\n    {\n        return Lang::has('auth.failed')\n            ? trans('auth.failed')\n            : 'These credentials do not match our records.';\n    }\n\n    /**\n     * Get the post login redirect path.\n     *\n     * @return string\n     */\n    protected function redirectPath()\n    {\n        if (method_exists($this, 'redirectTo')) {\n            return $this->redirectTo();\n        }\n\n        return property_exists($this, 'redirectTo') ? $this->redirectTo : config('admin.route.prefix');\n    }\n\n    /**\n     * Send the response after the user was authenticated.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     *\n     * @return \\Illuminate\\Http\\RedirectResponse\n     */\n    protected function sendLoginResponse(Request $request)\n    {\n        admin_toastr(trans('admin.login_successful'));\n\n        $request->session()->regenerate();\n\n        return redirect()->intended($this->redirectPath());\n    }\n\n    /**\n     * Get the login username to be used by the controller.\n     *\n     * @return string\n     */\n    protected function username()\n    {\n        return 'username';\n    }\n\n    /**\n     * Get the guard to be used during authentication.\n     *\n     * @return \\Illuminate\\Contracts\\Auth\\StatefulGuard\n     */\n    protected function guard()\n    {\n        return Admin::guard();\n    }\n}\n"
  },
  {
    "path": "src/Controllers/Dashboard.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Controllers;\n\nuse Encore\\Admin\\Admin;\nuse Illuminate\\Support\\Arr;\n\nclass Dashboard\n{\n    /**\n     * @return \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View\n     */\n    public static function title()\n    {\n        return view('admin::dashboard.title');\n    }\n\n    /**\n     * @return \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View\n     */\n    public static function environment()\n    {\n        $envs = [\n            ['name' => 'PHP version',       'value' => 'PHP/'.PHP_VERSION],\n            ['name' => 'Laravel version',   'value' => app()->version()],\n            ['name' => 'CGI',               'value' => php_sapi_name()],\n            ['name' => 'Uname',             'value' => php_uname()],\n            ['name' => 'Server',            'value' => Arr::get($_SERVER, 'SERVER_SOFTWARE')],\n\n            ['name' => 'Cache driver',      'value' => config('cache.default')],\n            ['name' => 'Session driver',    'value' => config('session.driver')],\n            ['name' => 'Queue driver',      'value' => config('queue.default')],\n\n            ['name' => 'Timezone',          'value' => config('app.timezone')],\n            ['name' => 'Locale',            'value' => config('app.locale')],\n            ['name' => 'Env',               'value' => config('app.env')],\n            ['name' => 'URL',               'value' => config('app.url')],\n        ];\n\n        return view('admin::dashboard.environment', compact('envs'));\n    }\n\n    /**\n     * @return \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View\n     */\n    public static function extensions()\n    {\n        $extensions = [\n            'helpers' => [\n                'name' => 'laravel-admin-ext/helpers',\n                'link' => 'https://github.com/laravel-admin-extensions/helpers',\n                'icon' => 'gears',\n            ],\n            'log-viewer' => [\n                'name' => 'laravel-admin-ext/log-viewer',\n                'link' => 'https://github.com/laravel-admin-extensions/log-viewer',\n                'icon' => 'database',\n            ],\n            'backup' => [\n                'name' => 'laravel-admin-ext/backup',\n                'link' => 'https://github.com/laravel-admin-extensions/backup',\n                'icon' => 'copy',\n            ],\n            'config' => [\n                'name' => 'laravel-admin-ext/config',\n                'link' => 'https://github.com/laravel-admin-extensions/config',\n                'icon' => 'toggle-on',\n            ],\n            'api-tester' => [\n                'name' => 'laravel-admin-ext/api-tester',\n                'link' => 'https://github.com/laravel-admin-extensions/api-tester',\n                'icon' => 'sliders',\n            ],\n            'media-manager' => [\n                'name' => 'laravel-admin-ext/media-manager',\n                'link' => 'https://github.com/laravel-admin-extensions/media-manager',\n                'icon' => 'file',\n            ],\n            'scheduling' => [\n                'name' => 'laravel-admin-ext/scheduling',\n                'link' => 'https://github.com/laravel-admin-extensions/scheduling',\n                'icon' => 'clock-o',\n            ],\n            'reporter' => [\n                'name' => 'laravel-admin-ext/reporter',\n                'link' => 'https://github.com/laravel-admin-extensions/reporter',\n                'icon' => 'bug',\n            ],\n            'redis-manager' => [\n                'name' => 'laravel-admin-ext/redis-manager',\n                'link' => 'https://github.com/laravel-admin-extensions/redis-manager',\n                'icon' => 'flask',\n            ],\n        ];\n\n        foreach ($extensions as &$extension) {\n            $name = explode('/', $extension['name']);\n            $extension['installed'] = array_key_exists(end($name), Admin::$extensions);\n        }\n\n        return view('admin::dashboard.extensions', compact('extensions'));\n    }\n\n    /**\n     * @return \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View\n     */\n    public static function dependencies()\n    {\n        $json = file_get_contents(base_path('composer.json'));\n\n        $dependencies = json_decode($json, true)['require'];\n\n        return Admin::component('admin::dashboard.dependencies', compact('dependencies'));\n    }\n}\n"
  },
  {
    "path": "src/Controllers/HandleController.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Controllers;\n\nuse Encore\\Admin\\Actions\\Action;\nuse Encore\\Admin\\Actions\\GridAction;\nuse Encore\\Admin\\Actions\\Response;\nuse Encore\\Admin\\Actions\\RowAction;\nuse Encore\\Admin\\Widgets\\Form;\nuse Exception;\nuse Illuminate\\Contracts\\Support\\Renderable;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Routing\\Controller;\nuse Illuminate\\Support\\Collection;\n\nclass HandleController extends Controller\n{\n    /**\n     * @param Request $request\n     *\n     * @return $this|mixed\n     */\n    public function handleForm(Request $request)\n    {\n        $form = $this->resolveForm($request);\n\n        if ($errors = $form->validate($request)) {\n            return back()->withInput()->withErrors($errors);\n        }\n\n        return $form->sanitize()->handle($request);\n    }\n\n    /**\n     * @param Request $request\n     *\n     * @throws Exception\n     *\n     * @return Form\n     */\n    protected function resolveForm(Request $request)\n    {\n        if (!$request->has('_form_')) {\n            throw new Exception('Invalid form request.');\n        }\n\n        $formClass = $request->get('_form_');\n\n        if (!class_exists($formClass)) {\n            throw new Exception(\"Form [{$formClass}] does not exist.\");\n        }\n\n        /** @var Form $form */\n        $form = app($formClass);\n\n        if (!method_exists($form, 'handle')) {\n            throw new Exception(\"Form method {$formClass}::handle() does not exist.\");\n        }\n\n        return $form;\n    }\n\n    /**\n     * @param Request $request\n     *\n     * @return $this|\\Illuminate\\Http\\JsonResponse\n     */\n    public function handleAction(Request $request)\n    {\n        $action = $this->resolveActionInstance($request);\n\n        $model = null;\n        $arguments = [];\n\n        if ($action instanceof GridAction) {\n            $model = $action->retrieveModel($request);\n            $arguments[] = $model;\n        }\n\n        if (!$action->passesAuthorization($model)) {\n            return $action->failedAuthorization();\n        }\n\n        if ($action instanceof RowAction) {\n            $action->setRow($model);\n        }\n\n        try {\n            $response = $action->validate($request)->handle(\n                ...$this->resolveActionArgs($request, ...$arguments)\n            );\n        } catch (Exception $exception) {\n            return Response::withException($exception)->send();\n        }\n\n        if ($response instanceof Response) {\n            return $response->send();\n        }\n    }\n\n    /**\n     * @param Request $request\n     *\n     * @throws Exception\n     *\n     * @return Action\n     */\n    protected function resolveActionInstance(Request $request)\n    {\n        if (!$request->has('_action')) {\n            throw new Exception('Invalid action request.');\n        }\n\n        $actionClass = str_replace('_', '\\\\', $request->get('_action'));\n\n        if (!class_exists($actionClass)) {\n            throw new Exception(\"Form [{$actionClass}] does not exist.\");\n        }\n\n        /** @var GridAction $form */\n        $action = app($actionClass);\n\n        if (!method_exists($action, 'handle')) {\n            throw new Exception(\"Action method {$actionClass}::handle() does not exist.\");\n        }\n\n        return $action;\n    }\n\n    /**\n     * @param Request               $request\n     * @param Model|Collection|bool $model\n     *\n     * @return array\n     */\n    protected function resolveActionArgs(Request $request, $model = null)\n    {\n        $args = [$request];\n\n        if (!empty($model)) {\n            array_unshift($args, $model);\n        }\n\n        return $args;\n    }\n\n    /**\n     * @param Request $request\n     *\n     * @return mixed|string|string[]\n     */\n    public function handleSelectable(Request $request)\n    {\n        $class = $request->get('selectable');\n        $args = $request->get('args', []);\n\n        $class = str_replace('_', '\\\\', $class);\n\n        if (class_exists($class)) {\n            /** @var \\Encore\\Admin\\Grid\\Selectable $selectable */\n            $selectable = new $class(...array_values($args));\n\n            return $selectable->render();\n        }\n\n        return $class;\n    }\n\n    /**\n     * @param Request $request\n     *\n     * @return mixed|string|string[]\n     */\n    public function handleRenderable(Request $request)\n    {\n        $class = $request->get('renderable');\n        $key = $request->get('key');\n\n        $class = str_replace('_', '\\\\', $class);\n\n        if (class_exists($class)) {\n            /** @var Renderable $selectable */\n            $renderable = new $class();\n\n            return $renderable->render($key);\n        }\n\n        return $class;\n    }\n}\n"
  },
  {
    "path": "src/Controllers/HasResourceActions.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Controllers;\n\ntrait HasResourceActions\n{\n    /**\n     * Update the specified resource in storage.\n     *\n     * @param int $id\n     *\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function update($id)\n    {\n        return $this->form()->update($id);\n    }\n\n    /**\n     * Store a newly created resource in storage.\n     *\n     * @return mixed\n     */\n    public function store()\n    {\n        return $this->form()->store();\n    }\n\n    /**\n     * Remove the specified resource from storage.\n     *\n     * @param int $id\n     *\n     * @return \\Illuminate\\Http\\Response\n     */\n    public function destroy($id)\n    {\n        return $this->form()->destroy($id);\n    }\n}\n"
  },
  {
    "path": "src/Controllers/LogController.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Controllers;\n\nuse Encore\\Admin\\Auth\\Database\\OperationLog;\nuse Encore\\Admin\\Grid;\nuse Illuminate\\Support\\Arr;\n\nclass LogController extends AdminController\n{\n    /**\n     * {@inheritdoc}\n     */\n    protected function title()\n    {\n        return trans('admin.operation_log');\n    }\n\n    /**\n     * @return Grid\n     */\n    protected function grid()\n    {\n        $grid = new Grid(new OperationLog());\n\n        $grid->model()->orderBy('id', 'DESC');\n\n        $grid->column('id', 'ID')->sortable();\n        $grid->column('user.name', 'User');\n        $grid->column('method')->display(function ($method) {\n            $color = Arr::get(OperationLog::$methodColors, $method, 'grey');\n\n            return \"<span class=\\\"badge bg-$color\\\">$method</span>\";\n        });\n        $grid->column('path')->label('info');\n        $grid->column('ip')->label('primary');\n        $grid->column('input')->display(function ($input) {\n            $input = json_decode($input, true);\n            $input = Arr::except($input, ['_pjax', '_token', '_method', '_previous_']);\n            if (empty($input)) {\n                return '<code>{}</code>';\n            }\n\n            return '<pre>'.json_encode($input, JSON_PRETTY_PRINT | JSON_HEX_TAG).'</pre>';\n        });\n\n        $grid->column('created_at', trans('admin.created_at'));\n\n        $grid->actions(function (Grid\\Displayers\\Actions $actions) {\n            $actions->disableEdit();\n            $actions->disableView();\n        });\n\n        $grid->disableCreateButton();\n\n        $grid->filter(function (Grid\\Filter $filter) {\n            $userModel = config('admin.database.users_model');\n\n            $filter->equal('user_id', 'User')->select($userModel::all()->pluck('name', 'id'));\n            $filter->equal('method')->select(array_combine(OperationLog::$methods, OperationLog::$methods));\n            $filter->like('path');\n            $filter->equal('ip');\n        });\n\n        return $grid;\n    }\n\n    /**\n     * @param mixed $id\n     *\n     * @return \\Illuminate\\Http\\JsonResponse\n     */\n    public function destroy($id)\n    {\n        $ids = explode(',', $id);\n\n        if (OperationLog::destroy(array_filter($ids))) {\n            $data = [\n                'status'  => true,\n                'message' => trans('admin.delete_succeeded'),\n            ];\n        } else {\n            $data = [\n                'status'  => false,\n                'message' => trans('admin.delete_failed'),\n            ];\n        }\n\n        return response()->json($data);\n    }\n}\n"
  },
  {
    "path": "src/Controllers/MenuController.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Controllers;\n\nuse Encore\\Admin\\Form;\nuse Encore\\Admin\\Layout\\Column;\nuse Encore\\Admin\\Layout\\Content;\nuse Encore\\Admin\\Layout\\Row;\nuse Encore\\Admin\\Tree;\nuse Encore\\Admin\\Widgets\\Box;\nuse Illuminate\\Routing\\Controller;\n\nclass MenuController extends Controller\n{\n    use HasResourceActions;\n\n    /**\n     * Index interface.\n     *\n     * @param Content $content\n     *\n     * @return Content\n     */\n    public function index(Content $content)\n    {\n        return $content\n            ->title(trans('admin.menu'))\n            ->description(trans('admin.list'))\n            ->row(function (Row $row) {\n                $row->column(6, $this->treeView()->render());\n\n                $row->column(6, function (Column $column) {\n                    $form = new \\Encore\\Admin\\Widgets\\Form();\n                    $form->action(admin_url('auth/menu'));\n\n                    $menuModel = config('admin.database.menu_model');\n                    $permissionModel = config('admin.database.permissions_model');\n                    $roleModel = config('admin.database.roles_model');\n\n                    $form->select('parent_id', trans('admin.parent_id'))->options($menuModel::selectOptions());\n                    $form->text('title', trans('admin.title'))->rules('required');\n                    $form->icon('icon', trans('admin.icon'))->default('fa-bars')->rules('required')->help($this->iconHelp());\n                    $form->text('uri', trans('admin.uri'));\n                    $form->multipleSelect('roles', trans('admin.roles'))->options($roleModel::all()->pluck('name', 'id'));\n                    if ((new $menuModel())->withPermission()) {\n                        $form->select('permission', trans('admin.permission'))->options($permissionModel::pluck('name', 'slug'));\n                    }\n                    $form->hidden('_token')->default(csrf_token());\n\n                    $column->append((new Box(trans('admin.new'), $form))->style('success'));\n                });\n            });\n    }\n\n    /**\n     * Redirect to edit page.\n     *\n     * @param int $id\n     *\n     * @return \\Illuminate\\Http\\RedirectResponse\n     */\n    public function show($id)\n    {\n        return redirect()->route('admin.auth.menu.edit', ['menu' => $id]);\n    }\n\n    /**\n     * @return \\Encore\\Admin\\Tree\n     */\n    protected function treeView()\n    {\n        $menuModel = config('admin.database.menu_model');\n\n        $tree = new Tree(new $menuModel());\n\n        $tree->disableCreate();\n\n        $tree->branch(function ($branch) {\n            $payload = \"<i class='fa {$branch['icon']}'></i>&nbsp;<strong>{$branch['title']}</strong>\";\n\n            if (!isset($branch['children'])) {\n                if (url()->isValidUrl($branch['uri'])) {\n                    $uri = $branch['uri'];\n                } else {\n                    $uri = admin_url($branch['uri']);\n                }\n\n                $payload .= \"&nbsp;&nbsp;&nbsp;<a href=\\\"$uri\\\" class=\\\"dd-nodrag\\\">$uri</a>\";\n            }\n\n            return $payload;\n        });\n\n        return $tree;\n    }\n\n    /**\n     * Edit interface.\n     *\n     * @param string  $id\n     * @param Content $content\n     *\n     * @return Content\n     */\n    public function edit($id, Content $content)\n    {\n        return $content\n            ->title(trans('admin.menu'))\n            ->description(trans('admin.edit'))\n            ->row($this->form()->edit($id));\n    }\n\n    /**\n     * Make a form builder.\n     *\n     * @return Form\n     */\n    public function form()\n    {\n        $menuModel = config('admin.database.menu_model');\n        $permissionModel = config('admin.database.permissions_model');\n        $roleModel = config('admin.database.roles_model');\n\n        $form = new Form(new $menuModel());\n\n        $form->display('id', 'ID');\n\n        $form->select('parent_id', trans('admin.parent_id'))->options($menuModel::selectOptions());\n        $form->text('title', trans('admin.title'))->rules('required');\n        $form->icon('icon', trans('admin.icon'))->default('fa-bars')->rules('required')->help($this->iconHelp());\n        $form->text('uri', trans('admin.uri'));\n        $form->multipleSelect('roles', trans('admin.roles'))->options($roleModel::all()->pluck('name', 'id'));\n        if ($form->model()->withPermission()) {\n            $form->select('permission', trans('admin.permission'))->options($permissionModel::pluck('name', 'slug'));\n        }\n\n        $form->display('created_at', trans('admin.created_at'));\n        $form->display('updated_at', trans('admin.updated_at'));\n\n        return $form;\n    }\n\n    /**\n     * Help message for icon field.\n     *\n     * @return string\n     */\n    protected function iconHelp()\n    {\n        return 'For more icons please see <a href=\"http://fontawesome.io/icons/\" target=\"_blank\">http://fontawesome.io/icons/</a>';\n    }\n}\n"
  },
  {
    "path": "src/Controllers/ModelForm.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Controllers;\n\n/**\n * Trait ModelForm.\n *\n * @deprecated Use `HasResourceActions` instead.\n */\ntrait ModelForm\n{\n    use HasResourceActions;\n}\n"
  },
  {
    "path": "src/Controllers/PermissionController.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Controllers;\n\nuse Encore\\Admin\\Form;\nuse Encore\\Admin\\Grid;\nuse Encore\\Admin\\Show;\nuse Illuminate\\Support\\Str;\n\nclass PermissionController extends AdminController\n{\n    /**\n     * {@inheritdoc}\n     */\n    protected function title()\n    {\n        return trans('admin.permissions');\n    }\n\n    /**\n     * Make a grid builder.\n     *\n     * @return Grid\n     */\n    protected function grid()\n    {\n        $permissionModel = config('admin.database.permissions_model');\n\n        $grid = new Grid(new $permissionModel());\n\n        $grid->column('id', 'ID')->sortable();\n        $grid->column('slug', trans('admin.slug'));\n        $grid->column('name', trans('admin.name'));\n\n        $grid->column('http_path', trans('admin.route'))->display(function ($path) {\n            return collect(explode(\"\\n\", $path))->map(function ($path) {\n                $method = $this->http_method ?: ['ANY'];\n\n                if (Str::contains($path, ':')) {\n                    list($method, $path) = explode(':', $path);\n                    $method = explode(',', $method);\n                }\n\n                $method = collect($method)->map(function ($name) {\n                    return strtoupper($name);\n                })->map(function ($name) {\n                    return \"<span class='label label-primary'>{$name}</span>\";\n                })->implode('&nbsp;');\n\n                if (!empty(config('admin.route.prefix'))) {\n                    $path = '/'.trim(config('admin.route.prefix'), '/').$path;\n                }\n\n                return \"<div style='margin-bottom: 5px;'>$method<code>$path</code></div>\";\n            })->implode('');\n        });\n\n        $grid->column('created_at', trans('admin.created_at'));\n        $grid->column('updated_at', trans('admin.updated_at'));\n\n        $grid->tools(function (Grid\\Tools $tools) {\n            $tools->batch(function (Grid\\Tools\\BatchActions $actions) {\n                $actions->disableDelete();\n            });\n        });\n\n        return $grid;\n    }\n\n    /**\n     * Make a show builder.\n     *\n     * @param mixed $id\n     *\n     * @return Show\n     */\n    protected function detail($id)\n    {\n        $permissionModel = config('admin.database.permissions_model');\n\n        $show = new Show($permissionModel::findOrFail($id));\n\n        $show->field('id', 'ID');\n        $show->field('slug', trans('admin.slug'));\n        $show->field('name', trans('admin.name'));\n\n        $show->field('http_path', trans('admin.route'))->unescape()->as(function ($path) {\n            return collect(explode(\"\\r\\n\", $path))->map(function ($path) {\n                $method = $this->http_method ?: ['ANY'];\n\n                if (Str::contains($path, ':')) {\n                    list($method, $path) = explode(':', $path);\n                    $method = explode(',', $method);\n                }\n\n                $method = collect($method)->map(function ($name) {\n                    return strtoupper($name);\n                })->map(function ($name) {\n                    return \"<span class='label label-primary'>{$name}</span>\";\n                })->implode('&nbsp;');\n\n                if (!empty(config('admin.route.prefix'))) {\n                    $path = '/'.trim(config('admin.route.prefix'), '/').$path;\n                }\n\n                return \"<div style='margin-bottom: 5px;'>$method<code>$path</code></div>\";\n            })->implode('');\n        });\n\n        $show->field('created_at', trans('admin.created_at'));\n        $show->field('updated_at', trans('admin.updated_at'));\n\n        return $show;\n    }\n\n    /**\n     * Make a form builder.\n     *\n     * @return Form\n     */\n    public function form()\n    {\n        $permissionModel = config('admin.database.permissions_model');\n\n        $form = new Form(new $permissionModel());\n\n        $form->display('id', 'ID');\n\n        $form->text('slug', trans('admin.slug'))->rules('required');\n        $form->text('name', trans('admin.name'))->rules('required');\n\n        $form->multipleSelect('http_method', trans('admin.http.method'))\n            ->options($this->getHttpMethodsOptions())\n            ->help(trans('admin.all_methods_if_empty'));\n        $form->textarea('http_path', trans('admin.http.path'));\n\n        $form->display('created_at', trans('admin.created_at'));\n        $form->display('updated_at', trans('admin.updated_at'));\n\n        return $form;\n    }\n\n    /**\n     * Get options of HTTP methods select field.\n     *\n     * @return array\n     */\n    protected function getHttpMethodsOptions()\n    {\n        $model = config('admin.database.permissions_model');\n\n        return array_combine($model::$httpMethods, $model::$httpMethods);\n    }\n}\n"
  },
  {
    "path": "src/Controllers/RoleController.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Controllers;\n\nuse Encore\\Admin\\Form;\nuse Encore\\Admin\\Grid;\nuse Encore\\Admin\\Show;\n\nclass RoleController extends AdminController\n{\n    /**\n     * {@inheritdoc}\n     */\n    protected function title()\n    {\n        return trans('admin.roles');\n    }\n\n    /**\n     * Make a grid builder.\n     *\n     * @return Grid\n     */\n    protected function grid()\n    {\n        $roleModel = config('admin.database.roles_model');\n\n        $grid = new Grid(new $roleModel());\n\n        $grid->column('id', 'ID')->sortable();\n        $grid->column('slug', trans('admin.slug'));\n        $grid->column('name', trans('admin.name'));\n\n        $grid->column('permissions', trans('admin.permission'))->pluck('name')->label();\n\n        $grid->column('created_at', trans('admin.created_at'));\n        $grid->column('updated_at', trans('admin.updated_at'));\n\n        $grid->actions(function (Grid\\Displayers\\Actions $actions) {\n            if ($actions->row->slug == 'administrator') {\n                $actions->disableDelete();\n            }\n        });\n\n        $grid->tools(function (Grid\\Tools $tools) {\n            $tools->batch(function (Grid\\Tools\\BatchActions $actions) {\n                $actions->disableDelete();\n            });\n        });\n\n        return $grid;\n    }\n\n    /**\n     * Make a show builder.\n     *\n     * @param mixed $id\n     *\n     * @return Show\n     */\n    protected function detail($id)\n    {\n        $roleModel = config('admin.database.roles_model');\n\n        $show = new Show($roleModel::findOrFail($id));\n\n        $show->field('id', 'ID');\n        $show->field('slug', trans('admin.slug'));\n        $show->field('name', trans('admin.name'));\n        $show->field('permissions', trans('admin.permissions'))->as(function ($permission) {\n            return $permission->pluck('name');\n        })->label();\n        $show->field('created_at', trans('admin.created_at'));\n        $show->field('updated_at', trans('admin.updated_at'));\n\n        return $show;\n    }\n\n    /**\n     * Make a form builder.\n     *\n     * @return Form\n     */\n    public function form()\n    {\n        $permissionModel = config('admin.database.permissions_model');\n        $roleModel = config('admin.database.roles_model');\n\n        $form = new Form(new $roleModel());\n\n        $form->display('id', 'ID');\n\n        $form->text('slug', trans('admin.slug'))->rules('required');\n        $form->text('name', trans('admin.name'))->rules('required');\n        $form->listbox('permissions', trans('admin.permissions'))->options($permissionModel::all()->pluck('name', 'id'));\n\n        $form->display('created_at', trans('admin.created_at'));\n        $form->display('updated_at', trans('admin.updated_at'));\n\n        return $form;\n    }\n}\n"
  },
  {
    "path": "src/Controllers/UserController.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Controllers;\n\nuse Encore\\Admin\\Form;\nuse Encore\\Admin\\Grid;\nuse Encore\\Admin\\Show;\nuse Illuminate\\Support\\Facades\\Hash;\n\nclass UserController extends AdminController\n{\n    /**\n     * {@inheritdoc}\n     */\n    protected function title()\n    {\n        return trans('admin.administrator');\n    }\n\n    /**\n     * Make a grid builder.\n     *\n     * @return Grid\n     */\n    protected function grid()\n    {\n        $userModel = config('admin.database.users_model');\n\n        $grid = new Grid(new $userModel());\n\n        $grid->column('id', 'ID')->sortable();\n        $grid->column('username', trans('admin.username'));\n        $grid->column('name', trans('admin.name'));\n        $grid->column('roles', trans('admin.roles'))->pluck('name')->label();\n        $grid->column('created_at', trans('admin.created_at'));\n        $grid->column('updated_at', trans('admin.updated_at'));\n\n        $grid->actions(function (Grid\\Displayers\\Actions $actions) {\n            if ($actions->getKey() == 1) {\n                $actions->disableDelete();\n            }\n        });\n\n        $grid->tools(function (Grid\\Tools $tools) {\n            $tools->batch(function (Grid\\Tools\\BatchActions $actions) {\n                $actions->disableDelete();\n            });\n        });\n\n        return $grid;\n    }\n\n    /**\n     * Make a show builder.\n     *\n     * @param mixed $id\n     *\n     * @return Show\n     */\n    protected function detail($id)\n    {\n        $userModel = config('admin.database.users_model');\n\n        $show = new Show($userModel::findOrFail($id));\n\n        $show->field('id', 'ID');\n        $show->field('username', trans('admin.username'));\n        $show->field('name', trans('admin.name'));\n        $show->field('roles', trans('admin.roles'))->as(function ($roles) {\n            return $roles->pluck('name');\n        })->label();\n        $show->field('permissions', trans('admin.permissions'))->as(function ($permission) {\n            return $permission->pluck('name');\n        })->label();\n        $show->field('created_at', trans('admin.created_at'));\n        $show->field('updated_at', trans('admin.updated_at'));\n\n        return $show;\n    }\n\n    /**\n     * Make a form builder.\n     *\n     * @return Form\n     */\n    public function form()\n    {\n        $userModel = config('admin.database.users_model');\n        $permissionModel = config('admin.database.permissions_model');\n        $roleModel = config('admin.database.roles_model');\n\n        $form = new Form(new $userModel());\n\n        $userTable = config('admin.database.users_table');\n        $connection = config('admin.database.connection');\n\n        $form->display('id', 'ID');\n        $form->text('username', trans('admin.username'))\n            ->creationRules(['required', \"unique:{$connection}.{$userTable}\"])\n            ->updateRules(['required', \"unique:{$connection}.{$userTable},username,{{id}}\"]);\n\n        $form->text('name', trans('admin.name'))->rules('required');\n        $form->image('avatar', trans('admin.avatar'));\n        $form->password('password', trans('admin.password'))->rules('required|confirmed');\n        $form->password('password_confirmation', trans('admin.password_confirmation'))->rules('required')\n            ->default(function ($form) {\n                return $form->model()->password;\n            });\n\n        $form->ignore(['password_confirmation']);\n\n        $form->multipleSelect('roles', trans('admin.roles'))->options($roleModel::all()->pluck('name', 'id'));\n        $form->multipleSelect('permissions', trans('admin.permissions'))->options($permissionModel::all()->pluck('name', 'id'));\n\n        $form->display('created_at', trans('admin.created_at'));\n        $form->display('updated_at', trans('admin.updated_at'));\n\n        $form->saving(function (Form $form) {\n            if ($form->password && $form->model()->password != $form->password) {\n                $form->password = Hash::make($form->password);\n            }\n        });\n\n        return $form;\n    }\n}\n"
  },
  {
    "path": "src/Exception/Handler.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Exception;\n\nuse Illuminate\\Support\\MessageBag;\nuse Illuminate\\Support\\ViewErrorBag;\n\nclass Handler\n{\n    /**\n     * Render exception.\n     *\n     * @param \\Exception $exception\n     *\n     * @return string\n     */\n    public static function renderException(\\Exception $exception)\n    {\n        $error = new MessageBag([\n            'type'    => get_class($exception),\n            'message' => $exception->getMessage(),\n            'file'    => $exception->getFile(),\n            'line'    => $exception->getLine(),\n            'trace'   => $exception->getTraceAsString(),\n        ]);\n\n        $errors = new ViewErrorBag();\n        $errors->put('exception', $error);\n\n        return view('admin::partials.exception', compact('errors'))->render();\n    }\n\n    /**\n     * Flash a error message to content.\n     *\n     * @param string $title\n     * @param string $message\n     *\n     * @return mixed\n     */\n    public static function error($title = '', $message = '')\n    {\n        $error = new MessageBag(compact('title', 'message'));\n\n        return session()->flash('error', $error);\n    }\n}\n"
  },
  {
    "path": "src/Extension.php",
    "content": "<?php\n\nnamespace Encore\\Admin;\n\nuse Encore\\Admin\\Auth\\Database\\Permission;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Facades\\Config;\nuse Illuminate\\Support\\Facades\\DB;\nuse Illuminate\\Support\\Facades\\Route;\nuse Illuminate\\Support\\Facades\\Validator;\nuse Illuminate\\Validation\\Rule;\n\nabstract class Extension\n{\n    /**\n     * @var string\n     */\n    protected $name;\n\n    /**\n     * @var array\n     */\n    public $css = [];\n\n    /**\n     * @var array\n     */\n    public $js = [];\n\n    /**\n     * @var string\n     */\n    public $assets = '';\n\n    /**\n     * @var string\n     */\n    public $views = '';\n\n    /**\n     * @var string\n     */\n    public $migrations = '';\n\n    /**\n     * @var array\n     */\n    public $menu = [];\n\n    /**\n     * @var array\n     */\n    public $permission = [];\n\n    /**\n     * Extension instance.\n     *\n     * @var Extension\n     */\n    protected static $instance;\n\n    /**\n     * The menu validation rules.\n     *\n     * @var array\n     */\n    protected $menuValidationRules = [\n        'title'    => 'required',\n        'path'     => 'required',\n        'icon'     => 'required',\n        'children' => 'nullable|array',\n    ];\n\n    /**\n     * The permission validation rules.\n     *\n     * @var array\n     */\n    protected $permissionValidationRules = [\n        'name'  => 'required',\n        'slug'  => 'required',\n        'path'  => 'required',\n    ];\n\n    /**\n     * Returns the singleton instance.\n     *\n     * @return self\n     */\n    protected static function getInstance()\n    {\n        $class = get_called_class();\n\n        if (!isset(self::$instance[$class]) || !self::$instance[$class] instanceof $class) {\n            self::$instance[$class] = new static();\n        }\n\n        return static::$instance[$class];\n    }\n\n    /**\n     * Bootstrap this extension.\n     */\n    public static function boot()\n    {\n        $extension = static::getInstance();\n\n        Admin::extend($extension->name, get_called_class());\n\n        if ($extension->disabled()) {\n            return false;\n        }\n\n        if (!empty($css = $extension->css())) {\n            Admin::css($css);\n        }\n\n        if (!empty($js = $extension->js())) {\n            Admin::js($js);\n        }\n\n        return true;\n    }\n\n    /**\n     * Get the path of assets files.\n     *\n     * @return string\n     */\n    public function assets()\n    {\n        return $this->assets;\n    }\n\n    /**\n     * Get the paths of css files.\n     *\n     * @return array\n     */\n    public function css()\n    {\n        return $this->css;\n    }\n\n    /**\n     * Get the paths of js files.\n     *\n     * @return array\n     */\n    public function js()\n    {\n        return $this->js;\n    }\n\n    /**\n     * Get the path of view files.\n     *\n     * @return string\n     */\n    public function views()\n    {\n        return $this->views;\n    }\n\n    /**\n     * Get the path of migration files.\n     *\n     * @return string\n     */\n    public function migrations()\n    {\n        return $this->migrations;\n    }\n\n    /**\n     * @return array\n     */\n    public function menu()\n    {\n        return $this->menu;\n    }\n\n    /**\n     * @return array\n     */\n    public function permission()\n    {\n        return $this->permission;\n    }\n\n    /**\n     * Whether the extension is enabled.\n     *\n     * @return bool\n     */\n    public function enabled()\n    {\n        return static::config('enable') !== false;\n    }\n\n    /**\n     * Whether the extension is disabled.\n     *\n     * @return bool\n     */\n    public function disabled()\n    {\n        return !$this->enabled();\n    }\n\n    /**\n     * Get config set in config/admin.php.\n     *\n     * @param string $key\n     * @param null   $default\n     *\n     * @return \\Illuminate\\Config\\Repository|mixed\n     */\n    public static function config($key = null, $default = null)\n    {\n        $name = array_search(get_called_class(), Admin::$extensions);\n\n        if (is_null($key)) {\n            $key = sprintf('admin.extensions.%s', strtolower($name));\n        } else {\n            $key = sprintf('admin.extensions.%s.%s', strtolower($name), $key);\n        }\n\n        return config($key, $default);\n    }\n\n    /**\n     * Import menu item and permission to laravel-admin.\n     */\n    public static function import()\n    {\n        $extension = static::getInstance();\n        DB::transaction(function () use ($extension) {\n            if ($menu = $extension->menu()) {\n                if ($extension->validateMenu($menu)) {\n                    extract($menu);\n                    $children = Arr::get($menu, 'children', []);\n                    static::createMenu($title, $path, $icon, 0, $children);\n                }\n            }\n            if ($permission = $extension->permission()) {\n                $name = Arr::get($permission, 'name', null);\n                if (null !== $name) {\n                    $permission = [$permission];\n                }\n                foreach ($permission as $item) {\n                    if ($extension->validatePermission($item)) {\n                        $method = [];\n                        extract($item);\n                        static::createPermission($name, $slug, implode(\"\\r\\n\", $path), $method);\n                    }\n                }\n            }\n        });\n    }\n\n    /**\n     * Validate menu fields.\n     *\n     * @param array $menu\n     *\n     * @throws \\Exception\n     *\n     * @return bool\n     */\n    public function validateMenu(array $menu)\n    {\n        /** @var \\Illuminate\\Validation\\Validator $validator */\n        $validator = Validator::make($menu, $this->getMenuValidationRules());\n\n        if ($validator->passes()) {\n            return true;\n        }\n\n        $message = \"Invalid menu:\\r\\n\".implode(\"\\r\\n\", Arr::flatten($validator->errors()->messages()));\n\n        throw new \\Exception($message);\n    }\n\n    /**\n     * Get menu validation rules.\n     *\n     * @return array\n     */\n    protected function getMenuValidationRules()\n    {\n        return [\n            'title'    => 'required',\n            'path'     => ['required', Rule::unique(Config::get('admin.database.menu_table'), 'uri')],\n            'icon'     => 'required',\n            'children' => 'nullable|array',\n        ];\n    }\n\n    /**\n     * Validate permission fields.\n     *\n     * @param array $permission\n     *\n     * @throws \\Exception\n     *\n     * @return bool\n     */\n    public function validatePermission(array $permission)\n    {\n        if (!empty($permission['method'])) {\n            $permission['method'] = array_map('strtoupper', $permission['method']);\n        }\n\n        /** @var \\Illuminate\\Validation\\Validator $validator */\n        $validator = Validator::make($permission, $this->getPermissionValidationRules());\n\n        if ($validator->passes()) {\n            return true;\n        }\n\n        $message = \"Invalid permission:\\r\\n\".implode(\"\\r\\n\", Arr::flatten($validator->errors()->messages()));\n\n        throw new \\Exception($message);\n    }\n\n    /**\n     * Get permission validation rules.\n     *\n     * @return array\n     */\n    protected function getPermissionValidationRules()\n    {\n        return [\n            'name'     => 'required',\n            'slug'     => ['required', Rule::unique(Config::get('admin.database.permissions_table'), 'slug')],\n            'path'     => 'required|array',\n            'path.*'   => 'string',\n            'method'   => 'nullable|array',\n            'method.*' => ['string', Rule::in(Permission::$httpMethods)],\n        ];\n    }\n\n    /**\n     * Create a item in laravel-admin left side menu.\n     *\n     * @param string $title\n     * @param string $uri\n     * @param string $icon\n     * @param int    $parentId\n     * @param array  $children\n     *\n     * @throws \\Exception\n     *\n     * @return Model\n     */\n    protected static function createMenu($title, $uri, $icon = 'fa-bars', $parentId = 0, array $children = [])\n    {\n        $menuModel = config('admin.database.menu_model');\n\n        $lastOrder = $menuModel::max('order');\n        /**\n         * @var Model\n         */\n        $menu = $menuModel::create([\n            'parent_id' => $parentId,\n            'order'     => $lastOrder + 1,\n            'title'     => $title,\n            'icon'      => $icon,\n            'uri'       => $uri,\n        ]);\n        if (!empty($children)) {\n            $extension = static::getInstance();\n            foreach ($children as $child) {\n                if ($extension->validateMenu($child)) {\n                    $subTitle = Arr::get($child, 'title');\n                    $subUri = Arr::get($child, 'path');\n                    $subIcon = Arr::get($child, 'icon');\n                    $subChildren = Arr::get($child, 'children', []);\n                    static::createMenu($subTitle, $subUri, $subIcon, $menu->getKey(), $subChildren);\n                }\n            }\n        }\n\n        return $menu;\n    }\n\n    /**\n     * Create a permission for this extension.\n     *\n     * @param       $name\n     * @param       $slug\n     * @param       $path\n     * @param array $methods\n     */\n    protected static function createPermission($name, $slug, $path, $methods = [])\n    {\n        $permissionModel = config('admin.database.permissions_model');\n\n        $permissionModel::create([\n            'name'        => $name,\n            'slug'        => $slug,\n            'http_path'   => '/'.trim($path, '/'),\n            'http_method' => $methods,\n        ]);\n    }\n\n    /**\n     * Set routes for this extension.\n     *\n     * @param $callback\n     */\n    public static function routes($callback)\n    {\n        $attributes = array_merge(\n            [\n                'prefix'     => config('admin.route.prefix'),\n                'middleware' => config('admin.route.middleware'),\n            ],\n            static::config('route', [])\n        );\n\n        Route::group($attributes, $callback);\n    }\n}\n"
  },
  {
    "path": "src/Facades/Admin.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Facades;\n\nuse Illuminate\\Support\\Facades\\Facade;\n\n/**\n * Class Admin.\n *\n * @method static \\Encore\\Admin\\Grid grid($model, \\Closure $callable)\n * @method static \\Encore\\Admin\\Form form($model, \\Closure $callable)\n * @method static \\Encore\\Admin\\Show show($model, $callable = null)\n * @method static \\Encore\\Admin\\Tree tree($model, \\Closure $callable = null)\n * @method static \\Encore\\Admin\\Layout\\Content content(\\Closure $callable = null)\n * @method static \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View|void css($css = null)\n * @method static \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View|void js($js = null)\n * @method static \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View|void headerJs($js = null)\n * @method static \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View|void script($script = '')\n * @method static \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View|void style($style = '')\n * @method static \\Illuminate\\Contracts\\Auth\\Authenticatable|null user()\n * @method static \\Illuminate\\Contracts\\Auth\\Guard|\\Illuminate\\Contracts\\Auth\\StatefulGuard guard()\n * @method static string title()\n * @method static void navbar(\\Closure $builder = null)\n * @method static void registerAuthRoutes()\n * @method static void extend($name, $class)\n * @method static void disablePjax()\n * @method static void booting(\\Closure $builder)\n * @method static void booted(\\Closure $builder)\n * @method static void bootstrap()\n * @method static void routes()\n *\n * @see \\Encore\\Admin\\Admin\n */\nclass Admin extends Facade\n{\n    protected static function getFacadeAccessor()\n    {\n        return \\Encore\\Admin\\Admin::class;\n    }\n}\n"
  },
  {
    "path": "src/Form/Builder.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form;\n\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Form;\nuse Encore\\Admin\\Form\\Field\\Hidden;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Support\\Facades\\URL;\nuse Illuminate\\Support\\Str;\n\n/**\n * Class Builder.\n */\nclass Builder\n{\n    /**\n     *  Previous url key.\n     */\n    const PREVIOUS_URL_KEY = '_previous_';\n\n    /**\n     * @var mixed\n     */\n    protected $id;\n\n    /**\n     * @var Form\n     */\n    protected $form;\n\n    /**\n     * @var\n     */\n    protected $action;\n\n    /**\n     * @var Collection\n     */\n    protected $fields;\n\n    /**\n     * @var array\n     */\n    protected $options = [];\n\n    /**\n     * Modes constants.\n     */\n    const MODE_EDIT = 'edit';\n    const MODE_CREATE = 'create';\n\n    /**\n     * Form action mode, could be create|view|edit.\n     *\n     * @var string\n     */\n    protected $mode = 'create';\n\n    /**\n     * @var array\n     */\n    protected $hiddenFields = [];\n\n    /**\n     * @var Tools\n     */\n    protected $tools;\n\n    /**\n     * @var Footer\n     */\n    protected $footer;\n\n    /**\n     * Width for label and field.\n     *\n     * @var array\n     */\n    protected $width = [\n        'label' => 2,\n        'field' => 8,\n    ];\n\n    /**\n     * View for this form.\n     *\n     * @var string\n     */\n    protected $view = 'admin::form';\n\n    /**\n     * Form title.\n     *\n     * @var string\n     */\n    protected $title;\n\n    /**\n     * @var string\n     */\n    protected $formClass;\n\n    /**\n     * Builder constructor.\n     *\n     * @param Form $form\n     *\n     * @return void\n     */\n    public function __construct(Form $form)\n    {\n        $this->form = $form;\n\n        $this->fields = new Collection();\n\n        $this->init();\n    }\n\n    /**\n     * Do initialize.\n     *\n     * @return void\n     */\n    public function init()\n    {\n        $this->tools = new Tools($this);\n        $this->footer = new Footer($this);\n\n        $this->formClass = 'model-form-'.uniqid();\n    }\n\n    /**\n     * Get form tools instance.\n     *\n     * @return Tools\n     */\n    public function getTools()\n    {\n        return $this->tools;\n    }\n\n    /**\n     * Get form footer instance.\n     *\n     * @return Footer\n     */\n    public function getFooter()\n    {\n        return $this->footer;\n    }\n\n    /**\n     * Set the builder mode.\n     *\n     * @param string $mode\n     *\n     * @return void\n     */\n    public function setMode($mode = 'create')\n    {\n        $this->mode = $mode;\n    }\n\n    /**\n     * @return string\n     */\n    public function getMode(): string\n    {\n        return $this->mode;\n    }\n\n    /**\n     * Returns builder is $mode.\n     *\n     * @param string $mode\n     *\n     * @return bool\n     */\n    public function isMode($mode): bool\n    {\n        return $this->mode === $mode;\n    }\n\n    /**\n     * Check if is creating resource.\n     *\n     * @return bool\n     */\n    public function isCreating(): bool\n    {\n        return $this->isMode(static::MODE_CREATE);\n    }\n\n    /**\n     * Check if is editing resource.\n     *\n     * @return bool\n     */\n    public function isEditing(): bool\n    {\n        return $this->isMode(static::MODE_EDIT);\n    }\n\n    /**\n     * Set resource Id.\n     *\n     * @param mixed $id\n     *\n     * @return void\n     */\n    public function setResourceId($id)\n    {\n        $this->id = $id;\n    }\n\n    /**\n     * Get Resource id.\n     *\n     * @return mixed\n     */\n    public function getResourceId()\n    {\n        return $this->id;\n    }\n\n    /**\n     * @param int|null $slice\n     *\n     * @return string\n     */\n    public function getResource(int $slice = null): string\n    {\n        if ($this->mode === self::MODE_CREATE) {\n            return $this->form->resource(-1);\n        }\n        if ($slice !== null) {\n            return $this->form->resource($slice);\n        }\n\n        return $this->form->resource();\n    }\n\n    /**\n     * @param int $field\n     * @param int $label\n     *\n     * @return $this\n     */\n    public function setWidth($field = 8, $label = 2): self\n    {\n        $this->width = [\n            'label' => $label,\n            'field' => $field,\n        ];\n\n        return $this;\n    }\n\n    /**\n     * Get label and field width.\n     *\n     * @return array\n     */\n    public function getWidth(): array\n    {\n        return $this->width;\n    }\n\n    /**\n     * Set form action.\n     *\n     * @param string $action\n     *\n     * @return void\n     */\n    public function setAction($action)\n    {\n        $this->action = $action;\n    }\n\n    /**\n     * Get Form action.\n     *\n     * @return string\n     */\n    public function getAction(): string\n    {\n        if ($this->action) {\n            return $this->action;\n        }\n\n        if ($this->isMode(static::MODE_EDIT)) {\n            return $this->form->resource().'/'.$this->id;\n        }\n\n        if ($this->isMode(static::MODE_CREATE)) {\n            return $this->form->resource(-1);\n        }\n\n        return '';\n    }\n\n    /**\n     * Set view for this form.\n     *\n     * @param string $view\n     *\n     * @return $this\n     */\n    public function setView($view): self\n    {\n        $this->view = $view;\n\n        return $this;\n    }\n\n    /**\n     * Set title for form.\n     *\n     * @param string $title\n     *\n     * @return $this\n     */\n    public function setTitle($title): self\n    {\n        $this->title = $title;\n\n        return $this;\n    }\n\n    /**\n     * Get fields of this builder.\n     *\n     * @return Collection\n     */\n    public function fields(): Collection\n    {\n        return $this->fields;\n    }\n\n    /**\n     * Get specify field.\n     *\n     * @param string $name\n     *\n     * @return mixed\n     */\n    public function field($name)\n    {\n        return $this->fields()->first(function (Field $field) use ($name) {\n            return $field->column() === $name;\n        });\n    }\n\n    /**\n     * If the parant form has rows.\n     *\n     * @return bool\n     */\n    public function hasRows(): bool\n    {\n        return !empty($this->form->rows);\n    }\n\n    /**\n     * Get field rows of form.\n     *\n     * @return array\n     */\n    public function getRows(): array\n    {\n        return $this->form->rows;\n    }\n\n    /**\n     * @return array\n     */\n    public function getHiddenFields(): array\n    {\n        return $this->hiddenFields;\n    }\n\n    /**\n     * @param Field $field\n     *\n     * @return void\n     */\n    public function addHiddenField(Field $field)\n    {\n        $this->hiddenFields[] = $field;\n    }\n\n    /**\n     * Add or get options.\n     *\n     * @param array $options\n     *\n     * @return array|null\n     */\n    public function options($options = [])\n    {\n        if (empty($options)) {\n            return $this->options;\n        }\n\n        $this->options = array_merge($this->options, $options);\n    }\n\n    /**\n     * Get or set option.\n     *\n     * @param string $option\n     * @param mixed  $value\n     *\n     * @return $this\n     */\n    public function option($option, $value = null)\n    {\n        if (func_num_args() === 1) {\n            return Arr::get($this->options, $option);\n        }\n\n        $this->options[$option] = $value;\n\n        return $this;\n    }\n\n    /**\n     * @return string\n     */\n    public function title(): string\n    {\n        if ($this->title) {\n            return $this->title;\n        }\n\n        if ($this->mode === static::MODE_CREATE) {\n            return trans('admin.create');\n        }\n\n        if ($this->mode === static::MODE_EDIT) {\n            return trans('admin.edit');\n        }\n\n        return '';\n    }\n\n    /**\n     * Determine if form fields has files.\n     *\n     * @return bool\n     */\n    public function hasFile(): bool\n    {\n        foreach ($this->fields() as $field) {\n            if ($field instanceof Field\\File || $field instanceof Field\\MultipleFile) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Add field for store redirect url after update or store.\n     *\n     * @return void\n     */\n    protected function addRedirectUrlField()\n    {\n        $previous = URL::previous();\n\n        if (!$previous || $previous === URL::current()) {\n            return;\n        }\n\n        if (Str::contains($previous, url($this->getResource()))) {\n            $this->addHiddenField((new Hidden(static::PREVIOUS_URL_KEY))->value($previous));\n        }\n    }\n\n    /**\n     * Open up a new HTML form.\n     *\n     * @param array $options\n     *\n     * @return string\n     */\n    public function open($options = []): string\n    {\n        $attributes = [];\n\n        if ($this->isMode(self::MODE_EDIT)) {\n            $this->addHiddenField((new Hidden('_method'))->value('PUT'));\n        }\n\n        $this->addRedirectUrlField();\n\n        $attributes['action'] = $this->getAction();\n        $attributes['method'] = Arr::get($options, 'method', 'post');\n        $attributes['class'] = implode(' ', ['form-horizontal', $this->formClass]);\n        $attributes['accept-charset'] = 'UTF-8';\n\n        if ($this->hasFile()) {\n            $attributes['enctype'] = 'multipart/form-data';\n        }\n\n        $html = [];\n        foreach ($attributes as $name => $value) {\n            $html[] = \"$name=\\\"$value\\\"\";\n        }\n\n        return '<form '.implode(' ', $html).' pjax-container>';\n    }\n\n    /**\n     * Close the current form.\n     *\n     * @return string\n     */\n    public function close(): string\n    {\n        $this->form = null;\n        $this->fields = null;\n\n        return '</form>';\n    }\n\n    /**\n     * @param string $message\n     *\n     * @return void\n     */\n    public function confirm(string $message)\n    {\n        $trans = [\n            'confirm' => trans('admin.confirm'),\n            'cancel'  => trans('admin.cancel'),\n        ];\n\n        $script = <<<SCRIPT\n$('form.{$this->formClass} button[type=submit]').click(function (e) {\n    e.preventDefault();\n    var form = $(this).parents('form');\n    swal({\n        title: \"$message\",\n        type: \"warning\",\n        showCancelButton: true,\n        confirmButtonColor: \"#DD6B55\",\n        confirmButtonText: \"{$trans['confirm']}\",\n        cancelButtonText: \"{$trans['cancel']}\",\n    }).then(function (result) {\n        if (result.value) {\n          form.submit();\n        }\n    });\n});\nSCRIPT;\n\n        Admin::script($script);\n    }\n\n    /**\n     * Remove reserved fields like `id` `created_at` `updated_at` in form fields.\n     *\n     * @return void\n     */\n    protected function removeReservedFields()\n    {\n        if (!$this->isCreating()) {\n            return;\n        }\n\n        $reservedColumns = [\n            $this->form->model()->getCreatedAtColumn(),\n            $this->form->model()->getUpdatedAtColumn(),\n        ];\n\n        if ($this->form->model()->incrementing) {\n            $reservedColumns[] = $this->form->model()->getKeyName();\n        }\n\n        $this->form->getLayout()->removeReservedFields($reservedColumns);\n\n        $this->fields = $this->fields()->reject(function (Field $field) use ($reservedColumns) {\n            return in_array($field->column(), $reservedColumns, true);\n        });\n    }\n\n    /**\n     * Render form header tools.\n     *\n     * @return string\n     */\n    public function renderTools(): string\n    {\n        return $this->tools->render();\n    }\n\n    /**\n     * Render form footer.\n     *\n     * @return string\n     */\n    public function renderFooter(): string\n    {\n        return $this->footer->render();\n    }\n\n    /**\n     * Add script for tab form.\n     *\n     * @return void\n     */\n    protected function addTabformScript()\n    {\n        $script = <<<'SCRIPT'\n\nvar hash = document.location.hash;\nif (hash) {\n    $('.nav-tabs a[href=\"' + hash + '\"]').tab('show');\n}\n\n// Change hash for page-reload\n$('.nav-tabs a').on('shown.bs.tab', function (e) {\n    history.pushState(null,null, e.target.hash);\n});\n\nif ($('.has-error').length) {\n    $('.has-error').each(function () {\n        var tabId = '#'+$(this).closest('.tab-pane').attr('id');\n        $('li a[href=\"'+tabId+'\"] i').removeClass('hide');\n    });\n\n    var first = $('.has-error:first').closest('.tab-pane').attr('id');\n    $('li a[href=\"#'+first+'\"]').tab('show');\n}\n\nSCRIPT;\n        Admin::script($script);\n    }\n\n    /**\n     * Add script for cascade.\n     *\n     * @return void\n     */\n    protected function addCascadeScript()\n    {\n        $script = <<<SCRIPT\n;(function () {\n    $('form.{$this->formClass}').submit(function (e) {\n        e.preventDefault();\n        $(this).find('div.cascade-group.hide :input').attr('disabled', true);\n    });\n})();\nSCRIPT;\n\n        Admin::script($script);\n    }\n\n    /**\n     * Render form.\n     *\n     * @return string\n     */\n    public function render(): string\n    {\n        $this->removeReservedFields();\n\n        $tabObj = $this->form->setTab();\n\n        if (!$tabObj->isEmpty()) {\n            $this->addTabformScript();\n        }\n\n        $this->addCascadeScript();\n\n        $data = [\n            'form'   => $this,\n            'tabObj' => $tabObj,\n            'width'  => $this->width,\n            'layout' => $this->form->getLayout(),\n        ];\n\n        return view($this->view, $data)->render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Concerns/HandleCascadeFields.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Concerns;\n\nuse Encore\\Admin\\Form\\Field;\n\ntrait HandleCascadeFields\n{\n    /**\n     * @param array    $dependency\n     * @param \\Closure $closure\n     */\n    public function cascadeGroup(\\Closure $closure, array $dependency)\n    {\n        $this->pushField($group = new Field\\CascadeGroup($dependency));\n\n        call_user_func($closure, $this);\n\n        $group->end();\n    }\n}\n"
  },
  {
    "path": "src/Form/Concerns/HasFields.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Concerns;\n\nuse Encore\\Admin\\Form\\Field;\nuse Illuminate\\Support\\Arr;\n\n/**\n * @method Field\\Text           text($column, $label = '')\n * @method Field\\Checkbox       checkbox($column, $label = '')\n * @method Field\\CheckboxButton checkboxButton($column, $label = '')\n * @method Field\\CheckboxCard   checkboxCard($column, $label = '')\n * @method Field\\Radio          radio($column, $label = '')\n * @method Field\\RadioButton    radioButton($column, $label = '')\n * @method Field\\RadioCard      radioCard($column, $label = '')\n * @method Field\\Select         select($column, $label = '')\n * @method Field\\MultipleSelect multipleSelect($column, $label = '')\n * @method Field\\Textarea       textarea($column, $label = '')\n * @method Field\\Hidden         hidden($column, $label = '')\n * @method Field\\Id             id($column, $label = '')\n * @method Field\\Ip             ip($column, $label = '')\n * @method Field\\Url            url($column, $label = '')\n * @method Field\\Color          color($column, $label = '')\n * @method Field\\Email          email($column, $label = '')\n * @method Field\\Mobile         mobile($column, $label = '')\n * @method Field\\Slider         slider($column, $label = '')\n * @method Field\\File           file($column, $label = '')\n * @method Field\\Image          image($column, $label = '')\n * @method Field\\Date           date($column, $label = '')\n * @method Field\\Datetime       datetime($column, $label = '')\n * @method Field\\Time           time($column, $label = '')\n * @method Field\\Year           year($column, $label = '')\n * @method Field\\Month          month($column, $label = '')\n * @method Field\\DateRange      dateRange($start, $end, $label = '')\n * @method Field\\DateMultiple   DateMultiple($column, $label = '')\n * @method Field\\DateTimeRange  datetimeRange($start, $end, $label = '')\n * @method Field\\TimeRange      timeRange($start, $end, $label = '')\n * @method Field\\Number         number($column, $label = '')\n * @method Field\\Currency       currency($column, $label = '')\n * @method Field\\SwitchField    switch($column, $label = '')\n * @method Field\\Display        display($column, $label = '')\n * @method Field\\Rate           rate($column, $label = '')\n * @method Field\\Divider        divider($title = '')\n * @method Field\\Password       password($column, $label = '')\n * @method Field\\Decimal        decimal($column, $label = '')\n * @method Field\\Html           html($html, $label = '')\n * @method Field\\Tags           tags($column, $label = '')\n * @method Field\\Icon           icon($column, $label = '')\n * @method Field\\Embeds         embeds($column, $label = '', $callback)\n * @method Field\\MultipleImage  multipleImage($column, $label = '')\n * @method Field\\MultipleFile   multipleFile($column, $label = '')\n * @method Field\\Captcha        captcha($column, $label = '')\n * @method Field\\Listbox        listbox($column, $label = '')\n * @method Field\\Table          table($column, $label, $builder)\n * @method Field\\Timezone       timezone($column, $label = '')\n * @method Field\\KeyValue       keyValue($column, $label = '')\n * @method Field\\ListField      list($column, $label = '')\n * @method Field\\HasMany        hasMany($relationName, $label = '', $callback)\n * @method Field\\HasMany        morphMany($relationName, $label = '', $callback)\n * @method Field\\BelongsTo      belongsTo($column, $selectable, $label = '')\n * @method Field\\BelongsToMany  belongsToMany($column, $selectable, $label = '')\n */\ntrait HasFields\n{\n    /**\n     * Available fields.\n     *\n     * @var array\n     */\n    public static $availableFields = [\n        'button'            => Field\\Button::class,\n        'checkbox'          => Field\\Checkbox::class,\n        'checkboxButton'    => Field\\CheckboxButton::class,\n        'checkboxCard'      => Field\\CheckboxCard::class,\n        'color'             => Field\\Color::class,\n        'currency'          => Field\\Currency::class,\n        'date'              => Field\\Date::class,\n        'dateRange'         => Field\\DateRange::class,\n        'DateMultiple'      => Field\\DateMultiple::class,\n        'datetime'          => Field\\Datetime::class,\n        'dateTimeRange'     => Field\\DatetimeRange::class,\n        'datetimeRange'     => Field\\DatetimeRange::class,\n        'decimal'           => Field\\Decimal::class,\n        'display'           => Field\\Display::class,\n        'divider'           => Field\\Divider::class,\n        'embeds'            => Field\\Embeds::class,\n        'email'             => Field\\Email::class,\n        'file'              => Field\\File::class,\n        'hidden'            => Field\\Hidden::class,\n        'id'                => Field\\Id::class,\n        'image'             => Field\\Image::class,\n        'ip'                => Field\\Ip::class,\n        'mobile'            => Field\\Mobile::class,\n        'month'             => Field\\Month::class,\n        'multipleSelect'    => Field\\MultipleSelect::class,\n        'number'            => Field\\Number::class,\n        'password'          => Field\\Password::class,\n        'radio'             => Field\\Radio::class,\n        'radioButton'       => Field\\RadioButton::class,\n        'radioCard'         => Field\\RadioCard::class,\n        'rate'              => Field\\Rate::class,\n        'select'            => Field\\Select::class,\n        'slider'            => Field\\Slider::class,\n        'switch'            => Field\\SwitchField::class,\n        'text'              => Field\\Text::class,\n        'textarea'          => Field\\Textarea::class,\n        'time'              => Field\\Time::class,\n        'timeRange'         => Field\\TimeRange::class,\n        'url'               => Field\\Url::class,\n        'year'              => Field\\Year::class,\n        'html'              => Field\\Html::class,\n        'tags'              => Field\\Tags::class,\n        'icon'              => Field\\Icon::class,\n        'multipleFile'      => Field\\MultipleFile::class,\n        'multipleImage'     => Field\\MultipleImage::class,\n        'captcha'           => Field\\Captcha::class,\n        'listbox'           => Field\\Listbox::class,\n        'table'             => Field\\Table::class,\n        'timezone'          => Field\\Timezone::class,\n        'keyValue'          => Field\\KeyValue::class,\n        'list'              => Field\\ListField::class,\n        'hasMany'           => Field\\HasMany::class,\n        'morphMany'         => Field\\HasMany::class,\n        'belongsTo'         => Field\\BelongsTo::class,\n        'belongsToMany'     => Field\\BelongsToMany::class,\n    ];\n\n    /**\n     * Form field alias.\n     *\n     * @var array\n     */\n    public static $fieldAlias = [];\n\n    /**\n     * Register custom field.\n     *\n     * @param string $abstract\n     * @param string $class\n     *\n     * @return void\n     */\n    public static function extend($abstract, $class)\n    {\n        static::$availableFields[$abstract] = $class;\n    }\n\n    /**\n     * Set form field alias.\n     *\n     * @param string $field\n     * @param string $alias\n     *\n     * @return void\n     */\n    public static function alias($field, $alias)\n    {\n        static::$fieldAlias[$alias] = $field;\n    }\n\n    /**\n     * Remove registered field.\n     *\n     * @param array|string $abstract\n     */\n    public static function forget($abstract)\n    {\n        Arr::forget(static::$availableFields, $abstract);\n    }\n\n    /**\n     * Find field class.\n     *\n     * @param string $method\n     *\n     * @return bool|mixed\n     */\n    public static function findFieldClass($method)\n    {\n        // If alias exists.\n        if (isset(static::$fieldAlias[$method])) {\n            $method = static::$fieldAlias[$method];\n        }\n\n        $class = Arr::get(static::$availableFields, $method);\n\n        if (class_exists($class)) {\n            return $class;\n        }\n\n        return false;\n    }\n\n    /**\n     * Collect assets required by registered field.\n     *\n     * @return array\n     */\n    public static function collectFieldAssets(): array\n    {\n        if (!empty(static::$collectedAssets)) {\n            return static::$collectedAssets;\n        }\n\n        $css = collect();\n        $js = collect();\n\n        foreach (static::$availableFields as $field) {\n            if (!method_exists($field, 'getAssets')) {\n                continue;\n            }\n\n            $assets = call_user_func([$field, 'getAssets']);\n\n            $css->push(Arr::get($assets, 'css'));\n            $js->push(Arr::get($assets, 'js'));\n        }\n\n        return static::$collectedAssets = [\n            'css' => $css->flatten()->unique()->filter()->toArray(),\n            'js'  => $js->flatten()->unique()->filter()->toArray(),\n        ];\n    }\n}\n"
  },
  {
    "path": "src/Form/Concerns/HasHooks.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Concerns;\n\nuse Closure;\nuse Illuminate\\Support\\Arr;\nuse Symfony\\Component\\HttpFoundation\\Response;\n\ntrait HasHooks\n{\n    /**\n     * Supported hooks: submitted, editing, saving, saved, deleting, deleted.\n     *\n     * @var array\n     */\n    protected $hooks = [];\n\n    /**\n     * Initialization closure array.\n     *\n     * @var []Closure\n     */\n    protected static $initCallbacks;\n\n    /**\n     * Initialize with user pre-defined default disables, etc.\n     *\n     * @param Closure $callback\n     */\n    public static function init(Closure $callback = null)\n    {\n        static::$initCallbacks[] = $callback;\n    }\n\n    /**\n     * Call the initialization closure array in sequence.\n     */\n    protected function callInitCallbacks()\n    {\n        if (empty(static::$initCallbacks)) {\n            return;\n        }\n\n        foreach (static::$initCallbacks as $callback) {\n            $callback($this);\n        }\n    }\n\n    /**\n     * Register a hook.\n     *\n     * @param string  $name\n     * @param Closure $callback\n     *\n     * @return $this\n     */\n    protected function registerHook($name, Closure $callback)\n    {\n        $this->hooks[$name][] = $callback;\n\n        return $this;\n    }\n\n    /**\n     * Call hooks by giving name.\n     *\n     * @param string $name\n     * @param array  $parameters\n     *\n     * @return Response\n     */\n    protected function callHooks($name, $parameters = [])\n    {\n        $hooks = Arr::get($this->hooks, $name, []);\n\n        foreach ($hooks as $func) {\n            if (!$func instanceof Closure) {\n                continue;\n            }\n\n            $response = call_user_func($func, $this, $parameters);\n\n            if ($response instanceof Response) {\n                return $response;\n            }\n        }\n    }\n\n    /**\n     * Set after getting editing model callback.\n     *\n     * @param Closure $callback\n     *\n     * @return $this\n     */\n    public function editing(Closure $callback)\n    {\n        return $this->registerHook('editing', $callback);\n    }\n\n    /**\n     * Set submitted callback.\n     *\n     * @param Closure $callback\n     *\n     * @return $this\n     */\n    public function submitted(Closure $callback)\n    {\n        return $this->registerHook('submitted', $callback);\n    }\n\n    /**\n     * Set saving callback.\n     *\n     * @param Closure $callback\n     *\n     * @return $this\n     */\n    public function saving(Closure $callback)\n    {\n        return $this->registerHook('saving', $callback);\n    }\n\n    /**\n     * Set saved callback.\n     *\n     * @param Closure $callback\n     *\n     * @return $this\n     */\n    public function saved(Closure $callback)\n    {\n        return $this->registerHook('saved', $callback);\n    }\n\n    /**\n     * @param Closure $callback\n     *\n     * @return $this\n     */\n    public function deleting(Closure $callback)\n    {\n        return $this->registerHook('deleting', $callback);\n    }\n\n    /**\n     * @param Closure $callback\n     *\n     * @return $this\n     */\n    public function deleted(Closure $callback)\n    {\n        return $this->registerHook('deleted', $callback);\n    }\n\n    /**\n     * Call editing callbacks.\n     *\n     * @return mixed\n     */\n    protected function callEditing()\n    {\n        return $this->callHooks('editing');\n    }\n\n    /**\n     * Call submitted callback.\n     *\n     * @return mixed\n     */\n    protected function callSubmitted()\n    {\n        return $this->callHooks('submitted');\n    }\n\n    /**\n     * Call saving callback.\n     *\n     * @return mixed\n     */\n    protected function callSaving()\n    {\n        return $this->callHooks('saving');\n    }\n\n    /**\n     * Callback after saving a Model.\n     *\n     * @return mixed|null\n     */\n    protected function callSaved()\n    {\n        return $this->callHooks('saved');\n    }\n\n    /**\n     * Call hooks when deleting.\n     *\n     * @param mixed $id\n     *\n     * @return mixed\n     */\n    protected function callDeleting($id)\n    {\n        return $this->callHooks('deleting', $id);\n    }\n\n    /**\n     * @return mixed\n     */\n    protected function callDeleted()\n    {\n        return $this->callHooks('deleted');\n    }\n}\n"
  },
  {
    "path": "src/Form/EmbeddedForm.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form;\n\nuse Encore\\Admin\\Form;\nuse Encore\\Admin\\Widgets\\Form as WidgetForm;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Collection;\n\n/**\n * Class EmbeddedForm.\n *\n * @method Field\\Text           text($column, $label = '')\n * @method Field\\Checkbox       checkbox($column, $label = '')\n * @method Field\\Radio          radio($column, $label = '')\n * @method Field\\Select         select($column, $label = '')\n * @method Field\\MultipleSelect multipleSelect($column, $label = '')\n * @method Field\\Textarea       textarea($column, $label = '')\n * @method Field\\Hidden         hidden($column, $label = '')\n * @method Field\\Id             id($column, $label = '')\n * @method Field\\Ip             ip($column, $label = '')\n * @method Field\\Url            url($column, $label = '')\n * @method Field\\Color          color($column, $label = '')\n * @method Field\\Email          email($column, $label = '')\n * @method Field\\Mobile         mobile($column, $label = '')\n * @method Field\\Slider         slider($column, $label = '')\n * @method Field\\Map            map($latitude, $longitude, $label = '')\n * @method Field\\Editor         editor($column, $label = '')\n * @method Field\\File           file($column, $label = '')\n * @method Field\\Image          image($column, $label = '')\n * @method Field\\Date           date($column, $label = '')\n * @method Field\\Datetime       datetime($column, $label = '')\n * @method Field\\Time           time($column, $label = '')\n * @method Field\\Year           year($column, $label = '')\n * @method Field\\Month          month($column, $label = '')\n * @method Field\\DateRange      dateRange($start, $end, $label = '')\n * @method Field\\DateTimeRange  datetimeRange($start, $end, $label = '')\n * @method Field\\TimeRange      timeRange($start, $end, $label = '')\n * @method Field\\Number         number($column, $label = '')\n * @method Field\\Currency       currency($column, $label = '')\n * @method Field\\HasMany        hasMany($relationName, $callback)\n * @method Field\\SwitchField    switch($column, $label = '')\n * @method Field\\Display        display($column, $label = '')\n * @method Field\\Rate           rate($column, $label = '')\n * @method Field\\Divide         divider()\n * @method Field\\Password       password($column, $label = '')\n * @method Field\\Decimal        decimal($column, $label = '')\n * @method Field\\Html           html($html, $label = '')\n * @method Field\\Tags           tags($column, $label = '')\n * @method Field\\Icon           icon($column, $label = '')\n * @method Field\\Embeds         embeds($column, $label = '')\n */\nclass EmbeddedForm\n{\n    /**\n     * @var Form|WidgetForm\n     */\n    protected $parent = null;\n\n    /**\n     * Fields in form.\n     *\n     * @var Collection\n     */\n    protected $fields;\n\n    /**\n     * Original data for this field.\n     *\n     * @var array\n     */\n    protected $original = [];\n\n    /**\n     * Column name for this form.\n     *\n     * @var string\n     */\n    protected $column;\n\n    /**\n     * EmbeddedForm constructor.\n     *\n     * @param string $column\n     */\n    public function __construct($column)\n    {\n        $this->column = $column;\n\n        $this->fields = new Collection();\n    }\n\n    /**\n     * Get all fields in current form.\n     *\n     * @return Collection\n     */\n    public function fields()\n    {\n        return $this->fields;\n    }\n\n    /**\n     * Set parent form for this form.\n     *\n     * @param Form $parent\n     *\n     * @return $this\n     */\n    public function setParent(Form $parent)\n    {\n        $this->parent = $parent;\n\n        return $this;\n    }\n\n    /**\n     * Set parent form for this form.\n     *\n     * @param WidgetForm $parent\n     *\n     * @return $this\n     */\n    public function setParentWidgetForm(WidgetForm $parent)\n    {\n        $this->parent = $parent;\n\n        return $this;\n    }\n\n    /**\n     * Set original values for fields.\n     *\n     * @param array $data\n     *\n     * @return $this\n     */\n    public function setOriginal($data)\n    {\n        if (empty($data)) {\n            return $this;\n        }\n\n        if (is_string($data)) {\n            $data = json_decode($data, true);\n        }\n\n        $this->original = $data;\n\n        return $this;\n    }\n\n    /**\n     * Prepare for insert or update.\n     *\n     * @param array $input\n     *\n     * @return mixed\n     */\n    public function prepare($input)\n    {\n        foreach ($input as $key => $record) {\n            $this->setFieldOriginalValue($key);\n            $input[$key] = $this->prepareValue($key, $record);\n        }\n\n        return $input;\n    }\n\n    /**\n     * Do prepare work for each field.\n     *\n     * @param string $key\n     * @param string $record\n     *\n     * @return mixed\n     */\n    protected function prepareValue($key, $record)\n    {\n        $field = $this->fields->first(function (Field $field) use ($key) {\n            return in_array($key, (array) $field->column());\n        });\n\n        if ($field && method_exists($field, 'prepare')) {\n            return $field->prepare($record);\n        }\n\n        return $record;\n    }\n\n    /**\n     * Set original data for each field.\n     *\n     * @param string $key\n     *\n     * @return void\n     */\n    protected function setFieldOriginalValue($key)\n    {\n        if (array_key_exists($key, $this->original)) {\n            $values = $this->original[$key];\n\n            $this->fields->each(function (Field $field) use ($values) {\n                $field->setOriginal($values);\n            });\n        }\n    }\n\n    /**\n     * Fill data to all fields in form.\n     *\n     * @param array $data\n     *\n     * @return $this\n     */\n    public function fill(array $data)\n    {\n        $this->fields->each(function (Field $field) use ($data) {\n            $field->fill($data);\n        });\n\n        return $this;\n    }\n\n    /**\n     * Format form, set `element name` `error key` and `element class`.\n     *\n     * @param Field $field\n     *\n     * @return Field\n     */\n    protected function formatField(Field $field)\n    {\n        $jsonKey = $field->column();\n\n        $elementName = $elementClass = $errorKey = [];\n\n        if (is_array($jsonKey)) {\n            foreach ($jsonKey as $index => $name) {\n                $elementName[$index] = \"{$this->column}[$name]\";\n                $errorKey[$index] = \"{$this->column}.$name\";\n                $elementClass[$index] = \"{$this->column}_$name\";\n            }\n        } else {\n            $elementName = \"{$this->column}[$jsonKey]\";\n            $errorKey = \"{$this->column}.$jsonKey\";\n            $elementClass = \"{$this->column}_$jsonKey\";\n        }\n\n        $field->setElementName($elementName)\n            ->setErrorKey($errorKey)\n            ->setElementClass($elementClass);\n\n        return $field;\n    }\n\n    /**\n     * Add a field to form.\n     *\n     * @param Field $field\n     *\n     * @return $this\n     */\n    public function pushField(Field $field)\n    {\n        $field = $this->formatField($field);\n\n        $this->fields->push($field);\n\n        return $this;\n    }\n\n    /**\n     * Add nested-form fields dynamically.\n     *\n     * @param string $method\n     * @param array  $arguments\n     *\n     * @return Field|$this\n     */\n    public function __call($method, $arguments)\n    {\n        if ($className = Form::findFieldClass($method)) {\n            $column = Arr::get($arguments, 0, '');\n\n            /** @var Field $field */\n            $field = new $className($column, array_slice($arguments, 1));\n\n            if ($this->parent instanceof WidgetForm) {\n                $field->setWidgetForm($this->parent);\n            } else {\n                $field->setForm($this->parent);\n            }\n\n            $this->pushField($field);\n\n            return $field;\n        }\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/BelongsTo.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Admin;\n\nclass BelongsTo extends Select\n{\n    use BelongsToRelation;\n\n    protected function addScript()\n    {\n        $script = <<<SCRIPT\n;(function () {\n\n    var grid = $('.belongsto-{$this->column()}');\n    var modal = $('#{$this->modalID}');\n    var table = grid.find('.grid-table');\n    var selected = $(\"{$this->getElementClassSelector()}\").val();\n    var row = null;\n\n    // open modal\n    grid.find('.select-relation').click(function (e) {\n        $('#{$this->modalID}').modal('show');\n        e.preventDefault();\n    });\n\n    // remove row\n    grid.on('click', '.grid-row-remove', function () {\n        selected = null;\n        $(this).parents('tr').remove();\n        $(\"{$this->getElementClassSelector()}\").val(null);\n\n        var empty = $('.belongsto-{$this->column()}').find('template.empty').html();\n\n        table.find('tbody').append(empty);\n    });\n\n    var load = function (url) {\n        $.get(url, function (data) {\n            modal.find('.modal-body').html(data);\n            modal.find('.select').iCheck({\n                radioClass:'iradio_minimal-blue',\n                checkboxClass:'icheckbox_minimal-blue'\n            });\n            modal.find('.box-header:first').hide();\n\n            modal.find('input.select').each(function (index, el) {\n                if ($(el).val() == selected) {\n                    $(el).iCheck('toggle');\n                }\n            });\n        });\n    };\n\n    var update = function (callback) {\n\n        $(\"{$this->getElementClassSelector()}\")\n            .select2({data: [selected]})\n            .val(selected)\n            .trigger('change')\n            .next()\n            .addClass('hide');\n\n        if (row) {\n            row.find('td:last a').removeClass('hide');\n            row.find('td:first').remove();\n            table.find('tbody').empty().append(row);\n        }\n\n        callback();\n    };\n\n    modal.on('show.bs.modal', function (e) {\n        load(\"{$this->getLoadUrl()}\");\n    }).on('click', '.page-item a, .filter-box a', function (e) {\n        load($(this).attr('href'));\n        e.preventDefault();\n    }).on('click', 'tr', function (e) {\n        $(this).find('input.select').iCheck('toggle');\n        e.preventDefault();\n    }).on('submit', '.box-header form', function (e) {\n        load($(this).attr('action')+'&'+$(this).serialize());\n        return false;\n    }).on('ifChecked', 'input.select', function (e) {\n        row = $(e.target).parents('tr');\n        selected = $(this).val();\n    }).find('.modal-footer .submit').click(function () {\n        update(function () {\n            modal.modal('toggle');\n        });\n    });\n})();\nSCRIPT;\n\n        Admin::script($script);\n\n        return $this;\n    }\n\n    protected function getOptions()\n    {\n        $options = [];\n\n        if ($value = $this->value()) {\n            $options = [$value => $value];\n        }\n\n        return $options;\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/BelongsToMany.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Admin;\n\nclass BelongsToMany extends MultipleSelect\n{\n    use BelongsToRelation;\n\n    protected function addScript()\n    {\n        $script = <<<SCRIPT\n;(function () {\n\n    var grid = $('.belongstomany-{$this->column()}');\n    var modal = $('#{$this->modalID}');\n    var table = grid.find('.grid-table');\n    var selected = $(\"{$this->getElementClassSelector()}\").val() || [];\n    var rows = {};\n\n    table.find('tbody').children().each(function (index, tr) {\n        if ($(tr).find('.grid-row-remove').length > 0) {\n            rows[$(tr).find('.grid-row-remove').data('key')] = $(tr);\n        }\n    });\n\n    // open modal\n    grid.find('.select-relation').click(function (e) {\n        $('#{$this->modalID}').modal('show');\n        e.preventDefault();\n    });\n\n    // remove row\n    grid.on('click', '.grid-row-remove', function () {\n        val = $(this).data('key').toString();\n\n        var index = selected.indexOf(val);\n        if (index !== -1) {\n           selected.splice(index, 1);\n           delete rows[val];\n        }\n\n        $(this).parents('tr').remove();\n        $(\"{$this->getElementClassSelector()}\").val(selected);\n\n        if (selected.length == 0) {\n            var empty = $('.belongstomany-{$this->column()}').find('template.empty').html();\n            table.find('tbody').append(empty);\n        }\n    });\n\n    var load = function (url) {\n        $.get(url, function (data) {\n            modal.find('.modal-body').html(data);\n            modal.find('.select').iCheck({\n                radioClass:'iradio_minimal-blue',\n                checkboxClass:'icheckbox_minimal-blue'\n            });\n            modal.find('.box-header:first').hide();\n\n            modal.find('input.select').each(function (index, el) {\n                if ($.inArray($(el).val().toString(), selected) >=0 ) {\n                    $(el).iCheck('toggle');\n                }\n            });\n        });\n    };\n\n    var update = function (callback) {\n\n        $(\"{$this->getElementClassSelector()}\")\n            .select2({data: selected})\n            .val(selected)\n            .trigger('change')\n            .next()\n            .addClass('hide');\n\n        table.find('tbody').empty();\n\n        Object.values(rows).forEach(function (row) {\n            row.find('td:last a').removeClass('hide');\n            row.find('td.column-__modal_selector__').remove();\n            table.find('tbody').append(row);\n        });\n\n        if (selected.length == 0) {\n            var empty = $('.belongstomany-{$this->column()}').find('template.empty').html();\n            table.find('tbody').append(empty);\n        } else {\n            table.find('.empty-grid').parent().remove();\n        }\n\n        callback();\n    };\n\n    modal.on('show.bs.modal', function (e) {\n        load(\"{$this->getLoadUrl(1)}\");\n    }).on('click', '.page-item a, .filter-box a', function (e) {\n        load($(this).attr('href'));\n        e.preventDefault();\n    }).on('click', 'tr', function (e) {\n        $(this).find('input.select').iCheck('toggle');\n        e.preventDefault();\n    }).on('submit', '.box-header form', function (e) {\n        load($(this).attr('action')+'&'+$(this).serialize());\n        e.preventDefault();\n        return false;\n    }).on('ifChecked', 'input.select', function (e) {\n        if (selected.indexOf($(this).val()) < 0) {\n            selected.push($(this).val());\n            rows[$(e.target).val()] = $(e.target).parents('tr');\n        }\n    }).on('ifUnchecked', 'input.select', function (e) {\n           var val = $(this).val();\n           var index = selected.indexOf(val);\n           if (index !== -1) {\n               selected.splice(index, 1);\n               delete rows[$(e.target).val()];\n           }\n    }).find('.modal-footer .submit').click(function () {\n        update(function () {\n            modal.modal('toggle');\n        });\n    });\n})();\nSCRIPT;\n\n        Admin::script($script);\n\n        return $this;\n    }\n\n    protected function getOptions()\n    {\n        $options = [];\n\n        if ($this->value()) {\n            $options = array_combine($this->value(), $this->value());\n        }\n\n        return $options;\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/BelongsToRelation.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Grid\\Selectable;\n\ntrait BelongsToRelation\n{\n    /**\n     * @var string\n     */\n    protected $modalID;\n\n    /**\n     * @var string\n     */\n    protected $selectable;\n\n    /**\n     * BelongsToRelation constructor.\n     *\n     * @param string $column\n     * @param array  $arguments\n     */\n    public function __construct($column, $arguments = [])\n    {\n        $this->setSelectable($arguments[0]);\n\n        parent::__construct($column, array_slice($arguments, 1));\n    }\n\n    /**\n     * @param string $selectable\n     */\n    protected function setSelectable($selectable)\n    {\n        if (!class_exists($selectable) || !is_subclass_of($selectable, Selectable::class)) {\n            throw new \\InvalidArgumentException(\n                \"[Class [{$selectable}] must be a sub class of Encore\\Admin\\Grid\\Selectable\"\n            );\n        }\n\n        $this->selectable = $selectable;\n    }\n\n    /**\n     * @return string\n     */\n    public function getSelectable()\n    {\n        return $this->selectable;\n    }\n\n    /**\n     * @param int $multiple\n     *\n     * @return string\n     */\n    protected function getLoadUrl($multiple = 0)\n    {\n        $selectable = str_replace('\\\\', '_', $this->selectable);\n        $args = [$multiple];\n\n        return route(admin_get_route('handle-selectable'), compact('selectable', 'args'));\n    }\n\n    /**\n     * @return $this\n     */\n    public function addHtml()\n    {\n        $trans = [\n            'choose' => admin_trans('admin.choose'),\n            'cancal' => admin_trans('admin.cancel'),\n            'submit' => admin_trans('admin.submit'),\n        ];\n\n        $html = <<<HTML\n<div class=\"modal fade belongsto\" id=\"{$this->modalID}\" tabindex=\"-1\" role=\"dialog\">\n  <div class=\"modal-dialog modal-lg\" role=\"document\">\n    <div class=\"modal-content\" style=\"border-radius: 5px;\">\n      <div class=\"modal-header\">\n        <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\">\n            <span aria-hidden=\"true\">&times;</span>\n        </button>\n        <h4 class=\"modal-title\">{$trans['choose']}</h4>\n      </div>\n      <div class=\"modal-body\">\n      <div class=\"loading text-center\">\n        <i class=\"fa fa-spinner fa-pulse fa-3x fa-fw\"></i>\n        </div>\n      </div>\n      <div class=\"modal-footer\">\n        <button type=\"button\" class=\"btn btn-default\" data-dismiss=\"modal\">{$trans['cancal']}</button>\n        <button type=\"button\" class=\"btn btn-primary submit\">{$trans['submit']}</button>\n      </div>\n    </div>\n  </div>\n</div>\nHTML;\n        Admin::html($html);\n\n        return $this;\n    }\n\n    /**\n     * @return $this\n     */\n    public function addStyle()\n    {\n        $style = <<<'STYLE'\n.belongsto.modal tr {\n    cursor: pointer;\n}\n.belongsto.modal .box {\n    border-top: none;\n    margin-bottom: 0;\n    box-shadow: none;\n}\n\n.belongsto.modal .loading {\n    margin: 50px;\n}\n\n.belongsto.modal .grid-table .empty-grid {\n    padding: 20px !important;\n}\n\n.belongsto.modal .grid-table .empty-grid svg {\n    width: 60px !important;\n    height: 60px !important;\n}\n\n.belongsto.modal .grid-box .box-footer {\n    border-top: none !important;\n}\nSTYLE;\n\n        Admin::style($style);\n\n        return $this;\n    }\n\n    /**\n     * @return \\Encore\\Admin\\Grid\n     */\n    protected function makeGrid()\n    {\n        /** @var Selectable $selectable */\n        $selectable = new $this->selectable();\n\n        return $selectable->renderFormGrid($this->value());\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function render()\n    {\n        $this->modalID = sprintf('modal-selector-%s', $this->getElementClassString());\n\n        $this->addScript()->addHtml()->addStyle();\n\n        $this->addVariables([\n            'grid'    => $this->makeGrid(),\n            'options' => $this->getOptions(),\n        ]);\n\n        $this->addCascadeScript();\n\n        return parent::fieldRender();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Button.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Form\\Field;\n\nclass Button extends Field\n{\n    protected $class = 'btn-primary';\n\n    public function info()\n    {\n        $this->class = 'btn-info';\n\n        return $this;\n    }\n\n    public function on($event, $callback)\n    {\n        $this->script = <<<EOT\n\n        $('{$this->getElementClassSelector()}').on('$event', function() {\n            $callback\n        });\n\nEOT;\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/CanCascadeFields.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Form;\nuse Illuminate\\Support\\Arr;\n\n/**\n * @property Form $form\n */\ntrait CanCascadeFields\n{\n    /**\n     * @var array\n     */\n    protected $conditions = [];\n\n    /**\n     * @param $operator\n     * @param $value\n     * @param $closure\n     *\n     * @return $this\n     */\n    public function when($operator, $value, $closure = null)\n    {\n        if (func_num_args() == 2) {\n            $closure = $value;\n            $value = $operator;\n            $operator = '=';\n        }\n\n        $this->formatValues($operator, $value);\n\n        $this->addDependents($operator, $value, $closure);\n\n        return $this;\n    }\n\n    /**\n     * @param string $operator\n     * @param mixed  $value\n     */\n    protected function formatValues(string $operator, &$value)\n    {\n        if (in_array($operator, ['in', 'notIn'])) {\n            $value = Arr::wrap($value);\n        }\n\n        if (is_array($value)) {\n            $value = array_map('strval', $value);\n        } else {\n            $value = strval($value);\n        }\n    }\n\n    /**\n     * @param string   $operator\n     * @param mixed    $value\n     * @param \\Closure $closure\n     */\n    protected function addDependents(string $operator, $value, \\Closure $closure)\n    {\n        $this->conditions[] = compact('operator', 'value', 'closure');\n\n        $this->form->cascadeGroup($closure, [\n            'column' => $this->column(),\n            'index'  => count($this->conditions) - 1,\n            'class'  => $this->getCascadeClass($value),\n        ]);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function fill($data)\n    {\n        parent::fill($data);\n\n        $this->applyCascadeConditions();\n    }\n\n    /**\n     * @param mixed $value\n     *\n     * @return string\n     */\n    protected function getCascadeClass($value)\n    {\n        if (is_array($value)) {\n            $value = implode('-', $value);\n        }\n\n        return sprintf('cascade-%s-%s', $this->getElementClassString(), bin2hex($value));\n    }\n\n    /**\n     * Apply conditions to dependents fields.\n     *\n     * @return void\n     */\n    protected function applyCascadeConditions()\n    {\n        if ($this->form) {\n            $this->form->fields()\n                ->filter(function (Form\\Field $field) {\n                    return $field instanceof CascadeGroup\n                        && $field->dependsOn($this)\n                        && $this->hitsCondition($field);\n                })->each->visiable();\n        }\n    }\n\n    /**\n     * @param CascadeGroup $group\n     *\n     * @throws \\Exception\n     *\n     * @return bool\n     */\n    protected function hitsCondition(CascadeGroup $group)\n    {\n        $condition = $this->conditions[$group->index()];\n\n        extract($condition);\n\n        $old = old($this->column(), $this->value());\n\n        switch ($operator) {\n            case '=':\n                return $old == $value;\n            case '>':\n                return $old > $value;\n            case '<':\n                return $old < $value;\n            case '>=':\n                return $old >= $value;\n            case '<=':\n                return $old <= $value;\n            case '!=':\n                return $old != $value;\n            case 'in':\n                return in_array($old, $value);\n            case 'notIn':\n                return !in_array($old, $value);\n            case 'has':\n                return in_array($value, $old);\n            case 'oneIn':\n                return count(array_intersect($value, $old)) >= 1;\n            case 'oneNotIn':\n                return count(array_intersect($value, $old)) == 0;\n            default:\n                throw new \\Exception(\"Operator [$operator] not support.\");\n        }\n    }\n\n    /**\n     * Js Value.\n     */\n    protected function getValueByJs()\n    {\n        return addslashes(old($this->column(), $this->value()));\n    }\n\n    /**\n     * Add cascade scripts to contents.\n     *\n     * @return void\n     */\n    protected function addCascadeScript()\n    {\n        if (empty($this->conditions)) {\n            return;\n        }\n\n        $cascadeGroups = collect($this->conditions)->map(function ($condition) {\n            return [\n                'class'    => $this->getCascadeClass($condition['value']),\n                'operator' => $condition['operator'],\n                'value'    => $condition['value'],\n            ];\n        })->toJson();\n\n        $script = <<<SCRIPT\n;(function () {\n    var operator_table = {\n        '=': function(a, b) {\n            if ($.isArray(a) && $.isArray(b)) {\n                return $(a).not(b).length === 0 && $(b).not(a).length === 0;\n            }\n\n            return a == b;\n        },\n        '>': function(a, b) { return a > b; },\n        '<': function(a, b) { return a < b; },\n        '>=': function(a, b) { return a >= b; },\n        '<=': function(a, b) { return a <= b; },\n        '!=': function(a, b) {\n             if ($.isArray(a) && $.isArray(b)) {\n                return !($(a).not(b).length === 0 && $(b).not(a).length === 0);\n             }\n\n             return a != b;\n        },\n        'in': function(a, b) { return $.inArray(a, b) != -1; },\n        'notIn': function(a, b) { return $.inArray(a, b) == -1; },\n        'has': function(a, b) { return $.inArray(b, a) != -1; },\n        'oneIn': function(a, b) { return a.filter(v => b.includes(v)).length >= 1; },\n        'oneNotIn': function(a, b) { return a.filter(v => b.includes(v)).length == 0; },\n    };\n    var cascade_groups = {$cascadeGroups};\n        \n    cascade_groups.forEach(function (event) {\n        var default_value = '{$this->getValueByJs()}' + '';\n        var class_name = event.class;\n        if(default_value == event.value) {\n            $('.'+class_name+'').removeClass('hide');\n        }\n    });\n    \n    $('{$this->getElementClassSelector()}').on('{$this->cascadeEvent}', function (e) {\n\n        {$this->getFormFrontValue()}\n\n        cascade_groups.forEach(function (event) {\n            var group = $('div.cascade-group.'+event.class);\n            if( operator_table[event.operator](checked, event.value) ) {\n                group.removeClass('hide');\n            } else {\n                group.addClass('hide');\n            }\n        });\n    })\n})();\nSCRIPT;\n\n        Admin::script($script);\n    }\n\n    /**\n     * @return string\n     */\n    protected function getFormFrontValue()\n    {\n        switch (get_class($this)) {\n            case Radio::class:\n            case RadioButton::class:\n            case RadioCard::class:\n            case Select::class:\n            case BelongsTo::class:\n            case BelongsToMany::class:\n            case MultipleSelect::class:\n                return 'var checked = $(this).val();';\n            case Checkbox::class:\n            case CheckboxButton::class:\n            case CheckboxCard::class:\n                return <<<SCRIPT\nvar checked = $('{$this->getElementClassSelector()}:checked').map(function(){\n  return $(this).val();\n}).get();\nSCRIPT;\n            default:\n                throw new \\InvalidArgumentException('Invalid form field type');\n        }\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Captcha.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Form;\n\nclass Captcha extends Text\n{\n    protected $rules = 'required|captcha';\n\n    protected $view = 'admin::form.captcha';\n\n    public function __construct($column, $arguments = [])\n    {\n        if (!class_exists(\\Mews\\Captcha\\Captcha::class)) {\n            throw new \\Exception('To use captcha field, please install [mews/captcha] first.');\n        }\n\n        $this->column = '__captcha__';\n        $this->label = trans('admin.captcha');\n    }\n\n    public function setForm(Form $form = null)\n    {\n        $this->form = $form;\n\n        $this->form->ignore($this->column);\n\n        return $this;\n    }\n\n    public function render()\n    {\n        $this->script = <<<EOT\n\n$('#{$this->column}-captcha').click(function () {\n    $(this).attr('src', $(this).attr('src')+'?'+Math.random());\n});\n\nEOT;\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/CascadeGroup.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Form\\Field;\n\nclass CascadeGroup extends Field\n{\n    /**\n     * @var array\n     */\n    protected $dependency;\n\n    /**\n     * @var string\n     */\n    protected $hide = 'hide';\n\n    /**\n     * CascadeGroup constructor.\n     *\n     * @param array $dependency\n     */\n    public function __construct(array $dependency)\n    {\n        $this->dependency = $dependency;\n    }\n\n    /**\n     * @param Field $field\n     *\n     * @return bool\n     */\n    public function dependsOn(Field $field)\n    {\n        return $this->dependency['column'] == $field->column();\n    }\n\n    /**\n     * @return int\n     */\n    public function index()\n    {\n        return $this->dependency['index'];\n    }\n\n    /**\n     * @return void\n     */\n    public function visiable()\n    {\n        $this->hide = '';\n    }\n\n    /**\n     * @return string\n     */\n    public function render()\n    {\n        return <<<HTML\n<div class=\"cascade-group {$this->dependency['class']} {$this->hide}\">\nHTML;\n    }\n\n    /**\n     * @return void\n     */\n    public function end()\n    {\n        $this->form->html('</div>')->plain();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Checkbox.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Illuminate\\Contracts\\Support\\Arrayable;\n\nclass Checkbox extends MultipleSelect\n{\n    protected $inline = true;\n\n    protected $canCheckAll = false;\n\n    protected $groups = null;\n\n    protected static $css = [\n        '/vendor/laravel-admin/AdminLTE/plugins/iCheck/all.css',\n    ];\n\n    protected static $js = [\n        '/vendor/laravel-admin/AdminLTE/plugins/iCheck/icheck.min.js',\n    ];\n\n    /**\n     * @var string\n     */\n    protected $cascadeEvent = 'ifChanged';\n\n    /**\n     * Set options.\n     *\n     * @param array|callable|string $options\n     *\n     * @return $this|mixed\n     */\n    public function options($options = [])\n    {\n        if ($options instanceof Arrayable) {\n            $options = $options->toArray();\n        }\n\n        if (is_callable($options)) {\n            $this->options = $options;\n        } else {\n            $this->options = (array) $options;\n        }\n\n        return $this;\n    }\n\n    /**\n     * Add a checkbox above this component, so you can select all checkboxes by click on it.\n     *\n     * @return $this\n     */\n    public function canCheckAll()\n    {\n        $this->canCheckAll = true;\n\n        return $this;\n    }\n\n    /**\n     * Set chekbox groups.\n     *\n     * @param array\n     *\n     * @return $this\n     */\n    public function groups(array $groups = [])\n    {\n        $this->groups = $groups;\n\n        return $this;\n    }\n\n    /**\n     * Set checked.\n     *\n     * @param array|callable|string $checked\n     *\n     * @return $this\n     */\n    public function checked($checked = [])\n    {\n        if ($checked instanceof Arrayable) {\n            $checked = $checked->toArray();\n        }\n\n        $this->checked = (array) $checked;\n\n        return $this;\n    }\n\n    /**\n     * Draw inline checkboxes.\n     *\n     * @return $this\n     */\n    public function inline()\n    {\n        $this->inline = true;\n\n        return $this;\n    }\n\n    /**\n     * Draw stacked checkboxes.\n     *\n     * @return $this\n     */\n    public function stacked()\n    {\n        $this->inline = false;\n\n        return $this;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function render()\n    {\n        $this->script = \"$('{$this->getElementClassSelector()}').iCheck({checkboxClass:'icheckbox_minimal-blue'});\";\n\n        $this->addVariables([\n            'checked'     => $this->checked,\n            'inline'      => $this->inline,\n            'canCheckAll' => $this->canCheckAll,\n            'groups'      => $this->groups,\n        ]);\n\n        if ($this->canCheckAll) {\n            $checkAllClass = uniqid('check-all-');\n\n            $this->script .= <<<SCRIPT\n$('.{$checkAllClass}').iCheck({checkboxClass:'icheckbox_minimal-blue'}).on('ifChanged', function () {\n    if (this.checked) {\n        $('{$this->getElementClassSelector()}').iCheck('check');\n    } else {\n        $('{$this->getElementClassSelector()}').iCheck('uncheck');\n    }\n});\nSCRIPT;\n            $this->addVariables(['checkAllClass' => $checkAllClass]);\n        }\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/CheckboxButton.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Admin;\n\nclass CheckboxButton extends Checkbox\n{\n    /**\n     * @var string\n     */\n    protected $cascadeEvent = 'change';\n\n    protected function addScript()\n    {\n        $script = <<<'SCRIPT'\n$('.checkbox-group-toggle label').click(function(e) {\n    e.stopPropagation();\n    e.preventDefault();\n\n    if ($(this).hasClass('active')) {\n        $(this).removeClass('active');\n        $(this).find('input').prop('checked', false);\n    } else {\n        $(this).addClass('active');\n        $(this).find('input').prop('checked', true);\n    }\n\n    $(this).find('input').trigger('change');\n});\nSCRIPT;\n\n        Admin::script($script);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function render()\n    {\n        $this->addScript();\n\n        $this->addCascadeScript();\n\n        $this->addVariables([\n            'options' => $this->options,\n            'checked' => $this->checked,\n        ]);\n\n        return parent::fieldRender();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/CheckboxCard.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Admin;\n\nclass CheckboxCard extends CheckboxButton\n{\n    protected function addStyle()\n    {\n        $style = <<<'STYLE'\n.card-group label {\n    cursor: pointer;\n    margin-right: 8px;\n    font-weight: 400;\n}\n\n.card-group .panel {\n    margin-bottom: 0px;\n}\n\n.card-group .panel-body {\n    padding: 10px 15px;\n}\n\n.card-group .active {\n    border: 2px solid #367fa9;\n}\nSTYLE;\n\n        Admin::style($style);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function render()\n    {\n        $this->addStyle();\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Color.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nclass Color extends Text\n{\n    protected static $css = [\n        '/vendor/laravel-admin/AdminLTE/plugins/colorpicker/bootstrap-colorpicker.min.css',\n    ];\n\n    protected static $js = [\n        '/vendor/laravel-admin/AdminLTE/plugins/colorpicker/bootstrap-colorpicker.min.js',\n    ];\n\n    /**\n     * Use `hex` format.\n     *\n     * @return $this\n     */\n    public function hex()\n    {\n        return $this->options(['format' => 'hex']);\n    }\n\n    /**\n     * Use `rgb` format.\n     *\n     * @return $this\n     */\n    public function rgb()\n    {\n        return $this->options(['format' => 'rgb']);\n    }\n\n    /**\n     * Use `rgba` format.\n     *\n     * @return $this\n     */\n    public function rgba()\n    {\n        return $this->options(['format' => 'rgba']);\n    }\n\n    /**\n     * Render this filed.\n     *\n     * @return \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View\n     */\n    public function render()\n    {\n        $options = json_encode($this->options);\n\n        $this->script = \"$('{$this->getElementClassSelector()}').parent().colorpicker($options);\";\n\n        $this->prepend('<i></i>')\n            ->defaultAttribute('style', 'width: 140px');\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Currency.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nclass Currency extends Text\n{\n    /**\n     * @var string\n     */\n    protected $symbol = '$';\n\n    /**\n     * @var array\n     */\n    protected static $js = [\n        '/vendor/laravel-admin/AdminLTE/plugins/input-mask/jquery.inputmask.bundle.min.js',\n    ];\n\n    /**\n     * @see https://github.com/RobinHerbots/Inputmask#options\n     *\n     * @var array\n     */\n    protected $options = [\n        'alias'              => 'currency',\n        'radixPoint'         => '.',\n        'prefix'             => '',\n        'removeMaskOnSubmit' => true,\n    ];\n\n    /**\n     * Set symbol for currency field.\n     *\n     * @param string $symbol\n     *\n     * @return $this\n     */\n    public function symbol($symbol)\n    {\n        $this->symbol = $symbol;\n\n        return $this;\n    }\n\n    /**\n     * Set digits for input number.\n     *\n     * @param int $digits\n     *\n     * @return $this\n     */\n    public function digits($digits)\n    {\n        return $this->options(compact('digits'));\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function prepare($value)\n    {\n        return (float) $value;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function render()\n    {\n        $this->inputmask($this->options);\n\n        $this->prepend($this->symbol)\n            ->defaultAttribute('style', 'width: 120px');\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Date.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nclass Date extends Text\n{\n    protected static $css = [\n        '/vendor/laravel-admin/eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.min.css',\n    ];\n\n    protected static $js = [\n        '/vendor/laravel-admin/moment/min/moment-with-locales.min.js',\n        '/vendor/laravel-admin/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min.js',\n    ];\n\n    protected $format = 'YYYY-MM-DD';\n\n    public function format($format)\n    {\n        $this->format = $format;\n\n        return $this;\n    }\n\n    public function prepare($value)\n    {\n        if ($value === '') {\n            $value = null;\n        }\n\n        return $value;\n    }\n\n    public function render()\n    {\n        $this->options['format'] = $this->format;\n        $this->options['locale'] = array_key_exists('locale', $this->options) ? $this->options['locale'] : config('app.locale');\n        $this->options['allowInputToggle'] = true;\n\n        $this->script = \"$('{$this->getElementClassSelector()}').parent().datetimepicker(\".json_encode($this->options).');';\n\n        $this->prepend('<i class=\"fa fa-calendar fa-fw\"></i>')\n            ->defaultAttribute('style', 'width: 110px');\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/DateMultiple.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nclass DateMultiple extends Text\n{\n    protected static $css = [\n        '/vendor/laravel-admin/flatpickr/dist/flatpickr.min.css',\n        '/vendor/laravel-admin/flatpickr/dist/shortcut-buttons-flatpickr/themes/light.min.css',\n\n    ];\n\n    protected static $js = [\n        '/vendor/laravel-admin/flatpickr/dist/flatpickr.js',\n        '/vendor/laravel-admin/flatpickr/dist/shortcut-buttons-flatpickr/shortcut-buttons-flatpickr.min.js',\n        '/vendor/laravel-admin/flatpickr/dist/l10n/zh.js',\n    ];\n\n    protected $format = 'YYYY-MM-DD';\n\n    public function format($format)\n    {\n        $this->format = $format;\n\n        return $this;\n    }\n\n    public function prepare($value)\n    {\n        if ($value === '') {\n            $value = null;\n        }\n\n        return $value;\n    }\n\n    public function render()\n    {\n        $this->options['format'] = $this->format;\n        $this->options['locale'] = array_key_exists('locale', $this->options) ? $this->options['locale'] : config('app.locale');\n        $this->options['allowInputToggle'] = true;\n\n        $this->script = \"$('{$this->getElementClassSelector()}').flatpickr({mode: 'multiple',dateFormat: 'Y-m-d', locale: 'zh', plugins: [\n            ShortcutButtonsPlugin({\n              button: {\n                label: 'Clear',\n              },\n              onClick: (index, fp) => {\n                fp.clear();\n                fp.close();\n              }\n            })\n          ]});\";\n\n        $this->prepend('<i class=\"fa fa-calendar fa-fw\"></i>')\n            ->defaultAttribute('style', 'width: 100%');\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/DateRange.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Form\\Field;\n\nclass DateRange extends Field\n{\n    protected static $css = [\n        '/vendor/laravel-admin/eonasdan-bootstrap-datetimepicker/build/css/bootstrap-datetimepicker.min.css',\n    ];\n\n    protected static $js = [\n        '/vendor/laravel-admin/moment/min/moment-with-locales.min.js',\n        '/vendor/laravel-admin/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min.js',\n    ];\n\n    protected $format = 'YYYY-MM-DD';\n\n    /**\n     * Column name.\n     *\n     * @var array\n     */\n    protected $column = [];\n\n    public function __construct($column, $arguments)\n    {\n        $this->column['start'] = $column;\n        $this->column['end'] = $arguments[0];\n\n        array_shift($arguments);\n        $this->label = $this->formatLabel($arguments);\n        $this->id = $this->formatId($this->column);\n\n        $this->options(['format' => $this->format]);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function prepare($value)\n    {\n        if ($value === '') {\n            $value = null;\n        }\n\n        return $value;\n    }\n\n    public function render()\n    {\n        $this->options['locale'] = array_key_exists('locale', $this->options) ? $this->options['locale'] : config('app.locale');\n\n        $startOptions = json_encode($this->options);\n        $endOptions = json_encode($this->options + ['useCurrent' => false]);\n\n        $class = $this->getElementClassSelector();\n\n        $this->script = <<<EOT\n            $('{$class['start']}').datetimepicker($startOptions);\n            $('{$class['end']}').datetimepicker($endOptions);\n            $(\"{$class['start']}\").on(\"dp.change\", function (e) {\n                $('{$class['end']}').data(\"DateTimePicker\").minDate(e.date);\n            });\n            $(\"{$class['end']}\").on(\"dp.change\", function (e) {\n                $('{$class['start']}').data(\"DateTimePicker\").maxDate(e.date);\n            });\nEOT;\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Datetime.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nclass Datetime extends Date\n{\n    protected $format = 'YYYY-MM-DD HH:mm:ss';\n\n    public function render()\n    {\n        $this->defaultAttribute('style', 'width: 160px');\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/DatetimeRange.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nclass DatetimeRange extends DateRange\n{\n    protected $format = 'YYYY-MM-DD HH:mm:ss';\n}\n"
  },
  {
    "path": "src/Form/Field/Decimal.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nclass Decimal extends Text\n{\n    protected static $js = [\n        '/vendor/laravel-admin/AdminLTE/plugins/input-mask/jquery.inputmask.bundle.min.js',\n    ];\n\n    /**\n     * @see https://github.com/RobinHerbots/Inputmask#options\n     *\n     * @var array\n     */\n    protected $options = [\n        'alias'      => 'decimal',\n        'rightAlign' => true,\n    ];\n\n    public function render()\n    {\n        $this->inputmask($this->options);\n\n        $this->prepend('<i class=\"fa '.$this->icon.' fa-fw\"></i>')\n            ->defaultAttribute('style', 'width: 130px');\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Display.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Form\\Field;\n\nclass Display extends Field\n{\n}\n"
  },
  {
    "path": "src/Form/Field/Divider.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Form\\Field;\n\nclass Divider extends Field\n{\n    protected $title;\n\n    public function __construct($title = '')\n    {\n        $this->title = $title;\n    }\n\n    public function render()\n    {\n        if (empty($this->title)) {\n            return '<hr>';\n        }\n\n        return <<<HTML\n<div style=\"height: 20px; border-bottom: 1px solid #eee; text-align: center;margin-top: 20px;margin-bottom: 20px;\">\n  <span style=\"font-size: 18px; background-color: #ffffff; padding: 0 10px;\">\n    {$this->title}\n  </span>\n</div>\nHTML;\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Editor.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Form\\Field;\n\nclass Editor extends Field\n{\n    protected static $js = [\n        '//cdn.ckeditor.com/4.5.10/standard/ckeditor.js',\n    ];\n\n    public function render()\n    {\n        $this->script = \"CKEDITOR.replace('{$this->id}');\";\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Email.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nclass Email extends Text\n{\n    protected $rules = 'nullable|email';\n\n    public function render()\n    {\n        $this->prepend('<i class=\"fa fa-envelope fa-fw\"></i>')\n            ->defaultAttribute('type', 'email');\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Embeds.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Form\\EmbeddedForm;\nuse Encore\\Admin\\Form\\Field;\nuse Encore\\Admin\\Widgets\\Form as WidgetForm;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Str;\n\nclass Embeds extends Field\n{\n    /**\n     * @var \\Closure\n     */\n    protected $builder = null;\n\n    /**\n     * Create a new HasMany field instance.\n     *\n     * @param string $column\n     * @param array  $arguments\n     */\n    public function __construct($column, $arguments = [])\n    {\n        $this->column = $column;\n\n        if (count($arguments) == 1) {\n            $this->label = $this->formatLabel();\n            $this->builder = $arguments[0];\n        }\n\n        if (count($arguments) == 2) {\n            list($this->label, $this->builder) = $arguments;\n        }\n    }\n\n    /**\n     * Prepare input data for insert or update.\n     *\n     * @param array $input\n     *\n     * @return array\n     */\n    public function prepare($input)\n    {\n        $form = $this->buildEmbeddedForm();\n\n        return $form->setOriginal($this->original)->prepare($input);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function getValidator(array $input)\n    {\n        if (!array_key_exists($this->column, $input)) {\n            return false;\n        }\n\n        $input = Arr::only($input, $this->column);\n\n        $rules = $attributes = [];\n\n        /** @var Field $field */\n        foreach ($this->buildEmbeddedForm()->fields() as $field) {\n            if (!$fieldRules = $field->getRules()) {\n                continue;\n            }\n\n            $column = $field->column();\n\n            /*\n             *\n             * For single column field format rules to:\n             * [\n             *     'extra.name' => 'required'\n             *     'extra.email' => 'required'\n             * ]\n             *\n             * For multiple column field with rules like 'required':\n             * 'extra' => [\n             *     'start' => 'start_at'\n             *     'end'   => 'end_at',\n             * ]\n             *\n             * format rules to:\n             * [\n             *     'extra.start_atstart' => 'required'\n             *     'extra.end_atend' => 'required'\n             * ]\n             */\n            if (is_array($column)) {\n                foreach ($column as $key => $name) {\n                    $rules[\"{$this->column}.$name$key\"] = $fieldRules;\n                }\n\n                $this->resetInputKey($input, $column);\n            } else {\n                $rules[\"{$this->column}.$column\"] = $fieldRules;\n            }\n\n            /**\n             * For single column field format attributes to:\n             * [\n             *     'extra.name' => $label\n             *     'extra.email' => $label\n             * ].\n             *\n             * For multiple column field with rules like 'required':\n             * 'extra' => [\n             *     'start' => 'start_at'\n             *     'end'   => 'end_at',\n             * ]\n             *\n             * format rules to:\n             * [\n             *     'extra.start_atstart' => \"$label[start_at]\"\n             *     'extra.end_atend' => \"$label[end_at]\"\n             * ]\n             */\n            $attributes = array_merge(\n                $attributes,\n                $this->formatValidationAttribute($input, $field->label(), $column)\n            );\n        }\n\n        if (empty($rules)) {\n            return false;\n        }\n\n        return \\validator($input, $rules, $this->getValidationMessages(), $attributes);\n    }\n\n    /**\n     * Format validation attributes.\n     *\n     * @param array  $input\n     * @param string $label\n     * @param string $column\n     *\n     * @return array\n     */\n    protected function formatValidationAttribute($input, $label, $column)\n    {\n        $new = $attributes = [];\n\n        if (is_array($column)) {\n            foreach ($column as $index => $col) {\n                $new[$col.$index] = $col;\n            }\n        }\n\n        foreach (array_keys(Arr::dot($input)) as $key) {\n            if (is_string($column)) {\n                if (Str::endsWith($key, \".$column\")) {\n                    $attributes[$key] = $label;\n                }\n            } else {\n                foreach ($new as $k => $val) {\n                    if (Str::endsWith($key, \".$k\")) {\n                        $attributes[$key] = $label.\"[$val]\";\n                    }\n                }\n            }\n        }\n\n        return $attributes;\n    }\n\n    /**\n     * Reset input key for validation.\n     *\n     * @param array $input\n     * @param array $column $column is the column name array set\n     *\n     * @return void.\n     */\n    public function resetInputKey(array &$input, array $column)\n    {\n        $column = array_flip($column);\n\n        foreach ($input[$this->column] as $key => $value) {\n            if (!array_key_exists($key, $column)) {\n                continue;\n            }\n\n            $newKey = $key.$column[$key];\n\n            /*\n             * set new key\n             */\n            Arr::set($input, \"{$this->column}.$newKey\", $value);\n            /*\n             * forget the old key and value\n             */\n            Arr::forget($input, \"{$this->column}.$key\");\n        }\n    }\n\n    /**\n     * Get data for Embedded form.\n     *\n     * Normally, data is obtained from the database.\n     *\n     * When the data validation errors, data is obtained from session flash.\n     *\n     * @return array\n     */\n    protected function getEmbeddedData()\n    {\n        if ($old = old($this->column)) {\n            return $old;\n        }\n\n        if (empty($this->value)) {\n            return [];\n        }\n\n        if (is_string($this->value)) {\n            return json_decode($this->value, true);\n        }\n\n        return (array) $this->value;\n    }\n\n    /**\n     * Build a Embedded Form and fill data.\n     *\n     * @return EmbeddedForm\n     */\n    protected function buildEmbeddedForm()\n    {\n        $form = new EmbeddedForm($this->getEmbeddedColumnName());\n\n        if ($this->form instanceof WidgetForm) {\n            $form->setParentWidgetForm($this->form);\n        } else {\n            $form->setParent($this->form);\n        }\n\n        call_user_func($this->builder, $form);\n\n        $form->fill($this->getEmbeddedData());\n\n        return $form;\n    }\n\n    /**\n     * Determine the column name to use with the embedded form.\n     *\n     * @return array|string\n     */\n    protected function getEmbeddedColumnName()\n    {\n        if ($this->isNested()) {\n            return $this->elementName;\n        }\n\n        return $this->column;\n    }\n\n    /**\n     * Check if the field is in a nested form.\n     *\n     * @return bool\n     */\n    protected function isNested()\n    {\n        return !empty($this->elementName);\n    }\n\n    /**\n     * Render the form.\n     *\n     * @return \\Illuminate\\View\\View\n     */\n    public function render()\n    {\n        return parent::fieldRender(['form' => $this->buildEmbeddedForm()]);\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Fieldset.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Admin;\n\nclass Fieldset\n{\n    protected $name = '';\n\n    public function __construct()\n    {\n        $this->name = uniqid('fieldset-');\n    }\n\n    public function start($title)\n    {\n        $script = <<<SCRIPT\n$('.{$this->name}-title').click(function () {\n    $(\"i\", this).toggleClass(\"fa-angle-double-down fa-angle-double-up\");\n});\nSCRIPT;\n\n        Admin::script($script);\n\n        return <<<HTML\n<div>\n    <div style=\"height: 20px; border-bottom: 1px solid #eee; text-align: center;margin-top: 20px;margin-bottom: 20px;\">\n      <span style=\"font-size: 16px; background-color: #ffffff; padding: 0 10px;\">\n        <a data-toggle=\"collapse\" href=\"#{$this->name}\" class=\"{$this->name}-title\">\n          <i class=\"fa fa-angle-double-up\"></i>&nbsp;&nbsp;{$title}\n        </a>\n      </span>\n    </div>\n    <div class=\"collapse in\" id=\"{$this->name}\">\nHTML;\n    }\n\n    public function end()\n    {\n        return '</div></div>';\n    }\n\n    public function collapsed()\n    {\n        $script = <<<SCRIPT\n$(\"#{$this->name}\").removeClass(\"in\");\n$(\".{$this->name}-title i\").toggleClass(\"fa-angle-double-down fa-angle-double-up\");\nSCRIPT;\n\n        Admin::script($script);\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/File.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Form\\Field;\nuse Illuminate\\Support\\Arr;\nuse Symfony\\Component\\HttpFoundation\\File\\UploadedFile;\n\nclass File extends Field\n{\n    use UploadField;\n    use HasValuePicker;\n\n    /**\n     * Css.\n     *\n     * @var array\n     */\n    protected static $css = [\n        '/vendor/laravel-admin/bootstrap-fileinput/css/fileinput.min.css?v=4.5.2',\n    ];\n\n    /**\n     * Js.\n     *\n     * @var array\n     */\n    protected static $js = [\n        '/vendor/laravel-admin/bootstrap-fileinput/js/plugins/canvas-to-blob.min.js',\n        '/vendor/laravel-admin/bootstrap-fileinput/js/fileinput.min.js?v=4.5.2',\n    ];\n\n    /**\n     * Create a new File instance.\n     *\n     * @param string $column\n     * @param array  $arguments\n     */\n    public function __construct($column, $arguments = [])\n    {\n        $this->initStorage();\n\n        parent::__construct($column, $arguments);\n    }\n\n    /**\n     * Default directory for file to upload.\n     *\n     * @return mixed\n     */\n    public function defaultDirectory()\n    {\n        return config('admin.upload.directory.file');\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function getValidator(array $input)\n    {\n        if (request()->has(static::FILE_DELETE_FLAG)) {\n            return false;\n        }\n\n        if ($this->validator) {\n            return $this->validator->call($this, $input);\n        }\n\n        /*\n         * If has original value, means the form is in edit mode,\n         * then remove required rule from rules.\n         */\n        if ($this->original()) {\n            $this->removeRule('required');\n        }\n\n        /*\n         * Make input data validatable if the column data is `null`.\n         */\n        if (Arr::has($input, $this->column) && is_null(Arr::get($input, $this->column))) {\n            $input[$this->column] = '';\n        }\n\n        $rules = $attributes = [];\n\n        if (!$fieldRules = $this->getRules()) {\n            return false;\n        }\n\n        $rules[$this->column] = $fieldRules;\n        $attributes[$this->column] = $this->label;\n\n        return \\validator($input, $rules, $this->getValidationMessages(), $attributes);\n    }\n\n    /**\n     * Prepare for saving.\n     *\n     * @param UploadedFile|array $file\n     *\n     * @return mixed|string\n     */\n    public function prepare($file)\n    {\n        if ($this->picker) {\n            return parent::prepare($file);\n        }\n\n        if (request()->has(static::FILE_DELETE_FLAG)) {\n            return $this->destroy();\n        }\n\n        $this->name = $this->getStoreName($file);\n\n        return $this->uploadAndDeleteOriginal($file);\n    }\n\n    /**\n     * Upload file and delete original file.\n     *\n     * @param UploadedFile $file\n     *\n     * @return mixed\n     */\n    protected function uploadAndDeleteOriginal(UploadedFile $file)\n    {\n        $this->renameIfExists($file);\n\n        $path = null;\n\n        if (!is_null($this->storagePermission)) {\n            $path = $this->storage->putFileAs($this->getDirectory(), $file, $this->name, $this->storagePermission);\n        } else {\n            $path = $this->storage->putFileAs($this->getDirectory(), $file, $this->name);\n        }\n\n        $this->destroy();\n\n        return $path;\n    }\n\n    /**\n     * Preview html for file-upload plugin.\n     *\n     * @return string\n     */\n    protected function preview()\n    {\n        return $this->objectUrl($this->value);\n    }\n\n    /**\n     * Hides the file preview.\n     *\n     * @return $this\n     */\n    public function hidePreview()\n    {\n        return $this->options([\n            'showPreview' => false,\n        ]);\n    }\n\n    /**\n     * Initialize the caption.\n     *\n     * @param string $caption\n     *\n     * @return string\n     */\n    protected function initialCaption($caption)\n    {\n        return basename($caption);\n    }\n\n    /**\n     * @return array\n     */\n    protected function initialPreviewConfig()\n    {\n        $config = ['caption' => basename($this->value), 'key' => 0];\n\n        $config = array_merge($config, $this->guessPreviewType($this->value));\n\n        return [$config];\n    }\n\n    /**\n     * @param string $options\n     */\n    protected function setupScripts($options)\n    {\n        $this->script = <<<EOT\n$(\"input{$this->getElementClassSelector()}\").fileinput({$options});\nEOT;\n\n        if ($this->fileActionSettings['showRemove']) {\n            $text = [\n                'title'   => trans('admin.delete_confirm'),\n                'confirm' => trans('admin.confirm'),\n                'cancel'  => trans('admin.cancel'),\n            ];\n\n            $this->script .= <<<EOT\n$(\"input{$this->getElementClassSelector()}\").on('filebeforedelete', function() {\n\n    return new Promise(function(resolve, reject) {\n\n        var remove = resolve;\n\n        swal({\n            title: \"{$text['title']}\",\n            type: \"warning\",\n            showCancelButton: true,\n            confirmButtonColor: \"#DD6B55\",\n            confirmButtonText: \"{$text['confirm']}\",\n            showLoaderOnConfirm: true,\n            cancelButtonText: \"{$text['cancel']}\",\n            preConfirm: function() {\n                return new Promise(function(resolve) {\n                    resolve(remove());\n                });\n            }\n        });\n    });\n});\nEOT;\n        }\n    }\n\n    /**\n     * Render file upload field.\n     *\n     * @return \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View\n     */\n    public function render()\n    {\n        if ($this->picker) {\n            return $this->renderFilePicker();\n        }\n\n        $this->options(['overwriteInitial' => true, 'msgPlaceholder' => trans('admin.choose_file')]);\n\n        $this->setupDefaultOptions();\n\n        if (!empty($this->value)) {\n            $this->attribute('data-initial-preview', $this->preview());\n            $this->attribute('data-initial-caption', $this->initialCaption($this->value));\n\n            $this->setupPreviewOptions();\n            /*\n             * If has original value, means the form is in edit mode,\n             * then remove required rule from rules.\n             */\n            unset($this->attributes['required']);\n        }\n\n        $options = json_encode_options($this->options);\n\n        $this->setupScripts($options);\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/HasMany.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Form;\nuse Encore\\Admin\\Form\\Field;\nuse Encore\\Admin\\Form\\NestedForm;\nuse Encore\\Admin\\Widgets\\Form as WidgetForm;\nuse Illuminate\\Database\\Eloquent\\Relations\\HasMany as Relation;\nuse Illuminate\\Database\\Eloquent\\Relations\\MorphMany;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Str;\n\n/**\n * Class HasMany.\n */\nclass HasMany extends Field\n{\n    /**\n     * Relation name.\n     *\n     * @var string\n     */\n    protected $relationName = '';\n\n    /**\n     * Form builder.\n     *\n     * @var \\Closure\n     */\n    protected $builder = null;\n\n    /**\n     * Form data.\n     *\n     * @var array\n     */\n    protected $value = [];\n\n    /**\n     * View Mode.\n     *\n     * Supports `default` and `tab` currently.\n     *\n     * @var string\n     */\n    protected $viewMode = 'default';\n\n    /**\n     * Available views for HasMany field.\n     *\n     * @var array\n     */\n    protected $views = [\n        'default' => 'admin::form.hasmany',\n        'tab'     => 'admin::form.hasmanytab',\n        'table'   => 'admin::form.hasmanytable',\n    ];\n\n    /**\n     * Options for template.\n     *\n     * @var array\n     */\n    protected $options = [\n        'allowCreate' => true,\n        'allowDelete' => true,\n    ];\n\n    /**\n     * Distinct fields.\n     *\n     * @var array\n     */\n    protected $distinctFields = [];\n\n    /**\n     * Create a new HasMany field instance.\n     *\n     * @param $relationName\n     * @param array $arguments\n     */\n    public function __construct($relationName, $arguments = [])\n    {\n        $this->relationName = $relationName;\n\n        $this->column = $relationName;\n\n        if (count($arguments) == 1) {\n            $this->label = $this->formatLabel();\n            $this->builder = $arguments[0];\n        }\n\n        if (count($arguments) == 2) {\n            list($this->label, $this->builder) = $arguments;\n        }\n    }\n\n    /**\n     * Get validator for this field.\n     *\n     * @param array $input\n     *\n     * @return bool|\\Illuminate\\Contracts\\Validation\\Validator\n     */\n    public function getValidator(array $input)\n    {\n        if (!array_key_exists($this->column, $input)) {\n            return false;\n        }\n\n        $input = Arr::only($input, $this->column);\n\n        /** unset item that contains remove flag */\n        foreach ($input[$this->column] as $key => $value) {\n            if ($value[NestedForm::REMOVE_FLAG_NAME]) {\n                unset($input[$this->column][$key]);\n            }\n        }\n\n        $form = $this->buildNestedForm($this->column, $this->builder);\n\n        $rules = $attributes = [];\n\n        /* @var Field $field */\n        foreach ($form->fields() as $field) {\n            if (!$fieldRules = $field->getRules()) {\n                continue;\n            }\n\n            $column = $field->column();\n\n            if (is_array($column)) {\n                foreach ($column as $key => $name) {\n                    $rules[$name.$key] = $fieldRules;\n                }\n\n                $this->resetInputKey($input, $column);\n            } else {\n                $rules[$column] = $fieldRules;\n            }\n\n            $attributes = array_merge(\n                $attributes,\n                $this->formatValidationAttribute($input, $field->label(), $column)\n            );\n        }\n\n        Arr::forget($rules, NestedForm::REMOVE_FLAG_NAME);\n\n        if (empty($rules)) {\n            return false;\n        }\n\n        $newRules = [];\n        $newInput = [];\n\n        foreach ($rules as $column => $rule) {\n            foreach (array_keys($input[$this->column]) as $key) {\n                $newRules[\"{$this->column}.$key.$column\"] = $rule;\n                if (isset($input[$this->column][$key][$column]) &&\n                    is_array($input[$this->column][$key][$column])) {\n                    foreach ($input[$this->column][$key][$column] as $vkey => $value) {\n                        $newInput[\"{$this->column}.$key.{$column}$vkey\"] = $value;\n                    }\n                }\n            }\n        }\n\n        if (empty($newInput)) {\n            $newInput = $input;\n        }\n\n        $this->appendDistinctRules($newRules);\n\n        return \\validator($newInput, $newRules, $this->getValidationMessages(), $attributes);\n    }\n\n    /**\n     * Set distinct fields.\n     *\n     * @param array $fields\n     *\n     * @return $this\n     */\n    public function distinctFields(array $fields)\n    {\n        $this->distinctFields = $fields;\n\n        return $this;\n    }\n\n    /**\n     * Append distinct rules.\n     *\n     * @param array $rules\n     */\n    protected function appendDistinctRules(array &$rules)\n    {\n        foreach ($this->distinctFields as $field) {\n            $rules[\"{$this->column}.*.$field\"] = 'distinct';\n        }\n    }\n\n    /**\n     * Format validation attributes.\n     *\n     * @param array  $input\n     * @param string $label\n     * @param string $column\n     *\n     * @return array\n     */\n    protected function formatValidationAttribute($input, $label, $column)\n    {\n        $new = $attributes = [];\n\n        if (is_array($column)) {\n            foreach ($column as $index => $col) {\n                $new[$col.$index] = $col;\n            }\n        }\n\n        foreach (array_keys(Arr::dot($input)) as $key) {\n            if (is_string($column)) {\n                if (Str::endsWith($key, \".$column\")) {\n                    $attributes[$key] = $label;\n                }\n            } else {\n                foreach ($new as $k => $val) {\n                    if (Str::endsWith($key, \".$k\")) {\n                        $attributes[$key] = $label.\"[$val]\";\n                    }\n                }\n            }\n        }\n\n        return $attributes;\n    }\n\n    /**\n     * Reset input key for validation.\n     *\n     * @param array $input\n     * @param array $column $column is the column name array set\n     *\n     * @return void.\n     */\n    protected function resetInputKey(array &$input, array $column)\n    {\n        /**\n         * flip the column name array set.\n         *\n         * for example, for the DateRange, the column like as below\n         *\n         * [\"start\" => \"created_at\", \"end\" => \"updated_at\"]\n         *\n         * to:\n         *\n         * [ \"created_at\" => \"start\", \"updated_at\" => \"end\" ]\n         */\n        $column = array_flip($column);\n\n        /**\n         * $this->column is the inputs array's node name, default is the relation name.\n         *\n         * So... $input[$this->column] is the data of this column's inputs data\n         *\n         * in the HasMany relation, has many data/field set, $set is field set in the below\n         */\n        foreach ($input[$this->column] as $index => $set) {\n\n            /*\n             * foreach the field set to find the corresponding $column\n             */\n            foreach ($set as $name => $value) {\n                /*\n                 * if doesn't have column name, continue to the next loop\n                 */\n                if (!array_key_exists($name, $column)) {\n                    continue;\n                }\n\n                /**\n                 * example:  $newKey = created_atstart.\n                 *\n                 * Σ( ° △ °|||)︴\n                 *\n                 * I don't know why a form need range input? Only can imagine is for range search....\n                 */\n                $newKey = $name.$column[$name];\n\n                /*\n                 * set new key\n                 */\n                Arr::set($input, \"{$this->column}.$index.$newKey\", $value);\n                /*\n                 * forget the old key and value\n                 */\n                Arr::forget($input, \"{$this->column}.$index.$name\");\n            }\n        }\n    }\n\n    /**\n     * Prepare input data for insert or update.\n     *\n     * @param array $input\n     *\n     * @return array\n     */\n    public function prepare($input)\n    {\n        $form = $this->buildNestedForm($this->column, $this->builder);\n\n        return $form->setOriginal($this->original, $this->getKeyName())->prepare($input);\n    }\n\n    /**\n     * Build a Nested form.\n     *\n     * @param string   $column\n     * @param \\Closure $builder\n     * @param null     $model\n     *\n     * @return NestedForm\n     */\n    protected function buildNestedForm($column, \\Closure $builder, $model = null)\n    {\n        $form = new Form\\NestedForm($column, $model);\n\n        if ($this->form instanceof WidgetForm) {\n            $form->setWidgetForm($this->form);\n        } else {\n            $form->setForm($this->form);\n        }\n\n        call_user_func($builder, $form);\n\n        $form->hidden($this->getKeyName());\n\n        $form->hidden(NestedForm::REMOVE_FLAG_NAME)->default(0)->addElementClass(NestedForm::REMOVE_FLAG_CLASS);\n\n        return $form;\n    }\n\n    /**\n     * Get the HasMany relation key name.\n     *\n     * @return string\n     */\n    protected function getKeyName()\n    {\n        if (is_null($this->form)) {\n            return;\n        }\n\n        return $this->form->model()->{$this->relationName}()->getRelated()->getKeyName();\n    }\n\n    /**\n     * Set view mode.\n     *\n     * @param string $mode currently support `tab` mode.\n     *\n     * @return $this\n     *\n     * @author Edwin Hui\n     */\n    public function mode($mode)\n    {\n        $this->viewMode = $mode;\n\n        return $this;\n    }\n\n    /**\n     * Use tab mode to showing hasmany field.\n     *\n     * @return HasMany\n     */\n    public function useTab()\n    {\n        return $this->mode('tab');\n    }\n\n    /**\n     * Use table mode to showing hasmany field.\n     *\n     * @return HasMany\n     */\n    public function useTable()\n    {\n        return $this->mode('table');\n    }\n\n    /**\n     * Build Nested form for related data.\n     *\n     * @throws \\Exception\n     *\n     * @return array\n     */\n    protected function buildRelatedForms()\n    {\n        if (is_null($this->form)) {\n            return [];\n        }\n\n        $model = $this->form->model();\n\n        $relation = call_user_func([$model, $this->relationName]);\n\n        if (!$relation instanceof Relation && !$relation instanceof MorphMany) {\n            throw new \\Exception('hasMany field must be a HasMany or MorphMany relation.');\n        }\n\n        $forms = [];\n\n        /*\n         * If redirect from `exception` or `validation error` page.\n         *\n         * Then get form data from session flash.\n         *\n         * Else get data from database.\n         */\n        if ($values = old($this->column)) {\n            foreach ($values as $key => $data) {\n                if ($data[NestedForm::REMOVE_FLAG_NAME] == 1) {\n                    continue;\n                }\n\n                $model = $relation->getRelated()->replicate()->forceFill($data);\n\n                $forms[$key] = $this->buildNestedForm($this->column, $this->builder, $model)\n                    ->fill($data);\n            }\n        } else {\n            if (empty($this->value)) {\n                return [];\n            }\n\n            foreach ($this->value as $data) {\n                $key = Arr::get($data, $relation->getRelated()->getKeyName());\n\n                $model = $relation->getRelated()->replicate()->forceFill($data);\n\n                $forms[$key] = $this->buildNestedForm($this->column, $this->builder, $model)\n                    ->fill($data);\n            }\n        }\n\n        return $forms;\n    }\n\n    /**\n     * Setup script for this field in different view mode.\n     *\n     * @param string $script\n     *\n     * @return void\n     */\n    protected function setupScript($script)\n    {\n        $method = 'setupScriptFor'.ucfirst($this->viewMode).'View';\n\n        call_user_func([$this, $method], $script);\n    }\n\n    /**\n     * Setup default template script.\n     *\n     * @param string $templateScript\n     *\n     * @return void\n     */\n    protected function setupScriptForDefaultView($templateScript)\n    {\n        $removeClass = NestedForm::REMOVE_FLAG_CLASS;\n        $defaultKey = NestedForm::DEFAULT_KEY_NAME;\n\n        /**\n         * When add a new sub form, replace all element key in new sub form.\n         *\n         * @example comments[new___key__][title]  => comments[new_{index}][title]\n         *\n         * {count} is increment number of current sub form count.\n         */\n        $script = <<<EOT\nvar index = 0;\n$('#has-many-{$this->column}').off('click', '.add').on('click', '.add', function () {\n\n    var tpl = $('template.{$this->column}-tpl');\n\n    index++;\n\n    var template = tpl.html().replace(/{$defaultKey}/g, index);\n    $('.has-many-{$this->column}-forms').append(template);\n    {$templateScript}\n    return false;\n});\n\n$('#has-many-{$this->column}').off('click', '.remove').on('click', '.remove', function () {\n    $(this).closest('.has-many-{$this->column}-form').find('input').removeAttr('required');\n    $(this).closest('.has-many-{$this->column}-form').hide();\n    $(this).closest('.has-many-{$this->column}-form').find('.$removeClass').val(1);\n    return false;\n});\n\nEOT;\n\n        Admin::script($script);\n    }\n\n    /**\n     * Setup tab template script.\n     *\n     * @param string $templateScript\n     *\n     * @return void\n     */\n    protected function setupScriptForTabView($templateScript)\n    {\n        $removeClass = NestedForm::REMOVE_FLAG_CLASS;\n        $defaultKey = NestedForm::DEFAULT_KEY_NAME;\n\n        $script = <<<EOT\n\n$('#has-many-{$this->column} > .nav').off('click', 'i.close-tab').on('click', 'i.close-tab', function(){\n    var \\$navTab = $(this).siblings('a');\n    var \\$pane = $(\\$navTab.attr('href'));\n    if( \\$pane.hasClass('new') ){\n        \\$pane.remove();\n    }else{\n        \\$pane.removeClass('active').find('.$removeClass').val(1);\n    }\n    if(\\$navTab.closest('li').hasClass('active')){\n        \\$navTab.closest('li').remove();\n        $('#has-many-{$this->column} > .nav > li:nth-child(1) > a').tab('show');\n    }else{\n        \\$navTab.closest('li').remove();\n    }\n});\n\nvar index = 0;\n$('#has-many-{$this->column} > .header').off('click', '.add').on('click', '.add', function(){\n    index++;\n    var navTabHtml = $('#has-many-{$this->column} > template.nav-tab-tpl').html().replace(/{$defaultKey}/g, index);\n    var paneHtml = $('#has-many-{$this->column} > template.pane-tpl').html().replace(/{$defaultKey}/g, index);\n    $('#has-many-{$this->column} > .nav').append(navTabHtml);\n    $('#has-many-{$this->column} > .tab-content').append(paneHtml);\n    $('#has-many-{$this->column} > .nav > li:last-child a').tab('show');\n    {$templateScript}\n});\n\nif ($('.has-error').length) {\n    $('.has-error').parent('.tab-pane').each(function () {\n        var tabId = '#'+$(this).attr('id');\n        $('li a[href=\"'+tabId+'\"] i').removeClass('hide');\n    });\n\n    var first = $('.has-error:first').parent().attr('id');\n    $('li a[href=\"#'+first+'\"]').tab('show');\n}\nEOT;\n\n        Admin::script($script);\n    }\n\n    /**\n     * Setup default template script.\n     *\n     * @param string $templateScript\n     *\n     * @return void\n     */\n    protected function setupScriptForTableView($templateScript)\n    {\n        $removeClass = NestedForm::REMOVE_FLAG_CLASS;\n        $defaultKey = NestedForm::DEFAULT_KEY_NAME;\n\n        /**\n         * When add a new sub form, replace all element key in new sub form.\n         *\n         * @example comments[new___key__][title]  => comments[new_{index}][title]\n         *\n         * {count} is increment number of current sub form count.\n         */\n        $script = <<<EOT\nvar index = 0;\n$('#has-many-{$this->column}').on('click', '.add', function () {\n\n    var tpl = $('template.{$this->column}-tpl');\n\n    index++;\n\n    var template = tpl.html().replace(/{$defaultKey}/g, index);\n    $('.has-many-{$this->column}-forms').append(template);\n    {$templateScript}\n    return false;\n});\n\n$('#has-many-{$this->column}').on('click', '.remove', function () {\n    var first_input_name = $(this).closest('.has-many-{$this->column}-form').find('input[name]:first').attr('name');\n    if (first_input_name.match('{$this->column}\\\\\\[new_')) {\n        $(this).closest('.has-many-{$this->column}-form').remove();\n    } else {\n        $(this).closest('.has-many-{$this->column}-form').hide();\n        $(this).closest('.has-many-{$this->column}-form').find('.$removeClass').val(1);\n        $(this).closest('.has-many-{$this->column}-form').find('input').removeAttr('required');\n    }\n    return false;\n});\n\nEOT;\n\n        Admin::script($script);\n    }\n\n    /**\n     * Disable create button.\n     *\n     * @return $this\n     */\n    public function disableCreate()\n    {\n        $this->options['allowCreate'] = false;\n\n        return $this;\n    }\n\n    /**\n     * Disable delete button.\n     *\n     * @return $this\n     */\n    public function disableDelete()\n    {\n        $this->options['allowDelete'] = false;\n\n        return $this;\n    }\n\n    /**\n     * Render the `HasMany` field.\n     *\n     * @throws \\Exception\n     *\n     * @return \\Illuminate\\View\\View\n     */\n    public function render()\n    {\n        if (!$this->shouldRender()) {\n            return '';\n        }\n\n        if ($this->viewMode == 'table') {\n            return $this->renderTable();\n        }\n\n        // specify a view to render.\n        $this->view = $this->views[$this->viewMode];\n\n        list($template, $script) = $this->buildNestedForm($this->column, $this->builder)\n            ->getTemplateHtmlAndScript();\n\n        $this->setupScript($script);\n\n        return parent::fieldRender([\n            'forms'        => $this->buildRelatedForms(),\n            'template'     => $template,\n            'relationName' => $this->relationName,\n            'options'      => $this->options,\n        ]);\n    }\n\n    /**\n     * Render the `HasMany` field for table style.\n     *\n     * @throws \\Exception\n     *\n     * @return mixed\n     */\n    protected function renderTable()\n    {\n        $headers = [];\n        $fields = [];\n        $hidden = [];\n        $scripts = [];\n\n        /* @var Field $field */\n        foreach ($this->buildNestedForm($this->column, $this->builder)->fields() as $field) {\n            if (is_a($field, Hidden::class)) {\n                $hidden[] = $field->render();\n            } else {\n                /* Hide label and set field width 100% */\n                $field->setLabelClass(['hidden']);\n                $field->setWidth(12, 0);\n                $fields[] = $field->render();\n                $headers[] = $field->label();\n            }\n\n            /*\n             * Get and remove the last script of Admin::$script stack.\n             */\n            if ($field->getScript()) {\n                $scripts[] = array_pop(Admin::$script);\n            }\n        }\n\n        /* Build row elements */\n        $template = array_reduce($fields, function ($all, $field) {\n            $all .= \"<td>{$field}</td>\";\n\n            return $all;\n        }, '');\n\n        /* Build cell with hidden elements */\n        $template .= '<td class=\"hidden\">'.implode('', $hidden).'</td>';\n\n        $this->setupScript(implode(\"\\r\\n\", $scripts));\n\n        // specify a view to render.\n        $this->view = $this->views[$this->viewMode];\n\n        return parent::fieldRender([\n            'headers'      => $headers,\n            'forms'        => $this->buildRelatedForms(),\n            'template'     => $template,\n            'relationName' => $this->relationName,\n            'options'      => $this->options,\n        ]);\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/HasValuePicker.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Form\\Field;\n\n/**\n * @mixin Field\n */\ntrait HasValuePicker\n{\n    /**\n     * @var ValuePicker\n     */\n    protected $picker;\n\n    /**\n     * @param string $picker\n     * @param string $column\n     *\n     * @return $this\n     */\n    public function pick($picker, $column = '')\n    {\n        $this->picker = new ValuePicker($picker, $column);\n\n        return $this;\n    }\n\n    /**\n     * @param string $picker\n     * @param string $column\n     * @param string $separator\n     */\n    public function pickMany($picker, $column = '', $separator = ';')\n    {\n        $this->picker = new ValuePicker($picker, $column, true, $separator);\n\n        return $this;\n    }\n\n    /**\n     * @param \\Closure|null $callback\n     *\n     * @return $this\n     */\n    protected function mountPicker(\\Closure $callback = null)\n    {\n        $this->picker && $this->picker->mount($this, $callback);\n\n        return $this;\n    }\n\n    /**\n     * @return string\n     */\n    public function getRules()\n    {\n        $rules = parent::getRules();\n\n        array_delete($rules, 'image');\n\n        return $rules;\n    }\n\n    /**\n     * @return \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View|string\n     */\n    protected function renderFilePicker()\n    {\n        $this->mountPicker()\n            ->setView('admin::form.filepicker')\n            ->attribute('type', 'text')\n            ->attribute('id', $this->id)\n            ->attribute('name', $this->elementName ?: $this->formatName($this->column))\n            ->attribute('value', old($this->elementName ?: $this->column, $this->value()))\n            ->attribute('class', 'form-control '.$this->getElementClassString())\n            ->attribute('placeholder', $this->getPlaceholder())\n            ->addVariables([\n                'preview' => $this->picker->getPreview(get_called_class()),\n            ]);\n\n        return Admin::component('admin::form.filepicker', $this->variables());\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Hidden.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Form\\Field;\n\nclass Hidden extends Field\n{\n}\n"
  },
  {
    "path": "src/Form/Field/Html.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Form\\Field;\nuse Illuminate\\Support\\Arr;\n\nclass Html extends Field\n{\n    /**\n     * Htmlable.\n     *\n     * @var string|\\Closure\n     */\n    protected $html = '';\n\n    /**\n     * @var string\n     */\n    protected $label = '';\n\n    /**\n     * @var bool\n     */\n    protected $plain = false;\n\n    /**\n     * Create a new Html instance.\n     *\n     * @param mixed $html\n     * @param array $arguments\n     */\n    public function __construct($html, $arguments)\n    {\n        $this->html = $html;\n\n        $this->label = Arr::get($arguments, 0);\n    }\n\n    /**\n     * @return $this\n     */\n    public function plain()\n    {\n        $this->plain = true;\n\n        return $this;\n    }\n\n    /**\n     * Render html field.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        if ($this->html instanceof \\Closure) {\n            $this->html = $this->html->call($this->form->model(), $this->form);\n        }\n\n        if ($this->plain) {\n            return $this->html;\n        }\n\n        $viewClass = $this->getViewElementClasses();\n\n        return <<<EOT\n<div class=\"{$viewClass['form-group']}\">\n    <label  class=\"{$viewClass['label']} control-label\">{$this->label}</label>\n    <div class=\"{$viewClass['field']}\">\n        {$this->html}\n    </div>\n</div>\nEOT;\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Icon.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nclass Icon extends Text\n{\n    protected $default = 'fa-pencil';\n\n    protected static $css = [\n        '/vendor/laravel-admin/fontawesome-iconpicker/dist/css/fontawesome-iconpicker.min.css',\n    ];\n\n    protected static $js = [\n        '/vendor/laravel-admin/fontawesome-iconpicker/dist/js/fontawesome-iconpicker.min.js',\n    ];\n\n    public function render()\n    {\n        $this->script = <<<EOT\n\n$('{$this->getElementClassSelector()}').iconpicker({placement:'bottomLeft'});\n\nEOT;\n\n        $this->prepend('<i class=\"fa fa-pencil fa-fw\"></i>')\n            ->defaultAttribute('style', 'width: 140px');\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Id.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Form\\Field;\n\nclass Id extends Field\n{\n}\n"
  },
  {
    "path": "src/Form/Field/Image.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Symfony\\Component\\HttpFoundation\\File\\UploadedFile;\n\nclass Image extends File\n{\n    use ImageField;\n\n    /**\n     * {@inheritdoc}\n     */\n    protected $view = 'admin::form.file';\n\n    /**\n     *  Validation rules.\n     *\n     * @var string\n     */\n    protected $rules = 'image';\n\n    /**\n     * @param array|UploadedFile $image\n     *\n     * @return string\n     */\n    public function prepare($image)\n    {\n        if ($this->picker) {\n            return parent::prepare($image);\n        }\n\n        if (request()->has(static::FILE_DELETE_FLAG)) {\n            return $this->destroy();\n        }\n\n        $this->name = $this->getStoreName($image);\n\n        $this->callInterventionMethods($image->getRealPath());\n\n        $path = $this->uploadAndDeleteOriginal($image);\n\n        $this->uploadAndDeleteOriginalThumbnail($image);\n\n        return $path;\n    }\n\n    /**\n     * force file type to image.\n     *\n     * @param $file\n     *\n     * @return array|bool|int[]|string[]\n     */\n    public function guessPreviewType($file)\n    {\n        $extra = parent::guessPreviewType($file);\n        $extra['type'] = 'image';\n\n        return $extra;\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/ImageField.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Illuminate\\Support\\Str;\nuse Intervention\\Image\\Constraint;\nuse Intervention\\Image\\Facades\\Image as InterventionImage;\nuse Intervention\\Image\\ImageManagerStatic;\nuse Symfony\\Component\\HttpFoundation\\File\\UploadedFile;\n\ntrait ImageField\n{\n    /**\n     * Intervention calls.\n     *\n     * @var array\n     */\n    protected $interventionCalls = [];\n\n    /**\n     * Thumbnail settings.\n     *\n     * @var array\n     */\n    protected $thumbnails = [];\n\n    /**\n     * Default directory for file to upload.\n     *\n     * @return mixed\n     */\n    public function defaultDirectory()\n    {\n        return config('admin.upload.directory.image');\n    }\n\n    /**\n     * Execute Intervention calls.\n     *\n     * @param string $target\n     *\n     * @return mixed\n     */\n    public function callInterventionMethods($target)\n    {\n        if (!empty($this->interventionCalls)) {\n            $image = ImageManagerStatic::make($target);\n\n            foreach ($this->interventionCalls as $call) {\n                call_user_func_array(\n                    [$image, $call['method']],\n                    $call['arguments']\n                )->save($target);\n            }\n        }\n\n        return $target;\n    }\n\n    /**\n     * Call intervention methods.\n     *\n     * @param string $method\n     * @param array  $arguments\n     *\n     * @throws \\Exception\n     *\n     * @return $this\n     */\n    public function __call($method, $arguments)\n    {\n        if (static::hasMacro($method)) {\n            return $this;\n        }\n\n        if (!class_exists(ImageManagerStatic::class)) {\n            throw new \\Exception('To use image handling and manipulation, please install [intervention/image] first.');\n        }\n\n        $this->interventionCalls[] = [\n            'method'    => $method,\n            'arguments' => $arguments,\n        ];\n\n        return $this;\n    }\n\n    /**\n     * Render a image form field.\n     *\n     * @return \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View\n     */\n    public function render()\n    {\n        $this->options(['allowedFileTypes' => ['image'], 'msgPlaceholder' => trans('admin.choose_image')]);\n\n        return parent::render();\n    }\n\n    /**\n     * @param string|array $name\n     * @param int          $width\n     * @param int          $height\n     *\n     * @return $this\n     */\n    public function thumbnail($name, int $width = null, int $height = null)\n    {\n        if (func_num_args() == 1 && is_array($name)) {\n            foreach ($name as $key => $size) {\n                if (count($size) >= 2) {\n                    $this->thumbnails[$key] = $size;\n                }\n            }\n        } elseif (func_num_args() == 3) {\n            $this->thumbnails[$name] = [$width, $height];\n        }\n\n        return $this;\n    }\n\n    /**\n     * Destroy original thumbnail files.\n     *\n     * @return void.\n     */\n    public function destroyThumbnail()\n    {\n        if ($this->retainable) {\n            return;\n        }\n\n        foreach ($this->thumbnails as $name => $_) {\n            /*  Refactoring actual remove lofic to another method destroyThumbnailFile()\n            to make deleting thumbnails work with multiple as well as\n            single image upload. */\n\n            if (is_array($this->original)) {\n                if (empty($this->original)) {\n                    continue;\n                }\n\n                foreach ($this->original as $original) {\n                    $this->destroyThumbnailFile($original, $name);\n                }\n            } else {\n                $this->destroyThumbnailFile($this->original, $name);\n            }\n        }\n    }\n\n    /**\n     * Remove thumbnail file from disk.\n     *\n     * @return void.\n     */\n    public function destroyThumbnailFile($original, $name)\n    {\n        $ext = @pathinfo($original, PATHINFO_EXTENSION);\n\n        // We remove extension from file name so we can append thumbnail type\n        $path = @Str::replaceLast('.'.$ext, '', $original);\n\n        // We merge original name + thumbnail name + extension\n        $path = $path.'-'.$name.'.'.$ext;\n\n        if ($this->storage->exists($path)) {\n            $this->storage->delete($path);\n        }\n    }\n\n    /**\n     * Upload file and delete original thumbnail files.\n     *\n     * @param UploadedFile $file\n     *\n     * @return $this\n     */\n    protected function uploadAndDeleteOriginalThumbnail(UploadedFile $file)\n    {\n        foreach ($this->thumbnails as $name => $size) {\n            // We need to get extension type ( .jpeg , .png ...)\n            $ext = pathinfo($this->name, PATHINFO_EXTENSION);\n\n            // We remove extension from file name so we can append thumbnail type\n            $path = Str::replaceLast('.'.$ext, '', $this->name);\n\n            // We merge original name + thumbnail name + extension\n            $path = $path.'-'.$name.'.'.$ext;\n\n            /** @var \\Intervention\\Image\\Image $image */\n            $image = InterventionImage::make($file);\n\n            $action = $size[2] ?? 'resize';\n            // Resize image with aspect ratio\n            $image->$action($size[0], $size[1], function (Constraint $constraint) {\n                $constraint->aspectRatio();\n            })->resizeCanvas($size[0], $size[1], 'center', false, '#ffffff');\n\n            if (!is_null($this->storagePermission)) {\n                $this->storage->put(\"{$this->getDirectory()}/{$path}\", $image->encode(), $this->storagePermission);\n            } else {\n                $this->storage->put(\"{$this->getDirectory()}/{$path}\", $image->encode());\n            }\n        }\n\n        $this->destroyThumbnail();\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Ip.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nclass Ip extends Text\n{\n    protected $rules = 'nullable|ip';\n\n    protected static $js = [\n        '/vendor/laravel-admin/AdminLTE/plugins/input-mask/jquery.inputmask.bundle.min.js',\n    ];\n\n    /**\n     * @see https://github.com/RobinHerbots/Inputmask#options\n     *\n     * @var array\n     */\n    protected $options = [\n        'alias' => 'ip',\n    ];\n\n    public function render()\n    {\n        $this->inputmask($this->options);\n\n        $this->prepend('<i class=\"fa fa-laptop fa-fw\"></i>')\n            ->defaultAttribute('style', 'width: 130px');\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/KeyValue.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Form\\Field;\nuse Illuminate\\Support\\Arr;\n\nclass KeyValue extends Field\n{\n    /**\n     * @var array\n     */\n    protected $value = ['' => ''];\n\n    /**\n     * Fill data to the field.\n     *\n     * @param array $data\n     *\n     * @return void\n     */\n    public function fill($data)\n    {\n        $this->data = $data;\n\n        $this->value = Arr::get($data, $this->column, $this->value);\n\n        $this->formatValue();\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function getValidator(array $input)\n    {\n        if ($this->validator) {\n            return $this->validator->call($this, $input);\n        }\n\n        if (!is_string($this->column)) {\n            return false;\n        }\n\n        $rules = $attributes = [];\n\n        if (!$fieldRules = $this->getRules()) {\n            return false;\n        }\n\n        if (!Arr::has($input, $this->column)) {\n            return false;\n        }\n\n        $rules[\"{$this->column}.keys.*\"] = 'distinct';\n        $rules[\"{$this->column}.values.*\"] = $fieldRules;\n        $attributes[\"{$this->column}.keys.*\"] = __('Key');\n        $attributes[\"{$this->column}.values.*\"] = __('Value');\n\n        return validator($input, $rules, $this->getValidationMessages(), $attributes);\n    }\n\n    protected function setupScript()\n    {\n        $this->script = <<<SCRIPT\n\n$('.{$this->column}-add').on('click', function () {\n    var tpl = $('template.{$this->column}-tpl').html();\n    $('tbody.kv-{$this->column}-table').append(tpl);\n});\n\n$('tbody').on('click', '.{$this->column}-remove', function () {\n    $(this).closest('tr').remove();\n});\n\nSCRIPT;\n    }\n\n    public function prepare($value)\n    {\n        return array_combine($value['keys'], $value['values']);\n    }\n\n    public function render()\n    {\n        $this->setupScript();\n\n        Admin::style('td .form-group {margin-bottom: 0 !important;}');\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/ListField.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Form\\Field;\nuse Illuminate\\Support\\Arr;\n\nclass ListField extends Field\n{\n    /**\n     * Max list size.\n     *\n     * @var int\n     */\n    protected $max;\n\n    /**\n     * Minimum list size.\n     *\n     * @var int\n     */\n    protected $min = 0;\n\n    /**\n     * @var array\n     */\n    protected $value = [''];\n\n    /**\n     * Set Max list size.\n     *\n     * @param int $size\n     *\n     * @return $this\n     */\n    public function max(int $size)\n    {\n        $this->max = $size;\n\n        return $this;\n    }\n\n    /**\n     * Set Minimum list size.\n     *\n     * @param int $size\n     *\n     * @return $this\n     */\n    public function min(int $size)\n    {\n        $this->min = $size;\n\n        return $this;\n    }\n\n    /**\n     * Fill data to the field.\n     *\n     * @param array $data\n     *\n     * @return void\n     */\n    public function fill($data)\n    {\n        $this->data = $data;\n\n        $this->value = Arr::get($data, $this->column, $this->value);\n\n        $this->formatValue();\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function getValidator(array $input)\n    {\n        if ($this->validator) {\n            return $this->validator->call($this, $input);\n        }\n\n        if (!is_string($this->column)) {\n            return false;\n        }\n\n        $rules = $attributes = [];\n\n        if (!$fieldRules = $this->getRules()) {\n            return false;\n        }\n\n        if (!Arr::has($input, $this->column)) {\n            return false;\n        }\n\n        $rules[\"{$this->column}.values.*\"] = $fieldRules;\n        $attributes[\"{$this->column}.values.*\"] = __('Value');\n\n        $rules[\"{$this->column}.values\"][] = 'array';\n\n        if (!is_null($this->max)) {\n            $rules[\"{$this->column}.values\"][] = \"max:$this->max\";\n        }\n\n        if (!is_null($this->min)) {\n            $rules[\"{$this->column}.values\"][] = \"min:$this->min\";\n        }\n\n        $attributes[\"{$this->column}.values\"] = $this->label;\n\n        return validator($input, $rules, $this->getValidationMessages(), $attributes);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function setupScript()\n    {\n        $this->script = <<<SCRIPT\n\n$('.{$this->column}-add').on('click', function () {\n    var tpl = $('template.{$this->column}-tpl').html();\n    $('tbody.list-{$this->column}-table').append(tpl);\n});\n\n$('tbody').on('click', '.{$this->column}-remove', function () {\n    $(this).closest('tr').remove();\n});\n\nSCRIPT;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function prepare($value)\n    {\n        return array_values($value['values']);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function render()\n    {\n        $this->setupScript();\n\n        Admin::style('td .form-group {margin-bottom: 0 !important;}');\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Listbox.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\n/**\n * Class ListBox.\n *\n * @see https://github.com/istvan-ujjmeszaros/bootstrap-duallistbox\n */\nclass Listbox extends MultipleSelect\n{\n    protected $settings = [];\n\n    protected static $css = [\n        '/vendor/laravel-admin/bootstrap-duallistbox/dist/bootstrap-duallistbox.min.css',\n    ];\n\n    protected static $js = [\n        '/vendor/laravel-admin/bootstrap-duallistbox/dist/jquery.bootstrap-duallistbox.min.js',\n    ];\n\n    public function settings(array $settings)\n    {\n        $this->settings = $settings;\n\n        return $this;\n    }\n\n    /**\n     * Set listbox height.\n     *\n     * @param int $height\n     *\n     * @return Listbox\n     */\n    public function height($height = 200)\n    {\n        return $this->settings(['selectorMinimalHeight' => $height]);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected function loadRemoteOptions($url, $parameters = [], $options = [])\n    {\n        $ajaxOptions = json_encode(array_merge([\n            'url' => $url.'?'.http_build_query($parameters),\n        ], $options));\n\n        $this->script = <<<EOT\n        \n$.ajax($ajaxOptions).done(function(data) {\n\n  var listbox = $(\"{$this->getElementClassSelector()}\");\n\n    var value = listbox.data('value') + '';\n    \n    if (value) {\n      value = value.split(',');\n    }\n    \n    for (var key in data) {\n        var selected =  ($.inArray(key, value) >= 0) ? 'selected' : '';\n        listbox.append('<option value=\"'+key+'\" '+selected+'>'+data[key]+'</option>');\n    }\n    \n    listbox.bootstrapDualListbox('refresh', true);\n});\nEOT;\n\n        return $this;\n    }\n\n    public function render()\n    {\n        $settings = array_merge([\n            'infoText'              => trans('admin.listbox.text_total'),\n            'infoTextEmpty'         => trans('admin.listbox.text_empty'),\n            'infoTextFiltered'      => trans('admin.listbox.filtered'),\n            'filterTextClear'       => trans('admin.listbox.filter_clear'),\n            'filterPlaceHolder'     => trans('admin.listbox.filter_placeholder'),\n            'selectorMinimalHeight' => 200,\n        ], $this->settings);\n\n        $settings = json_encode($settings);\n\n        $this->script .= <<<SCRIPT\n\n$(\"{$this->getElementClassSelector()}\").bootstrapDualListbox($settings);\n\nSCRIPT;\n\n        $this->attribute('data-value', implode(',', (array) $this->value()));\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Map.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Form\\Field;\n\nclass Map extends Field\n{\n    protected $value = [\n        'lat' => null,\n        'lng' => null,\n    ];\n\n    /**\n     * Column name.\n     *\n     * @var array\n     */\n    protected $column = [];\n\n    /**\n     * Get assets required by this field.\n     *\n     * @return array\n     */\n    public static function getAssets()\n    {\n        switch (config('admin.map_provider')) {\n            case 'tencent':\n                $js = '//map.qq.com/api/js?v=2.exp&key='.env('TENCENT_MAP_API_KEY');\n                break;\n            case 'google':\n                $js = '//maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&key='.env('GOOGLE_API_KEY');\n                break;\n            case 'yandex':\n                $js = '//api-maps.yandex.ru/2.1/?lang=ru_RU';\n                break;\n            default:\n                $js = '//maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&key='.env('GOOGLE_API_KEY');\n        }\n\n        return compact('js');\n    }\n\n    public function __construct($column, $arguments)\n    {\n        $this->column['lat'] = (string) $column;\n        $this->column['lng'] = (string) $arguments[0];\n\n        array_shift($arguments);\n\n        $this->label = $this->formatLabel($arguments);\n        $this->id = $this->formatId($this->column);\n\n        /*\n         * Google map is blocked in mainland China\n         * people in China can use Tencent map instead(;\n         */\n        switch (config('admin.map_provider')) {\n            case 'tencent':\n                $this->useTencentMap();\n                break;\n            case 'google':\n                $this->useGoogleMap();\n                break;\n            case 'yandex':\n                $this->useYandexMap();\n                break;\n            default:\n                $this->useGoogleMap();\n        }\n    }\n\n    public function useGoogleMap()\n    {\n        $this->script = <<<EOT\n        (function() {\n            function initGoogleMap(name) {\n                var lat = $('#{$this->id['lat']}');\n                var lng = $('#{$this->id['lng']}');\n    \n                var LatLng = new google.maps.LatLng(lat.val(), lng.val());\n    \n                var options = {\n                    zoom: 13,\n                    center: LatLng,\n                    panControl: false,\n                    zoomControl: true,\n                    scaleControl: true,\n                    mapTypeId: google.maps.MapTypeId.ROADMAP\n                }\n    \n                var container = document.getElementById(\"map_\"+name);\n                var map = new google.maps.Map(container, options);\n    \n                var marker = new google.maps.Marker({\n                    position: LatLng,\n                    map: map,\n                    title: 'Drag Me!',\n                    draggable: true\n                });\n    \n                google.maps.event.addListener(marker, 'dragend', function (event) {\n                    lat.val(event.latLng.lat());\n                    lng.val(event.latLng.lng());\n                });\n            }\n    \n            initGoogleMap('{$this->id['lat']}{$this->id['lng']}');\n        })();\nEOT;\n    }\n\n    public function useTencentMap()\n    {\n        $this->script = <<<EOT\n        (function() {\n            function initTencentMap(name) {\n                var lat = $('#{$this->id['lat']}');\n                var lng = $('#{$this->id['lng']}');\n    \n                var center = new qq.maps.LatLng(lat.val(), lng.val());\n    \n                var container = document.getElementById(\"map_\"+name);\n                var map = new qq.maps.Map(container, {\n                    center: center,\n                    zoom: 13\n                });\n    \n                var marker = new qq.maps.Marker({\n                    position: center,\n                    draggable: true,\n                    map: map\n                });\n    \n                if( ! lat.val() || ! lng.val()) {\n                    var citylocation = new qq.maps.CityService({\n                        complete : function(result){\n                            map.setCenter(result.detail.latLng);\n                            marker.setPosition(result.detail.latLng);\n                        }\n                    });\n    \n                    citylocation.searchLocalCity();\n                }\n    \n                qq.maps.event.addListener(map, 'click', function(event) {\n                    marker.setPosition(event.latLng);\n                });\n    \n                qq.maps.event.addListener(marker, 'position_changed', function(event) {\n                    var position = marker.getPosition();\n                    lat.val(position.getLat());\n                    lng.val(position.getLng());\n                });\n            }\n    \n            initTencentMap('{$this->id['lat']}{$this->id['lng']}');\n        })();\nEOT;\n    }\n\n    public function useYandexMap()\n    {\n        $this->script = <<<EOT\n        (function() {\n            function initYandexMap(name) {\n                ymaps.ready(function(){\n        \n                    var lat = $('#{$this->id['lat']}');\n                    var lng = $('#{$this->id['lng']}');\n        \n                    var myMap = new ymaps.Map(\"map_\"+name, {\n                        center: [lat.val(), lng.val()],\n                        zoom: 18\n                    }); \n    \n                    var myPlacemark = new ymaps.Placemark([lat.val(), lng.val()], {\n                    }, {\n                        preset: 'islands#redDotIcon',\n                        draggable: true\n                    });\n    \n                    myPlacemark.events.add(['dragend'], function (e) {\n                        lat.val(myPlacemark.geometry.getCoordinates()[0]);\n                        lng.val(myPlacemark.geometry.getCoordinates()[1]);\n                    });                \n    \n                    myMap.geoObjects.add(myPlacemark);\n                });\n    \n            }\n            \n            initYandexMap('{$this->id['lat']}{$this->id['lng']}');\n        })();\nEOT;\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Mobile.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nclass Mobile extends Text\n{\n    protected static $js = [\n        '/vendor/laravel-admin/AdminLTE/plugins/input-mask/jquery.inputmask.bundle.min.js',\n    ];\n\n    /**\n     * @see https://github.com/RobinHerbots/Inputmask#options\n     *\n     * @var array\n     */\n    protected $options = [\n        'mask' => '99999999999',\n    ];\n\n    public function render()\n    {\n        $this->inputmask($this->options);\n\n        $this->prepend('<i class=\"fa fa-phone fa-fw\"></i>')\n            ->defaultAttribute('style', 'width: 150px');\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Month.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nclass Month extends Date\n{\n    protected $format = 'MM';\n}\n"
  },
  {
    "path": "src/Form/Field/MultipleFile.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Form;\nuse Encore\\Admin\\Form\\Field;\nuse Illuminate\\Support\\Arr;\nuse Symfony\\Component\\HttpFoundation\\File\\UploadedFile;\n\nclass MultipleFile extends Field\n{\n    use UploadField;\n\n    /**\n     * Css.\n     *\n     * @var array\n     */\n    protected static $css = [\n        '/vendor/laravel-admin/bootstrap-fileinput/css/fileinput.min.css?v=4.5.2',\n    ];\n\n    /**\n     * Js.\n     *\n     * @var array\n     */\n    protected static $js = [\n        '/vendor/laravel-admin/bootstrap-fileinput/js/plugins/canvas-to-blob.min.js',\n        '/vendor/laravel-admin/bootstrap-fileinput/js/fileinput.min.js?v=4.5.2',\n        '/vendor/laravel-admin/bootstrap-fileinput/js/plugins/sortable.min.js?v=4.5.2',\n    ];\n\n    /**\n     * Create a new File instance.\n     *\n     * @param string $column\n     * @param array  $arguments\n     */\n    public function __construct($column, $arguments = [])\n    {\n        $this->initStorage();\n\n        parent::__construct($column, $arguments);\n    }\n\n    /**\n     * Default directory for file to upload.\n     *\n     * @return mixed\n     */\n    public function defaultDirectory()\n    {\n        return config('admin.upload.directory.file');\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function getValidator(array $input)\n    {\n        if (request()->has(static::FILE_DELETE_FLAG)) {\n            return false;\n        }\n\n        if ($this->validator) {\n            return $this->validator->call($this, $input);\n        }\n\n        $attributes = [];\n\n        if (!$fieldRules = $this->getRules()) {\n            return false;\n        }\n\n        $attributes[$this->column] = $this->label;\n\n        list($rules, $input) = $this->hydrateFiles(Arr::get($input, $this->column, []));\n\n        return \\validator($input, $rules, $this->getValidationMessages(), $attributes);\n    }\n\n    /**\n     * Hydrate the files array.\n     *\n     * @param array $value\n     *\n     * @return array\n     */\n    protected function hydrateFiles(array $value)\n    {\n        if (empty($value)) {\n            return [[$this->column => $this->getRules()], []];\n        }\n\n        $rules = $input = [];\n\n        foreach ($value as $key => $file) {\n            $rules[$this->column.$key] = $this->getRules();\n            $input[$this->column.$key] = $file;\n        }\n\n        return [$rules, $input];\n    }\n\n    /**\n     * Sort files.\n     *\n     * @param string $order\n     *\n     * @return array\n     */\n    protected function sortFiles($order)\n    {\n        $order = explode(',', $order);\n\n        $new = [];\n        $original = $this->original();\n\n        foreach ($order as $item) {\n            $new[] = Arr::get($original, $item);\n        }\n\n        return $new;\n    }\n\n    /**\n     * Prepare for saving.\n     *\n     * @param UploadedFile|array $files\n     *\n     * @return mixed|string\n     */\n    public function prepare($files)\n    {\n        if (request()->has(static::FILE_DELETE_FLAG)) {\n            if ($this->pathColumn) {\n                return $this->destroyFromHasMany(request(static::FILE_DELETE_FLAG));\n            }\n\n            return $this->destroy(request(static::FILE_DELETE_FLAG));\n        }\n\n        if (is_string($files) && request()->has(static::FILE_SORT_FLAG)) {\n            return $this->sortFiles($files);\n        }\n\n        $targets = array_map([$this, 'prepareForeach'], $files);\n\n        // for create or update\n        if ($this->pathColumn) {\n            $targets = array_map(function ($target) {\n                return [$this->pathColumn => $target];\n            }, $targets);\n        }\n\n        return array_merge($this->original(), $targets);\n    }\n\n    /**\n     * @return array|mixed\n     */\n    public function original()\n    {\n        if (empty($this->original)) {\n            return [];\n        }\n\n        return $this->original;\n    }\n\n    /**\n     * Prepare for each file.\n     *\n     * @param UploadedFile $file\n     *\n     * @return mixed|string\n     */\n    protected function prepareForeach(UploadedFile $file = null)\n    {\n        $this->name = $this->getStoreName($file);\n\n        return tap($this->upload($file), function () {\n            $this->name = null;\n        });\n    }\n\n    /**\n     * Preview html for file-upload plugin.\n     *\n     * @return array\n     */\n    protected function preview()\n    {\n        $files = $this->value ?: [];\n\n        return array_values(array_map([$this, 'objectUrl'], $files));\n    }\n\n    /**\n     * Initialize the caption.\n     *\n     * @param array $caption\n     *\n     * @return string\n     */\n    protected function initialCaption($caption)\n    {\n        if (empty($caption)) {\n            return '';\n        }\n\n        $caption = array_map('basename', $caption);\n\n        return implode(',', $caption);\n    }\n\n    /**\n     * @return array\n     */\n    protected function initialPreviewConfig()\n    {\n        $files = $this->value ?: [];\n\n        $config = [];\n\n        foreach ($files as $index => $file) {\n            if (is_array($file) && $this->pathColumn) {\n                $index = Arr::get($file, $this->getRelatedKeyName(), $index);\n                $file = Arr::get($file, $this->pathColumn);\n            }\n\n            $preview = array_merge([\n                'caption' => basename($file),\n                'key'     => $index,\n            ], $this->guessPreviewType($file));\n\n            $config[] = $preview;\n        }\n\n        return $config;\n    }\n\n    /**\n     * Get related model key name.\n     *\n     * @return string\n     */\n    protected function getRelatedKeyName()\n    {\n        if (is_null($this->form)) {\n            return;\n        }\n\n        return $this->form->model()->{$this->column}()->getRelated()->getKeyName();\n    }\n\n    /**\n     * Allow to sort files.\n     *\n     * @return $this\n     */\n    public function sortable()\n    {\n        $this->fileActionSettings['showDrag'] = true;\n\n        return $this;\n    }\n\n    /**\n     * @param string $options\n     */\n    protected function setupScripts($options)\n    {\n        $this->script = <<<EOT\n$(\"input{$this->getElementClassSelector()}\").fileinput({$options});\nEOT;\n\n        if ($this->fileActionSettings['showRemove']) {\n            $text = [\n                'title'   => trans('admin.delete_confirm'),\n                'confirm' => trans('admin.confirm'),\n                'cancel'  => trans('admin.cancel'),\n            ];\n\n            $this->script .= <<<EOT\n$(\"input{$this->getElementClassSelector()}\").on('filebeforedelete', function() {\n\n    return new Promise(function(resolve, reject) {\n\n        var remove = resolve;\n\n        swal({\n            title: \"{$text['title']}\",\n            type: \"warning\",\n            showCancelButton: true,\n            confirmButtonColor: \"#DD6B55\",\n            confirmButtonText: \"{$text['confirm']}\",\n            showLoaderOnConfirm: true,\n            cancelButtonText: \"{$text['cancel']}\",\n            preConfirm: function() {\n                return new Promise(function(resolve) {\n                    resolve(remove());\n                });\n            }\n        });\n    });\n});\nEOT;\n        }\n\n        if ($this->fileActionSettings['showDrag']) {\n            $this->addVariables([\n                'sortable'  => true,\n                'sort_flag' => static::FILE_SORT_FLAG,\n            ]);\n\n            $this->script .= <<<EOT\n$(\"input{$this->getElementClassSelector()}\").on('filesorted', function(event, params) {\n\n    var order = [];\n\n    params.stack.forEach(function (item) {\n        order.push(item.key);\n    });\n\n    $(\"input{$this->getElementClassSelector()}_sort\").val(order);\n});\nEOT;\n        }\n    }\n\n    /**\n     * Render file upload field.\n     *\n     * @return \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View\n     */\n    public function render()\n    {\n        $this->attribute('multiple', true);\n\n        $this->setupDefaultOptions();\n\n        if (!empty($this->value)) {\n            $this->options(['initialPreview' => $this->preview()]);\n            $this->setupPreviewOptions();\n        }\n\n        $options = json_encode($this->options);\n\n        $this->setupScripts($options);\n\n        return parent::render();\n    }\n\n    /**\n     * Destroy original files.\n     *\n     * @param string $key\n     *\n     * @return array\n     */\n    public function destroy($key)\n    {\n        $files = $this->original ?: [];\n\n        $path = Arr::get($files, $key);\n\n        if (!$this->retainable && $this->storage->exists($path)) {\n            /* If this field class is using ImageField trait i.e MultipleImage field,\n            we loop through the thumbnails to delete them as well. */\n\n            if (isset($this->thumbnails) && method_exists($this, 'destroyThumbnailFile')) {\n                foreach ($this->thumbnails as $name => $_) {\n                    $this->destroyThumbnailFile($path, $name);\n                }\n            }\n            $this->storage->delete($path);\n        }\n\n        unset($files[$key]);\n\n        return $files;\n    }\n\n    /**\n     * Destroy original files from hasmany related model.\n     *\n     * @param int $key\n     *\n     * @return array\n     */\n    public function destroyFromHasMany($key)\n    {\n        $files = collect($this->original ?: [])->keyBy($this->getRelatedKeyName())->toArray();\n\n        $path = Arr::get($files, \"{$key}.{$this->pathColumn}\");\n\n        if (!$this->retainable && $this->storage->exists($path)) {\n            $this->storage->delete($path);\n        }\n\n        $files[$key][Form::REMOVE_FLAG_NAME] = 1;\n\n        return $files;\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/MultipleImage.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Symfony\\Component\\HttpFoundation\\File\\UploadedFile;\n\nclass MultipleImage extends MultipleFile\n{\n    use ImageField;\n\n    /**\n     * {@inheritdoc}\n     */\n    protected $view = 'admin::form.multiplefile';\n\n    /**\n     *  Validation rules.\n     *\n     * @var string\n     */\n    protected $rules = 'image';\n\n    /**\n     * Prepare for each file.\n     *\n     * @param UploadedFile $image\n     *\n     * @return mixed|string\n     */\n    protected function prepareForeach(UploadedFile $image = null)\n    {\n        $this->name = $this->getStoreName($image);\n\n        $this->callInterventionMethods($image->getRealPath());\n\n        /* return tap($this->upload($image), function () {\n            $this->name = null;\n        }); */\n\n        /* Copied from single image prepare section and made necessary changes so the return\n        value is same as before, but now thumbnails are saved to the disk as well. */\n\n        $path = $this->upload($image);\n        $this->uploadAndDeleteOriginalThumbnail($image);\n        $this->name = null;\n\n        return $path;\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/MultipleSelect.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsToMany;\nuse Illuminate\\Database\\Eloquent\\Relations\\HasMany as HasManyRelation;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Str;\n\nclass MultipleSelect extends Select\n{\n    /**\n     * Other key for many-to-many relation.\n     *\n     * @var string\n     */\n    protected $otherKey;\n\n    /**\n     * Get other key for this many-to-many relation.\n     *\n     * @throws \\Exception\n     *\n     * @return string\n     */\n    protected function getOtherKey()\n    {\n        if ($this->otherKey) {\n            return $this->otherKey;\n        }\n\n        if (is_callable([$this->form->model(), $this->column])) {\n            $relation = $this->form->model()->{$this->column}();\n\n            if ($relation instanceof BelongsToMany) {\n                /* @var BelongsToMany $relation */\n                $fullKey = $relation->getQualifiedRelatedPivotKeyName();\n                $fullKeyArray = explode('.', $fullKey);\n\n                return $this->otherKey = 'pivot.'.end($fullKeyArray);\n            } elseif ($relation instanceof HasManyRelation) {\n                /* @var HasManyRelation $relation */\n                return $this->otherKey = $relation->getRelated()->getKeyName();\n            }\n        }\n\n        throw new \\Exception('Column of this field must be a `BelongsToMany` or `HasMany` relation.');\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function fill($data)\n    {\n        if ($this->form && $this->form->shouldSnakeAttributes()) {\n            $key = Str::snake($this->column);\n        } else {\n            $key = $this->column;\n        }\n\n        $relations = Arr::get($data, $key);\n\n        if (is_string($relations)) {\n            $this->value = explode(',', $relations);\n        }\n\n        if (!is_array($relations)) {\n            $this->applyCascadeConditions();\n\n            return;\n        }\n\n        $first = current($relations);\n\n        if (is_null($first)) {\n            $this->value = null;\n\n        // MultipleSelect value store as an ont-to-many relationship.\n        } elseif (is_array($first)) {\n            foreach ($relations as $relation) {\n                $this->value[] = Arr::get($relation, $this->getOtherKey());\n            }\n\n            // MultipleSelect value store as a column.\n        } else {\n            $this->value = $relations;\n        }\n\n        $this->applyCascadeConditions();\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function setOriginal($data)\n    {\n        $relations = Arr::get($data, $this->column);\n\n        if (is_string($relations)) {\n            $this->original = explode(',', $relations);\n        }\n\n        if (!is_array($relations)) {\n            return;\n        }\n\n        $first = current($relations);\n\n        if (is_null($first)) {\n            $this->original = null;\n\n        // MultipleSelect value store as an ont-to-many relationship.\n        } elseif (is_array($first)) {\n            foreach ($relations as $relation) {\n                $this->original[] = Arr::get($relation, $this->getOtherKey());\n            }\n\n            // MultipleSelect value store as a column.\n        } else {\n            $this->original = $relations;\n        }\n    }\n\n    public function prepare($value)\n    {\n        $value = (array) $value;\n\n        return array_filter($value, 'strlen');\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Nullable.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Form\\Field;\n\nclass Nullable extends Field\n{\n    public function __construct()\n    {\n    }\n\n    public function __call($method, $parameters)\n    {\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Number.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nclass Number extends Text\n{\n    protected static $js = [\n        '/vendor/laravel-admin/number-input/bootstrap-number-input.js',\n    ];\n\n    public function render()\n    {\n        $this->default($this->default);\n\n        $this->script = <<<EOT\n\n$('{$this->getElementClassSelector()}:not(.initialized)')\n    .addClass('initialized')\n    .bootstrapNumber({\n        upClass: 'success',\n        downClass: 'primary',\n        center: true\n    });\n\nEOT;\n\n        $this->prepend('')->defaultAttribute('style', 'width: 100px');\n\n        return parent::render();\n    }\n\n    /**\n     * Set min value of number field.\n     *\n     * @param int $value\n     *\n     * @return $this\n     */\n    public function min($value)\n    {\n        $this->attribute('min', $value);\n\n        return $this;\n    }\n\n    /**\n     * Set max value of number field.\n     *\n     * @param int $value\n     *\n     * @return $this\n     */\n    public function max($value)\n    {\n        $this->attribute('max', $value);\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Password.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nclass Password extends Text\n{\n    public function render()\n    {\n        $this->prepend('<i class=\"fa fa-eye-slash fa-fw\"></i>')\n            ->defaultAttribute('type', 'password');\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/PlainInput.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\ntrait PlainInput\n{\n    /**\n     * @var string\n     */\n    protected $prepend;\n\n    /**\n     * @var string\n     */\n    protected $append;\n\n    /**\n     * @param mixed $string\n     *\n     * @return $this\n     */\n    public function prepend($string)\n    {\n        if (is_null($this->prepend)) {\n            $this->prepend = $string;\n        }\n\n        return $this;\n    }\n\n    /**\n     * @param mixed $string\n     *\n     * @return $this\n     */\n    public function append($string)\n    {\n        if (is_null($this->append)) {\n            $this->append = $string;\n        }\n\n        return $this;\n    }\n\n    /**\n     * @return void\n     */\n    protected function initPlainInput()\n    {\n        if (empty($this->view)) {\n            $this->view = 'admin::form.input';\n        }\n    }\n\n    /**\n     * @param string $attribute\n     * @param string $value\n     *\n     * @return $this\n     */\n    protected function defaultAttribute($attribute, $value)\n    {\n        if (!array_key_exists($attribute, $this->attributes)) {\n            $this->attribute($attribute, $value);\n        }\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Radio.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Form\\Field;\nuse Illuminate\\Contracts\\Support\\Arrayable;\n\nclass Radio extends Field\n{\n    use CanCascadeFields;\n\n    protected $inline = true;\n\n    protected static $css = [\n        '/vendor/laravel-admin/AdminLTE/plugins/iCheck/all.css',\n    ];\n\n    protected static $js = [\n        '/vendor/laravel-admin/AdminLTE/plugins/iCheck/icheck.min.js',\n    ];\n\n    /**\n     * @var string\n     */\n    protected $cascadeEvent = 'ifChecked';\n\n    /**\n     * Set options.\n     *\n     * @param array|callable|string $options\n     *\n     * @return $this\n     */\n    public function options($options = [])\n    {\n        if ($options instanceof Arrayable) {\n            $options = $options->toArray();\n        }\n\n        $this->options = (array) $options;\n\n        return $this;\n    }\n\n    /**\n     * Set checked.\n     *\n     * @param array|callable|string $checked\n     *\n     * @return $this\n     */\n    public function checked($checked = [])\n    {\n        if ($checked instanceof Arrayable) {\n            $checked = $checked->toArray();\n        }\n\n        // input radio checked should be unique\n        $this->checked = is_array($checked) ? (array) end($checked) : (array) $checked;\n\n        return $this;\n    }\n\n    /**\n     * Draw inline radios.\n     *\n     * @return $this\n     */\n    public function inline()\n    {\n        $this->inline = true;\n\n        return $this;\n    }\n\n    /**\n     * Draw stacked radios.\n     *\n     * @return $this\n     */\n    public function stacked()\n    {\n        $this->inline = false;\n\n        return $this;\n    }\n\n    /**\n     * Set options.\n     *\n     * @param array|callable|string $values\n     *\n     * @return $this\n     */\n    public function values($values)\n    {\n        return $this->options($values);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function render()\n    {\n        $this->script = \"$('{$this->getElementClassSelector()}').iCheck({radioClass:'iradio_minimal-blue'});\";\n\n        $this->addCascadeScript();\n\n        $this->addVariables(['options' => $this->options, 'checked' => $this->checked, 'inline' => $this->inline]);\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/RadioButton.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Admin;\n\nclass RadioButton extends Radio\n{\n    /**\n     * @var string\n     */\n    protected $cascadeEvent = 'change';\n\n    protected function addScript()\n    {\n        $script = <<<'SCRIPT'\n$('.radio-group-toggle label').click(function() {\n    $(this).parent().children().removeClass('active');\n    $(this).addClass('active');\n});\nSCRIPT;\n\n        Admin::script($script);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function render()\n    {\n        $this->addScript();\n\n        $this->addCascadeScript();\n\n        $this->addVariables([\n            'options' => $this->options,\n            'checked' => $this->checked,\n        ]);\n\n        return parent::fieldRender();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/RadioCard.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Admin;\n\nclass RadioCard extends RadioButton\n{\n    protected function addStyle()\n    {\n        $style = <<<'STYLE'\n.card-group label {\n    cursor: pointer;\n    margin-right: 8px;\n    font-weight: 400;\n}\n\n.card-group .panel {\n    margin-bottom: 0px;\n}\n\n.card-group .panel-body {\n    padding: 10px 15px;\n}\n\n.card-group .active {\n    border: 2px solid #367fa9;\n}\nSTYLE;\n\n        Admin::style($style);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function render()\n    {\n        $this->addStyle();\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Rate.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nclass Rate extends Text\n{\n    public function render()\n    {\n        $this->prepend('')\n            ->append('%')\n            ->defaultAttribute('style', 'text-align:right;')\n            ->defaultAttribute('placeholder', 0);\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Select.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Facades\\Admin;\nuse Encore\\Admin\\Form\\Field;\nuse Illuminate\\Contracts\\Support\\Arrayable;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Str;\n\nclass Select extends Field\n{\n    use CanCascadeFields;\n\n    /**\n     * @var array\n     */\n    protected static $css = [\n        '/vendor/laravel-admin/AdminLTE/plugins/select2/select2.min.css',\n    ];\n\n    /**\n     * @var array\n     */\n    protected static $js = [\n        '/vendor/laravel-admin/AdminLTE/plugins/select2/select2.full.min.js',\n    ];\n\n    /**\n     * @var array\n     */\n    protected $groups = [];\n\n    /**\n     * @var array\n     */\n    protected $config = [];\n\n    /**\n     * @var string\n     */\n    protected $cascadeEvent = 'change';\n\n    /**\n     * Set options.\n     *\n     * @param array|callable|string $options\n     *\n     * @return $this|mixed\n     */\n    public function options($options = [])\n    {\n        // remote options\n        if (is_string($options)) {\n            // reload selected\n            if (class_exists($options) && in_array(Model::class, class_parents($options))) {\n                return $this->model(...func_get_args());\n            }\n\n            return $this->loadRemoteOptions(...func_get_args());\n        }\n\n        if ($options instanceof Arrayable) {\n            $options = $options->toArray();\n        }\n\n        if (is_callable($options)) {\n            $this->options = $options;\n        } else {\n            $this->options = (array) $options;\n        }\n\n        return $this;\n    }\n\n    /**\n     * @param array $groups\n     */\n\n    /**\n     * Set option groups.\n     *\n     * eg: $group = [\n     *        [\n     *        'label' => 'xxxx',\n     *        'options' => [\n     *            1 => 'foo',\n     *            2 => 'bar',\n     *            ...\n     *        ],\n     *        ...\n     *     ]\n     *\n     * @param array $groups\n     *\n     * @return $this\n     */\n    public function groups(array $groups)\n    {\n        $this->groups = $groups;\n\n        return $this;\n    }\n\n    /**\n     * Load options for other select on change.\n     *\n     * @param string $field\n     * @param string $sourceUrl\n     * @param string $idField\n     * @param string $textField\n     *\n     * @return $this\n     */\n    public function load($field, $sourceUrl, $idField = 'id', $textField = 'text', bool $allowClear = true)\n    {\n        if (Str::contains($field, '.')) {\n            $field = $this->formatName($field);\n            $class = str_replace(['[', ']'], '_', $field);\n        } else {\n            $class = $field;\n        }\n\n        $placeholder = json_encode([\n            'id'   => '',\n            'text' => trans('admin.choose'),\n        ]);\n\n        $strAllowClear = var_export($allowClear, true);\n\n        $script = <<<EOT\n$(document).off('change', \"{$this->getElementClassSelector()}\");\n$(document).on('change', \"{$this->getElementClassSelector()}\", function () {\n    var target = $(this).closest('.fields-group').find(\".$class\");\n    $.get(\"$sourceUrl\",{q : this.value}, function (data) {\n        target.find(\"option\").remove();\n        $(target).select2({\n            placeholder: $placeholder,\n            allowClear: $strAllowClear,\n            data: $.map(data, function (d) {\n                d.id = d.$idField;\n                d.text = d.$textField;\n                return d;\n            })\n        });\n        if (target.data('value')) {\n            $(target).val(target.data('value'));\n        }\n        $(target).trigger('change');\n    });\n});\nEOT;\n\n        Admin::script($script);\n\n        return $this;\n    }\n\n    /**\n     * Load options for other selects on change.\n     *\n     * @param array  $fields\n     * @param array  $sourceUrls\n     * @param string $idField\n     * @param string $textField\n     *\n     * @return $this\n     */\n    public function loads($fields = [], $sourceUrls = [], $idField = 'id', $textField = 'text', bool $allowClear = true)\n    {\n        $fieldsStr = implode('.', $fields);\n        $urlsStr = implode('^', $sourceUrls);\n\n        $placeholder = json_encode([\n            'id'   => '',\n            'text' => trans('admin.choose'),\n        ]);\n\n        $strAllowClear = var_export($allowClear, true);\n\n        $script = <<<EOT\nvar fields = '$fieldsStr'.split('.');\nvar urls = '$urlsStr'.split('^');\n\nvar refreshOptions = function(url, target) {\n    $.get(url).then(function(data) {\n        target.find(\"option\").remove();\n        $(target).select2({\n            placeholder: $placeholder,\n            allowClear: $strAllowClear,\n            data: $.map(data, function (d) {\n                d.id = d.$idField;\n                d.text = d.$textField;\n                return d;\n            })\n        }).trigger('change');\n    });\n};\n\n$(document).off('change', \"{$this->getElementClassSelector()}\");\n$(document).on('change', \"{$this->getElementClassSelector()}\", function () {\n    var _this = this;\n    var promises = [];\n\n    fields.forEach(function(field, index){\n        var target = $(_this).closest('.fields-group').find('.' + fields[index]);\n        promises.push(refreshOptions(urls[index] + \"?q=\"+ _this.value, target));\n    });\n});\nEOT;\n\n        Admin::script($script);\n\n        return $this;\n    }\n\n    /**\n     * Load options from current selected resource(s).\n     *\n     * @param string $model\n     * @param string $idField\n     * @param string $textField\n     *\n     * @return $this\n     */\n    public function model($model, $idField = 'id', $textField = 'name')\n    {\n        if (!class_exists($model)\n            || !in_array(Model::class, class_parents($model))\n        ) {\n            throw new \\InvalidArgumentException(\"[$model] must be a valid model class\");\n        }\n\n        $this->options = function ($value) use ($model, $idField, $textField) {\n            if (empty($value)) {\n                return [];\n            }\n\n            $resources = [];\n\n            if (is_array($value)) {\n                if (Arr::isAssoc($value)) {\n                    $resources[] = Arr::get($value, $idField);\n                } else {\n                    $resources = array_column($value, $idField);\n                }\n            } else {\n                $resources[] = $value;\n            }\n\n            return $model::find($resources)->pluck($textField, $idField)->toArray();\n        };\n\n        return $this;\n    }\n\n    /**\n     * Load options from remote.\n     *\n     * @param string $url\n     * @param array  $parameters\n     * @param array  $options\n     *\n     * @return $this\n     */\n    protected function loadRemoteOptions($url, $parameters = [], $options = [])\n    {\n        $ajaxOptions = [\n            'url' => $url.'?'.http_build_query($parameters),\n        ];\n        $configs = array_merge([\n            'allowClear'         => true,\n            'placeholder'        => [\n                'id'        => '',\n                'text'      => trans('admin.choose'),\n            ],\n        ], $this->config);\n\n        $configs = json_encode($configs);\n        $configs = substr($configs, 1, strlen($configs) - 2);\n\n        $ajaxOptions = json_encode(array_merge($ajaxOptions, $options));\n\n        $this->script = <<<EOT\n\n$.ajax($ajaxOptions).done(function(data) {\n\n  $(\"{$this->getElementClassSelector()}\").each(function(index, element) {\n      $(element).select2({\n        data: data,\n        $configs\n      });\n      var value = $(element).data('value') + '';\n      if (value) {\n        value = value.split(',');\n        $(element).val(value).trigger(\"change\");\n      }\n  });\n});\n\nEOT;\n\n        return $this;\n    }\n\n    /**\n     * Load options from ajax results.\n     *\n     * @param string $url\n     * @param $idField\n     * @param $textField\n     *\n     * @return $this\n     */\n    public function ajax($url, $idField = 'id', $textField = 'text')\n    {\n        $configs = array_merge([\n            'allowClear'         => true,\n            'placeholder'        => $this->label,\n            'minimumInputLength' => 1,\n        ], $this->config);\n\n        $configs = json_encode($configs);\n        $configs = substr($configs, 1, strlen($configs) - 2);\n\n        $this->script = <<<EOT\n\n$(\"{$this->getElementClassSelector()}\").select2({\n  ajax: {\n    url: \"$url\",\n    dataType: 'json',\n    delay: 250,\n    data: function (params) {\n      return {\n        q: params.term,\n        page: params.page\n      };\n    },\n    processResults: function (data, params) {\n      params.page = params.page || 1;\n\n      return {\n        results: $.map(data.data, function (d) {\n                   d.id = d.$idField;\n                   d.text = d.$textField;\n                   return d;\n                }),\n        pagination: {\n          more: data.next_page_url\n        }\n      };\n    },\n    cache: true\n  },\n  $configs,\n  escapeMarkup: function (markup) {\n      return markup;\n  }\n});\n\nEOT;\n\n        return $this;\n    }\n\n    /**\n     * Set config for select2.\n     *\n     * all configurations see https://select2.org/configuration/options-api\n     *\n     * @param string $key\n     * @param mixed  $val\n     *\n     * @return $this\n     */\n    public function config($key, $val)\n    {\n        $this->config[$key] = $val;\n\n        return $this;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function readOnly()\n    {\n        //移除特定字段名称,增加MultipleSelect的修订\n        //没有特定字段名可以使多个readonly的JS代码片段被Admin::script的array_unique精简代码\n        $script = <<<'EOT'\n$(\"form select\").on(\"select2:opening\", function (e) {\n    if($(this).attr('readonly') || $(this).is(':hidden')){\n    e.preventDefault();\n    }\n});\n$(document).ready(function(){\n    $('select').each(function(){\n        if($(this).is('[readonly]')){\n            $(this).closest('.form-group').find('span.select2-selection__choice__remove').remove();\n            $(this).closest('.form-group').find('li.select2-search').first().remove();\n            $(this).closest('.form-group').find('span.select2-selection__clear').first().remove();\n        }\n    });\n});\nEOT;\n        Admin::script($script);\n\n        return parent::readOnly();\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function render()\n    {\n        $configs = array_merge([\n            'allowClear'  => true,\n            'placeholder' => [\n                'id'   => '',\n                'text' => $this->label,\n            ],\n        ], $this->config);\n\n        $configs = json_encode($configs);\n\n        if (empty($this->script)) {\n            $this->script = \"$(\\\"{$this->getElementClassSelector()}\\\").select2($configs);\";\n        }\n\n        if ($this->options instanceof \\Closure) {\n            if ($this->form) {\n                $this->options = $this->options->bindTo($this->form->model());\n            }\n\n            $this->options(call_user_func($this->options, $this->value, $this));\n        }\n\n        $this->options = array_filter($this->options, 'strlen');\n\n        $this->addVariables([\n            'options' => $this->options,\n            'groups'  => $this->groups,\n        ]);\n\n        $this->addCascadeScript();\n\n        $this->attribute('data-value', implode(',', (array) $this->value()));\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Slider.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Form\\Field;\n\nclass Slider extends Field\n{\n    protected static $css = [\n        '/vendor/laravel-admin/AdminLTE/plugins/ionslider/ion.rangeSlider.css',\n        '/vendor/laravel-admin/AdminLTE/plugins/ionslider/ion.rangeSlider.skinNice.css',\n    ];\n\n    protected static $js = [\n        '/vendor/laravel-admin/AdminLTE/plugins/ionslider/ion.rangeSlider.min.js',\n    ];\n\n    protected $options = [\n        'type'     => 'single',\n        'prettify' => false,\n        'hasGrid'  => true,\n    ];\n\n    public function render()\n    {\n        $option = json_encode($this->options);\n\n        $this->script = \"$('{$this->getElementClassSelector()}').ionRangeSlider($option);\";\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/SwitchField.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Form\\Field;\nuse Illuminate\\Support\\Arr;\n\nclass SwitchField extends Field\n{\n    protected static $css = [\n        '/vendor/laravel-admin/bootstrap-switch/dist/css/bootstrap3/bootstrap-switch.min.css',\n    ];\n\n    protected static $js = [\n        '/vendor/laravel-admin/bootstrap-switch/dist/js/bootstrap-switch.min.js',\n    ];\n\n    protected $states = [\n        'on'  => ['value' => 1, 'text' => 'ON', 'color' => 'primary'],\n        'off' => ['value' => 0, 'text' => 'OFF', 'color' => 'default'],\n    ];\n\n    protected $size = 'small';\n\n    public function setSize($size)\n    {\n        $this->size = $size;\n\n        return $this;\n    }\n\n    public function states($states = [])\n    {\n        foreach (Arr::dot($states) as $key => $state) {\n            Arr::set($this->states, $key, $state);\n        }\n\n        return $this;\n    }\n\n    public function prepare($value)\n    {\n        if (isset($this->states[$value])) {\n            return $this->states[$value]['value'];\n        }\n\n        return $value;\n    }\n\n    public function render()\n    {\n        if (!$this->shouldRender()) {\n            return '';\n        }\n\n        foreach ($this->states as $state => $option) {\n            if ($this->value() == $option['value']) {\n                $this->value = $state;\n                break;\n            }\n        }\n\n        $this->script = <<<EOT\n\n$('{$this->getElementClassSelector()}.la_checkbox').bootstrapSwitch({\n    size:'{$this->size}',\n    onText: '{$this->states['on']['text']}',\n    offText: '{$this->states['off']['text']}',\n    onColor: '{$this->states['on']['color']}',\n    offColor: '{$this->states['off']['color']}',\n    onSwitchChange: function(event, state) {\n        $(event.target).closest('.bootstrap-switch').next().val(state ? 'on' : 'off').change();\n    }\n});\n\nEOT;\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Table.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Form\\NestedForm;\nuse Encore\\Admin\\Widgets\\Form as WidgetForm;\n\nclass Table extends HasMany\n{\n    /**\n     * @var string\n     */\n    protected $viewMode = 'table';\n\n    /**\n     * Table constructor.\n     *\n     * @param string $column\n     * @param array  $arguments\n     */\n    public function __construct($column, $arguments = [])\n    {\n        $this->column = $column;\n\n        if (count($arguments) == 1) {\n            $this->label = $this->formatLabel();\n            $this->builder = $arguments[0];\n        }\n\n        if (count($arguments) == 2) {\n            list($this->label, $this->builder) = $arguments;\n        }\n    }\n\n    /**\n     * @return array\n     */\n    protected function buildRelatedForms()\n    {\n//        if (is_null($this->form)) {\n//            return [];\n//        }\n\n        $forms = [];\n\n        if ($values = old($this->column)) {\n            foreach ($values as $key => $data) {\n                if ($data[NestedForm::REMOVE_FLAG_NAME] == 1) {\n                    continue;\n                }\n\n                $forms[$key] = $this->buildNestedForm($this->column, $this->builder, $key)->fill($data);\n            }\n        } else {\n            foreach ($this->value ?? [] as $key => $data) {\n                if (isset($data['pivot'])) {\n                    $data = array_merge($data, $data['pivot']);\n                }\n                if (is_array($data)) {\n                    $forms[$key] = $this->buildNestedForm($this->column, $this->builder, $key)->fill($data);\n                }\n            }\n        }\n\n        return $forms;\n    }\n\n    public function prepare($input)\n    {\n        $form = $this->buildNestedForm($this->column, $this->builder);\n\n        $prepare = $form->prepare($input);\n\n        return collect($prepare)->reject(function ($item) {\n            return $item[NestedForm::REMOVE_FLAG_NAME] == 1;\n        })->map(function ($item) {\n            unset($item[NestedForm::REMOVE_FLAG_NAME]);\n\n            return $item;\n        })->toArray();\n    }\n\n    protected function getKeyName()\n    {\n        if (is_null($this->form)) {\n            return;\n        }\n\n        return 'id';\n    }\n\n    protected function buildNestedForm($column, \\Closure $builder, $key = null)\n    {\n        $form = new NestedForm($column);\n\n        if ($this->form instanceof WidgetForm) {\n            $form->setWidgetForm($this->form);\n        } else {\n            $form->setForm($this->form);\n        }\n\n        $form->setKey($key);\n\n        call_user_func($builder, $form);\n\n        $form->hidden(NestedForm::REMOVE_FLAG_NAME)->default(0)->addElementClass(NestedForm::REMOVE_FLAG_CLASS);\n\n        return $form;\n    }\n\n    public function render()\n    {\n        return $this->renderTable();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Tags.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Facades\\Admin;\nuse Encore\\Admin\\Form\\Field;\nuse Illuminate\\Contracts\\Support\\Arrayable;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Collection;\n\nclass Tags extends Field\n{\n    /**\n     * @var array\n     */\n    protected $value = [];\n\n    /**\n     * @var bool\n     */\n    protected $keyAsValue = false;\n\n    /**\n     * @var string\n     */\n    protected $visibleColumn = null;\n\n    /**\n     * @var string\n     */\n    protected $key = null;\n\n    /**\n     * @var \\Closure\n     */\n    protected $saveAction = null;\n\n    /**\n     * @var array\n     */\n    protected $separators = [',', ';', '，', '；', ' '];\n\n    /**\n     * @var array\n     */\n    protected static $css = [\n        '/vendor/laravel-admin/AdminLTE/plugins/select2/select2.min.css',\n    ];\n\n    /**\n     * @var array\n     */\n    protected static $js = [\n        '/vendor/laravel-admin/AdminLTE/plugins/select2/select2.full.min.js',\n    ];\n\n    /**\n     * {@inheritdoc}\n     */\n    public function fill($data)\n    {\n        $this->value = Arr::get($data, $this->column);\n\n        if (is_array($this->value) && $this->keyAsValue) {\n            $this->value = array_column($this->value, $this->visibleColumn, $this->key);\n        }\n\n        if (is_string($this->value)) {\n            $this->value = explode(',', $this->value);\n        }\n\n        $this->value = array_filter((array) $this->value, 'strlen');\n    }\n\n    /**\n     * Set visible column and key of data.\n     *\n     * @param $visibleColumn\n     * @param $key\n     *\n     * @return $this\n     */\n    public function pluck($visibleColumn, $key)\n    {\n        if (!empty($visibleColumn) && !empty($key)) {\n            $this->keyAsValue = true;\n        }\n\n        $this->visibleColumn = $visibleColumn;\n        $this->key = $key;\n\n        return $this;\n    }\n\n    /**\n     * Set the field options.\n     *\n     * @param array|Collection|Arrayable $options\n     *\n     * @return $this|Field\n     */\n    public function options($options = [])\n    {\n        if (!$this->keyAsValue) {\n            return parent::options($options);\n        }\n\n        if ($options instanceof Collection) {\n            $options = $options->pluck($this->visibleColumn, $this->key)->toArray();\n        }\n\n        if ($options instanceof Arrayable) {\n            $options = $options->toArray();\n        }\n\n        $this->options = $options + $this->options;\n\n        return $this;\n    }\n\n    /**\n     * Set Tag Separators.\n     *\n     * @param array $separators\n     *\n     * @return $this\n     */\n    public function separators($separators = [])\n    {\n        if ($separators instanceof Collection or $separators instanceof Arrayable) {\n            $separators = $separators->toArray();\n        }\n        if (!empty($separators)) {\n            $this->separators = $separators;\n        }\n\n        return $this;\n    }\n\n    /**\n     * Set save Action.\n     *\n     * @param \\Closure $saveAction\n     *\n     * @return $this\n     */\n    public function saving(\\Closure $saveAction)\n    {\n        $this->saveAction = $saveAction;\n\n        return $this;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function prepare($value)\n    {\n        $value = array_filter($value, 'strlen');\n\n        if ($this->keyAsValue) {\n            return is_null($this->saveAction) ? $value : ($this->saveAction)($value);\n        }\n\n        if (is_array($value) && !Arr::isAssoc($value)) {\n            $value = implode(',', $value);\n        }\n\n        return $value;\n    }\n\n    /**\n     * Get or set value for this field.\n     *\n     * @param mixed $value\n     *\n     * @return $this|array|mixed\n     */\n    public function value($value = null)\n    {\n        if (is_null($value)) {\n            return empty($this->value) ? ($this->getDefault() ?? []) : $this->value;\n        }\n\n        $this->value = (array) $value;\n\n        return $this;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function render()\n    {\n        if (!$this->shouldRender()) {\n            return '';\n        }\n\n        $this->setupScript();\n\n        if ($this->keyAsValue) {\n            $options = $this->value + $this->options;\n        } else {\n            $options = array_unique(array_merge($this->value, $this->options));\n        }\n\n        return parent::fieldRender([\n            'options'    => $options,\n            'keyAsValue' => $this->keyAsValue,\n        ]);\n    }\n\n    protected function setupScript()\n    {\n        $separators = json_encode($this->separators);\n        $separatorsStr = implode('', $this->separators);\n        $this->script = <<<JS\n$(\"{$this->getElementClassSelector()}\").select2({\n    tags: true,\n    tokenSeparators: $separators,\n    createTag: function(params) {\n        if (/[$separatorsStr]/.test(params.term)) {\n            var str = params.term.trim().replace(/[$separatorsStr]*$/, '');\n            return { id: str, text: str }\n        } else {\n            return null;\n        }\n    }\n});\nJS;\n\n        Admin::script(\n            <<<'JS'\n$(document).off('keyup', '.select2-selection--multiple .select2-search__field').on('keyup', '.select2-selection--multiple .select2-search__field', function (event) {\n    try {\n        if (event.keyCode == 13) {\n            var $this = $(this), optionText = $this.val();\n            if (optionText != \"\" && $this.find(\"option[value='\" + optionText + \"']\").length === 0) {\n                var $select = $this.parents('.select2-container').prev(\"select\");\n                var newOption = new Option(optionText, optionText, true, true);\n                $select.append(newOption).trigger('change');\n                $this.val('');\n                $select.select2('close');\n            }\n        }\n    } catch (e) {\n        console.error(e);\n    }\n});\nJS\n        );\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Text.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Form\\Field;\n\nclass Text extends Field\n{\n    use PlainInput;\n    use HasValuePicker;\n\n    /**\n     * @var string\n     */\n    protected $icon = 'fa-pencil';\n\n    /**\n     * @var bool\n     */\n    protected $withoutIcon = false;\n\n    /**\n     * Set custom fa-icon.\n     *\n     * @param string $icon\n     *\n     * @return $this\n     */\n    public function icon($icon)\n    {\n        $this->icon = $icon;\n\n        return $this;\n    }\n\n    /**\n     * Render this filed.\n     *\n     * @return \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View\n     */\n    public function render()\n    {\n        $this->initPlainInput();\n\n        if (!$this->withoutIcon) {\n            $this->prepend('<i class=\"fa '.$this->icon.' fa-fw\"></i>');\n        }\n        $this->defaultAttribute('type', 'text')\n            ->defaultAttribute('id', $this->id)\n            ->defaultAttribute('name', $this->elementName ?: $this->formatName($this->column))\n            ->defaultAttribute('value', old($this->elementName ?: $this->column, $this->value()))\n            ->defaultAttribute('class', 'form-control '.$this->getElementClassString())\n            ->defaultAttribute('placeholder', $this->getPlaceholder())\n            ->mountPicker()\n            ->addVariables([\n                'prepend' => $this->prepend,\n                'append'  => $this->append,\n            ]);\n\n        return parent::render();\n    }\n\n    /**\n     * Add inputmask to an elements.\n     *\n     * @param array $options\n     *\n     * @return $this\n     */\n    public function inputmask($options)\n    {\n        $options = json_encode_options($options);\n\n        $this->script = \"$('{$this->getElementClassSelector()}').inputmask($options);\";\n\n        return $this;\n    }\n\n    /**\n     * Add datalist element to Text input.\n     *\n     * @param array $entries\n     *\n     * @return $this\n     */\n    public function datalist($entries = [])\n    {\n        $this->defaultAttribute('list', \"list-{$this->id}\");\n\n        $datalist = \"<datalist id=\\\"list-{$this->id}\\\">\";\n        foreach ($entries as $k => $v) {\n            $datalist .= \"<option value=\\\"{$k}\\\">{$v}</option>\";\n        }\n        $datalist .= '</datalist>';\n\n        return $this->append($datalist);\n    }\n\n    /**\n     * show no icon in font of input.\n     *\n     * @return $this\n     */\n    public function withoutIcon()\n    {\n        $this->withoutIcon = true;\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Textarea.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Form\\Field;\n\nclass Textarea extends Field\n{\n    use HasValuePicker;\n\n    /**\n     * Default rows of textarea.\n     *\n     * @var int\n     */\n    protected $rows = 5;\n\n    /**\n     * @var string\n     */\n    protected $append = '';\n\n    /**\n     * Set rows of textarea.\n     *\n     * @param int $rows\n     *\n     * @return $this\n     */\n    public function rows($rows = 5)\n    {\n        $this->rows = $rows;\n\n        return $this;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function render()\n    {\n        if (!$this->shouldRender()) {\n            return '';\n        }\n\n        if (is_array($this->value)) {\n            $this->value = json_encode($this->value, JSON_PRETTY_PRINT);\n        }\n\n        $this->mountPicker(function ($btn) {\n            $this->addPickBtn($btn);\n        });\n\n        return parent::fieldRender([\n            'append' => $this->append,\n            'rows'   => $this->rows,\n        ]);\n    }\n\n    /**\n     * @param string $wrap\n     */\n    protected function addPickBtn($btn)\n    {\n        $style = <<<'STYLE'\n.textarea-picker {\n    padding: 5px;\n    border-bottom: 1px solid #d2d6de;\n    border-left: 1px solid #d2d6de;\n    border-right: 1px solid #d2d6de;\n    border-bottom-left-radius: 5px;\n    border-bottom-right-radius: 5px;\n    background-color: #f1f2f3;\n}\n\n.textarea-picker .btn {\n    padding: 5px 10px;\n    font-size: 12px;\n    line-height: 1.5;\n}\nSTYLE;\n        Admin::style($style);\n\n        $this->append = <<<HTML\n<div class=\"text-right textarea-picker\">\n    {$btn}\n</div>\nHTML;\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Time.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nclass Time extends Date\n{\n    protected $format = 'HH:mm:ss';\n\n    public function render()\n    {\n        $this->prepend('<i class=\"fa fa-clock-o fa-fw\"></i>')\n            ->defaultAttribute('style', 'width: 150px');\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/TimeRange.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nclass TimeRange extends DateRange\n{\n    protected $format = 'HH:mm:ss';\n}\n"
  },
  {
    "path": "src/Form/Field/Timezone.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse DateTimeZone;\n\nclass Timezone extends Select\n{\n    protected $view = 'admin::form.select';\n\n    public function render()\n    {\n        $this->options = collect(DateTimeZone::listIdentifiers(DateTimeZone::ALL))->mapWithKeys(function ($timezone) {\n            return [$timezone => $timezone];\n        })->toArray();\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/UploadField.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Form;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Facades\\Storage;\nuse Illuminate\\Support\\Facades\\URL;\nuse Symfony\\Component\\HttpFoundation\\File\\UploadedFile;\n\ntrait UploadField\n{\n    /**\n     * Upload directory.\n     *\n     * @var string\n     */\n    protected $directory = '';\n\n    /**\n     * File name.\n     *\n     * @var null\n     */\n    protected $name = null;\n\n    /**\n     * Storage instance.\n     *\n     * @var \\Illuminate\\Filesystem\\Filesystem\n     */\n    protected $storage = '';\n\n    /**\n     * If use unique name to store upload file.\n     *\n     * @var bool\n     */\n    protected $useUniqueName = false;\n\n    /**\n     * If use sequence name to store upload file.\n     *\n     * @var bool\n     */\n    protected $useSequenceName = false;\n\n    /**\n     * Retain file when delete record from DB.\n     *\n     * @var bool\n     */\n    protected $retainable = false;\n\n    /**\n     * @var bool\n     */\n    protected $downloadable = true;\n\n    /**\n     * Configuration for setting up file actions for newly selected file thumbnails in the preview window.\n     *\n     * @var array\n     */\n    protected $fileActionSettings = [\n        'showRemove' => false,\n        'showDrag'   => false,\n    ];\n\n    /**\n     * Controls the storage permission. Could be 'private' or 'public'.\n     *\n     * @var string\n     */\n    protected $storagePermission;\n\n    /**\n     * @var array\n     */\n    protected $fileTypes = [\n        'image'  => '/^(gif|png|jpe?g|svg|webp)$/i',\n        'html'   => '/^(htm|html)$/i',\n        'office' => '/^(docx?|xlsx?|pptx?|pps|potx?)$/i',\n        'gdocs'  => '/^(docx?|xlsx?|pptx?|pps|potx?|rtf|ods|odt|pages|ai|dxf|ttf|tiff?|wmf|e?ps)$/i',\n        'text'   => '/^(txt|md|csv|nfo|ini|json|php|js|css|ts|sql)$/i',\n        'video'  => '/^(og?|mp4|webm|mp?g|mov|3gp)$/i',\n        'audio'  => '/^(og?|mp3|mp?g|wav)$/i',\n        'pdf'    => '/^(pdf)$/i',\n        'flash'  => '/^(swf)$/i',\n    ];\n\n    /**\n     * @var string\n     */\n    protected $pathColumn;\n\n    /**\n     * Initialize the storage instance.\n     *\n     * @return void.\n     */\n    protected function initStorage()\n    {\n        $this->disk(config('admin.upload.disk'));\n    }\n\n    /**\n     * Set default options form image field.\n     *\n     * @return void\n     */\n    protected function setupDefaultOptions()\n    {\n        $defaults = [\n            'overwriteInitial'     => false,\n            'initialPreviewAsData' => true,\n            'msgPlaceholder'       => trans('admin.choose_file'),\n            'browseLabel'          => trans('admin.browse'),\n            'cancelLabel'          => trans('admin.cancel'),\n            'showRemove'           => false,\n            'showUpload'           => false,\n            'showCancel'           => false,\n            'dropZoneEnabled'      => false,\n            'deleteExtraData'      => [\n                $this->formatName($this->column) => static::FILE_DELETE_FLAG,\n                static::FILE_DELETE_FLAG         => '',\n                '_token'                         => csrf_token(),\n                '_method'                        => 'PUT',\n            ],\n        ];\n\n        if ($this->form instanceof Form) {\n            $defaults['deleteUrl'] = $this->form->resource().'/'.$this->form->model()->getKey();\n        }\n\n        $defaults = array_merge($defaults, ['fileActionSettings' => $this->fileActionSettings]);\n\n        $this->options($defaults);\n    }\n\n    /**\n     * Set preview options form image field.\n     *\n     * @return void\n     */\n    protected function setupPreviewOptions()\n    {\n        $initialPreviewConfig = $this->initialPreviewConfig();\n\n        $this->options(compact('initialPreviewConfig'));\n    }\n\n    /**\n     * @return array|bool\n     */\n    protected function guessPreviewType($file)\n    {\n        $filetype = 'other';\n        $ext = strtok(strtolower(pathinfo($file, PATHINFO_EXTENSION)), '?');\n\n        foreach ($this->fileTypes as $type => $pattern) {\n            if (preg_match($pattern, $ext) === 1) {\n                $filetype = $type;\n                break;\n            }\n        }\n\n        $extra = ['type' => $filetype];\n\n        if ($filetype == 'video') {\n            $extra['filetype'] = \"video/{$ext}\";\n        }\n\n        if ($filetype == 'audio') {\n            $extra['filetype'] = \"audio/{$ext}\";\n        }\n\n        if ($this->downloadable) {\n            $extra['downloadUrl'] = $this->objectUrl($file);\n        }\n\n        return $extra;\n    }\n\n    /**\n     * Indicates if the underlying field is downloadable.\n     *\n     * @param bool $downloadable\n     *\n     * @return $this\n     */\n    public function downloadable($downloadable = true)\n    {\n        $this->downloadable = $downloadable;\n\n        return $this;\n    }\n\n    /**\n     * Allow use to remove file.\n     *\n     * @return $this\n     */\n    public function removable()\n    {\n        $this->fileActionSettings['showRemove'] = true;\n\n        return $this;\n    }\n\n    /**\n     * Indicates if the underlying field is retainable.\n     *\n     * @return $this\n     */\n    public function retainable($retainable = true)\n    {\n        $this->retainable = $retainable;\n\n        return $this;\n    }\n\n    /**\n     * Set options for file-upload plugin.\n     *\n     * @param array $options\n     *\n     * @return $this\n     */\n    public function options($options = [])\n    {\n        $this->options = array_merge($options, $this->options);\n\n        return $this;\n    }\n\n    /**\n     * Set disk for storage.\n     *\n     * @param string $disk Disks defined in `config/filesystems.php`.\n     *\n     * @throws \\Exception\n     *\n     * @return $this\n     */\n    public function disk($disk)\n    {\n        try {\n            $this->storage = Storage::disk($disk);\n        } catch (\\Exception $exception) {\n            if (!array_key_exists($disk, config('filesystems.disks'))) {\n                admin_error(\n                    'Config error.',\n                    \"Disk [$disk] not configured, please add a disk config in `config/filesystems.php`.\"\n                );\n\n                return $this;\n            }\n\n            throw $exception;\n        }\n\n        return $this;\n    }\n\n    /**\n     * Specify the directory and name for upload file.\n     *\n     * @param string      $directory\n     * @param null|string $name\n     *\n     * @return $this\n     */\n    public function move($directory, $name = null)\n    {\n        $this->dir($directory);\n\n        $this->name($name);\n\n        return $this;\n    }\n\n    /**\n     * Specify the directory upload file.\n     *\n     * @param string $dir\n     *\n     * @return $this\n     */\n    public function dir($dir)\n    {\n        if ($dir) {\n            $this->directory = $dir;\n        }\n\n        return $this;\n    }\n\n    /**\n     * Set name of store name.\n     *\n     * @param string|callable $name\n     *\n     * @return $this\n     */\n    public function name($name)\n    {\n        if ($name) {\n            $this->name = $name;\n        }\n\n        return $this;\n    }\n\n    /**\n     * Use unique name for store upload file.\n     *\n     * @return $this\n     */\n    public function uniqueName()\n    {\n        $this->useUniqueName = true;\n\n        return $this;\n    }\n\n    /**\n     * Use sequence name for store upload file.\n     *\n     * @return $this\n     */\n    public function sequenceName()\n    {\n        $this->useSequenceName = true;\n\n        return $this;\n    }\n\n    /**\n     * Get store name of upload file.\n     *\n     * @param UploadedFile $file\n     *\n     * @return string\n     */\n    protected function getStoreName(UploadedFile $file)\n    {\n        if ($this->useUniqueName) {\n            return $this->generateUniqueName($file);\n        }\n\n        if ($this->useSequenceName) {\n            return $this->generateSequenceName($file);\n        }\n\n        if ($this->name instanceof \\Closure) {\n            return $this->name->call($this, $file);\n        }\n\n        if (is_string($this->name)) {\n            return $this->name;\n        }\n\n        return $file->getClientOriginalName();\n    }\n\n    /**\n     * Get directory for store file.\n     *\n     * @return mixed|string\n     */\n    public function getDirectory()\n    {\n        if ($this->directory instanceof \\Closure) {\n            return call_user_func($this->directory, $this->form);\n        }\n\n        return $this->directory ?: $this->defaultDirectory();\n    }\n\n    /**\n     * Set path column in has-many related model.\n     *\n     * @param string $column\n     *\n     * @return $this\n     */\n    public function pathColumn($column = 'path')\n    {\n        $this->pathColumn = $column;\n\n        return $this;\n    }\n\n    /**\n     * Upload file and delete original file.\n     *\n     * @param UploadedFile $file\n     *\n     * @return mixed\n     */\n    protected function upload(UploadedFile $file)\n    {\n        $this->renameIfExists($file);\n\n        if (!is_null($this->storagePermission)) {\n            return $this->storage->putFileAs($this->getDirectory(), $file, $this->name, $this->storagePermission);\n        }\n\n        return $this->storage->putFileAs($this->getDirectory(), $file, $this->name);\n    }\n\n    /**\n     * If name already exists, rename it.\n     *\n     * @param $file\n     *\n     * @return void\n     */\n    public function renameIfExists(UploadedFile $file)\n    {\n        if ($this->storage->exists(\"{$this->getDirectory()}/$this->name\")) {\n            $this->name = $this->generateUniqueName($file);\n        }\n    }\n\n    /**\n     * Get file visit url.\n     *\n     * @param $path\n     *\n     * @return string\n     */\n    public function objectUrl($path)\n    {\n        if ($this->pathColumn && is_array($path)) {\n            $path = Arr::get($path, $this->pathColumn);\n        }\n\n        if (URL::isValidUrl($path)) {\n            return $path;\n        }\n\n        if ($this->storage) {\n            return $this->storage->url($path);\n        }\n\n        return Storage::disk(config('admin.upload.disk'))->url($path);\n    }\n\n    /**\n     * Generate a unique name for uploaded file.\n     *\n     * @param UploadedFile $file\n     *\n     * @return string\n     */\n    protected function generateUniqueName(UploadedFile $file)\n    {\n        return md5(uniqid()).'.'.$file->getClientOriginalExtension();\n    }\n\n    /**\n     * Generate a sequence name for uploaded file.\n     *\n     * @param UploadedFile $file\n     *\n     * @return string\n     */\n    protected function generateSequenceName(UploadedFile $file)\n    {\n        $index = 1;\n        $extension = $file->getClientOriginalExtension();\n        $original = $file->getClientOriginalName();\n        $new = sprintf('%s_%s.%s', $original, $index, $extension);\n\n        while ($this->storage->exists(\"{$this->getDirectory()}/$new\")) {\n            $index++;\n            $new = sprintf('%s_%s.%s', $original, $index, $extension);\n        }\n\n        return $new;\n    }\n\n    /**\n     * Destroy original files.\n     *\n     * @return void.\n     */\n    public function destroy()\n    {\n        if ($this->retainable) {\n            return;\n        }\n\n        if (method_exists($this, 'destroyThumbnail')) {\n            $this->destroyThumbnail();\n        }\n\n        if (!empty($this->original) && $this->storage->exists($this->original)) {\n            $this->storage->delete($this->original);\n        }\n    }\n\n    /**\n     * Set file permission when stored into storage.\n     *\n     * @param string $permission\n     *\n     * @return $this\n     */\n    public function storagePermission($permission)\n    {\n        $this->storagePermission = $permission;\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Url.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nclass Url extends Text\n{\n    protected $rules = 'nullable|url';\n\n    public function render()\n    {\n        $this->prepend('<i class=\"fa fa-internet-explorer fa-fw\"></i>')\n            ->defaultAttribute('type', 'url');\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/ValuePicker.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Form\\Field;\nuse Illuminate\\Support\\Arr;\n\nclass ValuePicker\n{\n    /**\n     * @var string\n     */\n    protected $modal;\n\n    /**\n     * @var Text|File\n     */\n    protected $field;\n\n    /**\n     * @var string\n     */\n    protected $column;\n\n    /**\n     * @var string\n     */\n    protected $selecteable;\n\n    /**\n     * @var string\n     */\n    protected $separator;\n\n    /**\n     * @var bool\n     */\n    protected $multiple = false;\n\n    /**\n     * ValuePicker constructor.\n     *\n     * @param string $selecteable\n     * @param string $column\n     * @param bool   $multiple\n     * @param string $separator\n     */\n    public function __construct($selecteable, $column = '', $multiple = false, $separator = ';')\n    {\n        $this->selecteable = $selecteable;\n        $this->column = $column;\n        $this->multiple = $multiple;\n        $this->separator = $separator;\n    }\n\n    /**\n     * @param int $multiple\n     *\n     * @return string\n     */\n    protected function getLoadUrl()\n    {\n        $selectable = str_replace('\\\\', '_', $this->selecteable);\n\n        $args = [$this->multiple, $this->column];\n\n        return route(admin_get_route('handle-selectable'), compact('selectable', 'args'));\n    }\n\n    /**\n     * @param Field         $field\n     * @param \\Closure|null $callback\n     */\n    public function mount(Field $field, \\Closure $callback = null)\n    {\n        $this->field = $field;\n        $this->modal = sprintf('picker-modal-%s', $field->getElementClassString());\n\n        $this->addPickBtn($callback);\n\n        Admin::component('admin::components.filepicker', [\n            'url'       => $this->getLoadUrl(),\n            'modal'     => $this->modal,\n            'selector'  => $this->field->getElementClassSelector(),\n            'separator' => $this->separator,\n            'multiple'  => $this->multiple,\n            'is_file'   => $this->field instanceof File,\n            'is_image'  => $this->field instanceof Image,\n            'url_tpl'   => $this->field instanceof File ? $this->field->objectUrl('__URL__') : '',\n        ]);\n    }\n\n    /**\n     * @param \\Closure|null $callback\n     */\n    protected function addPickBtn(\\Closure $callback = null)\n    {\n        $text = admin_trans('admin.browse');\n\n        $btn = <<<HTML\n<a class=\"btn btn-primary\" data-toggle=\"modal\" data-target=\"#{$this->modal}\">\n    <i class=\"fa fa-folder-open\"></i>  {$text}\n</a>\nHTML;\n\n        if ($callback) {\n            $callback($btn);\n        } else {\n            $this->field->addVariables(compact('btn'));\n        }\n    }\n\n    /**\n     * @param string $field\n     *\n     * @return array|\\Illuminate\\Support\\Collection\n     */\n    public function getPreview(string $field)\n    {\n        if (empty($value = $this->field->value())) {\n            return [];\n        }\n\n        if ($this->multiple) {\n            $value = explode($this->separator, $value);\n        }\n\n        return collect(Arr::wrap($value))->map(function ($item) use ($field) {\n            return [\n                'url'     => $this->field->objectUrl($item),\n                'value'   => $item,\n                'is_file' => $field == File::class,\n            ];\n        });\n    }\n}\n"
  },
  {
    "path": "src/Form/Field/Year.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form\\Field;\n\nclass Year extends Date\n{\n    protected $format = 'YYYY';\n}\n"
  },
  {
    "path": "src/Form/Field.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form;\n\nuse Closure;\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Form;\nuse Encore\\Admin\\Widgets\\Form as WidgetForm;\nuse Illuminate\\Contracts\\Support\\Arrayable;\nuse Illuminate\\Contracts\\Support\\Renderable;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Str;\nuse Illuminate\\Support\\Traits\\Macroable;\n\n/**\n * Class Field.\n */\nclass Field implements Renderable\n{\n    use Macroable;\n\n    const FILE_DELETE_FLAG = '_file_del_';\n    const FILE_SORT_FLAG = '_file_sort_';\n\n    /**\n     * Element id.\n     *\n     * @var array|string\n     */\n    protected $id;\n\n    /**\n     * Element value.\n     *\n     * @var mixed\n     */\n    protected $value;\n\n    /**\n     * Data of all original columns of value.\n     *\n     * @var mixed\n     */\n    protected $data;\n\n    /**\n     * Field original value.\n     *\n     * @var mixed\n     */\n    protected $original;\n\n    /**\n     * Field default value.\n     *\n     * @var mixed\n     */\n    protected $default;\n\n    /**\n     * Element label.\n     *\n     * @var string\n     */\n    protected $label = '';\n\n    /**\n     * Column name.\n     *\n     * @var string|array\n     */\n    protected $column = '';\n\n    /**\n     * Form element name.\n     *\n     * @var string\n     */\n    protected $elementName = [];\n\n    /**\n     * Form element classes.\n     *\n     * @var array\n     */\n    protected $elementClass = [];\n\n    /**\n     * Variables of elements.\n     *\n     * @var array\n     */\n    protected $variables = [];\n\n    /**\n     * Options for specify elements.\n     *\n     * @var array\n     */\n    protected $options = [];\n\n    /**\n     * Checked for specify elements.\n     *\n     * @var array\n     */\n    protected $checked = [];\n\n    /**\n     * Validation rules.\n     *\n     * @var array|\\Closure\n     */\n    protected $rules = [];\n\n    /**\n     * The validation rules for creation.\n     *\n     * @var array|\\Closure\n     */\n    public $creationRules = [];\n\n    /**\n     * The validation rules for updates.\n     *\n     * @var array|\\Closure\n     */\n    public $updateRules = [];\n\n    /**\n     * @var \\Closure\n     */\n    protected $validator;\n\n    /**\n     * Validation messages.\n     *\n     * @var array\n     */\n    protected $validationMessages = [];\n\n    /**\n     * Css required by this field.\n     *\n     * @var array\n     */\n    protected static $css = [];\n\n    /**\n     * Js required by this field.\n     *\n     * @var array\n     */\n    protected static $js = [];\n\n    /**\n     * Script for field.\n     *\n     * @var string\n     */\n    protected $script = '';\n\n    /**\n     * Element attributes.\n     *\n     * @var array\n     */\n    protected $attributes = [];\n\n    /**\n     * Parent form.\n     *\n     * @var Form|WidgetForm\n     */\n    protected $form = null;\n\n    /**\n     * View for field to render.\n     *\n     * @var string\n     */\n    protected $view = '';\n\n    /**\n     * Help block.\n     *\n     * @var array\n     */\n    protected $help = [];\n\n    /**\n     * Key for errors.\n     *\n     * @var mixed\n     */\n    protected $errorKey;\n\n    /**\n     * Placeholder for this field.\n     *\n     * @var string|array\n     */\n    protected $placeholder;\n\n    /**\n     * Width for label and field.\n     *\n     * @var array\n     */\n    protected $width = [\n        'label' => 2,\n        'field' => 8,\n    ];\n\n    /**\n     * If the form horizontal layout.\n     *\n     * @var bool\n     */\n    protected $horizontal = true;\n\n    /**\n     * column data format.\n     *\n     * @var \\Closure\n     */\n    protected $customFormat = null;\n\n    /**\n     * @var bool\n     */\n    protected $display = true;\n\n    /**\n     * @var array\n     */\n    protected $labelClass = [];\n\n    /**\n     * @var array\n     */\n    protected $groupClass = [];\n\n    /**\n     * @var \\Closure\n     */\n    protected $callback;\n\n    /**\n     * column is snake-casing attributes.\n     *\n     * @var bool\n     */\n    protected $snakeAttributes = false;\n\n    /**\n     * @var bool\n     */\n    public $isJsonType = false;\n\n    /**\n     * Field constructor.\n     *\n     * @param       $column\n     * @param array $arguments\n     */\n    public function __construct($column = '', $arguments = [])\n    {\n        $this->column = $this->formatColumn($column);\n        $this->label = $this->formatLabel($arguments);\n        $this->id = $this->formatId($column);\n    }\n\n    /**\n     * Get assets required by this field.\n     *\n     * @return array\n     */\n    public static function getAssets()\n    {\n        return [\n            'css' => static::$css,\n            'js'  => static::$js,\n        ];\n    }\n\n    /**\n     * Format the field column name.\n     *\n     * @param string $column\n     *\n     * @return mixed|string\n     */\n    protected function formatColumn($column = '')\n    {\n        if (Str::contains($column, '->')) {\n            $this->isJsonType = true;\n\n            $column = str_replace('->', '.', $column);\n        }\n\n        return $column;\n    }\n\n    /**\n     * Format the field element id.\n     *\n     * @param string|array $column\n     *\n     * @return string|array\n     */\n    protected function formatId($column)\n    {\n        return str_replace('.', '_', $column);\n    }\n\n    /**\n     * Format the label value.\n     *\n     * @param array $arguments\n     *\n     * @return string\n     */\n    protected function formatLabel($arguments = []): string\n    {\n        $column = is_array($this->column) ? current($this->column) : $this->column;\n\n        $label = $arguments[0] ?? ucfirst($column);\n\n        return str_replace(['.', '_', '->'], ' ', $label);\n    }\n\n    /**\n     * Format the name of the field.\n     *\n     * @param string $column\n     *\n     * @return array|mixed|string\n     */\n    protected function formatName($column)\n    {\n        if (is_string($column)) {\n            if (Str::contains($column, '->')) {\n                $name = explode('->', $column);\n            } else {\n                $name = explode('.', $column);\n            }\n\n            if (count($name) === 1) {\n                return $name[0];\n            }\n\n            $html = array_shift($name);\n            foreach ($name as $piece) {\n                $html .= \"[$piece]\";\n            }\n\n            return $html;\n        }\n\n        if (is_array($this->column)) {\n            $names = [];\n            foreach ($this->column as $key => $name) {\n                $names[$key] = $this->formatName($name);\n            }\n\n            return $names;\n        }\n\n        return '';\n    }\n\n    /**\n     * Set form element name.\n     *\n     * @param string $name\n     *\n     * @return $this\n     *\n     * @author Edwin Hui\n     */\n    public function setElementName($name): self\n    {\n        $this->elementName = $name;\n\n        return $this;\n    }\n\n    /**\n     * Set snake attributes to the field.\n     *\n     * @param bool $snakeAttributes\n     *\n     * @return $this\n     */\n    public function setSnakeAttributes($snakeAttributes)\n    {\n        $this->snakeAttributes = $snakeAttributes;\n\n        return $this;\n    }\n\n    /**\n     * Get snake attributes of the field.\n     *\n     * @return bool\n     */\n    public function getSnakeAttributes()\n    {\n        return $this->snakeAttributes;\n    }\n\n    /**\n     * Determine if a column needs to be snaked.\n     *\n     * @param string|array $column\n     *\n     * @return string|array\n     */\n    protected function columnShouldSnaked($column)\n    {\n        return $this->getSnakeAttributes() ? Str::snake($column) : $column;\n    }\n\n    /**\n     * Fill data to the field.\n     *\n     * @param array $data\n     *\n     * @return void\n     */\n    public function fill($data)\n    {\n        $this->data = $data;\n\n        if (is_array($this->column)) {\n            foreach ($this->column as $key => $column) {\n                $this->value[$key] = Arr::get($data, $this->columnShouldSnaked($column));\n            }\n\n            return;\n        }\n\n        $this->value = Arr::get($data, $this->columnShouldSnaked($this->column));\n\n        $this->formatValue();\n    }\n\n    /**\n     * Format value by passing custom formater.\n     */\n    protected function formatValue()\n    {\n        if (isset($this->customFormat) && $this->customFormat instanceof \\Closure) {\n            $this->value = call_user_func($this->customFormat, $this->value);\n        }\n    }\n\n    /**\n     * custom format form column data when edit.\n     *\n     * @param \\Closure $call\n     *\n     * @return $this\n     */\n    public function customFormat(\\Closure $call): self\n    {\n        $this->customFormat = $call;\n\n        return $this;\n    }\n\n    /**\n     * Set original value to the field.\n     *\n     * @param array $data\n     *\n     * @return void\n     */\n    public function setOriginal($data)\n    {\n        if (is_array($this->column)) {\n            foreach ($this->column as $key => $column) {\n                $this->original[$key] = Arr::get($data, $column);\n            }\n\n            return;\n        }\n\n        $this->original = Arr::get($data, $this->column);\n    }\n\n    /**\n     * @param Form $form\n     *\n     * @return $this\n     */\n    public function setForm(Form $form = null)\n    {\n        $this->form = $form;\n\n        return $this;\n    }\n\n    /**\n     * Set Widget/Form as field parent.\n     *\n     * @param WidgetForm $form\n     *\n     * @return $this\n     */\n    public function setWidgetForm(WidgetForm $form)\n    {\n        $this->form = $form;\n\n        return $this;\n    }\n\n    /**\n     * Set width for field and label.\n     *\n     * @param int $field\n     * @param int $label\n     *\n     * @return $this\n     */\n    public function setWidth($field = 8, $label = 2): self\n    {\n        $this->width = [\n            'label' => $label,\n            'field' => $field,\n        ];\n\n        return $this;\n    }\n\n    /**\n     * Set the field options.\n     *\n     * @param array $options\n     *\n     * @return $this\n     */\n    public function options($options = [])\n    {\n        if ($options instanceof Arrayable) {\n            $options = $options->toArray();\n        }\n\n        $this->options = array_merge($this->options, $options);\n\n        return $this;\n    }\n\n    /**\n     * Set the field option checked.\n     *\n     * @param array $checked\n     *\n     * @return $this\n     */\n    public function checked($checked = [])\n    {\n        if ($checked instanceof Arrayable) {\n            $checked = $checked->toArray();\n        }\n\n        $this->checked = array_merge($this->checked, $checked);\n\n        return $this;\n    }\n\n    /**\n     * Add `required` attribute to current field if has required rule,\n     * except file and image fields.\n     *\n     * @param array $rules\n     */\n    protected function addRequiredAttribute($rules)\n    {\n        if (!is_array($rules)) {\n            return;\n        }\n\n        if (!in_array('required', $rules, true)) {\n            return;\n        }\n\n        $this->setLabelClass(['asterisk']);\n\n        // Only text field has `required` attribute.\n        if (!$this instanceof Form\\Field\\Text) {\n            return;\n        }\n\n        //do not use required attribute with tabs\n        if ($this->form && $this->form->getTab()) {\n            return;\n        }\n\n        $this->required();\n    }\n\n    /**\n     * If has `required` rule, add required attribute to this field.\n     */\n    protected function addRequiredAttributeFromRules()\n    {\n        if ($this->data === null) {\n            // Create page\n            $rules = $this->creationRules ?: $this->rules;\n        } else {\n            // Update page\n            $rules = $this->updateRules ?: $this->rules;\n        }\n\n        $this->addRequiredAttribute($rules);\n    }\n\n    /**\n     * Format validation rules.\n     *\n     * @param array|string $rules\n     *\n     * @return array\n     */\n    protected function formatRules($rules): array\n    {\n        if (is_string($rules)) {\n            $rules = array_filter(explode('|', $rules));\n        }\n\n        return array_filter((array) $rules);\n    }\n\n    /**\n     * @param string|array|Closure $input\n     * @param string|array         $original\n     *\n     * @return array|Closure\n     */\n    protected function mergeRules($input, $original)\n    {\n        if ($input instanceof Closure) {\n            $rules = $input;\n        } else {\n            if (!empty($original)) {\n                $original = $this->formatRules($original);\n            }\n\n            $rules = array_merge($original, $this->formatRules($input));\n        }\n\n        return $rules;\n    }\n\n    /**\n     * Set the validation rules for the field.\n     *\n     * @param array|callable|string $rules\n     * @param array                 $messages\n     *\n     * @return $this\n     */\n    public function rules($rules = null, $messages = []): self\n    {\n        $this->rules = $this->mergeRules($rules, $this->rules);\n\n        $this->setValidationMessages('default', $messages);\n\n        return $this;\n    }\n\n    /**\n     * Set the update validation rules for the field.\n     *\n     * @param array|callable|string $rules\n     * @param array                 $messages\n     *\n     * @return $this\n     */\n    public function updateRules($rules = null, $messages = []): self\n    {\n        $this->updateRules = $this->mergeRules($rules, $this->updateRules);\n\n        $this->setValidationMessages('update', $messages);\n\n        return $this;\n    }\n\n    /**\n     * Set the creation validation rules for the field.\n     *\n     * @param array|callable|string $rules\n     * @param array                 $messages\n     *\n     * @return $this\n     */\n    public function creationRules($rules = null, $messages = []): self\n    {\n        $this->creationRules = $this->mergeRules($rules, $this->creationRules);\n\n        $this->setValidationMessages('creation', $messages);\n\n        return $this;\n    }\n\n    /**\n     * Set validation messages for column.\n     *\n     * @param string $key\n     * @param array  $messages\n     *\n     * @return $this\n     */\n    public function setValidationMessages($key, array $messages): self\n    {\n        $this->validationMessages[$key] = $messages;\n\n        return $this;\n    }\n\n    /**\n     * Get validation messages for the field.\n     *\n     * @return array|mixed\n     */\n    public function getValidationMessages()\n    {\n        // Default validation message.\n        $messages = $this->validationMessages['default'] ?? [];\n\n        if (request()->isMethod('POST')) {\n            $messages = $this->validationMessages['creation'] ?? $messages;\n        } elseif (request()->isMethod('PUT')) {\n            $messages = $this->validationMessages['update'] ?? $messages;\n        }\n\n        return $messages;\n    }\n\n    /**\n     * Get field validation rules.\n     *\n     * @return string\n     */\n    protected function getRules()\n    {\n        if (request()->isMethod('POST')) {\n            $rules = $this->creationRules ?: $this->rules;\n        } elseif (request()->isMethod('PUT')) {\n            $rules = $this->updateRules ?: $this->rules;\n        } else {\n            $rules = $this->rules;\n        }\n\n        if ($rules instanceof \\Closure) {\n            $rules = $rules->call($this, $this->form);\n        }\n\n        if (is_string($rules)) {\n            $rules = array_filter(explode('|', $rules));\n        }\n\n        if (!$this->form || !$this->form instanceof Form) {\n            return $rules;\n        }\n\n        if (!$id = $this->form->model()->getKey()) {\n            return $rules;\n        }\n\n        if (is_array($rules)) {\n            foreach ($rules as &$rule) {\n                if (is_string($rule)) {\n                    $rule = str_replace('{{id}}', $id, $rule);\n                }\n            }\n        }\n\n        return $rules;\n    }\n\n    /**\n     * Remove a specific rule by keyword.\n     *\n     * @param string $rule\n     *\n     * @return void\n     */\n    protected function removeRule($rule)\n    {\n        if (is_array($this->rules)) {\n            array_delete($this->rules, $rule);\n\n            return;\n        }\n\n        if (!is_string($this->rules)) {\n            return;\n        }\n\n        $pattern = \"/{$rule}[^\\|]?(\\||$)/\";\n        $this->rules = preg_replace($pattern, '', $this->rules, -1);\n    }\n\n    /**\n     * Set field validator.\n     *\n     * @param callable $validator\n     *\n     * @return $this\n     */\n    public function validator(callable $validator): self\n    {\n        $this->validator = $validator;\n\n        return $this;\n    }\n\n    /**\n     * Get key for error message.\n     *\n     * @return string|array\n     */\n    public function getErrorKey()\n    {\n        return $this->errorKey ?: $this->column;\n    }\n\n    /**\n     * Set key for error message.\n     *\n     * @param string $key\n     *\n     * @return $this\n     */\n    public function setErrorKey($key): self\n    {\n        $this->errorKey = $key;\n\n        return $this;\n    }\n\n    /**\n     * Set or get value of the field.\n     *\n     * @param null $value\n     *\n     * @return mixed\n     */\n    public function value($value = null)\n    {\n        if ($value === null) {\n            return $this->value ?? $this->getDefault();\n        }\n\n        $this->value = $value;\n\n        return $this;\n    }\n\n    /**\n     * Set or get data.\n     *\n     * @param array $data\n     *\n     * @return mixed\n     */\n    public function data(array $data = null)\n    {\n        if ($data === null) {\n            return $this->data;\n        }\n\n        $this->data = $data;\n\n        return $this;\n    }\n\n    /**\n     * Set default value for field.\n     *\n     * @param $default\n     *\n     * @return $this\n     */\n    public function default($default): self\n    {\n        $this->default = $default;\n\n        return $this;\n    }\n\n    /**\n     * Get default value.\n     *\n     * @return mixed\n     */\n    public function getDefault()\n    {\n        if ($this->default instanceof \\Closure) {\n            return call_user_func($this->default, $this->form);\n        }\n\n        return $this->default;\n    }\n\n    /**\n     * Set help block for current field.\n     *\n     * @param string $text\n     * @param string $icon\n     *\n     * @return $this\n     */\n    public function help($text = '', $icon = 'fa-info-circle'): self\n    {\n        $this->help = compact('text', 'icon');\n\n        return $this;\n    }\n\n    /**\n     * Get column of the field.\n     *\n     * @return string|array\n     */\n    public function column()\n    {\n        return $this->column;\n    }\n\n    /**\n     * Get label of the field.\n     *\n     * @return string\n     */\n    public function label(): string\n    {\n        return $this->label;\n    }\n\n    /**\n     * Get original value of the field.\n     *\n     * @return mixed\n     */\n    public function original()\n    {\n        return $this->original;\n    }\n\n    /**\n     * Get validator for this field.\n     *\n     * @param array $input\n     *\n     * @return bool|\\Illuminate\\Contracts\\Validation\\Validator|mixed\n     */\n    public function getValidator(array $input)\n    {\n        if ($this->validator) {\n            return $this->validator->call($this, $input);\n        }\n\n        $rules = $attributes = [];\n\n        if (!$fieldRules = $this->getRules()) {\n            return false;\n        }\n\n        if (is_string($this->column)) {\n            if (!Arr::has($input, $this->column)) {\n                return false;\n            }\n\n            $input = $this->sanitizeInput($input, $this->column);\n\n            $rules[$this->column] = $fieldRules;\n            $attributes[$this->column] = $this->label;\n        }\n\n        if (is_array($this->column)) {\n            foreach ($this->column as $key => $column) {\n                if (!array_key_exists($column, $input)) {\n                    continue;\n                }\n                $input[$column.$key] = Arr::get($input, $column);\n                $rules[$column.$key] = $fieldRules;\n                $attributes[$column.$key] = $this->label.\"[$column]\";\n            }\n        }\n\n        return \\validator($input, $rules, $this->getValidationMessages(), $attributes);\n    }\n\n    /**\n     * Sanitize input data.\n     *\n     * @param array  $input\n     * @param string $column\n     *\n     * @return array\n     */\n    protected function sanitizeInput($input, $column)\n    {\n        if ($this instanceof Field\\MultipleSelect) {\n            $value = Arr::get($input, $column);\n            Arr::set($input, $column, array_filter($value));\n        }\n\n        return $input;\n    }\n\n    /**\n     * Add html attributes to elements.\n     *\n     * @param array|string $attribute\n     * @param mixed        $value\n     *\n     * @return $this\n     */\n    public function attribute($attribute, $value = null): self\n    {\n        if (is_array($attribute)) {\n            $this->attributes = array_merge($this->attributes, $attribute);\n        } else {\n            $this->attributes[$attribute] = (string) $value;\n        }\n\n        return $this;\n    }\n\n    /**\n     * Remove html attributes from elements.\n     *\n     * @param array|string $attribute\n     *\n     * @return $this\n     */\n    public function removeAttribute($attribute): self\n    {\n        Arr::forget($this->attributes, $attribute);\n\n        return $this;\n    }\n\n    /**\n     * Set Field style.\n     *\n     * @param string $attr\n     * @param string $value\n     *\n     * @return $this\n     */\n    public function style($attr, $value): self\n    {\n        return $this->attribute('style', \"{$attr}: {$value}\");\n    }\n\n    /**\n     * Set Field width.\n     *\n     * @param string $width\n     *\n     * @return $this\n     */\n    public function width($width): self\n    {\n        return $this->style('width', $width);\n    }\n\n    /**\n     * Specifies a regular expression against which to validate the value of the input.\n     *\n     * @param string $regexp\n     *\n     * @return $this\n     */\n    public function pattern($regexp): self\n    {\n        return $this->attribute('pattern', $regexp);\n    }\n\n    /**\n     * set the input filed required.\n     *\n     * @param bool $isLabelAsterisked\n     *\n     * @return $this\n     */\n    public function required($isLabelAsterisked = true): self\n    {\n        if ($isLabelAsterisked) {\n            $this->setLabelClass(['asterisk']);\n        }\n\n        return $this->attribute('required', true);\n    }\n\n    /**\n     * Set the field automatically get focus.\n     *\n     * @return $this\n     */\n    public function autofocus(): self\n    {\n        return $this->attribute('autofocus', true);\n    }\n\n    /**\n     * Set the field as readonly mode.\n     *\n     * @return $this\n     */\n    public function readonly()\n    {\n        return $this->attribute('readonly', true);\n    }\n\n    /**\n     * Set field as disabled.\n     *\n     * @return $this\n     */\n    public function disable(): self\n    {\n        return $this->attribute('disabled', true);\n    }\n\n    /**\n     * Set field placeholder.\n     *\n     * @param string $placeholder\n     *\n     * @return $this\n     */\n    public function placeholder($placeholder = ''): self\n    {\n        $this->placeholder = $placeholder;\n\n        return $this;\n    }\n\n    /**\n     * Get placeholder.\n     *\n     * @return mixed\n     */\n    public function getPlaceholder()\n    {\n        return $this->placeholder ?: trans('admin.input').' '.$this->label;\n    }\n\n    /**\n     * Add a divider after this field.\n     *\n     * @return $this\n     */\n    public function divider()\n    {\n        $this->form->divider();\n\n        return $this;\n    }\n\n    /**\n     * Prepare for a field value before update or insert.\n     *\n     * @param $value\n     *\n     * @return mixed\n     */\n    public function prepare($value)\n    {\n        return $value;\n    }\n\n    /**\n     * Format the field attributes.\n     *\n     * @return string\n     */\n    protected function formatAttributes(): string\n    {\n        $html = [];\n\n        foreach ($this->attributes as $name => $value) {\n            $html[] = $name.'=\"'.e($value).'\"';\n        }\n\n        return implode(' ', $html);\n    }\n\n    /**\n     * @return $this\n     */\n    public function disableHorizontal(): self\n    {\n        $this->horizontal = false;\n\n        return $this;\n    }\n\n    /**\n     * @return array\n     */\n    public function getViewElementClasses(): array\n    {\n        if ($this->horizontal) {\n            return [\n                'label'      => \"col-sm-{$this->width['label']} {$this->getLabelClass()}\",\n                'field'      => \"col-sm-{$this->width['field']}\",\n                'form-group' => $this->getGroupClass(true),\n            ];\n        }\n\n        return ['label' => $this->getLabelClass(), 'field' => '', 'form-group' => ''];\n    }\n\n    /**\n     * Set form element class.\n     *\n     * @param string|array $class\n     *\n     * @return $this\n     */\n    public function setElementClass($class): self\n    {\n        $this->elementClass = array_merge($this->elementClass, (array) $class);\n\n        return $this;\n    }\n\n    /**\n     * Get element class.\n     *\n     * @return array\n     */\n    public function getElementClass(): array\n    {\n        if (!$this->elementClass) {\n            $name = $this->elementName ?: $this->formatName($this->column);\n\n            $this->elementClass = (array) str_replace(['[', ']'], '_', $name);\n        }\n\n        return $this->elementClass;\n    }\n\n    /**\n     * Get element class string.\n     *\n     * @return mixed\n     */\n    public function getElementClassString()\n    {\n        $elementClass = $this->getElementClass();\n\n        if (Arr::isAssoc($elementClass)) {\n            $classes = [];\n\n            foreach ($elementClass as $index => $class) {\n                $classes[$index] = is_array($class) ? implode(' ', $class) : $class;\n            }\n\n            return $classes;\n        }\n\n        return implode(' ', $elementClass);\n    }\n\n    /**\n     * Get element class selector.\n     *\n     * @return string|array\n     */\n    public function getElementClassSelector()\n    {\n        $elementClass = $this->getElementClass();\n\n        if (Arr::isAssoc($elementClass)) {\n            $classes = [];\n\n            foreach ($elementClass as $index => $class) {\n                $classes[$index] = '.'.(is_array($class) ? implode('.', $class) : $class);\n            }\n\n            return $classes;\n        }\n\n        return '.'.implode('.', $elementClass);\n    }\n\n    /**\n     * Add the element class.\n     *\n     * @param $class\n     *\n     * @return $this\n     */\n    public function addElementClass($class): self\n    {\n        if (is_array($class) || is_string($class)) {\n            $this->elementClass = array_unique(array_merge($this->elementClass, (array) $class));\n        }\n\n        return $this;\n    }\n\n    /**\n     * Remove element class.\n     *\n     * @param $class\n     *\n     * @return $this\n     */\n    public function removeElementClass($class): self\n    {\n        $delClass = [];\n\n        if (is_string($class) || is_array($class)) {\n            $delClass = (array) $class;\n        }\n\n        foreach ($delClass as $del) {\n            if (($key = array_search($del, $this->elementClass, true)) !== false) {\n                unset($this->elementClass[$key]);\n            }\n        }\n\n        return $this;\n    }\n\n    /**\n     * Set form group class.\n     *\n     * @param string|array $class\n     *\n     * @return $this\n     */\n    public function setGroupClass($class): self\n    {\n        if (is_array($class)) {\n            $this->groupClass = array_merge($this->groupClass, $class);\n        } else {\n            $this->groupClass[] = $class;\n        }\n\n        return $this;\n    }\n\n    /**\n     * Get element class.\n     *\n     * @param bool $default\n     *\n     * @return string\n     */\n    protected function getGroupClass($default = false): string\n    {\n        return ($default ? 'form-group ' : '').implode(' ', array_filter($this->groupClass));\n    }\n\n    /**\n     * reset field className.\n     *\n     * @param string $className\n     * @param string $resetClassName\n     *\n     * @return $this\n     */\n    public function resetElementClassName(string $className, string $resetClassName): self\n    {\n        if (($key = array_search($className, $this->getElementClass())) !== false) {\n            $this->elementClass[$key] = $resetClassName;\n        }\n\n        return $this;\n    }\n\n    /**\n     * Add variables to field view.\n     *\n     * @param array $variables\n     *\n     * @return $this\n     */\n    public function addVariables(array $variables = []): self\n    {\n        $this->variables = array_merge($this->variables, $variables);\n\n        return $this;\n    }\n\n    /**\n     * @return string\n     */\n    public function getLabelClass(): string\n    {\n        return implode(' ', $this->labelClass);\n    }\n\n    /**\n     * @param array $labelClass\n     * @param bool  $replace\n     *\n     * @return self\n     */\n    public function setLabelClass(array $labelClass, $replace = false): self\n    {\n        $this->labelClass = $replace ? $labelClass : array_merge($this->labelClass, $labelClass);\n\n        return $this;\n    }\n\n    /**\n     * Get the view variables of this field.\n     *\n     * @return array\n     */\n    public function variables(): array\n    {\n        return array_merge($this->variables, [\n            'id'          => $this->id,\n            'name'        => $this->elementName ?: $this->formatName($this->column),\n            'help'        => $this->help,\n            'class'       => $this->getElementClassString(),\n            'value'       => $this->value(),\n            'label'       => $this->label,\n            'viewClass'   => $this->getViewElementClasses(),\n            'column'      => $this->column,\n            'errorKey'    => $this->getErrorKey(),\n            'attributes'  => $this->formatAttributes(),\n            'placeholder' => $this->getPlaceholder(),\n        ]);\n    }\n\n    /**\n     * Get view of this field.\n     *\n     * @return string\n     */\n    public function getView(): string\n    {\n        if (!empty($this->view)) {\n            return $this->view;\n        }\n\n        $class = explode('\\\\', static::class);\n\n        return 'admin::form.'.strtolower(end($class));\n    }\n\n    /**\n     * Set view of current field.\n     *\n     * @param string $view\n     *\n     * @return string\n     */\n    public function setView($view): self\n    {\n        $this->view = $view;\n\n        return $this;\n    }\n\n    /**\n     * Get script of current field.\n     *\n     * @return string\n     */\n    public function getScript(): string\n    {\n        return $this->script;\n    }\n\n    /**\n     * Set script of current field.\n     *\n     * @param string $script\n     *\n     * @return $this\n     */\n    public function setScript($script): self\n    {\n        $this->script = $script;\n\n        return $this;\n    }\n\n    /**\n     * To set this field should render or not.\n     *\n     * @param bool $display\n     *\n     * @return $this\n     */\n    public function setDisplay(bool $display): self\n    {\n        $this->display = $display;\n\n        return $this;\n    }\n\n    /**\n     * If this field should render.\n     *\n     * @return bool\n     */\n    protected function shouldRender(): bool\n    {\n        if (!$this->display) {\n            return false;\n        }\n\n        return true;\n    }\n\n    /**\n     * @param \\Closure $callback\n     *\n     * @return \\Encore\\Admin\\Form\\Field\n     */\n    public function with(Closure $callback): self\n    {\n        $this->callback = $callback;\n\n        return $this;\n    }\n\n    /**\n     * Render this filed.\n     *\n     * @return \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View|string\n     */\n    public function render()\n    {\n        if (!$this->shouldRender()) {\n            return '';\n        }\n\n        $this->addRequiredAttributeFromRules();\n\n        if ($this->callback instanceof Closure) {\n            $this->value = $this->callback->call($this->form->model(), $this->value, $this);\n        }\n\n        Admin::script($this->script);\n\n        return Admin::component($this->getView(), $this->variables());\n    }\n\n    /**\n     * @return \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View|string\n     */\n    protected function fieldRender(array $variables = [])\n    {\n        if (!empty($variables)) {\n            $this->addVariables($variables);\n        }\n\n        return self::render();\n    }\n\n    /**\n     * @return string\n     */\n    public function __toString()\n    {\n        return $this->render()->render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Footer.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form;\n\nuse Encore\\Admin\\Admin;\nuse Illuminate\\Contracts\\Support\\Renderable;\n\nclass Footer implements Renderable\n{\n    /**\n     * Footer view.\n     *\n     * @var string\n     */\n    protected $view = 'admin::form.footer';\n\n    /**\n     * Form builder instance.\n     *\n     * @var Builder\n     */\n    protected $builder;\n\n    /**\n     * Available buttons.\n     *\n     * @var array\n     */\n    protected $buttons = ['reset', 'submit'];\n\n    /**\n     * Available checkboxes.\n     *\n     * @var array\n     */\n    protected $checkboxes = ['view', 'continue_editing', 'continue_creating'];\n\n    /**\n     * @var string\n     */\n    protected $defaultCheck;\n\n    /**\n     * Footer constructor.\n     *\n     * @param Builder $builder\n     */\n    public function __construct(Builder $builder)\n    {\n        $this->builder = $builder;\n    }\n\n    /**\n     * Disable reset button.\n     *\n     * @return $this\n     */\n    public function disableReset(bool $disable = true)\n    {\n        if ($disable) {\n            array_delete($this->buttons, 'reset');\n        } elseif (!in_array('reset', $this->buttons)) {\n            array_push($this->buttons, 'reset');\n        }\n\n        return $this;\n    }\n\n    /**\n     * Disable submit button.\n     *\n     * @return $this\n     */\n    public function disableSubmit(bool $disable = true)\n    {\n        if ($disable) {\n            array_delete($this->buttons, 'submit');\n        } elseif (!in_array('submit', $this->buttons)) {\n            array_push($this->buttons, 'submit');\n        }\n\n        return $this;\n    }\n\n    /**\n     * Disable View Checkbox.\n     *\n     * @return $this\n     */\n    public function disableViewCheck(bool $disable = true)\n    {\n        if ($disable) {\n            array_delete($this->checkboxes, 'view');\n        } elseif (!in_array('view', $this->checkboxes)) {\n            array_push($this->checkboxes, 'view');\n        }\n\n        return $this;\n    }\n\n    /**\n     * Disable Editing Checkbox.\n     *\n     * @return $this\n     */\n    public function disableEditingCheck(bool $disable = true)\n    {\n        if ($disable) {\n            array_delete($this->checkboxes, 'continue_editing');\n        } elseif (!in_array('continue_editing', $this->checkboxes)) {\n            array_push($this->checkboxes, 'continue_editing');\n        }\n\n        return $this;\n    }\n\n    /**\n     * Disable Creating Checkbox.\n     *\n     * @return $this\n     */\n    public function disableCreatingCheck(bool $disable = true)\n    {\n        if ($disable) {\n            array_delete($this->checkboxes, 'continue_creating');\n        } elseif (!in_array('continue_creating', $this->checkboxes)) {\n            array_push($this->checkboxes, 'continue_creating');\n        }\n\n        return $this;\n    }\n\n    /**\n     * Set `view` as default check.\n     *\n     * @return $this\n     */\n    public function checkView()\n    {\n        $this->defaultCheck = 'view';\n\n        return $this;\n    }\n\n    /**\n     * Set `continue_creating` as default check.\n     *\n     * @return $this\n     */\n    public function checkCreating()\n    {\n        $this->defaultCheck = 'continue_creating';\n\n        return $this;\n    }\n\n    /**\n     * Set `continue_editing` as default check.\n     *\n     * @return $this\n     */\n    public function checkEditing()\n    {\n        $this->defaultCheck = 'continue_editing';\n\n        return $this;\n    }\n\n    /**\n     * Setup scripts.\n     */\n    protected function setupScript()\n    {\n        $script = <<<'EOT'\n        \n$('.after-submit').iCheck({checkboxClass:'icheckbox_minimal-blue'}).on('ifChecked', function () {\n    $('.after-submit').not(this).iCheck('uncheck');\n});\nEOT;\n\n        Admin::script($script);\n    }\n\n    /**\n     * Render footer.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        $this->setupScript();\n\n        $submitRedirects = [\n            1 => 'continue_editing',\n            2 => 'continue_creating',\n            3 => 'view',\n        ];\n\n        $data = [\n            'width'            => $this->builder->getWidth(),\n            'buttons'          => $this->buttons,\n            'checkboxes'       => $this->checkboxes,\n            'submit_redirects' => $submitRedirects,\n            'default_check'    => $this->defaultCheck,\n        ];\n\n        return view($this->view, $data)->render();\n    }\n}\n"
  },
  {
    "path": "src/Form/Layout/Column.php",
    "content": "<?php\n/**\n * Copyright (c) 2019. Mallto.Co.Ltd.<mall-to.com> All rights reserved.\n */\n\nnamespace Encore\\Admin\\Form\\Layout;\n\nuse Encore\\Admin\\Form\\Field;\nuse Illuminate\\Support\\Collection;\n\nclass Column\n{\n    /**\n     * @var Collection\n     */\n    protected $fields;\n\n    /**\n     * @var int\n     */\n    protected $width;\n\n    /**\n     * Column constructor.\n     *\n     * @param int $width\n     */\n    public function __construct($width = 12)\n    {\n        $this->width = $width;\n        $this->fields = new Collection();\n    }\n\n    /**\n     * Add a filter to this column.\n     *\n     * @param Field $field\n     */\n    public function add(Field $field)\n    {\n        $this->fields->push($field);\n    }\n\n    /**\n     * Remove fields from column.\n     *\n     * @param $fields\n     */\n    public function removeFields($fields)\n    {\n        $this->fields = $this->fields->reject(function (Field $field) use ($fields) {\n            return in_array($field->column(), $fields);\n        });\n    }\n\n    /**\n     * Get all filters in this column.\n     *\n     * @return Collection\n     */\n    public function fields()\n    {\n        return $this->fields;\n    }\n\n    /**\n     * Set column width.\n     *\n     * @param int $width\n     */\n    public function setWidth($width)\n    {\n        $this->width = $width;\n    }\n\n    /**\n     * Get column width.\n     *\n     * @return int\n     */\n    public function width()\n    {\n        return $this->width;\n    }\n}\n"
  },
  {
    "path": "src/Form/Layout/Layout.php",
    "content": "<?php\n/**\n * Copyright (c) 2019. Mallto.Co.Ltd.<mall-to.com> All rights reserved.\n */\n\nnamespace Encore\\Admin\\Form\\Layout;\n\nuse Encore\\Admin\\Form;\nuse Illuminate\\Support\\Collection;\n\nclass Layout\n{\n    /**\n     * @var Collection\n     */\n    protected $columns;\n\n    /**\n     * @var Column\n     */\n    protected $current;\n\n    /**\n     * @var Form\n     */\n    protected $parent;\n\n    /**\n     * Layout constructor.\n     *\n     * @param Form $form\n     */\n    public function __construct(Form $form)\n    {\n        $this->parent = $form;\n\n        $this->current = new Column();\n\n        $this->columns = new Collection();\n    }\n\n    /**\n     * Add a filter to layout column.\n     *\n     * @param Form\\Field $field\n     */\n    public function addField(Form\\Field $field)\n    {\n        $this->current->add($field);\n    }\n\n    /**\n     * Add a new column in layout.\n     *\n     * @param int      $width\n     * @param \\Closure $closure\n     */\n    public function column($width, \\Closure $closure)\n    {\n        if ($this->columns->isEmpty()) {\n            $column = $this->current;\n\n            $column->setWidth($width);\n        } else {\n            $column = new Column($width);\n\n            $this->current = $column;\n        }\n\n        $this->columns->push($column);\n\n        $closure($this->parent);\n    }\n\n    /**\n     * Get all columns in filter layout.\n     *\n     * @return Collection\n     */\n    public function columns()\n    {\n        if ($this->columns->isEmpty()) {\n            $this->columns->push($this->current);\n        }\n\n        return $this->columns;\n    }\n\n    /**\n     * Remove reserved fields from form layout.\n     *\n     * @param array $fields\n     */\n    public function removeReservedFields(array $fields)\n    {\n        if (empty($fields)) {\n            return;\n        }\n\n        foreach ($this->columns() as &$column) {\n            $column->removeFields($fields);\n        }\n    }\n}\n"
  },
  {
    "path": "src/Form/NestedForm.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form;\n\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Form;\nuse Encore\\Admin\\Widgets\\Form as WidgetForm;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Collection;\n\n/**\n * Class NestedForm.\n *\n * @method Field\\Text           text($column, $label = '')\n * @method Field\\Checkbox       checkbox($column, $label = '')\n * @method Field\\Radio          radio($column, $label = '')\n * @method Field\\Select         select($column, $label = '')\n * @method Field\\MultipleSelect multipleSelect($column, $label = '')\n * @method Field\\Textarea       textarea($column, $label = '')\n * @method Field\\Hidden         hidden($column, $label = '')\n * @method Field\\Id             id($column, $label = '')\n * @method Field\\Ip             ip($column, $label = '')\n * @method Field\\Url            url($column, $label = '')\n * @method Field\\Color          color($column, $label = '')\n * @method Field\\Email          email($column, $label = '')\n * @method Field\\Mobile         mobile($column, $label = '')\n * @method Field\\Slider         slider($column, $label = '')\n * @method Field\\Map            map($latitude, $longitude, $label = '')\n * @method Field\\Editor         editor($column, $label = '')\n * @method Field\\File           file($column, $label = '')\n * @method Field\\Image          image($column, $label = '')\n * @method Field\\Date           date($column, $label = '')\n * @method Field\\Datetime       datetime($column, $label = '')\n * @method Field\\Time           time($column, $label = '')\n * @method Field\\Year           year($column, $label = '')\n * @method Field\\Month          month($column, $label = '')\n * @method Field\\DateRange      dateRange($start, $end, $label = '')\n * @method Field\\DateTimeRange  datetimeRange($start, $end, $label = '')\n * @method Field\\TimeRange      timeRange($start, $end, $label = '')\n * @method Field\\Number         number($column, $label = '')\n * @method Field\\Currency       currency($column, $label = '')\n * @method Field\\HasMany        hasMany($relationName, $callback)\n * @method Field\\SwitchField    switch($column, $label = '')\n * @method Field\\Display        display($column, $label = '')\n * @method Field\\Rate           rate($column, $label = '')\n * @method Field\\Divide         divider()\n * @method Field\\Password       password($column, $label = '')\n * @method Field\\Decimal        decimal($column, $label = '')\n * @method Field\\Html           html($html, $label = '')\n * @method Field\\Tags           tags($column, $label = '')\n * @method Field\\Icon           icon($column, $label = '')\n * @method Field\\Embeds         embeds($column, $label = '')\n */\nclass NestedForm\n{\n    const DEFAULT_KEY_NAME = '__LA_KEY__';\n\n    const REMOVE_FLAG_NAME = '_remove_';\n\n    const REMOVE_FLAG_CLASS = 'fom-removed';\n\n    /**\n     * @var mixed\n     */\n    protected $key;\n\n    /**\n     * @var string\n     */\n    protected $relationName;\n\n    /**\n     * NestedForm key.\n     *\n     * @var Model\n     */\n    protected $model;\n\n    /**\n     * Fields in form.\n     *\n     * @var Collection\n     */\n    protected $fields;\n\n    /**\n     * Original data for this field.\n     *\n     * @var array\n     */\n    protected $original = [];\n\n    /**\n     * @var \\Encore\\Admin\\Form|\\Encore\\Admin\\Widgets\\Form\n     */\n    protected $form;\n\n    /**\n     * Create a new NestedForm instance.\n     *\n     * NestedForm constructor.\n     *\n     * @param string $relation\n     * @param Model  $model\n     */\n    public function __construct($relation, $model = null)\n    {\n        $this->relationName = $relation;\n\n        $this->model = $model;\n\n        $this->fields = new Collection();\n    }\n\n    /**\n     * Get current model.\n     *\n     * @return Model|null\n     */\n    public function model()\n    {\n        return $this->model;\n    }\n\n    /**\n     * Get the value of the model's primary key.\n     *\n     * @return mixed|null\n     */\n    public function getKey()\n    {\n        if ($this->model) {\n            $key = $this->model->getKey();\n        }\n\n        if (!is_null($this->key)) {\n            $key = $this->key;\n        }\n\n        if (isset($key)) {\n            return $key;\n        }\n\n        return 'new_'.static::DEFAULT_KEY_NAME;\n    }\n\n    /**\n     * Set key for current form.\n     *\n     * @param mixed $key\n     *\n     * @return $this\n     */\n    public function setKey($key)\n    {\n        $this->key = $key;\n\n        return $this;\n    }\n\n    /**\n     * Set Form.\n     *\n     * @param Form $form\n     *\n     * @return $this\n     */\n    public function setForm(Form $form = null)\n    {\n        $this->form = $form;\n\n        return $this;\n    }\n\n    /**\n     * Set Widget/Form.\n     *\n     * @param WidgetForm $form\n     *\n     * @return $this\n     */\n    public function setWidgetForm(WidgetForm $form = null)\n    {\n        $this->form = $form;\n\n        return $this;\n    }\n\n    /**\n     * Get form.\n     *\n     * @return Form\n     */\n    public function getForm()\n    {\n        return $this->form;\n    }\n\n    /**\n     * Set original values for fields.\n     *\n     * @param array  $data\n     * @param string $relatedKeyName\n     *\n     * @return $this\n     */\n    public function setOriginal($data, $relatedKeyName = null)\n    {\n        if (empty($data)) {\n            return $this;\n        }\n\n        foreach ($data as $key => $value) {\n            /*\n             * like $this->original[30] = [ id = 30, .....]\n             */\n            if ($relatedKeyName) {\n                $key = $value[$relatedKeyName];\n            }\n\n            $this->original[$key] = $value;\n        }\n\n        return $this;\n    }\n\n    /**\n     * Prepare for insert or update.\n     *\n     * @param array $input\n     *\n     * @return mixed\n     */\n    public function prepare($input)\n    {\n        foreach ($input as $key => $record) {\n            $this->setFieldOriginalValue($key);\n            $input[$key] = $this->prepareRecord($record);\n        }\n\n        return $input;\n    }\n\n    /**\n     * Set original data for each field.\n     *\n     * @param string $key\n     *\n     * @return void\n     */\n    protected function setFieldOriginalValue($key)\n    {\n        $values = [];\n        if (array_key_exists($key, $this->original)) {\n            $values = $this->original[$key];\n        }\n\n        $this->fields->each(function (Field $field) use ($values) {\n            $field->setOriginal($values);\n        });\n    }\n\n    /**\n     * Do prepare work before store and update.\n     *\n     * @param array $record\n     *\n     * @return array\n     */\n    protected function prepareRecord($record)\n    {\n        if ($record[static::REMOVE_FLAG_NAME] == 1) {\n            return $record;\n        }\n\n        $prepared = [];\n\n        /* @var Field $field */\n        foreach ($this->fields as $field) {\n            $columns = $field->column();\n\n            $value = $this->fetchColumnValue($record, $columns);\n\n            if (is_null($value)) {\n                continue;\n            }\n\n            if (method_exists($field, 'prepare')) {\n                $value = $field->prepare($value);\n            }\n\n            if (($field instanceof \\Encore\\Admin\\Form\\Field\\Hidden) || $value != $field->original()) {\n                if (is_array($columns)) {\n                    foreach ($columns as $name => $column) {\n                        Arr::set($prepared, $column, $value[$name]);\n                    }\n                } elseif (is_string($columns)) {\n                    Arr::set($prepared, $columns, $value);\n                }\n            }\n        }\n\n        $prepared[static::REMOVE_FLAG_NAME] = $record[static::REMOVE_FLAG_NAME];\n\n        return $prepared;\n    }\n\n    /**\n     * Fetch value in input data by column name.\n     *\n     * @param array        $data\n     * @param string|array $columns\n     *\n     * @return array|mixed\n     */\n    protected function fetchColumnValue($data, $columns)\n    {\n        if (is_string($columns)) {\n            return Arr::get($data, $columns);\n        }\n\n        if (is_array($columns)) {\n            $value = [];\n            foreach ($columns as $name => $column) {\n                if (!Arr::has($data, $column)) {\n                    continue;\n                }\n                $value[$name] = Arr::get($data, $column);\n            }\n\n            return $value;\n        }\n    }\n\n    /**\n     * @param Field $field\n     *\n     * @return $this\n     */\n    public function pushField(Field $field)\n    {\n        $this->fields->push($field);\n\n        return $this;\n    }\n\n    /**\n     * Get fields of this form.\n     *\n     * @return Collection\n     */\n    public function fields()\n    {\n        return $this->fields;\n    }\n\n    /**\n     * Fill data to all fields in form.\n     *\n     * @param array $data\n     *\n     * @return $this\n     */\n    public function fill(array $data)\n    {\n        /* @var Field $field */\n        foreach ($this->fields() as $field) {\n            $field->fill($data);\n        }\n\n        return $this;\n    }\n\n    /**\n     * Get the html and script of template.\n     *\n     * @return array\n     */\n    public function getTemplateHtmlAndScript()\n    {\n        $html = '';\n        $scripts = [];\n\n        /* @var Field $field */\n        foreach ($this->fields() as $field) {\n\n            //when field render, will push $script to Admin\n            $html .= $field->render();\n\n            /*\n             * Get and remove the last script of Admin::$script stack.\n             */\n            if ($field->getScript()) {\n                $scripts[] = array_pop(Admin::$script);\n            }\n        }\n\n        return [$html, implode(\"\\r\\n\", $scripts)];\n    }\n\n    /**\n     * Set `errorKey` `elementName` `elementClass` for fields inside hasmany fields.\n     *\n     * @param Field $field\n     *\n     * @return Field\n     */\n    protected function formatField(Field $field)\n    {\n        $column = $field->column();\n\n        $elementName = $elementClass = $errorKey = [];\n\n        $key = $this->getKey();\n\n        if (is_array($column)) {\n            foreach ($column as $k => $name) {\n                $errorKey[$k] = sprintf('%s.%s.%s', $this->relationName, $key, $name);\n                $elementName[$k] = sprintf('%s[%s][%s]', $this->relationName, $key, $name);\n                $elementClass[$k] = [$this->relationName, $name];\n            }\n        } else {\n            $errorKey = sprintf('%s.%s.%s', $this->relationName, $key, $column);\n            $elementName = sprintf('%s[%s][%s]', $this->relationName, $key, $column);\n            $elementClass = [$this->relationName, $column];\n        }\n\n        return $field->setErrorKey($errorKey)\n            ->setElementName($elementName)\n            ->setElementClass($elementClass);\n    }\n\n    /**\n     * Add nested-form fields dynamically.\n     *\n     * @param string $method\n     * @param array  $arguments\n     *\n     * @return mixed\n     */\n    public function __call($method, $arguments)\n    {\n        if ($className = Form::findFieldClass($method)) {\n            $column = Arr::get($arguments, 0, '');\n\n            /* @var Field $field */\n            $field = new $className($column, array_slice($arguments, 1));\n\n            if ($this->form instanceof WidgetForm) {\n                $field->setWidgetForm($this->form);\n            } else {\n                $field->setForm($this->form);\n            }\n\n            $field = $this->formatField($field);\n\n            $this->pushField($field);\n\n            return $field;\n        }\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Form/Row.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form;\n\nuse Encore\\Admin\\Form;\nuse Illuminate\\Contracts\\Support\\Renderable;\n\nclass Row implements Renderable\n{\n    /**\n     * Callback for add field to current row.s.\n     *\n     * @var \\Closure\n     */\n    protected $callback;\n\n    /**\n     * Parent form.\n     *\n     * @var Form\n     */\n    protected $form;\n\n    /**\n     * Fields in this row.\n     *\n     * @var array\n     */\n    protected $fields = [];\n\n    /**\n     * Default field width for appended field.\n     *\n     * @var int\n     */\n    protected $defaultFieldWidth = 12;\n\n    /**\n     * Row constructor.\n     *\n     * @param \\Closure $callback\n     * @param Form     $form\n     */\n    public function __construct(\\Closure $callback, Form $form)\n    {\n        $this->callback = $callback;\n\n        $this->form = $form;\n\n        call_user_func($this->callback, $this);\n    }\n\n    /**\n     * Get fields of this row.\n     *\n     * @return array\n     */\n    public function getFields()\n    {\n        return $this->fields;\n    }\n\n    /**\n     * Set width for a incomming field.\n     *\n     * @param int $width\n     *\n     * @return $this\n     */\n    public function width($width = 12)\n    {\n        $this->defaultFieldWidth = $width;\n\n        return $this;\n    }\n\n    /**\n     * Render the row.\n     *\n     * @return \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View\n     */\n    public function render()\n    {\n        return view('admin::form.row', ['fields' => $this->fields]);\n    }\n\n    /**\n     * Add field.\n     *\n     * @param string $method\n     * @param array  $arguments\n     *\n     * @return Field|void\n     */\n    public function __call($method, $arguments)\n    {\n        $field = $this->form->__call($method, $arguments);\n\n        $field->disableHorizontal();\n\n        $this->fields[] = [\n            'width'   => $this->defaultFieldWidth,\n            'element' => $field,\n        ];\n\n        return $field;\n    }\n}\n"
  },
  {
    "path": "src/Form/Tab.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form;\n\nuse Encore\\Admin\\Form;\nuse Illuminate\\Support\\Collection;\n\nclass Tab\n{\n    /**\n     * @var Form\n     */\n    protected $form;\n\n    /**\n     * @var Collection\n     */\n    protected $tabs;\n\n    /**\n     * @var int\n     */\n    protected $offset = 0;\n\n    /**\n     * Tab constructor.\n     *\n     * @param Form $form\n     */\n    public function __construct(Form $form)\n    {\n        $this->form = $form;\n\n        $this->tabs = new Collection();\n    }\n\n    /**\n     * Append a tab section.\n     *\n     * @param string   $title\n     * @param \\Closure $content\n     * @param bool     $active\n     *\n     * @return $this\n     */\n    public function append($title, \\Closure $content, $active = false)\n    {\n        $fields = $this->collectFields($content);\n\n        $id = 'form-'.($this->tabs->count() + 1);\n\n        $this->tabs->push(compact('id', 'title', 'fields', 'active'));\n\n        return $this;\n    }\n\n    /**\n     * Collect fields under current tab.\n     *\n     * @param \\Closure $content\n     *\n     * @return Collection\n     */\n    protected function collectFields(\\Closure $content)\n    {\n        call_user_func($content, $this->form);\n\n        $fields = clone $this->form->fields();\n\n        $all = $fields->toArray();\n\n        foreach ($this->form->rows as $row) {\n            $rowFields = array_map(function ($field) {\n                return $field['element'];\n            }, $row->getFields());\n\n            $match = false;\n\n            foreach ($rowFields as $field) {\n                if (($index = array_search($field, $all)) !== false) {\n                    if (!$match) {\n                        $fields->put($index, $row);\n                    } else {\n                        $fields->pull($index);\n                    }\n\n                    $match = true;\n                }\n            }\n        }\n\n        $fields = $fields->slice($this->offset);\n\n        $this->offset += $fields->count();\n\n        return $fields;\n    }\n\n    /**\n     * Get all tabs.\n     *\n     * @return Collection\n     */\n    public function getTabs()\n    {\n        // If there is no active tab, then active the first.\n        if ($this->tabs->filter(function ($tab) {\n            return $tab['active'];\n        })->isEmpty()) {\n            $first = $this->tabs->first();\n            $first['active'] = true;\n\n            $this->tabs->offsetSet(0, $first);\n        }\n\n        return $this->tabs;\n    }\n\n    /**\n     * @return bool\n     */\n    public function isEmpty()\n    {\n        return $this->tabs->isEmpty();\n    }\n}\n"
  },
  {
    "path": "src/Form/Tools.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Form;\n\nuse Encore\\Admin\\Facades\\Admin;\nuse Illuminate\\Contracts\\Support\\Htmlable;\nuse Illuminate\\Contracts\\Support\\Renderable;\nuse Illuminate\\Support\\Collection;\n\nclass Tools implements Renderable\n{\n    /**\n     * @var Builder\n     */\n    protected $form;\n\n    /**\n     * Collection of tools.\n     *\n     * @var array\n     */\n    protected $tools = ['delete', 'view', 'list'];\n\n    /**\n     * Tools should be appends to default tools.\n     *\n     * @var Collection\n     */\n    protected $appends;\n\n    /**\n     * Tools should be prepends to default tools.\n     *\n     * @var Collection\n     */\n    protected $prepends;\n\n    /**\n     * Create a new Tools instance.\n     *\n     * @param Builder $builder\n     */\n    public function __construct(Builder $builder)\n    {\n        $this->form = $builder;\n        $this->appends = new Collection();\n        $this->prepends = new Collection();\n    }\n\n    /**\n     * Append a tools.\n     *\n     * @param mixed $tool\n     *\n     * @return $this\n     */\n    public function append($tool)\n    {\n        $this->appends->push($tool);\n\n        return $this;\n    }\n\n    /**\n     * Prepend a tool.\n     *\n     * @param mixed $tool\n     *\n     * @return $this\n     */\n    public function prepend($tool)\n    {\n        $this->prepends->push($tool);\n\n        return $this;\n    }\n\n    /**\n     * Disable `list` tool.\n     *\n     * @return $this\n     */\n    public function disableList(bool $disable = true)\n    {\n        if ($disable) {\n            array_delete($this->tools, 'list');\n        } elseif (!in_array('list', $this->tools)) {\n            array_push($this->tools, 'list');\n        }\n\n        return $this;\n    }\n\n    /**\n     * Disable `delete` tool.\n     *\n     * @return $this\n     */\n    public function disableDelete(bool $disable = true)\n    {\n        if ($disable) {\n            array_delete($this->tools, 'delete');\n        } elseif (!in_array('delete', $this->tools)) {\n            array_push($this->tools, 'delete');\n        }\n\n        return $this;\n    }\n\n    /**\n     * Disable `edit` tool.\n     *\n     * @return $this\n     */\n    public function disableView(bool $disable = true)\n    {\n        if ($disable) {\n            array_delete($this->tools, 'view');\n        } elseif (!in_array('view', $this->tools)) {\n            array_push($this->tools, 'view');\n        }\n\n        return $this;\n    }\n\n    /**\n     * Get request path for resource list.\n     *\n     * @return string\n     */\n    protected function getListPath()\n    {\n        return $this->form->getResource();\n    }\n\n    /**\n     * Get request path for edit.\n     *\n     * @return string\n     */\n    protected function getDeletePath()\n    {\n        return $this->getViewPath();\n    }\n\n    /**\n     * Get request path for delete.\n     *\n     * @return string\n     */\n    protected function getViewPath()\n    {\n        $key = $this->form->getResourceId();\n\n        if ($key) {\n            return $this->getListPath().'/'.$key;\n        } else {\n            return $this->getListPath();\n        }\n    }\n\n    /**\n     * Get parent form of tool.\n     *\n     * @return Builder\n     */\n    public function form()\n    {\n        return $this->form;\n    }\n\n    /**\n     * Render list button.\n     *\n     * @return string\n     */\n    protected function renderList()\n    {\n        $text = trans('admin.list');\n\n        return <<<EOT\n<div class=\"btn-group pull-right\" style=\"margin-right: 5px\">\n    <a href=\"{$this->getListPath()}\" class=\"btn btn-sm btn-default\" title=\"$text\"><i class=\"fa fa-list\"></i><span class=\"hidden-xs\">&nbsp;$text</span></a>\n</div>\nEOT;\n    }\n\n    /**\n     * Render list button.\n     *\n     * @return string\n     */\n    protected function renderView()\n    {\n        $view = trans('admin.view');\n\n        return <<<HTML\n<div class=\"btn-group pull-right\" style=\"margin-right: 5px\">\n    <a href=\"{$this->getViewPath()}\" class=\"btn btn-sm btn-primary\" title=\"{$view}\">\n        <i class=\"fa fa-eye\"></i><span class=\"hidden-xs\"> {$view}</span>\n    </a>\n</div>\nHTML;\n    }\n\n    /**\n     * Render `delete` tool.\n     *\n     * @return string\n     */\n    protected function renderDelete()\n    {\n        $trans = [\n            'delete_confirm' => trans('admin.delete_confirm'),\n            'confirm'        => trans('admin.confirm'),\n            'cancel'         => trans('admin.cancel'),\n            'delete'         => trans('admin.delete'),\n        ];\n\n        $class = uniqid();\n\n        $script = <<<SCRIPT\n\n$('.{$class}-delete').unbind('click').click(function() {\n\n    swal({\n        title: \"{$trans['delete_confirm']}\",\n        type: \"warning\",\n        showCancelButton: true,\n        confirmButtonColor: \"#DD6B55\",\n        confirmButtonText: \"{$trans['confirm']}\",\n        showLoaderOnConfirm: true,\n        cancelButtonText: \"{$trans['cancel']}\",\n        preConfirm: function() {\n            return new Promise(function(resolve) {\n                $.ajax({\n                    method: 'post',\n                    url: '{$this->getDeletePath()}',\n                    data: {\n                        _method:'delete',\n                        _token:LA.token,\n                    },\n                    success: function (data) {\n                        $.pjax({container:'#pjax-container', url: '{$this->getListPath()}' });\n\n                        resolve(data);\n                    }\n                });\n            });\n        }\n    }).then(function(result) {\n        var data = result.value;\n        if (typeof data === 'object') {\n            if (data.status) {\n                swal(data.message, '', 'success');\n            } else {\n                swal(data.message, '', 'error');\n            }\n        }\n    });\n});\n\nSCRIPT;\n\n        Admin::script($script);\n\n        return <<<HTML\n<div class=\"btn-group pull-right\" style=\"margin-right: 5px\">\n    <a href=\"javascript:void(0);\" class=\"btn btn-sm btn-danger {$class}-delete\" title=\"{$trans['delete']}\">\n        <i class=\"fa fa-trash\"></i><span class=\"hidden-xs\">  {$trans['delete']}</span>\n    </a>\n</div>\nHTML;\n    }\n\n    /**\n     * Add a tool.\n     *\n     * @param string $tool\n     *\n     * @return $this\n     *\n     * @deprecated use append instead.\n     */\n    public function add($tool)\n    {\n        return $this->append($tool);\n    }\n\n    /**\n     * Disable back button.\n     *\n     * @return $this\n     *\n     * @deprecated\n     */\n    public function disableBackButton()\n    {\n    }\n\n    /**\n     * Disable list button.\n     *\n     * @return $this\n     *\n     * @deprecated Use disableList instead.\n     */\n    public function disableListButton()\n    {\n        return $this->disableList();\n    }\n\n    /**\n     * Render custom tools.\n     *\n     * @param Collection $tools\n     *\n     * @return mixed\n     */\n    protected function renderCustomTools($tools)\n    {\n        if ($this->form->isCreating()) {\n            $this->disableView();\n            $this->disableDelete();\n        }\n\n        if (empty($tools)) {\n            return '';\n        }\n\n        return $tools->map(function ($tool) {\n            if ($tool instanceof Renderable) {\n                return $tool->render();\n            }\n\n            if ($tool instanceof Htmlable) {\n                return $tool->toHtml();\n            }\n\n            return (string) $tool;\n        })->implode(' ');\n    }\n\n    /**\n     * Render tools.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        $output = $this->renderCustomTools($this->prepends);\n\n        foreach ($this->tools as $tool) {\n            $renderMethod = 'render'.ucfirst($tool);\n            $output .= $this->$renderMethod();\n        }\n\n        return $output.$this->renderCustomTools($this->appends);\n    }\n}\n"
  },
  {
    "path": "src/Form.php",
    "content": "<?php\n\nnamespace Encore\\Admin;\n\nuse Closure;\nuse Encore\\Admin\\Exception\\Handler;\nuse Encore\\Admin\\Form\\Builder;\nuse Encore\\Admin\\Form\\Concerns\\HandleCascadeFields;\nuse Encore\\Admin\\Form\\Concerns\\HasFields;\nuse Encore\\Admin\\Form\\Concerns\\HasHooks;\nuse Encore\\Admin\\Form\\Field;\nuse Encore\\Admin\\Form\\Layout\\Layout;\nuse Encore\\Admin\\Form\\Row;\nuse Encore\\Admin\\Form\\Tab;\nuse Encore\\Admin\\Traits\\ShouldSnakeAttributes;\nuse Illuminate\\Contracts\\Support\\Arrayable;\nuse Illuminate\\Contracts\\Support\\Renderable;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Relations;\nuse Illuminate\\Database\\Eloquent\\SoftDeletes;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Facades\\DB;\nuse Illuminate\\Support\\MessageBag;\nuse Illuminate\\Support\\Str;\nuse Illuminate\\Validation\\Validator;\nuse Spatie\\EloquentSortable\\Sortable;\nuse Symfony\\Component\\HttpFoundation\\Response;\n\n/**\n * Class Form.\n */\nclass Form implements Renderable\n{\n    use HasHooks;\n    use HasFields;\n    use HandleCascadeFields;\n    use ShouldSnakeAttributes;\n    /**\n     * Remove flag in `has many` form.\n     */\n    const REMOVE_FLAG_NAME = '_remove_';\n\n    /**\n     * Eloquent model of the form.\n     *\n     * @var Model\n     */\n    protected $model;\n\n    /**\n     * @var \\Illuminate\\Validation\\Validator\n     */\n    protected $validator;\n\n    /**\n     * @var Builder\n     */\n    protected $builder;\n\n    /**\n     * Data for save to current model from input.\n     *\n     * @var array\n     */\n    protected $updates = [];\n\n    /**\n     * Data for save to model's relations from input.\n     *\n     * @var array\n     */\n    protected $relations = [];\n\n    /**\n     * Input data.\n     *\n     * @var array\n     */\n    protected $inputs = [];\n\n    /**\n     * @var Layout\n     */\n    protected $layout;\n\n    /**\n     * Ignored saving fields.\n     *\n     * @var array\n     */\n    protected $ignored = [];\n\n    /**\n     * Collected field assets.\n     *\n     * @var array\n     */\n    protected static $collectedAssets = [];\n\n    /**\n     * @var Form\\Tab\n     */\n    protected $tab = null;\n\n    /**\n     * Field rows in form.\n     *\n     * @var array\n     */\n    public $rows = [];\n\n    /**\n     * @var bool\n     */\n    protected $isSoftDeletes = false;\n\n    /**\n     * Create a new form instance.\n     *\n     * @param $model\n     * @param \\Closure $callback\n     */\n    public function __construct($model, Closure $callback = null)\n    {\n        $this->model = $model;\n\n        $this->builder = new Builder($this);\n\n        $this->initLayout();\n\n        if ($callback instanceof Closure) {\n            $callback($this);\n        }\n\n        $this->isSoftDeletes = in_array(SoftDeletes::class, class_uses_deep($this->model), true);\n\n        $this->callInitCallbacks();\n    }\n\n    /**\n     * @param Field $field\n     *\n     * @return $this\n     */\n    public function pushField(Field $field): self\n    {\n        $field->setForm($this);\n\n        $width = $this->builder->getWidth();\n        $field->setWidth($width['field'], $width['label']);\n\n        $this->fields()->push($field);\n        $this->layout->addField($field);\n\n        return $this;\n    }\n\n    /**\n     * @return Model\n     */\n    public function model(): Model\n    {\n        return $this->model;\n    }\n\n    /**\n     * @return Builder\n     */\n    public function builder(): Builder\n    {\n        return $this->builder;\n    }\n\n    /**\n     * @return \\Illuminate\\Support\\Collection\n     */\n    public function fields()\n    {\n        return $this->builder()->fields();\n    }\n\n    /**\n     * Generate a edit form.\n     *\n     * @param $id\n     *\n     * @return $this\n     */\n    public function edit($id): self\n    {\n        $this->builder->setMode(Builder::MODE_EDIT);\n        $this->builder->setResourceId($id);\n\n        $this->setRelationFieldSnakeAttributes();\n\n        $this->setFieldValue($id);\n\n        return $this;\n    }\n\n    /**\n     * Use tab to split form.\n     *\n     * @param string  $title\n     * @param Closure $content\n     * @param bool    $active\n     *\n     * @return $this\n     */\n    public function tab($title, Closure $content, bool $active = false): self\n    {\n        $this->setTab()->append($title, $content, $active);\n\n        return $this;\n    }\n\n    /**\n     * Get Tab instance.\n     *\n     * @return Tab\n     */\n    public function getTab()\n    {\n        return $this->tab;\n    }\n\n    /**\n     * Set Tab instance.\n     *\n     * @return Tab\n     */\n    public function setTab(): Tab\n    {\n        if ($this->tab === null) {\n            $this->tab = new Tab($this);\n        }\n\n        return $this->tab;\n    }\n\n    /**\n     * Destroy data entity and remove files.\n     *\n     * @param $id\n     *\n     * @return mixed\n     */\n    public function destroy($id)\n    {\n        try {\n            if (($ret = $this->callDeleting($id)) instanceof Response) {\n                return $ret;\n            }\n\n            collect(explode(',', $id))->filter()->each(function ($id) {\n                $builder = $this->model()->newQuery();\n\n                if ($this->isSoftDeletes) {\n                    $builder = $builder->withTrashed();\n                }\n\n                $model = $builder->with($this->getRelations())->findOrFail($id);\n\n                if ($this->isSoftDeletes && $model->trashed()) {\n                    $this->deleteFiles($model, true);\n                    $model->forceDelete();\n\n                    return;\n                }\n\n                $this->deleteFiles($model);\n                $model->delete();\n            });\n\n            if (($ret = $this->callDeleted()) instanceof Response) {\n                return $ret;\n            }\n\n            $response = [\n                'status'  => true,\n                'message' => trans('admin.delete_succeeded'),\n            ];\n        } catch (\\Exception $exception) {\n            $response = [\n                'status'  => false,\n                'message' => $exception->getMessage() ?: trans('admin.delete_failed'),\n            ];\n        }\n\n        return response()->json($response);\n    }\n\n    /**\n     * Remove files in record.\n     *\n     * @param Model $model\n     * @param bool  $forceDelete\n     */\n    protected function deleteFiles(Model $model, $forceDelete = false)\n    {\n        // If it's a soft delete, the files in the data will not be deleted.\n        if (!$forceDelete && $this->isSoftDeletes) {\n            return;\n        }\n\n        $data = $model->toArray();\n\n        $this->fields()->filter(function ($field) {\n            return $field instanceof Field\\File;\n        })->each(function (Field\\File $file) use ($data) {\n            $file->setOriginal($data);\n\n            $file->destroy();\n        });\n    }\n\n    /**\n     * Store a new record.\n     *\n     * @return \\Illuminate\\Http\\RedirectResponse|\\Illuminate\\Routing\\Redirector|\\Illuminate\\Http\\JsonResponse\n     */\n    public function store()\n    {\n        $data = \\request()->all();\n\n        // Handle validation errors.\n        if ($validationMessages = $this->validationMessages($data)) {\n            return $this->responseValidationError($validationMessages);\n        }\n\n        if (($response = $this->prepare($data)) instanceof Response) {\n            return $response;\n        }\n\n        DB::transaction(function () {\n            $inserts = $this->prepareInsert($this->updates);\n\n            foreach ($inserts as $column => $value) {\n                $this->model->setAttribute($column, $value);\n            }\n\n            $this->model->save();\n\n            $this->updateRelation($this->relations);\n        });\n\n        if (($response = $this->callSaved()) instanceof Response) {\n            return $response;\n        }\n\n        if ($response = $this->ajaxResponse(trans('admin.save_succeeded'))) {\n            return $response;\n        }\n\n        return $this->redirectAfterStore();\n    }\n\n    /**\n     * @param MessageBag $message\n     *\n     * @return $this|\\Illuminate\\Http\\JsonResponse\n     */\n    protected function responseValidationError(MessageBag $message)\n    {\n        if (\\request()->ajax() && !\\request()->pjax()) {\n            return response()->json([\n                'status'     => false,\n                'validation' => $message,\n                'message'    => $message->first(),\n            ]);\n        }\n\n        return back()->withInput()->withErrors($message);\n    }\n\n    /**\n     * Get ajax response.\n     *\n     * @param string $message\n     *\n     * @return bool|\\Illuminate\\Http\\JsonResponse\n     */\n    protected function ajaxResponse($message)\n    {\n        $request = \\request();\n\n        // ajax but not pjax\n        if ($request->ajax() && !$request->pjax()) {\n            return response()->json([\n                'status'    => true,\n                'message'   => $message,\n                'display'   => $this->applayFieldDisplay(),\n            ]);\n        }\n\n        return false;\n    }\n\n    /**\n     * @return array\n     */\n    protected function applayFieldDisplay()\n    {\n        $editable = [];\n\n        /** @var Field $field */\n        foreach ($this->fields() as $field) {\n            if (!\\request()->has($field->column())) {\n                continue;\n            }\n\n            $newValue = $this->model->fresh()->getAttribute($field->column());\n\n            if ($newValue instanceof Arrayable) {\n                $newValue = $newValue->toArray();\n            }\n\n            if ($field instanceof Field\\BelongsTo || $field instanceof Field\\BelongsToMany) {\n                $selectable = $field->getSelectable();\n\n                if (method_exists($selectable, 'display')) {\n                    $display = $selectable::display();\n\n                    $editable[$field->column()] = $display->call($this->model, $newValue);\n                }\n            }\n        }\n\n        return $editable;\n    }\n\n    /**\n     * Prepare input data for insert or update.\n     *\n     * @param array $data\n     *\n     * @return mixed\n     */\n    protected function prepare($data = [])\n    {\n        if (($response = $this->callSubmitted()) instanceof Response) {\n            return $response;\n        }\n\n        $this->inputs = array_merge($this->removeIgnoredFields($data), $this->inputs);\n\n        if (($response = $this->callSaving()) instanceof Response) {\n            return $response;\n        }\n\n        $this->relations = $this->getRelationInputs($this->inputs);\n\n        $this->updates = Arr::except($this->inputs, array_keys($this->relations));\n    }\n\n    /**\n     * Remove ignored fields from input.\n     *\n     * @param array $input\n     *\n     * @return array\n     */\n    protected function removeIgnoredFields($input): array\n    {\n        Arr::forget($input, $this->ignored);\n\n        return $input;\n    }\n\n    /**\n     * Get inputs for relations.\n     *\n     * @param array $inputs\n     *\n     * @return array\n     */\n    protected function getRelationInputs($inputs = []): array\n    {\n        $relations = [];\n\n        foreach ($inputs as $column => $value) {\n            if ((method_exists($this->model, $column) ||\n                method_exists($this->model, $column = Str::camel($column))) &&\n                !method_exists(Model::class, $column)\n            ) {\n                $relation = call_user_func([$this->model, $column]);\n\n                if ($relation instanceof Relations\\Relation) {\n                    $relations[$column] = $value;\n                }\n            }\n        }\n\n        return $relations;\n    }\n\n    /**\n     * Handle update.\n     *\n     * @param int  $id\n     * @param null $data\n     *\n     * @return bool|\\Illuminate\\Contracts\\Routing\\ResponseFactory|\\Illuminate\\Http\\JsonResponse|\\Illuminate\\Http\\RedirectResponse|\\Illuminate\\Http\\Response|mixed|null|Response\n     */\n    public function update($id, $data = null)\n    {\n        $data = ($data) ?: request()->all();\n\n        $isEditable = $this->isEditable($data);\n\n        if (($data = $this->handleColumnUpdates($id, $data)) instanceof Response) {\n            return $data;\n        }\n\n        /* @var Model $this ->model */\n        $builder = $this->model();\n\n        if ($this->isSoftDeletes) {\n            $builder = $builder->withTrashed();\n        }\n\n        $this->model = $builder->with($this->getRelations())->findOrFail($id);\n\n        $this->setFieldOriginalValue();\n\n        // Handle validation errors.\n        if ($validationMessages = $this->validationMessages($data)) {\n            if (!$isEditable) {\n                return back()->withInput()->withErrors($validationMessages);\n            }\n\n            return response()->json(['errors' => Arr::dot($validationMessages->getMessages())], 422);\n        }\n\n        if (($response = $this->prepare($data)) instanceof Response) {\n            return $response;\n        }\n\n        DB::transaction(function () {\n            $updates = $this->prepareUpdate($this->updates);\n\n            foreach ($updates as $column => $value) {\n                /* @var Model $this ->model */\n                $this->model->setAttribute($column, $value);\n            }\n\n            $this->model->save();\n\n            $this->updateRelation($this->relations);\n        });\n\n        if (($result = $this->callSaved()) instanceof Response) {\n            return $result;\n        }\n\n        if ($response = $this->ajaxResponse(trans('admin.update_succeeded'))) {\n            return $response;\n        }\n\n        return $this->redirectAfterUpdate($id);\n    }\n\n    /**\n     * Get RedirectResponse after store.\n     *\n     * @return \\Illuminate\\Http\\RedirectResponse\n     */\n    protected function redirectAfterStore()\n    {\n        $resourcesPath = $this->resource(0);\n\n        $key = $this->model->getKey();\n\n        return $this->redirectAfterSaving($resourcesPath, $key);\n    }\n\n    /**\n     * Get RedirectResponse after update.\n     *\n     * @param mixed $key\n     *\n     * @return \\Illuminate\\Http\\RedirectResponse\n     */\n    protected function redirectAfterUpdate($key)\n    {\n        $resourcesPath = $this->resource(-1);\n\n        return $this->redirectAfterSaving($resourcesPath, $key);\n    }\n\n    /**\n     * Get RedirectResponse after data saving.\n     *\n     * @param string $resourcesPath\n     * @param string $key\n     *\n     * @return \\Illuminate\\Http\\RedirectResponse|\\Illuminate\\Routing\\Redirector\n     */\n    protected function redirectAfterSaving($resourcesPath, $key)\n    {\n        if (request('after-save') == 1) {\n            // continue editing\n            $url = rtrim($resourcesPath, '/').\"/{$key}/edit\";\n        } elseif (request('after-save') == 2) {\n            // continue creating\n            $url = rtrim($resourcesPath, '/').'/create';\n        } elseif (request('after-save') == 3) {\n            // view resource\n            $url = rtrim($resourcesPath, '/').\"/{$key}\";\n        } else {\n            $url = request(Builder::PREVIOUS_URL_KEY) ?: $resourcesPath;\n        }\n\n        admin_toastr(trans('admin.save_succeeded'));\n\n        return redirect($url);\n    }\n\n    /**\n     * Check if request is from editable.\n     *\n     * @param array $input\n     *\n     * @return bool\n     */\n    protected function isEditable(array $input = []): bool\n    {\n        return array_key_exists('_editable', $input) || array_key_exists('_edit_inline', $input);\n    }\n\n    /**\n     * Handle updates for single column.\n     *\n     * @param int   $id\n     * @param array $data\n     *\n     * @return array|\\Illuminate\\Contracts\\Routing\\ResponseFactory|\\Illuminate\\Http\\Response|Response\n     */\n    protected function handleColumnUpdates($id, $data)\n    {\n        $data = $this->handleEditable($data);\n\n        $data = $this->handleFileDelete($data);\n\n        $data = $this->handleFileSort($data);\n\n        if ($this->handleOrderable($id, $data)) {\n            return response([\n                'status'  => true,\n                'message' => trans('admin.update_succeeded'),\n            ]);\n        }\n\n        return $data;\n    }\n\n    /**\n     * Handle editable update.\n     *\n     * @param array $input\n     *\n     * @return array\n     */\n    protected function handleEditable(array $input = []): array\n    {\n        if (array_key_exists('_editable', $input)) {\n            $name = $input['name'];\n            $value = $input['value'];\n\n            Arr::forget($input, ['pk', 'value', 'name']);\n            Arr::set($input, $name, $value);\n        }\n\n        return $input;\n    }\n\n    /**\n     * @param array $input\n     *\n     * @return array\n     */\n    protected function handleFileDelete(array $input = []): array\n    {\n        if (array_key_exists(Field::FILE_DELETE_FLAG, $input)) {\n            $input[Field::FILE_DELETE_FLAG] = $input['key'];\n            unset($input['key']);\n        }\n\n        request()->replace($input);\n\n        return $input;\n    }\n\n    /**\n     * @param array $input\n     *\n     * @return array\n     */\n    protected function handleFileSort(array $input = []): array\n    {\n        if (!array_key_exists(Field::FILE_SORT_FLAG, $input)) {\n            return $input;\n        }\n\n        $sorts = array_filter($input[Field::FILE_SORT_FLAG]);\n\n        if (empty($sorts)) {\n            return $input;\n        }\n\n        foreach ($sorts as $column => $order) {\n            $input[$column] = $order;\n        }\n\n        request()->replace($input);\n\n        return $input;\n    }\n\n    /**\n     * Handle orderable update.\n     *\n     * @param int   $id\n     * @param array $input\n     *\n     * @return bool\n     */\n    protected function handleOrderable($id, array $input = [])\n    {\n        if (array_key_exists('_orderable', $input)) {\n            $model = $this->model->find($id);\n\n            if ($model instanceof Sortable) {\n                $input['_orderable'] == 1 ? $model->moveOrderUp() : $model->moveOrderDown();\n\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Update relation data.\n     *\n     * @param array $relationsData\n     *\n     * @return void\n     */\n    protected function updateRelation($relationsData)\n    {\n        foreach ($relationsData as $name => $values) {\n            if (!method_exists($this->model, $name)) {\n                continue;\n            }\n\n            $relation = $this->model->$name();\n\n            $oneToOneRelation = $relation instanceof Relations\\HasOne\n                || $relation instanceof Relations\\MorphOne\n                || $relation instanceof Relations\\BelongsTo;\n\n            $prepared = $this->prepareUpdate([$name => $values], $oneToOneRelation);\n\n            if (empty($prepared)) {\n                continue;\n            }\n\n            switch (true) {\n                case $relation instanceof Relations\\BelongsToMany:\n                case $relation instanceof Relations\\MorphToMany:\n                    if (isset($prepared[$name])) {\n                        $relation->sync($prepared[$name]);\n                    }\n                    break;\n                case $relation instanceof Relations\\HasOne:\n                case $relation instanceof Relations\\MorphOne:\n                    $related = $this->model->getRelationValue($name) ?: $relation->getRelated();\n\n                    foreach ($prepared[$name] as $column => $value) {\n                        $related->setAttribute($column, $value);\n                    }\n\n                    // save child\n                    $relation->save($related);\n                    break;\n                case $relation instanceof Relations\\BelongsTo:\n                case $relation instanceof Relations\\MorphTo:\n                    $related = $this->model->getRelationValue($name) ?: $relation->getRelated();\n\n                    foreach ($prepared[$name] as $column => $value) {\n                        $related->setAttribute($column, $value);\n                    }\n\n                    // save parent\n                    $related->save();\n\n                    // save child (self)\n                    $relation->associate($related)->save();\n                    break;\n                case $relation instanceof Relations\\HasMany:\n                case $relation instanceof Relations\\MorphMany:\n                    /** @var Relations\\HasOneOrMany $relation */\n                    $relation = $this->model->$name();\n\n                    $data = $prepared[$name];\n                    $first = Arr::first($data);\n\n                    if (is_array($first)) { //relation updated via HasMany field\n                        foreach ($data as $related) {\n                            /** @var Relations\\HasOneOrMany $relation */\n                            $relation = $this->model->$name();\n\n                            $keyName = $relation->getRelated()->getKeyName();\n\n                            /** @var Model $child */\n                            $child = $relation->findOrNew(Arr::get($related, $keyName));\n\n                            if (Arr::get($related, static::REMOVE_FLAG_NAME) == 1) {\n                                $child->delete();\n                                continue;\n                            }\n\n                            Arr::forget($related, static::REMOVE_FLAG_NAME);\n\n                            $child->fill($related);\n\n                            $child->save();\n                        }\n                    } else { //relation updated via MultipleSelect field\n                        $foreignKeyName = $relation->getForeignKeyName();\n                        $localKeyName = $relation->getLocalKeyName();\n\n                        foreach ($relation->get() as $child) {\n                            if (($ind = array_search($child->getKey(), $data)) !== false) {\n                                unset($data[$ind]);\n                            } else {\n                                $child->$foreignKeyName = null;\n                                $child->save();\n                            }\n                        }\n\n                        foreach ($data as $id) {\n                            $child = $relation->getRelated()->find($id);\n                            $child->$foreignKeyName = $this->model->$localKeyName;\n                            $child->save();\n                        }\n                    }\n                    break;\n            }\n        }\n    }\n\n    /**\n     * Prepare input data for update.\n     *\n     * @param array $updates\n     * @param bool  $oneToOneRelation If column is one-to-one relation.\n     *\n     * @return array\n     */\n    protected function prepareUpdate(array $updates, $oneToOneRelation = false): array\n    {\n        $prepared = [];\n\n        /** @var Field $field */\n        foreach ($this->fields() as $field) {\n            $columns = $field->column();\n\n            // If column not in input array data, then continue.\n            if (!Arr::has($updates, $columns)) {\n                continue;\n            }\n\n            if ($this->isInvalidColumn($columns, $oneToOneRelation || $field->isJsonType)) {\n                continue;\n            }\n\n            $value = $this->getDataByColumn($updates, $columns);\n\n            $value = $field->prepare($value);\n\n            if (is_array($columns)) {\n                foreach ($columns as $name => $column) {\n                    Arr::set($prepared, $column, $value[$name]);\n                }\n            } elseif (is_string($columns)) {\n                Arr::set($prepared, $columns, $value);\n            }\n        }\n\n        return $prepared;\n    }\n\n    /**\n     * @param string|array $columns\n     * @param bool         $containsDot\n     *\n     * @return bool\n     */\n    protected function isInvalidColumn($columns, $containsDot = false): bool\n    {\n        foreach ((array) $columns as $column) {\n            if ((!$containsDot && Str::contains($column, '.')) ||\n                ($containsDot && !Str::contains($column, '.'))) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Prepare input data for insert.\n     *\n     * @param $inserts\n     *\n     * @return array\n     */\n    protected function prepareInsert($inserts): array\n    {\n        if ($this->isHasOneRelation($inserts)) {\n            $inserts = Arr::dot($inserts);\n        }\n\n        foreach ($inserts as $column => $value) {\n            if (($field = $this->getFieldByColumn($column)) === null) {\n                unset($inserts[$column]);\n                continue;\n            }\n\n            $inserts[$column] = $field->prepare($value);\n        }\n\n        $prepared = [];\n\n        foreach ($inserts as $key => $value) {\n            Arr::set($prepared, $key, $value);\n        }\n\n        return $prepared;\n    }\n\n    /**\n     * Is input data is has-one relation.\n     *\n     * @param array $inserts\n     *\n     * @return bool\n     */\n    protected function isHasOneRelation($inserts): bool\n    {\n        $first = current($inserts);\n\n        if (!is_array($first)) {\n            return false;\n        }\n\n        if (is_array(current($first))) {\n            return false;\n        }\n\n        return Arr::isAssoc($first);\n    }\n\n    /**\n     * Ignore fields to save.\n     *\n     * @param string|array $fields\n     *\n     * @return $this\n     */\n    public function ignore($fields): self\n    {\n        $this->ignored = array_merge($this->ignored, (array) $fields);\n\n        return $this;\n    }\n\n    /**\n     * @param array        $data\n     * @param string|array $columns\n     *\n     * @return array|mixed\n     */\n    protected function getDataByColumn($data, $columns)\n    {\n        if (is_string($columns)) {\n            return Arr::get($data, $columns);\n        }\n\n        if (is_array($columns)) {\n            $value = [];\n            foreach ($columns as $name => $column) {\n                if (!Arr::has($data, $column)) {\n                    continue;\n                }\n                $value[$name] = Arr::get($data, $column);\n            }\n\n            return $value;\n        }\n    }\n\n    /**\n     * Find field object by column.\n     *\n     * @param $column\n     *\n     * @return mixed\n     */\n    protected function getFieldByColumn($column)\n    {\n        return $this->fields()->first(\n            function (Field $field) use ($column) {\n                if (is_array($field->column())) {\n                    return in_array($column, $field->column());\n                }\n\n                return $field->column() == $column;\n            }\n        );\n    }\n\n    /**\n     * Set original data for each field.\n     *\n     * @return void\n     */\n    protected function setFieldOriginalValue()\n    {\n        $values = $this->model->toArray();\n\n        $this->fields()->each(function (Field $field) use ($values) {\n            $field->setOriginal($values);\n        });\n    }\n\n    /**\n     * Determine relational column needs to be snaked.\n     *\n     * @return void\n     */\n    protected function setRelationFieldSnakeAttributes()\n    {\n        $relations = $this->getRelations();\n\n        $this->fields()->each(function (Field $field) use ($relations) {\n            if ($field->getSnakeAttributes()) {\n                return;\n            }\n\n            $column = $field->column();\n\n            $column = is_array($column) ? head($column) : $column;\n\n            list($relation) = explode('.', $column);\n\n            if (!in_array($relation, $relations)) {\n                return;\n            }\n\n            $field->setSnakeAttributes($this->model::$snakeAttributes);\n        });\n    }\n\n    /**\n     * Set all fields value in form.\n     *\n     * @param $id\n     *\n     * @return void\n     */\n    protected function setFieldValue($id)\n    {\n        $relations = $this->getRelations();\n\n        $builder = $this->model();\n\n        if ($this->isSoftDeletes) {\n            $builder = $builder->withTrashed();\n        }\n\n        $this->model = $builder->with($relations)->findOrFail($id);\n\n        $this->callEditing();\n\n        $data = $this->model->toArray();\n\n        $this->fields()->each(function (Field $field) use ($data) {\n            if (!in_array($field->column(), $this->ignored, true)) {\n                $field->fill($data);\n            }\n        });\n    }\n\n    /**\n     * Add a fieldset to form.\n     *\n     * @param string  $title\n     * @param Closure $setCallback\n     *\n     * @return Field\\Fieldset\n     */\n    public function fieldset(string $title, Closure $setCallback)\n    {\n        $fieldset = new Field\\Fieldset();\n\n        $this->html($fieldset->start($title))->plain();\n\n        $setCallback($this);\n\n        $this->html($fieldset->end())->plain();\n\n        return $fieldset;\n    }\n\n    /**\n     * Get validation messages.\n     *\n     * @param array $input\n     *\n     * @return MessageBag|bool\n     */\n    public function validationMessages($input)\n    {\n        $failedValidators = [];\n\n        /** @var Field $field */\n        foreach ($this->fields() as $field) {\n            if (!$validator = $field->getValidator($input)) {\n                continue;\n            }\n\n            if (($validator instanceof Validator) && !$validator->passes()) {\n                $failedValidators[] = $validator;\n            }\n        }\n\n        $message = $this->mergeValidationMessages($failedValidators);\n\n        return $message->any() ? $message : false;\n    }\n\n    /**\n     * Merge validation messages from input validators.\n     *\n     * @param \\Illuminate\\Validation\\Validator[] $validators\n     *\n     * @return MessageBag\n     */\n    protected function mergeValidationMessages($validators): MessageBag\n    {\n        $messageBag = new MessageBag();\n\n        foreach ($validators as $validator) {\n            $messageBag = $messageBag->merge($validator->messages());\n        }\n\n        return $messageBag;\n    }\n\n    /**\n     * Get all relations of model from callable.\n     *\n     * @return array\n     */\n    public function getRelations(): array\n    {\n        $relations = $columns = [];\n\n        /** @var Field $field */\n        foreach ($this->fields() as $field) {\n            $columns[] = $field->column();\n        }\n\n        foreach (Arr::flatten($columns) as $column) {\n            if (Str::contains($column, '.')) {\n                list($relation) = explode('.', $column);\n\n                if (method_exists($this->model, $relation) &&\n                    !method_exists(Model::class, $relation) &&\n                    $this->model->$relation() instanceof Relations\\Relation\n                ) {\n                    $relations[] = $relation;\n                }\n            } elseif (method_exists($this->model, $column) &&\n                !method_exists(Model::class, $column)\n            ) {\n                $relations[] = $column;\n            }\n        }\n\n        return array_unique($relations);\n    }\n\n    /**\n     * Set action for form.\n     *\n     * @param string $action\n     *\n     * @return $this\n     */\n    public function setAction($action): self\n    {\n        $this->builder()->setAction($action);\n\n        return $this;\n    }\n\n    /**\n     * Set field and label width in current form.\n     *\n     * @param int $fieldWidth\n     * @param int $labelWidth\n     *\n     * @return $this\n     */\n    public function setWidth($fieldWidth = 8, $labelWidth = 2): self\n    {\n        $this->fields()->each(function ($field) use ($fieldWidth, $labelWidth) {\n            /* @var Field $field  */\n            $field->setWidth($fieldWidth, $labelWidth);\n        });\n\n        $this->builder()->setWidth($fieldWidth, $labelWidth);\n\n        return $this;\n    }\n\n    /**\n     * Set view for form.\n     *\n     * @param string $view\n     *\n     * @return $this\n     */\n    public function setView($view): self\n    {\n        $this->builder()->setView($view);\n\n        return $this;\n    }\n\n    /**\n     * Set title for form.\n     *\n     * @param string $title\n     *\n     * @return $this\n     */\n    public function setTitle($title = ''): self\n    {\n        $this->builder()->setTitle($title);\n\n        return $this;\n    }\n\n    /**\n     * Set a submit confirm.\n     *\n     * @param string $message\n     * @param string $on\n     *\n     * @return $this\n     */\n    public function confirm(string $message, $on = null)\n    {\n        if ($on && !in_array($on, ['create', 'edit'])) {\n            throw new \\InvalidArgumentException(\"The second paramater `\\$on` must be one of ['create', 'edit']\");\n        }\n\n        if ($on == 'create' && !$this->isCreating()) {\n            return;\n        }\n\n        if ($on == 'edit' && !$this->isEditing()) {\n            return;\n        }\n\n        $this->builder()->confirm($message);\n\n        return $this;\n    }\n\n    /**\n     * Add a row in form.\n     *\n     * @param Closure $callback\n     *\n     * @return $this\n     */\n    public function row(Closure $callback): self\n    {\n        $this->rows[] = new Row($callback, $this);\n\n        return $this;\n    }\n\n    /**\n     * Tools setting for form.\n     *\n     * @param Closure $callback\n     */\n    public function tools(Closure $callback)\n    {\n        $callback->call($this, $this->builder->getTools());\n    }\n\n    /**\n     * @param Closure|null $callback\n     *\n     * @return Form\\Tools\n     */\n    public function header(Closure $callback = null)\n    {\n        if (func_num_args() === 0) {\n            return $this->builder->getTools();\n        }\n\n        $callback->call($this, $this->builder->getTools());\n    }\n\n    /**\n     * Indicates if current form page is creating.\n     *\n     * @return bool\n     */\n    public function isCreating(): bool\n    {\n        return Str::endsWith(\\request()->route()->getName(), ['.create', '.store']);\n    }\n\n    /**\n     * Indicates if current form page is editing.\n     *\n     * @return bool\n     */\n    public function isEditing(): bool\n    {\n        return Str::endsWith(\\request()->route()->getName(), ['.edit', '.update']);\n    }\n\n    /**\n     * Disable form submit.\n     *\n     * @param bool $disable\n     *\n     * @return $this\n     *\n     * @deprecated\n     */\n    public function disableSubmit(bool $disable = true): self\n    {\n        $this->builder()->getFooter()->disableSubmit($disable);\n\n        return $this;\n    }\n\n    /**\n     * Disable form reset.\n     *\n     * @param bool $disable\n     *\n     * @return $this\n     *\n     * @deprecated\n     */\n    public function disableReset(bool $disable = true): self\n    {\n        $this->builder()->getFooter()->disableReset($disable);\n\n        return $this;\n    }\n\n    /**\n     * Disable View Checkbox on footer.\n     *\n     * @param bool $disable\n     *\n     * @return $this\n     */\n    public function disableViewCheck(bool $disable = true): self\n    {\n        $this->builder()->getFooter()->disableViewCheck($disable);\n\n        return $this;\n    }\n\n    /**\n     * Disable Editing Checkbox on footer.\n     *\n     * @param bool $disable\n     *\n     * @return $this\n     */\n    public function disableEditingCheck(bool $disable = true): self\n    {\n        $this->builder()->getFooter()->disableEditingCheck($disable);\n\n        return $this;\n    }\n\n    /**\n     * Disable Creating Checkbox on footer.\n     *\n     * @param bool $disable\n     *\n     * @return $this\n     */\n    public function disableCreatingCheck(bool $disable = true): self\n    {\n        $this->builder()->getFooter()->disableCreatingCheck($disable);\n\n        return $this;\n    }\n\n    /**\n     * Footer setting for form.\n     *\n     * @param Closure $callback\n     *\n     * @return \\Encore\\Admin\\Form\\Footer\n     */\n    public function footer(Closure $callback = null)\n    {\n        if (func_num_args() === 0) {\n            return $this->builder()->getFooter();\n        }\n\n        $callback($this->builder()->getFooter());\n    }\n\n    /**\n     * Get current resource route url.\n     *\n     * @param int $slice\n     *\n     * @return string\n     */\n    public function resource($slice = -2): string\n    {\n        $segments = explode('/', trim(\\request()->getUri(), '/'));\n\n        if ($slice !== 0) {\n            $segments = array_slice($segments, 0, $slice);\n        }\n\n        return implode('/', $segments);\n    }\n\n    /**\n     * Render the form contents.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        try {\n            return $this->builder->render();\n        } catch (\\Exception $e) {\n            return Handler::renderException($e);\n        }\n    }\n\n    /**\n     * Get or set input data.\n     *\n     * @param string $key\n     * @param null   $value\n     *\n     * @return array|mixed\n     */\n    public function input($key, $value = null)\n    {\n        if ($value === null) {\n            return Arr::get($this->inputs, $key);\n        }\n\n        return Arr::set($this->inputs, $key, $value);\n    }\n\n    /**\n     * Add a new layout column.\n     *\n     * @param int      $width\n     * @param \\Closure $closure\n     *\n     * @return $this\n     */\n    public function column($width, \\Closure $closure): self\n    {\n        $width = $width < 1 ? round(12 * $width) : $width;\n\n        $this->layout->column($width, $closure);\n\n        return $this;\n    }\n\n    /**\n     * Initialize filter layout.\n     */\n    protected function initLayout()\n    {\n        $this->layout = new Layout($this);\n    }\n\n    /**\n     * Getter.\n     *\n     * @param string $name\n     *\n     * @return array|mixed\n     */\n    public function __get($name)\n    {\n        return $this->input($name);\n    }\n\n    /**\n     * Setter.\n     *\n     * @param string $name\n     * @param mixed  $value\n     *\n     * @return array\n     */\n    public function __set($name, $value)\n    {\n        return Arr::set($this->inputs, $name, $value);\n    }\n\n    /**\n     * __isset.\n     *\n     * @param string $name\n     *\n     * @return bool\n     */\n    public function __isset($name)\n    {\n        return isset($this->inputs[$name]);\n    }\n\n    /**\n     * Generate a Field object and add to form builder if Field exists.\n     *\n     * @param string $method\n     * @param array  $arguments\n     *\n     * @return Field\n     */\n    public function __call($method, $arguments)\n    {\n        if ($className = static::findFieldClass($method)) {\n            $column = Arr::get($arguments, 0, ''); //[0];\n\n            $element = new $className($column, array_slice($arguments, 1));\n\n            $this->pushField($element);\n\n            return $element;\n        }\n\n        admin_error('Error', \"Field type [$method] does not exist.\");\n\n        return new Field\\Nullable();\n    }\n\n    /**\n     * @return Layout\n     */\n    public function getLayout(): Layout\n    {\n        return $this->layout;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Actions/Delete.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Actions;\n\nuse Encore\\Admin\\Actions\\Response;\nuse Encore\\Admin\\Actions\\RowAction;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Support\\Facades\\DB;\n\nclass Delete extends RowAction\n{\n    /**\n     * @return array|null|string\n     */\n    public function name()\n    {\n        return __('admin.delete');\n    }\n\n    /**\n     * @param Model $model\n     *\n     * @return Response\n     */\n    public function handle(Model $model)\n    {\n        $trans = [\n            'failed'    => trans('admin.delete_failed'),\n            'succeeded' => trans('admin.delete_succeeded'),\n        ];\n\n        try {\n            DB::transaction(function () use ($model) {\n                $model->delete();\n            });\n        } catch (\\Exception $exception) {\n            return $this->response()->error(\"{$trans['failed']} : {$exception->getMessage()}\");\n        }\n\n        return $this->response()->success($trans['succeeded'])->refresh();\n    }\n\n    /**\n     * @return void\n     */\n    public function dialog()\n    {\n        $this->question(trans('admin.delete_confirm'), '', ['confirmButtonColor' => '#d33']);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Actions/Edit.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Actions;\n\nuse Encore\\Admin\\Actions\\RowAction;\n\nclass Edit extends RowAction\n{\n    /**\n     * @return array|null|string\n     */\n    public function name()\n    {\n        return __('admin.edit');\n    }\n\n    /**\n     * @return string\n     */\n    public function href()\n    {\n        return \"{$this->getResource()}/{$this->getKey()}/edit\";\n    }\n}\n"
  },
  {
    "path": "src/Grid/Actions/Show.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Actions;\n\nuse Encore\\Admin\\Actions\\RowAction;\n\nclass Show extends RowAction\n{\n    /**\n     * @return array|null|string\n     */\n    public function name()\n    {\n        return __('admin.show');\n    }\n\n    /**\n     * @return string\n     */\n    public function href()\n    {\n        return \"{$this->getResource()}/{$this->getKey()}\";\n    }\n}\n"
  },
  {
    "path": "src/Grid/Column/CheckFilter.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Column;\n\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Grid\\Model;\n\nclass CheckFilter extends Filter\n{\n    /**\n     * @var array\n     */\n    protected $options;\n\n    /**\n     * CheckFilter constructor.\n     *\n     * @param array $options\n     */\n    public function __construct(array $options)\n    {\n        $this->options = $options;\n\n        $this->class = [\n            'all'  => uniqid('column-filter-all-'),\n            'item' => uniqid('column-filter-item-'),\n        ];\n    }\n\n    /**\n     * Add a binding to the query.\n     *\n     * @param array $value\n     * @param Model $model\n     */\n    public function addBinding($value, Model $model)\n    {\n        if (empty($value)) {\n            return;\n        }\n\n        $model->whereIn($this->getColumnName(), $value);\n    }\n\n    /**\n     * Add script to page.\n     *\n     * @return void\n     */\n    protected function addScript()\n    {\n        $script = <<<SCRIPT\n$('.{$this->class['all']}').on('ifChanged', function () {\n    if (this.checked) {\n        $('.{$this->class['item']}').iCheck('check');\n    } else {\n        $('.{$this->class['item']}').iCheck('uncheck');\n    }\n    return false;\n});\n\n$('.{$this->class['item']},.{$this->class['all']}').iCheck({\n    checkboxClass:'icheckbox_minimal-blue'\n});\nSCRIPT;\n\n        Admin::script($script);\n    }\n\n    /**\n     * Render this filter.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        $value = $this->getFilterValue([]);\n\n        $lists = collect($this->options)->map(function ($label, $key) use ($value) {\n            $checked = in_array($key, $value) ? 'checked' : '';\n\n            return <<<HTML\n<li class=\"checkbox icheck\" style=\"margin: 0;\">\n    <label style=\"width: 100%;padding: 3px;\">\n        <input type=\"checkbox\" class=\"{$this->class['item']}\" name=\"{$this->getColumnName()}[]\" value=\"{$key}\" {$checked}/>&nbsp;&nbsp;&nbsp;{$label}\n    </label>\n</li>\nHTML;\n        })->implode(\"\\r\\n\");\n\n        $this->addScript();\n\n        $allCheck = (count($value) == count($this->options)) ? 'checked' : '';\n        $active = empty($value) ? '' : 'text-yellow';\n\n        return <<<EOT\n<span class=\"dropdown\">\n<form action=\"{$this->getFormAction()}\" pjax-container style=\"display: inline-block;\">\n    <a href=\"javascript:void(0);\" class=\"dropdown-toggle {$active}\" data-toggle=\"dropdown\">\n        <i class=\"fa fa-filter\"></i>\n    </a>\n    <ul class=\"dropdown-menu\" role=\"menu\" style=\"padding: 10px;box-shadow: 0 2px 3px 0 rgba(0,0,0,.2);left: -70px;border-radius: 0;\">\n\n        <li>\n            <ul style='padding: 0;'>\n            <li class=\"checkbox icheck\" style=\"margin: 0;\">\n                <label style=\"width: 100%;padding: 3px;\">\n                    <input type=\"checkbox\" class=\"{$this->class['all']}\" {$allCheck}/>&nbsp;&nbsp;&nbsp;{$this->trans('all')}\n                </label>\n            </li>\n                <li class=\"divider\"></li>\n                {$lists}\n            </ul>\n        </li>\n        <li class=\"divider\"></li>\n        <li class=\"text-right\">\n            <button class=\"btn btn-sm btn-flat btn-primary pull-left\" data-loading-text=\"{$this->trans('search')}...\"><i class=\"fa fa-search\"></i>&nbsp;&nbsp;{$this->trans('search')}</button>\n            <span><a href=\"{$this->getFormAction()}\" class=\"btn btn-sm btn-flat btn-default\"><i class=\"fa fa-undo\"></i></a></span>\n        </li>\n    </ul>\n</form>\n</span>\nEOT;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Column/ExtendDisplay.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Column;\n\nuse Carbon\\Carbon;\nuse Encore\\Admin\\Grid\\Column;\nuse Encore\\Admin\\Grid\\Displayers;\nuse Encore\\Admin\\Grid\\Model;\nuse Illuminate\\Support\\Arr;\n\n/**\n * Trait ExtendDisplay.\n *\n * @method $this editable()\n * @method $this image($server = '', $width = 200, $height = 200)\n * @method $this label($style = 'success')\n * @method $this button($style = null)\n * @method $this link($href = '', $target = '_blank')\n * @method $this badge($style = 'red')\n * @method $this progress($style = 'primary', $size = 'sm', $max = 100)\n * @method $this orderable($column, $label = '')\n * @method $this table($titles = [])`\n * @method $this expand($callback = null)\n * @method $this modal($title, $callback = null)\n * @method $this carousel(int $width = 300, int $height = 200, $server = '')\n * @method $this downloadable($server = '')\n * @method $this copyable()\n * @method $this qrcode($formatter = null, $width = 150, $height = 150)\n * @method $this prefix($prefix, $delimiter = '&nbsp;')\n * @method $this suffix($suffix, $delimiter = '&nbsp;')\n * @method $this secret($dotCount = 6)\n * @method $this limit($limit = 100, $end = '...')\n */\ntrait ExtendDisplay\n{\n    /**\n     * Displayers for grid column.\n     *\n     * @var array\n     */\n    public static $displayers = [\n        'editable'      => Displayers\\Editable::class,\n        'image'         => Displayers\\Image::class,\n        'label'         => Displayers\\Label::class,\n        'button'        => Displayers\\Button::class,\n        'link'          => Displayers\\Link::class,\n        'badge'         => Displayers\\Badge::class,\n        'progressBar'   => Displayers\\ProgressBar::class,\n        'progress'      => Displayers\\ProgressBar::class,\n        'orderable'     => Displayers\\Orderable::class,\n        'table'         => Displayers\\Table::class,\n        'expand'        => Displayers\\Expand::class,\n        'modal'         => Displayers\\Modal::class,\n        'carousel'      => Displayers\\Carousel::class,\n        'downloadable'  => Displayers\\Downloadable::class,\n        'copyable'      => Displayers\\Copyable::class,\n        'qrcode'        => Displayers\\QRCode::class,\n        'prefix'        => Displayers\\Prefix::class,\n        'suffix'        => Displayers\\Suffix::class,\n        'secret'        => Displayers\\Secret::class,\n        'limit'         => Displayers\\Limit::class,\n    ];\n\n    /**\n     * @var bool\n     */\n    protected $searchable = false;\n\n    /**\n     * Extend column displayer.\n     *\n     * @param $name\n     * @param $displayer\n     */\n    public static function extend($name, $displayer)\n    {\n        static::$displayers[$name] = $displayer;\n    }\n\n    /**\n     * Set column as searchable.\n     *\n     * @return $this\n     */\n    public function searchable()\n    {\n        $this->searchable = true;\n\n        $name = $this->getName();\n        $query = request()->query();\n\n        $this->prefix(function ($_, $original) use ($name, $query) {\n            Arr::set($query, $name, $original);\n\n            $url = request()->fullUrlWithQuery($query);\n\n            return \"<a href=\\\"{$url}\\\"><i class=\\\"fa fa-search\\\"></i></a>\";\n        }, '&nbsp;&nbsp;');\n\n        return $this;\n    }\n\n    /**\n     * Bind search query to grid model.\n     *\n     * @param Model $model\n     */\n    public function bindSearchQuery(Model $model)\n    {\n        if ($this->searchable && ($value = request($this->getName())) != '') {\n            $model->where($this->getName(), $value);\n        }\n    }\n\n    /**\n     * Display column using array value map.\n     *\n     * @param array $values\n     * @param null  $default\n     *\n     * @return $this\n     */\n    public function using(array $values, $default = null)\n    {\n        return $this->display(function ($value) use ($values, $default) {\n            if (is_null($value)) {\n                return $default;\n            }\n\n            return Arr::get($values, $value, $default);\n        });\n    }\n\n    /**\n     * Replace output value with giving map.\n     *\n     * @param array $replacements\n     *\n     * @return $this\n     */\n    public function replace(array $replacements)\n    {\n        return $this->display(function ($value) use ($replacements) {\n            if (isset($replacements[$value])) {\n                return $replacements[$value];\n            }\n\n            return $value;\n        });\n    }\n\n    /**\n     * @param string|Closure $input\n     * @param string         $seperator\n     *\n     * @return $this\n     */\n    public function repeat($input, $seperator = '')\n    {\n        if (is_string($input)) {\n            $input = function () use ($input) {\n                return $input;\n            };\n        }\n\n        if ($input instanceof Closure) {\n            return $this->display(function ($value) use ($input, $seperator) {\n                return join($seperator, array_fill(0, (int) $value, $input->call($this, [$value])));\n            });\n        }\n\n        return $this;\n    }\n\n    /**\n     * Render this column with the given view.\n     *\n     * @param string $view\n     *\n     * @return $this\n     */\n    public function view($view)\n    {\n        return $this->display(function ($value) use ($view) {\n            $model = $this;\n\n            return view($view, compact('model', 'value'))->render();\n        });\n    }\n\n    /**\n     * Convert file size to a human readable format like `100mb`.\n     *\n     * @return $this\n     */\n    public function filesize()\n    {\n        return $this->display(function ($value) {\n            return file_size($value);\n        });\n    }\n\n    /**\n     * Display the fields in the email format as gavatar.\n     *\n     * @param int $size\n     *\n     * @return $this\n     */\n    public function gravatar($size = 30)\n    {\n        return $this->display(function ($value) use ($size) {\n            $src = sprintf(\n                'https://www.gravatar.com/avatar/%s?s=%d',\n                md5(strtolower($value)),\n                $size\n            );\n\n            return \"<img src='$src' class='img img-circle'/>\";\n        });\n    }\n\n    /**\n     * Display field as a loading icon.\n     *\n     * @param array $values\n     * @param array $others\n     *\n     * @return $this\n     */\n    public function loading($values = [], $others = [])\n    {\n        return $this->display(function ($value) use ($values, $others) {\n            $values = (array) $values;\n\n            if (in_array($value, $values)) {\n                return '<i class=\"fa fa-refresh fa-spin text-primary\"></i>';\n            }\n\n            return Arr::get($others, $value, $value);\n        });\n    }\n\n    /**\n     * Display column as an font-awesome icon based on it's value.\n     *\n     * @param array  $setting\n     * @param string $default\n     *\n     * @return $this\n     */\n    public function icon(array $setting, $default = '')\n    {\n        return $this->display(function ($value) use ($setting, $default) {\n            $fa = '';\n\n            if (isset($setting[$value])) {\n                $fa = $setting[$value];\n            } elseif ($default) {\n                $fa = $default;\n            }\n\n            return \"<i class=\\\"fa fa-{$fa}\\\"></i>\";\n        });\n    }\n\n    /**\n     * Return a human readable format time.\n     *\n     * @param null $locale\n     *\n     * @return $this\n     */\n    public function diffForHumans($locale = null)\n    {\n        if ($locale) {\n            Carbon::setLocale($locale);\n        }\n\n        return $this->display(function ($value) {\n            return Carbon::parse($value)->diffForHumans();\n        });\n    }\n\n    /**\n     * Display column as boolean , `✓` for true, and `✗` for false.\n     *\n     * @param array $map\n     * @param bool  $default\n     *\n     * @return $this\n     */\n    public function bool(array $map = [], $default = false)\n    {\n        return $this->display(function ($value) use ($map, $default) {\n            $bool = empty($map) ? boolval($value) : Arr::get($map, $value, $default);\n\n            return $bool ? '<i class=\"fa fa-check text-green\"></i>' : '<i class=\"fa fa-close text-red\"></i>';\n        });\n    }\n\n    /**\n     * Display column as a default value if empty.\n     *\n     * @param string $default\n     *\n     * @return $this\n     */\n    public function default($default = '-')\n    {\n        return $this->display(function ($value) use ($default) {\n            return $value ?: $default;\n        });\n    }\n\n    /**\n     * Add a `dot` before column text.\n     *\n     * @param array  $options\n     * @param string $default\n     *\n     * @return $this\n     */\n    public function dot($options = [], $default = '')\n    {\n        return $this->prefix(function ($_, $original) use ($options, $default) {\n            if (is_null($original)) {\n                $style = $default;\n            } else {\n                $style = Arr::get($options, $original, $default);\n            }\n\n            return \"<span class=\\\"label-{$style}\\\" style='width: 8px;height: 8px;padding: 0;border-radius: 50%;display: inline-block;'></span>\";\n        }, '&nbsp;&nbsp;');\n    }\n}\n"
  },
  {
    "path": "src/Grid/Column/Filter.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Column;\n\nuse Encore\\Admin\\Grid\\Column;\nuse Encore\\Admin\\Grid\\Model;\nuse Illuminate\\Contracts\\Support\\Renderable;\nuse Illuminate\\Support\\Arr;\n\nclass Filter implements Renderable\n{\n    /**\n     * @var string|array\n     */\n    protected $class;\n\n    /**\n     * @var Column\n     */\n    protected $parent;\n\n    /**\n     * @param Column $column\n     */\n    public function setParent(Column $column)\n    {\n        $this->parent = $column;\n    }\n\n    /**\n     * Get column name.\n     *\n     * @return string\n     */\n    public function getColumnName()\n    {\n        return $this->parent->getName();\n    }\n\n    /**\n     * Get filter value of this column.\n     *\n     * @param string $default\n     *\n     * @return array|\\Illuminate\\Http\\Request|string\n     */\n    public function getFilterValue($default = '')\n    {\n        return request($this->getColumnName(), $default);\n    }\n\n    /**\n     * Get form action url.\n     *\n     * @return string\n     */\n    public function getFormAction()\n    {\n        $request = request();\n\n        $query = $request->query();\n        Arr::forget($query, [$this->getColumnName(), '_pjax']);\n\n        $question = $request->getBaseUrl().$request->getPathInfo() == '/' ? '/?' : '?';\n\n        return count($request->query()) > 0\n            ? $request->url().$question.http_build_query($query)\n            : $request->fullUrl();\n    }\n\n    /**\n     * @param string $key\n     *\n     * @return array|null|string\n     */\n    protected function trans($key)\n    {\n        return __(\"admin.{$key}\");\n    }\n\n    /**\n     * Add a query binding.\n     *\n     * @param mixed $value\n     * @param Model $model\n     */\n    public function addBinding($value, Model $model)\n    {\n        //\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function render()\n    {\n        //\n    }\n}\n"
  },
  {
    "path": "src/Grid/Column/HasHeader.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Column;\n\nuse Encore\\Admin\\Grid\\Column;\nuse Encore\\Admin\\Grid\\Model;\nuse Illuminate\\Contracts\\Support\\Htmlable;\nuse Illuminate\\Contracts\\Support\\Renderable;\n\ntrait HasHeader\n{\n    /**\n     * @var Filter\n     */\n    public $filter;\n\n    /**\n     * @var array\n     */\n    protected $headers = [];\n\n    /**\n     * Add contents to column header.\n     *\n     * @param string|Renderable|Htmlable $header\n     *\n     * @return $this\n     */\n    public function addHeader($header)\n    {\n        if ($header instanceof Filter) {\n            $header->setParent($this);\n            $this->filter = $header;\n        }\n\n        $this->headers[] = $header;\n\n        return $this;\n    }\n\n    /**\n     * Add a column sortable to column header.\n     *\n     * @param string $cast\n     *\n     * @return Column|string\n     */\n    protected function addSorter($cast = null)\n    {\n        $sortName = $this->grid->model()->getSortName();\n\n        $sorter = new Sorter($sortName, $this->getName(), $cast);\n\n        return $this->addHeader($sorter);\n    }\n\n    /**\n     * Add a help tooltip to column header.\n     *\n     * @param string $message\n     *\n     * @return $this\n     */\n    protected function addHelp($message)\n    {\n        return $this->addHeader(new Help($message));\n    }\n\n    /**\n     * Add a filter to column header.\n     *\n     * @return $this\n     */\n    protected function addFilter($type = null, $formal = null)\n    {\n        if (is_array($type)) {\n            return $this->addHeader(new CheckFilter($type));\n        }\n\n        if (is_null($type)) {\n            $type = 'equal';\n        }\n\n        if (in_array($type, ['equal', 'like', 'date', 'time', 'datetime'])) {\n            return $this->addHeader(new InputFilter($type));\n        }\n\n        if ($type === 'range') {\n            if (is_null($formal)) {\n                $formal = 'equal';\n            }\n\n            return $this->addHeader(new RangeFilter($formal));\n        }\n\n        return $this;\n    }\n\n    /**\n     * Add a binding based on filter to the model query.\n     *\n     * @param Model $model\n     */\n    public function bindFilterQuery(Model $model)\n    {\n        if ($this->filter) {\n            $this->filter->addBinding(request($this->getName()), $model);\n        }\n    }\n\n    /**\n     * Render Column header.\n     *\n     * @return string\n     */\n    public function renderHeader()\n    {\n        return collect($this->headers)->map(function ($item) {\n            if ($item instanceof Renderable) {\n                return $item->render();\n            }\n\n            if ($item instanceof Htmlable) {\n                return $item->toHtml();\n            }\n\n            return (string) $item;\n        })->implode('');\n    }\n}\n"
  },
  {
    "path": "src/Grid/Column/Help.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Column;\n\nuse Illuminate\\Contracts\\Support\\Renderable;\n\nclass Help implements Renderable\n{\n    /**\n     * @var string\n     */\n    protected $message = '';\n\n    /**\n     * Help constructor.\n     *\n     * @param string $message\n     */\n    public function __construct($message = '')\n    {\n        $this->message = $message;\n    }\n\n    /**\n     * Render help  header.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        $data = [\n            'toggle'    => 'tooltip',\n            'placement' => 'right',\n            'html'      => 'true',\n            'title'     => $this->message,\n        ];\n\n        $data = collect($data)->map(function ($val, $key) {\n            return \"data-{$key}=\\\"{$val}\\\"\";\n        })->implode(' ');\n\n        return <<<HELP\n<a href=\"javascript:void(0);\" class=\"grid-column-help\" {$data}>\n    <i class=\"fa fa-question-circle\"></i>\n</a>\nHELP;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Column/InlineEditing.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Column;\n\nuse Encore\\Admin\\Grid\\Displayers;\n\ntrait InlineEditing\n{\n    /**\n     * @param string $selectable\n     *\n     * @return $this\n     */\n    public function belongsTo($selectable)\n    {\n        if (method_exists($selectable, 'display')) {\n            $this->display($selectable::display());\n        }\n\n        return $this->displayUsing(Displayers\\BelongsTo::class, [$selectable]);\n    }\n\n    /**\n     * @param string $selectable\n     *\n     * @return $this\n     */\n    public function belongsToMany($selectable)\n    {\n        if (method_exists($selectable, 'display')) {\n            $this->display($selectable::display());\n        }\n\n        return $this->displayUsing(Displayers\\BelongsToMany::class, [$selectable]);\n    }\n\n    /**\n     * Upload file.\n     *\n     * @return $this\n     */\n    public function upload()\n    {\n        return $this->displayUsing(Displayers\\Upload::class);\n    }\n\n    /**\n     * Upload many files.\n     *\n     * @return $this\n     */\n    public function uplaodMany()\n    {\n        return $this->displayUsing(Displayers\\Upload::class, [true]);\n    }\n\n    /**\n     * Grid inline datetime picker.\n     *\n     * @param string $format\n     *\n     * @return $this\n     */\n    public function datetime($format = 'YYYY-MM-DD HH:mm:ss')\n    {\n        return $this->displayUsing(Displayers\\Datetime::class, [$format]);\n    }\n\n    /**\n     * Grid inline date picker.\n     *\n     * @param string $format\n     *\n     * @return $this\n     */\n    public function date()\n    {\n        return $this->datetime('YYYY-MM-DD');\n    }\n\n    /**\n     * Grid inline time picker.\n     *\n     * @param string $format\n     *\n     * @return $this\n     */\n    public function time()\n    {\n        return $this->datetime('HH:mm:ss');\n    }\n\n    /**\n     * Grid inline year picker.\n     *\n     * @return $this\n     */\n    public function year()\n    {\n        return $this->datetime('YYYY');\n    }\n\n    /**\n     * Grid inline month picker.\n     *\n     * @return $this\n     */\n    public function month()\n    {\n        return $this->datetime('MM');\n    }\n\n    /**\n     * Grid inline day picker.\n     *\n     * @return $this\n     */\n    public function day()\n    {\n        return $this->datetime('DD');\n    }\n\n    /**\n     * Grid inline input.\n     *\n     * @return $this\n     */\n    protected function input($mask = [])\n    {\n        return $this->displayUsing(Displayers\\Input::class, [$mask]);\n    }\n\n    /**\n     * Grid inline text input.\n     *\n     * @return $this\n     */\n    public function text()\n    {\n        return $this->input();\n    }\n\n    /**\n     * Grid inline ip input.\n     *\n     * @return $this\n     */\n    public function ip()\n    {\n        return $this->input(['alias' => 'ip']);\n    }\n\n    /**\n     * Grid inline email input.\n     *\n     * @return $this\n     */\n    public function email()\n    {\n        return $this->input(['alias' => 'email']);\n    }\n\n    /**\n     * Grid inline url input.\n     *\n     * @return $this\n     */\n    public function url()\n    {\n        return $this->input(['alias' => 'url']);\n    }\n\n    /**\n     * Grid inline currency input.\n     *\n     * @return $this\n     */\n    public function currency()\n    {\n        return $this->input([\n            'alias'              => 'currency',\n            'radixPoint'         => '.',\n            'prefix'             => '',\n            'removeMaskOnSubmit' => true,\n        ]);\n    }\n\n    /**\n     * Grid inline decimal input.\n     *\n     * @return $this\n     */\n    public function decimal()\n    {\n        return $this->input([\n            'alias'      => 'decimal',\n            'rightAlign' => true,\n        ]);\n    }\n\n    /**\n     * Grid inline integer input.\n     *\n     * @return $this\n     */\n    public function integer()\n    {\n        return $this->input([\n            'alias' => 'integer',\n        ]);\n    }\n\n    /**\n     * Grid inline textarea.\n     *\n     * @param int $rows\n     *\n     * @return $this\n     */\n    public function textarea($rows = 5)\n    {\n        return $this->displayUsing(Displayers\\Textarea::class, [$rows]);\n    }\n\n    /**\n     * Grid inline tiemzone select.\n     *\n     * @return $this\n     */\n    public function timezone()\n    {\n        $identifiers = \\DateTimeZone::listIdentifiers(\\DateTimeZone::ALL);\n\n        $options = collect($identifiers)->mapWithKeys(function ($timezone) {\n            return [$timezone => $timezone];\n        })->toArray();\n\n        return $this->select($options);\n    }\n\n    /**\n     * Grid inline select.\n     *\n     * @param array $options\n     *\n     * @return mixed\n     */\n    public function select(array $options)\n    {\n        return $this->displayUsing(Displayers\\Select::class, [$options]);\n    }\n\n    /**\n     * Grid inline multiple-select input.\n     *\n     * @param array $options\n     *\n     * @return $this\n     */\n    public function multipleSelect(array $options)\n    {\n        return $this->displayUsing(Displayers\\MultipleSelect::class, [$options]);\n    }\n\n    /**\n     * Grid inline checkbox.\n     *\n     * @param array $options\n     *\n     * @return $this\n     */\n    public function checkbox(array $options)\n    {\n        return $this->displayUsing(Displayers\\Checkbox::class, [$options]);\n    }\n\n    /**\n     * Grid inline checkbox.\n     *\n     * @param array $options\n     *\n     * @return $this\n     */\n    public function radio(array $options)\n    {\n        return $this->displayUsing(Displayers\\Radio::class, [$options]);\n    }\n\n    /**\n     * Grid inline switch.\n     *\n     * @param array $states\n     *\n     * @return $this\n     */\n    public function switch(array $states = [])\n    {\n        return $this->displayUsing(Displayers\\SwitchDisplay::class, [$states]);\n    }\n\n    /**\n     * Grid inline switch group.\n     *\n     * @param array $states\n     *\n     * @return $this\n     */\n    public function switchGroup(array $columns = [], array $states = [])\n    {\n        return $this->displayUsing(Displayers\\SwitchGroup::class, [$columns, $states]);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Column/InputFilter.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Column;\n\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Grid\\Model;\n\nclass InputFilter extends Filter\n{\n    /**\n     * @var string\n     */\n    protected $type;\n\n    /**\n     * InputFilter constructor.\n     *\n     * @param string $type\n     */\n    public function __construct($type)\n    {\n        $this->type = $type;\n        $this->class = uniqid('column-filter-');\n    }\n\n    /**\n     * Add a binding to the query.\n     *\n     * @param string     $value\n     * @param Model|null $model\n     */\n    public function addBinding($value, Model $model)\n    {\n        if (empty($value)) {\n            return;\n        }\n\n        if ($this->type == 'like') {\n            $model->where($this->getColumnName(), 'like', \"%{$value}%\");\n\n            return;\n        }\n\n        if (in_array($this->type, ['date', 'time'])) {\n            $method = 'where'.ucfirst($this->type);\n            $model->{$method}($this->getColumnName(), $value);\n\n            return;\n        }\n\n        $model->where($this->getColumnName(), $value);\n    }\n\n    /**\n     * Add script to page.\n     *\n     * @return void\n     */\n    protected function addScript()\n    {\n        $options = [\n            'locale'           => config('app.locale'),\n            'allowInputToggle' => true,\n        ];\n\n        if ($this->type == 'date') {\n            $options['format'] = 'YYYY-MM-DD';\n        } elseif ($this->type == 'time') {\n            $options['format'] = 'HH:mm:ss';\n        } elseif ($this->type == 'datetime') {\n            $options['format'] = 'YYYY-MM-DD HH:mm:ss';\n        } else {\n            return;\n        }\n\n        $options = json_encode($options);\n\n        Admin::script(\"$('.{$this->class}').datetimepicker($options);\");\n    }\n\n    /**\n     * Render this filter.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        $script = <<<'SCRIPT'\n$('.dropdown-menu input').click(function(e) {\n    e.stopPropagation();\n});\nSCRIPT;\n        Admin::script($script);\n\n        $this->addScript();\n\n        $value = $this->getFilterValue();\n\n        $active = empty($value) ? '' : 'text-yellow';\n\n        return <<<EOT\n<span class=\"dropdown\">\n    <form action=\"{$this->getFormAction()}\" pjax-container style=\"display: inline-block;\">\n    <a href=\"javascript:void(0);\" class=\"dropdown-toggle {$active}\" data-toggle=\"dropdown\">\n        <i class=\"fa fa-filter\"></i>\n    </a>\n    <ul class=\"dropdown-menu\" role=\"menu\" style=\"padding: 10px;box-shadow: 0 2px 3px 0 rgba(0,0,0,.2);left: -70px;border-radius: 0;\">\n        <li>\n            <input type=\"text\" name=\"{$this->getColumnName()}\" value=\"{$this->getFilterValue()}\" class=\"form-control input-sm {$this->class}\" autocomplete=\"off\"/>\n        </li>\n        <li class=\"divider\"></li>\n        <li class=\"text-right\">\n            <button class=\"btn btn-sm btn-flat btn-primary column-filter-submit pull-left\" data-loading-text=\"{$this->trans('search')}...\"><i class=\"fa fa-search\"></i>&nbsp;&nbsp;{$this->trans('search')}</button>\n            <span><a href=\"{$this->getFormAction()}\" class=\"btn btn-sm btn-default btn-flat column-filter-all\"><i class=\"fa fa-undo\"></i></a></span>\n        </li>\n    </ul>\n    </form>\n</span>\nEOT;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Column/RangeFilter.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Column;\n\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Grid\\Model;\n\nclass RangeFilter extends Filter\n{\n    /**\n     * @var string\n     */\n    protected $type;\n\n    /**\n     * RangeFilter constructor.\n     *\n     * @param string $type\n     */\n    public function __construct($type)\n    {\n        $this->type = $type;\n        $this->class = [\n            'start' => uniqid('column-filter-start-'),\n            'end'   => uniqid('column-filter-end-'),\n        ];\n    }\n\n    /**\n     * Add a binding to the query.\n     *\n     * @param mixed $value\n     * @param Model $model\n     */\n    public function addBinding($value, Model $model)\n    {\n        $value = array_filter((array) $value);\n\n        if (empty($value)) {\n            return;\n        }\n\n        if (!isset($value['start'])) {\n            return $model->where($this->getColumnName(), '<', $value['end']);\n        } elseif (!isset($value['end'])) {\n            return $model->where($this->getColumnName(), '>', $value['start']);\n        } else {\n            return $model->whereBetween($this->getColumnName(), array_values($value));\n        }\n    }\n\n    protected function addScript()\n    {\n        $options = [\n            'locale'           => config('app.locale'),\n            'allowInputToggle' => true,\n        ];\n\n        if ($this->type == 'date') {\n            $options['format'] = 'YYYY-MM-DD';\n        } elseif ($this->type == 'time') {\n            $options['format'] = 'HH:mm:ss';\n        } elseif ($this->type == 'datetime') {\n            $options['format'] = 'YYYY-MM-DD HH:mm:ss';\n        } else {\n            return;\n        }\n\n        $options = json_encode($options);\n\n        Admin::script(\"$('.{$this->class['start']},.{$this->class['end']}').datetimepicker($options);\");\n    }\n\n    /**\n     * Render this filter.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        $script = <<<'SCRIPT'\n$('.dropdown-menu input').click(function(e) {\n    e.stopPropagation();\n});\nSCRIPT;\n\n        Admin::script($script);\n\n        $this->addScript();\n\n        $value = array_merge(['start' => '', 'end' => ''], $this->getFilterValue([]));\n        $active = empty(array_filter($value)) ? '' : 'text-yellow';\n\n        return <<<EOT\n<span class=\"dropdown\">\n<form action=\"{$this->getFormAction()}\" pjax-container style=\"display: inline-block;\">\n    <a href=\"javascript:void(0);\" class=\"dropdown-toggle {$active}\" data-toggle=\"dropdown\">\n        <i class=\"fa fa-filter\"></i>\n    </a>\n    <ul class=\"dropdown-menu\" role=\"menu\" style=\"padding: 10px;box-shadow: 0 2px 3px 0 rgba(0,0,0,.2);left: -70px;border-radius: 0;\">\n        <li>\n            <input type=\"text\" class=\"form-control input-sm {$this->class['start']}\" name=\"{$this->getColumnName()}[start]\" value=\"{$value['start']}\" autocomplete=\"off\"/>\n        </li>\n        <li style=\"margin: 5px;\"></li>\n        <li>\n            <input type=\"text\" class=\"form-control input-sm {$this->class['start']}\" name=\"{$this->getColumnName()}[end]\"  value=\"{$value['end']}\" autocomplete=\"off\"/>\n        </li>\n        <li class=\"divider\"></li>\n        <li class=\"text-right\">\n            <button class=\"btn btn-sm btn-primary btn-flat column-filter-submit pull-left\" data-loading-text=\"{$this->trans('search')}...\"><i class=\"fa fa-search\"></i>&nbsp;&nbsp;{$this->trans('search')}</button>\n            <span><a href=\"{$this->getFormAction()}\" class=\"btn btn-sm btn-default btn-flat column-filter-all\"><i class=\"fa fa-undo\"></i></a></span>\n        </li>\n    </ul>\n    </form>\n</span>\nEOT;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Column/Sorter.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Column;\n\nuse Illuminate\\Contracts\\Support\\Renderable;\n\nclass Sorter implements Renderable\n{\n    /**\n     * Sort arguments.\n     *\n     * @var array\n     */\n    protected $sort;\n\n    /**\n     * Cast Name.\n     *\n     * @var array\n     */\n    protected $cast;\n\n    /**\n     * @var string\n     */\n    protected $sortName;\n\n    /**\n     * @var string\n     */\n    protected $columnName;\n\n    /**\n     * Sorter constructor.\n     *\n     * @param string $sortName\n     * @param string $columnName\n     * @param string $cast\n     */\n    public function __construct($sortName, $columnName, $cast)\n    {\n        $this->sortName = $sortName;\n        $this->columnName = $columnName;\n        $this->cast = $cast;\n    }\n\n    /**\n     * Determine if this column is currently sorted.\n     *\n     * @return bool\n     */\n    protected function isSorted()\n    {\n        $this->sort = \\request()->get($this->sortName);\n\n        if (empty($this->sort)) {\n            return false;\n        }\n\n        return isset($this->sort['column']) && $this->sort['column'] == $this->columnName;\n    }\n\n    /**\n     * @return string\n     */\n    public function render()\n    {\n        $icon = 'fa-sort';\n        $type = 'desc';\n\n        if ($this->isSorted()) {\n            $type = $this->sort['type'] == 'desc' ? 'asc' : 'desc';\n            $icon .= \"-amount-{$this->sort['type']}\";\n        }\n\n        // set sort value\n        $sort = ['column' => $this->columnName, 'type' => $type];\n\n        if ($this->cast) {\n            $sort['cast'] = $this->cast;\n        }\n\n        $query = \\request()->all();\n        $query = array_merge($query, [$this->sortName => $sort]);\n\n        $url = url()->current().'?'.http_build_query($query);\n\n        return \"<a class=\\\"fa fa-fw $icon\\\" href=\\\"$url\\\"></a>\";\n    }\n}\n"
  },
  {
    "path": "src/Grid/Column.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid;\n\nuse Closure;\nuse Encore\\Admin\\Actions\\RowAction;\nuse Encore\\Admin\\Grid;\nuse Encore\\Admin\\Grid\\Displayers\\AbstractDisplayer;\nuse Illuminate\\Contracts\\Support\\Arrayable;\nuse Illuminate\\Database\\Eloquent\\Model as BaseModel;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Support\\Str;\n\nclass Column\n{\n    use Column\\HasHeader;\n    use Column\\InlineEditing;\n    use Column\\ExtendDisplay;\n\n    const SELECT_COLUMN_NAME = '__row_selector__';\n\n    const ACTION_COLUMN_NAME = '__actions__';\n\n    /**\n     * @var Grid\n     */\n    protected $grid;\n\n    /**\n     * Name of column.\n     *\n     * @var string\n     */\n    protected $name;\n\n    /**\n     * Label of column.\n     *\n     * @var string\n     */\n    protected $label;\n\n    /**\n     * Original value of column.\n     *\n     * @var mixed\n     */\n    protected $original;\n\n    /**\n     * Attributes of column.\n     *\n     * @var array\n     */\n    protected $attributes = [];\n\n    /**\n     * Relation name.\n     *\n     * @var bool\n     */\n    protected $relation = false;\n\n    /**\n     * Relation column.\n     *\n     * @var string\n     */\n    protected $relationColumn;\n\n    /**\n     * Original grid data.\n     *\n     * @var Collection\n     */\n    protected static $originalGridModels;\n\n    /**\n     * @var []Closure\n     */\n    protected $displayCallbacks = [];\n\n    /**\n     * Defined columns.\n     *\n     * @var array\n     */\n    public static $defined = [];\n\n    /**\n     * @var array\n     */\n    protected static $htmlAttributes = [];\n\n    /**\n     * @var array\n     */\n    protected static $rowAttributes = [];\n\n    /**\n     * @var Model\n     */\n    protected static $model;\n\n    /**\n     * @param string $name\n     * @param string $label\n     */\n    public function __construct($name, $label)\n    {\n        $this->name = $name;\n\n        $this->label = $this->formatLabel($label);\n\n        $this->initAttributes();\n    }\n\n    /**\n     * Initialize column attributes.\n     */\n    protected function initAttributes()\n    {\n        $name = str_replace('.', '-', $this->name);\n\n        $this->setAttributes(['class' => \"column-{$name}\"]);\n    }\n\n    /**\n     * Define a column globally.\n     *\n     * @param string $name\n     * @param mixed  $definition\n     */\n    public static function define($name, $definition)\n    {\n        static::$defined[$name] = $definition;\n    }\n\n    /**\n     * Set grid instance for column.\n     *\n     * @param Grid $grid\n     */\n    public function setGrid(Grid $grid)\n    {\n        $this->grid = $grid;\n\n        $this->setModel($grid->model()->eloquent());\n    }\n\n    /**\n     * Set model for column.\n     *\n     * @param $model\n     */\n    public function setModel($model)\n    {\n        if (is_null(static::$model) && ($model instanceof BaseModel)) {\n            static::$model = $model->newInstance();\n        }\n    }\n\n    /**\n     * Set original data for column.\n     *\n     * @param Collection $collection\n     */\n    public static function setOriginalGridModels(Collection $collection)\n    {\n        static::$originalGridModels = $collection;\n    }\n\n    /**\n     * Set column attributes.\n     *\n     * @param array $attributes\n     *\n     * @return $this\n     */\n    public function setAttributes($attributes = [], $key = null)\n    {\n        if ($key) {\n            static::$rowAttributes[$this->name][$key] = array_merge(\n                Arr::get(static::$rowAttributes, \"{$this->name}.{$key}\", []),\n                $attributes\n            );\n\n            return $this;\n        }\n\n        static::$htmlAttributes[$this->name] = array_merge(\n            Arr::get(static::$htmlAttributes, $this->name, []),\n            $attributes\n        );\n\n        return $this;\n    }\n\n    /**\n     * Get column attributes.\n     *\n     * @param string $name\n     *\n     * @return mixed\n     */\n    public static function getAttributes($name, $key = null)\n    {\n        $rowAttributes = [];\n\n        if ($key && Arr::has(static::$rowAttributes, \"{$name}.{$key}\")) {\n            $rowAttributes = Arr::get(static::$rowAttributes, \"{$name}.{$key}\", []);\n        }\n\n        $columnAttributes = Arr::get(static::$htmlAttributes, $name, []);\n\n        return array_merge($rowAttributes, $columnAttributes);\n    }\n\n    /**\n     * Format attributes to html.\n     *\n     * @return string\n     */\n    public function formatHtmlAttributes()\n    {\n        $attrArr = [];\n        foreach (static::getAttributes($this->name) as $name => $val) {\n            $attrArr[] = \"$name=\\\"$val\\\"\";\n        }\n\n        return implode(' ', $attrArr);\n    }\n\n    /**\n     * Set style of this column.\n     *\n     * @param string $style\n     *\n     * @return $this\n     */\n    public function style($style)\n    {\n        return $this->setAttributes(compact('style'));\n    }\n\n    /**\n     * Set the width of column.\n     *\n     * @param int $width\n     *\n     * @return $this\n     */\n    public function width(int $width)\n    {\n        return $this->style(\"width: {$width}px;max-width: {$width}px;word-wrap: break-word;word-break: normal;\");\n    }\n\n    /**\n     * Set the color of column.\n     *\n     * @param string $color\n     *\n     * @return $this\n     */\n    public function color($color)\n    {\n        return $this->style(\"color:$color;\");\n    }\n\n    /**\n     * Get original column value.\n     *\n     * @return mixed\n     */\n    public function getOriginal()\n    {\n        return $this->original;\n    }\n\n    /**\n     * Get name of this column.\n     *\n     * @return mixed\n     */\n    public function getName()\n    {\n        return $this->name;\n    }\n\n    /**\n     * @return string\n     */\n    public function getClassName()\n    {\n        $name = str_replace('.', '-', $this->getName());\n\n        return \"column-{$name}\";\n    }\n\n    /**\n     * Format label.\n     *\n     * @param $label\n     *\n     * @return mixed\n     */\n    protected function formatLabel($label)\n    {\n        if ($label) {\n            return $label;\n        }\n\n        $label = ucfirst($this->name);\n\n        return __(str_replace(['.', '_'], ' ', $label));\n    }\n\n    /**\n     * Get label of the column.\n     *\n     * @return mixed\n     */\n    public function getLabel()\n    {\n        return $this->label;\n    }\n\n    /**\n     * Set relation.\n     *\n     * @param string $relation\n     * @param string $relationColumn\n     *\n     * @return $this\n     */\n    public function setRelation($relation, $relationColumn = null)\n    {\n        $this->relation = $relation;\n        $this->relationColumn = $relationColumn;\n\n        return $this;\n    }\n\n    /**\n     * If this column is relation column.\n     *\n     * @return bool\n     */\n    protected function isRelation()\n    {\n        return (bool) $this->relation;\n    }\n\n    /**\n     * Mark this column as sortable.\n     *\n     * @param null|string $cast\n     *\n     * @return Column|string\n     */\n    public function sortable($cast = null)\n    {\n        return $this->addSorter($cast);\n    }\n\n    /**\n     * Set cast name for sortable.\n     *\n     * @return $this\n     *\n     * @deprecated Use `$column->sortable($cast)` instead.\n     */\n    public function cast($cast)\n    {\n        $this->cast = $cast;\n\n        return $this;\n    }\n\n    /**\n     * Set help message for column.\n     *\n     * @param string $help\n     *\n     * @return $this|string\n     */\n    public function help($help = '')\n    {\n        return $this->addHelp($help);\n    }\n\n    /**\n     * Set column filter.\n     *\n     * @param mixed|null $builder\n     *\n     * @return $this\n     */\n    public function filter($builder = null)\n    {\n        return $this->addFilter(...func_get_args());\n    }\n\n    /**\n     * Add a display callback.\n     *\n     * @param Closure $callback\n     *\n     * @return $this\n     */\n    public function display(Closure $callback)\n    {\n        $this->displayCallbacks[] = $callback;\n\n        return $this;\n    }\n\n    /**\n     * Display using display abstract.\n     *\n     * @param string $abstract\n     * @param array  $arguments\n     *\n     * @return $this\n     */\n    public function displayUsing($abstract, $arguments = [])\n    {\n        $grid = $this->grid;\n\n        $column = $this;\n\n        return $this->display(function ($value) use ($grid, $column, $abstract, $arguments) {\n            /** @var AbstractDisplayer $displayer */\n            $displayer = new $abstract($value, $grid, $column, $this);\n\n            return $displayer->display(...$arguments);\n        });\n    }\n\n    /**\n     * Hide this column by default.\n     *\n     * @return $this\n     */\n    public function hide()\n    {\n        $this->grid->hideColumns($this->getName());\n\n        return $this;\n    }\n\n    /**\n     * Add column to total-row.\n     *\n     * @param null $display\n     *\n     * @return $this\n     */\n    public function totalRow($display = null)\n    {\n        $this->grid->addTotalRow($this->name, $display);\n\n        return $this;\n    }\n\n    /**\n     * Display column using a grid row action.\n     *\n     * @param string $action\n     *\n     * @return $this\n     */\n    public function action($action)\n    {\n        if (!is_subclass_of($action, RowAction::class)) {\n            throw new \\InvalidArgumentException(\"Action class [$action] must be sub-class of [Encore\\Admin\\Actions\\GridAction]\");\n        }\n\n        $grid = $this->grid;\n\n        return $this->display(function ($_, $column) use ($action, $grid) {\n            /** @var RowAction $action */\n            $action = new $action();\n\n            return $action\n                ->asColumn()\n                ->setGrid($grid)\n                ->setColumn($column)\n                ->setRow($this);\n        });\n    }\n\n    /**\n     * If has display callbacks.\n     *\n     * @return bool\n     */\n    protected function hasDisplayCallbacks()\n    {\n        return !empty($this->displayCallbacks);\n    }\n\n    /**\n     * Call all of the \"display\" callbacks column.\n     *\n     * @param mixed $value\n     * @param int   $key\n     *\n     * @return mixed\n     */\n    protected function callDisplayCallbacks($value, $key)\n    {\n        foreach ($this->displayCallbacks as $callback) {\n            $previous = $value;\n\n            $callback = $this->bindOriginalRowModel($callback, $key);\n            $value = call_user_func_array($callback, [$value, $this]);\n\n            if (($value instanceof static) &&\n                ($last = array_pop($this->displayCallbacks))\n            ) {\n                $last = $this->bindOriginalRowModel($last, $key);\n                $value = call_user_func_array($last, [$previous, $this]);\n            }\n        }\n\n        return $value;\n    }\n\n    /**\n     * Set original grid data to column.\n     *\n     * @param Closure $callback\n     * @param int     $key\n     *\n     * @return Closure\n     */\n    protected function bindOriginalRowModel(Closure $callback, $key)\n    {\n        $rowModel = static::$originalGridModels[$key];\n\n        return $callback->bindTo($rowModel);\n    }\n\n    /**\n     * Fill all data to every column.\n     *\n     * @param array $data\n     *\n     * @return mixed\n     */\n    public function fill(array $data)\n    {\n        foreach ($data as $key => &$row) {\n            $this->original = $value = Arr::get($row, $this->name);\n\n            $value = $this->htmlEntityEncode($value);\n\n            Arr::set($row, $this->name, $value);\n\n            if ($this->isDefinedColumn()) {\n                $this->useDefinedColumn();\n            }\n\n            if ($this->hasDisplayCallbacks()) {\n                $value = $this->callDisplayCallbacks($this->original, $key);\n                Arr::set($row, $this->name, $value);\n            }\n        }\n\n        return $data;\n    }\n\n    /**\n     * If current column is a defined column.\n     *\n     * @return bool\n     */\n    protected function isDefinedColumn()\n    {\n        return array_key_exists($this->name, static::$defined);\n    }\n\n    /**\n     * Use a defined column.\n     *\n     * @throws \\Exception\n     */\n    protected function useDefinedColumn()\n    {\n        // clear all display callbacks.\n        $this->displayCallbacks = [];\n\n        $class = static::$defined[$this->name];\n\n        if ($class instanceof Closure) {\n            $this->display($class);\n\n            return;\n        }\n\n        if (!class_exists($class) || !is_subclass_of($class, AbstractDisplayer::class)) {\n            throw new \\Exception(\"Invalid column definition [$class]\");\n        }\n\n        $grid = $this->grid;\n        $column = $this;\n\n        $this->display(function ($value) use ($grid, $column, $class) {\n            /** @var AbstractDisplayer $definition */\n            $definition = new $class($value, $grid, $column, $this);\n\n            return $definition->display();\n        });\n    }\n\n    /**\n     * Convert characters to HTML entities recursively.\n     *\n     * @param array|string|null $item\n     *\n     * @return mixed\n     */\n    protected function htmlEntityEncode($item)\n    {\n        if (is_array($item)) {\n            array_walk_recursive($item, function (&$value) {\n                $value = htmlentities($value ?? '');\n            });\n        } else {\n            $item = htmlentities($item ?? '');\n        }\n\n        return $item;\n    }\n\n    /**\n     * Find a displayer to display column.\n     *\n     * @param string $abstract\n     * @param array  $arguments\n     *\n     * @return $this\n     */\n    protected function resolveDisplayer($abstract, $arguments)\n    {\n        if (array_key_exists($abstract, static::$displayers)) {\n            return $this->callBuiltinDisplayer(static::$displayers[$abstract], $arguments);\n        }\n\n        return $this->callSupportDisplayer($abstract, $arguments);\n    }\n\n    /**\n     * Call Illuminate/Support displayer.\n     *\n     * @param string $abstract\n     * @param array  $arguments\n     *\n     * @return $this\n     */\n    protected function callSupportDisplayer($abstract, $arguments)\n    {\n        return $this->display(function ($value) use ($abstract, $arguments) {\n            if (is_array($value) || $value instanceof Arrayable) {\n                return call_user_func_array([collect($value), $abstract], $arguments);\n            }\n\n            if (is_string($value)) {\n                return call_user_func_array([Str::class, $abstract], array_merge([$value], $arguments));\n            }\n\n            return $value;\n        });\n    }\n\n    /**\n     * Call Builtin displayer.\n     *\n     * @param string $abstract\n     * @param array  $arguments\n     *\n     * @return $this\n     */\n    protected function callBuiltinDisplayer($abstract, $arguments)\n    {\n        if ($abstract instanceof Closure) {\n            return $this->display(function ($value) use ($abstract, $arguments) {\n                return $abstract->call($this, ...array_merge([$value], $arguments));\n            });\n        }\n\n        if (class_exists($abstract) && is_subclass_of($abstract, AbstractDisplayer::class)) {\n            $grid = $this->grid;\n            $column = $this;\n\n            return $this->display(function ($value) use ($abstract, $grid, $column, $arguments) {\n                /** @var AbstractDisplayer $displayer */\n                $displayer = new $abstract($value, $grid, $column, $this);\n\n                return $displayer->display(...$arguments);\n            });\n        }\n\n        return $this;\n    }\n\n    /**\n     * Passes through all unknown calls to builtin displayer or supported displayer.\n     *\n     * Allow fluent calls on the Column object.\n     *\n     * @param string $method\n     * @param array  $arguments\n     *\n     * @return $this\n     */\n    public function __call($method, $arguments)\n    {\n        if ($this->isRelation() && !$this->relationColumn) {\n            $this->name = \"{$this->relation}.$method\";\n            $this->label = $this->formatLabel($arguments[0] ?? null);\n\n            $this->relationColumn = $method;\n\n            return $this;\n        }\n\n        return $this->resolveDisplayer($method, $arguments);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Concerns/CanDoubleClick.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Concerns;\n\nuse Encore\\Admin\\Admin;\n\ntrait CanDoubleClick\n{\n    /**\n     * Double-click grid row to jump to the edit page.\n     *\n     * @return $this\n     */\n    public function enableDblClick()\n    {\n        $script = <<<SCRIPT\n$('body').on('dblclick', 'table#{$this->tableID}>tbody>tr', function(e) {\n    var url = \"{$this->resource()}/\"+$(this).data('key')+\"/edit\";\n    $.admin.redirect(url);\n});\nSCRIPT;\n        Admin::script($script);\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Concerns/CanExportGrid.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Concerns;\n\nuse Encore\\Admin\\Grid;\nuse Encore\\Admin\\Grid\\Exporter;\nuse Encore\\Admin\\Grid\\Exporters\\AbstractExporter;\n\ntrait CanExportGrid\n{\n    /**\n     * Export driver.\n     *\n     * @var string\n     */\n    protected $exporter;\n\n    /**\n     * Handle export request.\n     *\n     * @param bool $forceExport\n     */\n    protected function handleExportRequest($forceExport = false)\n    {\n        if (!$scope = request(Exporter::$queryName)) {\n            return;\n        }\n\n        // clear output buffer.\n        if (ob_get_length()) {\n            ob_end_clean();\n        }\n\n        $this->disablePagination();\n\n        if ($forceExport) {\n            $this->getExporter($scope)->export();\n        }\n    }\n\n    /**\n     * @param string $scope\n     *\n     * @return AbstractExporter\n     */\n    protected function getExporter($scope)\n    {\n        return (new Exporter($this))->resolve($this->exporter)->withScope($scope);\n    }\n\n    /**\n     * Set exporter driver for Grid to export.\n     *\n     * @param $exporter\n     *\n     * @return $this\n     */\n    public function exporter($exporter)\n    {\n        $this->exporter = $exporter;\n\n        return $this;\n    }\n\n    /**\n     * Get the export url.\n     *\n     * @param int  $scope\n     * @param null $args\n     *\n     * @return string\n     */\n    public function getExportUrl($scope = 1, $args = null)\n    {\n        $input = array_merge(request()->all(), Exporter::formatExportQuery($scope, $args));\n\n        if ($constraints = $this->model()->getConstraints()) {\n            $input = array_merge($input, $constraints);\n        }\n\n        return $this->resource().'?'.http_build_query($input);\n    }\n\n    /**\n     * If grid show export btn.\n     *\n     * @return bool\n     */\n    public function showExportBtn()\n    {\n        return $this->option('show_exporter');\n    }\n\n    /**\n     * Disable export.\n     *\n     * @return $this\n     */\n    public function disableExport(bool $disable = true)\n    {\n        return $this->option('show_exporter', !$disable);\n    }\n\n    /**\n     * Render export button.\n     *\n     * @return string\n     */\n    public function renderExportButton()\n    {\n        return (new Grid\\Tools\\ExportButton($this))->render();\n    }\n\n    /**\n     * @param \\Closure $callback\n     */\n    public function export(\\Closure $callback)\n    {\n        if (!$scope = request(Exporter::$queryName)) {\n            return;\n        }\n\n        $this->getExporter($scope)->setCallback($callback);\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Concerns/CanFixColumns.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Concerns;\n\nuse Encore\\Admin\\Grid\\Tools\\FixColumns;\nuse Illuminate\\Support\\Collection;\n\ntrait CanFixColumns\n{\n    /**\n     * @var FixColumns\n     */\n    protected $fixColumns;\n\n    /**\n     * @param int $head\n     * @param int $tail\n     */\n    public function fixColumns(int $head, int $tail = -1)\n    {\n        $this->fixColumns = new FixColumns($this, $head, $tail);\n\n        $this->rendering($this->fixColumns->apply());\n    }\n\n    /**\n     * @return Collection\n     */\n    public function leftVisibleColumns()\n    {\n        return $this->fixColumns->leftColumns();\n    }\n\n    /**\n     * @return Collection\n     */\n    public function rightVisibleColumns()\n    {\n        return $this->fixColumns->rightColumns();\n    }\n}\n"
  },
  {
    "path": "src/Grid/Concerns/CanFixHeader.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Concerns;\n\nuse Encore\\Admin\\Admin;\n\ntrait CanFixHeader\n{\n    public function fixHeader()\n    {\n        Admin::style(\n            <<<'STYLE'\n.wrapper, .grid-box .box-body {\n    overflow: visible;\n}\n\n.grid-table {\n    position: relative;\n    border-collapse: separate;\n}\n\n.grid-table thead tr:first-child th {\n    background: white;\n    position: sticky;\n    top: 0;\n    z-index: 1;\n}\nSTYLE\n        );\n    }\n}\n"
  },
  {
    "path": "src/Grid/Concerns/CanHidesColumns.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Concerns;\n\nuse Encore\\Admin\\Grid;\nuse Encore\\Admin\\Grid\\Tools\\ColumnSelector;\nuse Illuminate\\Support\\Collection;\n\ntrait CanHidesColumns\n{\n    /**\n     * Default columns be hidden.\n     *\n     * @var array\n     */\n    public $hiddenColumns = [];\n\n    /**\n     * Remove column selector on grid.\n     *\n     * @param bool $disable\n     *\n     * @return Grid|mixed\n     */\n    public function disableColumnSelector(bool $disable = true)\n    {\n        return $this->option('show_column_selector', !$disable);\n    }\n\n    /**\n     * @return bool\n     */\n    public function showColumnSelector()\n    {\n        return $this->option('show_column_selector');\n    }\n\n    /**\n     * @return string\n     */\n    public function renderColumnSelector()\n    {\n        return (new ColumnSelector($this))->render();\n    }\n\n    /**\n     * Setting default shown columns on grid.\n     *\n     * @param array|string $columns\n     *\n     * @return $this\n     */\n    public function hideColumns($columns)\n    {\n        if (func_num_args()) {\n            $columns = (array) $columns;\n        } else {\n            $columns = func_get_args();\n        }\n\n        $this->hiddenColumns = array_merge($this->hiddenColumns, $columns);\n\n        return $this;\n    }\n\n    /**\n     * Get visible columns from request query.\n     *\n     * @return array\n     */\n    protected function getVisibleColumnsFromQuery()\n    {\n        $requestColumn = request(ColumnSelector::SELECT_COLUMN_NAME);\n\n        $columns = $requestColumn ? explode(',', $requestColumn) : [];\n\n        return array_filter($columns) ?:\n            array_values(array_diff($this->columnNames, $this->hiddenColumns));\n    }\n\n    /**\n     * Get all visible column instances.\n     *\n     * @return Collection|static\n     */\n    public function visibleColumns()\n    {\n        $visible = $this->getVisibleColumnsFromQuery();\n\n        if (empty($visible)) {\n            return $this->columns;\n        }\n\n        array_push($visible, Grid\\Column::SELECT_COLUMN_NAME, Grid\\Column::ACTION_COLUMN_NAME);\n\n        return $this->columns->filter(function (Grid\\Column $column) use ($visible) {\n            return in_array($column->getName(), $visible);\n        });\n    }\n\n    /**\n     * Get all visible column names.\n     *\n     * @return array\n     */\n    public function visibleColumnNames()\n    {\n        $visible = $this->getVisibleColumnsFromQuery();\n\n        if (empty($visible)) {\n            return $this->columnNames;\n        }\n\n        array_push($visible, Grid\\Column::SELECT_COLUMN_NAME, Grid\\Column::ACTION_COLUMN_NAME);\n\n        return collect($this->columnNames)->filter(function ($column) use ($visible) {\n            return in_array($column, $visible);\n        })->toArray();\n    }\n\n    /**\n     * Get default visible column names.\n     *\n     * @return array\n     */\n    public function getDefaultVisibleColumnNames()\n    {\n        return array_values(\n            array_diff(\n                $this->columnNames,\n                $this->hiddenColumns,\n                [Grid\\Column::SELECT_COLUMN_NAME, Grid\\Column::ACTION_COLUMN_NAME]\n            )\n        );\n    }\n}\n"
  },
  {
    "path": "src/Grid/Concerns/HasActions.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Concerns;\n\nuse Closure;\nuse Encore\\Admin\\Grid;\n\ntrait HasActions\n{\n    /**\n     * Callback for grid actions.\n     *\n     * @var Closure\n     */\n    protected $actionsCallback;\n\n    /**\n     * Actions column display class.\n     *\n     * @var string\n     */\n    protected $actionsClass;\n\n    /**\n     * Set grid action callback.\n     *\n     * @param Closure|string $actions\n     *\n     * @return $this\n     */\n    public function actions($actions)\n    {\n        if ($actions instanceof Closure) {\n            $this->actionsCallback = $actions;\n        }\n\n        return $this;\n    }\n\n    /**\n     * Get action display class.\n     *\n     * @return \\Illuminate\\Config\\Repository|mixed|string\n     */\n    public function getActionClass()\n    {\n        if ($this->actionsClass) {\n            return $this->actionsClass;\n        }\n\n        if ($class = config('admin.grid_action_class')) {\n            return $class;\n        }\n\n        return Grid\\Displayers\\Actions::class;\n    }\n\n    /**\n     * @param string $actionClass\n     *\n     * @return $this\n     */\n    public function setActionClass(string $actionClass)\n    {\n        if (is_subclass_of($actionClass, Grid\\Displayers\\Actions::class) || ($actionClass == Grid\\Displayers\\Actions::class)) {\n            $this->actionsClass = $actionClass;\n        }\n\n        return $this;\n    }\n\n    /**\n     * Disable all actions.\n     *\n     * @return $this\n     */\n    public function disableActions(bool $disable = true)\n    {\n        return $this->option('show_actions', !$disable);\n    }\n\n    /**\n     * Set grid batch-action callback.\n     *\n     * @param Closure $closure\n     *\n     * @return $this\n     */\n    public function batchActions(Closure $closure)\n    {\n        $this->tools(function (Grid\\Tools $tools) use ($closure) {\n            $tools->batch($closure);\n        });\n\n        return $this;\n    }\n\n    /**\n     * @param bool $disable\n     *\n     * @return Grid|mixed\n     */\n    public function disableBatchActions(bool $disable = true)\n    {\n        $this->tools->disableBatchActions($disable);\n\n        return $this->option('show_row_selector', !$disable);\n    }\n\n    /**\n     * Add `actions` column for grid.\n     *\n     * @return void\n     */\n    protected function appendActionsColumn()\n    {\n        if (!$this->option('show_actions')) {\n            return;\n        }\n\n        $this->addColumn(Grid\\Column::ACTION_COLUMN_NAME, trans('admin.action'))\n            ->displayUsing($this->getActionClass(), [$this->actionsCallback]);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Concerns/HasElementNames.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Concerns;\n\ntrait HasElementNames\n{\n    /**\n     * Grid name.\n     *\n     * @var string\n     */\n    protected $name;\n\n    /**\n     * HTML element names.\n     *\n     * @var array\n     */\n    protected $elementNames = [\n        'grid_row'        => 'grid-row',\n        'grid_select_all' => 'grid-select-all',\n        'grid_per_page'   => 'grid-per-pager',\n        'grid_batch'      => 'grid-batch',\n        'export_selected' => 'export-selected',\n        'selected_rows'   => 'selectedRows',\n    ];\n\n    /**\n     * Set name to grid.\n     *\n     * @param string $name\n     *\n     * @return $this\n     */\n    public function setName($name)\n    {\n        $this->name = $name;\n\n        $this->model()->setPerPageName(\"{$name}_{$this->model()->getPerPageName()}\");\n\n        $this->getFilter()->setName($name);\n\n        return $this;\n    }\n\n    /**\n     * Get name of grid.\n     *\n     * @return string\n     */\n    public function getName()\n    {\n        return $this->name;\n    }\n\n    /**\n     * @return string\n     */\n    public function getGridRowName()\n    {\n        return $this->elementNameWithPrefix('grid_row');\n    }\n\n    /**\n     * @return string\n     */\n    public function getSelectAllName()\n    {\n        return $this->elementNameWithPrefix('grid_select_all');\n    }\n\n    /**\n     * @return string\n     */\n    public function getPerPageName()\n    {\n        return $this->elementNameWithPrefix('grid_per_page');\n    }\n\n    /**\n     * @return string\n     */\n    public function getGridBatchName()\n    {\n        return $this->elementNameWithPrefix('grid_batch');\n    }\n\n    /**\n     * @return string\n     */\n    public function getExportSelectedName()\n    {\n        return $this->elementNameWithPrefix('export_selected');\n    }\n\n    /**\n     * @return string\n     */\n    public function getSelectedRowsName()\n    {\n        $elementName = $this->elementNames['selected_rows'];\n\n        if ($this->name) {\n            return sprintf('%s%s', $this->name, ucfirst($elementName));\n        }\n\n        return $elementName;\n    }\n\n    /**\n     * @return string\n     */\n    protected function elementNameWithPrefix($name)\n    {\n        $elementName = $this->elementNames[$name];\n\n        if ($this->name) {\n            return sprintf('%s-%s', $this->name, $elementName);\n        }\n\n        return $elementName;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Concerns/HasFilter.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Concerns;\n\nuse Closure;\nuse Encore\\Admin\\Grid\\Filter;\nuse Illuminate\\Support\\Collection;\n\ntrait HasFilter\n{\n    /**\n     * The grid Filter.\n     *\n     * @var \\Encore\\Admin\\Grid\\Filter\n     */\n    protected $filter;\n\n    /**\n     * Setup grid filter.\n     *\n     * @return $this\n     */\n    protected function initFilter()\n    {\n        $this->filter = new Filter($this->model());\n\n        return $this;\n    }\n\n    /**\n     * Disable grid filter.\n     *\n     * @return $this\n     */\n    public function disableFilter(bool $disable = true)\n    {\n        $this->tools->disableFilterButton($disable);\n\n        return $this->option('show_filter', !$disable);\n    }\n\n    /**\n     * Get filter of Grid.\n     *\n     * @return Filter\n     */\n    public function getFilter()\n    {\n        return $this->filter;\n    }\n\n    /**\n     * Process the grid filter.\n     *\n     * @param bool $toArray\n     *\n     * @return array|Collection|mixed\n     */\n    public function applyFilter($toArray = true)\n    {\n        if ($this->builder) {\n            call_user_func($this->builder, $this);\n        }\n\n        return $this->filter->execute($toArray);\n    }\n\n    /**\n     * Set the grid filter.\n     *\n     * @param Closure $callback\n     */\n    public function filter(Closure $callback)\n    {\n        call_user_func($callback, $this->filter);\n    }\n\n    /**\n     * Render the grid filter.\n     *\n     * @return \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View|string\n     */\n    public function renderFilter()\n    {\n        if (!$this->option('show_filter')) {\n            return '';\n        }\n\n        return $this->filter->render();\n    }\n\n    /**\n     * Expand filter.\n     *\n     * @return $this\n     */\n    public function expandFilter()\n    {\n        $this->filter->expand();\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Concerns/HasFooter.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Concerns;\n\nuse Closure;\nuse Encore\\Admin\\Grid\\Tools\\Footer;\n\ntrait HasFooter\n{\n    /**\n     * @var Closure\n     */\n    protected $footer;\n\n    /**\n     * Set grid footer.\n     *\n     * @param Closure|null $closure\n     *\n     * @return $this|Closure\n     */\n    public function footer(Closure $closure = null)\n    {\n        if (!$closure) {\n            return $this->footer;\n        }\n\n        $this->footer = $closure;\n\n        return $this;\n    }\n\n    /**\n     * Render grid footer.\n     *\n     * @return string\n     */\n    public function renderFooter()\n    {\n        if (!$this->footer) {\n            return '';\n        }\n\n        return (new Footer($this))->render();\n    }\n}\n"
  },
  {
    "path": "src/Grid/Concerns/HasHeader.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Concerns;\n\nuse Closure;\nuse Encore\\Admin\\Grid\\Tools\\Header;\n\ntrait HasHeader\n{\n    /**\n     * @var Closure\n     */\n    protected $header;\n\n    /**\n     * Set grid header.\n     *\n     * @param Closure|null $closure\n     *\n     * @return $this|Closure\n     */\n    public function header(Closure $closure = null)\n    {\n        if (!$closure) {\n            return $this->header;\n        }\n\n        $this->header = $closure;\n\n        return $this;\n    }\n\n    /**\n     * @return string\n     */\n    public function renderHeader()\n    {\n        if (!$this->header) {\n            return '';\n        }\n\n        return (new Header($this))->render();\n    }\n}\n"
  },
  {
    "path": "src/Grid/Concerns/HasHotKeys.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Concerns;\n\nuse Encore\\Admin\\Admin;\n\ntrait HasHotKeys\n{\n    protected function addHotKeyScript()\n    {\n        $filterID = $this->getFilter()->getFilterID();\n\n        $refreshMessage = __('admin.refresh_succeeded');\n\n        $script = <<<SCRIPT\n\n$(document).off('keydown').keydown(function(e) {\n    var tag = e.target.tagName.toLowerCase();\n    \n    if (tag == 'input' || tag == 'textarea' || e.ctrlKey || e.metaKey || e.altKey || e.shiftKey) {\n        return;\n    }\n\n    var \\$box = $(\"#{$this->tableID}\").closest('.box');\n    var \\$current_page = \\$box.find('.pagination .page-item.active');\n\n    switch(e.which) {\n        case 82: // `r` for reload\n            $.admin.reload();\n            $.admin.toastr.success('{$refreshMessage}', '', {positionClass:\"toast-top-center\"});\n            break;\n        case 83: // `s` for search\n            \\$box.find('input.grid-quick-search').trigger('focus');\n            break; \n        case 70: // `f` for open filter\n            \\$box.find('#{$filterID}').toggleClass('hide');\n            break;\n        case 67: // `c` go to create page \n            \\$box.find('.grid-create-btn>a').trigger('click');\n            break; \n        case 37: // `left` for go to prev page\n            \\$current_page.prev().find('a').trigger('click');\n            break;\n        case 39: // `right` for go to next page\n            \\$current_page.next().find('a').trigger('click');\n            break;\n        default: return;\n    }\n    e.preventDefault();\n});\n\nSCRIPT;\n\n        Admin::script($script);\n    }\n\n    public function enableHotKeys()\n    {\n        $this->addHotKeyScript();\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Concerns/HasQuickCreate.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Concerns;\n\nuse Encore\\Admin\\Grid\\Tools\\QuickCreate;\n\ntrait HasQuickCreate\n{\n    protected $hasQuickCreate = false;\n\n    /**\n     * @var QuickCreate\n     */\n    protected $quickCreate;\n\n    /**\n     * @param \\Closure $closure\n     *\n     * @return $this\n     */\n    public function quickCreate(\\Closure $closure)\n    {\n        $this->quickCreate = new QuickCreate($this);\n\n        call_user_func($closure, $this->quickCreate);\n\n        return $this;\n    }\n\n    /**\n     * Indicates grid has quick-create.\n     *\n     * @return bool\n     */\n    public function hasQuickCreate()\n    {\n        return !is_null($this->quickCreate);\n    }\n\n    /**\n     * Render quick-create form.\n     *\n     * @return array|string\n     */\n    public function renderQuickCreate()\n    {\n        $columnCount = $this->visibleColumns()->count();\n\n        return $this->quickCreate->render($columnCount);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Concerns/HasQuickSearch.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Concerns;\n\nuse Encore\\Admin\\Grid\\Column;\nuse Encore\\Admin\\Grid\\Model;\nuse Encore\\Admin\\Grid\\Tools;\nuse Illuminate\\Database\\Eloquent\\Builder;\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Support\\Str;\n\n/**\n * Trait HasQuickSearch.\n *\n * @property Collection $columns\n * @property Tools      $tools\n *\n * @method Model model()\n */\ntrait HasQuickSearch\n{\n    /**\n     * @var string\n     */\n    public static $searchKey = '__search__';\n\n    /**\n     * @var array|string|\\Closure\n     */\n    protected $search;\n\n    /**\n     * @param array|string|\\Closure\n     *\n     * @return Tools\\QuickSearch\n     */\n    public function quickSearch($search = null)\n    {\n        if (func_num_args() > 1) {\n            $this->search = func_get_args();\n        } else {\n            $this->search = $search;\n        }\n\n        return tap(new Tools\\QuickSearch(), function ($search) {\n            $this->tools->append($search);\n        });\n    }\n\n    /**\n     * Apply the search query to the query.\n     *\n     * @return mixed|void\n     */\n    protected function applyQuickSearch()\n    {\n        if (!$query = request()->get(static::$searchKey)) {\n            return;\n        }\n\n        if ($this->search instanceof \\Closure) {\n            return call_user_func($this->search, $this->model(), $query);\n        }\n\n        if (is_string($this->search)) {\n            $this->search = [$this->search];\n        }\n\n        if (is_array($this->search)) {\n            $this->model()->where(function (Builder $builder) use ($query) {\n                foreach ($this->search as $column) {\n                    $this->addWhereLikeBinding($builder, $column, true, '%'.$query.'%');\n                }\n            });\n        } elseif (is_null($this->search)) {\n            $this->model()->where(function (Builder $builder) use ($query) {\n                $this->addWhereBindings($builder, $query);\n            });\n        }\n    }\n\n    /**\n     * Add where bindings.\n     *\n     * @param Builder $builder\n     * @param string  $query\n     */\n    protected function addWhereBindings(Builder $builder, $query)\n    {\n        $queries = preg_split('/\\s(?=([^\"]*\"[^\"]*\")*[^\"]*$)/', trim($query));\n\n        foreach ($this->parseQueryBindings($queries) as list($column, $condition, $or)) {\n            if (preg_match('/(?<not>!?)\\((?<values>.+)\\)/', $condition, $match) !== 0) {\n                $this->addWhereInBinding($builder, $column, $or, (bool) $match['not'], $match['values']);\n                continue;\n            }\n\n            if (preg_match('/\\[(?<start>.*?),(?<end>.*?)]/', $condition, $match) !== 0) {\n                $this->addWhereBetweenBinding($builder, $column, $or, $match['start'], $match['end']);\n                continue;\n            }\n\n            if (preg_match('/(?<function>date|time|day|month|year),(?<value>.*)/', $condition, $match) !== 0) {\n                $this->addWhereDatetimeBinding($builder, $column, $or, $match['function'], $match['value']);\n                continue;\n            }\n\n            if (preg_match('/(?<pattern>%[^%]+%)/', $condition, $match) !== 0) {\n                $this->addWhereLikeBinding($builder, $column, $or, $match['pattern']);\n                continue;\n            }\n\n            if (preg_match('/\\/(?<value>.*)\\//', $condition, $match) !== 0) {\n                $this->addWhereBasicBinding($builder, $column, $or, 'REGEXP', $match['value']);\n                continue;\n            }\n\n            if (preg_match('/(?<operator>>=?|<=?|!=|%){0,1}(?<value>.*)/', $condition, $match) !== 0) {\n                $this->addWhereBasicBinding($builder, $column, $or, $match['operator'], $match['value']);\n                continue;\n            }\n        }\n    }\n\n    /**\n     * Parse quick query bindings.\n     *\n     * @param array $queries\n     *\n     * @return array\n     */\n    protected function parseQueryBindings(array $queries)\n    {\n        $columnMap = $this->columns->mapWithKeys(function (Column $column) {\n            $label = $column->getLabel();\n            $name = $column->getName();\n\n            return [$label => $name, $name => $name];\n        });\n\n        return collect($queries)->map(function ($query) use ($columnMap) {\n            $segments = explode(':', $query, 2);\n\n            if (count($segments) != 2) {\n                return;\n            }\n\n            $or = false;\n\n            list($column, $condition) = $segments;\n\n            if (Str::startsWith($column, '|')) {\n                $or = true;\n                $column = substr($column, 1);\n            }\n\n            $column = $columnMap[$column];\n\n            return [$column, $condition, $or];\n        })->filter()->toArray();\n    }\n\n    /**\n     * Add where like binding to model query.\n     *\n     * @param Builder $builder\n     * @param string  $column\n     * @param bool    $or\n     * @param string  $pattern\n     */\n    protected function addWhereLikeBinding(Builder $builder, string $column, bool $or, string $pattern)\n    {\n        $connectionType = $builder->getModel()->getConnection()->getDriverName();\n        $likeOperator = $connectionType == 'pgsql' ? 'ilike' : 'like';\n\n        $method = $or ? 'orWhere' : 'where';\n\n        $builder->{$method}($column, $likeOperator, $pattern);\n    }\n\n    /**\n     * Add where date time function binding to model query.\n     *\n     * @param Builder $builder\n     * @param string  $column\n     * @param bool    $or\n     * @param string  $function\n     * @param string  $value\n     */\n    protected function addWhereDatetimeBinding(Builder $builder, string $column, bool $or, string $function, string $value)\n    {\n        $method = ($or ? 'orWhere' : 'where').ucfirst($function);\n\n        $builder->{$method}($column, $value);\n    }\n\n    /**\n     * Add where in binding to the model query.\n     *\n     * @param Builder $builder\n     * @param string  $column\n     * @param bool    $or\n     * @param bool    $not\n     * @param string  $values\n     */\n    protected function addWhereInBinding(Builder $builder, string $column, bool $or, bool $not, string $values)\n    {\n        $values = explode(',', $values);\n\n        foreach ($values as $key => $value) {\n            if ($value === 'NULL') {\n                $values[$key] = null;\n            }\n        }\n\n        $where = $or ? 'orWhere' : 'where';\n\n        $method = $where.($not ? 'NotIn' : 'In');\n\n        $builder->{$method}($column, $values);\n    }\n\n    /**\n     * Add where between binding to the model query.\n     *\n     * @param Builder $builder\n     * @param string  $column\n     * @param bool    $or\n     * @param string  $start\n     * @param string  $end\n     */\n    protected function addWhereBetweenBinding(Builder $builder, string $column, bool $or, string $start, string $end)\n    {\n        $method = $or ? 'orWhereBetween' : 'whereBetween';\n\n        $builder->{$method}($column, [$start, $end]);\n    }\n\n    /**\n     * Add where basic binding to the model query.\n     *\n     * @param Builder $builder\n     * @param string  $column\n     * @param bool    $or\n     * @param string  $operator\n     * @param string  $value\n     */\n    protected function addWhereBasicBinding(Builder $builder, string $column, bool $or, string $operator, string $value)\n    {\n        $method = $or ? 'orWhere' : 'where';\n\n        $operator = $operator ?: '=';\n\n        if ($operator == '%') {\n            $operator = 'like';\n            $value = \"%{$value}%\";\n        }\n\n        if ($value === 'NULL') {\n            $value = null;\n        }\n\n        if (Str::startsWith($value, '\"') && Str::endsWith($value, '\"')) {\n            $value = substr($value, 1, -1);\n        }\n\n        $builder->{$method}($column, $operator, $value);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Concerns/HasSelector.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Concerns;\n\nuse Encore\\Admin\\Grid;\nuse Encore\\Admin\\Grid\\Tools\\Selector;\n\n/**\n * @mixin Grid\n */\ntrait HasSelector\n{\n    /**\n     * @var Selector\n     */\n    protected $selector;\n\n    /**\n     * @param \\Closure $closure\n     *\n     * @return $this\n     */\n    public function selector(\\Closure $closure)\n    {\n        $this->selector = new Selector();\n\n        call_user_func($closure, $this->selector);\n\n        $this->header(function () {\n            return $this->renderSelector();\n        });\n\n        return $this;\n    }\n\n    /**\n     * Apply selector query to grid model query.\n     *\n     * @return $this\n     */\n    protected function applySelectorQuery()\n    {\n        if (is_null($this->selector)) {\n            return $this;\n        }\n\n        $active = Selector::parseSelected();\n\n        $this->selector->getSelectors()->each(function ($selector, $column) use ($active) {\n            if (!array_key_exists($column, $active)) {\n                return;\n            }\n\n            $values = $active[$column];\n\n            if ($selector['type'] === 'one') {\n                $values = current($values);\n            }\n\n            if (is_null($selector['query'])) {\n                $this->model()->whereIn($column, (array) $values);\n            } else {\n                call_user_func($selector['query'], $this->model(), $values);\n            }\n        });\n\n        return $this;\n    }\n\n    /**\n     * Render grid selector.\n     *\n     * @return \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View|string\n     */\n    public function renderSelector()\n    {\n        return $this->selector->render();\n    }\n}\n"
  },
  {
    "path": "src/Grid/Concerns/HasTools.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Concerns;\n\nuse Closure;\nuse Encore\\Admin\\Grid\\Tools;\n\ntrait HasTools\n{\n    use HasQuickSearch;\n\n    /**\n     * Header tools.\n     *\n     * @var Tools\n     */\n    public $tools;\n\n    /**\n     * Setup grid tools.\n     *\n     * @return $this\n     */\n    protected function initTools()\n    {\n        $this->tools = new Tools($this);\n\n        return $this;\n    }\n\n    /**\n     * Disable header tools.\n     *\n     * @return $this\n     */\n    public function disableTools(bool $disable = true)\n    {\n        return $this->option('show_tools', !$disable);\n    }\n\n    /**\n     * Setup grid tools.\n     *\n     * @param Closure $callback\n     *\n     * @return void\n     */\n    public function tools(Closure $callback)\n    {\n        call_user_func($callback, $this->tools);\n    }\n\n    /**\n     * Render custom tools.\n     *\n     * @return string\n     */\n    public function renderHeaderTools()\n    {\n        return $this->tools->render();\n    }\n\n    /**\n     * If grid show header tools.\n     *\n     * @return bool\n     */\n    public function showTools()\n    {\n        return $this->option('show_tools');\n    }\n}\n"
  },
  {
    "path": "src/Grid/Concerns/HasTotalRow.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Concerns;\n\nuse Closure;\nuse Encore\\Admin\\Grid\\Tools\\TotalRow;\n\ntrait HasTotalRow\n{\n    /**\n     * @var array\n     */\n    protected $totalRowColumns = [];\n\n    /**\n     * @param string  $column\n     * @param Closure $callback\n     *\n     * @return $this\n     */\n    public function addTotalRow($column, $callback)\n    {\n        $this->totalRowColumns[$column] = $callback;\n\n        return $this;\n    }\n\n    /**\n     * @return \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View|string\n     */\n    public function renderTotalRow($columns = null)\n    {\n        if (empty($this->totalRowColumns)) {\n            return '';\n        }\n\n        $query = $this->model()->getQueryBuilder();\n\n        $totalRow = new TotalRow($query, $this->totalRowColumns);\n\n        $totalRow->setGrid($this);\n\n        if ($columns) {\n            $totalRow->setVisibleColumns($columns);\n        }\n\n        return $totalRow->render();\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/AbstractDisplayer.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Encore\\Admin\\Grid;\nuse Encore\\Admin\\Grid\\Column;\nuse Illuminate\\Database\\Eloquent\\Model;\n\nabstract class AbstractDisplayer\n{\n    /**\n     * @var Grid\n     */\n    protected $grid;\n\n    /**\n     * @var Column\n     */\n    protected $column;\n\n    /**\n     * @var Model\n     */\n    public $row;\n\n    /**\n     * @var mixed\n     */\n    protected $value;\n\n    /**\n     * Create a new displayer instance.\n     *\n     * @param mixed     $value\n     * @param Grid      $grid\n     * @param Column    $column\n     * @param \\stdClass $row\n     */\n    public function __construct($value, Grid $grid, Column $column, $row)\n    {\n        $this->value = $value;\n        $this->grid = $grid;\n        $this->column = $column;\n        $this->row = $row;\n    }\n\n    /**\n     * @return mixed\n     */\n    public function getValue()\n    {\n        return $this->value;\n    }\n\n    /**\n     * @return Grid\n     */\n    public function getGrid()\n    {\n        return $this->grid;\n    }\n\n    /**\n     * @return Column\n     */\n    public function getColumn()\n    {\n        return $this->column;\n    }\n\n    /**\n     * Get key of current row.\n     *\n     * @return mixed\n     */\n    public function getKey()\n    {\n        return $this->row->{$this->grid->getKeyName()};\n    }\n\n    /**\n     * @param mixed $key\n     *\n     * @return mixed\n     */\n    public function getAttribute($key)\n    {\n        return $this->row->getAttribute($key);\n    }\n\n    /**\n     * Get url path of current resource.\n     *\n     * @return string\n     */\n    public function getResource()\n    {\n        return $this->grid->resource();\n    }\n\n    /**\n     * @return string\n     */\n    public function getName()\n    {\n        return $this->getColumn()->getName();\n    }\n\n    /**\n     * @return string\n     */\n    public function getClassName()\n    {\n        return $this->getColumn()->getClassName();\n    }\n\n    /**\n     * `foo.bar.baz` => `foo[bar][baz]`.\n     *\n     * @return string\n     */\n    protected function getPayloadName($name = '')\n    {\n        $keys = collect(explode('.', $name ?: $this->getName()));\n\n        return $keys->shift().$keys->reduce(function ($carry, $val) {\n            return $carry.\"[$val]\";\n        });\n    }\n\n    /**\n     * Get translation.\n     *\n     * @param string $text\n     *\n     * @return string|\\Symfony\\Component\\Translation\\TranslatorInterface\n     */\n    protected function trans($text)\n    {\n        return trans(\"admin.$text\");\n    }\n\n    /**\n     * Display method.\n     *\n     * @return mixed\n     */\n    abstract public function display();\n}\n"
  },
  {
    "path": "src/Grid/Displayers/Actions.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Encore\\Admin\\Admin;\n\nclass Actions extends AbstractDisplayer\n{\n    /**\n     * @var array\n     */\n    protected $appends = [];\n\n    /**\n     * @var array\n     */\n    protected $prepends = [];\n\n    /**\n     * Default actions.\n     *\n     * @var array\n     */\n    protected $actions = ['view', 'edit', 'delete'];\n\n    /**\n     * @var string\n     */\n    protected $resource;\n\n    /**\n     * Disable all actions.\n     *\n     * @var bool\n     */\n    protected $disableAll = false;\n\n    /**\n     * diy translate.\n     *\n     * @var array\n     */\n    protected $trans = [];\n\n    /**\n     * Append a action.\n     *\n     * @param $action\n     *\n     * @return $this\n     */\n    public function append($action)\n    {\n        array_push($this->appends, $action);\n\n        return $this;\n    }\n\n    /**\n     * Prepend a action.\n     *\n     * @param $action\n     *\n     * @return $this\n     */\n    public function prepend($action)\n    {\n        array_unshift($this->prepends, $action);\n\n        return $this;\n    }\n\n    /**\n     * Get route key name of current row.\n     *\n     * @return mixed\n     */\n    public function getRouteKey()\n    {\n        return $this->row->{$this->row->getRouteKeyName()};\n    }\n\n    /**\n     * Disable view action.\n     *\n     * @return $this\n     */\n    public function disableView(bool $disable = true)\n    {\n        if ($disable) {\n            array_delete($this->actions, 'view');\n        } elseif (!in_array('view', $this->actions)) {\n            array_push($this->actions, 'view');\n        }\n\n        return $this;\n    }\n\n    /**\n     * Disable delete.\n     *\n     * @return $this.\n     */\n    public function disableDelete(bool $disable = true)\n    {\n        if ($disable) {\n            array_delete($this->actions, 'delete');\n        } elseif (!in_array('delete', $this->actions)) {\n            array_push($this->actions, 'delete');\n        }\n\n        return $this;\n    }\n\n    /**\n     * Disable edit.\n     *\n     * @return $this.\n     */\n    public function disableEdit(bool $disable = true)\n    {\n        if ($disable) {\n            array_delete($this->actions, 'edit');\n        } elseif (!in_array('edit', $this->actions)) {\n            array_push($this->actions, 'edit');\n        }\n\n        return $this;\n    }\n\n    /**\n     * Disable all actions.\n     *\n     * @return $this\n     */\n    public function disableAll()\n    {\n        $this->disableAll = true;\n\n        return $this;\n    }\n\n    /**\n     * Set resource of current resource.\n     *\n     * @param $resource\n     *\n     * @return $this\n     */\n    public function setResource($resource)\n    {\n        $this->resource = $resource;\n\n        return $this;\n    }\n\n    /**\n     * Get resource of current resource.\n     *\n     * @return string\n     */\n    public function getResource()\n    {\n        return $this->resource ?: parent::getResource();\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function display($callback = null)\n    {\n        if ($callback instanceof \\Closure) {\n            $callback->call($this, $this);\n        }\n\n        if ($this->disableAll) {\n            return '';\n        }\n\n        $actions = $this->prepends;\n\n        foreach ($this->actions as $action) {\n            $method = 'render'.ucfirst($action);\n            array_push($actions, $this->{$method}());\n        }\n\n        $actions = array_merge($actions, $this->appends);\n\n        return implode('', $actions);\n    }\n\n    /**\n     * Render view action.\n     *\n     * @return string\n     */\n    protected function renderView()\n    {\n        return <<<EOT\n<a href=\"{$this->getResource()}/{$this->getRouteKey()}\" class=\"{$this->grid->getGridRowName()}-view\">\n    <i class=\"fa fa-eye\"></i>\n</a>\nEOT;\n    }\n\n    /**\n     * Render edit action.\n     *\n     * @return string\n     */\n    protected function renderEdit()\n    {\n        return <<<EOT\n<a href=\"{$this->getResource()}/{$this->getRouteKey()}/edit\" class=\"{$this->grid->getGridRowName()}-edit\">\n    <i class=\"fa fa-edit\"></i>\n</a>\nEOT;\n    }\n\n    /**\n     * Render delete action.\n     *\n     * @return string\n     */\n    protected function renderDelete()\n    {\n        $this->setupDeleteScript();\n\n        return <<<EOT\n<a href=\"javascript:void(0);\" data-id=\"{$this->getKey()}\" class=\"{$this->grid->getGridRowName()}-delete\">\n    <i class=\"fa fa-trash\"></i>\n</a>\nEOT;\n    }\n\n    protected function setupDeleteScript()\n    {\n        $trans = [\n            'delete_confirm' => trans('admin.delete_confirm'),\n            'confirm'        => trans('admin.confirm'),\n            'cancel'         => trans('admin.cancel'),\n        ];\n\n        $trans = array_merge($trans, $this->trans);\n\n        $script = <<<SCRIPT\n\n$('.{$this->grid->getGridRowName()}-delete').unbind('click').click(function() {\n\n    var id = $(this).data('id');\n\n    swal({\n        title: \"{$trans['delete_confirm']}\",\n        type: \"warning\",\n        showCancelButton: true,\n        confirmButtonColor: \"#DD6B55\",\n        confirmButtonText: \"{$trans['confirm']}\",\n        showLoaderOnConfirm: true,\n        cancelButtonText: \"{$trans['cancel']}\",\n        preConfirm: function() {\n            return new Promise(function(resolve) {\n                $.ajax({\n                    method: 'post',\n                    url: '{$this->getResource()}/' + id,\n                    data: {\n                        _method:'delete',\n                        _token:LA.token,\n                    },\n                    success: function (data) {\n                        $.pjax.reload('#pjax-container');\n\n                        resolve(data);\n                    }\n                });\n            });\n        }\n    }).then(function(result) {\n        var data = result.value;\n        if (typeof data === 'object') {\n            if (data.status) {\n                swal(data.message, '', 'success');\n            } else {\n                swal(data.message, '', 'error');\n            }\n        }\n    });\n});\n\nSCRIPT;\n\n        Admin::script($script);\n    }\n\n    /**\n     * diy delete translate.\n     *\n     * @param $tans\n     */\n    public function setTrans($tans)\n    {\n        $this->trans = $tans;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/Badge.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Illuminate\\Contracts\\Support\\Arrayable;\nuse Illuminate\\Support\\Arr;\n\nclass Badge extends AbstractDisplayer\n{\n    public function display($style = 'red')\n    {\n        if ($this->value instanceof Arrayable) {\n            $this->value = $this->value->toArray();\n        }\n\n        return collect((array) $this->value)->map(function ($name) use ($style) {\n            if (is_array($style)) {\n                $style = Arr::get($style, $this->getColumn()->getOriginal(), 'red');\n            }\n\n            return \"<span class='badge bg-{$style}'>$name</span>\";\n        })->implode('&nbsp;');\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/BelongsTo.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Grid\\Selectable;\n\nclass BelongsTo extends AbstractDisplayer\n{\n    /**\n     * @param int $multiple\n     *\n     * @return string\n     */\n    protected function getLoadUrl($selectable, $multiple = 0)\n    {\n        $selectable = str_replace('\\\\', '_', $selectable);\n        $args = [$multiple];\n\n        return route(admin_get_route('handle-selectable'), compact('selectable', 'args'));\n    }\n\n    /**\n     * @return mixed\n     */\n    protected function getOriginalData()\n    {\n        return $this->getColumn()->getOriginal();\n    }\n\n    /**\n     * @param string $selectable\n     * @param string $column\n     *\n     * @return string\n     */\n    public function display($selectable = null, $column = '')\n    {\n        if (!class_exists($selectable) || !is_subclass_of($selectable, Selectable::class)) {\n            throw new \\InvalidArgumentException(\n                \"[Class [{$selectable}] must be a sub class of Encore\\Admin\\Grid\\Selectable\"\n            );\n        }\n\n        return Admin::component('admin::grid.inline-edit.belongsto', [\n            'modal'     => sprintf('modal-grid-selector-%s', $this->getClassName()),\n            'key'       => $this->getKey(),\n            'original'  => $this->getOriginalData(),\n            'value'     => $this->getValue(),\n            'resource'  => $this->getResource(),\n            'name'      => $column ?: $this->getName(),\n            'relation'  => get_called_class(),\n            'url'       => $this->getLoadUrl($selectable, get_called_class() == BelongsToMany::class),\n        ]);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/BelongsToMany.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsToMany as Relation;\nuse Illuminate\\Support\\Arr;\n\nclass BelongsToMany extends BelongsTo\n{\n    /**\n     * Other key for many-to-many relation.\n     *\n     * @var string\n     */\n    protected static $otherKey = [];\n\n    /**\n     * Get other key for this many-to-many relation.\n     *\n     * @throws \\Exception\n     *\n     * @return string\n     */\n    protected function getOtherKey()\n    {\n        if (isset(static::$otherKey[$this->getName()])) {\n            return static::$otherKey[$this->getName()];\n        }\n\n        $model = $this->getGrid()->model()->getOriginalModel();\n\n        if (is_callable([$model, $this->getName()]) &&\n            ($relation = $model->{$this->getName()}()) instanceof Relation\n        ) {\n            /* @var Relation $relation */\n            $fullKey = $relation->getQualifiedRelatedPivotKeyName();\n            $fullKeyArray = explode('.', $fullKey);\n\n            return static::$otherKey[$this->getName()] = end($fullKeyArray);\n        }\n\n        throw new \\Exception('Column of this field must be a `BelongsToMany` relation.');\n    }\n\n    /**\n     * @throws \\Exception\n     *\n     * @return false|string|void\n     */\n    protected function getOriginalData()\n    {\n        $relations = $this->getColumn()->getOriginal();\n\n        if (is_string($relations)) {\n            $data = explode(',', $relations);\n        }\n\n        if (!is_array($relations)) {\n            return;\n        }\n\n        $first = current($relations);\n\n        if (is_null($first)) {\n            $data = null;\n\n        // MultipleSelect value store as an ont-to-many relationship.\n        } elseif (is_array($first)) {\n            foreach ($relations as $relation) {\n                $data[] = Arr::get($relation, \"pivot.{$this->getOtherKey()}\");\n            }\n\n            // MultipleSelect value store as a column.\n        } else {\n            $data = $relations;\n        }\n\n        return json_encode($data);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/Button.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nclass Button extends AbstractDisplayer\n{\n    public function display($style = null)\n    {\n        $style = collect((array) $style)->map(function ($style) {\n            return 'btn-'.$style;\n        })->implode(' ');\n\n        return \"<span class='btn $style'>{$this->value}</span>\";\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/Carousel.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Encore\\Admin\\Widgets\\Carousel as CarouselWidget;\nuse Illuminate\\Contracts\\Support\\Arrayable;\nuse Illuminate\\Support\\Facades\\Storage;\n\nclass Carousel extends AbstractDisplayer\n{\n    public function display(int $width = 300, int $height = 200, $server = '')\n    {\n        if ($this->value instanceof Arrayable) {\n            $this->value = $this->value->toArray();\n        }\n\n        $this->value = array_values($this->value);\n\n        if (empty($this->value)) {\n            return '';\n        }\n\n        $images = collect((array) $this->value)->filter()->map(function ($path) use ($server) {\n            if (url()->isValidUrl($path) || strpos($path, 'data:image') === 0) {\n                $image = $path;\n            } elseif ($server) {\n                $image = rtrim($server, '/').'/'.ltrim($path, '/');\n            } else {\n                $image = Storage::disk(config('admin.upload.disk'))->url($path);\n            }\n\n            $caption = '';\n\n            return compact('image', 'caption');\n        });\n\n        $id = sprintf('carousel-%s-%s', $this->getName(), $this->getKey());\n\n        return (new CarouselWidget($images))->width($width)->height($height)->id($id);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/Checkbox.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Encore\\Admin\\Admin;\nuse Illuminate\\Support\\Arr;\n\nclass Checkbox extends AbstractDisplayer\n{\n    public function display($options = [])\n    {\n        return Admin::component('admin::grid.inline-edit.checkbox', [\n            'key'      => $this->getKey(),\n            'name'     => $this->getPayloadName(),\n            'resource' => $this->getResource(),\n            'trigger'  => \"ie-trigger-{$this->getClassName()}\",\n            'target'   => \"ie-content-{$this->getClassName()}-{$this->getKey()}\",\n            'value'    => json_encode($this->getValue()),\n            'display'  => implode(';', Arr::only($options, $this->getValue())),\n            'options'  => $options,\n        ]);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/ContextMenuActions.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nclass ContextMenuActions extends DropdownActions\n{\n    protected $view = 'admin::grid.actions.contextmenu';\n}\n"
  },
  {
    "path": "src/Grid/Displayers/Copyable.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Encore\\Admin\\Facades\\Admin;\n\n/**\n * Class Copyable.\n *\n * @see https://codepen.io/shaikmaqsood/pen/XmydxJ\n */\nclass Copyable extends AbstractDisplayer\n{\n    protected function addScript()\n    {\n        $script = <<<SCRIPT\n$('#{$this->grid->tableID}').on('click','.grid-column-copyable',(function (e) {\n    var content = $(this).data('content');\n    \n    var temp = $('<input>');\n    \n    $(\"body\").append(temp);\n    temp.val(content).select();\n    document.execCommand(\"copy\");\n    temp.remove();\n    \n    $(this).tooltip('show');\n}));\nSCRIPT;\n\n        Admin::script($script);\n    }\n\n    public function display()\n    {\n        $this->addScript();\n\n        $content = $this->getColumn()->getOriginal();\n\n        return <<<HTML\n<a href=\"javascript:void(0);\" class=\"grid-column-copyable text-muted\" data-content=\"{$content}\" title=\"Copied!\" data-placement=\"bottom\">\n    <i class=\"fa fa-copy\"></i>\n</a>&nbsp;{$this->getValue()}\nHTML;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/Datetime.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Encore\\Admin\\Admin;\n\nclass Datetime extends AbstractDisplayer\n{\n    public function display($format = '')\n    {\n        return Admin::component('admin::grid.inline-edit.datetime', [\n            'key'      => $this->getKey(),\n            'value'    => $this->getValue(),\n            'display'  => $this->getValue(),\n            'name'     => $this->getPayloadName(),\n            'resource' => $this->getResource(),\n            'trigger'  => \"ie-trigger-{$this->getClassName()}\",\n            'target'   => \"ie-template-{$this->getClassName()}\",\n\n            'format'   => $format,\n            'locale'   => config('app.locale'),\n        ]);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/Downloadable.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Illuminate\\Contracts\\Support\\Arrayable;\nuse Illuminate\\Support\\Facades\\Storage;\n\nclass Downloadable extends AbstractDisplayer\n{\n    public function display($server = '')\n    {\n        if ($this->value instanceof Arrayable) {\n            $this->value = $this->value->toArray();\n        }\n\n        return collect((array) $this->value)->filter()->map(function ($value) use ($server) {\n            if (empty($value)) {\n                return '';\n            }\n\n            if (url()->isValidUrl($value)) {\n                $src = $value;\n            } elseif ($server) {\n                $src = rtrim($server, '/').'/'.ltrim($value, '/');\n            } else {\n                $src = Storage::disk(config('admin.upload.disk'))->url($value);\n            }\n\n            $name = basename($value);\n\n            return <<<HTML\n<a href='$src' download='{$name}' target='_blank' class='text-muted'>\n    <i class=\"fa fa-download\"></i> {$name}\n</a>\nHTML;\n        })->implode('<br>');\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/DropdownActions.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Encore\\Admin\\Actions\\RowAction;\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Grid\\Actions\\Delete;\nuse Encore\\Admin\\Grid\\Actions\\Edit;\nuse Encore\\Admin\\Grid\\Actions\\Show;\n\nclass DropdownActions extends Actions\n{\n    protected $view = 'admin::grid.actions.dropdown';\n\n    /**\n     * @var array\n     */\n    protected $custom = [];\n\n    /**\n     * @var array\n     */\n    protected $default = [];\n\n    /**\n     * @var array\n     */\n    protected $defaultClass = [Edit::class, Show::class, Delete::class];\n\n    /**\n     * @param RowAction $action\n     *\n     * @return $this\n     */\n    public function add(RowAction $action)\n    {\n        $this->prepareAction($action);\n\n        array_push($this->custom, $action);\n\n        return $this;\n    }\n\n    /**\n     * Prepend default `edit` `view` `delete` actions.\n     */\n    protected function prependDefaultActions()\n    {\n        foreach ($this->defaultClass as $class) {\n            /** @var RowAction $action */\n            $action = new $class();\n\n            $this->prepareAction($action);\n\n            array_push($this->default, $action);\n        }\n    }\n\n    /**\n     * @param RowAction $action\n     */\n    protected function prepareAction(RowAction $action)\n    {\n        $action->setGrid($this->grid)\n            ->setColumn($this->column)\n            ->setRow($this->row);\n    }\n\n    /**\n     * Disable view action.\n     *\n     * @param bool $disable\n     *\n     * @return $this\n     */\n    public function disableView(bool $disable = true)\n    {\n        if ($disable) {\n            array_delete($this->defaultClass, Show::class);\n        } elseif (!in_array(Show::class, $this->defaultClass)) {\n            array_push($this->defaultClass, Show::class);\n        }\n\n        return $this;\n    }\n\n    /**\n     * Disable delete.\n     *\n     * @param bool $disable\n     *\n     * @return $this.\n     */\n    public function disableDelete(bool $disable = true)\n    {\n        if ($disable) {\n            array_delete($this->defaultClass, Delete::class);\n        } elseif (!in_array(Delete::class, $this->defaultClass)) {\n            array_push($this->defaultClass, Delete::class);\n        }\n\n        return $this;\n    }\n\n    /**\n     * Disable edit.\n     *\n     * @param bool $disable\n     *\n     * @return $this\n     */\n    public function disableEdit(bool $disable = true)\n    {\n        if ($disable) {\n            array_delete($this->defaultClass, Edit::class);\n        } elseif (!in_array(Edit::class, $this->defaultClass)) {\n            array_push($this->defaultClass, Edit::class);\n        }\n\n        return $this;\n    }\n\n    /**\n     * @param null|\\Closure $callback\n     *\n     * @return \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View|string\n     */\n    public function display($callback = null)\n    {\n        if ($callback instanceof \\Closure) {\n            $callback->call($this, $this);\n        }\n\n        if ($this->disableAll) {\n            return '';\n        }\n\n        $this->prependDefaultActions();\n\n        $variables = [\n            'default' => $this->default,\n            'custom'  => $this->custom,\n        ];\n\n        if (empty($variables['default']) && empty($variables['custom'])) {\n            return;\n        }\n\n        return Admin::component($this->view, $variables);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/Editable.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Encore\\Admin\\Admin;\nuse Illuminate\\Support\\Arr;\n\nclass Editable extends AbstractDisplayer\n{\n    /**\n     * @var array\n     */\n    protected $arguments = [];\n\n    /**\n     * Type of editable.\n     *\n     * @var string\n     */\n    protected $type = '';\n\n    /**\n     * Options of editable function.\n     *\n     * @var array\n     */\n    protected $options = [\n        'emptytext'  => '<i class=\"fa fa-pencil\"></i>',\n    ];\n\n    /**\n     * @var array\n     */\n    protected $attributes = [];\n\n    /**\n     * Add options for editable.\n     *\n     * @param array $options\n     */\n    public function addOptions($options = [])\n    {\n        $this->options = array_merge($this->options, $options);\n    }\n\n    /**\n     * Add attributes for editable.\n     *\n     * @param array $attributes\n     */\n    public function addAttributes($attributes = [])\n    {\n        $this->attributes = array_merge($this->attributes, $attributes);\n    }\n\n    /**\n     * Text type editable.\n     */\n    public function text()\n    {\n    }\n\n    /**\n     * Textarea type editable.\n     */\n    public function textarea()\n    {\n    }\n\n    /**\n     * Select type editable.\n     *\n     * @param array|\\Closure $options\n     */\n    public function select($options = [])\n    {\n        $useClosure = false;\n\n        if ($options instanceof \\Closure) {\n            $useClosure = true;\n            $options = $options->call($this, $this->row);\n        }\n\n        $source = [];\n\n        foreach ($options as $value => $text) {\n            $source[] = compact('value', 'text');\n        }\n\n        if ($useClosure) {\n            $this->addAttributes(['data-source' => json_encode($source)]);\n        } else {\n            $this->addOptions(compact('source'));\n        }\n    }\n\n    /**\n     * Date type editable.\n     */\n    public function date()\n    {\n        $this->combodate();\n    }\n\n    /**\n     * Datetime type editable.\n     */\n    public function datetime()\n    {\n        $this->combodate('YYYY-MM-DD HH:mm:ss');\n    }\n\n    /**\n     * Year type editable.\n     */\n    public function year()\n    {\n        $this->combodate('YYYY');\n    }\n\n    /**\n     * Month type editable.\n     */\n    public function month()\n    {\n        $this->combodate('MM');\n    }\n\n    /**\n     * Day type editable.\n     */\n    public function day()\n    {\n        $this->combodate('DD');\n    }\n\n    /**\n     * Time type editable.\n     */\n    public function time()\n    {\n        $this->combodate('HH:mm:ss');\n    }\n\n    /**\n     * Combodate type editable.\n     *\n     * @param string $format\n     */\n    public function combodate($format = 'YYYY-MM-DD')\n    {\n        $this->type = 'combodate';\n\n        $this->addOptions([\n            'format'     => $format,\n            'viewformat' => $format,\n            'template'   => $format,\n            'combodate'  => [\n                'maxYear' => 2035,\n            ],\n        ]);\n    }\n\n    /**\n     * @param array $arguments\n     */\n    protected function buildEditableOptions(array $arguments = [])\n    {\n        $this->type = Arr::get($arguments, 0, 'text');\n\n        call_user_func_array([$this, $this->type], array_slice($arguments, 1));\n    }\n\n    /**\n     * @return string\n     */\n    public function display()\n    {\n        $this->options['name'] = $column = $this->getName();\n\n        $class = 'grid-editable-'.str_replace(['.', '#', '[', ']'], '-', $column);\n\n        $this->buildEditableOptions(func_get_args());\n\n        $options = json_encode($this->options);\n\n        $options = substr($options, 0, -1).<<<'STR'\n    ,\n    \"success\":function(response, newValue){\n        if (response.status){\n            $.admin.toastr.success(response.message, '', {positionClass:\"toast-top-center\"});\n        } else {\n            $.admin.toastr.error(response.message, '', {positionClass:\"toast-top-center\"});\n        }\n    }\n}\nSTR;\n\n        Admin::script(\"$('.$class').editable($options);\");\n\n        $this->value = htmlentities($this->value ?? '');\n\n        $attributes = [\n            'href'       => '#',\n            'class'      => \"$class\",\n            'data-type'  => $this->type,\n            'data-pk'    => \"{$this->getKey()}\",\n            'data-url'   => \"{$this->getResource()}/{$this->getKey()}\",\n            'data-value' => \"{$this->value}\",\n        ];\n\n        if (!empty($this->attributes)) {\n            $attributes = array_merge($attributes, $this->attributes);\n        }\n\n        $attributes = collect($attributes)->map(function ($attribute, $name) {\n            return \"$name='$attribute'\";\n        })->implode(' ');\n\n        $html = $this->type === 'select' ? '' : $this->value;\n\n        return \"<a $attributes>{$html}</a>\";\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/Expand.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Grid\\Simple;\nuse Illuminate\\Contracts\\Support\\Renderable;\n\nclass Expand extends AbstractDisplayer\n{\n    protected $renderable;\n\n    public function display($callback = null, $isExpand = false)\n    {\n        $html = '';\n        $async = false;\n        $loadGrid = false;\n\n        if (is_subclass_of($callback, Renderable::class)) {\n            $this->renderable = $callback;\n            $async = true;\n            $loadGrid = is_subclass_of($callback, Simple::class);\n        } else {\n            $html = call_user_func_array($callback->bindTo($this->row), [$this->row]);\n        }\n\n        return Admin::component('admin::components.column-expand', [\n            'key'           => $this->getKey(),\n            'url'           => $this->getLoadUrl(),\n            'name'          => str_replace('.', '-', $this->getName()).'-'.$this->getKey(),\n            'html'          => $html,\n            'value'         => $this->value,\n            'async'         => $async,\n            'expand'        => $isExpand,\n            'loadGrid'      => $loadGrid,\n            'elementClass'  => \"grid-expand-{$this->grid->getGridRowName()}\",\n        ]);\n    }\n\n    /**\n     * @param int $multiple\n     *\n     * @return string\n     */\n    protected function getLoadUrl()\n    {\n        $renderable = str_replace('\\\\', '_', $this->renderable);\n\n        return route('admin.handle-renderable', compact('renderable'));\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/Image.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Illuminate\\Contracts\\Support\\Arrayable;\nuse Illuminate\\Support\\Facades\\Storage;\n\nclass Image extends AbstractDisplayer\n{\n    public function display($server = '', $width = 200, $height = 200)\n    {\n        if ($this->value instanceof Arrayable) {\n            $this->value = $this->value->toArray();\n        }\n\n        return collect((array) $this->value)->filter()->map(function ($path) use ($server, $width, $height) {\n            if (url()->isValidUrl($path) || strpos($path, 'data:image') === 0) {\n                $src = $path;\n            } elseif ($server) {\n                $src = rtrim($server, '/').'/'.ltrim($path, '/');\n            } else {\n                $src = Storage::disk(config('admin.upload.disk'))->url($path);\n            }\n\n            return \"<img src='$src' style='max-width:{$width}px;max-height:{$height}px' class='img img-thumbnail' />\";\n        })->implode('&nbsp;');\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/Input.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Encore\\Admin\\Admin;\n\nclass Input extends AbstractDisplayer\n{\n    public function display($mask = '')\n    {\n        return Admin::component('admin::grid.inline-edit.input', [\n            'key'      => $this->getKey(),\n            'value'    => $this->getValue(),\n            'display'  => $this->getValue(),\n            'name'     => $this->getPayloadName(),\n            'resource' => $this->getResource(),\n            'trigger'  => \"ie-trigger-{$this->getClassName()}\",\n            'target'   => \"ie-template-{$this->getClassName()}\",\n            'mask'     => $mask,\n        ]);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/Label.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Illuminate\\Contracts\\Support\\Arrayable;\nuse Illuminate\\Support\\Arr;\n\nclass Label extends AbstractDisplayer\n{\n    public function display($style = 'success')\n    {\n        if ($this->value instanceof Arrayable) {\n            $this->value = $this->value->toArray();\n        }\n\n        return collect((array) $this->value)->map(function ($item) use ($style) {\n            if (is_array($style)) {\n                $columnValue = $this->getColumn()->getOriginal();\n\n                if (is_string($columnValue) || is_int($columnValue) || is_bool($columnValue)) {\n                    $columnValue = is_bool($columnValue) ? (int) $columnValue : $columnValue;\n\n                    $style = Arr::get($style, $columnValue, 'success');\n                } else {\n                    $style = Arr::get($style, $item, 'success');\n                }\n            }\n\n            return \"<span class='label label-{$style}'>$item</span>\";\n        })->implode('&nbsp;');\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/Limit.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Encore\\Admin\\Facades\\Admin;\nuse Illuminate\\Support\\Str;\n\nclass Limit extends AbstractDisplayer\n{\n    protected function addScript()\n    {\n        $script = <<<'JS'\n$('.limit-more').click(function () {\n    $(this).parent('.limit-text').toggleClass('hide').siblings().toggleClass('hide');\n});\nJS;\n\n        Admin::script($script);\n    }\n\n    public function display($limit = 100, $end = '...')\n    {\n        $this->addScript();\n\n        $value = Str::limit($this->value, $limit, $end);\n\n        $original = $this->getColumn()->getOriginal();\n\n        if ($value == $original) {\n            return $value;\n        }\n\n        return <<<HTML\n<div class=\"limit-text\">\n    <span class=\"text\">{$value}</span>\n    &nbsp;<a href=\"javascript:void(0);\" class=\"limit-more\">&nbsp;<i class=\"fa fa-angle-double-down\"></i></a>\n</div>\n<div class=\"limit-text hide\">\n    <span class=\"text\">{$original}</span>\n    &nbsp;<a href=\"javascript:void(0);\" class=\"limit-more\">&nbsp;<i class=\"fa fa-angle-double-up\"></i></a>\n</div>\nHTML;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/Link.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nclass Link extends AbstractDisplayer\n{\n    public function display($callback = '', $target = '_blank')\n    {\n        if ($callback instanceof \\Closure) {\n            $callback = $callback->bindTo($this->row);\n            $href = call_user_func_array($callback, [$this->row]);\n        } else {\n            $href = $callback ?: $this->value;\n        }\n\n        return \"<a href='$href' target='$target'>{$this->value}</a>\";\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/Modal.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Grid\\Simple;\nuse Illuminate\\Contracts\\Support\\Renderable;\n\nclass Modal extends AbstractDisplayer\n{\n    /**\n     * @var string\n     */\n    protected $renderable;\n\n    /**\n     * @param int $multiple\n     *\n     * @return string\n     */\n    protected function getLoadUrl()\n    {\n        $renderable = str_replace('\\\\', '_', $this->renderable);\n\n        return route(admin_get_route('handle-renderable'), compact('renderable'));\n    }\n\n    /**\n     * @param \\Closure|string $callback\n     *\n     * @return mixed|string\n     */\n    public function display($callback = null)\n    {\n        if (func_num_args() == 2) {\n            list($title, $callback) = func_get_args();\n        } elseif (func_num_args() == 1) {\n            $title = $this->trans('title');\n        }\n\n        $html = '';\n\n        if ($async = is_subclass_of($callback, Renderable::class)) {\n            $this->renderable = $callback;\n        } else {\n            $html = call_user_func_array($callback->bindTo($this->row), [$this->row]);\n        }\n\n        return Admin::component('admin::components.column-modal', [\n            'url'     => $this->getLoadUrl(),\n            'async'   => $async,\n            'grid'    => is_subclass_of($callback, Simple::class),\n            'title'   => $title,\n            'html'    => $html,\n            'key'     => $this->getKey(),\n            'value'   => $this->value,\n            'name'    => $this->getKey().'-'.str_replace('.', '_', $this->getColumn()->getName()),\n        ]);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/MultipleSelect.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Encore\\Admin\\Admin;\nuse Illuminate\\Support\\Arr;\n\nclass MultipleSelect extends AbstractDisplayer\n{\n    public function display($options = [])\n    {\n        return Admin::component('admin::grid.inline-edit.multiple-select', [\n            'key'      => $this->getKey(),\n            'name'     => $this->getPayloadName(),\n            'value'    => json_encode($this->getValue()),\n            'resource' => $this->getResource(),\n            'trigger'  => \"ie-trigger-{$this->getClassName()}\",\n            'target'   => \"ie-template-{$this->getClassName()}\",\n            'display'  => implode(';', Arr::only($options, $this->getValue())),\n            'options'  => $options,\n        ]);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/Orderable.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Encore\\Admin\\Admin;\n\nclass Orderable extends AbstractDisplayer\n{\n    public function display()\n    {\n        if (!trait_exists('\\Spatie\\EloquentSortable\\SortableTrait')) {\n            throw new \\Exception('To use orderable grid, please install package [spatie/eloquent-sortable] first.');\n        }\n\n        Admin::script($this->script());\n\n        return <<<EOT\n\n<div class=\"btn-group\">\n    <button type=\"button\" class=\"btn btn-xs btn-info {$this->grid->getGridRowName()}-orderable\" data-id=\"{$this->getKey()}\" data-direction=\"1\">\n        <i class=\"fa fa-caret-up fa-fw\"></i>\n    </button>\n    <button type=\"button\" class=\"btn btn-xs btn-default {$this->grid->getGridRowName()}-orderable\" data-id=\"{$this->getKey()}\" data-direction=\"0\">\n        <i class=\"fa fa-caret-down fa-fw\"></i>\n    </button>\n</div>\n\nEOT;\n    }\n\n    protected function script()\n    {\n        return <<<EOT\n\n$('.{$this->grid->getGridRowName()}-orderable').on('click', function() {\n\n    var key = $(this).data('id');\n    var direction = $(this).data('direction');\n\n    $.post('{$this->getResource()}/' + key, {_method:'PUT', _token:LA.token, _orderable:direction}, function(data){\n        if (data.status) {\n            $.pjax.reload('#pjax-container');\n            toastr.success(data.message);\n        }\n    });\n\n});\nEOT;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/Prefix.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nclass Prefix extends AbstractDisplayer\n{\n    public function display($prefix = null, $delimiter = '&nbsp;')\n    {\n        if ($prefix instanceof \\Closure) {\n            $prefix = $prefix->call($this->row, $this->getValue(), $this->getColumn()->getOriginal());\n        }\n\n        return <<<HTML\n{$prefix}{$delimiter}{$this->getValue()}\nHTML;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/ProgressBar.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nclass ProgressBar extends AbstractDisplayer\n{\n    public function display($style = 'primary', $size = 'sm', $max = 100)\n    {\n        $style = collect((array) $style)->map(function ($style) {\n            return 'progress-bar-'.$style;\n        })->implode(' ');\n\n        $this->value = (int) $this->value;\n\n        return <<<EOT\n<div class=\"row\" style=\"min-width: 100px;\">\n    <span class=\"col-sm-3\" style=\"color:#777;\">{$this->value}%</span>\n    <div class=\"progress progress-$size col-sm-9\" style=\"padding-left: 0;padding-right: 0;width: 100px;\"> \n        <div class=\"progress-bar $style\" role=\"progressbar\" aria-valuenow=\"{$this->value}\" aria-valuemin=\"0\" aria-valuemax=\"$max\" style=\"width: {$this->value}%\">\n        </div>\n    </div>\n</div>\nEOT;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/QRCode.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Encore\\Admin\\Facades\\Admin;\n\n/**\n * Class QRCode.\n */\nclass QRCode extends AbstractDisplayer\n{\n    protected function addScript()\n    {\n        $script = <<<'SCRIPT'\n$('.grid-column-qrcode').popover({\n    html: true,\n    container: 'body',\n    trigger: 'focus'\n});\nSCRIPT;\n\n        Admin::script($script);\n    }\n\n    public function display($formatter = null, $width = 150, $height = 150)\n    {\n        $this->addScript();\n\n        $content = $this->getColumn()->getOriginal();\n\n        if ($formatter instanceof \\Closure) {\n            $content = call_user_func($formatter, $content, $this->row);\n        }\n\n        $img = sprintf(\n            \"<img src='https://api.qrserver.com/v1/create-qr-code/?size=%sx%s&data=%s' style='height:%spx;width:%spx;'/>\",\n            $width,\n            $height,\n            $content,\n            $height,\n            $width\n        );\n\n        return <<<HTML\n<a href=\"javascript:void(0);\" class=\"grid-column-qrcode text-muted\" data-content=\"{$img}\" data-toggle='popover' tabindex='0'>\n    <i class=\"fa fa-qrcode\"></i>\n</a>&nbsp;{$this->getValue()}\nHTML;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/Radio.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Encore\\Admin\\Admin;\nuse Illuminate\\Support\\Arr;\n\nclass Radio extends AbstractDisplayer\n{\n    public function display($options = [])\n    {\n        return Admin::component('admin::grid.inline-edit.radio', [\n            'key'      => $this->getKey(),\n            'name'     => $this->getPayloadName(),\n            'value'    => $this->getValue(),\n            'resource' => $this->getResource(),\n            'trigger'  => \"ie-trigger-{$this->getClassName()}\",\n            'target'   => \"ie-template-{$this->getClassName()}\",\n            'display'  => Arr::get($options, $this->getValue(), ''),\n            'options'  => $options,\n        ]);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/RowSelector.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Encore\\Admin\\Admin;\n\nclass RowSelector extends AbstractDisplayer\n{\n    public function display()\n    {\n        Admin::script($this->script());\n\n        return <<<EOT\n<input type=\"checkbox\" class=\"{$this->grid->getGridRowName()}-checkbox\" data-id=\"{$this->getKey()}\"  autocomplete=\"off\"/>\nEOT;\n    }\n\n    protected function script()\n    {\n        $all = $this->grid->getSelectAllName();\n        $row = $this->grid->getGridRowName();\n\n        $selected = trans('admin.grid_items_selected');\n\n        return <<<EOT\n$('.{$row}-checkbox').iCheck({checkboxClass:'icheckbox_minimal-blue'}).on('ifChanged', function () {\n\n    var id = $(this).data('id');\n\n    if (this.checked) {\n        \\$.admin.grid.select(id);\n        $(this).closest('tr').css('background-color', '#ffffd5');\n    } else {\n        \\$.admin.grid.unselect(id);\n        $(this).closest('tr').css('background-color', '');\n    }\n}).on('ifClicked', function () {\n\n    var id = $(this).data('id');\n\n    if (this.checked) {\n        $.admin.grid.unselect(id);\n    } else {\n        $.admin.grid.select(id);\n    }\n\n    var selected = $.admin.grid.selected().length;\n\n    if (selected > 0) {\n        $('.{$all}-btn').show();\n    } else {\n        $('.{$all}-btn').hide();\n    }\n\n    $('.{$all}-btn .selected').html(\"{$selected}\".replace('{n}', selected));\n});\n\nEOT;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/Secret.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Encore\\Admin\\Facades\\Admin;\n\nclass Secret extends AbstractDisplayer\n{\n    public function display($dotCount = 6)\n    {\n        $this->addScript();\n\n        $dots = str_repeat('*', $dotCount);\n\n        return <<<HTML\n<span class=\"secret-wrapper\">\n    <i class=\"fa fa-eye\" style=\"cursor: pointer;\"></i>\n    &nbsp;\n    <span class=\"secret-placeholder\" style=\"vertical-align: middle;\">{$dots}</span>\n    <span class=\"secret-content\" style=\"display: none;\">{$this->getValue()}</span>\n</span>\nHTML;\n    }\n\n    protected function addScript()\n    {\n        $script = <<<'SCRIPT'\n$('.secret-wrapper i').click(function () {\n    $(this).toggleClass('fa-eye fa-eye-slash').parent().find('.secret-placeholder,.secret-content').toggle();\n});\nSCRIPT;\n\n        Admin::script($script);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/Select.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Encore\\Admin\\Admin;\nuse Illuminate\\Support\\Arr;\n\nclass Select extends AbstractDisplayer\n{\n    public function display($options = [])\n    {\n        return Admin::component('admin::grid.inline-edit.select', [\n            'key'      => $this->getKey(),\n            'value'    => $this->getValue(),\n            'display'  => Arr::get($options, $this->getValue(), ''),\n            'name'     => $this->getPayloadName(),\n            'resource' => $this->getResource(),\n            'trigger'  => \"ie-trigger-{$this->getClassName()}\",\n            'target'   => \"ie-template-{$this->getClassName()}\",\n            'options'  => $options,\n        ]);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/Suffix.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nclass Suffix extends AbstractDisplayer\n{\n    public function display($suffix = null, $delimiter = '&nbsp;')\n    {\n        if ($suffix instanceof \\Closure) {\n            $suffix = $suffix->call($this->row, $this->getValue());\n        }\n\n        return <<<HTML\n{$this->getValue()}{$delimiter}{$suffix}\nHTML;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/SwitchDisplay.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Encore\\Admin\\Admin;\nuse Illuminate\\Support\\Arr;\n\nclass SwitchDisplay extends AbstractDisplayer\n{\n    /**\n     * @var array\n     */\n    protected $states = [\n        'on'  => ['value' => 1, 'text' => 'ON', 'color' => 'primary'],\n        'off' => ['value' => 0, 'text' => 'OFF', 'color' => 'default'],\n    ];\n\n    protected function overrideStates($states)\n    {\n        if (empty($states)) {\n            return;\n        }\n\n        foreach (Arr::dot($states) as $key => $state) {\n            Arr::set($this->states, $key, $state);\n        }\n    }\n\n    public function display($states = [])\n    {\n        $this->overrideStates($states);\n\n        return Admin::component('admin::grid.inline-edit.switch', [\n            'class'    => 'grid-switch-'.str_replace('.', '-', $this->getName()),\n            'key'      => $this->getKey(),\n            'resource' => $this->getResource(),\n            'name'     => $this->getPayloadName(),\n            'states'   => $this->states,\n            'checked'  => $this->states['on']['value'] == $this->getValue() ? 'checked' : '',\n        ]);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/SwitchGroup.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Encore\\Admin\\Admin;\nuse Illuminate\\Support\\Arr;\n\nclass SwitchGroup extends SwitchDisplay\n{\n    public function display($columns = [], $states = [])\n    {\n        $this->overrideStates($states);\n\n        if (!Arr::isAssoc($columns)) {\n            $columns = collect($columns)->map(function ($column) {\n                return [$column => ucfirst($column)];\n            })->collapse();\n        }\n\n        $html = [];\n\n        foreach ($columns as $column => $label) {\n            $html[] = $this->buildSwitch($column, $label);\n        }\n\n        return '<table>'.implode('', $html).'</table>';\n    }\n\n    protected function buildSwitch($name, $label = '')\n    {\n        return Admin::component('admin::grid.inline-edit.switch-group', [\n            'class'    => 'grid-switch-'.str_replace('.', '-', $name),\n            'key'      => $this->getKey(),\n            'resource' => $this->getResource(),\n            'name'     => $this->getPayloadName($name),\n            'states'   => $this->states,\n            'checked'  => $this->states['on']['value'] == $this->getAttribute($name) ? 'checked' : '',\n            'label'    => $label,\n        ]);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/Table.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Illuminate\\Support\\Arr;\n\nclass Table extends AbstractDisplayer\n{\n    public function display($titles = [])\n    {\n        if (empty($this->value)) {\n            return '';\n        }\n\n        if (empty($titles)) {\n            $titles = array_keys($this->value[0]);\n        }\n\n        if (Arr::isAssoc($titles)) {\n            $columns = array_keys($titles);\n        } else {\n            $titles = array_combine($titles, $titles);\n            $columns = $titles;\n        }\n\n        $data = array_map(function ($item) use ($columns) {\n            $sorted = [];\n\n            $arr = Arr::only($item, $columns);\n\n            foreach ($columns as $column) {\n                if (array_key_exists($column, $arr)) {\n                    $sorted[$column] = $arr[$column];\n                }\n            }\n\n            return $sorted;\n        }, $this->value);\n\n        $variables = [\n            'titles' => $titles,\n            'data'   => $data,\n        ];\n\n        return view('admin::grid.displayer.table', $variables)->render();\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/Textarea.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Encore\\Admin\\Admin;\n\nclass Textarea extends AbstractDisplayer\n{\n    public function display($rows = 5)\n    {\n        return Admin::component('admin::grid.inline-edit.textarea', [\n            'key'      => $this->getKey(),\n            'value'    => $this->getValue(),\n            'display'  => $this->getValue(),\n            'name'     => $this->getPayloadName(),\n            'resource' => $this->getResource(),\n            'trigger'  => \"ie-trigger-{$this->getClassName()}\",\n            'target'   => \"ie-template-{$this->getClassName()}\",\n            'rows'     => $rows,\n        ]);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Displayers/Upload.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Displayers;\n\nuse Encore\\Admin\\Admin;\n\nclass Upload extends AbstractDisplayer\n{\n    public function display($multiple = false)\n    {\n        return Admin::component('admin::grid.inline-edit.upload', [\n            'key'      => $this->getKey(),\n            'name'     => $this->getPayloadName(),\n            'value'    => $this->getValue(),\n            'target'   => \"inline-upload-{$this->getKey()}\",\n            'resource' => $this->getResource(),\n            'multiple' => $multiple,\n        ]);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Exporter.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid;\n\nuse Encore\\Admin\\Grid;\nuse Encore\\Admin\\Grid\\Exporters\\CsvExporter;\n\nclass Exporter\n{\n    /**\n     * Export scope constants.\n     */\n    const SCOPE_ALL = 'all';\n    const SCOPE_CURRENT_PAGE = 'page';\n    const SCOPE_SELECTED_ROWS = 'selected';\n\n    /**\n     * @var Grid\n     */\n    protected $grid;\n\n    /**\n     * Available exporter drivers.\n     *\n     * @var array\n     */\n    protected static $drivers = [];\n\n    /**\n     * Export query name.\n     *\n     * @var string\n     */\n    public static $queryName = '_export_';\n\n    /**\n     * @var Grid\\Exporters\\AbstractExporter\n     */\n    protected static $exporter;\n\n    /**\n     * Create a new Exporter instance.\n     *\n     * @param Grid $grid\n     */\n    public function __construct(Grid $grid)\n    {\n        $this->grid = $grid;\n\n        $this->grid->model()->usePaginate(false);\n    }\n\n    /**\n     * Set export query name.\n     *\n     * @param $name\n     */\n    public static function setQueryName($name)\n    {\n        static::$queryName = $name;\n    }\n\n    /**\n     * Extends new exporter driver.\n     *\n     * @param $driver\n     * @param $extend\n     */\n    public static function extend($driver, $extend)\n    {\n        static::$drivers[$driver] = $extend;\n    }\n\n    /**\n     * Resolve export driver.\n     *\n     * @param string $driver\n     *\n     * @return CsvExporter\n     */\n    public function resolve($driver)\n    {\n        if ($driver instanceof Grid\\Exporters\\AbstractExporter) {\n            return $driver->setGrid($this->grid);\n        }\n\n        return $this->getExporter($driver);\n    }\n\n    /**\n     * Get export driver.\n     *\n     * @param string $driver\n     *\n     * @return CsvExporter\n     */\n    protected function getExporter($driver)\n    {\n        if (static::$exporter) {\n            return static::$exporter;\n        }\n\n        if (!array_key_exists($driver, static::$drivers)) {\n            return static::$exporter = $this->getDefaultExporter();\n        }\n\n        return static::$exporter = new static::$drivers[$driver]($this->grid);\n    }\n\n    /**\n     * Get default exporter.\n     *\n     * @return CsvExporter\n     */\n    public function getDefaultExporter()\n    {\n        return new CsvExporter($this->grid);\n    }\n\n    /**\n     * Format query for export url.\n     *\n     * @param int  $scope\n     * @param null $args\n     *\n     * @return array\n     */\n    public static function formatExportQuery($scope = '', $args = null)\n    {\n        $query = '';\n\n        if ($scope == static::SCOPE_ALL) {\n            $query = 'all';\n        }\n\n        if ($scope == static::SCOPE_CURRENT_PAGE) {\n            $query = \"page:$args\";\n        }\n\n        if ($scope == static::SCOPE_SELECTED_ROWS) {\n            $query = \"selected:$args\";\n        }\n\n        return [static::$queryName => $query];\n    }\n}\n"
  },
  {
    "path": "src/Grid/Exporters/AbstractExporter.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Exporters;\n\nuse Encore\\Admin\\Grid;\n\nabstract class AbstractExporter implements ExporterInterface\n{\n    /**\n     * @var \\Encore\\Admin\\Grid\n     */\n    protected $grid;\n\n    /**\n     * @var int\n     */\n    protected $page;\n\n    /**\n     * Create a new exporter instance.\n     *\n     * @param $grid\n     */\n    public function __construct(Grid $grid = null)\n    {\n        if ($grid) {\n            $this->setGrid($grid);\n        }\n    }\n\n    /**\n     * Set grid for exporter.\n     *\n     * @param Grid $grid\n     *\n     * @return $this\n     */\n    public function setGrid(Grid $grid)\n    {\n        $this->grid = $grid;\n\n        return $this;\n    }\n\n    /**\n     * Get table of grid.\n     *\n     * @return string\n     */\n    public function getTable()\n    {\n        return $this->grid->model()->getOriginalModel()->getTable();\n    }\n\n    /**\n     * Get data with export query.\n     *\n     * @param bool $toArray\n     *\n     * @return array|\\Illuminate\\Support\\Collection|mixed\n     */\n    public function getData($toArray = true)\n    {\n        return $this->grid->getFilter()->execute($toArray);\n    }\n\n    /**\n     * @param callable $callback\n     * @param int      $count\n     *\n     * @return bool\n     */\n    public function chunk(callable $callback, $count = 100)\n    {\n        $this->grid->applyQuery();\n\n        return $this->grid->getFilter()->chunk($callback, $count);\n    }\n\n    /**\n     * @return \\Illuminate\\Support\\Collection\n     */\n    public function getCollection()\n    {\n        return collect($this->getData());\n    }\n\n    /**\n     * @return \\Illuminate\\Database\\Eloquent\\Builder|\\Illuminate\\Database\\Eloquent\\Model\n     */\n    public function getQuery()\n    {\n        $model = $this->grid->getFilter()->getModel();\n\n        $queryBuilder = $model->getQueryBuilder();\n\n        // Export data of giving page number.\n        if ($this->page) {\n            $keyName = $this->grid->getKeyName();\n            $perPage = request($model->getPerPageName(), $model->getPerPage());\n\n            $scope = (clone $queryBuilder)\n                ->select([$keyName])\n                ->setEagerLoads([])\n                ->forPage($this->page, $perPage)->get();\n            // If $querybuilder is a Model, it must be reassigned, unless it is a eloquent/query builder.\n            $queryBuilder = $queryBuilder->whereIn($keyName, $scope->pluck($keyName));\n        }\n\n        return $queryBuilder;\n    }\n\n    /**\n     * Export data with scope.\n     *\n     * @param string $scope\n     *\n     * @return $this\n     */\n    public function withScope($scope)\n    {\n        if ($scope == Grid\\Exporter::SCOPE_ALL) {\n            return $this;\n        }\n\n        list($scope, $args) = explode(':', $scope);\n\n        if ($scope == Grid\\Exporter::SCOPE_CURRENT_PAGE) {\n            $this->grid->model()->usePaginate(true);\n            $this->page = $args ?: 1;\n        }\n\n        if ($scope == Grid\\Exporter::SCOPE_SELECTED_ROWS) {\n            $selected = explode(',', $args);\n            $this->grid->model()->whereIn($this->grid->getKeyName(), $selected);\n        }\n\n        return $this;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    abstract public function export();\n}\n"
  },
  {
    "path": "src/Grid/Exporters/CsvExporter.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Exporters;\n\nuse Encore\\Admin\\Grid\\Column;\n\nclass CsvExporter extends AbstractExporter\n{\n    /**\n     * @var string\n     */\n    protected $filename;\n\n    /**\n     * @var \\Closure\n     */\n    protected $callback;\n\n    /**\n     * @var array\n     */\n    protected $exceptColumns;\n\n    /**\n     * @var array\n     */\n    protected $onlyColumns;\n\n    /**\n     * @var []\\Closure\n     */\n    protected $columnCallbacks;\n\n    /**\n     * @var []\\Closure\n     */\n    protected $titleCallbacks;\n\n    /**\n     * @var array\n     */\n    protected $visibleColumns;\n\n    /**\n     * @var array\n     */\n    protected $columnUseOriginalValue;\n\n    /**\n     * @param string $filename\n     *\n     * @return $this\n     */\n    public function filename(string $filename = ''): self\n    {\n        $this->filename = $filename;\n\n        return $this;\n    }\n\n    /**\n     * @param \\Closure $closure\n     */\n    public function setCallback(\\Closure $closure): self\n    {\n        $this->callback = $closure;\n\n        return $this;\n    }\n\n    /**\n     * @param array $columns\n     *\n     * @return $this\n     */\n    public function except(array $columns = []): self\n    {\n        $this->exceptColumns = $columns;\n\n        return $this;\n    }\n\n    /**\n     * @param array $columns\n     *\n     * @return $this\n     */\n    public function only(array $columns = []): self\n    {\n        $this->onlyColumns = $columns;\n\n        return $this;\n    }\n\n    /**\n     * @param array $columns\n     *\n     * @return $this\n     */\n    public function originalValue($columns = []): self\n    {\n        $this->columnUseOriginalValue = $columns;\n\n        return $this;\n    }\n\n    /**\n     * @param string   $name\n     * @param \\Closure $callback\n     *\n     * @return $this\n     */\n    public function column(string $name, \\Closure $callback): self\n    {\n        $this->columnCallbacks[$name] = $callback;\n\n        return $this;\n    }\n\n    /**\n     * @param string   $name\n     * @param \\Closure $callback\n     *\n     * @return $this\n     */\n    public function title(string $name, \\Closure $callback): self\n    {\n        $this->titleCallbacks[$name] = $callback;\n\n        return $this;\n    }\n\n    /**\n     * Get download response headers.\n     *\n     * @return array\n     */\n    protected function getHeaders()\n    {\n        if (!$this->filename) {\n            $this->filename = $this->getTable();\n        }\n\n        return [\n            'Content-Encoding'    => 'UTF-8',\n            'Content-Type'        => 'text/csv;charset=UTF-8',\n            'Content-Disposition' => \"attachment;filename=\\\"{$this->filename}.csv\\\"\",\n        ];\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function export()\n    {\n        if ($this->callback) {\n            call_user_func($this->callback, $this);\n        }\n\n        $response = function () {\n            $handle = fopen('php://output', 'w');\n            $titles = [];\n            fwrite($handle, chr(0xEF).chr(0xBB).chr(0xBF)); //导出的CSV文件是无BOM编码UTF-8，而我们通常使用UTF-8编码格式都是有BOM的。所以添加BOM于CSV中\n            $this->chunk(function ($collection) use ($handle, &$titles) {\n                Column::setOriginalGridModels($collection);\n\n                $original = $current = $collection->toArray();\n\n                $this->grid->getColumns()->map(function (Column $column) use (&$current) {\n                    $current = $column->fill($current);\n                    $this->grid->columnNames[] = $column->getName();\n                });\n\n                // Write title\n                if (empty($titles)) {\n                    fputcsv($handle, $titles = $this->getVisiableTitles());\n                }\n\n                // Write rows\n                foreach ($current as $index => $record) {\n                    fputcsv($handle, $this->getVisiableFields($record, $original[$index]));\n                }\n            });\n            fclose($handle);\n        };\n\n        response()->stream($response, 200, $this->getHeaders())->send();\n\n        exit;\n    }\n\n    /**\n     * @return array\n     */\n    protected function getVisiableTitles()\n    {\n        $titles = $this->grid->visibleColumns()\n            ->mapWithKeys(function (Column $column) {\n                $columnName = $column->getName();\n                $columnTitle = $column->getLabel();\n                if (isset($this->titleCallbacks[$columnName])) {\n                    $columnTitle = $this->titleCallbacks[$columnName]($columnTitle);\n                }\n\n                return [$columnName => $columnTitle];\n            });\n\n        if ($this->onlyColumns) {\n            $titles = $titles->only($this->onlyColumns);\n        }\n\n        if ($this->exceptColumns) {\n            $titles = $titles->except($this->exceptColumns);\n        }\n\n        $this->visibleColumns = $titles->keys();\n\n        return $titles->values()->toArray();\n    }\n\n    /**\n     * @param array $value\n     * @param array $original\n     *\n     * @return array\n     */\n    public function getVisiableFields(array $value, array $original): array\n    {\n        $fields = [];\n\n        foreach ($this->visibleColumns as $column) {\n            $fields[] = $this->getColumnValue(\n                $column,\n                data_get($value, $column),\n                data_get($original, $column)\n            );\n        }\n\n        return $fields;\n    }\n\n    /**\n     * @param string $column\n     * @param mixed  $value\n     * @param mixed  $original\n     *\n     * @return mixed\n     */\n    protected function getColumnValue(string $column, $value, $original)\n    {\n        if (!empty($this->columnUseOriginalValue)\n            && in_array($column, $this->columnUseOriginalValue)) {\n            return $original;\n        }\n\n        if (isset($this->columnCallbacks[$column])) {\n            return $this->columnCallbacks[$column]($value, $original);\n        }\n\n        return $value;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Exporters/ExcelExporter.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Exporters;\n\nuse Illuminate\\Support\\Str;\nuse Maatwebsite\\Excel\\Concerns\\Exportable;\nuse Maatwebsite\\Excel\\Concerns\\FromQuery;\nuse Maatwebsite\\Excel\\Concerns\\WithHeadings;\n\nabstract class ExcelExporter extends AbstractExporter implements FromQuery, WithHeadings\n{\n    use Exportable;\n\n    /**\n     * @var string\n     */\n    protected $fileName;\n\n    /**\n     * @var array\n     */\n    protected $headings = [];\n\n    /**\n     * @var array\n     */\n    protected $columns = [];\n\n    /**\n     * @return array\n     */\n    public function headings(): array\n    {\n        if (!empty($this->columns)) {\n            return array_values($this->columns);\n        }\n\n        return $this->headings;\n    }\n\n    /**\n     * @return \\Illuminate\\Database\\Eloquent\\Builder|\\Illuminate\\Database\\Eloquent\\Model\n     */\n    public function query()\n    {\n        if (!empty($this->columns)) {\n            $columns = array_keys($this->columns);\n\n            $eagerLoads = array_keys($this->getQuery()->getEagerLoads());\n\n            $columns = collect($columns)->reject(function ($column) use ($eagerLoads) {\n                return Str::contains($column, '.') || in_array($column, $eagerLoads);\n            });\n\n            return $this->getQuery()->select($columns->toArray());\n        }\n\n        return $this->getQuery();\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function export()\n    {\n        $this->download($this->fileName)->prepare(request())->send();\n\n        exit;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Exporters/ExporterInterface.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Exporters;\n\ninterface ExporterInterface\n{\n    /**\n     * Export data from grid.\n     *\n     * @return mixed\n     */\n    public function export();\n}\n"
  },
  {
    "path": "src/Grid/Filter/AbstractFilter.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter;\n\nuse Encore\\Admin\\Grid\\Filter;\nuse Encore\\Admin\\Grid\\Filter\\Presenter\\Checkbox;\nuse Encore\\Admin\\Grid\\Filter\\Presenter\\DateTime;\nuse Encore\\Admin\\Grid\\Filter\\Presenter\\MultipleSelect;\nuse Encore\\Admin\\Grid\\Filter\\Presenter\\Presenter;\nuse Encore\\Admin\\Grid\\Filter\\Presenter\\Radio;\nuse Encore\\Admin\\Grid\\Filter\\Presenter\\Select;\nuse Encore\\Admin\\Grid\\Filter\\Presenter\\Text;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Collection;\n\n/**\n * Class AbstractFilter.\n *\n * @method Text url()\n * @method Text email()\n * @method Text integer()\n * @method Text decimal($options = [])\n * @method Text currency($options = [])\n * @method Text percentage($options = [])\n * @method Text ip()\n * @method Text mac()\n * @method Text mobile($mask = '19999999999')\n * @method Text inputmask($options = [], $icon = '')\n * @method Text placeholder($placeholder = '')\n */\nabstract class AbstractFilter\n{\n    /**\n     * Element id.\n     *\n     * @var array|string\n     */\n    protected $id;\n\n    /**\n     * Label of presenter.\n     *\n     * @var string\n     */\n    protected $label;\n\n    /**\n     * @var array|string\n     */\n    protected $value;\n\n    /**\n     * @var array|string\n     */\n    protected $defaultValue;\n\n    /**\n     * @var string\n     */\n    protected $column;\n\n    /**\n     * Presenter object.\n     *\n     * @var Presenter\n     */\n    protected $presenter;\n\n    /**\n     * Query for filter.\n     *\n     * @var string\n     */\n    protected $query = 'where';\n\n    /**\n     * @var Filter\n     */\n    protected $parent;\n\n    /**\n     * @var string\n     */\n    protected $view = 'admin::filter.where';\n\n    /**\n     * @var Collection\n     */\n    public $group;\n\n    /**\n     * @var bool\n     */\n    protected $ignore = false;\n\n    /**\n     * AbstractFilter constructor.\n     *\n     * @param $column\n     * @param string $label\n     */\n    public function __construct($column, $label = '')\n    {\n        $this->column = $column;\n        $this->label = $this->formatLabel($label);\n        $this->id = $this->formatId($column);\n\n        $this->setupDefaultPresenter();\n    }\n\n    /**\n     * Setup default presenter.\n     *\n     * @return void\n     */\n    protected function setupDefaultPresenter()\n    {\n        $this->setPresenter(new Text($this->label));\n    }\n\n    /**\n     * Format label.\n     *\n     * @param string $label\n     *\n     * @return string\n     */\n    protected function formatLabel($label)\n    {\n        $label = $label ?: ucfirst($this->column);\n\n        return str_replace(['.', '_'], ' ', $label);\n    }\n\n    /**\n     * Format name.\n     *\n     * @param string $column\n     *\n     * @return string\n     */\n    protected function formatName($column)\n    {\n        $columns = explode('.', $column);\n\n        if (count($columns) == 1) {\n            $name = $columns[0];\n        } else {\n            $name = array_shift($columns);\n            foreach ($columns as $column) {\n                $name .= \"[$column]\";\n            }\n        }\n\n        $parenName = $this->parent->getName();\n\n        return $parenName ? \"{$parenName}_{$name}\" : $name;\n    }\n\n    /**\n     * Format id.\n     *\n     * @param $columns\n     *\n     * @return array|string\n     */\n    protected function formatId($columns)\n    {\n        return str_replace('.', '_', $columns);\n    }\n\n    /**\n     * @param Filter $filter\n     */\n    public function setParent(Filter $filter)\n    {\n        $this->parent = $filter;\n    }\n\n    /**\n     * Get siblings of current filter.\n     *\n     * @param null $index\n     *\n     * @return AbstractFilter[]|mixed\n     */\n    public function siblings($index = null)\n    {\n        if (!is_null($index)) {\n            return Arr::get($this->parent->filters(), $index);\n        }\n\n        return $this->parent->filters();\n    }\n\n    /**\n     * Get previous filter.\n     *\n     * @param int $step\n     *\n     * @return AbstractFilter[]|mixed\n     */\n    public function previous($step = 1)\n    {\n        return $this->siblings(\n            array_search($this, $this->parent->filters()) - $step\n        );\n    }\n\n    /**\n     * Get next filter.\n     *\n     * @param int $step\n     *\n     * @return AbstractFilter[]|mixed\n     */\n    public function next($step = 1)\n    {\n        return $this->siblings(\n            array_search($this, $this->parent->filters()) + $step\n        );\n    }\n\n    /**\n     * Get query condition from filter.\n     *\n     * @param array $inputs\n     *\n     * @return array|mixed|null\n     */\n    public function condition($inputs)\n    {\n        if ($this->ignore) {\n            return;\n        }\n\n        $value = Arr::get($inputs, $this->column);\n\n        if (!isset($value)) {\n            return;\n        }\n\n        $this->value = $value;\n\n        return $this->buildCondition($this->column, $this->value);\n    }\n\n    /**\n     * Ignore this query filter.\n     *\n     * @return $this\n     */\n    public function ignore()\n    {\n        $this->ignore = true;\n\n        return $this;\n    }\n\n    /**\n     * Select filter.\n     *\n     * @param array|\\Illuminate\\Support\\Collection $options\n     *\n     * @return Select\n     */\n    public function select($options = [])\n    {\n        return $this->setPresenter(new Select($options));\n    }\n\n    /**\n     * @param array|\\Illuminate\\Support\\Collection $options\n     *\n     * @return MultipleSelect\n     */\n    public function multipleSelect($options = [])\n    {\n        return $this->setPresenter(new MultipleSelect($options));\n    }\n\n    /**\n     * @param array|\\Illuminate\\Support\\Collection $options\n     *\n     * @return Radio\n     */\n    public function radio($options = [])\n    {\n        return $this->setPresenter(new Radio($options));\n    }\n\n    /**\n     * @param array|\\Illuminate\\Support\\Collection $options\n     *\n     * @return Checkbox\n     */\n    public function checkbox($options = [])\n    {\n        return $this->setPresenter(new Checkbox($options));\n    }\n\n    /**\n     * Datetime filter.\n     *\n     * @param array|\\Illuminate\\Support\\Collection $options\n     *\n     * @return DateTime\n     */\n    public function datetime($options = [])\n    {\n        return $this->setPresenter(new DateTime($options));\n    }\n\n    /**\n     * Date filter.\n     *\n     * @return DateTime\n     */\n    public function date()\n    {\n        return $this->datetime(['format' => 'YYYY-MM-DD']);\n    }\n\n    /**\n     * Time filter.\n     *\n     * @return DateTime\n     */\n    public function time()\n    {\n        return $this->datetime(['format' => 'HH:mm:ss']);\n    }\n\n    /**\n     * Day filter.\n     *\n     * @return DateTime\n     */\n    public function day()\n    {\n        return $this->datetime(['format' => 'DD']);\n    }\n\n    /**\n     * Month filter.\n     *\n     * @return DateTime\n     */\n    public function month()\n    {\n        return $this->datetime(['format' => 'MM']);\n    }\n\n    /**\n     * Year filter.\n     *\n     * @return DateTime\n     */\n    public function year()\n    {\n        return $this->datetime(['format' => 'YYYY']);\n    }\n\n    /**\n     * Set presenter object of filter.\n     *\n     * @param Presenter $presenter\n     *\n     * @return mixed\n     */\n    protected function setPresenter(Presenter $presenter)\n    {\n        $presenter->setParent($this);\n\n        return $this->presenter = $presenter;\n    }\n\n    /**\n     * Get presenter object of filter.\n     *\n     * @return Presenter\n     */\n    protected function presenter()\n    {\n        return $this->presenter;\n    }\n\n    /**\n     * Set default value for filter.\n     *\n     * @param null $default\n     *\n     * @return $this\n     */\n    public function default($default = null)\n    {\n        if ($default) {\n            $this->defaultValue = $default;\n        }\n\n        return $this;\n    }\n\n    public function getFilterBoxId()\n    {\n        return $this->parent ? $this->parent->getFilterID() : 'filter-box';\n    }\n\n    /**\n     * Get element id.\n     *\n     * @return array|string\n     */\n    public function getId()\n    {\n        return $this->id;\n    }\n\n    /**\n     * Set element id.\n     *\n     * @param string $id\n     *\n     * @return $this\n     */\n    public function setId($id)\n    {\n        $this->id = $this->formatId($id);\n\n        return $this;\n    }\n\n    /**\n     * Get column name of current filter.\n     *\n     * @return string\n     */\n    public function getColumn()\n    {\n        $parentName = $this->parent->getName();\n\n        return $parentName ? \"{$parentName}_{$this->column}\" : $this->column;\n    }\n\n    /**\n     * Get value of current filter.\n     *\n     * @return array|string\n     */\n    public function getValue()\n    {\n        return $this->value;\n    }\n\n    /**\n     * Build conditions of filter.\n     *\n     * @return mixed\n     */\n    protected function buildCondition()\n    {\n        $column = explode('.', $this->column);\n\n        if (count($column) == 1) {\n            return [$this->query => func_get_args()];\n        }\n\n        return $this->buildRelationQuery(...func_get_args());\n    }\n\n    /**\n     * Build query condition of model relation.\n     *\n     * @return array\n     */\n    protected function buildRelationQuery()\n    {\n        $args = func_get_args();\n\n        $relation = substr($this->column, 0, strrpos($this->column, '.'));\n        $args[0] = last(explode('.', $this->column));\n\n        return ['whereHas' => [$relation, function ($relation) use ($args) {\n            call_user_func_array([$relation, $this->query], $args);\n        }]];\n    }\n\n    /**\n     * Variables for filter view.\n     *\n     * @return array\n     */\n    protected function variables()\n    {\n        return array_merge([\n            'id'        => $this->id,\n            'column'    => $this->column,\n            'name'      => $this->formatName($this->column),\n            'label'     => $this->label,\n            'value'     => $this->value ?: $this->defaultValue,\n            'presenter' => $this->presenter(),\n        ], $this->presenter()->variables());\n    }\n\n    /**\n     * Render this filter.\n     *\n     * @return \\Illuminate\\View\\View|string\n     */\n    public function render()\n    {\n        return view($this->view, $this->variables());\n    }\n\n    /**\n     * Render this filter.\n     *\n     * @return \\Illuminate\\View\\View|string\n     */\n    public function __toString()\n    {\n        return $this->render();\n    }\n\n    /**\n     * @param $method\n     * @param $params\n     *\n     * @throws \\Exception\n     *\n     * @return mixed\n     */\n    public function __call($method, $params)\n    {\n        if (method_exists($this->presenter, $method)) {\n            return $this->presenter()->{$method}(...$params);\n        }\n\n        throw new \\Exception('Method \"'.$method.'\" not exists.');\n    }\n}\n"
  },
  {
    "path": "src/Grid/Filter/Between.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter;\n\nuse Encore\\Admin\\Admin;\nuse Illuminate\\Support\\Arr;\n\nclass Between extends AbstractFilter\n{\n    /**\n     * {@inheritdoc}\n     */\n    protected $view = 'admin::filter.between';\n\n    /**\n     * Format id.\n     *\n     * @param string $column\n     *\n     * @return array|string\n     */\n    public function formatId($column)\n    {\n        $id = str_replace('.', '_', $column);\n\n        return ['start' => \"{$id}_start\", 'end' => \"{$id}_end\"];\n    }\n\n    /**\n     * Format two field names of this filter.\n     *\n     * @param string $column\n     *\n     * @return array\n     */\n    protected function formatName($column)\n    {\n        $columns = explode('.', $column);\n\n        if (count($columns) == 1) {\n            $name = $columns[0];\n        } else {\n            $name = array_shift($columns);\n\n            foreach ($columns as $column) {\n                $name .= \"[$column]\";\n            }\n        }\n\n        return ['start' => \"{$name}[start]\", 'end' => \"{$name}[end]\"];\n    }\n\n    /**\n     * Get condition of this filter.\n     *\n     * @param array $inputs\n     *\n     * @return mixed\n     */\n    public function condition($inputs)\n    {\n        if ($this->ignore) {\n            return;\n        }\n\n        if (!Arr::has($inputs, $this->column)) {\n            return;\n        }\n\n        $this->value = Arr::get($inputs, $this->column);\n\n        $value = array_filter($this->value, function ($val) {\n            return $val !== '';\n        });\n\n        if (empty($value)) {\n            return;\n        }\n\n        if (!isset($value['start'])) {\n            return $this->buildCondition($this->column, '<=', $value['end']);\n        }\n\n        if (!isset($value['end'])) {\n            return $this->buildCondition($this->column, '>=', $value['start']);\n        }\n\n        $this->query = 'whereBetween';\n\n        return $this->buildCondition($this->column, $this->value);\n    }\n\n    /**\n     * @param array $options\n     *\n     * @return $this\n     */\n    public function datetime($options = [])\n    {\n        $this->view = 'admin::filter.betweenDatetime';\n\n        $this->setupDatetime($options);\n\n        return $this;\n    }\n\n    /**\n     * @param array $options\n     */\n    protected function setupDatetime($options = [])\n    {\n        $options['format'] = Arr::get($options, 'format', 'YYYY-MM-DD HH:mm:ss');\n        $options['locale'] = Arr::get($options, 'locale', config('app.locale'));\n\n        $startOptions = json_encode($options);\n        $endOptions = json_encode($options + ['useCurrent' => false]);\n\n        $script = <<<EOT\n            $('#{$this->id['start']}').datetimepicker($startOptions);\n            $('#{$this->id['end']}').datetimepicker($endOptions);\n            $(\"#{$this->id['start']}\").on(\"dp.change\", function (e) {\n                $('#{$this->id['end']}').data(\"DateTimePicker\").minDate(e.date);\n            });\n            $(\"#{$this->id['end']}\").on(\"dp.change\", function (e) {\n                $('#{$this->id['start']}').data(\"DateTimePicker\").maxDate(e.date);\n            });\nEOT;\n\n        Admin::script($script);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Filter/Date.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter;\n\nclass Date extends AbstractFilter\n{\n    /**\n     * {@inheritdoc}\n     */\n    protected $query = 'whereDate';\n\n    /**\n     * @var string\n     */\n    protected $fieldName = 'date';\n\n    /**\n     * {@inheritdoc}\n     */\n    public function __construct($column, $label = '')\n    {\n        parent::__construct($column, $label);\n\n        $this->{$this->fieldName}();\n    }\n}\n"
  },
  {
    "path": "src/Grid/Filter/Day.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter;\n\nclass Day extends Date\n{\n    /**\n     * {@inheritdoc}\n     */\n    protected $query = 'whereDay';\n\n    /**\n     * @var string\n     */\n    protected $fieldName = 'day';\n}\n"
  },
  {
    "path": "src/Grid/Filter/EndsWith.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter;\n\nclass EndsWith extends Like\n{\n    protected $exprFormat = '%{value}';\n}\n"
  },
  {
    "path": "src/Grid/Filter/Equal.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter;\n\nclass Equal extends AbstractFilter\n{\n}\n"
  },
  {
    "path": "src/Grid/Filter/Group.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter;\n\nuse Encore\\Admin\\Admin;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Collection;\n\nclass Group extends AbstractFilter\n{\n    /**\n     * @var \\Closure|null\n     */\n    protected $builder;\n\n    /**\n     * @var string\n     */\n    protected $name;\n\n    /**\n     * Input value from presenter.\n     *\n     * @var mixed\n     */\n    public $input;\n\n    /**\n     * Group constructor.\n     *\n     * @param string        $column\n     * @param string        $label\n     * @param \\Closure|null $builder\n     */\n    public function __construct($column, $label = '', \\Closure $builder = null)\n    {\n        $this->column = $column;\n\n        if (is_callable($label) && is_null($builder)) {\n            $this->builder = $label;\n            $this->label = ucfirst($this->column);\n        } elseif (is_string($label) && is_callable($builder)) {\n            $this->label = $label;\n            $this->builder = $builder;\n        }\n\n        $this->initialize();\n    }\n\n    /**\n     * Initialize a group filter.\n     */\n    protected function initialize()\n    {\n        $this->id = $this->formatId($this->column);\n        $this->group = new Collection();\n        $this->name = \"{$this->id}-filter-group\";\n\n        $this->setupDefaultPresenter();\n    }\n\n    /**\n     * Join a query to group.\n     *\n     * @param string $label\n     * @param array  $condition\n     *\n     * @return $this\n     */\n    protected function joinGroup($label, array $condition)\n    {\n        $this->group->push(\n            compact('label', 'condition')\n        );\n\n        return $this;\n    }\n\n    /**\n     * Filter out `equal` records.\n     *\n     * @param string $label\n     * @param string $operator\n     *\n     * @return Group\n     */\n    public function equal($label = '', $operator = '=')\n    {\n        $label = $label ?: $operator;\n\n        $condition = [$this->column, $operator, $this->value];\n\n        return $this->joinGroup($label, $condition);\n    }\n\n    /**\n     * Filter out `not equal` records.\n     *\n     * @param string $label\n     *\n     * @return Group\n     */\n    public function notEqual($label = '')\n    {\n        return $this->equal($label, '!=');\n    }\n\n    /**\n     * Filter out `greater then` records.\n     *\n     * @param string $label\n     *\n     * @return Group\n     */\n    public function gt($label = '')\n    {\n        return $this->equal($label, '>');\n    }\n\n    /**\n     * Filter out `less then` records.\n     *\n     * @param string $label\n     *\n     * @return Group\n     */\n    public function lt($label = '')\n    {\n        return $this->equal($label, '<');\n    }\n\n    /**\n     * Filter out `not less then` records.\n     *\n     * @param string $label\n     *\n     * @return Group\n     */\n    public function nlt($label = '')\n    {\n        return $this->equal($label, '>=');\n    }\n\n    /**\n     * Filter out `not greater than` records.\n     *\n     * @param string $label\n     *\n     * @return Group\n     */\n    public function ngt($label = '')\n    {\n        return $this->equal($label, '<=');\n    }\n\n    /**\n     * Filter out records that match the regex.\n     *\n     * @param string $label\n     *\n     * @return Group\n     */\n    public function match($label = '')\n    {\n        $label = $label ?: 'Match';\n\n        return $this->equal($label, 'REGEXP');\n    }\n\n    /**\n     * Specify a where query.\n     *\n     * @param string   $label\n     * @param \\Closure $builder\n     *\n     * @return Group\n     */\n    public function where($label, \\Closure $builder)\n    {\n        $this->input = $this->value;\n\n        $condition = [$builder->bindTo($this)];\n\n        return $this->joinGroup($label, $condition);\n    }\n\n    /**\n     * Specify a where like query.\n     *\n     * @param string $label\n     * @param string $operator\n     *\n     * @return Group\n     */\n    public function like($label = '', $operator = 'like')\n    {\n        $label = $label ?: $operator;\n\n        $condition = [$this->column, $operator, \"%{$this->value}%\"];\n\n        return $this->joinGroup($label, $condition);\n    }\n\n    /**\n     * Alias of `like` method.\n     *\n     * @param string $label\n     *\n     * @return Group\n     */\n    public function contains($label = '')\n    {\n        return $this->like($label);\n    }\n\n    /**\n     * Specify a where ilike query.\n     *\n     * @param string $label\n     *\n     * @return Group\n     */\n    public function ilike($label = '')\n    {\n        return $this->like($label, 'ilike');\n    }\n\n    /**\n     * Filter out records which starts with input query.\n     *\n     * @param string $label\n     *\n     * @return Group\n     */\n    public function startWith($label = '')\n    {\n        $label = $label ?: 'Start with';\n\n        $condition = [$this->column, 'like', \"{$this->value}%\"];\n\n        return $this->joinGroup($label, $condition);\n    }\n\n    /**\n     * Filter out records which ends with input query.\n     *\n     * @param string $label\n     *\n     * @return Group\n     */\n    public function endWith($label = '')\n    {\n        $label = $label ?: 'End with';\n\n        $condition = [$this->column, 'like', \"%{$this->value}\"];\n\n        return $this->joinGroup($label, $condition);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function condition($inputs)\n    {\n        $value = Arr::get($inputs, $this->column);\n\n        if (!isset($value)) {\n            return;\n        }\n\n        $this->value = $value;\n\n        $group = Arr::get($inputs, \"{$this->id}_group\");\n\n        call_user_func($this->builder, $this);\n\n        if ($query = $this->group->get($group)) {\n            return $this->buildCondition(...$query['condition']);\n        }\n    }\n\n    /**\n     * Inject script to current page.\n     */\n    protected function injectScript()\n    {\n        $script = <<<SCRIPT\n$(\".{$this->name} li a\").click(function(){\n    $(\".{$this->name}-label\").text($(this).text());\n    $(\".{$this->name}-operation\").val($(this).data('index'));\n});\nSCRIPT;\n\n        Admin::script($script);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function variables()\n    {\n        $select = request(\"{$this->id}_group\");\n\n        $default = $this->group->get($select) ?: $this->group->first();\n\n        return array_merge(parent::variables(), [\n            'group_name' => $this->name,\n            'default'    => $default,\n        ]);\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function render()\n    {\n        $this->injectScript();\n\n        if ($this->builder && $this->group->isEmpty()) {\n            call_user_func($this->builder, $this);\n        }\n\n        return parent::render();\n    }\n}\n"
  },
  {
    "path": "src/Grid/Filter/Gt.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter;\n\nuse Illuminate\\Support\\Arr;\n\nclass Gt extends AbstractFilter\n{\n    /**\n     * {@inheritdoc}\n     */\n    protected $view = 'admin::filter.gt';\n\n    /**\n     * Get condition of this filter.\n     *\n     * @param array $inputs\n     *\n     * @return array|mixed|void\n     */\n    public function condition($inputs)\n    {\n        $value = Arr::get($inputs, $this->column);\n\n        if (is_null($value)) {\n            return;\n        }\n\n        $this->value = $value;\n\n        return $this->buildCondition($this->column, '>=', $this->value);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Filter/Hidden.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter;\n\nclass Hidden extends AbstractFilter\n{\n    /**\n     * @var string\n     */\n    protected $name;\n\n    /**\n     * @var string\n     */\n    protected $value;\n\n    /**\n     * Hidden constructor.\n     *\n     * @param string $name\n     * @param string $value\n     */\n    public function __construct($name, $value)\n    {\n        $this->name = $name;\n\n        $this->value = $value;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function condition($inputs)\n    {\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function render()\n    {\n        return \"<input type='hidden' name='$this->name' value='$this->value'>\";\n    }\n}\n"
  },
  {
    "path": "src/Grid/Filter/Ilike.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter;\n\nclass Ilike extends Like\n{\n    protected $operator = 'ilike';\n}\n"
  },
  {
    "path": "src/Grid/Filter/In.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter;\n\nuse Illuminate\\Support\\Arr;\n\nclass In extends AbstractFilter\n{\n    /**\n     * {@inheritdoc}\n     */\n    protected $query = 'whereIn';\n\n    /**\n     * Get condition of this filter.\n     *\n     * @param array $inputs\n     *\n     * @return mixed\n     */\n    public function condition($inputs)\n    {\n        $value = Arr::get($inputs, $this->column);\n\n        if (is_null($value)) {\n            return;\n        }\n\n        $this->value = (array) $value;\n\n        return $this->buildCondition($this->column, $this->value);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Filter/Layout/Column.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter\\Layout;\n\nuse Encore\\Admin\\Grid\\Filter\\AbstractFilter;\nuse Illuminate\\Support\\Collection;\n\nclass Column\n{\n    /**\n     * @var Collection\n     */\n    protected $filters;\n\n    /**\n     * @var int\n     */\n    protected $width;\n\n    /**\n     * Column constructor.\n     *\n     * @param int $width\n     */\n    public function __construct($width = 12)\n    {\n        $this->width = $width;\n        $this->filters = new Collection();\n    }\n\n    /**\n     * Add a filter to this column.\n     *\n     * @param AbstractFilter $filter\n     */\n    public function addFilter(AbstractFilter $filter)\n    {\n        $this->filters->push($filter);\n    }\n\n    /**\n     * Get all filters in this column.\n     *\n     * @return Collection\n     */\n    public function filters()\n    {\n        return $this->filters;\n    }\n\n    /**\n     * Set column width.\n     *\n     * @param int $width\n     */\n    public function setWidth($width)\n    {\n        $this->width = $width;\n    }\n\n    /**\n     * Get column width.\n     *\n     * @return int\n     */\n    public function width()\n    {\n        return $this->width;\n    }\n\n    /**\n     * Remove filter from column by id.\n     */\n    public function removeFilterByID($id)\n    {\n        $this->filters = $this->filters->reject(function (AbstractFilter $filter) use ($id) {\n            return $filter->getId() == $id;\n        });\n    }\n}\n"
  },
  {
    "path": "src/Grid/Filter/Layout/Layout.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter\\Layout;\n\nuse Encore\\Admin\\Grid\\Filter;\nuse Illuminate\\Support\\Collection;\n\nclass Layout\n{\n    /**\n     * @var Collection\n     */\n    protected $columns;\n\n    /**\n     * @var Column\n     */\n    protected $current;\n\n    /**\n     * @var Filter\n     */\n    protected $parent;\n\n    /**\n     * Layout constructor.\n     *\n     * @param Filter $filter\n     */\n    public function __construct(Filter $filter)\n    {\n        $this->parent = $filter;\n\n        $this->current = new Column();\n\n        $this->columns = new Collection();\n    }\n\n    /**\n     * Add a filter to layout column.\n     *\n     * @param Filter\\AbstractFilter $filter\n     */\n    public function addFilter(Filter\\AbstractFilter $filter)\n    {\n        $this->current->addFilter($filter);\n    }\n\n    /**\n     * Add a new column in layout.\n     *\n     * @param int      $width\n     * @param \\Closure $closure\n     */\n    public function column($width, \\Closure $closure)\n    {\n        if ($this->columns->isEmpty()) {\n            $column = $this->current;\n\n            $column->setWidth($width);\n        } else {\n            $column = new Column($width);\n\n            $this->current = $column;\n        }\n\n        $this->columns->push($column);\n\n        $closure($this->parent);\n    }\n\n    /**\n     * Get all columns in filter layout.\n     *\n     * @return Collection\n     */\n    public function columns()\n    {\n        if ($this->columns->isEmpty()) {\n            $this->columns->push($this->current);\n        }\n\n        return $this->columns;\n    }\n\n    /**\n     * Remove the default ID filter of the default(first) column.\n     */\n    public function removeDefaultIDFilter()\n    {\n        $this->columns()\n            ->first()\n            ->filters()\n            ->shift();\n    }\n}\n"
  },
  {
    "path": "src/Grid/Filter/Like.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter;\n\nuse Illuminate\\Support\\Arr;\n\nclass Like extends AbstractFilter\n{\n    /**\n     * @var string\n     */\n    protected $exprFormat = '%{value}%';\n\n    /**\n     * @var string\n     */\n    protected $operator = 'like';\n\n    /**\n     * Get condition of this filter.\n     *\n     * @param array $inputs\n     *\n     * @return array|mixed|void\n     */\n    public function condition($inputs)\n    {\n        $value = Arr::get($inputs, $this->column);\n\n        if (is_array($value)) {\n            $value = array_filter($value);\n        }\n\n        if (is_null($value) || empty($value)) {\n            return;\n        }\n\n        $this->value = $value;\n\n        $expr = str_replace('{value}', $this->value, $this->exprFormat);\n\n        return $this->buildCondition($this->column, $this->operator, $expr);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Filter/Lt.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter;\n\nuse Illuminate\\Support\\Arr;\n\nclass Lt extends AbstractFilter\n{\n    /**\n     * {@inheritdoc}\n     */\n    protected $view = 'admin::filter.lt';\n\n    /**\n     * Get condition of this filter.\n     *\n     * @param array $inputs\n     *\n     * @return array|mixed|void\n     */\n    public function condition($inputs)\n    {\n        $value = Arr::get($inputs, $this->column);\n\n        if (is_null($value)) {\n            return;\n        }\n\n        $this->value = $value;\n\n        return $this->buildCondition($this->column, '<=', $this->value);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Filter/Month.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter;\n\nclass Month extends Date\n{\n    /**\n     * {@inheritdoc}\n     */\n    protected $query = 'whereMonth';\n\n    /**\n     * @var string\n     */\n    protected $fieldName = 'month';\n}\n"
  },
  {
    "path": "src/Grid/Filter/NotEqual.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter;\n\nuse Illuminate\\Support\\Arr;\n\nclass NotEqual extends AbstractFilter\n{\n    /**\n     * {@inheritdoc}\n     */\n    public function condition($inputs)\n    {\n        $value = Arr::get($inputs, $this->column);\n\n        if (!isset($value)) {\n            return;\n        }\n\n        $this->value = $value;\n\n        return $this->buildCondition($this->column, '!=', $this->value);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Filter/NotIn.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter;\n\nclass NotIn extends In\n{\n    /**\n     * {@inheritdoc}\n     */\n    protected $query = 'whereNotIn';\n}\n"
  },
  {
    "path": "src/Grid/Filter/Presenter/Checkbox.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter\\Presenter;\n\nuse Encore\\Admin\\Facades\\Admin;\n\nclass Checkbox extends Radio\n{\n    protected function prepare()\n    {\n        $script = \"$('.{$this->filter->getId()}').iCheck({checkboxClass:'icheckbox_minimal-blue'});\";\n\n        Admin::script($script);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Filter/Presenter/DateTime.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter\\Presenter;\n\nuse Encore\\Admin\\Admin;\nuse Illuminate\\Support\\Arr;\n\nclass DateTime extends Presenter\n{\n    /**\n     * @var array\n     */\n    protected $options = [];\n\n    /**\n     * @var string\n     */\n    protected $format = 'YYYY-MM-DD HH:mm:ss';\n\n    /**\n     * DateTime constructor.\n     *\n     * @param array $options\n     */\n    public function __construct($options = [])\n    {\n        $this->options = $this->getOptions($options);\n    }\n\n    /**\n     * @param array $options\n     *\n     * @return mixed\n     */\n    protected function getOptions(array $options): array\n    {\n        $options['format'] = Arr::get($options, 'format', $this->format);\n        $options['locale'] = Arr::get($options, 'locale', config('app.locale'));\n\n        return $options;\n    }\n\n    protected function prepare()\n    {\n        $script = \"$('#{$this->filter->getId()}').datetimepicker(\".json_encode($this->options).');';\n\n        Admin::script($script);\n    }\n\n    public function variables(): array\n    {\n        $this->prepare();\n\n        return [\n            'group' => $this->filter->group,\n        ];\n    }\n}\n"
  },
  {
    "path": "src/Grid/Filter/Presenter/MultipleSelect.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter\\Presenter;\n\nuse Encore\\Admin\\Facades\\Admin;\n\nclass MultipleSelect extends Select\n{\n    /**\n     * Load options for other select when change.\n     *\n     * @param string $target\n     * @param string $resourceUrl\n     * @param string $idField\n     * @param string $textField\n     *\n     * @return $this\n     */\n    public function loadMore($target, $resourceUrl, $idField = 'id', $textField = 'text'): self\n    {\n        $column = $this->filter->getColumn();\n\n        $script = <<<EOT\n\n$(document).on('change', \".{$this->getClass($column)}\", function () {\n    var target = $(this).closest('form').find(\".{$this->getClass($target)}\");\n     var ids = $(this).find(\"option:selected\").map(function(index,elem) {\n            return $(elem).val();\n        }).get().join(',');\n    $.get(\"$resourceUrl?q=\"+ids, function (data) {\n        target.find(\"option\").remove();\n        $.each(data, function (i, item) {\n            $(target).append($('<option>', {\n                value: item.$idField,\n                text : item.$textField\n            }));\n        });\n        \n        $(target).trigger('change');\n    });\n});\nEOT;\n\n        Admin::script($script);\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Filter/Presenter/Presenter.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter\\Presenter;\n\nuse Encore\\Admin\\Grid\\Filter\\AbstractFilter;\n\nabstract class Presenter\n{\n    /**\n     * @var AbstractFilter\n     */\n    protected $filter;\n\n    /**\n     * Set parent filter.\n     *\n     * @param AbstractFilter $filter\n     */\n    public function setParent(AbstractFilter $filter)\n    {\n        $this->filter = $filter;\n    }\n\n    /**\n     * @see https://stackoverflow.com/questions/19901850/how-do-i-get-an-objects-unqualified-short-class-name\n     *\n     * @return string\n     */\n    public function view(): string\n    {\n        $reflect = new \\ReflectionClass(get_called_class());\n\n        return 'admin::filter.'.strtolower($reflect->getShortName());\n    }\n\n    /**\n     * Set default value for filter.\n     *\n     * @param $default\n     *\n     * @return $this\n     */\n    public function default($default)\n    {\n        $this->filter->default($default);\n\n        return $this;\n    }\n\n    /**\n     * Blade template variables for this presenter.\n     *\n     * @return array\n     */\n    public function variables(): array\n    {\n        return [];\n    }\n}\n"
  },
  {
    "path": "src/Grid/Filter/Presenter/Radio.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter\\Presenter;\n\nuse Encore\\Admin\\Facades\\Admin;\nuse Illuminate\\Contracts\\Support\\Arrayable;\n\nclass Radio extends Presenter\n{\n    /**\n     * @var array\n     */\n    protected $options = [];\n\n    /**\n     * Display inline.\n     *\n     * @var bool\n     */\n    protected $inline = true;\n\n    /**\n     * Radio constructor.\n     *\n     * @param array $options\n     */\n    public function __construct($options = [])\n    {\n        if ($options instanceof Arrayable) {\n            $options = $options->toArray();\n        }\n\n        $this->options = (array) $options;\n\n        return $this;\n    }\n\n    /**\n     * Draw stacked radios.\n     *\n     * @return $this\n     */\n    public function stacked(): self\n    {\n        $this->inline = false;\n\n        return $this;\n    }\n\n    protected function prepare()\n    {\n        $script = \"$('.{$this->filter->getId()}').iCheck({radioClass:'iradio_minimal-blue'});\";\n\n        Admin::script($script);\n    }\n\n    /**\n     * @return array\n     */\n    public function variables(): array\n    {\n        $this->prepare();\n\n        return [\n            'options' => $this->options,\n            'inline'  => $this->inline,\n        ];\n    }\n}\n"
  },
  {
    "path": "src/Grid/Filter/Presenter/Select.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter\\Presenter;\n\nuse Encore\\Admin\\Facades\\Admin;\nuse Illuminate\\Contracts\\Support\\Arrayable;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Support\\Arr;\n\nclass Select extends Presenter\n{\n    /**\n     * Options of select.\n     *\n     * @var array\n     */\n    protected $options = [];\n\n    /**\n     * @var array\n     */\n    protected $config = [];\n\n    /**\n     * @var string\n     */\n    protected $script = '';\n\n    /**\n     * Select constructor.\n     *\n     * @param mixed $options\n     */\n    public function __construct($options)\n    {\n        $this->options = $options;\n    }\n\n    /**\n     * Set config for select2.\n     *\n     * all configurations see https://select2.org/configuration/options-api\n     *\n     * @param string $key\n     * @param mixed  $val\n     *\n     * @return $this\n     */\n    public function config($key, $val)\n    {\n        $this->config[$key] = $val;\n\n        return $this;\n    }\n\n    /**\n     * Build options.\n     *\n     * @return array\n     */\n    protected function buildOptions(): array\n    {\n        if (is_string($this->options)) {\n            $this->loadRemoteOptions($this->options);\n        }\n\n        if ($this->options instanceof \\Closure) {\n            $this->options = $this->options->call($this->filter, $this->filter->getValue());\n        }\n\n        if ($this->options instanceof Arrayable) {\n            $this->options = $this->options->toArray();\n        }\n\n        if (empty($this->script)) {\n            $placeholder = json_encode([\n                'id'   => '',\n                'text' => trans('admin.choose'),\n            ]);\n\n            $configs = array_merge([\n                'allowClear'         => true,\n            ], $this->config);\n\n            $configs = json_encode($configs);\n            $configs = substr($configs, 1, strlen($configs) - 2);\n\n            $this->script = <<<SCRIPT\n(function ($){\n    $(\".{$this->getElementClass()}\").select2({\n      placeholder: $placeholder,\n      $configs\n    });\n})(jQuery);\n\nSCRIPT;\n        }\n\n        Admin::script($this->script);\n\n        return is_array($this->options) ? $this->options : [];\n    }\n\n    /**\n     * Load options from current selected resource(s).\n     *\n     * @param string $model\n     * @param string $idField\n     * @param string $textField\n     *\n     * @return $this\n     */\n    public function model($model, $idField = 'id', $textField = 'name')\n    {\n        if (!class_exists($model)\n            || !in_array(Model::class, class_parents($model))\n        ) {\n            throw new \\InvalidArgumentException(\"[$model] must be a valid model class\");\n        }\n\n        $this->options = function ($value) use ($model, $idField, $textField) {\n            if (empty($value)) {\n                return [];\n            }\n\n            $resources = [];\n\n            if (is_array($value)) {\n                if (Arr::isAssoc($value)) {\n                    $resources[] = Arr::get($value, $idField);\n                } else {\n                    $resources = array_column($value, $idField);\n                }\n            } else {\n                $resources[] = $value;\n            }\n\n            return $model::find($resources)->pluck($textField, $idField)->toArray();\n        };\n\n        return $this;\n    }\n\n    /**\n     * Load options from remote.\n     *\n     * @param string $url\n     * @param array  $parameters\n     * @param array  $options\n     *\n     * @return $this\n     */\n    protected function loadRemoteOptions($url, $parameters = [], $options = [])\n    {\n        $ajaxOptions = [\n            'url'  => $url,\n            'data' => $parameters,\n        ];\n        $configs = array_merge([\n            'allowClear'         => true,\n            'placeholder'        => [\n                'id'        => '',\n                'text'      => trans('admin.choose'),\n            ],\n        ], $this->config);\n\n        $configs = json_encode($configs);\n        $configs = substr($configs, 1, strlen($configs) - 2);\n\n        $ajaxOptions = json_encode(array_merge($ajaxOptions, $options), JSON_UNESCAPED_UNICODE);\n\n        $values = (array) $this->filter->getValue();\n        $values = array_filter($values);\n        $values = json_encode($values);\n\n        $this->script = <<<EOT\n\n$.ajax($ajaxOptions).done(function(data) {\n  $(\".{$this->getElementClass()}\").select2({\n    data: data,\n    $configs\n  }).val($values).trigger(\"change\");\n  \n});\n\nEOT;\n    }\n\n    /**\n     * Load options from ajax.\n     *\n     * @param string $resourceUrl\n     * @param $idField\n     * @param $textField\n     */\n    public function ajax($resourceUrl, $idField = 'id', $textField = 'text')\n    {\n        $configs = array_merge([\n            'allowClear'         => true,\n            'placeholder'        => trans('admin.choose'),\n            'minimumInputLength' => 1,\n        ], $this->config);\n\n        $configs = json_encode($configs);\n        $configs = substr($configs, 1, strlen($configs) - 2);\n\n        $this->script = <<<EOT\n\n$(\".{$this->getElementClass()}\").select2({\n  ajax: {\n    url: \"$resourceUrl\",\n    dataType: 'json',\n    delay: 250,\n    data: function (params) {\n      return {\n        q: params.term,\n        page: params.page\n      };\n    },\n    processResults: function (data, params) {\n      params.page = params.page || 1;\n\n      return {\n        results: $.map(data.data, function (d) {\n                   d.id = d.$idField;\n                   d.text = d.$textField;\n                   return d;\n                }),\n        pagination: {\n          more: data.next_page_url\n        }\n      };\n    },\n    cache: true\n  },\n  $configs,\n  escapeMarkup: function (markup) {\n      return markup;\n  }\n});\n\nEOT;\n    }\n\n    /**\n     * @return array\n     */\n    public function variables(): array\n    {\n        return [\n            'options' => $this->buildOptions(),\n            'class'   => $this->getElementClass(),\n        ];\n    }\n\n    /**\n     * @return string\n     */\n    protected function getElementClass(): string\n    {\n        return str_replace('.', '_', $this->filter->getColumn());\n    }\n\n    /**\n     * Load options for other select when change.\n     *\n     * @param string $target\n     * @param string $resourceUrl\n     * @param string $idField\n     * @param string $textField\n     *\n     * @return $this\n     */\n    public function load($target, $resourceUrl, $idField = 'id', $textField = 'text'): self\n    {\n        $column = $this->filter->getColumn();\n\n        $script = <<<EOT\n$(document).off('change', \".{$this->getClass($column)}\");\n$(document).on('change', \".{$this->getClass($column)}\", function () {\n    var target = $(this).closest('form').find(\".{$this->getClass($target)}\");\n    $.get(\"$resourceUrl\",{q : this.value}, function (data) {\n        target.find(\"option\").remove();\n        $.each(data, function (i, item) {\n            $(target).append($('<option>', {\n                value: item.$idField,\n                text : item.$textField\n            }));\n        });\n        \n        $(target).val(null).trigger('change');\n    }, 'json');\n});\nEOT;\n\n        Admin::script($script);\n\n        return $this;\n    }\n\n    /**\n     * Get form element class.\n     *\n     * @param string $target\n     *\n     * @return mixed\n     */\n    protected function getClass($target): string\n    {\n        return str_replace('.', '_', $target);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Filter/Presenter/Text.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter\\Presenter;\n\nuse Encore\\Admin\\Admin;\n\nclass Text extends Presenter\n{\n    /**\n     * @var string\n     */\n    protected $placeholder = '';\n\n    /**\n     * @var string\n     */\n    protected $icon = 'pencil';\n\n    /**\n     * @var string\n     */\n    protected $type = 'text';\n\n    /**\n     * Text constructor.\n     *\n     * @param string $placeholder\n     */\n    public function __construct($placeholder = '')\n    {\n        $this->placeholder($placeholder);\n    }\n\n    /**\n     * Get variables for field template.\n     *\n     * @return array\n     */\n    public function variables(): array\n    {\n        return [\n            'placeholder' => $this->placeholder,\n            'icon'        => $this->icon,\n            'type'        => $this->type,\n            'group'       => $this->filter->group,\n        ];\n    }\n\n    /**\n     * Set input placeholder.\n     *\n     * @param string $placeholder\n     *\n     * @return $this\n     */\n    public function placeholder($placeholder = ''): self\n    {\n        $this->placeholder = $placeholder;\n\n        return $this;\n    }\n\n    /**\n     * @return Text\n     */\n    public function url(): self\n    {\n        return $this->inputmask(['alias' => 'url'], 'internet-explorer');\n    }\n\n    /**\n     * @return Text\n     */\n    public function email(): self\n    {\n        return $this->inputmask(['alias' => 'email'], 'envelope');\n    }\n\n    /**\n     * @return Text\n     */\n    public function integer(): self\n    {\n        return $this->inputmask(['alias' => 'integer']);\n    }\n\n    /**\n     * @param array $options\n     *\n     * @see https://github.com/RobinHerbots/Inputmask/blob/4.x/README_numeric.md\n     *\n     * @return Text\n     */\n    public function decimal($options = []): self\n    {\n        return $this->inputmask(array_merge($options, ['alias' => 'decimal']));\n    }\n\n    /**\n     * @param array $options\n     *\n     * @see https://github.com/RobinHerbots/Inputmask/blob/4.x/README_numeric.md\n     *\n     * @return Text\n     */\n    public function currency($options = []): self\n    {\n        return $this->inputmask(array_merge($options, [\n            'alias'              => 'currency',\n            'prefix'             => '',\n            'removeMaskOnSubmit' => true,\n        ]));\n    }\n\n    /**\n     * @param array $options\n     *\n     * @see https://github.com/RobinHerbots/Inputmask/blob/4.x/README_numeric.md\n     *\n     * @return Text\n     */\n    public function percentage($options = [])\n    {\n        $options = array_merge(['alias' => 'percentage'], $options);\n\n        return $this->inputmask($options);\n    }\n\n    /**\n     * @return Text\n     */\n    public function ip(): self\n    {\n        return $this->inputmask(['alias' => 'ip'], 'laptop');\n    }\n\n    /**\n     * @return Text\n     */\n    public function mac(): self\n    {\n        return $this->inputmask(['alias' => 'mac'], 'laptop');\n    }\n\n    /**\n     * @param string $mask\n     *\n     * @return Text\n     */\n    public function mobile($mask = '19999999999'): self\n    {\n        return $this->inputmask(compact('mask'), 'phone');\n    }\n\n    /**\n     * @param array  $options\n     * @param string $icon\n     *\n     * @return $this\n     */\n    public function inputmask($options = [], $icon = 'pencil'): self\n    {\n        $options = json_encode($options);\n\n        $ids = (array) $this->filter->getId();\n\n        foreach ($ids as $id) {\n            Admin::script(\"$('#{$this->filter->getFilterBoxId()} input.{$id}').inputmask($options);\");\n        }\n\n        $this->icon = $icon;\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Filter/Scope.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter;\n\nuse Illuminate\\Contracts\\Support\\Renderable;\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Support\\Str;\n\nclass Scope implements Renderable\n{\n    const QUERY_NAME = '_scope_';\n    const SEPARATOR = '_separator_';\n\n    /**\n     * @var string\n     */\n    public $key = '';\n\n    /**\n     * @var string\n     */\n    protected $label = '';\n\n    /**\n     * @var Collection\n     */\n    protected $queries;\n\n    /**\n     * Scope constructor.\n     *\n     * @param $key\n     * @param string $label\n     */\n    public function __construct($key, $label = '')\n    {\n        $this->key = $key;\n        $this->label = $label ? $label : Str::studly($key);\n\n        $this->queries = new Collection();\n    }\n\n    /**\n     * Get label.\n     *\n     * @return string\n     */\n    public function getLabel()\n    {\n        return $this->label;\n    }\n\n    /**\n     * Get model query conditions.\n     *\n     * @return array\n     */\n    public function condition()\n    {\n        return $this->queries->map(function ($query) {\n            return [$query['method'] => $query['arguments']];\n        })->toArray();\n    }\n\n    /**\n     * @return string\n     */\n    public function render()\n    {\n        if ($this->key == static::SEPARATOR) {\n            return '<li role=\"separator\" class=\"divider\"></li>';\n        }\n\n        $url = request()->fullUrlWithQuery([static::QUERY_NAME => $this->key]);\n\n        return \"<li><a href=\\\"{$url}\\\">{$this->label}</a></li>\";\n    }\n\n    /**\n     * Set this scope as default.\n     *\n     * @return self\n     */\n    public function asDefault()\n    {\n        if (!request()->input('_scope_')) {\n            request()->merge(['_scope_' => $this->key]);\n        }\n\n        return $this;\n    }\n\n    /**\n     * @param string $method\n     * @param array  $arguments\n     *\n     * @return $this\n     */\n    public function __call($method, $arguments)\n    {\n        $this->queries->push(compact('method', 'arguments'));\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Filter/StartsWith.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter;\n\nclass StartsWith extends Like\n{\n    protected $exprFormat = '{value}%';\n}\n"
  },
  {
    "path": "src/Grid/Filter/Where.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter;\n\nuse Illuminate\\Support\\Arr;\n\nclass Where extends AbstractFilter\n{\n    /**\n     * Query closure.\n     *\n     * @var \\Closure\n     */\n    protected $where;\n\n    /**\n     * Input value from presenter.\n     *\n     * @var mixed\n     */\n    public $input;\n\n    /**\n     * Where constructor.\n     *\n     * @param \\Closure $query\n     * @param string   $label\n     * @param string   $column\n     */\n    public function __construct(\\Closure $query, $label, $column = null)\n    {\n        $this->where = $query;\n\n        $this->label = $this->formatLabel($label);\n        $this->column = $column ?: static::getQueryHash($query, $this->label);\n        $this->id = $this->formatId($this->column);\n\n        $this->setupDefaultPresenter();\n    }\n\n    /**\n     * Get the hash string of query closure.\n     *\n     * @param \\Closure $closure\n     * @param string   $label\n     *\n     * @return string\n     */\n    public static function getQueryHash(\\Closure $closure, $label = '')\n    {\n        $reflection = new \\ReflectionFunction($closure);\n\n        return md5($reflection->getFileName().$reflection->getStartLine().$reflection->getEndLine().$label);\n    }\n\n    /**\n     * Get condition of this filter.\n     *\n     * @param array $inputs\n     *\n     * @return array|mixed|void\n     */\n    public function condition($inputs)\n    {\n        $value = Arr::get($inputs, $this->column ?: static::getQueryHash($this->where, $this->label));\n\n        if (is_null($value)) {\n            return;\n        }\n\n        $this->input = $this->value = $value;\n\n        return $this->buildCondition($this->where->bindTo($this));\n    }\n}\n"
  },
  {
    "path": "src/Grid/Filter/Year.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Filter;\n\nclass Year extends Date\n{\n    /**\n     * {@inheritdoc}\n     */\n    protected $query = 'whereYear';\n\n    /**\n     * @var string\n     */\n    protected $fieldName = 'year';\n}\n"
  },
  {
    "path": "src/Grid/Filter.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid;\n\nuse Encore\\Admin\\Grid\\Filter\\AbstractFilter;\nuse Encore\\Admin\\Grid\\Filter\\Layout\\Layout;\nuse Encore\\Admin\\Grid\\Filter\\Scope;\nuse Illuminate\\Contracts\\Support\\Arrayable;\nuse Illuminate\\Contracts\\Support\\Renderable;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Support\\Str;\n\n/**\n * Class Filter.\n *\n * @method AbstractFilter equal($column, $label = '')\n * @method AbstractFilter notEqual($column, $label = '')\n * @method AbstractFilter leftLike($column, $label = '')\n * @method AbstractFilter like($column, $label = '')\n * @method AbstractFilter contains($column, $label = '')\n * @method AbstractFilter startsWith($column, $label = '')\n * @method AbstractFilter endsWith($column, $label = '')\n * @method AbstractFilter ilike($column, $label = '')\n * @method AbstractFilter gt($column, $label = '')\n * @method AbstractFilter lt($column, $label = '')\n * @method AbstractFilter between($column, $label = '')\n * @method AbstractFilter in($column, $label = '')\n * @method AbstractFilter notIn($column, $label = '')\n * @method AbstractFilter where($callback, $label = '', $column = null)\n * @method AbstractFilter date($column, $label = '')\n * @method AbstractFilter day($column, $label = '')\n * @method AbstractFilter month($column, $label = '')\n * @method AbstractFilter year($column, $label = '')\n * @method AbstractFilter hidden($name, $value)\n * @method AbstractFilter group($column, $label = '', $builder = null)\n */\nclass Filter implements Renderable\n{\n    /**\n     * @var Model\n     */\n    protected $model;\n\n    /**\n     * @var array\n     */\n    protected $filters = [];\n\n    /**\n     * @var array\n     */\n    protected static $supports = [\n        'equal'      => Filter\\Equal::class,\n        'notEqual'   => Filter\\NotEqual::class,\n        'ilike'      => Filter\\Ilike::class,\n        'like'       => Filter\\Like::class,\n        'gt'         => Filter\\Gt::class,\n        'lt'         => Filter\\Lt::class,\n        'between'    => Filter\\Between::class,\n        'group'      => Filter\\Group::class,\n        'where'      => Filter\\Where::class,\n        'in'         => Filter\\In::class,\n        'notIn'      => Filter\\NotIn::class,\n        'date'       => Filter\\Date::class,\n        'day'        => Filter\\Day::class,\n        'month'      => Filter\\Month::class,\n        'year'       => Filter\\Year::class,\n        'hidden'     => Filter\\Hidden::class,\n        'contains'   => Filter\\Like::class,\n        'startsWith' => Filter\\StartsWith::class,\n        'endsWith'   => Filter\\EndsWith::class,\n    ];\n\n    /**\n     * If use id filter.\n     *\n     * @var bool\n     */\n    protected $useIdFilter = true;\n\n    /**\n     * Id filter was removed.\n     *\n     * @var bool\n     */\n    protected $idFilterRemoved = false;\n\n    /**\n     * Action of search form.\n     *\n     * @var string\n     */\n    protected $action;\n\n    /**\n     * @var string\n     */\n    public $view = 'admin::filter.container';\n\n    /**\n     * @var string\n     */\n    protected $filterID = 'filter-box';\n\n    /**\n     * @var string\n     */\n    protected $name = '';\n\n    /**\n     * @var bool\n     */\n    public $expand = false;\n\n    /**\n     * @var Collection\n     */\n    protected $scopes;\n\n    /**\n     * @var Layout\n     */\n    protected $layout;\n\n    /**\n     * Set this filter only in the layout.\n     *\n     * @var bool\n     */\n    protected $thisFilterLayoutOnly = false;\n\n    /**\n     * Columns of filter that are layout-only.\n     *\n     * @var array\n     */\n    protected $layoutOnlyFilterColumns = [];\n\n    /**\n     * Primary key of giving model.\n     *\n     * @var mixed\n     */\n    protected $primaryKey;\n\n    /**\n     * Create a new filter instance.\n     *\n     * @param Model $model\n     */\n    public function __construct(Model $model)\n    {\n        $this->model = $model;\n\n        $this->primaryKey = $this->model->eloquent()->getKeyName();\n\n        $this->initLayout();\n\n        $this->equal($this->primaryKey, strtoupper($this->primaryKey));\n        $this->scopes = new Collection();\n    }\n\n    /**\n     * Initialize filter layout.\n     */\n    protected function initLayout()\n    {\n        $this->layout = new Filter\\Layout\\Layout($this);\n    }\n\n    /**\n     * Set action of search form.\n     *\n     * @param string $action\n     *\n     * @return $this\n     */\n    public function setAction($action)\n    {\n        $this->action = $action;\n\n        return $this;\n    }\n\n    /**\n     * Get grid model.\n     *\n     * @return Model\n     */\n    public function getModel()\n    {\n        $conditions = array_merge(\n            $this->conditions(),\n            $this->scopeConditions()\n        );\n\n        return $this->model->addConditions($conditions);\n    }\n\n    /**\n     * Set ID of search form.\n     *\n     * @param string $filterID\n     *\n     * @return $this\n     */\n    public function setFilterID($filterID)\n    {\n        $this->filterID = $filterID;\n\n        return $this;\n    }\n\n    /**\n     * Get filter ID.\n     *\n     * @return string\n     */\n    public function getFilterID()\n    {\n        return $this->filterID;\n    }\n\n    /**\n     * @param $name\n     *\n     * @return $this\n     */\n    public function setName($name)\n    {\n        $this->name = $name;\n\n        $this->setFilterID(\"{$this->name}-{$this->filterID}\");\n\n        return $this;\n    }\n\n    /**\n     * @return string\n     */\n    public function getName()\n    {\n        return $this->name;\n    }\n\n    /**\n     * Disable Id filter.\n     *\n     * @return $this\n     */\n    public function disableIdFilter(bool $disable = true)\n    {\n        $this->useIdFilter = !$disable;\n\n        return $this;\n    }\n\n    /**\n     * Remove ID filter if needed.\n     */\n    public function removeIDFilterIfNeeded()\n    {\n        if (!$this->useIdFilter && !$this->idFilterRemoved) {\n            $this->removeDefaultIDFilter();\n\n            $this->layout->removeDefaultIDFilter();\n\n            $this->idFilterRemoved = true;\n        }\n    }\n\n    /**\n     * Remove the default ID filter.\n     */\n    protected function removeDefaultIDFilter()\n    {\n        array_shift($this->filters);\n    }\n\n    /**\n     * Remove filter by filter id.\n     *\n     * @param mixed $id\n     */\n    public function removeFilterByID($id)\n    {\n        $this->filters = array_filter($this->filters, function (AbstractFilter $filter) use ($id) {\n            return $filter->getId() != $id;\n        });\n    }\n\n    /**\n     * Get all conditions of the filters.\n     *\n     * @return array\n     */\n    public function conditions()\n    {\n        $inputs = Arr::dot(request()->all());\n\n        $inputs = array_filter($inputs, function ($input) {\n            return $input !== '' && !is_null($input);\n        });\n\n        $this->sanitizeInputs($inputs);\n\n        if (empty($inputs)) {\n            return [];\n        }\n\n        $params = [];\n\n        foreach ($inputs as $key => $value) {\n            Arr::set($params, $key, $value);\n        }\n\n        $conditions = [];\n\n        $this->removeIDFilterIfNeeded();\n\n        foreach ($this->filters() as $filter) {\n            if (in_array($column = $filter->getColumn(), $this->layoutOnlyFilterColumns)) {\n                $filter->default(Arr::get($params, $column));\n            } else {\n                $conditions[] = $filter->condition($params);\n            }\n        }\n\n        return tap(array_filter($conditions), function ($conditions) {\n            if (!empty($conditions)) {\n                $this->expand();\n            }\n        });\n    }\n\n    /**\n     * @param $inputs\n     *\n     * @return array\n     */\n    protected function sanitizeInputs(&$inputs)\n    {\n        if (!$this->name) {\n            return $inputs;\n        }\n\n        $inputs = collect($inputs)->filter(function ($input, $key) {\n            return Str::startsWith($key, \"{$this->name}_\");\n        })->mapWithKeys(function ($val, $key) {\n            $key = str_replace(\"{$this->name}_\", '', $key);\n\n            return [$key => $val];\n        })->toArray();\n    }\n\n    /**\n     * Set this filter layout only.\n     *\n     * @return $this\n     */\n    public function layoutOnly()\n    {\n        $this->thisFilterLayoutOnly = true;\n\n        return $this;\n    }\n\n    /**\n     * Add a filter to grid.\n     *\n     * @param AbstractFilter $filter\n     *\n     * @return AbstractFilter\n     */\n    protected function addFilter(AbstractFilter $filter)\n    {\n        $this->layout->addFilter($filter);\n\n        $filter->setParent($this);\n\n        if ($this->thisFilterLayoutOnly) {\n            $this->thisFilterLayoutOnly = false;\n            $this->layoutOnlyFilterColumns[] = $filter->getColumn();\n        }\n\n        return $this->filters[] = $filter;\n    }\n\n    /**\n     * Use a custom filter.\n     *\n     * @param AbstractFilter $filter\n     *\n     * @return AbstractFilter\n     */\n    public function use(AbstractFilter $filter)\n    {\n        return $this->addFilter($filter);\n    }\n\n    /**\n     * Get all filters.\n     *\n     * @return AbstractFilter[]\n     */\n    public function filters()\n    {\n        return $this->filters;\n    }\n\n    /**\n     * @param string $key\n     * @param string $label\n     *\n     * @return mixed\n     */\n    public function scope($key, $label = '')\n    {\n        return tap(new Scope($key, $label), function (Scope $scope) {\n            return $this->scopes->push($scope);\n        });\n    }\n\n    /**\n     * Add separator in filter scope.\n     *\n     * @return mixed\n     */\n    public function scopeSeparator()\n    {\n        return $this->scope(Scope::SEPARATOR);\n    }\n\n    /**\n     * Get all filter scopes.\n     *\n     * @return Collection\n     */\n    public function getScopes()\n    {\n        return $this->scopes;\n    }\n\n    /**\n     * Get current scope.\n     *\n     * @return Scope|null\n     */\n    public function getCurrentScope()\n    {\n        $key = request(Scope::QUERY_NAME);\n\n        return $this->scopes->first(function ($scope) use ($key) {\n            return $scope->key == $key;\n        });\n    }\n\n    /**\n     * Get scope conditions.\n     *\n     * @return array\n     */\n    protected function scopeConditions()\n    {\n        if ($scope = $this->getCurrentScope()) {\n            return $scope->condition();\n        }\n\n        return [];\n    }\n\n    /**\n     * Add a new layout column.\n     *\n     * @param int      $width\n     * @param \\Closure $closure\n     *\n     * @return $this\n     */\n    public function column($width, \\Closure $closure)\n    {\n        $width = $width < 1 ? round(12 * $width) : $width;\n\n        $this->layout->column($width, $closure);\n\n        return $this;\n    }\n\n    /**\n     * Expand filter container.\n     *\n     * @return $this\n     */\n    public function expand()\n    {\n        $this->expand = true;\n\n        return $this;\n    }\n\n    /**\n     * Execute the filter with conditions.\n     *\n     * @param bool $toArray\n     *\n     * @return array|Collection|mixed\n     */\n    public function execute($toArray = true)\n    {\n        if (method_exists($this->model->eloquent(), 'paginate')) {\n            $this->model->usePaginate(true);\n\n            return $this->model->buildData($toArray);\n        }\n        $conditions = array_merge(\n            $this->conditions(),\n            $this->scopeConditions()\n        );\n\n        return $this->model->addConditions($conditions)->buildData($toArray);\n    }\n\n    /**\n     * @param callable $callback\n     * @param int      $count\n     *\n     * @return bool\n     */\n    public function chunk(callable $callback, $count = 100)\n    {\n        $conditions = array_merge(\n            $this->conditions(),\n            $this->scopeConditions()\n        );\n\n        return $this->model->addConditions($conditions)->chunk($callback, $count);\n    }\n\n    /**\n     * Get the string contents of the filter view.\n     *\n     * @return \\Illuminate\\View\\View|string\n     */\n    public function render()\n    {\n        $this->removeIDFilterIfNeeded();\n\n        if (empty($this->filters)) {\n            return '';\n        }\n\n        return view($this->view)->with([\n            'action'   => $this->action ?: $this->urlWithoutFilters(),\n            'layout'   => $this->layout,\n            'filterID' => $this->filterID,\n            'expand'   => $this->expand,\n        ])->render();\n    }\n\n    /**\n     * Get url without filter queryString.\n     *\n     * @return string\n     */\n    public function urlWithoutFilters()\n    {\n        /** @var Collection $columns */\n        $columns = collect($this->filters)->map->getColumn()->flatten();\n\n        $pageKey = 'page';\n\n        if ($gridName = $this->model->getGrid()->getName()) {\n            $pageKey = \"{$gridName}_{$pageKey}\";\n        }\n\n        $columns->push($pageKey);\n\n        $groupNames = collect($this->filters)->filter(function ($filter) {\n            return $filter instanceof Filter\\Group;\n        })->map(function (AbstractFilter $filter) {\n            return \"{$filter->getId()}_group\";\n        });\n\n        return $this->fullUrlWithoutQuery(\n            $columns->merge($groupNames)\n        );\n    }\n\n    /**\n     * Get url without scope queryString.\n     *\n     * @return string\n     */\n    public function urlWithoutScopes()\n    {\n        return $this->fullUrlWithoutQuery(Scope::QUERY_NAME);\n    }\n\n    /**\n     * Get full url without query strings.\n     *\n     * @param Arrayable|array|string $keys\n     *\n     * @return string\n     */\n    protected function fullUrlWithoutQuery($keys)\n    {\n        if ($keys instanceof Arrayable) {\n            $keys = $keys->toArray();\n        }\n\n        $keys = (array) $keys;\n\n        $request = request();\n\n        $query = $request->query();\n        Arr::forget($query, $keys);\n\n        $question = $request->getBaseUrl().$request->getPathInfo() == '/' ? '/?' : '?';\n\n        return count($request->query()) > 0\n            ? $request->url().$question.http_build_query($query)\n            : $request->fullUrl();\n    }\n\n    /**\n     * @param string $name\n     * @param string $filterClass\n     */\n    public static function extend($name, $filterClass)\n    {\n        if (!is_subclass_of($filterClass, AbstractFilter::class)) {\n            throw new \\InvalidArgumentException(\"The class [$filterClass] must be a type of \".AbstractFilter::class.'.');\n        }\n\n        static::$supports[$name] = $filterClass;\n    }\n\n    /**\n     * @param string $abstract\n     * @param array  $arguments\n     *\n     * @return AbstractFilter\n     */\n    public function resolveFilter($abstract, $arguments)\n    {\n        if (isset(static::$supports[$abstract])) {\n            return new static::$supports[$abstract](...$arguments);\n        }\n    }\n\n    /**\n     * Generate a filter object and add to grid.\n     *\n     * @param string $method\n     * @param array  $arguments\n     *\n     * @return AbstractFilter|$this\n     */\n    public function __call($method, $arguments)\n    {\n        if ($filter = $this->resolveFilter($method, $arguments)) {\n            return $this->addFilter($filter);\n        }\n\n        return $this;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Model.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid;\n\nuse Encore\\Admin\\Grid;\nuse Encore\\Admin\\Middleware\\Pjax;\nuse Illuminate\\Database\\Eloquent\\Model as EloquentModel;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsTo;\nuse Illuminate\\Database\\Eloquent\\Relations\\HasMany;\nuse Illuminate\\Database\\Eloquent\\Relations\\HasOne;\nuse Illuminate\\Database\\Eloquent\\Relations\\Relation;\nuse Illuminate\\Database\\Query\\Expression;\nuse Illuminate\\Pagination\\LengthAwarePaginator;\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Support\\Facades\\Request;\nuse Illuminate\\Support\\Str;\n\nclass Model\n{\n    /**\n     * Eloquent model instance of the grid model.\n     *\n     * @var EloquentModel\n     */\n    protected $model;\n\n    /**\n     * @var EloquentModel\n     */\n    protected $originalModel;\n\n    /**\n     * Array of queries of the eloquent model.\n     *\n     * @var \\Illuminate\\Support\\Collection\n     */\n    protected $queries;\n\n    /**\n     * Sort parameters of the model.\n     *\n     * @var array\n     */\n    protected $sort;\n\n    /**\n     * @var array\n     */\n    protected $data = [];\n\n    /*\n     * 20 items per page as default.\n     *\n     * @var int\n     */\n    protected $perPage = 20;\n\n    /**\n     * If the model use pagination.\n     *\n     * @var bool\n     */\n    protected $usePaginate = true;\n\n    /**\n     * The query string variable used to store the per-page.\n     *\n     * @var string\n     */\n    protected $perPageName = 'per_page';\n\n    /**\n     * The query string variable used to store the sort.\n     *\n     * @var string\n     */\n    protected $sortName = '_sort';\n\n    /**\n     * Collection callback.\n     *\n     * @var \\Closure\n     */\n    protected $collectionCallback;\n\n    /**\n     * @var Grid\n     */\n    protected $grid;\n\n    /**\n     * @var Relation\n     */\n    protected $relation;\n\n    /**\n     * Create a new grid model instance.\n     *\n     * @param EloquentModel $model\n     * @param Grid          $grid\n     */\n    public function __construct(EloquentModel $model, Grid $grid = null)\n    {\n        $this->model = $model;\n\n        $this->originalModel = $model;\n\n        $this->grid = $grid;\n\n        $this->queries = collect();\n    }\n\n    /**\n     * @return EloquentModel\n     */\n    public function getOriginalModel()\n    {\n        return $this->originalModel;\n    }\n\n    /**\n     * Get the eloquent model of the grid model.\n     *\n     * @return EloquentModel\n     */\n    public function eloquent()\n    {\n        return $this->model;\n    }\n\n    /**\n     * Enable or disable pagination.\n     *\n     * @param bool $use\n     */\n    public function usePaginate($use = true)\n    {\n        $this->usePaginate = $use;\n    }\n\n    /**\n     * Get the query string variable used to store the per-page.\n     *\n     * @return string\n     */\n    public function getPerPageName()\n    {\n        return $this->perPageName;\n    }\n\n    /**\n     * Set the query string variable used to store the per-page.\n     *\n     * @param string $name\n     *\n     * @return $this\n     */\n    public function setPerPageName($name)\n    {\n        $this->perPageName = $name;\n\n        return $this;\n    }\n\n    /**\n     * Get per-page number.\n     *\n     * @return int\n     */\n    public function getPerPage()\n    {\n        return $this->perPage;\n    }\n\n    /**\n     * Set per-page number.\n     *\n     * @param int $perPage\n     *\n     * @return $this\n     */\n    public function setPerPage($perPage)\n    {\n        $this->perPage = $perPage;\n\n        $this->__call('paginate', [$perPage]);\n\n        return $this;\n    }\n\n    /**\n     * Get the query string variable used to store the sort.\n     *\n     * @return string\n     */\n    public function getSortName()\n    {\n        return $this->sortName;\n    }\n\n    /**\n     * Set the query string variable used to store the sort.\n     *\n     * @param string $name\n     *\n     * @return $this\n     */\n    public function setSortName($name)\n    {\n        $this->sortName = $name;\n\n        return $this;\n    }\n\n    /**\n     * Set parent grid instance.\n     *\n     * @param Grid $grid\n     *\n     * @return $this\n     */\n    public function setGrid(Grid $grid)\n    {\n        $this->grid = $grid;\n\n        return $this;\n    }\n\n    /**\n     * Get parent gird instance.\n     *\n     * @return Grid\n     */\n    public function getGrid()\n    {\n        return $this->grid;\n    }\n\n    /**\n     * @param Relation $relation\n     *\n     * @return $this\n     */\n    public function setRelation(Relation $relation)\n    {\n        $this->relation = $relation;\n\n        return $this;\n    }\n\n    /**\n     * @return Relation\n     */\n    public function getRelation()\n    {\n        return $this->relation;\n    }\n\n    /**\n     * Get constraints.\n     *\n     * @return array|bool\n     */\n    public function getConstraints()\n    {\n        if ($this->relation instanceof HasMany) {\n            return [\n                $this->relation->getForeignKeyName() => $this->relation->getParentKey(),\n            ];\n        }\n\n        return false;\n    }\n\n    /**\n     * Set collection callback.\n     *\n     * @param \\Closure $callback\n     *\n     * @return $this\n     */\n    public function collection(\\Closure $callback = null)\n    {\n        $this->collectionCallback = $callback;\n\n        return $this;\n    }\n\n    /**\n     * Build.\n     *\n     * @param bool $toArray\n     *\n     * @return array|Collection|mixed\n     */\n    public function buildData($toArray = true)\n    {\n        if (empty($this->data)) {\n            $collection = $this->get();\n\n            if ($this->collectionCallback) {\n                $collection = call_user_func($this->collectionCallback, $collection);\n            }\n\n            if ($toArray) {\n                $this->data = $collection->toArray();\n            } else {\n                $this->data = $collection;\n            }\n        }\n\n        return $this->data;\n    }\n\n    /**\n     * @param callable $callback\n     * @param int      $count\n     *\n     * @return bool\n     */\n    public function chunk($callback, $count = 100)\n    {\n        if ($this->usePaginate) {\n            return $this->buildData(false)->chunk($count)->each($callback);\n        }\n\n        $this->setSort();\n\n        $this->queries->reject(function ($query) {\n            return $query['method'] == 'paginate';\n        })->each(function ($query) {\n            $this->model = $this->model->{$query['method']}(...$query['arguments']);\n        });\n\n        return $this->model->chunk($count, $callback);\n    }\n\n    /**\n     * Add conditions to grid model.\n     *\n     * @param array $conditions\n     *\n     * @return $this\n     */\n    public function addConditions(array $conditions)\n    {\n        foreach ($conditions as $condition) {\n            call_user_func_array([$this, key($condition)], current($condition));\n        }\n\n        return $this;\n    }\n\n    /**\n     * Get table of the model.\n     *\n     * @return string\n     */\n    public function getTable()\n    {\n        return $this->model->getTable();\n    }\n\n    /**\n     * @throws \\Exception\n     *\n     * @return Collection\n     */\n    protected function get()\n    {\n        if ($this->model instanceof LengthAwarePaginator) {\n            return $this->model;\n        }\n\n        if ($this->relation) {\n            $this->model = $this->relation;\n        }\n\n        $this->setSort();\n        $this->setPaginate();\n\n        $this->queries->unique()->each(function ($query) {\n            $this->model = call_user_func_array([$this->model, $query['method']], $query['arguments']);\n        });\n\n        if ($this->model instanceof Collection) {\n            return $this->model;\n        }\n\n        if ($this->model instanceof LengthAwarePaginator) {\n            $this->handleInvalidPage($this->model);\n\n            return $this->model->getCollection();\n        }\n\n        throw new \\Exception('Grid query error');\n    }\n\n    /**\n     * @return \\Illuminate\\Database\\Eloquent\\Builder|EloquentModel\n     */\n    public function getQueryBuilder()\n    {\n        if ($this->relation) {\n            return $this->relation->getQuery();\n        }\n\n        $this->setSort();\n\n        $queryBuilder = $this->originalModel;\n\n        $this->queries->reject(function ($query) {\n            return in_array($query['method'], ['get', 'paginate']);\n        })->each(function ($query) use (&$queryBuilder) {\n            $queryBuilder = $queryBuilder->{$query['method']}(...$query['arguments']);\n        });\n\n        return $queryBuilder;\n    }\n\n    /**\n     * If current page is greater than last page, then redirect to last page.\n     *\n     * @param LengthAwarePaginator $paginator\n     *\n     * @return void\n     */\n    protected function handleInvalidPage(LengthAwarePaginator $paginator)\n    {\n        if ($paginator->lastPage() && $paginator->currentPage() > $paginator->lastPage()) {\n            $lastPageUrl = Request::fullUrlWithQuery([\n                $paginator->getPageName() => $paginator->lastPage(),\n            ]);\n\n            Pjax::respond(redirect($lastPageUrl));\n        }\n    }\n\n    /**\n     * Set the grid paginate.\n     *\n     * @return void\n     */\n    protected function setPaginate()\n    {\n        $paginate = $this->findQueryByMethod('paginate');\n\n        $this->queries = $this->queries->reject(function ($query) {\n            return $query['method'] == 'paginate';\n        });\n\n        if (!$this->usePaginate) {\n            $query = [\n                'method'    => 'get',\n                'arguments' => [],\n            ];\n        } else {\n            $query = [\n                'method'    => 'paginate',\n                'arguments' => $this->resolvePerPage($paginate),\n            ];\n        }\n\n        $this->queries->push($query);\n    }\n\n    /**\n     * Resolve perPage for pagination.\n     *\n     * @param array|null $paginate\n     *\n     * @return array\n     */\n    protected function resolvePerPage($paginate)\n    {\n        if ($perPage = request($this->perPageName)) {\n            if (is_array($paginate)) {\n                $paginate['arguments'][0] = (int) $perPage;\n\n                return $paginate['arguments'];\n            }\n\n            $this->perPage = (int) $perPage;\n        }\n\n        if (isset($paginate['arguments'][0])) {\n            return $paginate['arguments'];\n        }\n\n        if ($name = $this->grid->getName()) {\n            return [$this->perPage, ['*'], \"{$name}_page\"];\n        }\n\n        return [$this->perPage];\n    }\n\n    /**\n     * Find query by method name.\n     *\n     * @param $method\n     *\n     * @return static\n     */\n    protected function findQueryByMethod($method)\n    {\n        return $this->queries->first(function ($query) use ($method) {\n            return $query['method'] == $method;\n        });\n    }\n\n    /**\n     * Set the grid sort.\n     *\n     * @return void\n     */\n    protected function setSort()\n    {\n        $this->sort = \\request($this->sortName, []);\n        if (!is_array($this->sort)) {\n            return;\n        }\n\n        $columnName = $this->sort['column'] ?? null;\n        if ($columnName === null || empty($this->sort['type'])) {\n            return;\n        }\n\n        $columnNameContainsDots = Str::contains($columnName, '.');\n        $isRelation = $this->queries->contains(function ($query) use ($columnName) {\n            // relationship should be camel case\n            $columnName = Str::camel(Str::before($columnName, '.'));\n\n            return $query['method'] === 'with' && in_array($columnName, $query['arguments'], true);\n        });\n        if ($columnNameContainsDots === true && $isRelation) {\n            $this->setRelationSort($columnName);\n        } else {\n            $this->resetOrderBy();\n\n            if ($columnNameContainsDots === true) {\n                //json\n                $this->resetOrderBy();\n                $explodedCols = explode('.', $this->sort['column']);\n                $col = array_shift($explodedCols);\n                $parts = implode('.', $explodedCols);\n                $columnName = \"JSON_EXTRACT({$col}, '$.{$parts}')\";\n            }\n\n            // get column. if contains \"cast\", set set column as cast\n            if (!empty($this->sort['cast'])) {\n                $column = \"CAST({$columnName} AS {$this->sort['cast']}) {$this->sort['type']}\";\n                $method = 'orderByRaw';\n                $arguments = [$column];\n            } else {\n                $column = $columnNameContainsDots ? new Expression($columnName) : $columnName;\n                $method = 'orderBy';\n                $arguments = [$column, $this->sort['type']];\n            }\n\n            $this->queries->push([\n                'method'    => $method,\n                'arguments' => $arguments,\n            ]);\n        }\n    }\n\n    /**\n     * Set relation sort.\n     *\n     * @param string $column\n     *\n     * @return void\n     */\n    protected function setRelationSort($column)\n    {\n        list($relationName, $relationColumn) = explode('.', $column);\n        // relationship should be camel case\n        $relationName = Str::camel($relationName);\n\n        if ($this->queries->contains(function ($query) use ($relationName) {\n            return $query['method'] == 'with' && in_array($relationName, $query['arguments']);\n        })) {\n            $relation = $this->model->$relationName();\n\n            $this->queries->push([\n                'method'    => 'select',\n                'arguments' => [$this->model->getTable().'.*'],\n            ]);\n\n            $this->queries->push([\n                'method'    => 'join',\n                'arguments' => $this->joinParameters($relation),\n            ]);\n\n            $this->resetOrderBy();\n\n            $this->queries->push([\n                'method'    => 'orderBy',\n                'arguments' => [\n                    $relation->getRelated()->getTable().'.'.$relationColumn,\n                    $this->sort['type'],\n                ],\n            ]);\n        }\n    }\n\n    /**\n     * Reset orderBy query.\n     *\n     * @return void\n     */\n    public function resetOrderBy()\n    {\n        $this->queries = $this->queries->reject(function ($query) {\n            return $query['method'] == 'orderBy' || $query['method'] == 'orderByDesc';\n        });\n    }\n\n    /**\n     * Build join parameters for related model.\n     *\n     * `HasOne` and `BelongsTo` relation has different join parameters.\n     *\n     * @param Relation $relation\n     *\n     * @throws \\Exception\n     *\n     * @return array\n     */\n    protected function joinParameters(Relation $relation)\n    {\n        $relatedTable = $relation->getRelated()->getTable();\n\n        if ($relation instanceof BelongsTo) {\n            $foreignKeyMethod = version_compare(app()->version(), '5.8.0', '<') ? 'getForeignKey' : 'getForeignKeyName';\n\n            return [\n                $relatedTable,\n                $relation->{$foreignKeyMethod}(),\n                '=',\n                $relatedTable.'.'.$relation->getRelated()->getKeyName(),\n            ];\n        }\n\n        if ($relation instanceof HasOne) {\n            return [\n                $relatedTable,\n                $relation->getQualifiedParentKeyName(),\n                '=',\n                $relation->getQualifiedForeignKeyName(),\n            ];\n        }\n\n        throw new \\Exception('Related sortable only support `HasOne` and `BelongsTo` relation.');\n    }\n\n    /**\n     * @param string $method\n     * @param array  $arguments\n     *\n     * @return $this\n     */\n    public function __call($method, $arguments)\n    {\n        $this->queries->push([\n            'method'    => $method,\n            'arguments' => $arguments,\n        ]);\n\n        return $this;\n    }\n\n    /**\n     * @param $key\n     *\n     * @return mixed\n     */\n    public function __get($key)\n    {\n        $data = $this->buildData();\n\n        if (array_key_exists($key, $data)) {\n            return $data[$key];\n        }\n    }\n}\n"
  },
  {
    "path": "src/Grid/Row.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid;\n\nuse Closure;\nuse Illuminate\\Contracts\\Support\\Htmlable;\nuse Illuminate\\Contracts\\Support\\Jsonable;\nuse Illuminate\\Contracts\\Support\\Renderable;\nuse Illuminate\\Support\\Arr;\n\nclass Row\n{\n    /**\n     * Row number.\n     *\n     * @var\n     */\n    public $number;\n\n    /**\n     * Row data.\n     *\n     * @var\n     */\n    protected $data;\n\n    /**\n     * Attributes of row.\n     *\n     * @var array\n     */\n    protected $attributes = [];\n\n    /**\n     * @var string\n     */\n    protected $key;\n\n    /**\n     * Row constructor.\n     *\n     * @param mixed $number\n     * @param array $data\n     * @param mixed $key\n     */\n    public function __construct($number, $data, $key)\n    {\n        $this->data = $data;\n        $this->number = $number;\n        $this->key = $key;\n\n        $this->attributes = [\n            'data-key' => $key,\n        ];\n    }\n\n    /**\n     * Get the value of the model's primary key.\n     *\n     * @return mixed\n     */\n    public function getKey()\n    {\n        return $this->key;\n    }\n\n    /**\n     * Get attributes in html format.\n     *\n     * @return string\n     */\n    public function getRowAttributes()\n    {\n        return $this->formatHtmlAttribute($this->attributes);\n    }\n\n    /**\n     * Get column attributes.\n     *\n     * @param string $column\n     *\n     * @return string\n     */\n    public function getColumnAttributes($column)\n    {\n        if ($attributes = Column::getAttributes($column, $this->getKey())) {\n            return $this->formatHtmlAttribute($attributes);\n        }\n\n        return '';\n    }\n\n    /**\n     * Format attributes to html.\n     *\n     * @param array $attributes\n     *\n     * @return string\n     */\n    private function formatHtmlAttribute($attributes = [])\n    {\n        $attrArr = [];\n        foreach ($attributes as $name => $val) {\n            $attrArr[] = \"$name=\\\"$val\\\"\";\n        }\n\n        return implode(' ', $attrArr);\n    }\n\n    /**\n     * Set attributes.\n     *\n     * @param array $attributes\n     */\n    public function setAttributes(array $attributes)\n    {\n        $this->attributes = array_merge($this->attributes, $attributes);\n    }\n\n    /**\n     * Set style of the row.\n     *\n     * @param array|string $style\n     */\n    public function style($style)\n    {\n        if (is_array($style)) {\n            $style = implode(';', array_map(function ($key, $val) {\n                return \"$key:$val\";\n            }, array_keys($style), array_values($style)));\n        }\n\n        if (is_string($style)) {\n            $this->attributes['style'] = $style;\n        }\n    }\n\n    /**\n     * Get data of this row.\n     *\n     * @return mixed\n     */\n    public function model()\n    {\n        return $this->data;\n    }\n\n    /**\n     * Getter.\n     *\n     * @param mixed $attr\n     *\n     * @return mixed\n     */\n    public function __get($attr)\n    {\n        return Arr::get($this->data, $attr);\n    }\n\n    /**\n     * Get or set value of column in this row.\n     *\n     * @param string $name\n     * @param mixed  $value\n     *\n     * @return $this|mixed\n     */\n    public function column($name, $value = null)\n    {\n        if (is_null($value)) {\n            $column = Arr::get($this->data, $name);\n\n            return $this->output($column);\n        }\n\n        if ($value instanceof Closure) {\n            $value = $value->call($this, $this->column($name));\n        }\n\n        Arr::set($this->data, $name, $value);\n\n        return $this;\n    }\n\n    /**\n     * Output column value.\n     *\n     * @param mixed $value\n     *\n     * @return mixed|string\n     */\n    protected function output($value)\n    {\n        if ($value instanceof Renderable) {\n            $value = $value->render();\n        }\n\n        if ($value instanceof Htmlable) {\n            $value = $value->toHtml();\n        }\n\n        if ($value instanceof Jsonable) {\n            $value = $value->toJson();\n        }\n\n        if (!is_null($value) && !is_scalar($value)) {\n            return sprintf('<pre>%s</pre>', var_export($value, true));\n        }\n\n        return $value;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Selectable/BrowserBtn.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Selectable;\n\nuse Illuminate\\Contracts\\Support\\Renderable;\n\nclass BrowserBtn implements Renderable\n{\n    public function render()\n    {\n        $text = admin_trans('admin.choose');\n\n        $html = <<<HTML\n<a href=\"javascript:void(0)\" class=\"btn btn-primary btn-sm pull-left select-relation\">\n    <i class=\"glyphicon glyphicon-folder-open\"></i>\n    &nbsp;&nbsp;{$text}\n</a>\nHTML;\n\n        return $html;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Selectable/Checkbox.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Selectable;\n\nuse Encore\\Admin\\Grid\\Displayers\\AbstractDisplayer;\n\nclass Checkbox extends AbstractDisplayer\n{\n    public function display($key = '')\n    {\n        $value = $this->getAttribute($key);\n\n        return <<<EOT\n<input type=\"checkbox\" name=\"item\" class=\"select\" value=\"{$value}\"/>\nEOT;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Selectable/Radio.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Selectable;\n\nuse Encore\\Admin\\Grid\\Displayers\\AbstractDisplayer;\n\nclass Radio extends AbstractDisplayer\n{\n    public function display($key = '')\n    {\n        $value = $this->getAttribute($key);\n\n        return <<<EOT\n<input type=\"radio\" name=\"item\" class=\"select\" value=\"{$value}\"/>\nEOT;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Selectable.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid;\n\nuse Encore\\Admin\\Grid;\nuse Encore\\Admin\\Grid\\Selectable\\Checkbox;\nuse Encore\\Admin\\Grid\\Selectable\\Radio;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Support\\Arr;\n\n/**\n * @mixin Grid\n */\nabstract class Selectable\n{\n    /**\n     * @var string\n     */\n    public $model;\n\n    /**\n     * @var Grid\n     */\n    protected $grid;\n\n    /**\n     * @var string\n     */\n    protected $key = '';\n\n    /**\n     * @var bool\n     */\n    protected $multiple = false;\n\n    /**\n     * @var int\n     */\n    protected $perPage = 10;\n\n    /**\n     * @var bool\n     */\n    protected $imageLayout = false;\n\n    /**\n     * Selectable constructor.\n     *\n     * @param $key\n     * @param $multiple\n     */\n    public function __construct($multiple = false, $key = '')\n    {\n        $this->key = $key ?: $this->key;\n        $this->multiple = $multiple;\n\n        $this->initGrid();\n    }\n\n    /**\n     * @return void\n     */\n    abstract public function make();\n\n    protected function imageLayout()\n    {\n        $this->imageLayout = true;\n    }\n\n    /**\n     * @param bool $multiple\n     *\n     * @return string\n     */\n    public function render()\n    {\n        $this->make();\n\n        if ($this->imageLayout) {\n            $this->setView('admin::grid.image', ['key' => $this->key]);\n        } else {\n            $this->appendRemoveBtn(true);\n        }\n\n        $this->disableFeatures()->paginate($this->perPage)->expandFilter();\n\n        $displayer = $this->multiple ? Checkbox::class : Radio::class;\n\n        $this->prependColumn('__modal_selector__', ' ')->displayUsing($displayer, [$this->key]);\n\n        return $this->grid->render();\n    }\n\n    /**\n     * @return $this\n     */\n    protected function disableFeatures()\n    {\n        return $this->disableExport()\n            ->disableActions()\n            ->disableBatchActions()\n            ->disableCreateButton()\n            ->disableColumnSelector()\n            ->disablePerPageSelector();\n    }\n\n    public function renderFormGrid($values)\n    {\n        $this->make();\n\n        $this->appendRemoveBtn(false);\n\n        $this->model()->whereKey(Arr::wrap($values));\n\n        $this->disableFeatures()->disableFilter();\n\n        if (!$this->multiple) {\n            $this->disablePagination();\n        }\n\n        $this->tools(function (Tools $tools) {\n            $tools->append(new Grid\\Selectable\\BrowserBtn());\n        });\n\n        return $this->grid;\n    }\n\n    protected function appendRemoveBtn($hide = true)\n    {\n        $hide = $hide ? 'hide' : '';\n        $key = $this->key;\n\n        $this->column('__remove__', ' ')->display(function () use ($hide, $key) {\n            return <<<BTN\n<a href=\"javascript:void(0);\" class=\"grid-row-remove {$hide}\" data-key=\"{$this->getAttribute($key)}\">\n    <i class=\"fa fa-trash\"></i>\n</a>\nBTN;\n        });\n    }\n\n    protected function initGrid()\n    {\n        if (!class_exists($this->model) || !is_subclass_of($this->model, Model::class)) {\n            throw new \\InvalidArgumentException(\"Invalid model [{$this->model}]\");\n        }\n\n        /** @var Model $model */\n        $model = new $this->model();\n\n        $this->grid = new Grid(new $model());\n\n        if (!$this->key) {\n            $this->key = $model->getKeyName();\n        }\n    }\n\n    /**\n     * @param string $method\n     * @param array  $arguments\n     *\n     * @return mixed\n     */\n    public function __call(string $method, array $arguments = [])\n    {\n        return $this->grid->{$method}(...$arguments);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Simple.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid;\n\nuse Encore\\Admin\\Grid;\nuse Illuminate\\Contracts\\Support\\Renderable;\n\n/**\n * @mixin Grid\n */\nclass Simple implements Renderable\n{\n    /**\n     * @var Grid\n     */\n    protected $grid;\n\n    /**\n     * @var string\n     */\n    protected $model;\n\n    /**\n     * @param null $key\n     *\n     * @return string\n     */\n    public function render($key = null)\n    {\n        $this->grid = new Grid(new $this->model());\n\n        $this->make($key);\n\n        return $this->grid\n            ->disableActions()\n            ->disableBatchActions()\n            ->disableExport()\n            ->disableColumnSelector()\n            ->disableCreateButton()\n            ->disablePerPageSelector()\n            ->paginate(10)\n            ->expandFilter()\n            ->render();\n    }\n\n    /**\n     * @param string $name\n     * @param array  $arguments\n     *\n     * @return mixed\n     */\n    public function __call($name, $arguments)\n    {\n        return call_user_func_array([$this->grid, $name], $arguments);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Tools/AbstractTool.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Tools;\n\nuse Encore\\Admin\\Grid;\nuse Illuminate\\Contracts\\Support\\Renderable;\n\nabstract class AbstractTool implements Renderable\n{\n    /**\n     * @var Grid\n     */\n    protected $grid;\n\n    /**\n     * @var bool\n     */\n    protected $disabled = false;\n\n    /**\n     * Toggle this button.\n     *\n     * @param bool $disable\n     *\n     * @return $this\n     */\n    public function disable(bool $disable = true)\n    {\n        $this->disabled = $disable;\n\n        return $this;\n    }\n\n    /**\n     * If the tool is allowed.\n     */\n    public function allowed()\n    {\n        return !$this->disabled;\n    }\n\n    /**\n     * Set parent grid.\n     *\n     * @param Grid $grid\n     *\n     * @return $this\n     */\n    public function setGrid(Grid $grid)\n    {\n        $this->grid = $grid;\n\n        return $this;\n    }\n\n    /**\n     * @return Grid\n     */\n    public function getGrid()\n    {\n        return $this->grid;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    abstract public function render();\n\n    /**\n     * @return string\n     */\n    public function __toString()\n    {\n        return $this->render();\n    }\n}\n"
  },
  {
    "path": "src/Grid/Tools/BatchAction.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Tools;\n\nuse Encore\\Admin\\Grid;\nuse Illuminate\\Contracts\\Support\\Renderable;\n\nabstract class BatchAction implements Renderable\n{\n    /**\n     * @var int\n     */\n    protected $id;\n\n    /**\n     * @var string\n     */\n    protected $title;\n\n    /**\n     * @var string\n     */\n    protected $resource;\n\n    /**\n     * @var Grid\n     */\n    protected $grid;\n\n    /**\n     * @param $id\n     */\n    public function setId($id)\n    {\n        $this->id = $id;\n    }\n\n    /**\n     * Set title for this action.\n     *\n     * @param string $title\n     *\n     * @return $this\n     */\n    public function setTitle($title)\n    {\n        $this->title = $title;\n\n        return $this;\n    }\n\n    /**\n     * @return string\n     */\n    public function getTitle()\n    {\n        return $this->title;\n    }\n\n    /**\n     * @param Grid $grid\n     */\n    public function setGrid(Grid $grid)\n    {\n        $this->grid = $grid;\n\n        $this->resource = $grid->resource();\n    }\n\n    /**\n     * @return string\n     */\n    public function getToken()\n    {\n        return csrf_token();\n    }\n\n    /**\n     * @param bool $dotPrefix\n     *\n     * @return string\n     */\n    public function getElementClass($dotPrefix = true)\n    {\n        return sprintf(\n            '%s%s-%s',\n            $dotPrefix ? '.' : '',\n            $this->grid->getGridBatchName(),\n            $this->id\n        );\n    }\n\n    /**\n     * @return string\n     */\n    public function render()\n    {\n        return $this->title;\n    }\n\n    /**\n     * @return mixed\n     */\n    abstract public function script();\n}\n"
  },
  {
    "path": "src/Grid/Tools/BatchActions.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Tools;\n\nuse Encore\\Admin\\Admin;\nuse Illuminate\\Support\\Collection;\n\nclass BatchActions extends AbstractTool\n{\n    /**\n     * @var Collection\n     */\n    protected $actions;\n\n    /**\n     * @var bool\n     */\n    protected $enableDelete = true;\n\n    /**\n     * @var bool\n     */\n    private $holdAll = false;\n\n    /**\n     * BatchActions constructor.\n     */\n    public function __construct()\n    {\n        $this->actions = new Collection();\n\n        $this->appendDefaultAction();\n    }\n\n    /**\n     * Append default action(batch delete action).\n     *\n     * return void\n     */\n    protected function appendDefaultAction()\n    {\n        $this->add(new BatchDelete(trans('admin.batch_delete')));\n    }\n\n    /**\n     * Disable delete.\n     *\n     * @return $this\n     */\n    public function disableDelete(bool $disable = true)\n    {\n        $this->enableDelete = !$disable;\n\n        return $this;\n    }\n\n    /**\n     * Disable delete And Hode SelectAll Checkbox.\n     *\n     * @return $this\n     */\n    public function disableDeleteAndHodeSelectAll()\n    {\n        $this->enableDelete = false;\n\n        $this->holdAll = true;\n\n        return $this;\n    }\n\n    /**\n     * Add a batch action.\n     *\n     * @param $title\n     * @param BatchAction|null $action\n     *\n     * @return $this\n     */\n    public function add($title, BatchAction $action = null)\n    {\n        $id = $this->actions->count();\n\n        if (func_num_args() == 1) {\n            $action = $title;\n        } elseif (func_num_args() == 2) {\n            $action->setTitle($title);\n        }\n\n        if (method_exists($action, 'setId')) {\n            $action->setId($id);\n        }\n\n        $this->actions->push($action);\n\n        return $this;\n    }\n\n    /**\n     * Setup scripts of batch actions.\n     *\n     * @return void\n     */\n    protected function addActionScripts()\n    {\n        $this->actions->each(function ($action) {\n            $action->setGrid($this->grid);\n\n            if (method_exists($action, 'script')) {\n                Admin::script($action->script());\n            }\n        });\n    }\n\n    /**\n     * Render BatchActions button groups.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        if (!$this->enableDelete) {\n            $this->actions->shift();\n        }\n\n        $this->addActionScripts();\n\n        return Admin::component('admin::grid.batch-actions', [\n            'all'     => $this->grid->getSelectAllName(),\n            'row'     => $this->grid->getGridRowName(),\n            'actions' => $this->actions,\n            'holdAll' => $this->holdAll,\n        ]);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Tools/BatchDelete.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Tools;\n\nclass BatchDelete extends BatchAction\n{\n    public function __construct($title)\n    {\n        $this->title = $title;\n    }\n\n    /**\n     * Script of batch delete action.\n     */\n    public function script()\n    {\n        $trans = [\n            'delete_confirm' => trans('admin.delete_confirm'),\n            'confirm'        => trans('admin.confirm'),\n            'cancel'         => trans('admin.cancel'),\n        ];\n\n        return <<<EOT\n\n$('{$this->getElementClass()}').on('click', function() {\n\n    swal({\n        title: \"{$trans['delete_confirm']}\",\n        type: \"warning\",\n        showCancelButton: true,\n        confirmButtonColor: \"#DD6B55\",\n        confirmButtonText: \"{$trans['confirm']}\",\n        showLoaderOnConfirm: true,\n        cancelButtonText: \"{$trans['cancel']}\",\n        preConfirm: function() {\n            return new Promise(function(resolve) {\n                $.ajax({\n                    method: 'post',\n                    url: '{$this->resource}/' + $.admin.grid.selected().join(),\n                    data: {\n                        _method:'delete',\n                        _token:'{$this->getToken()}'\n                    },\n                    success: function (data) {\n                        $.pjax.reload('#pjax-container');\n\n                        resolve(data);\n                    }\n                });\n            });\n        }\n    }).then(function(result) {\n        var data = result.value;\n        if (typeof data === 'object') {\n            if (data.status) {\n                swal(data.message, '', 'success');\n            } else {\n                swal(data.message, '', 'error');\n            }\n        }\n    });\n});\n\nEOT;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Tools/ColumnSelector.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Tools;\n\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Grid;\nuse Illuminate\\Support\\Collection;\n\nclass ColumnSelector extends AbstractTool\n{\n    const SELECT_COLUMN_NAME = '_columns_';\n\n    /**\n     * @var array\n     */\n    protected static $ignored = [\n        Grid\\Column::SELECT_COLUMN_NAME,\n        Grid\\Column::ACTION_COLUMN_NAME,\n    ];\n\n    /**\n     * Create a new Export button instance.\n     *\n     * @param Grid $grid\n     */\n    public function __construct(Grid $grid)\n    {\n        $this->grid = $grid;\n    }\n\n    /**\n     * @return Collection\n     */\n    protected function getGridColumns()\n    {\n        return $this->grid->columns()->reject(function ($column) {\n            return in_array($column->getName(), static::$ignored);\n        })->map(function ($column) {\n            return [$column->getName() => $column->getLabel()];\n        })->collapse();\n    }\n\n    /**\n     * Ignore a column to display in column selector.\n     *\n     * @param string|array $name\n     */\n    public static function ignore($name)\n    {\n        static::$ignored = array_merge(static::$ignored, (array) $name);\n    }\n\n    /**\n     * {@inheritdoc}\n     *\n     * @return string\n     */\n    public function render()\n    {\n        if (!$this->grid->showColumnSelector()) {\n            return '';\n        }\n\n        return Admin::component('admin::components.grid-column-selector', [\n            'columns'  => $this->getGridColumns(),\n            'visible'  => $this->grid->visibleColumnNames(),\n            'defaults' => $this->grid->getDefaultVisibleColumnNames(),\n        ]);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Tools/CreateButton.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Tools;\n\nuse Encore\\Admin\\Grid;\n\nclass CreateButton extends AbstractTool\n{\n    /**\n     * @var Grid\n     */\n    protected $grid;\n\n    /**\n     * Create a new CreateButton instance.\n     *\n     * @param Grid $grid\n     */\n    public function __construct(Grid $grid)\n    {\n        $this->grid = $grid;\n    }\n\n    /**\n     * Render CreateButton.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        if (!$this->grid->showCreateBtn()) {\n            return '';\n        }\n\n        $new = trans('admin.new');\n\n        return <<<EOT\n\n<div class=\"btn-group pull-right grid-create-btn\" style=\"margin-right: 10px\">\n    <a href=\"{$this->grid->getCreateUrl()}\" class=\"btn btn-sm btn-success\" title=\"{$new}\">\n        <i class=\"fa fa-plus\"></i><span class=\"hidden-xs\">&nbsp;&nbsp;{$new}</span>\n    </a>\n</div>\n\nEOT;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Tools/ExportButton.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Tools;\n\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Grid;\n\nclass ExportButton extends AbstractTool\n{\n    /**\n     * @var Grid\n     */\n    protected $grid;\n\n    /**\n     * Create a new Export button instance.\n     *\n     * @param Grid $grid\n     */\n    public function __construct(Grid $grid)\n    {\n        $this->grid = $grid;\n    }\n\n    /**\n     * Set up script for export button.\n     */\n    protected function setUpScripts()\n    {\n        $script = <<<SCRIPT\n\n$('.{$this->grid->getExportSelectedName()}').click(function (e) {\n    e.preventDefault();\n    \n    var rows = $.admin.grid.selected().join();\n\n    if (!rows) {\n        return false;\n    }\n    \n    var href = $(this).attr('href').replace('__rows__', rows);\n    location.href = href;\n});\n\nSCRIPT;\n\n        Admin::script($script);\n    }\n\n    /**\n     * Render Export button.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        if (!$this->grid->showExportBtn()) {\n            return '';\n        }\n\n        $this->setUpScripts();\n\n        $trans = [\n            'export'        => trans('admin.export'),\n            'all'           => trans('admin.all'),\n            'current_page'  => trans('admin.current_page'),\n            'selected_rows' => trans('admin.selected_rows'),\n        ];\n\n        $page = request('page', 1);\n\n        return <<<EOT\n\n<div class=\"btn-group pull-right\" style=\"margin-right: 10px\">\n    <a href=\"{$this->grid->getExportUrl('all')}\" target=\"_blank\" class=\"btn btn-sm btn-twitter\" title=\"{$trans['export']}\"><i class=\"fa fa-download\"></i><span class=\"hidden-xs\"> {$trans['export']}</span></a>\n    <button type=\"button\" class=\"btn btn-sm btn-twitter dropdown-toggle\" data-toggle=\"dropdown\">\n        <span class=\"caret\"></span>\n        <span class=\"sr-only\">Toggle Dropdown</span>\n    </button>\n    <ul class=\"dropdown-menu\" role=\"menu\">\n        <li><a href=\"{$this->grid->getExportUrl('all')}\" target=\"_blank\">{$trans['all']}</a></li>\n        <li><a href=\"{$this->grid->getExportUrl('page', $page)}\" target=\"_blank\">{$trans['current_page']}</a></li>\n        <li><a href=\"{$this->grid->getExportUrl('selected', '__rows__')}\" target=\"_blank\" class='{$this->grid->getExportSelectedName()}'>{$trans['selected_rows']}</a></li>\n    </ul>\n</div>\nEOT;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Tools/FilterButton.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Tools;\n\nuse Encore\\Admin\\Admin;\n\nclass FilterButton extends AbstractTool\n{\n    /**\n     * {@inheritdoc}\n     */\n    public function render()\n    {\n        $label = '';\n        $filter = $this->grid->getFilter();\n\n        if ($scope = $filter->getCurrentScope()) {\n            $label = \"&nbsp;{$scope->getLabel()}&nbsp;\";\n        }\n\n        return Admin::component('admin::filter.button', [\n            'scopes'    => $filter->getScopes(),\n            'label'     => $label,\n            'cancel'    => $filter->urlWithoutScopes(),\n            'btn_class' => uniqid().'-filter-btn',\n            'expand'    => $filter->expand,\n            'filter_id' => $filter->getFilterID(),\n        ]);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Tools/FixColumns.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Tools;\n\nuse Encore\\Admin\\Grid;\nuse Illuminate\\Support\\Collection;\n\nclass FixColumns\n{\n    /**\n     * @var Grid\n     */\n    protected $grid;\n\n    /**\n     * @var int\n     */\n    protected $head;\n\n    /**\n     * @var int\n     */\n    protected $tail;\n\n    /**\n     * @var Collection\n     */\n    protected $left;\n\n    /**\n     * @var Collection\n     */\n    protected $right;\n\n    /**\n     * @var string\n     */\n    protected $view = 'admin::grid.fixed-table';\n\n    /**\n     * FixColumns constructor.\n     *\n     * @param Grid $grid\n     * @param int  $head\n     * @param int  $tail\n     */\n    public function __construct(Grid $grid, $head, $tail = -1)\n    {\n        $this->grid = $grid;\n        $this->head = $head;\n        $this->tail = $tail;\n\n        $this->left = Collection::make();\n        $this->right = Collection::make();\n    }\n\n    /**\n     * @return Collection\n     */\n    public function leftColumns()\n    {\n        return $this->left;\n    }\n\n    /**\n     * @return Collection\n     */\n    public function rightColumns()\n    {\n        return $this->right;\n    }\n\n    /**\n     * @return \\Closure\n     */\n    public function apply()\n    {\n        $this->grid->setView($this->view, [\n            'allName' => $this->grid->getSelectAllName(),\n            'rowName' => $this->grid->getGridRowName(),\n        ]);\n\n        return function (Grid $grid) {\n            if ($this->head > 0) {\n                $this->left = $grid->visibleColumns()->slice(0, $this->head);\n            }\n\n            if ($this->tail < 0) {\n                $this->right = $grid->visibleColumns()->slice($this->tail);\n            }\n        };\n    }\n}\n"
  },
  {
    "path": "src/Grid/Tools/Footer.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Tools;\n\nuse Encore\\Admin\\Grid;\nuse Illuminate\\Contracts\\Support\\Htmlable;\nuse Illuminate\\Contracts\\Support\\Renderable;\nuse Illuminate\\Database\\Query\\Builder;\n\nclass Footer extends AbstractTool\n{\n    /**\n     * @var Builder\n     */\n    protected $queryBuilder;\n\n    /**\n     * Footer constructor.\n     *\n     * @param Grid $grid\n     */\n    public function __construct(Grid $grid)\n    {\n        $this->grid = $grid;\n    }\n\n    /**\n     * Get model query builder.\n     *\n     * @return \\Illuminate\\Database\\Eloquent\\Builder\n     */\n    public function queryBuilder()\n    {\n        if (!$this->queryBuilder) {\n            $this->queryBuilder = $this->grid->model()->getQueryBuilder();\n        }\n\n        return $this->queryBuilder;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function render()\n    {\n        $content = call_user_func($this->grid->footer(), $this->queryBuilder());\n\n        if (empty($content)) {\n            return '';\n        }\n\n        if ($content instanceof Renderable) {\n            $content = $content->render();\n        }\n\n        if ($content instanceof Htmlable) {\n            $content = $content->toHtml();\n        }\n\n        return <<<HTML\n    <div class=\"box-footer clearfix\">\n        {$content}\n    </div>\nHTML;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Tools/Header.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Tools;\n\nuse Encore\\Admin\\Grid;\nuse Illuminate\\Contracts\\Support\\Htmlable;\nuse Illuminate\\Contracts\\Support\\Renderable;\nuse Illuminate\\Database\\Query\\Builder;\n\nclass Header extends AbstractTool\n{\n    /**\n     * @var Builder\n     */\n    protected $queryBuilder;\n\n    /**\n     * Header constructor.\n     *\n     * @param Grid $grid\n     */\n    public function __construct(Grid $grid)\n    {\n        $this->grid = $grid;\n    }\n\n    /**\n     * Get model query builder.\n     *\n     * @return \\Illuminate\\Database\\Eloquent\\Builder\n     */\n    public function queryBuilder()\n    {\n        if (!$this->queryBuilder) {\n            $this->queryBuilder = $this->grid->model()->getQueryBuilder();\n        }\n\n        return $this->queryBuilder;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function render()\n    {\n        $content = call_user_func($this->grid->header(), $this->queryBuilder());\n\n        if (empty($content)) {\n            return '';\n        }\n\n        if ($content instanceof Renderable) {\n            $content = $content->render();\n        }\n\n        if ($content instanceof Htmlable) {\n            $content = $content->toHtml();\n        }\n\n        return <<<HTML\n    <div class=\"box-header with-border clearfix\">\n        {$content}\n    </div>\nHTML;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Tools/Paginator.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Tools;\n\nuse Encore\\Admin\\Grid;\nuse Illuminate\\Pagination\\LengthAwarePaginator;\n\nclass Paginator extends AbstractTool\n{\n    /**\n     * @var \\Illuminate\\Pagination\\LengthAwarePaginator\n     */\n    protected $paginator = null;\n\n    /**\n     * @var bool\n     */\n    protected $perPageSelector = true;\n\n    /**\n     * Create a new Paginator instance.\n     *\n     * @param Grid $grid\n     */\n    public function __construct(Grid $grid, $perPageSelector = true)\n    {\n        $this->grid = $grid;\n        $this->perPageSelector = $perPageSelector;\n\n        $this->initPaginator();\n    }\n\n    /**\n     * Initialize work for Paginator.\n     *\n     * @return void\n     */\n    protected function initPaginator()\n    {\n        $this->paginator = $this->grid->model()->eloquent();\n\n        if ($this->paginator instanceof LengthAwarePaginator) {\n            $this->paginator->appends(request()->all());\n        }\n    }\n\n    /**\n     * Get Pagination links.\n     *\n     * @return string\n     */\n    protected function paginationLinks()\n    {\n        return $this->paginator->render('admin::pagination');\n    }\n\n    /**\n     * Get per-page selector.\n     *\n     * @return PerPageSelector\n     */\n    protected function perPageSelector()\n    {\n        if (!$this->perPageSelector) {\n            return;\n        }\n\n        return new PerPageSelector($this->grid);\n    }\n\n    /**\n     * Get range infomation of paginator.\n     *\n     * @return string|\\Symfony\\Component\\Translation\\TranslatorInterface\n     */\n    protected function paginationRanger()\n    {\n        $parameters = [\n            'first' => $this->paginator->firstItem(),\n            'last'  => $this->paginator->lastItem(),\n            'total' => $this->paginator->total(),\n        ];\n\n        $parameters = collect($parameters)->flatMap(function ($parameter, $key) {\n            return [$key => \"<b>$parameter</b>\"];\n        });\n\n        return trans('admin.pagination.range', $parameters->all());\n    }\n\n    /**\n     * Render Paginator.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        if (!$this->grid->showPagination()) {\n            return '';\n        }\n\n        return $this->paginationRanger().\n            $this->paginationLinks().\n            $this->perPageSelector();\n    }\n}\n"
  },
  {
    "path": "src/Grid/Tools/PerPageSelector.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Tools;\n\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Grid;\n\nclass PerPageSelector extends AbstractTool\n{\n    /**\n     * @var string\n     */\n    protected $perPage;\n\n    /**\n     * @var string\n     */\n    protected $perPageName = '';\n\n    /**\n     * Create a new PerPageSelector instance.\n     *\n     * @param Grid $grid\n     */\n    public function __construct(Grid $grid)\n    {\n        $this->grid = $grid;\n\n        $this->initialize();\n    }\n\n    /**\n     * Do initialize work.\n     *\n     * @return void\n     */\n    protected function initialize()\n    {\n        $this->perPageName = $this->grid->model()->getPerPageName();\n\n        $this->perPage = (int) \\request()->input(\n            $this->perPageName,\n            $this->grid->perPage\n        );\n    }\n\n    /**\n     * Get options for selector.\n     *\n     * @return static\n     */\n    public function getOptions()\n    {\n        return collect($this->grid->perPages)\n            ->push($this->grid->perPage)\n            ->push($this->perPage)\n            ->unique()\n            ->sort();\n    }\n\n    /**\n     * Render PerPageSelector。\n     *\n     * @return string\n     */\n    public function render()\n    {\n        Admin::script($this->script());\n\n        $options = $this->getOptions()->map(function ($option) {\n            $selected = ($option == $this->perPage) ? 'selected' : '';\n            $url = \\request()->fullUrlWithQuery([$this->perPageName => $option]);\n\n            return \"<option value=\\\"$url\\\" $selected>$option</option>\";\n        })->implode(\"\\r\\n\");\n\n        $trans = [\n            'show'    => trans('admin.show'),\n            'entries' => trans('admin.entries'),\n        ];\n\n        return <<<EOT\n\n<label class=\"control-label pull-right\" style=\"margin-right: 10px; font-weight: 100;\">\n\n        <small>{$trans['show']}</small>&nbsp;\n        <select class=\"input-sm {$this->grid->getPerPageName()}\" name=\"per-page\">\n            $options\n        </select>\n        &nbsp;<small>{$trans['entries']}</small>\n    </label>\n\nEOT;\n    }\n\n    /**\n     * Script of PerPageSelector.\n     *\n     * @return string\n     */\n    protected function script()\n    {\n        return <<<EOT\n\n$('.{$this->grid->getPerPageName()}').on(\"change\", function(e) {\n    $.pjax({url: this.value, container: '#pjax-container'});\n});\n\nEOT;\n    }\n}\n"
  },
  {
    "path": "src/Grid/Tools/QuickCreate.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Tools;\n\nuse Encore\\Admin\\Admin;\nuse Encore\\Admin\\Form\\Field;\nuse Encore\\Admin\\Form\\Field\\MultipleSelect;\nuse Encore\\Admin\\Form\\Field\\Select;\nuse Encore\\Admin\\Form\\Field\\Text;\nuse Encore\\Admin\\Grid;\nuse Illuminate\\Contracts\\Support\\Renderable;\nuse Illuminate\\Support\\Collection;\n\nclass QuickCreate implements Renderable\n{\n    /**\n     * @var Grid\n     */\n    protected $parent;\n\n    /**\n     * @var Collection\n     */\n    protected $fields;\n\n    /**\n     * QuickCreate constructor.\n     *\n     * @param Grid $grid\n     */\n    public function __construct(Grid $grid)\n    {\n        $this->parent = $grid;\n        $this->fields = Collection::make();\n    }\n\n    protected function formatPlaceholder($placeholder)\n    {\n        return array_filter((array) $placeholder);\n    }\n\n    /**\n     * @param string $column\n     * @param string $placeholder\n     *\n     * @return Text\n     */\n    public function text($column, $placeholder = '')\n    {\n        $field = new Text($column, $this->formatPlaceholder($placeholder));\n\n        $this->addField($field->width('200px'));\n\n        return $field;\n    }\n\n    /**\n     * @param string $column\n     * @param string $placeholder\n     *\n     * @return Text\n     */\n    public function email($column, $placeholder = '')\n    {\n        return $this->text($column, $placeholder)\n            ->inputmask(['alias' => 'email']);\n    }\n\n    /**\n     * @param string $column\n     * @param string $placeholder\n     *\n     * @return Text\n     */\n    public function ip($column, $placeholder = '')\n    {\n        return $this->text($column, $placeholder)\n            ->inputmask(['alias' => 'ip'])\n            ->width('120px');\n    }\n\n    /**\n     * @param string $column\n     * @param string $placeholder\n     *\n     * @return Text\n     */\n    public function url($column, $placeholder = '')\n    {\n        return $this->text($column, $placeholder)\n            ->inputmask(['alias' => 'url']);\n    }\n\n    /**\n     * @param string $column\n     * @param string $placeholder\n     *\n     * @return Text\n     */\n    public function password($column, $placeholder = '')\n    {\n        return $this->text($column, $placeholder)\n            ->attribute('type', 'password')\n            ->width('100px');\n    }\n\n    /**\n     * @param string $column\n     * @param string $placeholder\n     *\n     * @return Text\n     */\n    public function mobile($column, $placeholder = '')\n    {\n        return $this->text($column, $placeholder)\n            ->inputmask(['mask' => '99999999999'])\n            ->width('100px');\n    }\n\n    /**\n     * @param string $column\n     * @param string $placeholder\n     *\n     * @return Text\n     */\n    public function integer($column, $placeholder = '')\n    {\n        return $this->text($column, $placeholder)\n            ->inputmask(['alias' => 'integer'])\n            ->width('120px');\n    }\n\n    /**\n     * @param string $column\n     * @param string $placeholder\n     *\n     * @return Select\n     */\n    public function select($column, $placeholder = '')\n    {\n        $field = new Select($column, $this->formatPlaceholder($placeholder));\n\n        $this->addField($field);\n\n        return $field;\n    }\n\n    /**\n     * @param string $column\n     * @param string $placeholder\n     *\n     * @return MultipleSelect\n     */\n    public function multipleSelect($column, $placeholder = '')\n    {\n        $field = new MultipleSelect($column, $this->formatPlaceholder($placeholder));\n\n        $this->addField($field);\n\n        return $field;\n    }\n\n    /**\n     * @param string $column\n     * @param string $placeholder\n     *\n     * @return Field\\Date\n     */\n    public function datetime($column, $placeholder = '')\n    {\n        return $this->date($column, $placeholder)->format('YYYY-MM-DD HH:mm:ss');\n    }\n\n    /**\n     * @param string $column\n     * @param string $placeholder\n     *\n     * @return Field\\Date\n     */\n    public function time($column, $placeholder = '')\n    {\n        return $this->date($column, $placeholder)->format('HH:mm:ss');\n    }\n\n    /**\n     * @param string $column\n     * @param string $placeholder\n     *\n     * @return Field\\Date\n     */\n    public function date($column, $placeholder = '')\n    {\n        $field = new Field\\Date($column, $this->formatPlaceholder($placeholder));\n\n        $this->addField($field);\n\n        return $field;\n    }\n\n    /**\n     * @param Field $field\n     *\n     * @return Field\n     */\n    protected function addField(Field $field)\n    {\n        $elementClass = array_merge(['quick-create'], $field->getElementClass());\n\n        $field->addElementClass($elementClass);\n\n        $field->setView($this->resolveView(get_class($field)));\n\n        $this->fields->push($field);\n\n        return $field;\n    }\n\n    /**\n     * @param string $class\n     *\n     * @return string\n     */\n    protected function resolveView($class)\n    {\n        $path = explode('\\\\', $class);\n\n        $name = strtolower(array_pop($path));\n\n        return \"admin::grid.quick-create.{$name}\";\n    }\n\n    protected function script()\n    {\n        $url = $this->parent->resource();\n\n        $script = <<<SCRIPT\n\n;(function () {\n\n    $('.quick-create .create').click(function () {\n        $('.quick-create .create-form').show();\n        $(this).hide();\n    });\n    \n    $('.quick-create .cancel').click(function () {\n        $('.quick-create .create-form').hide();\n        $('.quick-create .create').show();\n    });\n    \n    $('.quick-create .create-form').submit(function (e) {\n        $(':submit', e.target).button('loading');\n        e.preventDefault();\n    \n        $.ajax({\n            url: '{$url}',\n            type: 'POST',\n            data: $(this).serialize(),\n            success: function(data, textStatus, jqXHR) {\n                console.info(data);\n                \n                if (data.status == true) {\n                    $.admin.toastr.success(data.message, '', {positionClass:\"toast-top-center\"});\n                    $.admin.reload();\n                    return;\n                }\n                \n                if (typeof data.validation !== 'undefined') {\n                    $.admin.toastr.warning(data.message, '', {positionClass:\"toast-top-center\"})\n                }\n            },\n            error: function(XMLHttpRequest, textStatus){\n                $(':submit', e.target).button('reset');\n\n                if (typeof XMLHttpRequest.responseJSON === 'object') {\n                    $.admin.toastr.error(XMLHttpRequest.responseJSON.message, '', {positionClass:\"toast-top-center\", timeOut: 10000});\n                }\n            }\n        });\n        \n        return false;\n    });\n\n})();\n\nSCRIPT;\n\n        Admin::script($script);\n    }\n\n    /**\n     * @param int $columnCount\n     *\n     * @return array|string\n     */\n    public function render($columnCount = 0)\n    {\n        if ($this->fields->isEmpty()) {\n            return '';\n        }\n\n        $this->script();\n\n        $vars = [\n            'columnCount' => $columnCount,\n            'fields'      => $this->fields,\n        ];\n\n        return view('admin::grid.quick-create.form', $vars)->render();\n    }\n}\n"
  },
  {
    "path": "src/Grid/Tools/QuickSearch.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Tools;\n\nuse Encore\\Admin\\Grid\\Concerns\\HasQuickSearch;\nuse Illuminate\\Support\\Arr;\n\nclass QuickSearch extends AbstractTool\n{\n    /**\n     * @var string\n     */\n    protected $view = 'admin::grid.quick-search';\n\n    /**\n     * @var string\n     */\n    protected $placeholder;\n\n    /**\n     * Set placeholder.\n     *\n     * @param string $text\n     *\n     * @return $this\n     */\n    public function placeholder($text = '')\n    {\n        $this->placeholder = $text;\n\n        return $this;\n    }\n\n    /**\n     * @return \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View\n     */\n    public function render()\n    {\n        $query = request()->query();\n\n        Arr::forget($query, HasQuickSearch::$searchKey);\n\n        $vars = [\n            'action'      => request()->url().'?'.http_build_query($query),\n            'key'         => HasQuickSearch::$searchKey,\n            'value'       => request(HasQuickSearch::$searchKey),\n            'placeholder' => $this->placeholder,\n        ];\n\n        return view($this->view, $vars);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Tools/Selector.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Tools;\n\nuse Illuminate\\Contracts\\Support\\Renderable;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Support\\Str;\n\nclass Selector implements Renderable\n{\n    /**\n     * @var array|Collection\n     */\n    protected $selectors = [];\n\n    /**\n     * @var array\n     */\n    protected static $selected;\n\n    /**\n     * Selector constructor.\n     */\n    public function __construct()\n    {\n        $this->selectors = new Collection();\n    }\n\n    /**\n     * @param string         $column\n     * @param string|array   $label\n     * @param array|\\Closure $options\n     * @param null|\\Closure  $query\n     *\n     * @return $this\n     */\n    public function select($column, $label, $options = [], $query = null)\n    {\n        return $this->addSelector($column, $label, $options, $query);\n    }\n\n    /**\n     * @param string        $column\n     * @param string        $label\n     * @param array         $options\n     * @param null|\\Closure $query\n     *\n     * @return $this\n     */\n    public function selectOne($column, $label, $options = [], $query = null)\n    {\n        return $this->addSelector($column, $label, $options, $query, 'one');\n    }\n\n    /**\n     * @param string $column\n     * @param string $label\n     * @param array  $options\n     * @param null   $query\n     * @param string $type\n     *\n     * @return $this\n     */\n    protected function addSelector($column, $label, $options = [], $query = null, $type = 'many')\n    {\n        if (is_array($label)) {\n            if ($options instanceof \\Closure) {\n                $query = $options;\n            }\n\n            $options = $label;\n            $label = __(Str::title($column));\n        }\n\n        $this->selectors[$column] = compact('label', 'options', 'type', 'query');\n\n        return $this;\n    }\n\n    /**\n     * Get all selectors.\n     *\n     * @return array|Collection\n     */\n    public function getSelectors()\n    {\n        return $this->selectors;\n    }\n\n    /**\n     * @return array\n     */\n    public static function parseSelected()\n    {\n        if (!is_null(static::$selected)) {\n            return static::$selected;\n        }\n\n        $selected = request('_selector', []);\n\n        if (!is_array($selected)) {\n            return [];\n        }\n\n        $selected = array_filter($selected, function ($value) {\n            return !is_null($value);\n        });\n\n        foreach ($selected as &$value) {\n            $value = explode(',', $value);\n        }\n\n        return static::$selected = $selected;\n    }\n\n    /**\n     * @param string $column\n     * @param mixed  $value\n     * @param bool   $add\n     *\n     * @return string\n     */\n    public static function url($column, $value = null, $add = false)\n    {\n        $query = request()->query();\n        $selected = static::parseSelected();\n\n        $options = Arr::get($selected, $column, []);\n\n        if (is_null($value)) {\n            Arr::forget($query, \"_selector.{$column}\");\n\n            return request()->fullUrlWithQuery($query);\n        }\n\n        if (in_array($value, $options)) {\n            array_delete($options, $value);\n        } else {\n            if ($add) {\n                $options = [];\n            }\n\n            array_push($options, $value);\n        }\n\n        if (!empty($options)) {\n            Arr::set($query, \"_selector.{$column}\", implode(',', $options));\n        } else {\n            Arr::forget($query, \"_selector.{$column}\");\n        }\n\n        return request()->fullUrlWithQuery($query);\n    }\n\n    /**\n     * @return \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View\n     */\n    public function render()\n    {\n        return view('admin::grid.selector', [\n            'selectors' => $this->selectors,\n            'selected'  => static::parseSelected(),\n        ]);\n    }\n}\n"
  },
  {
    "path": "src/Grid/Tools/TotalRow.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid\\Tools;\n\nuse Encore\\Admin\\Grid\\Column;\nuse Illuminate\\Database\\Query\\Builder;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Collection;\n\nclass TotalRow extends AbstractTool\n{\n    /**\n     * @var Builder\n     */\n    protected $query;\n\n    /**\n     * @var array\n     */\n    protected $columns;\n\n    /**\n     * @var Collection\n     */\n    protected $visibleColumns;\n\n    /**\n     * TotalRow constructor.\n     *\n     * @param Builder $query\n     * @param array   $columns\n     */\n    public function __construct($query, array $columns)\n    {\n        $this->query = $query;\n\n        $this->columns = $columns;\n    }\n\n    /**\n     * Get total value of current column.\n     *\n     * @param string $column\n     * @param mixed  $display\n     *\n     * @return mixed\n     */\n    protected function total($column, $display = null)\n    {\n        if (!is_callable($display) && !is_null($display)) {\n            return $display;\n        }\n\n        $sum = $this->query->sum($column);\n\n        if (is_callable($display)) {\n            return call_user_func($display, $sum);\n        }\n\n        return $sum;\n    }\n\n    /**\n     * @param Collection $columns\n     */\n    public function setVisibleColumns($columns)\n    {\n        $this->visibleColumns = $columns;\n    }\n\n    /**\n     * @return Collection|static\n     */\n    public function getVisibleColumns()\n    {\n        if ($this->visibleColumns) {\n            return $this->visibleColumns;\n        }\n\n        return $this->getGrid()->visibleColumns();\n    }\n\n    /**\n     * Render total-row.\n     *\n     * @return \\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View\n     */\n    public function render()\n    {\n        $columns = $this->getVisibleColumns()->map(function (Column $column) {\n            $name = $column->getName();\n\n            $total = '';\n\n            if (Arr::has($this->columns, $name)) {\n                $total = $this->total($name, Arr::get($this->columns, $name));\n            }\n\n            return [\n                'class' => $column->getClassName(),\n                'value' => $total,\n            ];\n        });\n\n        return view('admin::grid.total-row', compact('columns'));\n    }\n}\n"
  },
  {
    "path": "src/Grid/Tools.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Grid;\n\nuse Encore\\Admin\\Actions\\GridAction;\nuse Encore\\Admin\\Grid;\nuse Encore\\Admin\\Grid\\Tools\\AbstractTool;\nuse Encore\\Admin\\Grid\\Tools\\BatchActions;\nuse Encore\\Admin\\Grid\\Tools\\FilterButton;\nuse Illuminate\\Contracts\\Support\\Htmlable;\nuse Illuminate\\Contracts\\Support\\Renderable;\nuse Illuminate\\Support\\Collection;\n\nclass Tools implements Renderable\n{\n    /**\n     * Parent grid.\n     *\n     * @var Grid\n     */\n    protected $grid;\n\n    /**\n     * Collection of tools.\n     *\n     * @var Collection\n     */\n    protected $tools;\n\n    /**\n     * Create a new Tools instance.\n     *\n     * @param Grid $grid\n     */\n    public function __construct(Grid $grid)\n    {\n        $this->grid = $grid;\n\n        $this->tools = new Collection();\n\n        $this->appendDefaultTools();\n    }\n\n    /**\n     * Append default tools.\n     */\n    protected function appendDefaultTools()\n    {\n        $this->append(new BatchActions())\n            ->append(new FilterButton());\n    }\n\n    /**\n     * Append tools.\n     *\n     * @param AbstractTool|string $tool\n     *\n     * @return $this\n     */\n    public function append($tool)\n    {\n        if ($tool instanceof GridAction) {\n            $tool->setGrid($this->grid);\n        }\n\n        $this->tools->push($tool);\n\n        return $this;\n    }\n\n    /**\n     * Prepend a tool.\n     *\n     * @param AbstractTool|string $tool\n     *\n     * @return $this\n     */\n    public function prepend($tool)\n    {\n        $this->tools->prepend($tool);\n\n        return $this;\n    }\n\n    /**\n     * Disable filter button.\n     *\n     * @return void\n     */\n    public function disableFilterButton(bool $disable = true)\n    {\n        $this->tools = $this->tools->map(function ($tool) use ($disable) {\n            if ($tool instanceof FilterButton) {\n                return $tool->disable($disable);\n            }\n\n            return $tool;\n        });\n    }\n\n    /**\n     * Disable refresh button.\n     *\n     * @return void\n     *\n     * @deprecated\n     */\n    public function disableRefreshButton(bool $disable = true)\n    {\n        //\n    }\n\n    /**\n     * Disable batch actions.\n     *\n     * @return void\n     */\n    public function disableBatchActions(bool $disable = true)\n    {\n        $this->tools = $this->tools->map(function ($tool) use ($disable) {\n            if ($tool instanceof BatchActions) {\n                return $tool->disable($disable);\n            }\n\n            return $tool;\n        });\n    }\n\n    /**\n     * @param \\Closure $closure\n     */\n    public function batch(\\Closure $closure)\n    {\n        call_user_func($closure, $this->tools->first(function ($tool) {\n            return $tool instanceof BatchActions;\n        }));\n    }\n\n    /**\n     * Render header tools bar.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        return $this->tools->map(function ($tool) {\n            if ($tool instanceof AbstractTool) {\n                if (!$tool->allowed()) {\n                    return '';\n                }\n\n                return $tool->setGrid($this->grid)->render();\n            }\n\n            if ($tool instanceof Renderable) {\n                return $tool->render();\n            }\n\n            if ($tool instanceof Htmlable) {\n                return $tool->toHtml();\n            }\n\n            return (string) $tool;\n        })->implode(' ');\n    }\n}\n"
  },
  {
    "path": "src/Grid.php",
    "content": "<?php\n\nnamespace Encore\\Admin;\n\nuse Closure;\nuse Encore\\Admin\\Exception\\Handler;\nuse Encore\\Admin\\Grid\\Column;\nuse Encore\\Admin\\Grid\\Concerns;\nuse Encore\\Admin\\Grid\\Displayers;\nuse Encore\\Admin\\Grid\\Model;\nuse Encore\\Admin\\Grid\\Row;\nuse Encore\\Admin\\Grid\\Tools;\nuse Encore\\Admin\\Traits\\ShouldSnakeAttributes;\nuse Illuminate\\Database\\Eloquent\\Model as Eloquent;\nuse Illuminate\\Database\\Eloquent\\Relations;\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Support\\Str;\nuse Illuminate\\Support\\Traits\\Macroable;\nuse Jenssegers\\Mongodb\\Eloquent\\Model as MongodbModel;\n\nclass Grid\n{\n    use Concerns\\HasElementNames,\n        Concerns\\HasHeader,\n        Concerns\\HasFooter,\n        Concerns\\HasFilter,\n        Concerns\\HasTools,\n        Concerns\\HasTotalRow,\n        Concerns\\HasHotKeys,\n        Concerns\\HasQuickCreate,\n        Concerns\\HasActions,\n        Concerns\\HasSelector,\n        Concerns\\CanHidesColumns,\n        Concerns\\CanFixHeader,\n        Concerns\\CanFixColumns,\n        Concerns\\CanExportGrid,\n        Concerns\\CanDoubleClick,\n        ShouldSnakeAttributes,\n        Macroable {\n            __call as macroCall;\n        }\n\n    /**\n     * The grid data model instance.\n     *\n     * @var \\Encore\\Admin\\Grid\\Model|\\Illuminate\\Database\\Eloquent\\Builder\n     */\n    protected $model;\n\n    /**\n     * Collection of all grid columns.\n     *\n     * @var \\Illuminate\\Support\\Collection\n     */\n    protected $columns;\n\n    /**\n     * Collection of all data rows.\n     *\n     * @var \\Illuminate\\Support\\Collection\n     */\n    protected $rows;\n\n    /**\n     * Rows callable fucntion.\n     *\n     * @var \\Closure\n     */\n    protected $rowsCallback;\n\n    /**\n     * All column names of the grid.\n     *\n     * @var array\n     */\n    public $columnNames = [];\n\n    /**\n     * Grid builder.\n     *\n     * @var \\Closure\n     */\n    protected $builder;\n\n    /**\n     * Mark if the grid is builded.\n     *\n     * @var bool\n     */\n    protected $builded = false;\n\n    /**\n     * All variables in grid view.\n     *\n     * @var array\n     */\n    protected $variables = [];\n\n    /**\n     * Resource path of the grid.\n     *\n     * @var\n     */\n    protected $resourcePath;\n\n    /**\n     * Default primary key name.\n     *\n     * @var string\n     */\n    protected $keyName = 'id';\n\n    /**\n     * View for grid to render.\n     *\n     * @var string\n     */\n    protected $view = 'admin::grid.table';\n\n    /**\n     * Per-page options.\n     *\n     * @var array\n     */\n    public $perPages = [10, 20, 30, 50, 100];\n\n    /**\n     * Default items count per-page.\n     *\n     * @var int\n     */\n    public $perPage = 20;\n\n    /**\n     * @var []callable\n     */\n    protected $renderingCallbacks = [];\n\n    /**\n     * Options for grid.\n     *\n     * @var array\n     */\n    protected $options = [\n        'show_pagination'        => true,\n        'show_tools'             => true,\n        'show_filter'            => true,\n        'show_exporter'          => true,\n        'show_actions'           => true,\n        'show_row_selector'      => true,\n        'show_create_btn'        => true,\n        'show_column_selector'   => true,\n        'show_define_empty_page' => true,\n        'show_perpage_selector'  => true,\n    ];\n\n    /**\n     * @var string\n     */\n    public $tableID;\n\n    /**\n     * Initialization closure array.\n     *\n     * @var []Closure\n     */\n    protected static $initCallbacks = [];\n\n    /**\n     * Create a new grid instance.\n     *\n     * @param Eloquent $model\n     * @param Closure  $builder\n     */\n    public function __construct(Eloquent $model, Closure $builder = null)\n    {\n        $this->model = new Model($model, $this);\n        $this->keyName = $model->getKeyName();\n        $this->builder = $builder;\n\n        $this->initialize();\n\n        $this->callInitCallbacks();\n    }\n\n    /**\n     * Initialize.\n     */\n    protected function initialize()\n    {\n        $this->tableID = uniqid('grid-table');\n\n        $this->columns = Collection::make();\n        $this->rows = Collection::make();\n\n        $this->initTools()\n            ->initFilter();\n    }\n\n    /**\n     * Initialize with user pre-defined default disables and exporter, etc.\n     *\n     * @param Closure $callback\n     */\n    public static function init(Closure $callback = null)\n    {\n        static::$initCallbacks[] = $callback;\n    }\n\n    /**\n     * Call the initialization closure array in sequence.\n     */\n    protected function callInitCallbacks()\n    {\n        if (empty(static::$initCallbacks)) {\n            return;\n        }\n\n        foreach (static::$initCallbacks as $callback) {\n            call_user_func($callback, $this);\n        }\n    }\n\n    /**\n     * Get or set option for grid.\n     *\n     * @param string $key\n     * @param mixed  $value\n     *\n     * @return $this|mixed\n     */\n    public function option($key, $value = null)\n    {\n        if (is_null($value)) {\n            return $this->options[$key];\n        }\n\n        $this->options[$key] = $value;\n\n        return $this;\n    }\n\n    /**\n     * Get primary key name of model.\n     *\n     * @return string\n     */\n    public function getKeyName()\n    {\n        return $this->keyName ?: 'id';\n    }\n\n    /**\n     * Add a column to Grid.\n     *\n     * @param string $name\n     * @param string $label\n     *\n     * @return Column\n     */\n    public function column($name, $label = '')\n    {\n        if (Str::contains($name, '.')) {\n            return $this->addRelationColumn($name, $label);\n        }\n\n        if (Str::contains($name, '->')) {\n            return $this->addJsonColumn($name, $label);\n        }\n\n        return $this->__call($name, array_filter([$label]));\n    }\n\n    /**\n     * Batch add column to grid.\n     *\n     * @example\n     * 1.$grid->columns(['name' => 'Name', 'email' => 'Email' ...]);\n     * 2.$grid->columns('name', 'email' ...)\n     *\n     * @param array $columns\n     *\n     * @return Collection|null\n     */\n    public function columns($columns = [])\n    {\n        if (func_num_args() == 0) {\n            return $this->columns;\n        }\n\n        if (func_num_args() == 1 && is_array($columns)) {\n            foreach ($columns as $column => $label) {\n                $this->column($column, $label);\n            }\n\n            return;\n        }\n\n        foreach (func_get_args() as $column) {\n            $this->column($column);\n        }\n    }\n\n    /**\n     * Add column to grid.\n     *\n     * @param string $column\n     * @param string $label\n     *\n     * @return Column\n     */\n    protected function addColumn($column = '', $label = '')\n    {\n        $column = new Column($column, $label);\n        $column->setGrid($this);\n\n        return tap($column, function ($value) {\n            $this->columns->push($value);\n        });\n    }\n\n    /**\n     * Get all columns object.\n     *\n     * @return Collection\n     */\n    public function getColumns()\n    {\n        return $this->columns;\n    }\n\n    /**\n     * Add a relation column to grid.\n     *\n     * @param string $name\n     * @param string $label\n     *\n     * @return $this|bool|Column\n     */\n    protected function addRelationColumn($name, $label = '')\n    {\n        list($relation, $column) = explode('.', $name);\n\n        $model = $this->model()->eloquent();\n\n        if (!method_exists($model, $relation) || !$model->{$relation}() instanceof Relations\\Relation) {\n            $class = get_class($model);\n\n            admin_error(\"Call to undefined relationship [{$relation}] on model [{$class}].\");\n\n            return $this;\n        }\n\n        $name = ($this->shouldSnakeAttributes() ? Str::snake($relation) : $relation).'.'.$column;\n\n        $this->model()->with($relation);\n\n        return $this->addColumn($name, $label)->setRelation($relation, $column);\n    }\n\n    /**\n     * Add a json type column to grid.\n     *\n     * @param string $name\n     * @param string $label\n     *\n     * @return Column\n     */\n    protected function addJsonColumn($name, $label = '')\n    {\n        $column = substr($name, strrpos($name, '->') + 2);\n\n        $name = str_replace('->', '.', $name);\n\n        return $this->addColumn($name, $label ?: ucfirst($column));\n    }\n\n    /**\n     * Prepend column to grid.\n     *\n     * @param string $column\n     * @param string $label\n     *\n     * @return Column\n     */\n    public function prependColumn($column = '', $label = '')\n    {\n        $column = new Column($column, $label);\n        $column->setGrid($this);\n\n        return tap($column, function ($value) {\n            $this->columns->prepend($value);\n        });\n    }\n\n    /**\n     * Get Grid model.\n     *\n     * @return Model|\\Illuminate\\Database\\Eloquent\\Builder\n     */\n    public function model()\n    {\n        return $this->model;\n    }\n\n    /**\n     * Paginate the grid.\n     *\n     * @param int $perPage\n     *\n     * @return $this\n     */\n    public function paginate($perPage = 20)\n    {\n        $this->perPage = $perPage;\n\n        $this->model()->setPerPage($perPage);\n\n        return $this;\n    }\n\n    /**\n     * Get the grid paginator.\n     *\n     * @return mixed\n     */\n    public function paginator()\n    {\n        return new Tools\\Paginator($this, $this->options['show_perpage_selector']);\n    }\n\n    /**\n     * Disable grid pagination.\n     *\n     * @return $this\n     */\n    public function disablePagination(bool $disable = true)\n    {\n        $this->model->usePaginate(!$disable);\n\n        return $this->option('show_pagination', !$disable);\n    }\n\n    /**\n     * If this grid use pagination.\n     *\n     * @return bool\n     */\n    public function showPagination()\n    {\n        return $this->option('show_pagination');\n    }\n\n    /**\n     * Set per-page options.\n     *\n     * @param array $perPages\n     */\n    public function perPages(array $perPages)\n    {\n        $this->perPages = $perPages;\n    }\n\n    /**\n     * @param bool $disable\n     *\n     * @return $this\n     */\n    public function disablePerPageSelector(bool $disable = true)\n    {\n        return $this->option('show_perpage_selector', !$disable);\n    }\n\n    /**\n     * Disable row selector.\n     *\n     * @return Grid|mixed\n     */\n    public function disableRowSelector(bool $disable = true)\n    {\n        return $this->disableBatchActions($disable);\n    }\n\n    /**\n     * Prepend checkbox column for grid.\n     *\n     * @return void\n     */\n    protected function prependRowSelectorColumn()\n    {\n        if (!$this->option('show_row_selector')) {\n            return;\n        }\n\n        $checkAllBox = \"<input type=\\\"checkbox\\\" class=\\\"{$this->getSelectAllName()}\\\" />&nbsp;\";\n\n        $this->prependColumn(Column::SELECT_COLUMN_NAME, ' ')\n            ->displayUsing(Displayers\\RowSelector::class)\n            ->addHeader($checkAllBox);\n    }\n\n    /**\n     * Apply column filter to grid query.\n     *\n     * @return void\n     */\n    protected function applyColumnFilter()\n    {\n        $this->columns->each->bindFilterQuery($this->model());\n    }\n\n    /**\n     * Apply column search to grid query.\n     *\n     * @return void\n     */\n    protected function applyColumnSearch()\n    {\n        $this->columns->each->bindSearchQuery($this->model());\n    }\n\n    /**\n     * @return array|Collection|mixed\n     */\n    public function applyQuery()\n    {\n        $this->applyQuickSearch();\n\n        $this->applyColumnFilter();\n\n        $this->applyColumnSearch();\n\n        $this->applySelectorQuery();\n    }\n\n    /**\n     * Add row selector columns and action columns before and after the grid.\n     *\n     * @return void\n     */\n    protected function addDefaultColumns()\n    {\n        $this->prependRowSelectorColumn();\n\n        $this->appendActionsColumn();\n    }\n\n    /**\n     * Build the grid.\n     *\n     * @return void\n     */\n    public function build()\n    {\n        if ($this->builded) {\n            return;\n        }\n\n        $this->applyQuery();\n\n        $collection = $this->applyFilter(false);\n\n        $this->addDefaultColumns();\n\n        Column::setOriginalGridModels($collection);\n\n        $data = $collection->toArray();\n\n        $this->columns->map(function (Column $column) use (&$data) {\n            $data = $column->fill($data);\n\n            $this->columnNames[] = $column->getName();\n        });\n\n        $this->buildRows($data, $collection);\n\n        $this->builded = true;\n    }\n\n    /**\n     * Build the grid rows.\n     *\n     * @param array      $data\n     * @param Collection $collection\n     *\n     * @return void\n     */\n    protected function buildRows(array $data, Collection $collection)\n    {\n        $this->rows = collect($data)->map(function ($model, $number) use ($collection) {\n            return new Row($number, $model, $collection->get($number)->getKey());\n        });\n\n        if ($this->rowsCallback) {\n            $this->rows->map($this->rowsCallback);\n        }\n    }\n\n    /**\n     * Set grid row callback function.\n     *\n     * @param Closure $callable\n     *\n     * @return Collection|null\n     */\n    public function rows(Closure $callable = null)\n    {\n        if (is_null($callable)) {\n            return $this->rows;\n        }\n\n        $this->rowsCallback = $callable;\n    }\n\n    /**\n     * Get create url.\n     *\n     * @return string\n     */\n    public function getCreateUrl()\n    {\n        $queryString = '';\n\n        if ($constraints = $this->model()->getConstraints()) {\n            $queryString = http_build_query($constraints);\n        }\n\n        return sprintf(\n            '%s/create%s',\n            $this->resource(),\n            $queryString ? ('?'.$queryString) : ''\n        );\n    }\n\n    /**\n     * Alias for method `disableCreateButton`.\n     *\n     * @return $this\n     *\n     * @deprecated\n     */\n    public function disableCreation()\n    {\n        return $this->disableCreateButton();\n    }\n\n    /**\n     * Remove create button on grid.\n     *\n     * @return $this\n     */\n    public function disableCreateButton(bool $disable = true)\n    {\n        return $this->option('show_create_btn', !$disable);\n    }\n\n    /**\n     * Remove define empty page on grid.\n     *\n     * @return $this\n     */\n    public function disableDefineEmptyPage(bool $disable = true)\n    {\n        return $this->option('show_define_empty_page', !$disable);\n    }\n\n    /**\n     * If grid show define empty page on grid.\n     *\n     * @return bool\n     */\n    public function showDefineEmptyPage()\n    {\n        return $this->option('show_define_empty_page');\n    }\n\n    /**\n     * If allow creation.\n     *\n     * @return bool\n     */\n    public function showCreateBtn()\n    {\n        return $this->option('show_create_btn');\n    }\n\n    /**\n     * Render create button for grid.\n     *\n     * @return string\n     */\n    public function renderCreateButton()\n    {\n        return (new Tools\\CreateButton($this))->render();\n    }\n\n    /**\n     * Get current resource url.\n     *\n     * @param string $path\n     *\n     * @return string\n     */\n    public function resource($path = null)\n    {\n        if (!empty($path)) {\n            $this->resourcePath = $path;\n\n            return $this;\n        }\n\n        if (!empty($this->resourcePath)) {\n            return $this->resourcePath;\n        }\n\n        return url(app('request')->getPathInfo());\n    }\n\n    /**\n     * Handle get mutator column for grid.\n     *\n     * @param string $method\n     * @param string $label\n     *\n     * @return bool|Column\n     */\n    protected function handleGetMutatorColumn($method, $label)\n    {\n        if ($this->model()->eloquent()->hasGetMutator($method)) {\n            return $this->addColumn($method, $label);\n        }\n\n        return false;\n    }\n\n    /**\n     * Handle relation column for grid.\n     *\n     * @param string $method\n     * @param string $label\n     *\n     * @return bool|Column\n     */\n    protected function handleRelationColumn($method, $label)\n    {\n        $model = $this->model()->eloquent();\n\n        if (!method_exists($model, $method)) {\n            return false;\n        }\n\n        if (!($relation = $model->$method()) instanceof Relations\\Relation) {\n            return false;\n        }\n\n        if ($relation instanceof Relations\\HasOne ||\n            $relation instanceof Relations\\BelongsTo ||\n            $relation instanceof Relations\\MorphOne\n        ) {\n            $this->model()->with($method);\n\n            return $this->addColumn($method, $label)->setRelation(\n                $this->shouldSnakeAttributes() ? Str::snake($method) : $method\n            );\n        }\n\n        if ($relation instanceof Relations\\HasMany\n            || $relation instanceof Relations\\BelongsToMany\n            || $relation instanceof Relations\\MorphToMany\n            || $relation instanceof Relations\\HasManyThrough\n        ) {\n            $this->model()->with($method);\n\n            return $this->addColumn($this->shouldSnakeAttributes() ? Str::snake($method) : $method, $label);\n        }\n\n        return false;\n    }\n\n    /**\n     * Dynamically add columns to the grid view.\n     *\n     * @param $method\n     * @param $arguments\n     *\n     * @return Column\n     */\n    public function __call($method, $arguments)\n    {\n        if (static::hasMacro($method)) {\n            return $this->macroCall($method, $arguments);\n        }\n\n        $label = $arguments[0] ?? null;\n\n        if ($this->model()->eloquent() instanceof MongodbModel) {\n            return $this->addColumn($method, $label);\n        }\n\n        if ($column = $this->handleGetMutatorColumn($method, $label)) {\n            return $column;\n        }\n\n        if ($column = $this->handleRelationColumn($method, $label)) {\n            return $column;\n        }\n\n        return $this->addColumn($method, $label);\n    }\n\n    /**\n     * Add variables to grid view.\n     *\n     * @param array $variables\n     *\n     * @return $this\n     */\n    public function with($variables = [])\n    {\n        $this->variables = $variables;\n\n        return $this;\n    }\n\n    /**\n     * Get all variables will used in grid view.\n     *\n     * @return array\n     */\n    protected function variables()\n    {\n        $this->variables['grid'] = $this;\n\n        return $this->variables;\n    }\n\n    /**\n     * Set a view to render.\n     *\n     * @param string $view\n     * @param array  $variables\n     */\n    public function setView($view, $variables = [])\n    {\n        if (!empty($variables)) {\n            $this->with($variables);\n        }\n\n        $this->view = $view;\n    }\n\n    /**\n     * Set grid title.\n     *\n     * @param string $title\n     *\n     * @return $this\n     */\n    public function setTitle($title)\n    {\n        $this->variables['title'] = $title;\n\n        return $this;\n    }\n\n    /**\n     * Set relation for grid.\n     *\n     * @param Relations\\Relation $relation\n     *\n     * @return $this\n     */\n    public function setRelation(Relations\\Relation $relation)\n    {\n        $this->model()->setRelation($relation);\n\n        return $this;\n    }\n\n    /**\n     * Set resource path for grid.\n     *\n     * @param string $path\n     *\n     * @return $this\n     */\n    public function setResource($path)\n    {\n        $this->resourcePath = $path;\n\n        return $this;\n    }\n\n    /**\n     * Set rendering callback.\n     *\n     * @param callable $callback\n     *\n     * @return $this\n     */\n    public function rendering(callable $callback)\n    {\n        $this->renderingCallbacks[] = $callback;\n\n        return $this;\n    }\n\n    /**\n     * Call callbacks before render.\n     *\n     * @return void\n     */\n    protected function callRenderingCallback()\n    {\n        foreach ($this->renderingCallbacks as $callback) {\n            call_user_func($callback, $this);\n        }\n    }\n\n    /**\n     * Get the string contents of the grid view.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        $this->handleExportRequest(true);\n\n        try {\n            $this->build();\n        } catch (\\Exception $e) {\n            return Handler::renderException($e);\n        }\n\n        $this->callRenderingCallback();\n\n        return Admin::component($this->view, $this->variables());\n    }\n}\n"
  },
  {
    "path": "src/Layout/Buildable.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Layout;\n\ninterface Buildable\n{\n    public function build();\n}\n"
  },
  {
    "path": "src/Layout/Column.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Layout;\n\nuse Encore\\Admin\\Grid;\nuse Illuminate\\Contracts\\Support\\Renderable;\n\nclass Column implements Buildable\n{\n    /**\n     * grid system prefix width.\n     *\n     * @var array\n     */\n    protected $width = [];\n\n    /**\n     * @var array\n     */\n    protected $contents = [];\n\n    /**\n     * Column constructor.\n     *\n     * @param $content\n     * @param int $width\n     */\n    public function __construct($content, $width = 12)\n    {\n        if ($content instanceof \\Closure) {\n            call_user_func($content, $this);\n        } else {\n            $this->append($content);\n        }\n\n        ///// set width.\n        // if null, or $this->width is empty array, set as \"md\" => \"12\"\n        if (is_null($width) || (is_array($width) && count($width) === 0)) {\n            $this->width['md'] = 12;\n        }\n        // $this->width is number(old version), set as \"md\" => $width\n        elseif (is_numeric($width)) {\n            $this->width['md'] = $width;\n        } else {\n            $this->width = $width;\n        }\n    }\n\n    /**\n     * Append content to column.\n     *\n     * @param $content\n     *\n     * @return $this\n     */\n    public function append($content)\n    {\n        $this->contents[] = $content;\n\n        return $this;\n    }\n\n    /**\n     * Add a row for column.\n     *\n     * @param $content\n     *\n     * @return Column\n     */\n    public function row($content)\n    {\n        if (!$content instanceof \\Closure) {\n            $row = new Row($content);\n        } else {\n            $row = new Row();\n\n            call_user_func($content, $row);\n        }\n\n        ob_start();\n\n        $row->build();\n\n        $contents = ob_get_contents();\n\n        ob_end_clean();\n\n        return $this->append($contents);\n    }\n\n    /**\n     * Build column html.\n     */\n    public function build()\n    {\n        $this->startColumn();\n\n        foreach ($this->contents as $content) {\n            if ($content instanceof Renderable || $content instanceof Grid) {\n                echo $content->render();\n            } else {\n                echo (string) $content;\n            }\n        }\n\n        $this->endColumn();\n    }\n\n    /**\n     * Start column.\n     */\n    protected function startColumn()\n    {\n        // get class name using width array\n        $classnName = collect($this->width)->map(function ($value, $key) {\n            return \"col-$key-$value\";\n        })->implode(' ');\n\n        echo \"<div class=\\\"{$classnName}\\\">\";\n    }\n\n    /**\n     * End column.\n     */\n    protected function endColumn()\n    {\n        echo '</div>';\n    }\n}\n"
  },
  {
    "path": "src/Layout/Content.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Layout;\n\nuse Closure;\nuse Encore\\Admin\\Facades\\Admin;\nuse Illuminate\\Contracts\\Support\\Renderable;\nuse Illuminate\\Support\\Arr;\n\nclass Content implements Renderable\n{\n    /**\n     * Content title.\n     *\n     * @var string\n     */\n    protected $title = ' ';\n\n    /**\n     * Content description.\n     *\n     * @var string\n     */\n    protected $description = ' ';\n\n    /**\n     * Page breadcrumb.\n     *\n     * @var array\n     */\n    protected $breadcrumb = [];\n\n    /**\n     * @var Row[]\n     */\n    protected $rows = [];\n\n    /**\n     * @var array\n     */\n    protected $view;\n\n    /**\n     * Content constructor.\n     *\n     * @param Closure|null $callback\n     */\n    public function __construct(\\Closure $callback = null)\n    {\n        if ($callback instanceof Closure) {\n            $callback($this);\n        }\n    }\n\n    /**\n     * Alias of method `title`.\n     *\n     * @param string $header\n     *\n     * @return $this\n     */\n    public function header($header = '')\n    {\n        return $this->title($header);\n    }\n\n    /**\n     * @param string $title\n     *\n     * @return $this\n     */\n    public function title($title)\n    {\n        $this->title = $title;\n\n        return $this;\n    }\n\n    /**\n     * Set description of content.\n     *\n     * @param string $description\n     *\n     * @return $this\n     */\n    public function description($description = '')\n    {\n        $this->description = $description;\n\n        return $this;\n    }\n\n    /**\n     * Set breadcrumb of content.\n     *\n     * @param array ...$breadcrumb\n     *\n     * @return $this\n     */\n    public function breadcrumb(...$breadcrumb)\n    {\n        $this->validateBreadcrumb($breadcrumb);\n\n        $this->breadcrumb = (array) $breadcrumb;\n\n        return $this;\n    }\n\n    /**\n     * Validate content breadcrumb.\n     *\n     * @param array $breadcrumb\n     *\n     * @throws \\Exception\n     *\n     * @return bool\n     */\n    protected function validateBreadcrumb(array $breadcrumb)\n    {\n        foreach ($breadcrumb as $item) {\n            if (!is_array($item) || !Arr::has($item, 'text')) {\n                throw new  \\Exception('Breadcrumb format error!');\n            }\n        }\n\n        return true;\n    }\n\n    /**\n     * Alias of method row.\n     *\n     * @param mixed $content\n     *\n     * @return $this\n     */\n    public function body($content)\n    {\n        return $this->row($content);\n    }\n\n    /**\n     * Add one row for content body.\n     *\n     * @param $content\n     *\n     * @return $this\n     */\n    public function row($content)\n    {\n        if ($content instanceof Closure) {\n            $row = new Row();\n            call_user_func($content, $row);\n            $this->addRow($row);\n        } else {\n            $this->addRow(new Row($content));\n        }\n\n        return $this;\n    }\n\n    /**\n     * Render giving view as content body.\n     *\n     * @param string $view\n     * @param array  $data\n     *\n     * @return $this\n     */\n    public function view($view, $data = [])\n    {\n        $this->view = compact('view', 'data');\n\n        return $this;\n    }\n\n    /**\n     * @param string $view\n     * @param array  $data\n     */\n    public function component($view, $data = [])\n    {\n        return $this->body(Admin::component($view, $data));\n    }\n\n    /**\n     * @param $var\n     *\n     * @return $this\n     */\n    public function dump($var)\n    {\n        return $this->row(admin_dump(...func_get_args()));\n    }\n\n    /**\n     * Add Row.\n     *\n     * @param Row $row\n     */\n    protected function addRow(Row $row)\n    {\n        $this->rows[] = $row;\n    }\n\n    /**\n     * Build html of content.\n     *\n     * @return string\n     */\n    public function build()\n    {\n        ob_start();\n\n        foreach ($this->rows as $row) {\n            $row->build();\n        }\n\n        $contents = ob_get_contents();\n\n        ob_end_clean();\n\n        return $contents;\n    }\n\n    /**\n     * Set success message for content.\n     *\n     * @param string $title\n     * @param string $message\n     *\n     * @return $this\n     */\n    public function withSuccess($title = '', $message = '')\n    {\n        admin_success($title, $message);\n\n        return $this;\n    }\n\n    /**\n     * Set error message for content.\n     *\n     * @param string $title\n     * @param string $message\n     *\n     * @return $this\n     */\n    public function withError($title = '', $message = '')\n    {\n        admin_error($title, $message);\n\n        return $this;\n    }\n\n    /**\n     * Set warning message for content.\n     *\n     * @param string $title\n     * @param string $message\n     *\n     * @return $this\n     */\n    public function withWarning($title = '', $message = '')\n    {\n        admin_warning($title, $message);\n\n        return $this;\n    }\n\n    /**\n     * Set info message for content.\n     *\n     * @param string $title\n     * @param string $message\n     *\n     * @return $this\n     */\n    public function withInfo($title = '', $message = '')\n    {\n        admin_info($title, $message);\n\n        return $this;\n    }\n\n    /**\n     * @return array\n     */\n    protected function getUserData()\n    {\n        if (!$user = Admin::user()) {\n            return [];\n        }\n\n        return Arr::only($user->toArray(), ['id', 'username', 'email', 'name', 'avatar']);\n    }\n\n    /**\n     * Render this content.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        $items = [\n            'header'      => $this->title,\n            'description' => $this->description,\n            'breadcrumb'  => $this->breadcrumb,\n            '_content_'   => $this->build(),\n            '_view_'      => $this->view,\n            '_user_'      => $this->getUserData(),\n        ];\n\n        return view('admin::content', $items)->render();\n    }\n}\n"
  },
  {
    "path": "src/Layout/Row.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Layout;\n\nuse Illuminate\\Contracts\\Support\\Renderable;\n\nclass Row implements Buildable, Renderable\n{\n    /**\n     * @var Column[]\n     */\n    protected $columns = [];\n\n    /**\n     * row classes.\n     *\n     * @var array\n     */\n    protected $class = [];\n\n    /**\n     * Row constructor.\n     *\n     * @param string $content\n     */\n    public function __construct($content = '')\n    {\n        if (!empty($content)) {\n            $this->column(12, $content);\n        }\n    }\n\n    /**\n     * Add a column.\n     *\n     * @param int $width\n     * @param $content\n     */\n    public function column($width, $content)\n    {\n        $width = $width < 1 ? round(12 * $width) : $width;\n\n        $column = new Column($content, $width);\n\n        $this->addColumn($column);\n    }\n\n    /**\n     * Add class in row.\n     *\n     * @param array|string $class\n     */\n    public function class($class)\n    {\n        if (is_string($class)) {\n            $class = [$class];\n        }\n\n        $this->class = $class;\n\n        return $this;\n    }\n\n    /**\n     * @param Column $column\n     */\n    protected function addColumn(Column $column)\n    {\n        $this->columns[] = $column;\n    }\n\n    /**\n     * Build row column.\n     */\n    public function build()\n    {\n        $this->startRow();\n\n        foreach ($this->columns as $column) {\n            $column->build();\n        }\n\n        $this->endRow();\n    }\n\n    /**\n     * Start row.\n     */\n    protected function startRow()\n    {\n        $class = $this->class;\n        $class[] = 'row';\n        echo '<div class=\"'.implode(' ', $class).'\">';\n    }\n\n    /**\n     * End column.\n     */\n    protected function endRow()\n    {\n        echo '</div>';\n    }\n\n    /**\n     * Render row.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        ob_start();\n\n        $this->build();\n\n        $contents = ob_get_contents();\n\n        ob_end_clean();\n\n        return $contents;\n    }\n}\n"
  },
  {
    "path": "src/Middleware/Authenticate.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Middleware;\n\nuse Closure;\nuse Encore\\Admin\\Facades\\Admin;\n\nclass Authenticate\n{\n    /**\n     * Handle an incoming request.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     * @param \\Closure                 $next\n     *\n     * @return mixed\n     */\n    public function handle($request, Closure $next)\n    {\n        \\config(['auth.defaults.guard' => 'admin']);\n\n        $redirectTo = admin_base_path(config('admin.auth.redirect_to', 'auth/login'));\n\n        if (Admin::guard()->guest() && !$this->shouldPassThrough($request)) {\n            return redirect()->to($redirectTo);\n        }\n\n        return $next($request);\n    }\n\n    /**\n     * Determine if the request has a URI that should pass through verification.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     *\n     * @return bool\n     */\n    protected function shouldPassThrough($request)\n    {\n        // 下面的路由不验证登陆\n        $excepts = config('admin.auth.excepts', []);\n\n        array_delete($excepts, [\n            '_handle_action_',\n            '_handle_form_',\n            '_handle_selectable_',\n            '_handle_renderable_',\n        ]);\n\n        return collect($excepts)\n            ->map('admin_base_path')\n            ->contains(function ($except) use ($request) {\n                if ($except !== '/') {\n                    $except = trim($except, '/');\n                }\n\n                return $request->is($except);\n            });\n    }\n}\n"
  },
  {
    "path": "src/Middleware/Bootstrap.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Middleware;\n\nuse Closure;\nuse Encore\\Admin\\Facades\\Admin;\nuse Illuminate\\Http\\Request;\n\nclass Bootstrap\n{\n    public function handle(Request $request, Closure $next)\n    {\n        Admin::bootstrap();\n\n        return $next($request);\n    }\n}\n"
  },
  {
    "path": "src/Middleware/LogOperation.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Middleware;\n\nuse Encore\\Admin\\Auth\\Database\\OperationLog as OperationLogModel;\nuse Encore\\Admin\\Facades\\Admin;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Str;\n\nclass LogOperation\n{\n    /**\n     * Handle an incoming request.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     * @param \\Closure                 $next\n     *\n     * @return mixed\n     */\n    public function handle(Request $request, \\Closure $next)\n    {\n        if ($this->shouldLogOperation($request)) {\n            $log = [\n                'user_id' => Admin::user()->id,\n                'path'    => substr($request->path(), 0, 255),\n                'method'  => $request->method(),\n                'ip'      => $request->getClientIp(),\n                'input'   => json_encode($request->input()),\n            ];\n\n            try {\n                OperationLogModel::create($log);\n            } catch (\\Exception $exception) {\n                // pass\n            }\n        }\n\n        return $next($request);\n    }\n\n    /**\n     * @param Request $request\n     *\n     * @return bool\n     */\n    protected function shouldLogOperation(Request $request)\n    {\n        return config('admin.operation_log.enable')\n            && !$this->inExceptArray($request)\n            && $this->inAllowedMethods($request->method())\n            && Admin::user();\n    }\n\n    /**\n     * Whether requests using this method are allowed to be logged.\n     *\n     * @param string $method\n     *\n     * @return bool\n     */\n    protected function inAllowedMethods($method)\n    {\n        $allowedMethods = collect(config('admin.operation_log.allowed_methods'))->filter();\n\n        if ($allowedMethods->isEmpty()) {\n            return true;\n        }\n\n        return $allowedMethods->map(function ($method) {\n            return strtoupper($method);\n        })->contains($method);\n    }\n\n    /**\n     * Determine if the request has a URI that should pass through CSRF verification.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     *\n     * @return bool\n     */\n    protected function inExceptArray($request)\n    {\n        foreach (config('admin.operation_log.except') as $except) {\n            if ($except !== '/') {\n                $except = trim($except, '/');\n            }\n\n            $methods = [];\n\n            if (Str::contains($except, ':')) {\n                list($methods, $except) = explode(':', $except);\n                $methods = explode(',', $methods);\n            }\n\n            $methods = array_map('strtoupper', $methods);\n\n            if ($request->is($except) &&\n                (empty($methods) || in_array($request->method(), $methods))) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n}\n"
  },
  {
    "path": "src/Middleware/Permission.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Middleware;\n\nuse Encore\\Admin\\Auth\\Permission as Checker;\nuse Encore\\Admin\\Facades\\Admin;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Str;\n\nclass Permission\n{\n    /**\n     * @var string\n     */\n    protected $middlewarePrefix = 'admin.permission:';\n\n    /**\n     * Handle an incoming request.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     * @param \\Closure                 $next\n     * @param array                    $args\n     *\n     * @return mixed\n     */\n    public function handle(Request $request, \\Closure $next, ...$args)\n    {\n        if (config('admin.check_route_permission') === false) {\n            return $next($request);\n        }\n\n        if (!Admin::user() || !empty($args) || $this->shouldPassThrough($request)) {\n            return $next($request);\n        }\n\n        if ($this->checkRoutePermission($request)) {\n            return $next($request);\n        }\n\n        if (!Admin::user()->allPermissions()->first(function ($permission) use ($request) {\n            return $permission->shouldPassThrough($request);\n        })) {\n            Checker::error();\n        }\n\n        return $next($request);\n    }\n\n    /**\n     * If the route of current request contains a middleware prefixed with 'admin.permission:',\n     * then it has a manually set permission middleware, we need to handle it first.\n     *\n     * @param Request $request\n     *\n     * @return bool\n     */\n    public function checkRoutePermission(Request $request)\n    {\n        if (!$middleware = collect($request->route()->middleware())->first(function ($middleware) {\n            return Str::startsWith($middleware, $this->middlewarePrefix);\n        })) {\n            return false;\n        }\n\n        $args = explode(',', str_replace($this->middlewarePrefix, '', $middleware));\n\n        $method = array_shift($args);\n\n        if (!method_exists(Checker::class, $method)) {\n            throw new \\InvalidArgumentException(\"Invalid permission method [$method].\");\n        }\n\n        call_user_func_array([Checker::class, $method], [$args]);\n\n        return true;\n    }\n\n    /**\n     * Determine if the request has a URI that should pass through verification.\n     *\n     * @param \\Illuminate\\Http\\Request $request\n     *\n     * @return bool\n     */\n    protected function shouldPassThrough($request)\n    {\n        // 下面这些路由不验证权限\n        $excepts = array_merge(config('admin.auth.excepts', []), [\n            'auth/login',\n            'auth/logout',\n            '_handle_action_',\n            '_handle_form_',\n            '_handle_selectable_',\n            '_handle_renderable_',\n        ]);\n\n        return collect($excepts)\n            ->map('admin_base_path')\n            ->contains(function ($except) use ($request) {\n                if ($except !== '/') {\n                    $except = trim($except, '/');\n                }\n\n                return $request->is($except);\n            });\n    }\n}\n"
  },
  {
    "path": "src/Middleware/Pjax.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Middleware;\n\nuse Closure;\nuse Encore\\Admin\\Facades\\Admin;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\MessageBag;\nuse Symfony\\Component\\DomCrawler\\Crawler;\nuse Symfony\\Component\\HttpFoundation\\Response;\n\nclass Pjax\n{\n    /**\n     * Handle an incoming request.\n     *\n     * @param Request $request\n     * @param Closure $next\n     *\n     * @return Response\n     */\n    public function handle($request, Closure $next)\n    {\n        $response = $next($request);\n\n        if (!$request->pjax() || $response->isRedirection() || Admin::guard()->guest()) {\n            return $response;\n        }\n\n        if (!$response->isSuccessful()) {\n            return $this->handleErrorResponse($response);\n        }\n\n        try {\n            $this->filterResponse($response, $request->header('X-PJAX-CONTAINER'))\n                ->setUriHeader($response, $request);\n        } catch (\\Exception $exception) {\n        }\n\n        return $response;\n    }\n\n    /**\n     * Send a response through this middleware.\n     *\n     * @param Response $response\n     */\n    public static function respond(Response $response)\n    {\n        $next = function () use ($response) {\n            return $response;\n        };\n\n        (new static())->handle(Request::capture(), $next)->send();\n\n        exit;\n    }\n\n    /**\n     * Handle Response with exceptions.\n     *\n     * @param Response $response\n     *\n     * @return \\Illuminate\\Http\\RedirectResponse\n     */\n    protected function handleErrorResponse(Response $response)\n    {\n        $exception = $response->exception;\n\n        $error = new MessageBag([\n            'type'    => get_class($exception),\n            'message' => $exception->getMessage(),\n            'file'    => $exception->getFile(),\n            'line'    => $exception->getLine(),\n        ]);\n\n        return back()->withInput()->withErrors($error, 'exception');\n    }\n\n    /**\n     * Prepare the PJAX-specific response content.\n     *\n     * @param Response $response\n     * @param string   $container\n     *\n     * @return $this\n     */\n    protected function filterResponse(Response $response, $container)\n    {\n        $crawler = new Crawler($response->getContent());\n\n        $response->setContent(\n            $this->makeTitle($crawler).\n            $this->fetchContents($crawler, $container)\n        );\n\n        return $this;\n    }\n\n    /**\n     * Prepare an HTML title tag.\n     *\n     * @param Crawler $crawler\n     *\n     * @return string\n     */\n    protected function makeTitle($crawler)\n    {\n        $pageTitle = $crawler->filter('head > title')->html();\n\n        return \"<title>{$pageTitle}</title>\";\n    }\n\n    /**\n     * Fetch the PJAX-specific HTML from the response.\n     *\n     * @param Crawler $crawler\n     * @param string  $container\n     *\n     * @return string\n     */\n    protected function fetchContents($crawler, $container)\n    {\n        $content = $crawler->filter($container);\n\n        if (!$content->count()) {\n            abort(422);\n        }\n\n        return $this->decodeUtf8HtmlEntities($content->html());\n    }\n\n    /**\n     * Decode utf-8 characters to html entities.\n     *\n     * @param string $html\n     *\n     * @return string\n     */\n    protected function decodeUtf8HtmlEntities($html)\n    {\n        return preg_replace_callback('/(&#[0-9]+;)/', function ($html) {\n            return mb_convert_encoding($html[1], 'UTF-8', 'HTML-ENTITIES');\n        }, $html);\n    }\n\n    /**\n     * Set the PJAX-URL header to the current uri.\n     *\n     * @param Response $response\n     * @param Request  $request\n     */\n    protected function setUriHeader(Response $response, Request $request)\n    {\n        $response->header(\n            'X-PJAX-URL',\n            $request->getRequestUri()\n        );\n    }\n}\n"
  },
  {
    "path": "src/Middleware/Session.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Middleware;\n\nuse Illuminate\\Http\\Request;\n\nclass Session\n{\n    public function handle(Request $request, \\Closure $next)\n    {\n        $path = '/'.trim(config('admin.route.prefix'), '/');\n\n        config(['session.path' => $path]);\n\n        if ($domain = config('admin.route.domain')) {\n            config(['session.domain' => $domain]);\n        }\n\n        return $next($request);\n    }\n}\n"
  },
  {
    "path": "src/Show/AbstractField.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Show;\n\nuse Illuminate\\Contracts\\Support\\Renderable;\nuse Illuminate\\Database\\Eloquent\\Model;\n\nabstract class AbstractField implements Renderable\n{\n    /**\n     * Field value.\n     *\n     * @var mixed\n     */\n    protected $value;\n\n    /**\n     * Current field model.\n     *\n     * @var Model\n     */\n    protected $model;\n\n    /**\n     * If this field show with a border.\n     *\n     * @var bool\n     */\n    public $border = true;\n\n    /**\n     * If this field show escaped contents.\n     *\n     * @var bool\n     */\n    public $escape = true;\n\n    /**\n     * @param mixed $value\n     *\n     * @return AbstractField $this\n     */\n    public function setValue($value)\n    {\n        $this->value = $value;\n\n        return $this;\n    }\n\n    /**\n     * @param Model $model\n     *\n     * @return AbstractField $this\n     */\n    public function setModel($model)\n    {\n        $this->model = $model;\n\n        return $this;\n    }\n\n    /**\n     * @return mixed\n     */\n    abstract public function render();\n}\n"
  },
  {
    "path": "src/Show/Divider.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Show;\n\nclass Divider extends Field\n{\n    public function render()\n    {\n        return '<hr>';\n    }\n}\n"
  },
  {
    "path": "src/Show/Field.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Show;\n\nuse Encore\\Admin\\Show;\nuse Encore\\Admin\\Widgets\\Carousel;\nuse Illuminate\\Contracts\\Support\\Arrayable;\nuse Illuminate\\Contracts\\Support\\Renderable;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Support\\Facades\\File;\nuse Illuminate\\Support\\Facades\\Storage;\nuse Illuminate\\Support\\Str;\nuse Illuminate\\Support\\Traits\\Macroable;\n\nclass Field implements Renderable\n{\n    use Macroable {\n        __call as macroCall;\n    }\n\n    /**\n     * @var string\n     */\n    protected $view = 'admin::show.field';\n\n    /**\n     * Name of column.\n     *\n     * @var string\n     */\n    protected $name;\n\n    /**\n     * Label of column.\n     *\n     * @var string\n     */\n    protected $label;\n\n    /**\n     * Width for label and field.\n     *\n     * @var array\n     */\n    protected $width = [\n        'label' => 2,\n        'field' => 8,\n    ];\n\n    /**\n     * Escape field value or not.\n     *\n     * @var bool\n     */\n    protected $escape = true;\n\n    /**\n     * Field value.\n     *\n     * @var mixed\n     */\n    protected $value;\n\n    /**\n     * @var Collection\n     */\n    protected $showAs = [];\n\n    /**\n     * Parent show instance.\n     *\n     * @var Show\n     */\n    protected $parent;\n\n    /**\n     * Relation name.\n     *\n     * @var string\n     */\n    protected $relation;\n\n    /**\n     * If show contents in box.\n     *\n     * @var bool\n     */\n    public $border = true;\n\n    /**\n     * @var array\n     */\n    protected $fileTypes = [\n        'image'      => 'png|jpg|jpeg|tmp|gif',\n        'word'       => 'doc|docx',\n        'excel'      => 'xls|xlsx|csv',\n        'powerpoint' => 'ppt|pptx',\n        'pdf'        => 'pdf',\n        'code'       => 'php|js|java|python|ruby|go|c|cpp|sql|m|h|json|html|aspx',\n        'archive'    => 'zip|tar\\.gz|rar|rpm',\n        'txt'        => 'txt|pac|log|md',\n        'audio'      => 'mp3|wav|flac|3pg|aa|aac|ape|au|m4a|mpc|ogg',\n        'video'      => 'mkv|rmvb|flv|mp4|avi|wmv|rm|asf|mpeg',\n    ];\n\n    /**\n     * Field constructor.\n     *\n     * @param string $name\n     * @param string $label\n     */\n    public function __construct($name = '', $label = '')\n    {\n        $this->name = $name;\n\n        $this->label = $this->formatLabel($label);\n\n        $this->showAs = new Collection();\n    }\n\n    /**\n     * Set parent show instance.\n     *\n     * @param Show $show\n     *\n     * @return $this\n     */\n    public function setParent(Show $show)\n    {\n        $this->parent = $show;\n\n        return $this;\n    }\n\n    /**\n     * Get name of this column.\n     *\n     * @return mixed\n     */\n    public function getName()\n    {\n        return $this->name;\n    }\n\n    /**\n     * Format label.\n     *\n     * @param $label\n     *\n     * @return mixed\n     */\n    protected function formatLabel($label)\n    {\n        $label = $label ?: ucfirst($this->name);\n\n        return str_replace(['.', '_'], ' ', $label);\n    }\n\n    /**\n     * Get label of the column.\n     *\n     * @return mixed\n     */\n    public function getLabel()\n    {\n        return $this->label;\n    }\n\n    /**\n     * Field display callback.\n     *\n     * @param callable $callable\n     *\n     * @return $this\n     */\n    public function as(callable $callable)\n    {\n        $this->showAs->push($callable);\n\n        return $this;\n    }\n\n    /**\n     * Display field using array value map.\n     *\n     * @param array $values\n     * @param null  $default\n     *\n     * @return $this\n     */\n    public function using(array $values, $default = null)\n    {\n        return $this->as(function ($value) use ($values, $default) {\n            if (is_null($value)) {\n                return $default;\n            }\n\n            return Arr::get($values, $value, $default);\n        });\n    }\n\n    /**\n     * Show field as a image.\n     *\n     * @param string $server\n     * @param int    $width\n     * @param int    $height\n     *\n     * @return $this\n     */\n    public function image($server = '', $width = 200, $height = 200)\n    {\n        return $this->unescape()->as(function ($images) use ($server, $width, $height) {\n            return collect($images)->map(function ($path) use ($server, $width, $height) {\n                if (empty($path)) {\n                    return '';\n                }\n\n                if (url()->isValidUrl($path)) {\n                    $src = $path;\n                } elseif ($server) {\n                    $src = $server.$path;\n                } else {\n                    $disk = config('admin.upload.disk');\n\n                    if (config(\"filesystems.disks.{$disk}\")) {\n                        $src = Storage::disk($disk)->url($path);\n                    } else {\n                        return '';\n                    }\n                }\n\n                return \"<img src='$src' style='max-width:{$width}px;max-height:{$height}px' class='img' />\";\n            })->implode('&nbsp;');\n        });\n    }\n\n    /**\n     * Show field as a carousel.\n     *\n     * @param int    $width\n     * @param int    $height\n     * @param string $server\n     *\n     * @return Field\n     */\n    public function carousel($width = 300, $height = 200, $server = '')\n    {\n        return $this->unescape()->as(function ($images) use ($server, $width, $height) {\n            $items = collect($images)->map(function ($path) use ($server, $width, $height) {\n                if (empty($path)) {\n                    return '';\n                }\n\n                if (url()->isValidUrl($path)) {\n                    $image = $path;\n                } elseif ($server) {\n                    $image = $server.$path;\n                } else {\n                    $disk = config('admin.upload.disk');\n\n                    if (config(\"filesystems.disks.{$disk}\")) {\n                        $image = Storage::disk($disk)->url($path);\n                    } else {\n                        $image = '';\n                    }\n                }\n\n                $caption = '';\n\n                return compact('image', 'caption');\n            });\n\n            return (new Carousel($items))->width($width)->height($height);\n        });\n    }\n\n    /**\n     * Show field as a file.\n     *\n     * @param string $server\n     * @param bool   $download\n     *\n     * @return Field\n     */\n    public function file($server = '', $download = true)\n    {\n        $field = $this;\n\n        return $this->unescape()->as(function ($path) use ($server, $download, $field) {\n            $name = basename($path);\n\n            $field->border = false;\n\n            $size = $url = '';\n\n            if (url()->isValidUrl($path)) {\n                $url = $path;\n            } elseif ($server) {\n                $url = $server.$path;\n            } else {\n                $storage = Storage::disk(config('admin.upload.disk'));\n                if ($storage->exists($path)) {\n                    $url = $storage->url($path);\n                    $size = ($storage->size($path) / 1000).'KB';\n                }\n            }\n\n            if (!$url) {\n                return '';\n            }\n\n            $download = $download ? \"download='$name'\" : '';\n\n            return <<<HTML\n<ul class=\"mailbox-attachments clearfix\">\n    <li style=\"margin-bottom: 0;\">\n      <span class=\"mailbox-attachment-icon\"><i class=\"fa {$field->getFileIcon($name)}\"></i></span>\n      <div class=\"mailbox-attachment-info\">\n        <div class=\"mailbox-attachment-name\">\n            <i class=\"fa fa-paperclip\"></i> {$name}\n            </div>\n            <span class=\"mailbox-attachment-size\">\n              {$size}&nbsp;\n              <a href=\"{$url}\" class=\"btn btn-default btn-xs pull-right\" target=\"_blank\" $download><i class=\"fa fa-cloud-download\"></i></a>\n            </span>\n      </div>\n    </li>\n  </ul>\nHTML;\n        });\n    }\n\n    /**\n     * Show field as a link.\n     *\n     * @param string $href\n     * @param string $target\n     *\n     * @return Field\n     */\n    public function link($href = '', $target = '_blank')\n    {\n        return $this->unescape()->as(function ($link) use ($href, $target) {\n            $href = $href ?: $link;\n\n            return \"<a href='$href' target='{$target}'>{$link}</a>\";\n        });\n    }\n\n    /**\n     * Show field as labels.\n     *\n     * @param string $style\n     *\n     * @return Field\n     */\n    public function label($style = 'success')\n    {\n        return $this->unescape()->as(function ($value) use ($style) {\n            if ($value instanceof Arrayable) {\n                $value = $value->toArray();\n            }\n\n            return collect((array) $value)->map(function ($name) use ($style) {\n                return \"<span class='label label-{$style}'>$name</span>\";\n            })->implode('&nbsp;');\n        });\n    }\n\n    /**\n     * Show field as badges.\n     *\n     * @param string $style\n     *\n     * @return Field\n     */\n    public function badge($style = 'blue')\n    {\n        return $this->unescape()->as(function ($value) use ($style) {\n            if ($value instanceof Arrayable) {\n                $value = $value->toArray();\n            }\n\n            return collect((array) $value)->map(function ($name) use ($style) {\n                return \"<span class='badge bg-{$style}'>$name</span>\";\n            })->implode('&nbsp;');\n        });\n    }\n\n    /**\n     * Show field as number.\n     *\n     * @param int    $decimals\n     * @param string $decimal_seperator\n     * @param string $thousands_seperator\n     *\n     * @return Field\n     */\n    public function number($decimals = 0, $decimal_seperator = '.', $thousands_seperator = ',')\n    {\n        return $this->unescape()->as(function ($value) use ($decimals, $decimal_seperator, $thousands_seperator) {\n            return number_format($value, $decimals, $decimal_seperator, $thousands_seperator);\n        });\n    }\n\n    /**\n     * Show field as json code.\n     *\n     * @return Field\n     */\n    public function json()\n    {\n        $field = $this;\n\n        return $this->unescape()->as(function ($value) use ($field) {\n            if (is_string($value)) {\n                $content = json_decode($value, true);\n            } else {\n                $content = $value;\n            }\n\n            if (json_last_error() == 0) {\n                $field->border = false;\n\n                return '<pre><code>'.json_encode($content, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE).'</code></pre>';\n            }\n\n            return $value;\n        });\n    }\n\n    /**\n     * Show readable filesize for giving integer size.\n     *\n     * @return Field\n     */\n    public function filesize()\n    {\n        return $this->as(function ($value) {\n            return file_size($value);\n        });\n    }\n\n    /**\n     * Get file icon.\n     *\n     * @param string $file\n     *\n     * @return string\n     */\n    public function getFileIcon($file = '')\n    {\n        $extension = File::extension($file);\n\n        foreach ($this->fileTypes as $type => $regex) {\n            if (preg_match(\"/^($regex)$/i\", $extension) !== 0) {\n                return \"fa-file-{$type}-o\";\n            }\n        }\n\n        return 'fa-file-o';\n    }\n\n    /**\n     * Set escape or not for this field.\n     *\n     * @param bool $escape\n     *\n     * @return $this\n     */\n    public function setEscape($escape = true)\n    {\n        $this->escape = $escape;\n\n        return $this;\n    }\n\n    /**\n     * Unescape for this field.\n     *\n     * @return Field\n     */\n    public function unescape()\n    {\n        return $this->setEscape(false);\n    }\n\n    /**\n     * Set value for this field.\n     *\n     * @param Model $model\n     *\n     * @return $this\n     */\n    public function setValue(Model $model)\n    {\n        if ($this->relation) {\n            if (!$relationValue = $model->{$this->relation}) {\n                return $this;\n            }\n\n            $this->value = $relationValue;\n        } else {\n            if (Str::contains($this->name, '.')) {\n                $this->value = $this->getRelationValue($model, $this->name);\n            } else {\n                $this->value = $model->getAttribute($this->name);\n            }\n        }\n\n        return $this;\n    }\n\n    /**\n     * Set relation name for this field.\n     *\n     * @param string $relation\n     *\n     * @return $this\n     */\n    public function setRelation($relation)\n    {\n        $this->relation = $relation;\n\n        return $this;\n    }\n\n    /**\n     * @param Model  $model\n     * @param string $name\n     *\n     * @return mixed\n     */\n    protected function getRelationValue($model, $name)\n    {\n        list($relation, $key) = explode('.', $name);\n\n        if ($related = $model->getRelationValue($relation)) {\n            return $related->getAttribute($key);\n        }\n    }\n\n    /**\n     * Set width for field and label.\n     *\n     * @param int $field\n     * @param int $label\n     *\n     * @return $this\n     */\n    public function setWidth($field = 8, $label = 2)\n    {\n        $this->width = [\n            'label' => $label,\n            'field' => $field,\n        ];\n\n        return $this;\n    }\n\n    /**\n     * Call extended field.\n     *\n     * @param string|AbstractField|\\Closure $abstract\n     * @param array                         $arguments\n     *\n     * @return Field\n     */\n    protected function callExtendedField($abstract, $arguments = [])\n    {\n        if ($abstract instanceof \\Closure) {\n            return $this->as($abstract);\n        }\n\n        if (is_string($abstract) && class_exists($abstract)) {\n            /** @var AbstractField $extend */\n            $extend = new $abstract();\n        }\n\n        if ($abstract instanceof AbstractField) {\n            /** @var AbstractField $extend */\n            $extend = $abstract;\n        }\n\n        if (!isset($extend)) {\n            admin_warning(\"[$abstract] is not a valid Show field.\");\n\n            return $this;\n        }\n\n        if (!$extend->escape) {\n            $this->unescape();\n        }\n\n        $field = $this;\n\n        return $this->as(function ($value) use ($extend, $field, $arguments) {\n            if (!$extend->border) {\n                $field->border = false;\n            }\n\n            $extend->setValue($value)->setModel($this);\n\n            return $extend->render(...$arguments);\n        });\n    }\n\n    /**\n     * @param string $method\n     * @param array  $arguments\n     *\n     * @return $this\n     */\n    public function __call($method, $arguments = [])\n    {\n        if ($class = Arr::get(Show::$extendedFields, $method)) {\n            return $this->callExtendedField($class, $arguments);\n        }\n\n        if (static::hasMacro($method)) {\n            return $this->macroCall($method, $arguments);\n        }\n\n        if ($this->relation) {\n            $this->name = $method;\n            $this->label = $this->formatLabel(Arr::get($arguments, 0));\n        }\n\n        return $this;\n    }\n\n    /**\n     * Get all variables passed to field view.\n     *\n     * @return array\n     */\n    protected function variables()\n    {\n        return [\n            'content'   => $this->value,\n            'escape'    => $this->escape,\n            'label'     => $this->getLabel(),\n            'wrapped'   => $this->border,\n            'width'     => $this->width,\n        ];\n    }\n\n    /**\n     * Render this field.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        if ($this->showAs->isNotEmpty()) {\n            $this->showAs->each(function ($callable) {\n                $this->value = $callable->call(\n                    $this->parent->getModel(),\n                    $this->value\n                );\n            });\n        }\n\n        return view($this->view, $this->variables());\n    }\n}\n"
  },
  {
    "path": "src/Show/Panel.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Show;\n\nuse Encore\\Admin\\Show;\nuse Illuminate\\Contracts\\Support\\Renderable;\nuse Illuminate\\Support\\Collection;\n\nclass Panel implements Renderable\n{\n    /**\n     * The view to be rendered.\n     *\n     * @var string\n     */\n    protected $view = 'admin::show.panel';\n\n    /**\n     * The fields that this panel holds.\n     *\n     * @var Collection\n     */\n    protected $fields;\n\n    /**\n     * Variables in the view.\n     *\n     * @var array\n     */\n    protected $data;\n\n    /**\n     * Parent show instance.\n     *\n     * @var Show\n     */\n    protected $parent;\n\n    /**\n     * Panel constructor.\n     */\n    public function __construct(Show $show)\n    {\n        $this->parent = $show;\n\n        $this->initData();\n    }\n\n    /**\n     * Initialize view data.\n     */\n    protected function initData()\n    {\n        $this->data = [\n            'fields' => new Collection(),\n            'tools'  => new Tools($this),\n            'style'  => 'info',\n            'title'  => trans('admin.detail'),\n        ];\n    }\n\n    /**\n     * Set parent container.\n     *\n     * @param Show $show\n     *\n     * @return $this\n     */\n    public function setParent(Show $show)\n    {\n        $this->parent = $show;\n\n        return $this;\n    }\n\n    /**\n     * Get parent container.\n     *\n     * @return Show\n     */\n    public function getParent()\n    {\n        return $this->parent;\n    }\n\n    /**\n     * Set style for this panel.\n     *\n     * @param string $style\n     *\n     * @return $this\n     */\n    public function style($style = 'info')\n    {\n        $this->data['style'] = $style;\n\n        return $this;\n    }\n\n    /**\n     * Set title for this panel.\n     *\n     * @param string $title\n     *\n     * @return $this\n     */\n    public function title($title)\n    {\n        $this->data['title'] = $title;\n\n        return $this;\n    }\n\n    /**\n     * Set view for this panel to render.\n     *\n     * @param string $view\n     *\n     * @return $this\n     */\n    public function view($view)\n    {\n        $this->view = $view;\n\n        return $this;\n    }\n\n    /**\n     * Build panel tools.\n     *\n     * @param $callable\n     */\n    public function tools($callable)\n    {\n        call_user_func($callable, $this->data['tools']);\n    }\n\n    /**\n     * Fill fields to panel.\n     *\n     * @param []Field $fields\n     *\n     * @return $this\n     */\n    public function fill($fields)\n    {\n        $this->data['fields'] = $fields;\n\n        return $this;\n    }\n\n    /**\n     * Render this panel.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        return view($this->view, $this->data)->render();\n    }\n}\n"
  },
  {
    "path": "src/Show/Relation.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Show;\n\nuse Encore\\Admin\\Grid;\nuse Encore\\Admin\\Show;\nuse Illuminate\\Contracts\\Support\\Renderable;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsTo;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsToMany;\nuse Illuminate\\Database\\Eloquent\\Relations\\HasMany;\nuse Illuminate\\Database\\Eloquent\\Relations\\HasManyThrough;\nuse Illuminate\\Database\\Eloquent\\Relations\\HasOne;\nuse Illuminate\\Database\\Eloquent\\Relations\\MorphMany;\nuse Illuminate\\Database\\Eloquent\\Relations\\MorphOne;\n\nclass Relation extends Field\n{\n    /**\n     * Relation name.\n     *\n     * @var string\n     */\n    protected $name;\n\n    /**\n     * Relation panel builder.\n     *\n     * @var callable\n     */\n    protected $builder;\n\n    /**\n     * Relation panel title.\n     *\n     * @var string\n     */\n    protected $title;\n\n    /**\n     * Parent model.\n     *\n     * @var Model\n     */\n    protected $model;\n\n    /**\n     * Relation constructor.\n     *\n     * @param string   $name\n     * @param callable $builder\n     * @param string   $title\n     */\n    public function __construct($name, $builder, $title = '')\n    {\n        $this->name = $name;\n        $this->builder = $builder;\n        $this->title = $this->formatLabel($title);\n    }\n\n    /**\n     * Set parent model for relation.\n     *\n     * @param Model $model\n     *\n     * @return $this\n     */\n    public function setModel(Model $model)\n    {\n        $this->model = $model;\n\n        return $this;\n    }\n\n    /**\n     * Get null renderable instance.\n     *\n     * @return Renderable|__anonymous@1539\n     */\n    protected function getNullRenderable()\n    {\n        return new class() implements Renderable {\n            public function render()\n            {\n            }\n        };\n    }\n\n    /**\n     * Render this relation panel.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        $relation = $this->model->{$this->name}();\n\n        $renderable = $this->getNullRenderable();\n\n        if ($relation    instanceof HasOne\n            || $relation instanceof BelongsTo\n            || $relation instanceof MorphOne\n        ) {\n            $model = $this->model->{$this->name};\n\n            if (!$model instanceof Model) {\n                $model = $relation->getRelated();\n            }\n\n            $renderable = new Show($model, $this->builder);\n\n            $renderable->panel()->title($this->title);\n        }\n\n        if ($relation    instanceof HasMany\n            || $relation instanceof MorphMany\n            || $relation instanceof BelongsToMany\n            || $relation instanceof HasManyThrough\n        ) {\n            $renderable = new Grid($relation->getRelated(), $this->builder);\n\n            $renderable->setName($this->name)\n                ->setTitle($this->title)\n                ->setRelation($relation);\n        }\n\n        return $renderable->render();\n    }\n}\n"
  },
  {
    "path": "src/Show/Tools.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Show;\n\nuse Encore\\Admin\\Admin;\nuse Illuminate\\Contracts\\Support\\Htmlable;\nuse Illuminate\\Contracts\\Support\\Renderable;\nuse Illuminate\\Support\\Collection;\n\nclass Tools implements Renderable\n{\n    /**\n     * The panel that holds this tool.\n     *\n     * @var Panel\n     */\n    protected $panel;\n\n    /**\n     * @var string\n     */\n    protected $resource;\n\n    /**\n     * Default tools.\n     *\n     * @var array\n     */\n    protected $tools = ['delete', 'edit', 'list'];\n\n    /**\n     * Tools should be appends to default tools.\n     *\n     * @var Collection\n     */\n    protected $appends;\n\n    /**\n     * Tools should be prepends to default tools.\n     *\n     * @var Collection\n     */\n    protected $prepends;\n\n    /**\n     * Tools constructor.\n     *\n     * @param Panel $panel\n     */\n    public function __construct(Panel $panel)\n    {\n        $this->panel = $panel;\n\n        $this->appends = new Collection();\n        $this->prepends = new Collection();\n    }\n\n    /**\n     * Append a tools.\n     *\n     * @param mixed $tool\n     *\n     * @return $this\n     */\n    public function append($tool)\n    {\n        $this->appends->push($tool);\n\n        return $this;\n    }\n\n    /**\n     * Prepend a tool.\n     *\n     * @param mixed $tool\n     *\n     * @return $this\n     */\n    public function prepend($tool)\n    {\n        $this->prepends->push($tool);\n\n        return $this;\n    }\n\n    /**\n     * Get resource path.\n     *\n     * @return string\n     */\n    public function getResource()\n    {\n        if (is_null($this->resource)) {\n            $this->resource = $this->panel->getParent()->getResourcePath();\n        }\n\n        return $this->resource;\n    }\n\n    /**\n     * Disable `list` tool.\n     *\n     * @return $this\n     */\n    public function disableList(bool $disable = true)\n    {\n        if ($disable) {\n            array_delete($this->tools, 'list');\n        } elseif (!in_array('list', $this->tools)) {\n            array_push($this->tools, 'list');\n        }\n\n        return $this;\n    }\n\n    /**\n     * Disable `delete` tool.\n     *\n     * @return $this\n     */\n    public function disableDelete(bool $disable = true)\n    {\n        if ($disable) {\n            array_delete($this->tools, 'delete');\n        } elseif (!in_array('delete', $this->tools)) {\n            array_push($this->tools, 'delete');\n        }\n\n        return $this;\n    }\n\n    /**\n     * Disable `edit` tool.\n     *\n     * @return $this\n     */\n    public function disableEdit(bool $disable = true)\n    {\n        if ($disable) {\n            array_delete($this->tools, 'edit');\n        } elseif (!in_array('edit', $this->tools)) {\n            array_push($this->tools, 'edit');\n        }\n\n        return $this;\n    }\n\n    /**\n     * Get request path for resource list.\n     *\n     * @return string\n     */\n    protected function getListPath()\n    {\n        return ltrim($this->getResource(), '/');\n    }\n\n    /**\n     * Get request path for edit.\n     *\n     * @return string\n     */\n    protected function getEditPath()\n    {\n        $key = $this->panel->getParent()->getModel()->getKey();\n\n        return $this->getListPath().'/'.$key.'/edit';\n    }\n\n    /**\n     * Get request path for delete.\n     *\n     * @return string\n     */\n    protected function getDeletePath()\n    {\n        $key = $this->panel->getParent()->getModel()->getKey();\n\n        return $this->getListPath().'/'.$key;\n    }\n\n    /**\n     * Render `list` tool.\n     *\n     * @return string\n     */\n    protected function renderList()\n    {\n        $list = trans('admin.list');\n\n        return <<<HTML\n<div class=\"btn-group pull-right\" style=\"margin-right: 5px\">\n    <a href=\"{$this->getListPath()}\" class=\"btn btn-sm btn-default\" title=\"{$list}\">\n        <i class=\"fa fa-list\"></i><span class=\"hidden-xs\"> {$list}</span>\n    </a>\n</div>\nHTML;\n    }\n\n    /**\n     * Render `edit` tool.\n     *\n     * @return string\n     */\n    protected function renderEdit()\n    {\n        $edit = trans('admin.edit');\n\n        return <<<HTML\n<div class=\"btn-group pull-right\" style=\"margin-right: 5px\">\n    <a href=\"{$this->getEditPath()}\" class=\"btn btn-sm btn-primary\" title=\"{$edit}\">\n        <i class=\"fa fa-edit\"></i><span class=\"hidden-xs\"> {$edit}</span>\n    </a>\n</div>\nHTML;\n    }\n\n    /**\n     * Render `delete` tool.\n     *\n     * @return string\n     */\n    protected function renderDelete()\n    {\n        $trans = [\n            'delete_confirm' => trans('admin.delete_confirm'),\n            'confirm'        => trans('admin.confirm'),\n            'cancel'         => trans('admin.cancel'),\n            'delete'         => trans('admin.delete'),\n        ];\n\n        $class = uniqid();\n\n        $script = <<<SCRIPT\n\n$('.{$class}-delete').unbind('click').click(function() {\n\n    swal({\n        title: \"{$trans['delete_confirm']}\",\n        type: \"warning\",\n        showCancelButton: true,\n        confirmButtonColor: \"#DD6B55\",\n        confirmButtonText: \"{$trans['confirm']}\",\n        showLoaderOnConfirm: true,\n        cancelButtonText: \"{$trans['cancel']}\",\n        preConfirm: function() {\n            return new Promise(function(resolve) {\n                $.ajax({\n                    method: 'post',\n                    url: '{$this->getDeletePath()}',\n                    data: {\n                        _method:'delete',\n                        _token:LA.token,\n                    },\n                    success: function (data) {\n                        $.pjax({container:'#pjax-container', url: '{$this->getListPath()}' });\n\n                        resolve(data);\n                    }\n                });\n            });\n        }\n    }).then(function(result) {\n        var data = result.value;\n        if (typeof data === 'object') {\n            if (data.status) {\n                swal(data.message, '', 'success');\n            } else {\n                swal(data.message, '', 'error');\n            }\n        }\n    });\n});\n\nSCRIPT;\n        Admin::script($script);\n\n        return <<<HTML\n<div class=\"btn-group pull-right\" style=\"margin-right: 5px\">\n    <a href=\"javascript:void(0);\" class=\"btn btn-sm btn-danger {$class}-delete\" title=\"{$trans['delete']}\">\n        <i class=\"fa fa-trash\"></i><span class=\"hidden-xs\">  {$trans['delete']}</span>\n    </a>\n</div>\nHTML;\n    }\n\n    /**\n     * Render custom tools.\n     *\n     * @param Collection $tools\n     *\n     * @return mixed\n     */\n    protected function renderCustomTools($tools)\n    {\n        return $tools->map(function ($tool) {\n            if ($tool instanceof Renderable) {\n                return $tool->render();\n            }\n\n            if ($tool instanceof Htmlable) {\n                return $tool->toHtml();\n            }\n\n            return (string) $tool;\n        })->implode(' ');\n    }\n\n    /**\n     * Render tools.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        $output = $this->renderCustomTools($this->prepends);\n\n        foreach ($this->tools as $tool) {\n            $renderMethod = 'render'.ucfirst($tool);\n            $output .= $this->$renderMethod();\n        }\n\n        return $output.$this->renderCustomTools($this->appends);\n    }\n}\n"
  },
  {
    "path": "src/Show.php",
    "content": "<?php\n\nnamespace Encore\\Admin;\n\nuse Encore\\Admin\\Show\\Divider;\nuse Encore\\Admin\\Show\\Field;\nuse Encore\\Admin\\Show\\Panel;\nuse Encore\\Admin\\Show\\Relation;\nuse Encore\\Admin\\Traits\\ShouldSnakeAttributes;\nuse Illuminate\\Contracts\\Support\\Renderable;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsTo;\nuse Illuminate\\Database\\Eloquent\\Relations\\BelongsToMany;\nuse Illuminate\\Database\\Eloquent\\Relations\\HasMany;\nuse Illuminate\\Database\\Eloquent\\Relations\\HasManyThrough;\nuse Illuminate\\Database\\Eloquent\\Relations\\HasOne;\nuse Illuminate\\Database\\Eloquent\\Relations\\MorphMany;\nuse Illuminate\\Database\\Eloquent\\Relations\\MorphOne;\nuse Illuminate\\Database\\Eloquent\\Relations\\Relation as EloquentRelation;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Collection;\nuse Illuminate\\Support\\Str;\n\nclass Show implements Renderable\n{\n    use ShouldSnakeAttributes;\n\n    /**\n     * The Eloquent model to show.\n     *\n     * @var Model\n     */\n    protected $model;\n\n    /**\n     * Show panel builder.\n     *\n     * @var callable\n     */\n    protected $builder;\n\n    /**\n     * Resource path for this show page.\n     *\n     * @var string\n     */\n    protected $resource;\n\n    /**\n     * Fields to be show.\n     *\n     * @var Collection\n     */\n    protected $fields;\n\n    /**\n     * Relations to be show.\n     *\n     * @var Collection\n     */\n    protected $relations;\n\n    /**\n     * @var Panel\n     */\n    protected $panel;\n\n    /**\n     * Extended fields.\n     *\n     * @var array\n     */\n    public static $extendedFields = [];\n\n    /**\n     * @var \\Closure\n     */\n    protected static $initCallback;\n\n    /**\n     * Show constructor.\n     *\n     * @param Model $model\n     * @param mixed $builder\n     */\n    public function __construct($model, $builder = null)\n    {\n        $this->model = $model;\n        $this->builder = $builder;\n\n        $this->initPanel();\n        $this->initContents();\n\n        if (static::$initCallback instanceof \\Closure) {\n            call_user_func(static::$initCallback, $this);\n        }\n    }\n\n    /**\n     * Initialize with user pre-defined default disables, etc.\n     *\n     * @param \\Closure $callback\n     */\n    public static function init(\\Closure $callback = null)\n    {\n        static::$initCallback = $callback;\n    }\n\n    /**\n     * Register custom field.\n     *\n     * @param string $abstract\n     * @param string $class\n     *\n     * @return void\n     */\n    public static function extend($abstract, $class)\n    {\n        static::$extendedFields[$abstract] = $class;\n    }\n\n    /**\n     * Initialize the contents to show.\n     */\n    protected function initContents()\n    {\n        $this->fields = new Collection();\n        $this->relations = new Collection();\n    }\n\n    /**\n     * Initialize panel.\n     */\n    protected function initPanel()\n    {\n        $this->panel = new Panel($this);\n    }\n\n    /**\n     * Get panel instance.\n     *\n     * @return Panel\n     */\n    public function panel()\n    {\n        return $this->panel;\n    }\n\n    /**\n     * Add a model field to show.\n     *\n     * @param string $name\n     * @param string $label\n     *\n     * @return Field\n     */\n    public function field($name, $label = '')\n    {\n        return $this->addField($name, $label);\n    }\n\n    /**\n     * Add multiple fields.\n     *\n     * @param array $fields\n     *\n     * @return $this\n     */\n    public function fields(array $fields = [])\n    {\n        if (!Arr::isAssoc($fields)) {\n            $fields = array_combine($fields, $fields);\n        }\n\n        foreach ($fields as $field => $label) {\n            $this->field($field, $label);\n        }\n\n        return $this;\n    }\n\n    /**\n     * Show all fields.\n     *\n     * @return Show\n     */\n    public function all()\n    {\n        $fields = array_keys($this->model->getAttributes());\n\n        return $this->fields($fields);\n    }\n\n    /**\n     * Add a relation to show.\n     *\n     * @param string          $name\n     * @param string|\\Closure $label\n     * @param null|\\Closure   $builder\n     *\n     * @return Relation\n     */\n    public function relation($name, $label, $builder = null)\n    {\n        if (is_null($builder)) {\n            $builder = $label;\n            $label = '';\n        }\n\n        return $this->addRelation($name, $builder, $label);\n    }\n\n    /**\n     * Add a model field to show.\n     *\n     * @param string $name\n     * @param string $label\n     *\n     * @return Field\n     */\n    protected function addField($name, $label = '')\n    {\n        $field = new Field($name, $label);\n\n        $field->setParent($this);\n\n        $this->overwriteExistingField($name);\n\n        return tap($field, function ($field) {\n            $this->fields->push($field);\n        });\n    }\n\n    /**\n     * Add a relation panel to show.\n     *\n     * @param string   $name\n     * @param \\Closure $builder\n     * @param string   $label\n     *\n     * @return Relation\n     */\n    protected function addRelation($name, $builder, $label = '')\n    {\n        $relation = new Relation($name, $builder, $label);\n\n        $relation->setParent($this);\n\n        $this->overwriteExistingRelation($name);\n\n        return tap($relation, function ($relation) {\n            $this->relations->push($relation);\n        });\n    }\n\n    /**\n     * Overwrite existing field.\n     *\n     * @param string $name\n     */\n    protected function overwriteExistingField($name)\n    {\n        if ($this->fields->isEmpty()) {\n            return;\n        }\n\n        $this->fields = $this->fields->filter(\n            function (Field $field) use ($name) {\n                return $field->getName() != $name;\n            }\n        );\n    }\n\n    /**\n     * Overwrite existing relation.\n     *\n     * @param string $name\n     */\n    protected function overwriteExistingRelation($name)\n    {\n        if ($this->relations->isEmpty()) {\n            return;\n        }\n\n        $this->relations = $this->relations->filter(\n            function (Relation $relation) use ($name) {\n                return $relation->getName() != $name;\n            }\n        );\n    }\n\n    /**\n     * Show a divider.\n     */\n    public function divider()\n    {\n        $this->fields->push(new Divider());\n    }\n\n    /**\n     * Set resource path.\n     *\n     * @param string $resource\n     *\n     * @return $this\n     */\n    public function setResource($resource)\n    {\n        $this->resource = $resource;\n\n        return $this;\n    }\n\n    /**\n     * Get resource path.\n     *\n     * @return string\n     */\n    public function getResourcePath()\n    {\n        if (empty($this->resource)) {\n            $path = request()->path();\n\n            $segments = explode('/', $path);\n            array_pop($segments);\n\n            $this->resource = implode('/', $segments);\n        }\n\n        return url($this->resource);\n    }\n\n    /**\n     * Set field and label width in fields.\n     *\n     * @param int $fieldWidth\n     * @param int $labelWidth\n     *\n     * @return $this\n     */\n    public function setWidth($fieldWidth = 8, $labelWidth = 2)\n    {\n        collect($this->fields)->each(function ($field) use ($fieldWidth, $labelWidth) {\n            $field->setWidth($fieldWidth, $labelWidth);\n        });\n\n        return $this;\n    }\n\n    /**\n     * Set the model instance.\n     *\n     * @param Model $model\n     *\n     * @return $this\n     */\n    public function setModel($model)\n    {\n        $this->model = $model;\n\n        return $this;\n    }\n\n    /**\n     * Get the model instance being queried.\n     *\n     * @return Model\n     */\n    public function getModel()\n    {\n        return $this->model;\n    }\n\n    /**\n     * Add field and relation dynamically.\n     *\n     * @param string $method\n     * @param array  $arguments\n     *\n     * @return bool|mixed\n     */\n    public function __call($method, $arguments = [])\n    {\n        $label = isset($arguments[0]) ? $arguments[0] : ucfirst($method);\n\n        if ($field = $this->handleGetMutatorField($method, $label)) {\n            return $field;\n        }\n\n        if ($field = $this->handleRelationField($method, $arguments)) {\n            return $field;\n        }\n\n        return $this->addField($method, $label);\n    }\n\n    /**\n     * Handle the get mutator field.\n     *\n     * @param string $method\n     * @param string $label\n     *\n     * @return bool|Field\n     */\n    protected function handleGetMutatorField($method, $label)\n    {\n        if (is_null($this->model)) {\n            return false;\n        }\n\n        if ($this->model->hasGetMutator($method)) {\n            return $this->addField($method, $label);\n        }\n\n        return false;\n    }\n\n    /**\n     * Handle relation field.\n     *\n     * @param string $method\n     * @param array  $arguments\n     *\n     * @return $this|bool|Relation|Field\n     */\n    protected function handleRelationField($method, $arguments)\n    {\n        if (!method_exists($this->model, $method)) {\n            return false;\n        }\n\n        if (!($relation = $this->model->$method()) instanceof EloquentRelation) {\n            return false;\n        }\n\n        if ($relation    instanceof HasOne\n            || $relation instanceof BelongsTo\n            || $relation instanceof MorphOne\n        ) {\n            $this->model->with($method);\n\n            if (count($arguments) == 1 && $arguments[0] instanceof \\Closure) {\n                return $this->addRelation($method, $arguments[0]);\n            }\n\n            if (count($arguments) == 2 && $arguments[1] instanceof \\Closure) {\n                return $this->addRelation($method, $arguments[1], $arguments[0]);\n            }\n\n            return $this->addField($method, Arr::get($arguments, 0))->setRelation(\n                $this->shouldSnakeAttributes() ? Str::snake($method) : $method\n            );\n        }\n\n        if ($relation    instanceof HasMany\n            || $relation instanceof MorphMany\n            || $relation instanceof BelongsToMany\n            || $relation instanceof HasManyThrough\n        ) {\n            if (empty($arguments) || (count($arguments) == 1 && is_string($arguments[0]))) {\n                return $this->showRelationAsField($method, $arguments[0] ?? '');\n            }\n\n            $this->model->with($method);\n\n            if (count($arguments) == 1 && is_callable($arguments[0])) {\n                return $this->addRelation($method, $arguments[0]);\n            } elseif (count($arguments) == 2 && is_callable($arguments[1])) {\n                return $this->addRelation($method, $arguments[1], $arguments[0]);\n            }\n\n            throw new \\InvalidArgumentException('Invalid eloquent relation');\n        }\n\n        return false;\n    }\n\n    /**\n     * @param string $relation\n     * @param string $label\n     *\n     * @return Field\n     */\n    protected function showRelationAsField($relation = '', $label = '')\n    {\n        return $this->addField($relation, $label);\n    }\n\n    /**\n     * Handle model field.\n     *\n     * @param string $method\n     * @param string $label\n     *\n     * @return bool|Field\n     */\n    protected function handleModelField($method, $label)\n    {\n        if (in_array($method, $this->model->getAttributes())) {\n            return $this->addField($method, $label);\n        }\n\n        return false;\n    }\n\n    /**\n     * Render the show panels.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        if (is_callable($this->builder)) {\n            call_user_func($this->builder, $this);\n        }\n\n        if ($this->fields->isEmpty()) {\n            $this->all();\n        }\n\n        if (is_array($this->builder)) {\n            $this->fields($this->builder);\n        }\n\n        $this->fields->each->setValue($this->model);\n        $this->relations->each->setModel($this->model);\n\n        $data = [\n            'panel'     => $this->panel->fill($this->fields),\n            'relations' => $this->relations,\n        ];\n\n        return view('admin::show', $data)->render();\n    }\n}\n"
  },
  {
    "path": "src/Traits/AdminBuilder.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Traits;\n\nuse Encore\\Admin\\Form;\nuse Encore\\Admin\\Grid;\nuse Encore\\Admin\\Tree;\n\n/**\n * @deprecated\n */\ntrait AdminBuilder\n{\n    /**\n     * @param \\Closure $callback\n     *\n     * @return Grid\n     */\n    public static function grid(\\Closure $callback)\n    {\n        return new Grid(new static(), $callback);\n    }\n\n    /**\n     * @param \\Closure $callback\n     *\n     * @return Form\n     */\n    public static function form(\\Closure $callback)\n    {\n        return new Form(new static(), $callback);\n    }\n\n    /**\n     * @param \\Closure $callback\n     *\n     * @return Tree\n     */\n    public static function tree(\\Closure $callback = null)\n    {\n        return new Tree(new static(), $callback);\n    }\n}\n"
  },
  {
    "path": "src/Traits/DefaultDatetimeFormat.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Traits;\n\nuse Carbon\\Carbon;\n\ntrait DefaultDatetimeFormat\n{\n    protected function serializeDate(\\DateTimeInterface $date)\n    {\n        if (version_compare(app()->version(), '7.0.0') < 0) {\n            return parent::serializeDate($date);\n        }\n\n        return $date->format(Carbon::DEFAULT_TO_STRING_FORMAT);\n    }\n}\n"
  },
  {
    "path": "src/Traits/HasAssets.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Traits;\n\ntrait HasAssets\n{\n    /**\n     * @var array\n     */\n    public static $script = [];\n\n    /**\n     * @var array\n     */\n    public static $deferredScript = [];\n\n    /**\n     * @var array\n     */\n    public static $style = [];\n\n    /**\n     * @var array\n     */\n    public static $css = [];\n\n    /**\n     * @var array\n     */\n    public static $js = [];\n\n    /**\n     * @var array\n     */\n    public static $html = [];\n\n    /**\n     * @var array\n     */\n    public static $headerJs = [];\n\n    /**\n     * @var string\n     */\n    public static $manifest = 'vendor/laravel-admin/minify-manifest.json';\n\n    /**\n     * @var array\n     */\n    public static $manifestData = [];\n\n    /**\n     * @var array\n     */\n    public static $min = [\n        'js'  => 'vendor/laravel-admin/laravel-admin.min.js',\n        'css' => 'vendor/laravel-admin/laravel-admin.min.css',\n    ];\n\n    /**\n     * @var array\n     */\n    public static $baseCss = [\n        'vendor/laravel-admin/AdminLTE/bootstrap/css/bootstrap.min.css',\n        'vendor/laravel-admin/font-awesome/css/font-awesome.min.css',\n        'vendor/laravel-admin/laravel-admin/laravel-admin.css',\n        'vendor/laravel-admin/nprogress/nprogress.css',\n        'vendor/laravel-admin/sweetalert2/dist/sweetalert2.css',\n        'vendor/laravel-admin/nestable/nestable.css',\n        'vendor/laravel-admin/toastr/build/toastr.min.css',\n        'vendor/laravel-admin/bootstrap3-editable/css/bootstrap-editable.css',\n        'vendor/laravel-admin/google-fonts/fonts.css',\n        'vendor/laravel-admin/AdminLTE/dist/css/AdminLTE.min.css',\n    ];\n\n    /**\n     * @var array\n     */\n    public static $baseJs = [\n        'vendor/laravel-admin/AdminLTE/bootstrap/js/bootstrap.min.js',\n        'vendor/laravel-admin/AdminLTE/plugins/slimScroll/jquery.slimscroll.min.js',\n        'vendor/laravel-admin/AdminLTE/dist/js/app.min.js',\n        'vendor/laravel-admin/jquery-pjax/jquery.pjax.js',\n        'vendor/laravel-admin/nprogress/nprogress.js',\n        'vendor/laravel-admin/nestable/jquery.nestable.js',\n        'vendor/laravel-admin/toastr/build/toastr.min.js',\n        'vendor/laravel-admin/bootstrap3-editable/js/bootstrap-editable.min.js',\n        'vendor/laravel-admin/sweetalert2/dist/sweetalert2.min.js',\n        'vendor/laravel-admin/laravel-admin/laravel-admin.js',\n    ];\n\n    /**\n     * @var string\n     */\n    public static $jQuery = 'vendor/laravel-admin/AdminLTE/plugins/jQuery/jQuery-2.1.4.min.js';\n\n    /**\n     * @var array\n     */\n    public static $minifyIgnores = [];\n\n    /**\n     * Add css or get all css.\n     *\n     * @param null $css\n     * @param bool $minify\n     *\n     * @return array|\\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View\n     */\n    public static function css($css = null, $minify = true)\n    {\n        static::ignoreMinify($css, $minify);\n\n        if (!is_null($css)) {\n            return self::$css = array_merge(self::$css, (array) $css);\n        }\n\n        if (!$css = static::getMinifiedCss()) {\n            $css = array_merge(static::$css, static::baseCss());\n        }\n\n        $css = array_filter(array_unique($css));\n\n        return view('admin::partials.css', compact('css'));\n    }\n\n    /**\n     * @param null $css\n     * @param bool $minify\n     *\n     * @return array|null\n     */\n    public static function baseCss($css = null, $minify = true)\n    {\n        static::ignoreMinify($css, $minify);\n\n        if (!is_null($css)) {\n            return static::$baseCss = $css;\n        }\n\n        $skin = config('admin.skin', 'skin-blue-light');\n\n        array_unshift(static::$baseCss, \"vendor/laravel-admin/AdminLTE/dist/css/skins/{$skin}.min.css\");\n\n        return static::$baseCss;\n    }\n\n    /**\n     * Add js or get all js.\n     *\n     * @param null $js\n     * @param bool $minify\n     *\n     * @return array|\\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View\n     */\n    public static function js($js = null, $minify = true)\n    {\n        static::ignoreMinify($js, $minify);\n\n        if (!is_null($js)) {\n            return self::$js = array_merge(self::$js, (array) $js);\n        }\n\n        if (!$js = static::getMinifiedJs()) {\n            $js = array_merge(static::baseJs(), static::$js);\n        }\n\n        $js = array_filter(array_unique($js));\n\n        return view('admin::partials.js', compact('js'));\n    }\n\n    /**\n     * Add js or get all js.\n     *\n     * @param null $js\n     *\n     * @return array|\\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View\n     */\n    public static function headerJs($js = null)\n    {\n        if (!is_null($js)) {\n            return self::$headerJs = array_merge(self::$headerJs, (array) $js);\n        }\n\n        return view('admin::partials.js', ['js' => array_unique(static::$headerJs)]);\n    }\n\n    /**\n     * @param null $js\n     * @param bool $minify\n     *\n     * @return array|null\n     */\n    public static function baseJs($js = null, $minify = true)\n    {\n        static::ignoreMinify($js, $minify);\n\n        if (!is_null($js)) {\n            return static::$baseJs = $js;\n        }\n\n        return static::$baseJs;\n    }\n\n    /**\n     * @param string $assets\n     * @param bool   $ignore\n     */\n    public static function ignoreMinify($assets, $ignore = true)\n    {\n        if (!$ignore) {\n            static::$minifyIgnores[] = $assets;\n        }\n    }\n\n    /**\n     * @param string $script\n     * @param bool   $deferred\n     *\n     * @return array|\\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View\n     */\n    public static function script($script = '', $deferred = false)\n    {\n        if (!empty($script)) {\n            if ($deferred) {\n                return self::$deferredScript = array_merge(self::$deferredScript, (array) $script);\n            }\n\n            return self::$script = array_merge(self::$script, (array) $script);\n        }\n\n        $script = collect(static::$script)\n            ->merge(static::$deferredScript)\n            ->unique()\n            ->map(function ($line) {\n                return $line;\n                //@see https://stackoverflow.com/questions/19509863/how-to-remove-js-comments-using-php\n                $pattern = '/(?:(?:\\/\\*(?:[^*]|(?:\\*+[^*\\/]))*\\*+\\/)|(?:(?<!\\:|\\\\\\|\\')\\/\\/.*))/';\n                $line = preg_replace($pattern, '', $line);\n\n                return preg_replace('/\\s+/', ' ', $line);\n            });\n\n        return view('admin::partials.script', compact('script'));\n    }\n\n    /**\n     * @param string $style\n     *\n     * @return array|\\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View\n     */\n    public static function style($style = '')\n    {\n        if (!empty($style)) {\n            return self::$style = array_merge(self::$style, (array) $style);\n        }\n\n        $style = collect(static::$style)\n            ->unique()\n            ->map(function ($line) {\n                return preg_replace('/\\s+/', ' ', $line);\n            });\n\n        return view('admin::partials.style', compact('style'));\n    }\n\n    /**\n     * @param string $html\n     *\n     * @return array|\\Illuminate\\Contracts\\View\\Factory|\\Illuminate\\View\\View\n     */\n    public static function html($html = '')\n    {\n        if (!empty($html)) {\n            return self::$html = array_merge(self::$html, (array) $html);\n        }\n\n        return view('admin::partials.html', ['html' => array_unique(self::$html)]);\n    }\n\n    /**\n     * @param string $key\n     *\n     * @return mixed\n     */\n    protected static function getManifestData($key)\n    {\n        if (!empty(static::$manifestData)) {\n            return static::$manifestData[$key];\n        }\n\n        static::$manifestData = json_decode(\n            file_get_contents(public_path(static::$manifest)),\n            true\n        );\n\n        return static::$manifestData[$key];\n    }\n\n    /**\n     * @return bool|mixed\n     */\n    protected static function getMinifiedCss()\n    {\n        if (!config('admin.minify_assets') || !file_exists(public_path(static::$manifest))) {\n            return false;\n        }\n\n        return static::getManifestData('css');\n    }\n\n    /**\n     * @return bool|mixed\n     */\n    protected static function getMinifiedJs()\n    {\n        if (!config('admin.minify_assets') || !file_exists(public_path(static::$manifest))) {\n            return false;\n        }\n\n        return static::getManifestData('js');\n    }\n\n    /**\n     * @return string\n     */\n    public function jQuery()\n    {\n        return admin_asset(static::$jQuery);\n    }\n\n    /**\n     * @param $component\n     */\n    public static function component($component, $data = [])\n    {\n        $string = view($component, $data)->render();\n\n        $dom = new \\DOMDocument();\n\n        libxml_use_internal_errors(true);\n        $dom->loadHTML('<?xml encoding=\"utf-8\" ?>'.$string);\n        libxml_use_internal_errors(false);\n\n        if ($head = $dom->getElementsByTagName('head')->item(0)) {\n            foreach ($head->childNodes as $child) {\n                if ($child instanceof \\DOMElement) {\n                    if ($child->tagName == 'style' && !empty($child->nodeValue)) {\n                        static::style($child->nodeValue);\n                        continue;\n                    }\n\n                    if ($child->tagName == 'link' && $child->hasAttribute('href')) {\n                        static::css($child->getAttribute('href'));\n                    }\n\n                    if ($child->tagName == 'script') {\n                        if ($child->hasAttribute('src')) {\n                            static::js($child->getAttribute('src'));\n                        } else {\n                            static::script(';(function () {'.$child->nodeValue.'})();');\n                        }\n\n                        continue;\n                    }\n                }\n            }\n        }\n\n        $render = '';\n\n        if ($body = $dom->getElementsByTagName('body')->item(0)) {\n            foreach ($body->childNodes as $child) {\n                if ($child instanceof \\DOMElement) {\n                    if ($child->tagName == 'style' && !empty($child->nodeValue)) {\n                        static::style($child->nodeValue);\n                        continue;\n                    }\n\n                    if ($child->tagName == 'script' && !empty($child->nodeValue)) {\n                        static::script(';(function () {'.$child->nodeValue.'})();');\n                        continue;\n                    }\n\n                    if ($child->tagName == 'template') {\n                        $html = '';\n                        foreach ($child->childNodes as $childNode) {\n                            $html .= $child->ownerDocument->saveHTML($childNode);\n                        }\n                        $html && static::html($html);\n                        continue;\n                    }\n                }\n\n                $render .= $body->ownerDocument->saveHTML($child);\n            }\n        }\n\n        return trim($render);\n    }\n}\n"
  },
  {
    "path": "src/Traits/ModelTree.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Traits;\n\nuse Encore\\Admin\\Tree;\nuse Illuminate\\Database\\Eloquent\\Model;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Facades\\DB;\nuse Illuminate\\Support\\Facades\\Request;\n\ntrait ModelTree\n{\n    /**\n     * @var array\n     */\n    protected static $branchOrder = [];\n\n    /**\n     * @var string\n     */\n    protected $parentColumn = 'parent_id';\n\n    /**\n     * @var string\n     */\n    protected $titleColumn = 'title';\n\n    /**\n     * @var string\n     */\n    protected $orderColumn = 'order';\n\n    /**\n     * @var \\Closure\n     */\n    protected $queryCallback;\n\n    /**\n     * Get children of current node.\n     *\n     * @return \\Illuminate\\Database\\Eloquent\\Relations\\HasMany\n     */\n    public function children()\n    {\n        return $this->hasMany(static::class, $this->parentColumn);\n    }\n\n    /**\n     * Get parent of current node.\n     *\n     * @return \\Illuminate\\Database\\Eloquent\\Relations\\BelongsTo\n     */\n    public function parent()\n    {\n        return $this->belongsTo(static::class, $this->parentColumn);\n    }\n\n    /**\n     * @return string\n     */\n    public function getParentColumn()\n    {\n        return $this->parentColumn;\n    }\n\n    /**\n     * Set parent column.\n     *\n     * @param string $column\n     */\n    public function setParentColumn($column)\n    {\n        $this->parentColumn = $column;\n    }\n\n    /**\n     * Get title column.\n     *\n     * @return string\n     */\n    public function getTitleColumn()\n    {\n        return $this->titleColumn;\n    }\n\n    /**\n     * Set title column.\n     *\n     * @param string $column\n     */\n    public function setTitleColumn($column)\n    {\n        $this->titleColumn = $column;\n    }\n\n    /**\n     * Get order column name.\n     *\n     * @return string\n     */\n    public function getOrderColumn()\n    {\n        return $this->orderColumn;\n    }\n\n    /**\n     * Set order column.\n     *\n     * @param string $column\n     */\n    public function setOrderColumn($column)\n    {\n        $this->orderColumn = $column;\n    }\n\n    /**\n     * Set query callback to model.\n     *\n     * @param \\Closure|null $query\n     *\n     * @return $this\n     */\n    public function withQuery(\\Closure $query = null)\n    {\n        $this->queryCallback = $query;\n\n        return $this;\n    }\n\n    /**\n     * Format data to tree like array.\n     *\n     * @return array\n     */\n    public function toTree()\n    {\n        return $this->buildNestedArray();\n    }\n\n    /**\n     * Build Nested array.\n     *\n     * @param array $nodes\n     * @param int   $parentId\n     *\n     * @return array\n     */\n    protected function buildNestedArray(array $nodes = [], $parentId = 0)\n    {\n        $branch = [];\n\n        if (empty($nodes)) {\n            $nodes = $this->allNodes();\n        }\n\n        foreach ($nodes as $node) {\n            if ($node[$this->parentColumn] == $parentId) {\n                $children = $this->buildNestedArray($nodes, $node[$this->getKeyName()]);\n\n                if ($children) {\n                    $node['children'] = $children;\n                }\n\n                $branch[] = $node;\n            }\n        }\n\n        return $branch;\n    }\n\n    /**\n     * Get all elements.\n     *\n     * @return mixed\n     */\n    public function allNodes()\n    {\n        $orderColumn = DB::getQueryGrammar()->wrap($this->orderColumn);\n        $byOrder = $orderColumn.' = 0,'.$orderColumn;\n\n        $self = new static();\n\n        if ($this->queryCallback instanceof \\Closure) {\n            $self = call_user_func($this->queryCallback, $self);\n        }\n\n        return $self->orderByRaw($byOrder)->get()->toArray();\n    }\n\n    /**\n     * Set the order of branches in the tree.\n     *\n     * @param array $order\n     *\n     * @return void\n     */\n    protected static function setBranchOrder(array $order)\n    {\n        static::$branchOrder = array_flip(Arr::flatten($order));\n\n        static::$branchOrder = array_map(function ($item) {\n            return ++$item;\n        }, static::$branchOrder);\n    }\n\n    /**\n     * Save tree order from a tree like array.\n     *\n     * @param array $tree\n     * @param int   $parentId\n     */\n    public static function saveOrder($tree = [], $parentId = 0)\n    {\n        if (empty(static::$branchOrder)) {\n            static::setBranchOrder($tree);\n        }\n\n        foreach ($tree as $branch) {\n            $node = static::find($branch['id']);\n\n            $node->{$node->getParentColumn()} = $parentId;\n            $node->{$node->getOrderColumn()} = static::$branchOrder[$branch['id']];\n            $node->save();\n\n            if (isset($branch['children'])) {\n                static::saveOrder($branch['children'], $branch['id']);\n            }\n        }\n    }\n\n    /**\n     * Get options for Select field in form.\n     *\n     * @param \\Closure|null $closure\n     * @param string        $rootText\n     *\n     * @return array\n     */\n    public static function selectOptions(\\Closure $closure = null, $rootText = 'ROOT')\n    {\n        $options = (new static())->withQuery($closure)->buildSelectOptions();\n\n        return collect($options)->prepend($rootText, 0)->all();\n    }\n\n    /**\n     * Build options of select field in form.\n     *\n     * @param array  $nodes\n     * @param int    $parentId\n     * @param string $prefix\n     * @param string $space\n     *\n     * @return array\n     */\n    protected function buildSelectOptions(array $nodes = [], $parentId = 0, $prefix = '', $space = '&nbsp;')\n    {\n        $prefix = $prefix ?: '┝'.$space;\n\n        $options = [];\n\n        if (empty($nodes)) {\n            $nodes = $this->allNodes();\n        }\n\n        foreach ($nodes as $index => $node) {\n            if ($node[$this->parentColumn] == $parentId) {\n                $node[$this->titleColumn] = $prefix.$space.$node[$this->titleColumn];\n\n                $childrenPrefix = str_replace('┝', str_repeat($space, 6), $prefix).'┝'.str_replace(['┝', $space], '', $prefix);\n\n                $children = $this->buildSelectOptions($nodes, $node[$this->getKeyName()], $childrenPrefix);\n\n                $options[$node[$this->getKeyName()]] = $node[$this->titleColumn];\n\n                if ($children) {\n                    $options += $children;\n                }\n            }\n        }\n\n        return $options;\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    public function delete()\n    {\n        $this->where($this->parentColumn, $this->getKey())->delete();\n\n        return parent::delete();\n    }\n\n    /**\n     * {@inheritdoc}\n     */\n    protected static function boot()\n    {\n        parent::boot();\n\n        static::saving(function (Model $branch) {\n            $parentColumn = $branch->getParentColumn();\n\n            if (Request::has($parentColumn) && Request::input($parentColumn) == $branch->getKey()) {\n                throw new \\Exception(trans('admin.parent_select_error'));\n            }\n\n            if (Request::has('_order')) {\n                $order = Request::input('_order');\n\n                Request::offsetUnset('_order');\n\n                (new Tree(new static()))->saveOrder($order);\n\n                return false;\n            }\n\n            return $branch;\n        });\n    }\n}\n"
  },
  {
    "path": "src/Traits/Resizable.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Traits;\n\nuse Illuminate\\Support\\Str;\n\ntrait Resizable\n{\n    /**\n     * Method for returning specific thumbnail for model.\n     *\n     * @param string $type\n     * @param string $attribute\n     *\n     * @return string\n     */\n    public function thumbnail($type, $attribute = 'image')\n    {\n        // Return empty string if the field not found\n        if (!isset($this->attributes[$attribute])) {\n            return '';\n        }\n\n        // We take image from posts field\n        $image = $this->attributes[$attribute];\n\n        $thumbnail = $this->getThumbnail($image, $type);\n\n        return \\Illuminate\\Support\\Facades\\Storage::disk(config('admin.upload.disk'))->exists($thumbnail) ? $thumbnail : $image;\n    }\n\n    /**\n     * Generate thumbnail URL.\n     *\n     * @param $image\n     * @param $type\n     *\n     * @return string\n     */\n    public function getThumbnail($image, $type)\n    {\n        // We need to get extension type ( .jpeg , .png ...)\n        $ext = pathinfo($image, PATHINFO_EXTENSION);\n\n        // We remove extension from file name so we can append thumbnail type\n        $name = Str::replaceLast('.'.$ext, '', $image);\n\n        // We merge original name + type + extension\n        return $name.'-'.$type.'.'.$ext;\n    }\n}\n"
  },
  {
    "path": "src/Traits/ShouldSnakeAttributes.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Traits;\n\nuse Encore\\Admin\\Grid\\Model as GridModel;\n\ntrait ShouldSnakeAttributes\n{\n    /**\n     * Indicates whether attributes are snake cased on arrays.\n     *\n     * @var bool\n     */\n    protected static $snakeAttributes;\n\n    /**\n     * Indicates if model should snake attribute name.\n     *\n     * @return bool\n     */\n    public function shouldSnakeAttributes()\n    {\n        if (is_bool(static::$snakeAttributes)) {\n            return static::$snakeAttributes;\n        }\n\n        $model = ($this->model instanceof GridModel) ?\n            $this->model->eloquent() : $this->model;\n\n        $class = get_class($model);\n\n        return static::$snakeAttributes = $class::$snakeAttributes;\n    }\n}\n"
  },
  {
    "path": "src/Tree/Tools.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Tree;\n\nuse Encore\\Admin\\Tree;\nuse Illuminate\\Contracts\\Support\\Htmlable;\nuse Illuminate\\Contracts\\Support\\Renderable;\nuse Illuminate\\Support\\Collection;\n\nclass Tools implements Renderable\n{\n    /**\n     * Parent tree.\n     *\n     * @var Tree\n     */\n    protected $tree;\n\n    /**\n     * Collection of tools.\n     *\n     * @var Collection\n     */\n    protected $tools;\n\n    /**\n     * Create a new Tools instance.\n     *\n     * @param Tree $tree\n     */\n    public function __construct(Tree $tree)\n    {\n        $this->tree = $tree;\n        $this->tools = new Collection();\n    }\n\n    /**\n     * Prepend a tool.\n     *\n     * @param string $tool\n     *\n     * @return $this\n     */\n    public function add($tool)\n    {\n        $this->tools->push($tool);\n\n        return $this;\n    }\n\n    /**\n     * Render header tools bar.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        return $this->tools->map(function ($tool) {\n            if ($tool instanceof Renderable) {\n                return $tool->render();\n            }\n\n            if ($tool instanceof Htmlable) {\n                return $tool->toHtml();\n            }\n\n            return (string) $tool;\n        })->implode(' ');\n    }\n}\n"
  },
  {
    "path": "src/Tree.php",
    "content": "<?php\n\nnamespace Encore\\Admin;\n\nuse Closure;\nuse Encore\\Admin\\Tree\\Tools;\nuse Illuminate\\Contracts\\Support\\Renderable;\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass Tree implements Renderable\n{\n    /**\n     * @var array\n     */\n    protected $items = [];\n\n    /**\n     * @var string\n     */\n    protected $elementId = 'tree-';\n\n    /**\n     * @var Model\n     */\n    protected $model;\n\n    /**\n     * @var \\Closure\n     */\n    protected $queryCallback;\n\n    /**\n     * View of tree to render.\n     *\n     * @var string\n     */\n    protected $view = [\n        'tree'   => 'admin::tree',\n        'branch' => 'admin::tree.branch',\n    ];\n\n    /**\n     * @var \\Closure\n     */\n    protected $callback;\n\n    /**\n     * @var null\n     */\n    protected $branchCallback = null;\n\n    /**\n     * @var bool\n     */\n    public $useCreate = true;\n\n    /**\n     * @var bool\n     */\n    public $useSave = true;\n\n    /**\n     * @var bool\n     */\n    public $useRefresh = true;\n\n    /**\n     * @var array\n     */\n    protected $nestableOptions = [];\n\n    /**\n     * Header tools.\n     *\n     * @var Tools\n     */\n    public $tools;\n\n    /**\n     * Menu constructor.\n     *\n     * @param Model|null $model\n     */\n    public function __construct(Model $model = null, \\Closure $callback = null)\n    {\n        $this->model = $model;\n\n        $this->path = \\request()->getPathInfo();\n        $this->elementId .= uniqid();\n\n        $this->setupTools();\n\n        if ($callback instanceof \\Closure) {\n            call_user_func($callback, $this);\n        }\n\n        $this->initBranchCallback();\n    }\n\n    /**\n     * Setup tree tools.\n     */\n    public function setupTools()\n    {\n        $this->tools = new Tools($this);\n    }\n\n    /**\n     * Initialize branch callback.\n     *\n     * @return void\n     */\n    protected function initBranchCallback()\n    {\n        if (is_null($this->branchCallback)) {\n            $this->branchCallback = function ($branch) {\n                $key = $branch[$this->model->getKeyName()];\n                $title = $branch[$this->model->getTitleColumn()];\n\n                return \"$key - $title\";\n            };\n        }\n    }\n\n    /**\n     * Set branch callback.\n     *\n     * @param \\Closure $branchCallback\n     *\n     * @return $this\n     */\n    public function branch(\\Closure $branchCallback)\n    {\n        $this->branchCallback = $branchCallback;\n\n        return $this;\n    }\n\n    /**\n     * Set query callback this tree.\n     *\n     * @return Model\n     */\n    public function query(\\Closure $callback)\n    {\n        $this->queryCallback = $callback;\n\n        return $this;\n    }\n\n    /**\n     * Set nestable options.\n     *\n     * @param array $options\n     *\n     * @return $this\n     */\n    public function nestable($options = [])\n    {\n        $this->nestableOptions = array_merge($this->nestableOptions, $options);\n\n        return $this;\n    }\n\n    /**\n     * Disable create.\n     *\n     * @return void\n     */\n    public function disableCreate()\n    {\n        $this->useCreate = false;\n    }\n\n    /**\n     * Disable save.\n     *\n     * @return void\n     */\n    public function disableSave()\n    {\n        $this->useSave = false;\n    }\n\n    /**\n     * Disable refresh.\n     *\n     * @return void\n     */\n    public function disableRefresh()\n    {\n        $this->useRefresh = false;\n    }\n\n    /**\n     * Save tree order from a input.\n     *\n     * @param string $serialize\n     *\n     * @return bool\n     */\n    public function saveOrder($serialize)\n    {\n        $tree = json_decode($serialize, true);\n\n        if (json_last_error() != JSON_ERROR_NONE) {\n            throw new \\InvalidArgumentException(json_last_error_msg());\n        }\n\n        $this->model->saveOrder($tree);\n\n        return true;\n    }\n\n    /**\n     * Build tree grid scripts.\n     *\n     * @return string\n     */\n    protected function script()\n    {\n        $trans = [\n            'delete_confirm'    => str_replace(\"'\", \"\\'\", trans('admin.delete_confirm')),\n            'save_succeeded'    => str_replace(\"'\", \"\\'\", trans('admin.save_succeeded')),\n            'refresh_succeeded' => str_replace(\"'\", \"\\'\", trans('admin.refresh_succeeded')),\n            'delete_succeeded'  => str_replace(\"'\", \"\\'\", trans('admin.delete_succeeded')),\n            'confirm'           => str_replace(\"'\", \"\\'\", trans('admin.confirm')),\n            'cancel'            => str_replace(\"'\", \"\\'\", trans('admin.cancel')),\n        ];\n\n        $nestableOptions = json_encode($this->nestableOptions);\n\n        $url = url($this->path);\n\n        return <<<SCRIPT\n\n        $('#{$this->elementId}').nestable($nestableOptions);\n\n        $('.tree_branch_delete').click(function() {\n            var id = $(this).data('id');\n            swal({\n                title: \"{$trans['delete_confirm']}\",\n                type: \"warning\",\n                showCancelButton: true,\n                confirmButtonColor: \"#DD6B55\",\n                confirmButtonText: \"{$trans['confirm']}\",\n                showLoaderOnConfirm: true,\n                cancelButtonText: \"{$trans['cancel']}\",\n                preConfirm: function() {\n                    return new Promise(function(resolve) {\n                        $.ajax({\n                            method: 'post',\n                            url: '{$url}/' + id,\n                            data: {\n                                _method:'delete',\n                                _token:LA.token,\n                            },\n                            success: function (data) {\n                                $.pjax.reload('#pjax-container');\n                                toastr.success('{$trans['delete_succeeded']}');\n                                resolve(data);\n                            }\n                        });\n                    });\n                }\n            }).then(function(result) {\n                var data = result.value;\n                if (typeof data === 'object') {\n                    if (data.status) {\n                        swal(data.message, '', 'success');\n                    } else {\n                        swal(data.message, '', 'error');\n                    }\n                }\n            });\n        });\n\n        $('.{$this->elementId}-save').click(function () {\n            var serialize = $('#{$this->elementId}').nestable('serialize');\n\n            $.post('{$url}', {\n                _token: LA.token,\n                _order: JSON.stringify(serialize)\n            },\n            function(data){\n                $.pjax.reload('#pjax-container');\n                toastr.success('{$trans['save_succeeded']}');\n            });\n        });\n\n        $('.{$this->elementId}-refresh').click(function () {\n            $.pjax.reload('#pjax-container');\n            toastr.success('{$trans['refresh_succeeded']}');\n        });\n\n        $('.{$this->elementId}-tree-tools').on('click', function(e){\n            var action = $(this).data('action');\n            if (action === 'expand') {\n                $('.dd').nestable('expandAll');\n            }\n            if (action === 'collapse') {\n                $('.dd').nestable('collapseAll');\n            }\n        });\n\n\nSCRIPT;\n    }\n\n    /**\n     * Set view of tree.\n     *\n     * @param string $view\n     */\n    public function setView($view)\n    {\n        $this->view = $view;\n    }\n\n    /**\n     * Return all items of the tree.\n     *\n     * @return array\n     */\n    public function getItems()\n    {\n        return $this->model->withQuery($this->queryCallback)->toTree();\n    }\n\n    /**\n     * Variables in tree template.\n     *\n     * @return array\n     */\n    public function variables()\n    {\n        return [\n            'id'         => $this->elementId,\n            'tools'      => $this->tools->render(),\n            'items'      => $this->getItems(),\n            'useCreate'  => $this->useCreate,\n            'useSave'    => $this->useSave,\n            'useRefresh' => $this->useRefresh,\n        ];\n    }\n\n    /**\n     * Setup grid tools.\n     *\n     * @param Closure $callback\n     *\n     * @return void\n     */\n    public function tools(Closure $callback)\n    {\n        call_user_func($callback, $this->tools);\n    }\n\n    /**\n     * Render a tree.\n     *\n     * @return \\Illuminate\\Http\\JsonResponse|string\n     */\n    public function render()\n    {\n        Admin::script($this->script());\n\n        view()->share([\n            'path'           => $this->path,\n            'keyName'        => $this->model->getKeyName(),\n            'branchView'     => $this->view['branch'],\n            'branchCallback' => $this->branchCallback,\n        ]);\n\n        return view($this->view['tree'], $this->variables())->render();\n    }\n\n    /**\n     * Get the string contents of the grid view.\n     *\n     * @return string\n     */\n    public function __toString()\n    {\n        return $this->render();\n    }\n}\n"
  },
  {
    "path": "src/Widgets/Alert.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Widgets;\n\nuse Illuminate\\Contracts\\Support\\Renderable;\n\nclass Alert extends Widget implements Renderable\n{\n    /**\n     * @var string\n     */\n    protected $view = 'admin::widgets.alert';\n\n    /**\n     * @var string|\\Symfony\\Component\\Translation\\TranslatorInterface\n     */\n    protected $title = '';\n\n    /**\n     * @var string\n     */\n    protected $content = '';\n\n    /**\n     * @var string\n     */\n    protected $style = 'danger';\n\n    /**\n     * @var string\n     */\n    protected $icon = 'ban';\n\n    /**\n     * Alert constructor.\n     *\n     * @param mixed  $content\n     * @param string $title\n     * @param string $style\n     */\n    public function __construct($content, $title = '', $style = 'danger')\n    {\n        $this->content = (string) $content;\n\n        $this->title = $title ?: trans('admin.alert');\n\n        $this->style($style);\n    }\n\n    /**\n     * Add style.\n     *\n     * @param string $style\n     *\n     * @return $this\n     */\n    public function style($style = 'info')\n    {\n        $this->style = $style;\n\n        return $this;\n    }\n\n    /**\n     * Add icon.\n     *\n     * @param string $icon\n     *\n     * @return $this\n     */\n    public function icon($icon)\n    {\n        $this->icon = $icon;\n\n        return $this;\n    }\n\n    /**\n     * @return array\n     */\n    protected function variables()\n    {\n        $this->class(\"alert alert-{$this->style} alert-dismissable\");\n\n        return [\n            'title'      => $this->title,\n            'content'    => $this->content,\n            'icon'       => $this->icon,\n            'attributes' => $this->formatAttributes(),\n        ];\n    }\n\n    /**\n     * Render alter.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        return view($this->view, $this->variables())->render();\n    }\n}\n"
  },
  {
    "path": "src/Widgets/Box.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Widgets;\n\nuse Illuminate\\Contracts\\Support\\Renderable;\n\nclass Box extends Widget implements Renderable\n{\n    /**\n     * @var string\n     */\n    protected $view = 'admin::widgets.box';\n\n    /**\n     * @var string\n     */\n    protected $title = '';\n\n    /**\n     * @var string\n     */\n    protected $content = 'here is the box content.';\n\n    /**\n     * @var string\n     */\n    protected $footer = '';\n\n    /**\n     * @var array\n     */\n    protected $tools = [];\n\n    /**\n     * @var string\n     */\n    protected $script;\n\n    /**\n     * Box constructor.\n     *\n     * @param string $title\n     * @param string $content\n     */\n    public function __construct($title = '', $content = '', $footer = '')\n    {\n        if ($title) {\n            $this->title($title);\n        }\n\n        if ($content) {\n            $this->content($content);\n        }\n\n        if ($footer) {\n            $this->footer($footer);\n        }\n\n        $this->class('box');\n    }\n\n    /**\n     * Set box content.\n     *\n     * @param string|Renderable $content\n     *\n     * @return $this\n     */\n    public function content($content)\n    {\n        if ($content instanceof Renderable) {\n            $this->content = $content->render();\n        } else {\n            $this->content = (string) $content;\n        }\n\n        return $this;\n    }\n\n    /**\n     * Set box footer.\n     *\n     * @param string|Renderable $footer\n     *\n     * @return $this\n     */\n    public function footer($footer)\n    {\n        if ($footer instanceof Renderable) {\n            $this->footer = $footer->render();\n        } else {\n            $this->footer = (string) $footer;\n        }\n\n        return $this;\n    }\n\n    /**\n     * Set box title.\n     *\n     * @param string $title\n     *\n     * @return $this\n     */\n    public function title($title)\n    {\n        $this->title = $title;\n\n        return $this;\n    }\n\n    /**\n     * Set box as collapsable.\n     *\n     * @return $this\n     */\n    public function collapsable()\n    {\n        $this->tools[] =\n            '<button class=\"btn btn-box-tool\" data-widget=\"collapse\"><i class=\"fa fa-minus\"></i></button>';\n\n        return $this;\n    }\n\n    /**\n     *  Set box body scrollable.\n     *\n     * @param array $options\n     *\n     * @return $this\n     */\n    public function scrollable($options = [], $nodeSelector = '')\n    {\n        $this->id = uniqid('box-slim-scroll-');\n        $scrollOptions = json_encode($options);\n        $nodeSelector = $nodeSelector ?: '.box-body';\n\n        $this->script = <<<SCRIPT\n$(\"#{$this->id} {$nodeSelector}\").slimScroll({$scrollOptions});\nSCRIPT;\n\n        return $this;\n    }\n\n    /**\n     * Set box as removable.\n     *\n     * @return $this\n     */\n    public function removable()\n    {\n        $this->tools[] =\n            '<button class=\"btn btn-box-tool\" data-widget=\"remove\"><i class=\"fa fa-times\"></i></button>';\n\n        return $this;\n    }\n\n    /**\n     * Set box style.\n     *\n     * @param string $styles\n     *\n     * @return $this|Box\n     */\n    public function style($styles)\n    {\n        if (is_string($styles)) {\n            return $this->style([$styles]);\n        }\n\n        $styles = array_map(function ($style) {\n            return 'box-'.$style;\n        }, $styles);\n\n        $this->class = $this->class.' '.implode(' ', $styles);\n\n        return $this;\n    }\n\n    /**\n     * Add `box-solid` class to box.\n     *\n     * @return $this\n     */\n    public function solid()\n    {\n        return $this->style('solid');\n    }\n\n    /**\n     * Variables in view.\n     *\n     * @return array\n     */\n    protected function variables()\n    {\n        return [\n            'title'      => $this->title,\n            'content'    => $this->content,\n            'footer'     => $this->footer,\n            'tools'      => $this->tools,\n            'attributes' => $this->formatAttributes(),\n            'script'     => $this->script,\n        ];\n    }\n\n    /**\n     * Render box.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        return view($this->view, $this->variables())->render();\n    }\n}\n"
  },
  {
    "path": "src/Widgets/Callout.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Widgets;\n\nuse Illuminate\\Contracts\\Support\\Renderable;\n\nclass Callout extends Widget implements Renderable\n{\n    /**\n     * @var string\n     */\n    protected $view = 'admin::widgets.callout';\n\n    /**\n     * @var string\n     */\n    protected $title = '';\n\n    /**\n     * @var string\n     */\n    protected $content = '';\n\n    /**\n     * @var string\n     */\n    protected $style = 'danger';\n\n    /**\n     * Callout constructor.\n     *\n     * @param string $content\n     * @param string $title\n     * @param string $style\n     */\n    public function __construct($content, $title = '', $style = 'danger')\n    {\n        $this->content = (string) $content;\n\n        $this->title = $title;\n\n        $this->style($style);\n    }\n\n    /**\n     * Add style to Callout.\n     *\n     * @param string $style\n     *\n     * @return $this\n     */\n    public function style($style = 'info')\n    {\n        $this->style = $style;\n\n        return $this;\n    }\n\n    /**\n     * @return array\n     */\n    protected function variables()\n    {\n        $this->class(\"callout callout-{$this->style}\");\n\n        return [\n            'title'      => $this->title,\n            'content'    => $this->content,\n            'attributes' => $this->formatAttributes(),\n        ];\n    }\n\n    /**\n     * Render Callout.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        return view($this->view, $this->variables())->render();\n    }\n}\n"
  },
  {
    "path": "src/Widgets/Carousel.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Widgets;\n\nuse Illuminate\\Contracts\\Support\\Renderable;\n\nclass Carousel extends Widget implements Renderable\n{\n    /**\n     * @var string\n     */\n    protected $view = 'admin::widgets.carousel';\n\n    /**\n     * @var array\n     */\n    protected $items;\n\n    /**\n     * @var string\n     */\n    protected $title = 'Carousel';\n\n    /**\n     * Carousel constructor.\n     *\n     * @param array $items\n     */\n    public function __construct($items = [])\n    {\n        $this->items = $items;\n\n        $this->id('carousel-'.uniqid());\n        $this->class('carousel slide');\n        $this->offsetSet('data-ride', 'carousel');\n    }\n\n    /**\n     * Set title.\n     *\n     * @param string $title\n     */\n    public function title($title)\n    {\n        $this->title = $title;\n    }\n\n    /**\n     * Render Carousel.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        $variables = [\n            'items'      => $this->items,\n            'title'      => $this->title,\n            'attributes' => $this->formatAttributes(),\n            'id'         => $this->id,\n            'width'      => $this->width ?: 300,\n            'height'     => $this->height ?: 200,\n        ];\n\n        return view($this->view, $variables)->render();\n    }\n}\n"
  },
  {
    "path": "src/Widgets/Collapse.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Widgets;\n\nuse Illuminate\\Contracts\\Support\\Renderable;\n\nclass Collapse extends Widget implements Renderable\n{\n    /**\n     * @var string\n     */\n    protected $view = 'admin::widgets.collapse';\n\n    /**\n     * @var array\n     */\n    protected $items = [];\n\n    /**\n     * Collapse constructor.\n     */\n    public function __construct()\n    {\n        $this->id('accordion-'.uniqid());\n        $this->class('box-group');\n        $this->style('margin-bottom: 20px');\n    }\n\n    /**\n     * Add item.\n     *\n     * @param string $title\n     * @param string $content\n     *\n     * @return $this\n     */\n    public function add($title, $content)\n    {\n        $this->items[] = [\n            'title'   => $title,\n            'content' => $content,\n        ];\n\n        return $this;\n    }\n\n    protected function variables()\n    {\n        return [\n            'id'         => $this->id,\n            'items'      => $this->items,\n            'attributes' => $this->formatAttributes(),\n        ];\n    }\n\n    /**\n     * Render Collapse.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        return view($this->view, $this->variables())->render();\n    }\n}\n"
  },
  {
    "path": "src/Widgets/ContainsForms.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Widgets;\n\ntrait ContainsForms\n{\n    /**\n     * @var string\n     */\n    protected $activeName = 'active';\n\n    /**\n     * @param array $forms\n     * @param null  $active\n     *\n     * @return mixed\n     */\n    public static function forms($forms, $active = null)\n    {\n        $tab = new static();\n\n        return $tab->buildTabbedForms($forms, $active);\n    }\n\n    /**\n     * @param array $forms\n     * @param null  $active\n     *\n     * @return $this\n     */\n    protected function buildTabbedForms($forms, $active = null)\n    {\n        $active = $active ?: request($this->activeName);\n\n        if (!isset($forms[$active])) {\n            $active = key($forms);\n        }\n\n        foreach ($forms as $name => $class) {\n            if (!is_subclass_of($class, Form::class)) {\n                admin_error(\"Class [{$class}] must be a sub-class of [Encore\\Admin\\Widgets\\Form].\");\n                continue;\n            }\n\n            /** @var Form $form */\n            $form = app()->make($class);\n\n            if ($name == $active) {\n                $this->add($form->title(), $form->unbox(), true);\n            } else {\n                $this->addLink($form->title(), $this->getTabUrl($name));\n            }\n        }\n\n        return $this;\n    }\n\n    /**\n     * @param string $name\n     *\n     * @return string\n     */\n    protected function getTabUrl($name)\n    {\n        $query = [$this->activeName => $name];\n\n        return request()->fullUrlWithQuery($query);\n    }\n}\n"
  },
  {
    "path": "src/Widgets/Form.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Widgets;\n\nuse Closure;\nuse Encore\\Admin\\Facades\\Admin;\nuse Encore\\Admin\\Form as BaseForm;\nuse Encore\\Admin\\Form\\Field;\nuse Encore\\Admin\\Layout\\Content;\nuse Illuminate\\Contracts\\Support\\Arrayable;\nuse Illuminate\\Contracts\\Support\\Renderable;\nuse Illuminate\\Http\\Request;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\MessageBag;\nuse Illuminate\\Validation\\Validator;\n\n/**\n * Class Form.\n *\n * @method Field\\Text           text($name, $label = '')\n * @method Field\\Password       password($name, $label = '')\n * @method Field\\Checkbox       checkbox($name, $label = '')\n * @method Field\\CheckboxButton checkboxButton($name, $label = '')\n * @method Field\\CheckboxCard   checkboxCard($name, $label = '')\n * @method Field\\Radio          radio($name, $label = '')\n * @method Field\\RadioButton    radioButton($name, $label = '')\n * @method Field\\RadioCard      radioCard($name, $label = '')\n * @method Field\\Select         select($name, $label = '')\n * @method Field\\MultipleSelect multipleSelect($name, $label = '')\n * @method Field\\Textarea       textarea($name, $label = '')\n * @method Field\\Hidden         hidden($name, $label = '')\n * @method Field\\Id             id($name, $label = '')\n * @method Field\\Ip             ip($name, $label = '')\n * @method Field\\Url            url($name, $label = '')\n * @method Field\\Color          color($name, $label = '')\n * @method Field\\Email          email($name, $label = '')\n * @method Field\\Mobile         mobile($name, $label = '')\n * @method Field\\Slider         slider($name, $label = '')\n * @method Field\\File           file($name, $label = '')\n * @method Field\\Image          image($name, $label = '')\n * @method Field\\Date           date($name, $label = '')\n * @method Field\\Datetime       datetime($name, $label = '')\n * @method Field\\Time           time($name, $label = '')\n * @method Field\\Year           year($column, $label = '')\n * @method Field\\Month          month($column, $label = '')\n * @method Field\\DateRange      dateRange($start, $end, $label = '')\n * @method Field\\DateTimeRange  dateTimeRange($start, $end, $label = '')\n * @method Field\\TimeRange      timeRange($start, $end, $label = '')\n * @method Field\\Number         number($name, $label = '')\n * @method Field\\Currency       currency($name, $label = '')\n * @method Field\\SwitchField    switch($name, $label = '')\n * @method Field\\Display        display($name, $label = '')\n * @method Field\\Rate           rate($name, $label = '')\n * @method Field\\Divider        divider($title = '')\n * @method Field\\Decimal        decimal($column, $label = '')\n * @method Field\\Html           html($html)\n * @method Field\\Tags           tags($column, $label = '')\n * @method Field\\Icon           icon($column, $label = '')\n * @method Field\\Captcha        captcha($column, $label = '')\n * @method Field\\Listbox        listbox($column, $label = '')\n * @method Field\\Table          table($column, $label, $builder)\n * @method Field\\Timezone       timezone($column, $label = '')\n * @method Field\\KeyValue       keyValue($column, $label = '')\n * @method Field\\ListField      list($column, $label = '')\n * @method mixed                handle(Request $request)\n */\nclass Form implements Renderable\n{\n    use BaseForm\\Concerns\\HandleCascadeFields;\n\n    /**\n     * The title of form.\n     *\n     * @var string\n     */\n    public $title;\n\n    /**\n     * The description of form.\n     *\n     * @var string\n     */\n    public $description;\n\n    /**\n     * @var Field[]\n     */\n    protected $fields = [];\n\n    /**\n     * @var array\n     */\n    protected $data = [];\n\n    /**\n     * @var array\n     */\n    protected $attributes = [];\n\n    /**\n     * Available buttons.\n     *\n     * @var array\n     */\n    protected $buttons = ['reset', 'submit'];\n\n    /**\n     * Width for label and submit field.\n     *\n     * @var array\n     */\n    protected $width = [\n        'label' => 2,\n        'field' => 8,\n    ];\n\n    /**\n     * @var bool\n     */\n    public $inbox = true;\n\n    /**\n     * @var string\n     */\n    public $confirm = '';\n\n    /**\n     * @var Form\n     */\n    protected $form;\n\n    /**\n     * Form constructor.\n     *\n     * @param array $data\n     */\n    public function __construct($data = [])\n    {\n        $this->fill($data);\n\n        $this->initFormAttributes();\n    }\n\n    /**\n     * Get form title.\n     *\n     * @return mixed\n     */\n    public function title()\n    {\n        return $this->title;\n    }\n\n    /**\n     * Get form description.\n     *\n     * @return mixed\n     */\n    public function description()\n    {\n        return $this->description ?: ' ';\n    }\n\n    /**\n     * @return array\n     */\n    public function data()\n    {\n        return $this->data;\n    }\n\n    /**\n     * @return array\n     */\n    public function confirm($message)\n    {\n        $this->confirm = $message;\n\n        return $this;\n    }\n\n    /**\n     * Fill data to form fields.\n     *\n     * @param array $data\n     *\n     * @return $this\n     */\n    public function fill($data = [])\n    {\n        if ($data instanceof Arrayable) {\n            $data = $data->toArray();\n        }\n\n        if (!empty($data)) {\n            $this->data = $data;\n        }\n\n        return $this;\n    }\n\n    /**\n     * @return $this\n     */\n    public function sanitize()\n    {\n        foreach (['_form_', '_token'] as $key) {\n            request()->request->remove($key);\n        }\n\n        return $this;\n    }\n\n    /**\n     * Initialize the form attributes.\n     */\n    protected function initFormAttributes()\n    {\n        $this->attributes = [\n            'id'             => 'widget-form-'.uniqid(),\n            'method'         => 'POST',\n            'action'         => '',\n            'class'          => 'form-horizontal',\n            'accept-charset' => 'UTF-8',\n            'pjax-container' => true,\n        ];\n    }\n\n    /**\n     * Add form attributes.\n     *\n     * @param string|array $attr\n     * @param string       $value\n     *\n     * @return $this\n     */\n    public function attribute($attr, $value = '')\n    {\n        if (is_array($attr)) {\n            foreach ($attr as $key => $value) {\n                $this->attribute($key, $value);\n            }\n        } else {\n            $this->attributes[$attr] = $value;\n        }\n\n        return $this;\n    }\n\n    /**\n     * Format form attributes form array to html.\n     *\n     * @param array $attributes\n     *\n     * @return string\n     */\n    public function formatAttribute($attributes = [])\n    {\n        $attributes = $attributes ?: $this->attributes;\n\n        if ($this->hasFile()) {\n            $attributes['enctype'] = 'multipart/form-data';\n        }\n\n        $html = [];\n        foreach ($attributes as $key => $val) {\n            $html[] = \"$key=\\\"$val\\\"\";\n        }\n\n        return implode(' ', $html) ?: '';\n    }\n\n    /**\n     * Action uri of the form.\n     *\n     * @param string $action\n     *\n     * @return $this\n     */\n    public function action($action)\n    {\n        return $this->attribute('action', $action);\n    }\n\n    /**\n     * Method of the form.\n     *\n     * @param string $method\n     *\n     * @return $this\n     */\n    public function method($method = 'POST')\n    {\n        if (strtolower($method) == 'put') {\n            $this->hidden('_method')->default($method);\n\n            return $this;\n        }\n\n        return $this->attribute('method', strtoupper($method));\n    }\n\n    /**\n     * Disable Pjax.\n     *\n     * @return $this\n     */\n    public function disablePjax()\n    {\n        Arr::forget($this->attributes, 'pjax-container');\n\n        return $this;\n    }\n\n    /**\n     * Disable reset button.\n     *\n     * @return $this\n     */\n    public function disableReset()\n    {\n        array_delete($this->buttons, 'reset');\n\n        return $this;\n    }\n\n    /**\n     * Disable submit button.\n     *\n     * @return $this\n     */\n    public function disableSubmit()\n    {\n        array_delete($this->buttons, 'submit');\n\n        return $this;\n    }\n\n    /**\n     * Set field and label width in current form.\n     *\n     * @param int $fieldWidth\n     * @param int $labelWidth\n     *\n     * @return $this\n     */\n    public function setWidth($fieldWidth = 8, $labelWidth = 2)\n    {\n        collect($this->fields)->each(function ($field) use ($fieldWidth, $labelWidth) {\n            /* @var Field $field  */\n            $field->setWidth($fieldWidth, $labelWidth);\n        });\n\n        // set this width\n        $this->width = [\n            'label' => $labelWidth,\n            'field' => $fieldWidth,\n        ];\n\n        return $this;\n    }\n\n    /**\n     * Determine if the form has field type.\n     *\n     * @param string $name\n     *\n     * @return bool\n     */\n    public function hasField($name)\n    {\n        return isset(BaseForm::$availableFields[$name]);\n    }\n\n    /**\n     * Add a form field to form.\n     *\n     * @param Field $field\n     *\n     * @return $this\n     */\n    public function pushField(Field $field)\n    {\n        $field->setWidgetForm($this);\n\n        array_push($this->fields, $field);\n\n        return $this;\n    }\n\n    /**\n     * Get all fields of form.\n     *\n     * @return Field[]\n     */\n    public function fields()\n    {\n        return collect($this->fields);\n    }\n\n    /**\n     * Get variables for render form.\n     *\n     * @return array\n     */\n    protected function getVariables()\n    {\n        $this->fields()->each->fill($this->data());\n\n        return [\n            'fields'     => $this->fields,\n            'attributes' => $this->formatAttribute(),\n            'method'     => $this->attributes['method'],\n            'buttons'    => $this->buttons,\n            'width'      => $this->width,\n        ];\n    }\n\n    /**\n     * Determine if form fields has files.\n     *\n     * @return bool\n     */\n    public function hasFile()\n    {\n        foreach ($this->fields as $field) {\n            if ($field instanceof Field\\File) {\n                return true;\n            }\n        }\n\n        return false;\n    }\n\n    /**\n     * Validate this form fields.\n     *\n     * @param Request $request\n     *\n     * @return bool|MessageBag\n     */\n    public function validate(Request $request)\n    {\n        if (method_exists($this, 'form')) {\n            $this->form();\n        }\n\n        $failedValidators = [];\n\n        /** @var Field $field */\n        foreach ($this->fields() as $field) {\n            if (!$validator = $field->getValidator($request->all())) {\n                continue;\n            }\n\n            if (($validator instanceof Validator) && !$validator->passes()) {\n                $failedValidators[] = $validator;\n            }\n        }\n\n        $message = $this->mergeValidationMessages($failedValidators);\n\n        return $message->any() ? $message : false;\n    }\n\n    /**\n     * Merge validation messages from input validators.\n     *\n     * @param \\Illuminate\\Validation\\Validator[] $validators\n     *\n     * @return MessageBag\n     */\n    protected function mergeValidationMessages($validators)\n    {\n        $messageBag = new MessageBag();\n\n        foreach ($validators as $validator) {\n            $messageBag = $messageBag->merge($validator->messages());\n        }\n\n        return $messageBag;\n    }\n\n    /**\n     * Add a fieldset to form.\n     *\n     * @param string  $title\n     * @param Closure $setCallback\n     *\n     * @return Field\\Fieldset\n     */\n    public function fieldset(string $title, Closure $setCallback)\n    {\n        $fieldset = new Field\\Fieldset();\n\n        $this->html($fieldset->start($title))->plain();\n\n        $setCallback($this);\n\n        $this->html($fieldset->end())->plain();\n\n        return $fieldset;\n    }\n\n    /**\n     * @return $this\n     */\n    public function unbox()\n    {\n        $this->inbox = false;\n\n        return $this;\n    }\n\n    protected function addConfirmScript()\n    {\n        $id = $this->attributes['id'];\n\n        $trans = [\n            'cancel' => trans('admin.cancel'),\n            'submit' => trans('admin.submit'),\n        ];\n\n        $settings = [\n            'type'                => 'question',\n            'showCancelButton'    => true,\n            'confirmButtonText'   => $trans['submit'],\n            'cancelButtonText'    => $trans['cancel'],\n            'title'               => $this->confirm,\n            'text'                => '',\n        ];\n\n        $settings = trim(json_encode($settings, JSON_PRETTY_PRINT));\n\n        $script = <<<SCRIPT\n\n$('form#{$id}').off('submit').on('submit', function (e) {\n    e.preventDefault();\n    var form = this;\n    $.admin.swal($settings).then(function (result) {\n        if (result.value == true) {\n            form.submit();\n        }\n    });\n    return false;\n});\nSCRIPT;\n\n        Admin::script($script);\n    }\n\n    protected function addCascadeScript()\n    {\n        $id = $this->attributes['id'];\n\n        $script = <<<SCRIPT\n;(function () {\n    $('form#{$id}').submit(function (e) {\n        e.preventDefault();\n        $(this).find('div.cascade-group.hide :input').attr('disabled', true);\n    });\n})();\nSCRIPT;\n\n        Admin::script($script);\n    }\n\n    protected function prepareForm()\n    {\n        if (method_exists($this, 'form')) {\n            $this->form();\n        }\n\n        if (!empty($this->confirm)) {\n            $this->addConfirmScript();\n        }\n\n        $this->addCascadeScript();\n    }\n\n    protected function prepareHandle()\n    {\n        if (method_exists($this, 'handle')) {\n            $this->method('POST');\n            $this->action(admin_url('_handle_form_'));\n            $this->hidden('_form_')->default(get_called_class());\n        }\n    }\n\n    /**\n     * Render the form.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        $this->prepareForm();\n\n        $this->prepareHandle();\n\n        $form = view('admin::widgets.form', $this->getVariables())->render();\n\n        if (!($title = $this->title()) || !$this->inbox) {\n            return $form;\n        }\n\n        return (new Box($title, $form))->render();\n    }\n\n    /**\n     * Generate a Field object and add to form builder if Field exists.\n     *\n     * @param string $method\n     * @param array  $arguments\n     *\n     * @return Field|$this\n     */\n    public function __call($method, $arguments)\n    {\n        if (!$this->hasField($method)) {\n            return $this;\n        }\n\n        $class = BaseForm::$availableFields[$method];\n\n        $field = new $class(Arr::get($arguments, 0), array_slice($arguments, 1));\n\n        return tap($field, function ($field) {\n            $this->pushField($field);\n        });\n    }\n\n    /**\n     * @param Content $content\n     *\n     * @return Content\n     */\n    public function __invoke(Content $content)\n    {\n        return $content->title($this->title())\n            ->description($this->description())\n            ->body($this);\n    }\n}\n"
  },
  {
    "path": "src/Widgets/InfoBox.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Widgets;\n\nuse Illuminate\\Contracts\\Support\\Renderable;\n\nclass InfoBox extends Widget implements Renderable\n{\n    /**\n     * @var string\n     */\n    protected $view = 'admin::widgets.info-box';\n\n    /**\n     * @var array\n     */\n    protected $data = [];\n\n    /**\n     * InfoBox constructor.\n     *\n     * @param string $name\n     * @param string $icon\n     * @param string $color\n     * @param string $link\n     * @param string $info\n     */\n    public function __construct($name, $icon, $color, $link, $info)\n    {\n        $this->data = [\n            'name' => $name,\n            'icon' => $icon,\n            'link' => $link,\n            'info' => $info,\n        ];\n\n        $this->class(\"small-box bg-$color\");\n    }\n\n    /**\n     * @return string\n     */\n    public function render()\n    {\n        $variables = array_merge($this->data, ['attributes' => $this->formatAttributes()]);\n\n        return view($this->view, $variables)->render();\n    }\n}\n"
  },
  {
    "path": "src/Widgets/MultipleSteps.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Widgets;\n\nuse Illuminate\\Contracts\\Support\\Renderable;\n\nclass MultipleSteps implements Renderable\n{\n    /**\n     * @var int|string\n     */\n    protected $current;\n\n    /**\n     * @var array\n     */\n    protected $steps = [];\n\n    /**\n     * @var string\n     */\n    protected $stepName = 'step';\n\n    /**\n     * MultipleSteps constructor.\n     *\n     * @param array $steps\n     * @param null  $current\n     */\n    public function __construct($steps = [], $current = null)\n    {\n        $this->steps = $steps;\n\n        $this->current = $this->resolveCurrentStep($steps, $current);\n    }\n\n    /**\n     * @param array $steps\n     * @param null  $current\n     *\n     * @return static\n     */\n    public static function make($steps, $current = null): self\n    {\n        return new static($steps, $current);\n    }\n\n    /**\n     * @param array      $steps\n     * @param string|int $current\n     *\n     * @return string|int\n     */\n    protected function resolveCurrentStep($steps, $current)\n    {\n        $current = $current ?: request($this->stepName, 0);\n\n        if (!isset($steps[$current])) {\n            $current = key($steps);\n        }\n\n        return $current;\n    }\n\n    /**\n     * @return string|null\n     */\n    public function render()\n    {\n        $class = $this->steps[$this->current];\n\n        if (!is_subclass_of($class, StepForm::class)) {\n            admin_error(\"Class [{$class}] must be a sub-class of [Encore\\Admin\\Widgets\\StepForm].\");\n\n            return;\n        }\n\n        /** @var StepForm $step */\n        $step = new $class();\n\n        return $step\n            ->setSteps(array_keys($this->steps))\n            ->setCurrent($this->current)\n            ->render();\n    }\n}\n"
  },
  {
    "path": "src/Widgets/Navbar/Fullscreen.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Widgets\\Navbar;\n\nuse Encore\\Admin\\Admin;\nuse Illuminate\\Contracts\\Support\\Renderable;\n\n/**\n * Class FullScreen.\n *\n * @see  https://javascript.ruanyifeng.com/htmlapi/fullscreen.html\n */\nclass Fullscreen implements Renderable\n{\n    public function render()\n    {\n        return Admin::component('admin::components.fullscreen');\n    }\n}\n"
  },
  {
    "path": "src/Widgets/Navbar/RefreshButton.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Widgets\\Navbar;\n\nuse Encore\\Admin\\Admin;\nuse Illuminate\\Contracts\\Support\\Renderable;\n\nclass RefreshButton implements Renderable\n{\n    public function render()\n    {\n        return Admin::component('admin::components.refresh-btn');\n    }\n}\n"
  },
  {
    "path": "src/Widgets/Navbar.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Widgets;\n\nuse Encore\\Admin\\Widgets\\Navbar\\RefreshButton;\nuse Illuminate\\Contracts\\Support\\Htmlable;\nuse Illuminate\\Contracts\\Support\\Renderable;\n\nclass Navbar implements Renderable\n{\n    /**\n     * @var array\n     */\n    protected $elements = [];\n\n    /**\n     * Navbar constructor.\n     */\n    public function __construct()\n    {\n        $this->elements = [\n            'left'  => collect(),\n            'right' => collect(),\n        ];\n    }\n\n    /**\n     * @param $element\n     *\n     * @return $this\n     */\n    public function left($element)\n    {\n        $this->elements['left']->push($element);\n\n        return $this;\n    }\n\n    /**\n     * @param $element\n     *\n     * @return $this\n     */\n    public function right($element)\n    {\n        $this->elements['right']->push($element);\n\n        return $this;\n    }\n\n    /**\n     * @param $element\n     *\n     * @return Navbar\n     *\n     * @deprecated\n     */\n    public function add($element)\n    {\n        return $this->right($element);\n    }\n\n    /**\n     * @param string $part\n     *\n     * @return mixed\n     */\n    public function render($part = 'right')\n    {\n        if ($part == 'right') {\n            $this->right(new RefreshButton());\n        }\n\n        if (!isset($this->elements[$part]) || $this->elements[$part]->isEmpty()) {\n            return '';\n        }\n\n        return $this->elements[$part]->map(function ($element) {\n            if ($element instanceof Htmlable) {\n                return $element->toHtml();\n            }\n\n            if ($element instanceof Renderable) {\n                return $element->render();\n            }\n\n            return (string) $element;\n        })->implode('');\n    }\n}\n"
  },
  {
    "path": "src/Widgets/StepForm.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Widgets;\n\nclass StepForm extends Form\n{\n    /**\n     * @var int|string\n     */\n    protected $current;\n\n    /**\n     * @var array\n     */\n    protected $steps = [];\n\n    /**\n     * @var string\n     */\n    protected $url;\n\n    /**\n     * @var array\n     */\n    protected $buttons = [];\n\n    /**\n     * @param array $data\n     *\n     * @return \\Illuminate\\Http\\RedirectResponse|\\Illuminate\\Routing\\Redirector\n     */\n    protected function next($data = [])\n    {\n        $this->remember($data);\n\n        return $this->redirectToNextStep();\n    }\n\n    protected function prev()\n    {\n        return back()->withInput();\n    }\n\n    /**\n     * @param array $data\n     */\n    protected function remember($data)\n    {\n        session()->put(\"steps.{$this->current}\", $data);\n    }\n\n    /**\n     * @return \\Illuminate\\Http\\RedirectResponse|\\Illuminate\\Routing\\Redirector\n     */\n    protected function redirectToNextStep()\n    {\n        $index = array_search($this->current, $this->steps);\n\n        $step = $this->steps[$index + 1];\n\n        $nextUrl = $this->url.'?'.http_build_query(compact('step'));\n\n        return redirect($nextUrl);\n    }\n\n    /**\n     * Get all data from steps.\n     *\n     * @return array\n     */\n    protected function all()\n    {\n        $prev = session()->get('steps', []);\n\n        return array_merge($prev, [$this->current => request()->all()]);\n    }\n\n    /**\n     * Clear all data from steps.\n     */\n    protected function clear()\n    {\n        session()->remove('steps');\n    }\n\n    /**\n     * @param array $steps\n     *\n     * @return $this\n     */\n    public function setSteps($steps)\n    {\n        $this->steps = $steps;\n\n        return $this;\n    }\n\n    /**\n     * @param string|int $current\n     *\n     * @return $this\n     */\n    public function setCurrent($current)\n    {\n        $this->current = $current;\n\n        return $this;\n    }\n\n    /**\n     * @param string $url\n     *\n     * @return $this\n     */\n    public function setUrl($url)\n    {\n        $this->url = $url;\n\n        return $this;\n    }\n\n    protected function prepareForm()\n    {\n        parent::prepareForm();\n\n        $url = request()->url();\n\n        $this->hidden('_url')->default($url);\n        $this->hidden('_current')->default($this->current);\n        $this->hidden('_steps')->default(implode(',', $this->steps));\n\n        $this->divider();\n\n        $this->addFooter();\n    }\n\n    protected function addFooter()\n    {\n        $footer = '';\n\n        $index = array_search($this->current, $this->steps);\n\n        $trans = [\n            'prev'   => __('admin.prev'),\n            'next'   => __('admin.next'),\n            'submit' => __('admin.submit'),\n        ];\n\n        if ($index !== 0) {\n            $step = $this->steps[$index - 1];\n            $prevUrl = request()->fullUrlWithQuery(compact('step'));\n            $footer .= \"<a href=\\\"{$prevUrl}\\\" class=\\\"btn btn-warning pull-left\\\">{$trans['prev']}</a>\";\n        }\n\n        if ($index !== count($this->steps) - 1) {\n            $footer .= \"<button class=\\\"btn btn-info pull-right\\\">{$trans['next']}</button>\";\n        }\n\n        if ($index === count($this->steps) - 1) {\n            $footer .= \"<button class=\\\"btn btn-info pull-right\\\">{$trans['submit']}</button>\";\n        }\n\n        $this->html($footer);\n    }\n\n    /**\n     * @return $this\n     */\n    public function sanitize()\n    {\n        $this->setUrl(request('_url'))\n            ->setCurrent(request('_current'))\n            ->setSteps(explode(',', request('_steps')));\n\n        foreach (['_form_', '_token', '_url', '_current', '_steps'] as $key) {\n            request()->request->remove($key);\n        }\n\n        return $this;\n    }\n\n    /**\n     * @return mixed\n     */\n    public function data()\n    {\n        return session()->get('steps.'.$this->current, []);\n    }\n}\n"
  },
  {
    "path": "src/Widgets/Tab.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Widgets;\n\nuse Encore\\Admin\\Facades\\Admin;\nuse Illuminate\\Contracts\\Support\\Renderable;\n\nclass Tab extends Widget implements Renderable\n{\n    use ContainsForms;\n\n    const TYPE_CONTENT = 1;\n    const TYPE_LINK = 2;\n\n    /**\n     * @var string\n     */\n    protected $view = 'admin::widgets.tab';\n\n    /**\n     * @var array\n     */\n    protected $data = [\n        'id'       => '',\n        'title'    => '',\n        'tabs'     => [],\n        'dropDown' => [],\n        'active'   => 0,\n    ];\n\n    public function __construct()\n    {\n        $this->class('nav-tabs-custom');\n    }\n\n    /**\n     * Add a tab and its contents.\n     *\n     * @param string            $title\n     * @param string|Renderable $content\n     * @param bool              $active\n     * @param string|null       $id\n     *\n     * @return $this\n     */\n    public function add($title, $content, $active = false, $id = null)\n    {\n        $this->data['tabs'][] = [\n            'id'      => $id ?: mt_rand(),\n            'title'   => $title,\n            'content' => $content,\n            'type'    => static::TYPE_CONTENT,\n        ];\n\n        if ($active) {\n            $this->data['active'] = count($this->data['tabs']) - 1;\n        }\n\n        return $this;\n    }\n\n    /**\n     * Add a link on tab.\n     *\n     * @param string $title\n     * @param string $href\n     * @param bool   $active\n     *\n     * @return $this\n     */\n    public function addLink($title, $href, $active = false)\n    {\n        $this->data['tabs'][] = [\n            'id'      => mt_rand(),\n            'title'   => $title,\n            'href'    => $href,\n            'type'    => static::TYPE_LINK,\n        ];\n\n        if ($active) {\n            $this->data['active'] = count($this->data['tabs']) - 1;\n        }\n\n        return $this;\n    }\n\n    /**\n     * Set title.\n     *\n     * @param string $title\n     */\n    public function title($title = '')\n    {\n        $this->data['title'] = $title;\n    }\n\n    /**\n     * Set drop-down items.\n     *\n     * @param array $links\n     *\n     * @return $this\n     */\n    public function dropDown(array $links)\n    {\n        if (is_array($links[0])) {\n            foreach ($links as $link) {\n                call_user_func([$this, 'dropDown'], $link);\n            }\n\n            return $this;\n        }\n\n        $this->data['dropDown'][] = [\n            'name' => $links[0],\n            'href' => $links[1],\n        ];\n\n        return $this;\n    }\n\n    /**\n     * Render Tab.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        $data = array_merge(\n            $this->data,\n            ['attributes' => $this->formatAttributes()]\n        );\n\n        $this->setupScript();\n\n        return view($this->view, $data)->render();\n    }\n\n    /**\n     * Setup script.\n     */\n    protected function setupScript()\n    {\n        $script = <<<'SCRIPT'\nvar hash = document.location.hash;\nif (hash) {\n    $('.nav-tabs a[href=\"' + hash + '\"]').tab('show');\n}\n\n// Change hash for page-reload\n$('.nav-tabs a').on('shown.bs.tab', function (e) {\n    history.pushState(null,null, e.target.hash);\n});\nSCRIPT;\n        Admin::script($script);\n    }\n}\n"
  },
  {
    "path": "src/Widgets/Table.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Widgets;\n\nuse Illuminate\\Contracts\\Support\\Renderable;\nuse Illuminate\\Support\\Arr;\n\nclass Table extends Widget implements Renderable\n{\n    /**\n     * @var string\n     */\n    protected $view = 'admin::widgets.table';\n\n    /**\n     * @var array\n     */\n    protected $headers = [];\n\n    /**\n     * @var array\n     */\n    protected $rows = [];\n\n    /**\n     * @var array\n     */\n    protected $style = [];\n\n    /**\n     * Table constructor.\n     *\n     * @param array $headers\n     * @param array $rows\n     * @param array $style\n     */\n    public function __construct($headers = [], $rows = [], $style = [])\n    {\n        $this->setHeaders($headers);\n        $this->setRows($rows);\n        $this->setStyle($style);\n\n        $this->class('table '.implode(' ', $this->style));\n    }\n\n    /**\n     * Set table headers.\n     *\n     * @param array $headers\n     *\n     * @return $this\n     */\n    public function setHeaders($headers = [])\n    {\n        $this->headers = $headers;\n\n        return $this;\n    }\n\n    /**\n     * Set table rows.\n     *\n     * @param array $rows\n     *\n     * @return $this\n     */\n    public function setRows($rows = [])\n    {\n        if (Arr::isAssoc($rows)) {\n            foreach ($rows as $key => $item) {\n                $this->rows[] = [$key, $item];\n            }\n\n            return $this;\n        }\n\n        $this->rows = $rows;\n\n        return $this;\n    }\n\n    /**\n     * Set table style.\n     *\n     * @param array $style\n     *\n     * @return $this\n     */\n    public function setStyle($style = [])\n    {\n        $this->style = $style;\n\n        return $this;\n    }\n\n    /**\n     * Render the table.\n     *\n     * @return string\n     */\n    public function render()\n    {\n        $vars = [\n            'headers'    => $this->headers,\n            'rows'       => $this->rows,\n            'style'      => $this->style,\n            'attributes' => $this->formatAttributes(),\n        ];\n\n        return view($this->view, $vars)->render();\n    }\n}\n"
  },
  {
    "path": "src/Widgets/Widget.php",
    "content": "<?php\n\nnamespace Encore\\Admin\\Widgets;\n\nuse Illuminate\\Support\\Fluent;\n\nabstract class Widget extends Fluent\n{\n    /**\n     * @var string\n     */\n    protected $view;\n\n    /**\n     * @return mixed\n     */\n    abstract public function render();\n\n    /**\n     * Set view of widget.\n     *\n     * @param string $view\n     */\n    public function view($view)\n    {\n        $this->view = $view;\n    }\n\n    /**\n     * Build an HTML attribute string from an array.\n     *\n     * @return string\n     */\n    public function formatAttributes()\n    {\n        $html = [];\n        foreach ((array) $this->getAttributes() as $key => $value) {\n            $element = $this->attributeElement($key, $value);\n            if (!is_null($element)) {\n                $html[] = $element;\n            }\n        }\n\n        return count($html) > 0 ? ' '.implode(' ', $html) : '';\n    }\n\n    /**\n     * Build a single attribute element.\n     *\n     * @param string $key\n     * @param string $value\n     *\n     * @return string\n     */\n    protected function attributeElement($key, $value)\n    {\n        if (is_numeric($key)) {\n            $key = $value;\n        }\n        if (!is_null($value)) {\n            return $key.'=\"'.htmlentities($value, ENT_QUOTES, 'UTF-8').'\"';\n        }\n    }\n\n    /**\n     * @return mixed\n     */\n    public function __toString()\n    {\n        return $this->render();\n    }\n}\n"
  },
  {
    "path": "src/helpers.php",
    "content": "<?php\n\nuse Illuminate\\Support\\MessageBag;\n\nif (!function_exists('admin_path')) {\n\n    /**\n     * Get admin path.\n     *\n     * @param string $path\n     *\n     * @return string\n     */\n    function admin_path($path = '')\n    {\n        return ucfirst(config('admin.directory')).($path ? DIRECTORY_SEPARATOR.$path : $path);\n    }\n}\n\nif (!function_exists('admin_url')) {\n    /**\n     * Get admin url.\n     *\n     * @param string $path\n     * @param mixed  $parameters\n     * @param bool   $secure\n     *\n     * @return string\n     */\n    function admin_url($path = '', $parameters = [], $secure = null)\n    {\n        if (\\Illuminate\\Support\\Facades\\URL::isValidUrl($path)) {\n            return $path;\n        }\n\n        $secure = $secure ?: (config('admin.https') || config('admin.secure'));\n\n        return url(admin_base_path($path), $parameters, $secure);\n    }\n}\n\nif (!function_exists('admin_base_path')) {\n    /**\n     * Get admin url.\n     *\n     * @param string $path\n     *\n     * @return string\n     */\n    function admin_base_path($path = '')\n    {\n        $prefix = '/'.trim(config('admin.route.prefix'), '/');\n\n        $prefix = ($prefix == '/') ? '' : $prefix;\n\n        $path = trim($path, '/');\n\n        if (is_null($path) || strlen($path) == 0) {\n            return $prefix ?: '/';\n        }\n\n        return $prefix.'/'.$path;\n    }\n}\n\nif (!function_exists('admin_toastr')) {\n\n    /**\n     * Flash a toastr message bag to session.\n     *\n     * @param string $message\n     * @param string $type\n     * @param array  $options\n     */\n    function admin_toastr($message = '', $type = 'success', $options = [])\n    {\n        $toastr = new MessageBag(get_defined_vars());\n\n        session()->flash('toastr', $toastr);\n    }\n}\n\nif (!function_exists('admin_success')) {\n\n    /**\n     * Flash a success message bag to session.\n     *\n     * @param string $title\n     * @param string $message\n     */\n    function admin_success($title, $message = '')\n    {\n        admin_info($title, $message, 'success');\n    }\n}\n\nif (!function_exists('admin_error')) {\n\n    /**\n     * Flash a error message bag to session.\n     *\n     * @param string $title\n     * @param string $message\n     */\n    function admin_error($title, $message = '')\n    {\n        admin_info($title, $message, 'error');\n    }\n}\n\nif (!function_exists('admin_warning')) {\n\n    /**\n     * Flash a warning message bag to session.\n     *\n     * @param string $title\n     * @param string $message\n     */\n    function admin_warning($title, $message = '')\n    {\n        admin_info($title, $message, 'warning');\n    }\n}\n\nif (!function_exists('admin_info')) {\n\n    /**\n     * Flash a message bag to session.\n     *\n     * @param string $title\n     * @param string $message\n     * @param string $type\n     */\n    function admin_info($title, $message = '', $type = 'info')\n    {\n        $message = new MessageBag(get_defined_vars());\n\n        session()->flash($type, $message);\n    }\n}\n\nif (!function_exists('admin_asset')) {\n\n    /**\n     * @param $path\n     *\n     * @return string\n     */\n    function admin_asset($path)\n    {\n        return (config('admin.https') || config('admin.secure')) ? secure_asset($path) : asset($path);\n    }\n}\n\nif (!function_exists('admin_trans')) {\n\n    /**\n     * Translate the given message.\n     *\n     * @param string $key\n     * @param array  $replace\n     * @param string $locale\n     *\n     * @return \\Illuminate\\Contracts\\Translation\\Translator|string|array|null\n     */\n    function admin_trans($key = null, $replace = [], $locale = null)\n    {\n        $line = __($key, $replace, $locale);\n\n        if (!is_string($line)) {\n            return $key;\n        }\n\n        return $line;\n    }\n}\n\nif (!function_exists('array_delete')) {\n\n    /**\n     * Delete from array by value.\n     *\n     * @param array $array\n     * @param mixed $value\n     */\n    function array_delete(&$array, $value)\n    {\n        $value = \\Illuminate\\Support\\Arr::wrap($value);\n\n        foreach ($array as $index => $item) {\n            if (in_array($item, $value)) {\n                unset($array[$index]);\n            }\n        }\n    }\n}\n\nif (!function_exists('class_uses_deep')) {\n\n    /**\n     * To get ALL traits including those used by parent classes and other traits.\n     *\n     * @param $class\n     * @param bool $autoload\n     *\n     * @return array\n     */\n    function class_uses_deep($class, $autoload = true)\n    {\n        $traits = [];\n\n        do {\n            $traits = array_merge(class_uses($class, $autoload), $traits);\n        } while ($class = get_parent_class($class));\n\n        foreach ($traits as $trait => $same) {\n            $traits = array_merge(class_uses($trait, $autoload), $traits);\n        }\n\n        return array_unique($traits);\n    }\n}\n\nif (!function_exists('admin_dump')) {\n\n    /**\n     * @param $var\n     *\n     * @return string\n     */\n    function admin_dump($var)\n    {\n        ob_start();\n\n        dump(...func_get_args());\n\n        $contents = ob_get_contents();\n\n        ob_end_clean();\n\n        return $contents;\n    }\n}\n\nif (!function_exists('file_size')) {\n\n    /**\n     * Convert file size to a human readable format like `100mb`.\n     *\n     * @param int $bytes\n     *\n     * @return string\n     *\n     * @see https://stackoverflow.com/a/5501447/9443583\n     */\n    function file_size($bytes)\n    {\n        if ($bytes >= 1073741824) {\n            $bytes = number_format($bytes / 1073741824, 2).' GB';\n        } elseif ($bytes >= 1048576) {\n            $bytes = number_format($bytes / 1048576, 2).' MB';\n        } elseif ($bytes >= 1024) {\n            $bytes = number_format($bytes / 1024, 2).' KB';\n        } elseif ($bytes > 1) {\n            $bytes = $bytes.' bytes';\n        } elseif ($bytes == 1) {\n            $bytes = $bytes.' byte';\n        } else {\n            $bytes = '0 bytes';\n        }\n\n        return $bytes;\n    }\n}\n\nif (!function_exists('prepare_options')) {\n\n    /**\n     * @param array $options\n     *\n     * @return array\n     */\n    function prepare_options(array $options)\n    {\n        $original = [];\n        $toReplace = [];\n\n        foreach ($options as $key => &$value) {\n            if (is_array($value)) {\n                $subArray = prepare_options($value);\n                $value = $subArray['options'];\n                $original = array_merge($original, $subArray['original']);\n                $toReplace = array_merge($toReplace, $subArray['toReplace']);\n            } elseif (strpos($value, 'function(') === 0) {\n                $original[] = $value;\n                $value = \"%{$key}%\";\n                $toReplace[] = \"\\\"{$value}\\\"\";\n            }\n        }\n\n        return compact('original', 'toReplace', 'options');\n    }\n}\n\nif (!function_exists('json_encode_options')) {\n\n    /**\n     * @param array $options\n     *\n     * @return string\n     *\n     * @see http://web.archive.org/web/20080828165256/http://solutoire.com/2008/06/12/sending-javascript-functions-over-json/\n     */\n    function json_encode_options(array $options)\n    {\n        $data = prepare_options($options);\n\n        $json = json_encode($data['options']);\n\n        return str_replace($data['toReplace'], $data['original'], $json);\n    }\n}\n\nif (!function_exists('admin_get_route')) {\n    function admin_get_route(string $name): string\n    {\n        return config('admin.route.prefix').'.'.$name;\n    }\n}\n"
  },
  {
    "path": "tests/AuthTest.php",
    "content": "<?php\n\nclass AuthTest extends TestCase\n{\n    public function testLoginPage()\n    {\n        $this->visit('admin/auth/login')\n            ->see('login');\n    }\n\n    public function testVisitWithoutLogin()\n    {\n        $this->visit('admin')\n            ->dontSeeIsAuthenticated('admin')\n            ->seePageIs('admin/auth/login');\n    }\n\n    public function testLogin()\n    {\n        $credentials = ['username' => 'admin', 'password' => 'admin'];\n\n        $this->visit('admin/auth/login')\n            ->see('login')\n            ->submitForm('Login', $credentials)\n            ->see('dashboard')\n            ->seeCredentials($credentials, 'admin')\n            ->seeIsAuthenticated('admin')\n            ->seePageIs('admin')\n            ->see('Dashboard')\n            ->see('Description...')\n\n            ->see('Environment')\n            ->see('PHP version')\n            ->see('Laravel version')\n\n            ->see('Available extensions')\n            ->seeLink('laravel-admin-ext/helpers', 'https://github.com/laravel-admin-extensions/helpers')\n            ->seeLink('laravel-admin-ext/backup', 'https://github.com/laravel-admin-extensions/backup')\n            ->seeLink('laravel-admin-ext/media-manager', 'https://github.com/laravel-admin-extensions/media-manager')\n\n            ->see('Dependencies')\n            ->see('php')\n//            ->see('>=7.0.0')\n            ->see('laravel/framework');\n\n        $this\n            ->see('<span>Admin</span>')\n            ->see('<span>Users</span>')\n            ->see('<span>Roles</span>')\n            ->see('<span>Permission</span>')\n            ->see('<span>Operation log</span>')\n            ->see('<span>Menu</span>');\n    }\n\n    public function testLogout()\n    {\n        $this->visit('admin/auth/logout')\n            ->seePageIs('admin/auth/login')\n            ->dontSeeIsAuthenticated('admin');\n    }\n}\n"
  },
  {
    "path": "tests/FileUploadTest.php",
    "content": "<?php\n\nuse Encore\\Admin\\Auth\\Database\\Administrator;\nuse Illuminate\\Support\\Facades\\File;\nuse Tests\\Models\\File as FileModel;\n\nclass FileUploadTest extends TestCase\n{\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->be(Administrator::first(), 'admin');\n    }\n\n    public function testFileUploadPage()\n    {\n        $this->visit('admin/files/create')\n            ->see('Files')\n            ->seeInElement('h3[class=box-title]', 'Create')\n            ->seeElement('input[name=file1]')\n            ->seeElement('input[name=file2]')\n            ->seeElement('input[name=file3]')\n            ->seeElement('input[name=file4]')\n            ->seeElement('input[name=file5]')\n            ->seeElement('input[name=file6]')\n//            ->seeInElement('a[href=\"/admin/files\"]', 'List')\n            ->seeInElement('button[type=reset]', 'Reset')\n            ->seeInElement('button[type=submit]', 'Submit');\n    }\n\n    protected function uploadFiles()\n    {\n        return $this->visit('admin/files/create')\n            ->attach(__DIR__.'/AuthTest.php', 'file1')\n            ->attach(__DIR__.'/InstallTest.php', 'file2')\n            ->attach(__DIR__.'/IndexTest.php', 'file3')\n            ->attach(__DIR__.'/LaravelTest.php', 'file4')\n            ->attach(__DIR__.'/routes.php', 'file5')\n            ->attach(__DIR__.'/migrations/2016_11_22_093148_create_test_tables.php', 'file6')\n            ->press('Submit');\n    }\n\n    public function testUploadFile()\n    {\n        File::cleanDirectory(public_path('uploads/files'));\n\n        $this->uploadFiles()\n            ->seePageIs('admin/files');\n\n        $this->assertEquals(FileModel::count(), 1);\n\n        $where = [\n            'file1' => 'files/AuthTest.php',\n            'file2' => 'files/InstallTest.php',\n            'file3' => 'files/IndexTest.php',\n            'file4' => 'files/LaravelTest.php',\n            'file5' => 'files/routes.php',\n            'file6' => 'files/2016_11_22_093148_create_test_tables.php',\n        ];\n\n        $this->seeInDatabase('test_files', $where);\n\n        $files = FileModel::first()->toArray();\n\n        foreach (range(1, 6) as $index) {\n            $this->assertFileExists(public_path('uploads/'.$files['file'.$index]));\n        }\n\n        File::cleanDirectory(public_path('uploads/files'));\n    }\n\n    public function testUpdateFile()\n    {\n        File::cleanDirectory(public_path('uploads/files'));\n\n        $this->uploadFiles();\n\n        $old = FileModel::first();\n\n        $this->visit('admin/files/1/edit')\n            ->see('ID')\n            ->see('Created At')\n            ->see('Updated At')\n            ->seeElement('input[name=file1]')\n            ->seeElement('input[name=file2]')\n            ->seeElement('input[name=file3]')\n            ->seeElement('input[name=file4]')\n            ->seeElement('input[name=file5]')\n            ->seeElement('input[name=file6]')\n//            ->seeInElement('a[href=\"/admin/files\"]', 'List')\n            ->seeInElement('button[type=reset]', 'Reset')\n            ->seeInElement('button[type=submit]', 'Submit');\n\n        $this->attach(__DIR__.'/RolesTest.php', 'file3')\n            ->attach(__DIR__.'/MenuTest.php', 'file4')\n            ->attach(__DIR__.'/TestCase.php', 'file5')\n            ->press('Submit');\n\n        $new = FileModel::first();\n\n        $this->assertEquals($old->id, $new->id);\n        $this->assertEquals($old->file1, $new->file1);\n        $this->assertEquals($old->file2, $new->file2);\n        $this->assertEquals($old->file6, $new->file6);\n\n        $this->assertNotEquals($old->file3, $new->file3);\n        $this->assertNotEquals($old->file4, $new->file4);\n        $this->assertNotEquals($old->file5, $new->file5);\n\n        File::cleanDirectory(public_path('uploads/files'));\n    }\n\n    public function testDeleteFiles()\n    {\n        File::cleanDirectory(public_path('uploads/files'));\n\n        $this->uploadFiles();\n\n        $this->visit('admin/files')\n            ->seeInElement('td', 1);\n\n        $files = FileModel::first()->toArray();\n\n        $this->delete('admin/files/1')\n            ->dontSeeInDatabase('test_files', ['id' => 1]);\n\n        foreach (range(1, 6) as $index) {\n            $this->assertFileDoesNotExist(public_path('uploads/'.$files['file'.$index]));\n        }\n\n        $this->visit('admin/files')\n            ->seeInElement('td', 'svg');\n    }\n\n    public function testBatchDelete()\n    {\n        File::cleanDirectory(public_path('uploads/files'));\n\n        $this->uploadFiles();\n        $this->uploadFiles();\n        $this->uploadFiles();\n\n        $this->visit('admin/files')\n            ->seeInElement('td', 1)\n            ->seeInElement('td', 2)\n            ->seeInElement('td', 3);\n\n        $fi = new FilesystemIterator(public_path('uploads/files'), FilesystemIterator::SKIP_DOTS);\n\n        $this->assertEquals(iterator_count($fi), 18);\n\n        $this->assertEquals(FileModel::count(), 3);\n\n        $this->delete('admin/files/1,2,3');\n\n        $this->assertEquals(FileModel::count(), 0);\n\n        $this->visit('admin/files')\n            ->seeInElement('td', 'svg');\n\n        $this->assertEquals(iterator_count($fi), 0);\n    }\n}\n"
  },
  {
    "path": "tests/ImageUploadTest.php",
    "content": "<?php\n\nuse Encore\\Admin\\Auth\\Database\\Administrator;\nuse Illuminate\\Support\\Facades\\File;\nuse Tests\\Models\\Image;\nuse Tests\\Models\\MultipleImage;\n\nclass ImageUploadTest extends TestCase\n{\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->be(Administrator::first(), 'admin');\n    }\n\n    public function testDisableFilter()\n    {\n        $this->visit('admin/images')\n            ->dontSeeElement('input[name=id]');\n    }\n\n    public function testImageUploadPage()\n    {\n        $this->visit('admin/images/create')\n            ->see('Images')\n            ->seeInElement('h3[class=box-title]', 'Create')\n            ->seeElement('input[name=image1]')\n            ->seeElement('input[name=image2]')\n            ->seeElement('input[name=image3]')\n            ->seeElement('input[name=image4]')\n            ->seeElement('input[name=image5]')\n            ->seeElement('input[name=image6]')\n            ->seeInElement('button[type=reset]', 'Reset')\n            ->seeInElement('button[type=submit]', 'Submit');\n    }\n\n    protected function uploadImages()\n    {\n        return $this->visit('admin/images/create')\n            ->attach(__DIR__.'/assets/test.jpg', 'image1')\n            ->attach(__DIR__.'/assets/test.jpg', 'image2')\n            ->attach(__DIR__.'/assets/test.jpg', 'image3')\n            ->attach(__DIR__.'/assets/test.jpg', 'image4')\n            ->attach(__DIR__.'/assets/test.jpg', 'image5')\n            ->attach(__DIR__.'/assets/test.jpg', 'image6')\n            ->press('Submit');\n    }\n\n    public function testUploadImage()\n    {\n        File::cleanDirectory(public_path('uploads/images'));\n\n        $this->uploadImages()\n            ->seePageIs('admin/images');\n\n        $this->assertEquals(Image::count(), 1);\n\n        $this->seeInDatabase('test_images', ['image4' => 'images/renamed.jpeg']);\n\n        $images = Image::first()->toArray();\n\n        foreach (range(1, 6) as $index) {\n            $this->assertFileExists(public_path('uploads/'.$images['image'.$index]));\n        }\n\n        $this->assertFileExists(public_path('uploads/images/asdasdasdasdasd.jpeg'));\n\n        File::cleanDirectory(public_path('uploads/images'));\n    }\n\n    public function testRemoveImage()\n    {\n        File::cleanDirectory(public_path('uploads/images'));\n\n        $this->uploadImages();\n\n        $this->assertEquals($this->fileCountInImageDir(), 6);\n    }\n\n    public function testUpdateImage()\n    {\n        File::cleanDirectory(public_path('uploads/images'));\n\n        $this->uploadImages();\n\n        $old = Image::first();\n\n        $this->visit('admin/images/1/edit')\n            ->see('ID')\n            ->see('Created At')\n            ->see('Updated At')\n            ->seeElement('input[name=image1]')\n            ->seeElement('input[name=image2]')\n            ->seeElement('input[name=image3]')\n            ->seeElement('input[name=image4]')\n            ->seeElement('input[name=image5]')\n            ->seeElement('input[name=image6]')\n            ->seeInElement('button[type=reset]', 'Reset')\n            ->seeInElement('button[type=submit]', 'Submit');\n\n        $this->attach(__DIR__.'/assets/test.jpg', 'image3')\n            ->attach(__DIR__.'/assets/test.jpg', 'image4')\n            ->attach(__DIR__.'/assets/test.jpg', 'image5')\n            ->press('Submit');\n\n        $new = Image::first();\n\n        $this->assertEquals($old->id, $new->id);\n        $this->assertEquals($old->image1, $new->image1);\n        $this->assertEquals($old->image2, $new->image2);\n        $this->assertEquals($old->image6, $new->image6);\n\n        $this->assertNotEquals($old->image3, $new->image3);\n        $this->assertNotEquals($old->image4, $new->image4);\n        $this->assertNotEquals($old->image5, $new->image5);\n\n        File::cleanDirectory(public_path('uploads/images'));\n    }\n\n    public function testDeleteImages()\n    {\n        File::cleanDirectory(public_path('uploads/images'));\n\n        $this->uploadImages();\n\n        $this->visit('admin/images')\n            ->seeInElement('td', 1);\n\n        $images = Image::first()->toArray();\n\n        $this->delete('admin/images/1')\n            ->dontSeeInDatabase('test_images', ['id' => 1]);\n\n        foreach (range(1, 6) as $index) {\n            $this->assertFileDoesNotExist(public_path('uploads/'.$images['image'.$index]));\n        }\n\n        $this->visit('admin/images')\n            ->seeInElement('td', 'svg');\n    }\n\n    public function testBatchDelete()\n    {\n        File::cleanDirectory(public_path('uploads/images'));\n\n        $this->uploadImages();\n        $this->uploadImages();\n        $this->uploadImages();\n\n        $this->visit('admin/images')\n            ->seeInElement('td', 1)\n            ->seeInElement('td', 2)\n            ->seeInElement('td', 3);\n\n        $this->assertEquals($this->fileCountInImageDir(), 18);\n\n        $this->assertEquals(Image::count(), 3);\n\n        $this->delete('admin/images/1,2,3');\n\n        $this->assertEquals(Image::count(), 0);\n\n        $this->visit('admin/images')\n            ->seeInElement('td', 'svg');\n\n        $this->assertEquals($this->fileCountInImageDir(), 0);\n    }\n\n    public function testUploadMultipleImage()\n    {\n        File::cleanDirectory(public_path('uploads/images'));\n\n        $this->visit('admin/multiple-images/create')\n            ->seeElement('input[type=file][name=\"pictures[]\"][multiple]');\n\n        $path = __DIR__.'/assets/test.jpg';\n\n        $file = new \\Illuminate\\Http\\UploadedFile($path, 'test.jpg', 'image/jpeg', null, true);\n\n        $size = rand(10, 20);\n        $files = ['pictures' => array_pad([], $size, $file)];\n\n        $this->call(\n            'POST', // $method\n            '/admin/multiple-images', // $action\n            [], // $parameters\n            [],\n            $files\n        );\n\n        $this->assertResponseStatus(302);\n        $this->assertRedirectedTo('/admin/multiple-images');\n\n        $this->assertEquals($this->fileCountInImageDir(), $size);\n\n        $pictures = MultipleImage::first()->pictures;\n\n        $this->assertCount($size, $pictures);\n\n        foreach ($pictures as $picture) {\n            $this->assertFileExists(public_path('uploads/'.$picture));\n        }\n    }\n\n    public function testRemoveMultipleFiles()\n    {\n        File::cleanDirectory(public_path('uploads/images'));\n\n        // upload files\n        $path = __DIR__.'/assets/test.jpg';\n\n        $file = new \\Illuminate\\Http\\UploadedFile($path, 'test.jpg', 'image/jpeg', null, true);\n\n        $size = rand(10, 20);\n        $files = ['pictures' => array_pad([], $size, $file)];\n\n        $this->call(\n            'POST', // $method\n            '/admin/multiple-images', // $action\n            [], // $parameters\n            [],\n            $files\n        );\n\n        $this->assertEquals($this->fileCountInImageDir(), $size);\n    }\n\n    protected function fileCountInImageDir($dir = 'uploads/images')\n    {\n        $file = new FilesystemIterator(public_path($dir), FilesystemIterator::SKIP_DOTS);\n\n        return iterator_count($file);\n    }\n}\n"
  },
  {
    "path": "tests/IndexTest.php",
    "content": "<?php\n\nuse Encore\\Admin\\Auth\\Database\\Administrator;\n\nclass IndexTest extends TestCase\n{\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->be(Administrator::first(), 'admin');\n    }\n\n    public function testIndex()\n    {\n        $this->visit('admin/')\n            ->see('Dashboard')\n            ->see('Description...')\n\n            ->see('Environment')\n            ->see('PHP version')\n            ->see('Laravel version')\n\n            ->see('Available extensions')\n            ->seeLink('laravel-admin-ext/helpers', 'https://github.com/laravel-admin-extensions/helpers')\n            ->seeLink('laravel-admin-ext/backup', 'https://github.com/laravel-admin-extensions/backup')\n            ->seeLink('laravel-admin-ext/media-manager', 'https://github.com/laravel-admin-extensions/media-manager')\n\n            ->see('Dependencies')\n            ->see('php')\n//            ->see('>=7.0.0')\n            ->see('laravel/framework');\n    }\n\n    public function testClickMenu()\n    {\n        $this->visit('admin/')\n            ->click('Users')\n            ->seePageis('admin/auth/users')\n            ->click('Roles')\n            ->seePageis('admin/auth/roles')\n            ->click('Permission')\n            ->seePageis('admin/auth/permissions')\n            ->click('Menu')\n            ->seePageis('admin/auth/menu')\n            ->click('Operation log')\n            ->seePageis('admin/auth/logs');\n    }\n}\n"
  },
  {
    "path": "tests/InstallTest.php",
    "content": "<?php\n\nclass InstallTest extends TestCase\n{\n    public function testInstalledDirectories()\n    {\n        $this->assertFileExists(admin_path());\n\n        $this->assertFileExists(admin_path('Controllers'));\n\n        $this->assertFileExists(admin_path('routes.php'));\n\n        $this->assertFileExists(admin_path('bootstrap.php'));\n\n        $this->assertFileExists(admin_path('Controllers/HomeController.php'));\n\n        $this->assertFileExists(admin_path('Controllers/AuthController.php'));\n\n        $this->assertFileExists(admin_path('Controllers/ExampleController.php'));\n\n        $this->assertFileExists(config_path('admin.php'));\n\n        $this->assertFileExists(public_path('vendor/laravel-admin'));\n    }\n}\n"
  },
  {
    "path": "tests/LaravelTest.php",
    "content": "<?php\n\nclass LaravelTest extends TestCase\n{\n    public function testLaravel()\n    {\n        $this->visit('/')\n            ->assertResponseStatus(200)\n            ->see('Laravel');\n    }\n}\n"
  },
  {
    "path": "tests/MenuTest.php",
    "content": "<?php\n\nuse Encore\\Admin\\Auth\\Database\\Administrator;\nuse Encore\\Admin\\Auth\\Database\\Menu;\n\nclass MenuTest extends TestCase\n{\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->be(Administrator::first(), 'admin');\n    }\n\n    public function testMenuIndex()\n    {\n        $this->visit('admin/auth/menu')\n            ->see('Menu')\n            ->see('Index')\n            ->see('Auth')\n            ->see('Users')\n            ->see('Roles')\n            ->see('Permission')\n            ->see('Menu');\n    }\n\n    public function testAddMenu()\n    {\n        $item = ['parent_id' => '0', 'title' => 'Test', 'uri' => 'test'];\n\n        $this->visit('admin/auth/menu')\n            ->seePageIs('admin/auth/menu')\n            ->see('Menu')\n            ->submitForm('Submit', $item)\n            ->seePageIs('admin/auth/menu')\n            ->seeInDatabase(config('admin.database.menu_table'), $item)\n            ->assertEquals(8, Menu::count());\n\n//        $this->expectException(\\Laravel\\BrowserKitTesting\\HttpException::class);\n//\n//        $this->visit('admin')\n//            ->see('Test')\n//            ->click('Test');\n    }\n\n    public function testDeleteMenu()\n    {\n        $this->delete('admin/auth/menu/8')\n            ->assertEquals(7, Menu::count());\n    }\n\n    public function testEditMenu()\n    {\n        $this->visit('admin/auth/menu/1/edit')\n            ->see('Menu')\n            ->submitForm('Submit', ['title' => 'blablabla'])\n            ->seePageIs('admin/auth/menu')\n            ->seeInDatabase(config('admin.database.menu_table'), ['title' => 'blablabla'])\n            ->assertEquals(7, Menu::count());\n    }\n\n    public function testShowPage()\n    {\n        $this->visit('admin/auth/menu/1/edit')\n            ->seePageIs('admin/auth/menu/1/edit');\n    }\n\n    public function testEditMenuParent()\n    {\n        $this->expectException(\\Laravel\\BrowserKitTesting\\HttpException::class);\n\n        $this->visit('admin/auth/menu/5/edit')\n            ->see('Menu')\n            ->submitForm('Submit', ['parent_id' => 5]);\n    }\n}\n"
  },
  {
    "path": "tests/ModelTreeTest.php",
    "content": "<?php\n\nuse Tests\\Models\\Tree;\n\nclass ModelTreeTest extends TestCase\n{\n    protected function setUp(): void\n    {\n        parent::setUp();\n    }\n\n    public function testSelectOptions()\n    {\n        $rootText = 'Root Text';\n\n        $options = Tree::selectOptions(function ($query) {\n            return $query->where('uri', '');\n        }, $rootText);\n\n        $count = Tree::query()->where('uri', '')->count();\n\n        $this->assertEquals(array_shift($options), $rootText);\n        $this->assertEquals(count($options), $count);\n    }\n}\n"
  },
  {
    "path": "tests/OperationLogTest.php",
    "content": "<?php\n\nuse Encore\\Admin\\Auth\\Database\\Administrator;\nuse Encore\\Admin\\Auth\\Database\\OperationLog;\n\nclass OperationLogTest extends TestCase\n{\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->be(Administrator::first(), 'admin');\n    }\n\n    public function testOperationLogIndex()\n    {\n        $this->visit('admin/auth/logs')\n            ->see('Operation log')\n            ->see('List')\n            ->see('GET')\n            ->see('admin/auth/logs');\n    }\n\n    public function testGenerateLogs()\n    {\n        $table = config('admin.database.operation_log_table');\n\n        $this->visit('admin/auth/menu')\n            ->seePageIs('admin/auth/menu')\n            ->visit('admin/auth/users')\n            ->seePageIs('admin/auth/users')\n            ->visit('admin/auth/permissions')\n            ->seePageIs('admin/auth/permissions')\n            ->visit('admin/auth/roles')\n            ->seePageIs('admin/auth/roles')\n            ->visit('admin/auth/logs')\n            ->seePageIs('admin/auth/logs')\n            ->seeInDatabase($table, ['path' => 'admin/auth/menu', 'method' => 'GET'])\n            ->seeInDatabase($table, ['path' => 'admin/auth/users', 'method' => 'GET'])\n            ->seeInDatabase($table, ['path' => 'admin/auth/permissions', 'method' => 'GET'])\n            ->seeInDatabase($table, ['path' => 'admin/auth/roles', 'method' => 'GET']);\n\n        $this->assertEquals(4, OperationLog::count());\n    }\n\n    public function testDeleteLogs()\n    {\n        $table = config('admin.database.operation_log_table');\n\n        $this->visit('admin/auth/logs')\n            ->seePageIs('admin/auth/logs')\n            ->assertEquals(0, OperationLog::count());\n\n        $this->visit('admin/auth/users');\n\n        $this->seeInDatabase($table, ['path' => 'admin/auth/users', 'method' => 'GET']);\n\n        $this->delete('admin/auth/logs/1')\n            ->assertEquals(0, OperationLog::count());\n    }\n\n    public function testDeleteMultipleLogs()\n    {\n        $table = config('admin.database.operation_log_table');\n\n        $this->visit('admin/auth/menu')\n            ->visit('admin/auth/users')\n            ->visit('admin/auth/permissions')\n            ->visit('admin/auth/roles')\n            ->seeInDatabase($table, ['path' => 'admin/auth/menu', 'method' => 'GET'])\n            ->seeInDatabase($table, ['path' => 'admin/auth/users', 'method' => 'GET'])\n            ->seeInDatabase($table, ['path' => 'admin/auth/permissions', 'method' => 'GET'])\n            ->seeInDatabase($table, ['path' => 'admin/auth/roles', 'method' => 'GET'])\n            ->assertEquals(4, OperationLog::count());\n\n        $this->delete('admin/auth/logs/1,2,3,4')\n            ->notSeeInDatabase($table, ['path' => 'admin/auth/menu', 'method' => 'GET'])\n            ->notSeeInDatabase($table, ['path' => 'admin/auth/users', 'method' => 'GET'])\n            ->notSeeInDatabase($table, ['path' => 'admin/auth/permissions', 'method' => 'GET'])\n            ->notSeeInDatabase($table, ['path' => 'admin/auth/roles', 'method' => 'GET'])\n\n            ->assertEquals(0, OperationLog::count());\n    }\n}\n"
  },
  {
    "path": "tests/PermissionsTest.php",
    "content": "<?php\n\nuse Encore\\Admin\\Auth\\Database\\Administrator;\nuse Encore\\Admin\\Auth\\Database\\Permission;\nuse Encore\\Admin\\Auth\\Database\\Role;\n\nclass PermissionsTest extends TestCase\n{\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->be(Administrator::first(), 'admin');\n    }\n\n    public function testPermissionsIndex()\n    {\n        $this->assertTrue(Administrator::first()->isAdministrator());\n\n        $this->visit('admin/auth/permissions')\n            ->see('Permissions');\n    }\n\n    public function testAddAndDeletePermissions()\n    {\n        $this->visit('admin/auth/permissions/create')\n            ->see('Permissions')\n            ->submitForm('Submit', ['slug' => 'can-edit', 'name' => 'Can edit', 'http_path' => 'users/1/edit', 'http_method' => ['GET']])\n            ->seePageIs('admin/auth/permissions')\n            ->visit('admin/auth/permissions/create')\n            ->see('Permissions')\n            ->submitForm('Submit', ['slug' => 'can-delete', 'name' => 'Can delete', 'http_path' => 'users/1', 'http_method' => ['DELETE']])\n            ->seePageIs('admin/auth/permissions')\n            ->seeInDatabase(config('admin.database.permissions_table'), ['slug' => 'can-edit', 'name' => 'Can edit', 'http_path' => 'users/1/edit', 'http_method' => 'GET'])\n            ->seeInDatabase(config('admin.database.permissions_table'), ['slug' => 'can-delete', 'name' => 'Can delete', 'http_path' => 'users/1', 'http_method' => 'DELETE'])\n            ->assertEquals(7, Permission::count());\n\n        $this->assertTrue(Administrator::first()->can('can-edit'));\n        $this->assertTrue(Administrator::first()->can('can-delete'));\n\n        $this->delete('admin/auth/permissions/6')\n            ->assertEquals(6, Permission::count());\n\n        $this->delete('admin/auth/permissions/7')\n            ->assertEquals(5, Permission::count());\n    }\n\n    public function testAddPermissionToRole()\n    {\n        $this->visit('admin/auth/permissions/create')\n            ->see('Permissions')\n            ->submitForm('Submit', ['slug' => 'can-create', 'name' => 'Can Create', 'http_path' => 'users/create', 'http_method' => ['GET']])\n            ->seePageIs('admin/auth/permissions');\n\n        $this->assertEquals(6, Permission::count());\n\n        $this->visit('admin/auth/roles/1/edit')\n            ->see('Edit')\n            ->submitForm('Submit', ['permissions' => [1]])\n            ->seePageIs('admin/auth/roles')\n            ->seeInDatabase(config('admin.database.role_permissions_table'), ['role_id' => 1, 'permission_id' => 1]);\n    }\n\n    public function testAddPermissionToUser()\n    {\n        $this->visit('admin/auth/permissions/create')\n            ->see('Permissions')\n            ->submitForm('Submit', ['slug' => 'can-create', 'name' => 'Can Create', 'http_path' => 'users/create', 'http_method' => ['GET']])\n            ->seePageIs('admin/auth/permissions');\n\n        $this->assertEquals(6, Permission::count());\n\n        $this->visit('admin/auth/users/1/edit')\n            ->see('Edit')\n            ->submitForm('Submit', ['permissions' => [1], 'roles' => [1]])\n            ->seePageIs('admin/auth/users')\n            ->seeInDatabase(config('admin.database.user_permissions_table'), ['user_id' => 1, 'permission_id' => 1])\n            ->seeInDatabase(config('admin.database.role_users_table'), ['user_id' => 1, 'role_id' => 1]);\n    }\n\n    public function testAddUserAndAssignPermission()\n    {\n        $user = [\n            'username'              => 'Test',\n            'name'                  => 'Name',\n            'password'              => '123456',\n            'password_confirmation' => '123456',\n        ];\n\n        $this->visit('admin/auth/users/create')\n            ->see('Create')\n            ->submitForm('Submit', $user)\n            ->seePageIs('admin/auth/users')\n            ->seeInDatabase(config('admin.database.users_table'), ['username' => 'Test']);\n\n        $this->assertFalse(Administrator::find(2)->isAdministrator());\n\n        $this->visit('admin/auth/permissions/create')\n            ->see('Permissions')\n            ->submitForm('Submit', ['slug' => 'can-update', 'name' => 'Can Update', 'http_path' => 'users/*/edit', 'http_method' => ['GET']])\n            ->seePageIs('admin/auth/permissions');\n\n        $this->assertEquals(6, Permission::count());\n\n        $this->visit('admin/auth/permissions/create')\n            ->see('Permissions')\n            ->submitForm('Submit', ['slug' => 'can-remove', 'name' => 'Can Remove', 'http_path' => 'users/*', 'http_method' => ['DELETE']])\n            ->seePageIs('admin/auth/permissions');\n\n        $this->assertEquals(7, Permission::count());\n\n        $this->visit('admin/auth/users/2/edit')\n            ->see('Edit')\n            ->submitForm('Submit', ['permissions' => [6]])\n            ->seePageIs('admin/auth/users')\n            ->seeInDatabase(config('admin.database.user_permissions_table'), ['user_id' => 2, 'permission_id' => 6]);\n\n        $this->assertTrue(Administrator::find(2)->can('can-update'));\n        $this->assertTrue(Administrator::find(2)->cannot('can-remove'));\n\n        $this->visit('admin/auth/users/2/edit')\n            ->see('Edit')\n            ->submitForm('Submit', ['permissions' => [7]])\n            ->seePageIs('admin/auth/users')\n            ->seeInDatabase(config('admin.database.user_permissions_table'), ['user_id' => 2, 'permission_id' => 7]);\n\n        $this->assertTrue(Administrator::find(2)->can('can-remove'));\n\n        $this->visit('admin/auth/users/2/edit')\n            ->see('Edit')\n            ->submitForm('Submit', ['permissions' => []])\n            ->seePageIs('admin/auth/users')\n            ->missingFromDatabase(config('admin.database.user_permissions_table'), ['user_id' => 2, 'permission_id' => 6])\n            ->missingFromDatabase(config('admin.database.user_permissions_table'), ['user_id' => 2, 'permission_id' => 7]);\n\n        $this->assertTrue(Administrator::find(2)->cannot('can-update'));\n        $this->assertTrue(Administrator::find(2)->cannot('can-remove'));\n    }\n\n    public function testPermissionThroughRole()\n    {\n        $user = [\n            'username'              => 'Test',\n            'name'                  => 'Name',\n            'password'              => '123456',\n            'password_confirmation' => '123456',\n        ];\n\n        // 1.add a user\n        $this->visit('admin/auth/users/create')\n            ->see('Create')\n            ->submitForm('Submit', $user)\n            ->seePageIs('admin/auth/users')\n            ->seeInDatabase(config('admin.database.users_table'), ['username' => 'Test']);\n\n        $this->assertFalse(Administrator::find(2)->isAdministrator());\n\n        // 2.add a role\n        $this->visit('admin/auth/roles/create')\n            ->see('Roles')\n            ->submitForm('Submit', ['slug' => 'developer', 'name' => 'Developer...'])\n            ->seePageIs('admin/auth/roles')\n            ->seeInDatabase(config('admin.database.roles_table'), ['slug' => 'developer', 'name' => 'Developer...'])\n            ->assertEquals(2, Role::count());\n\n        $this->assertFalse(Administrator::find(2)->isRole('developer'));\n\n        // 3.assign role to user\n        $this->visit('admin/auth/users/2/edit')\n            ->see('Edit')\n            ->submitForm('Submit', ['roles' => [2]])\n            ->seePageIs('admin/auth/users')\n            ->seeInDatabase(config('admin.database.role_users_table'), ['user_id' => 2, 'role_id' => 2]);\n\n        $this->assertTrue(Administrator::find(2)->isRole('developer'));\n\n        //  4.add a permission\n        $this->visit('admin/auth/permissions/create')\n            ->see('Permissions')\n            ->submitForm('Submit', ['slug' => 'can-remove', 'name' => 'Can Remove', 'http_path' => 'users/*', 'http_method' => ['DELETE']])\n            ->seePageIs('admin/auth/permissions');\n\n        $this->assertEquals(6, Permission::count());\n\n        $this->assertTrue(Administrator::find(2)->cannot('can-remove'));\n\n        // 5.assign permission to role\n        $this->visit('admin/auth/roles/2/edit')\n            ->see('Edit')\n            ->submitForm('Submit', ['permissions' => [6]])\n            ->seePageIs('admin/auth/roles')\n            ->seeInDatabase(config('admin.database.role_permissions_table'), ['role_id' => 2, 'permission_id' => 6]);\n\n        $this->assertTrue(Administrator::find(2)->can('can-remove'));\n    }\n\n    public function testEditPermission()\n    {\n        $this->visit('admin/auth/permissions/create')\n            ->see('Permissions')\n            ->submitForm('Submit', ['slug' => 'can-edit', 'name' => 'Can edit', 'http_path' => 'users/1/edit', 'http_method' => ['GET']])\n            ->seePageIs('admin/auth/permissions')\n            ->seeInDatabase(config('admin.database.permissions_table'), ['slug' => 'can-edit'])\n            ->seeInDatabase(config('admin.database.permissions_table'), ['name' => 'Can edit'])\n            ->assertEquals(6, Permission::count());\n\n        $this->visit('admin/auth/permissions/1/edit')\n            ->see('Permissions')\n            ->submitForm('Submit', ['slug' => 'can-delete'])\n            ->seePageIs('admin/auth/permissions')\n            ->seeInDatabase(config('admin.database.permissions_table'), ['slug' => 'can-delete'])\n            ->assertEquals(6, Permission::count());\n    }\n}\n"
  },
  {
    "path": "tests/RolesTest.php",
    "content": "<?php\n\nuse Encore\\Admin\\Auth\\Database\\Administrator;\nuse Encore\\Admin\\Auth\\Database\\Role;\n\nclass RolesTest extends TestCase\n{\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->be(Administrator::first(), 'admin');\n    }\n\n    public function testRolesIndex()\n    {\n        $this->visit('admin/auth/roles')\n            ->see('Roles')\n            ->see('administrator');\n    }\n\n    public function testAddRole()\n    {\n        $this->visit('admin/auth/roles/create')\n            ->see('Roles')\n            ->submitForm('Submit', ['slug' => 'developer', 'name' => 'Developer...'])\n            ->seePageIs('admin/auth/roles')\n            ->seeInDatabase(config('admin.database.roles_table'), ['slug' => 'developer', 'name' => 'Developer...'])\n            ->assertEquals(2, Role::count());\n    }\n\n    public function testAddRoleToUser()\n    {\n        $user = [\n            'username'              => 'Test',\n            'name'                  => 'Name',\n            'password'              => '123456',\n            'password_confirmation' => '123456',\n\n        ];\n\n        $this->visit('admin/auth/users/create')\n            ->see('Create')\n            ->submitForm('Submit', $user)\n            ->seePageIs('admin/auth/users')\n            ->seeInDatabase(config('admin.database.users_table'), ['username' => 'Test']);\n\n        $this->assertEquals(1, Role::count());\n\n        $this->visit('admin/auth/roles/create')\n            ->see('Roles')\n            ->submitForm('Submit', ['slug' => 'developer', 'name' => 'Developer...'])\n            ->seePageIs('admin/auth/roles')\n            ->seeInDatabase(config('admin.database.roles_table'), ['slug' => 'developer', 'name' => 'Developer...'])\n            ->assertEquals(2, Role::count());\n\n        $this->assertFalse(Administrator::find(2)->isRole('developer'));\n\n        $this->visit('admin/auth/users/2/edit')\n            ->see('Edit')\n            ->submitForm('Submit', ['roles' => [2]])\n            ->seePageIs('admin/auth/users')\n            ->seeInDatabase(config('admin.database.role_users_table'), ['user_id' => 2, 'role_id' => 2]);\n\n        $this->assertTrue(Administrator::find(2)->isRole('developer'));\n\n        $this->assertFalse(Administrator::find(2)->inRoles(['editor', 'operator']));\n        $this->assertTrue(Administrator::find(2)->inRoles(['developer', 'operator', 'editor']));\n    }\n\n    public function testDeleteRole()\n    {\n        $this->assertEquals(1, Role::count());\n\n        $this->visit('admin/auth/roles/create')\n            ->see('Roles')\n            ->submitForm('Submit', ['slug' => 'developer', 'name' => 'Developer...'])\n            ->seePageIs('admin/auth/roles')\n            ->seeInDatabase(config('admin.database.roles_table'), ['slug' => 'developer', 'name' => 'Developer...'])\n            ->assertEquals(2, Role::count());\n\n        $this->delete('admin/auth/roles/2')\n            ->assertEquals(1, Role::count());\n\n        $this->delete('admin/auth/roles/1')\n            ->assertEquals(0, Role::count());\n    }\n\n    public function testEditRole()\n    {\n        $this->visit('admin/auth/roles/create')\n            ->see('Roles')\n            ->submitForm('Submit', ['slug' => 'developer', 'name' => 'Developer...'])\n            ->seePageIs('admin/auth/roles')\n            ->seeInDatabase(config('admin.database.roles_table'), ['slug' => 'developer', 'name' => 'Developer...'])\n            ->assertEquals(2, Role::count());\n\n        $this->visit('admin/auth/roles/2/edit')\n            ->see('Roles')\n            ->submitForm('Submit', ['name' => 'blablabla'])\n            ->seePageIs('admin/auth/roles')\n            ->seeInDatabase(config('admin.database.roles_table'), ['name' => 'blablabla'])\n            ->assertEquals(2, Role::count());\n    }\n}\n"
  },
  {
    "path": "tests/TestCase.php",
    "content": "<?php\n\nuse Illuminate\\Filesystem\\Filesystem;\nuse Illuminate\\Support\\Arr;\nuse Illuminate\\Support\\Facades\\DB;\nuse Illuminate\\Support\\Facades\\Schema;\nuse Laravel\\BrowserKitTesting\\TestCase as BaseTestCase;\n\nclass TestCase extends BaseTestCase\n{\n    protected $baseUrl = 'http://localhost:8000';\n\n    /**\n     * Boots the application.\n     *\n     * @return \\Illuminate\\Foundation\\Application\n     */\n    public function createApplication()\n    {\n        $app = require __DIR__.'/../vendor/laravel/laravel/bootstrap/app.php';\n\n        $app->booting(function () {\n            $loader = \\Illuminate\\Foundation\\AliasLoader::getInstance();\n            $loader->alias('Admin', \\Encore\\Admin\\Facades\\Admin::class);\n        });\n\n        $app->make('Illuminate\\Contracts\\Console\\Kernel')->bootstrap();\n\n        $app->register('Encore\\Admin\\AdminServiceProvider');\n\n        return $app;\n    }\n\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $adminConfig = require __DIR__.'/config/admin.php';\n\n        $this->app['config']->set('database.default', env('DB_CONNECTION', 'mysql'));\n        $this->app['config']->set('database.connections.mysql.host', env('MYSQL_HOST', 'localhost'));\n        $this->app['config']->set('database.connections.mysql.database', env('MYSQL_DATABASE', 'laravel_admin_test'));\n        $this->app['config']->set('database.connections.mysql.username', env('MYSQL_USER', 'root'));\n        $this->app['config']->set('database.connections.mysql.password', env('MYSQL_PASSWORD', ''));\n        $this->app['config']->set('app.key', 'AckfSECXIvnK5r28GVIWUAxmbBSjTsmF');\n        $this->app['config']->set('filesystems', require __DIR__.'/config/filesystems.php');\n        $this->app['config']->set('admin', $adminConfig);\n\n        foreach (Arr::dot(Arr::get($adminConfig, 'auth'), 'auth.') as $key => $value) {\n            $this->app['config']->set($key, $value);\n        }\n\n        $this->artisan('vendor:publish', ['--provider' => 'Encore\\Admin\\AdminServiceProvider']);\n\n        Schema::defaultStringLength(191);\n\n        $this->artisan('admin:install');\n\n        $this->migrateTestTables();\n\n        if (file_exists($routes = admin_path('routes.php'))) {\n            require $routes;\n        }\n\n        require __DIR__.'/routes.php';\n\n        require __DIR__.'/seeds/factory.php';\n\n//        \\Encore\\Admin\\Admin::$css = [];\n//        \\Encore\\Admin\\Admin::$js = [];\n//        \\Encore\\Admin\\Admin::$script = [];\n    }\n\n    protected function tearDown(): void\n    {\n        (new CreateAdminTables())->down();\n\n        (new CreateTestTables())->down();\n\n        DB::select(\"delete from `migrations` where `migration` = '2016_01_04_173148_create_admin_tables'\");\n\n        parent::tearDown();\n    }\n\n    /**\n     * run package database migrations.\n     *\n     * @return void\n     */\n    public function migrateTestTables()\n    {\n        $fileSystem = new Filesystem();\n\n        $fileSystem->requireOnce(__DIR__.'/migrations/2016_11_22_093148_create_test_tables.php');\n\n        (new CreateTestTables())->up();\n    }\n}\n"
  },
  {
    "path": "tests/UserFormTest.php",
    "content": "<?php\n\nuse Encore\\Admin\\Auth\\Database\\Administrator;\nuse Tests\\Models\\User as UserModel;\n\nclass UserFormTest extends TestCase\n{\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->be(Administrator::first(), 'admin');\n    }\n\n    public function testCreatePage()\n    {\n        $this->visit('admin/users/create')\n            ->seeElement('input[type=text][name=username]')\n            ->seeElement('input[type=email][name=email]')\n            ->seeElement('input[type=text][name=mobile]')\n            ->seeElement('input[type=file][name=avatar]')\n            ->seeElement('hr')\n            ->seeElement(\"input[type=text][name='profile[first_name]']\")\n            ->seeElement(\"input[type=text][name='profile[last_name]']\")\n            ->seeElement(\"input[type=text][name='profile[postcode]']\")\n            ->seeElement(\"textarea[name='profile[address]'][rows=15]\")\n            ->seeElement(\"input[type=hidden][name='profile[latitude]']\")\n            ->seeElement(\"input[type=hidden][name='profile[longitude]']\")\n            ->seeElement(\"input[type=text][name='profile[color]']\")\n            ->seeElement(\"input[type=text][name='profile[start_at]']\")\n            ->seeElement(\"input[type=text][name='profile[end_at]']\")\n            ->seeElement('span[class=help-block] i[class*=fa-info-circle]')\n            ->seeInElement('span[class=help-block]', 'Please input your postcode')\n            ->seeElement('span[class=help-block] i[class*=fa-image]')\n            ->seeInElement('span[class=help-block]', '上传头像')\n            ->seeElement(\"select[name='tags[]'][multiple=multiple]\")\n            ->seeInElement('a[html-field]', 'html...');\n    }\n\n    public function testSubmitForm()\n    {\n        $data = [\n            'username'              => 'John Doe',\n            'email'                 => 'hello@world.com',\n            'mobile'                => '13421234123',\n            'password'              => '123456',\n            'password_confirmation' => '123456',\n            //\"avatar\"   => \"test.jpg\",\n            'profile' => [\n                'first_name' => 'John',\n                'last_name'  => 'Doe',\n                'postcode'   => '123456',\n                'address'    => 'Jinshajiang RD',\n                'latitude'   => '131.2123123456',\n                'longitude'  => '21.342123456',\n                'color'      => '#ffffff',\n                'start_at'   => date('Y-m-d H:i:s', time()),\n                'end_at'     => date('Y-m-d H:i:s', time()),\n            ],\n        ];\n\n        $this->visit('admin/users/create')\n            ->attach(__DIR__.'/assets/test.jpg', 'avatar')\n\n            ->submitForm('Submit', $data)\n            ->seePageIs('admin/users')\n            ->seeInElement('td', 1)\n            ->seeInElement('td', $data['username'])\n            ->seeInElement('td', $data['email'])\n            ->seeInElement('td', $data['mobile'])\n            ->seeInElement('td', \"{$data['profile']['first_name']} {$data['profile']['last_name']}\")\n            ->seeElement('td img')\n            ->seeInElement('td', $data['profile']['postcode'])\n            ->seeInElement('td', $data['profile']['address'])\n            ->seeInElement('td', \"{$data['profile']['latitude']} {$data['profile']['longitude']}\")\n            ->seeInElement('td', $data['profile']['color'])\n            ->seeInElement('td', $data['profile']['start_at'])\n            ->seeInElement('td', $data['profile']['end_at']);\n\n        $this->assertCount(1, UserModel::all());\n\n        $this->seeInDatabase('test_users', ['username' => $data['username']]);\n        $this->seeInDatabase('test_users', ['email' => $data['email']]);\n        $this->seeInDatabase('test_users', ['mobile' => $data['mobile']]);\n        $this->seeInDatabase('test_users', ['password' => $data['password']]);\n\n        $this->seeInDatabase('test_user_profiles', ['first_name' => $data['profile']['first_name']]);\n        $this->seeInDatabase('test_user_profiles', ['last_name' => $data['profile']['last_name']]);\n        $this->seeInDatabase('test_user_profiles', ['postcode' => $data['profile']['postcode']]);\n        $this->seeInDatabase('test_user_profiles', ['address' => $data['profile']['address']]);\n        $this->seeInDatabase('test_user_profiles', ['latitude' => $data['profile']['latitude']]);\n        $this->seeInDatabase('test_user_profiles', ['longitude' => $data['profile']['longitude']]);\n        $this->seeInDatabase('test_user_profiles', ['color' => $data['profile']['color']]);\n        $this->seeInDatabase('test_user_profiles', ['start_at' => $data['profile']['start_at']]);\n        $this->seeInDatabase('test_user_profiles', ['end_at' => $data['profile']['end_at']]);\n\n        $avatar = UserModel::first()->avatar;\n\n        $this->assertFileExists(public_path('uploads/'.$avatar));\n    }\n\n    protected function seedsTable($count = 100)\n    {\n        factory(\\Tests\\Models\\User::class, $count)\n            ->create()\n            ->each(function ($u) {\n                $u->profile()->save(factory(\\Tests\\Models\\Profile::class)->make());\n                $u->tags()->saveMany(factory(\\Tests\\Models\\Tag::class, 5)->make());\n            });\n    }\n\n    public function testEditForm()\n    {\n        $this->seedsTable(10);\n\n        $id = rand(1, 10);\n\n        $user = UserModel::with('profile')->find($id);\n\n        $this->visit(\"admin/users/$id/edit\")\n            ->seeElement(\"input[type=text][name=username][value='{$user->username}']\")\n            ->seeElement(\"input[type=email][name=email][value='{$user->email}']\")\n            ->seeElement(\"input[type=text][name=mobile][value='{$user->mobile}']\")\n            ->seeElement('hr')\n            ->seeElement(\"input[type=text][name='profile[first_name]'][value='{$user->profile->first_name}']\")\n            ->seeElement(\"input[type=text][name='profile[last_name]'][value='{$user->profile->last_name}']\")\n            ->seeElement(\"input[type=text][name='profile[postcode]'][value='{$user->profile->postcode}']\")\n            ->seeInElement(\"textarea[name='profile[address]']\", $user->profile->address)\n            ->seeElement(\"input[type=hidden][name='profile[latitude]'][value='{$user->profile->latitude}']\")\n            ->seeElement(\"input[type=hidden][name='profile[longitude]'][value='{$user->profile->longitude}']\")\n            ->seeElement(\"input[type=text][name='profile[color]'][value='{$user->profile->color}']\")\n            ->seeElement(\"input[type=text][name='profile[start_at]'][value='{$user->profile->start_at}']\")\n            ->seeElement(\"input[type=text][name='profile[end_at]'][value='{$user->profile->end_at}']\")\n            ->seeElement(\"select[name='tags[]'][multiple=multiple]\");\n\n        $this->assertCount(50, $this->crawler()->filter(\"select[name='tags[]'] option\"));\n        $this->assertCount(5, $this->crawler()->filter(\"select[name='tags[]'] option[selected]\"));\n    }\n\n    public function testUpdateForm()\n    {\n        $this->seedsTable(10);\n\n        $id = rand(1, 10);\n\n        $this->visit(\"admin/users/$id/edit\")\n            ->type('hello world', 'username')\n            ->type('123', 'password')\n            ->type('123', 'password_confirmation')\n            ->press('Submit')\n            ->seePageIs('admin/users')\n            ->seeInDatabase('test_users', ['username' => 'hello world']);\n\n        $user = UserModel::with('profile')->find($id);\n\n        $this->assertEquals($user->username, 'hello world');\n    }\n\n    public function testUpdateFormWithRule()\n    {\n        $this->seedsTable(10);\n\n        $id = rand(1, 10);\n\n        $this->visit(\"admin/users/$id/edit\")\n            ->type('', 'email')\n            ->press('Submit')\n            ->seePageIs(\"admin/users/$id/edit\")\n            ->see('The email field is required');\n\n        $this->type('xxaxx', 'email')\n            ->press('Submit')\n            ->seePageIs(\"admin/users/$id/edit\")\n            ->see('The email must be a valid email address.');\n\n        $this->visit(\"admin/users/$id/edit\")\n            ->type('123', 'password')\n            ->type('1234', 'password_confirmation')\n            ->press('Submit')\n            ->seePageIs(\"admin/users/$id/edit\")\n            ->see('The Password confirmation does not match.');\n\n        $this->type('xx@xx.xx', 'email')\n            ->type('123', 'password')\n            ->type('123', 'password_confirmation')\n            ->press('Submit')\n            ->seePageIs('admin/users')\n            ->seeInDatabase('test_users', ['email' => 'xx@xx.xx']);\n    }\n\n    public function testFormHeader()\n    {\n        $this->seedsTable(1);\n\n        $this->visit('admin/users/1/edit')\n            ->seeInElement('a[class*=btn-danger]', 'Delete')\n            ->seeInElement('a[class*=btn-default]', 'List')\n            ->seeInElement('a[class*=btn-primary]', 'View');\n    }\n\n    public function testFormFooter()\n    {\n        $this->seedsTable(1);\n\n        $this->visit('admin/users/1/edit')\n            ->seeElement('input[type=checkbox][value=1]')\n            ->seeElement('input[type=checkbox][value=2]');\n    }\n}\n"
  },
  {
    "path": "tests/UserGridTest.php",
    "content": "<?php\n\nuse Encore\\Admin\\Auth\\Database\\Administrator;\nuse Tests\\Models\\Profile as ProfileModel;\nuse Tests\\Models\\User as UserModel;\n\nclass UserGridTest extends TestCase\n{\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->be(Administrator::first(), 'admin');\n    }\n\n    public function testIndexPage()\n    {\n        $this->visit('admin/users')\n            ->see('Users')\n            ->seeInElement('tr th', 'Username')\n            ->seeInElement('tr th', 'Email')\n            ->seeInElement('tr th', 'Mobile')\n            ->seeInElement('tr th', 'Full name')\n            ->seeInElement('tr th', 'Avatar')\n            ->seeInElement('tr th', 'Post code')\n            ->seeInElement('tr th', 'Address')\n            ->seeInElement('tr th', 'Position')\n            ->seeInElement('tr th', 'Color')\n            ->seeInElement('tr th', '开始时间')\n            ->seeInElement('tr th', '结束时间')\n            ->seeInElement('tr th', 'Color')\n            ->seeInElement('tr th', 'Created at')\n            ->seeInElement('tr th', 'Updated at');\n\n        $action = url('/admin/users');\n\n        $this->seeElement(\"form[action='$action'][method=get]\")\n            ->seeElement(\"form[action='$action'][method=get] input[name=id]\")\n            ->seeElement(\"form[action='$action'][method=get] input[name=username]\")\n            ->seeElement(\"form[action='$action'][method=get] input[name=email]\")\n            ->seeElement(\"form[action='$action'][method=get] input[name='profile[start_at][start]']\")\n            ->seeElement(\"form[action='$action'][method=get] input[name='profile[start_at][end]']\")\n            ->seeElement(\"form[action='$action'][method=get] input[name='profile[end_at][start]']\")\n            ->seeElement(\"form[action='$action'][method=get] input[name='profile[end_at][end]']\");\n\n        $urlAll = url('/admin/users?_export_=all');\n        $urlNew = url('/admin/users/create');\n        $this->seeInElement(\"a[href=\\\"{$urlAll}\\\"]\", 'All')\n            ->seeInElement(\"a[href=\\\"{$urlNew}\\\"]\", 'New');\n    }\n\n    protected function seedsTable($count = 100)\n    {\n        factory(\\Tests\\Models\\User::class, $count)\n            ->create()\n            ->each(function ($u) {\n                $u->profile()->save(factory(\\Tests\\Models\\Profile::class)->make());\n                $u->tags()->saveMany(factory(\\Tests\\Models\\Tag::class, 5)->make());\n                $u->data = ['json' => ['field' => random_int(0, 50)]];\n                $u->save();\n            });\n    }\n\n    public function testGridWithData()\n    {\n        $this->seedsTable();\n\n        $this->visit('admin/users')\n            ->see('Users');\n\n        $this->assertCount(100, UserModel::all());\n        $this->assertCount(100, ProfileModel::all());\n    }\n\n    public function testGridPagination()\n    {\n        $this->seedsTable(65);\n\n        $this->visit('admin/users')\n            ->see('Users');\n\n        $this->visit('admin/users?page=2');\n        $this->assertCount(20, $this->crawler()->filter('td a i[class*=fa-edit]'));\n\n        $this->visit('admin/users?page=3');\n        $this->assertCount(20, $this->crawler()->filter('td a i[class*=fa-edit]'));\n\n        $this->visit('admin/users?page=4');\n        $this->assertCount(5, $this->crawler()->filter('td a i[class*=fa-edit]'));\n\n        $this->click(1)->seePageIs('admin/users?page=1');\n        $this->assertCount(20, $this->crawler()->filter('td a i[class*=fa-edit]'));\n    }\n\n    public function testOrderByJson()\n    {\n        $this->seedsTable(10);\n        $this->assertCount(10, UserModel::all());\n\n        $this->visit('admin/users?_sort[column]=data.json.field&_sort[type]=desc&_sort[cast]=unsigned');\n\n        $jsonTds = $this->crawler->filter('table.table tbody td.column-data-json-field');\n        $this->assertCount(10, $jsonTds);\n        $prevValue = PHP_INT_MAX;\n        foreach ($jsonTds as $jsonTd) {\n            $currentValue = (int) $jsonTd->nodeValue;\n            $this->assertTrue($currentValue <= $prevValue);\n            $prevValue = $currentValue;\n        }\n    }\n\n    public function testEqualFilter()\n    {\n        $this->seedsTable(50);\n\n        $this->visit('admin/users')\n            ->see('Users');\n\n        $this->assertCount(50, UserModel::all());\n        $this->assertCount(50, ProfileModel::all());\n\n        $id = rand(1, 50);\n\n        $user = UserModel::find($id);\n\n        $this->visit('admin/users?id='.$id)\n            ->seeInElement('td', $user->username)\n            ->seeInElement('td', $user->email)\n            ->seeInElement('td', $user->mobile)\n            ->seeElement(\"img[src='{$user->avatar}']\")\n            ->seeInElement('td', \"{$user->profile->first_name} {$user->profile->last_name}\")\n            ->seeInElement('td', $user->postcode)\n            ->seeInElement('td', $user->address)\n            ->seeInElement('td', \"{$user->profile->latitude} {$user->profile->longitude}\")\n            ->seeInElement('td', $user->color)\n            ->seeInElement('td', $user->start_at)\n            ->seeInElement('td', $user->end_at);\n    }\n\n    public function testLikeFilter()\n    {\n        $this->seedsTable(50);\n\n        $this->visit('admin/users')\n            ->see('Users');\n\n        $this->assertCount(50, UserModel::all());\n        $this->assertCount(50, ProfileModel::all());\n\n        $users = UserModel::where('username', 'like', '%mi%')->get();\n\n        $this->visit('admin/users?username=mi');\n\n        $this->assertCount($this->crawler()->filter('table tr')->count() - 1, $users);\n\n        foreach ($users as $user) {\n            $this->seeInElement('td', $user->username);\n        }\n    }\n\n    public function testFilterRelation()\n    {\n        $this->seedsTable(50);\n\n        $user = UserModel::with('profile')->find(rand(1, 50));\n\n        $this->visit('admin/users?email='.$user->email)\n            ->seeInElement('td', $user->username)\n            ->seeInElement('td', $user->email)\n            ->seeInElement('td', $user->mobile)\n            ->seeElement(\"img[src='{$user->avatar}']\")\n            ->seeInElement('td', \"{$user->profile->first_name} {$user->profile->last_name}\")\n            ->seeInElement('td', $user->postcode)\n            ->seeInElement('td', $user->address)\n            ->seeInElement('td', \"{$user->profile->latitude} {$user->profile->longitude}\")\n            ->seeInElement('td', $user->color)\n            ->seeInElement('td', $user->start_at)\n            ->seeInElement('td', $user->end_at);\n    }\n\n    public function testDisplayCallback()\n    {\n        $this->seedsTable(1);\n\n        $user = UserModel::with('profile')->find(1);\n\n        $this->visit('admin/users')\n            ->seeInElement('th', 'Column1 not in table')\n            ->seeInElement('th', 'Column2 not in table')\n            ->seeInElement('td', \"full name:{$user->profile->first_name} {$user->profile->last_name}\")\n            ->seeInElement('td', \"{$user->email}#{$user->profile->color}\");\n    }\n\n    public function testHasManyRelation()\n    {\n        factory(\\Tests\\Models\\User::class, 10)\n            ->create()\n            ->each(function ($u) {\n                $u->profile()->save(factory(\\Tests\\Models\\Profile::class)->make());\n                $u->tags()->saveMany(factory(\\Tests\\Models\\Tag::class, 5)->make());\n            });\n\n        $this->visit('admin/users')\n            ->seeElement('td code');\n\n        $this->assertCount(50, $this->crawler()->filter('td code'));\n    }\n\n    public function testGridActions()\n    {\n        $this->seedsTable(15);\n\n        $this->visit('admin/users');\n\n        $this->assertCount(15, $this->crawler()->filter('td a i[class*=fa-edit]'));\n        $this->assertCount(15, $this->crawler()->filter('td a i[class*=fa-trash]'));\n    }\n\n    public function testGridRows()\n    {\n        $this->seedsTable(10);\n\n        $this->visit('admin/users')\n            ->seeInElement('td a[class*=btn]', 'detail');\n\n        $this->assertCount(5, $this->crawler()->filter('td a[class*=btn]'));\n    }\n\n    public function testGridPerPage()\n    {\n        $this->seedsTable(98);\n\n        $this->visit('admin/users')\n            ->seeElement('select[class*=per-page][name=per-page]')\n            ->seeInElement('select option', 10)\n            ->seeInElement('select option[selected]', 20)\n            ->seeInElement('select option', 30)\n            ->seeInElement('select option', 50)\n            ->seeInElement('select option', 100);\n\n        $this->assertEquals('http://localhost:8000/admin/users?per_page=20', $this->crawler()->filter('select option[selected]')->attr('value'));\n\n        $perPage = rand(1, 98);\n\n        $this->visit('admin/users?per_page='.$perPage)\n            ->seeInElement('select option[selected]', $perPage)\n            ->assertCount($perPage + 1, $this->crawler()->filter('tr'));\n    }\n}\n"
  },
  {
    "path": "tests/UserSettingTest.php",
    "content": "<?php\n\nuse Encore\\Admin\\Auth\\Database\\Administrator;\nuse Illuminate\\Support\\Facades\\File;\n\nclass UserSettingTest extends TestCase\n{\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->be(Administrator::first(), 'admin');\n    }\n\n    public function testVisitSettingPage()\n    {\n        $this->visit('admin/auth/setting')\n            ->see('User setting')\n            ->see('Username')\n            ->see('Name')\n            ->see('Avatar')\n            ->see('Password')\n            ->see('Password confirmation');\n\n        $this->seeElement('input[value=Administrator]')\n            ->seeInElement('.box-body', 'administrator');\n    }\n\n    public function testUpdateName()\n    {\n        $data = [\n            'name' => 'tester',\n        ];\n\n        $this->visit('admin/auth/setting')\n            ->submitForm('Submit', $data)\n            ->seePageIs('admin/auth/setting');\n\n        $this->seeInDatabase('admin_users', ['name' => $data['name']]);\n    }\n\n    public function testUpdateAvatar()\n    {\n        File::cleanDirectory(public_path('uploads/images'));\n\n        $this->visit('admin/auth/setting')\n            ->attach(__DIR__.'/assets/test.jpg', 'avatar')\n            ->press('Submit')\n            ->seePageIs('admin/auth/setting');\n\n        $avatar = Administrator::first()->avatar;\n\n        $this->assertEquals('http://localhost:8000/uploads/images/test.jpg', $avatar);\n    }\n\n    public function testUpdatePasswordConfirmation()\n    {\n        $data = [\n            'password'              => '123456',\n            'password_confirmation' => '123',\n        ];\n\n        $this->visit('admin/auth/setting')\n            ->submitForm('Submit', $data)\n            ->seePageIs('admin/auth/setting')\n            ->see('The Password confirmation does not match.');\n    }\n\n    public function testUpdatePassword()\n    {\n        $data = [\n            'password'              => '123456',\n            'password_confirmation' => '123456',\n        ];\n\n        $this->visit('admin/auth/setting')\n            ->submitForm('Submit', $data)\n            ->seePageIs('admin/auth/setting');\n\n        $this->assertTrue(app('hash')->check($data['password'], Administrator::first()->makeVisible('password')->password));\n\n        $this->visit('admin/auth/logout')\n            ->seePageIs('admin/auth/login')\n            ->dontSeeIsAuthenticated('admin');\n\n        $credentials = ['username' => 'admin', 'password' => '123456'];\n\n        $this->visit('admin/auth/login')\n            ->see('login')\n            ->submitForm('Login', $credentials)\n            ->see('dashboard')\n            ->seeCredentials($credentials, 'admin')\n            ->seeIsAuthenticated('admin')\n            ->seePageIs('admin');\n    }\n}\n"
  },
  {
    "path": "tests/UsersTest.php",
    "content": "<?php\n\nuse Encore\\Admin\\Auth\\Database\\Administrator;\n\nclass UsersTest extends TestCase\n{\n    protected $user;\n\n    protected function setUp(): void\n    {\n        parent::setUp();\n\n        $this->user = Administrator::first();\n\n        $this->be($this->user, 'admin');\n    }\n\n    public function testUsersIndexPage()\n    {\n        $this->visit('admin/auth/users')\n            ->see('Administrator');\n    }\n\n    public function testCreateUser()\n    {\n        $user = [\n            'username'              => 'Test',\n            'name'                  => 'Name',\n            'password'              => '123456',\n            'password_confirmation' => '123456',\n        ];\n\n        // create user\n        $this->visit('admin/auth/users/create')\n            ->see('Create')\n            ->submitForm('Submit', $user)\n            ->seePageIs('admin/auth/users')\n            ->seeInDatabase(config('admin.database.users_table'), ['username' => 'Test']);\n\n        // assign role to user\n        $this->visit('admin/auth/users/2/edit')\n            ->see('Edit')\n            ->submitForm('Submit', ['roles' => [1]])\n            ->seePageIs('admin/auth/users')\n            ->seeInDatabase(config('admin.database.role_users_table'), ['user_id' => 2, 'role_id' => 1]);\n\n        $this->visit('admin/auth/logout')\n            ->dontSeeIsAuthenticated('admin')\n            ->seePageIs('admin/auth/login')\n            ->submitForm('Login', ['username' => $user['username'], 'password' => $user['password']])\n            ->see('dashboard')\n            ->seeIsAuthenticated('admin')\n            ->seePageIs('admin');\n\n        $this->assertTrue($this->app['auth']->guard('admin')->getUser()->isAdministrator());\n\n        $this->see('<span>Users</span>')\n            ->see('<span>Roles</span>')\n            ->see('<span>Permission</span>')\n            ->see('<span>Operation log</span>')\n            ->see('<span>Menu</span>');\n    }\n\n    public function testUpdateUser()\n    {\n        $this->visit('admin/auth/users/'.$this->user->id.'/edit')\n            ->see('Create')\n            ->submitForm('Submit', ['name' => 'test', 'roles' => [1]])\n            ->seePageIs('admin/auth/users')\n            ->seeInDatabase(config('admin.database.users_table'), ['name' => 'test']);\n    }\n\n    public function testResetPassword()\n    {\n        $password = 'odjwyufkglte';\n\n        $data = [\n            'password'              => $password,\n            'password_confirmation' => $password,\n            'roles'                 => [1],\n        ];\n\n        $this->visit('admin/auth/users/'.$this->user->id.'/edit')\n            ->see('Create')\n            ->submitForm('Submit', $data)\n            ->seePageIs('admin/auth/users')\n            ->visit('admin/auth/logout')\n            ->dontSeeIsAuthenticated('admin')\n            ->seePageIs('admin/auth/login')\n            ->submitForm('Login', ['username' => $this->user->username, 'password' => $password])\n            ->see('dashboard')\n            ->seeIsAuthenticated('admin')\n            ->seePageIs('admin');\n    }\n}\n"
  },
  {
    "path": "tests/config/admin.php",
    "content": "<?php\n\nreturn [\n\n    /*\n     * Laravel-admin name.\n     */\n    'name' => 'Laravel-admin',\n\n    /*\n     * Logo in admin panel header.\n     */\n    'logo' => '<b>Laravel</b> admin',\n\n    /*\n     * Mini-logo in admin panel header.\n     */\n    'logo-mini' => '<b>La</b>',\n\n    /*\n     * Route configuration.\n     */\n    'route' => [\n\n        'prefix' => 'admin',\n\n        'namespace' => 'App\\\\Admin\\\\Controllers',\n\n        'middleware' => ['web', 'admin'],\n    ],\n\n    /*\n     * Laravel-admin install directory.\n     */\n    'directory' => app_path('Admin'),\n\n    /*\n     * Laravel-admin html title.\n     */\n    'title' => 'Admin',\n\n    /*\n     * Use `https`.\n     */\n    'secure' => false,\n\n    /*\n     * Laravel-admin auth setting.\n     */\n    'auth' => [\n        'guards' => [\n            'admin' => [\n                'driver'   => 'session',\n                'provider' => 'admin',\n            ],\n        ],\n\n        'providers' => [\n            'admin' => [\n                'driver' => 'eloquent',\n                'model'  => Encore\\Admin\\Auth\\Database\\Administrator::class,\n            ],\n        ],\n    ],\n\n    /*\n     * Laravel-admin upload setting.\n     */\n    'upload' => [\n\n        'disk' => 'admin',\n\n        'directory' => [\n            'image' => 'images',\n            'file'  => 'files',\n        ],\n    ],\n\n    /*\n     * Laravel-admin database setting.\n     */\n    'database' => [\n\n        // Database connection for following tables.\n        'connection' => '',\n\n        // User tables and model.\n        'users_table' => 'admin_users',\n        'users_model' => Encore\\Admin\\Auth\\Database\\Administrator::class,\n\n        // Role table and model.\n        'roles_table' => 'admin_roles',\n        'roles_model' => Encore\\Admin\\Auth\\Database\\Role::class,\n\n        // Permission table and model.\n        'permissions_table' => 'admin_permissions',\n        'permissions_model' => Encore\\Admin\\Auth\\Database\\Permission::class,\n\n        // Menu table and model.\n        'menu_table' => 'admin_menu',\n        'menu_model' => Encore\\Admin\\Auth\\Database\\Menu::class,\n\n        // Pivot table for table above.\n        'operation_log_table'    => 'admin_operation_log',\n        'user_permissions_table' => 'admin_user_permissions',\n        'role_users_table'       => 'admin_role_users',\n        'role_permissions_table' => 'admin_role_permissions',\n        'role_menu_table'        => 'admin_role_menu',\n    ],\n\n    /*\n     * By setting this option to open or close operation log in laravel-admin.\n     */\n    'operation_log' => [\n\n        'enable' => true,\n\n        /*\n         * Routes that will not log to database.\n         *\n         * All method to path like: admin/auth/logs\n         * or specific method to path like: get:admin/auth/logs\n         */\n        'except' => [\n            'admin/auth/logs*',\n        ],\n    ],\n\n    /*\n     * @see https://adminlte.io/docs/2.4/layout\n     */\n    'skin' => 'skin-blue-light',\n\n    /*\n    |---------------------------------------------------------|\n    |LAYOUT OPTIONS | fixed                                   |\n    |               | layout-boxed                            |\n    |               | layout-top-nav                          |\n    |               | sidebar-collapse                        |\n    |               | sidebar-mini                            |\n    |---------------------------------------------------------|\n     */\n    'layout' => ['sidebar-mini', 'sidebar-collapse'],\n\n    /*\n     * Version displayed in footer.\n     */\n    'version' => '1.5.x-dev',\n\n    /*\n     * Settings for extensions.\n     */\n    'extensions' => [\n\n    ],\n];\n"
  },
  {
    "path": "tests/config/filesystems.php",
    "content": "<?php\n\nreturn [\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default Filesystem Disk\n    |--------------------------------------------------------------------------\n    |\n    | Here you may specify the default filesystem disk that should be used\n    | by the framework. A \"local\" driver, as well as a variety of cloud\n    | based drivers are available for your choosing. Just store away!\n    |\n    | Supported: \"local\", \"ftp\", \"s3\", \"rackspace\"\n    |\n    */\n\n    'default' => 'public',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Default Cloud Filesystem Disk\n    |--------------------------------------------------------------------------\n    |\n    | Many applications store files both locally and in the cloud. For this\n    | reason, you may specify a default \"cloud\" driver here. This driver\n    | will be bound as the Cloud disk implementation in the container.\n    |\n    */\n\n    'cloud' => 's3',\n\n    /*\n    |--------------------------------------------------------------------------\n    | Filesystem Disks\n    |--------------------------------------------------------------------------\n    |\n    | Here you may configure as many filesystem \"disks\" as you wish, and you\n    | may even configure multiple disks of the same driver. Defaults have\n    | been setup for each driver as an example of the required options.\n    |\n    */\n\n    'disks' => [\n\n        'local' => [\n            'driver' => 'local',\n            'root'   => storage_path('app'),\n        ],\n\n        'public' => [\n            'driver'     => 'local',\n            'root'       => storage_path('app/public'),\n            'visibility' => 'public',\n        ],\n\n        's3' => [\n            'driver' => 's3',\n            'key'    => 'your-key',\n            'secret' => 'your-secret',\n            'region' => 'your-region',\n            'bucket' => 'your-bucket',\n        ],\n\n        'admin' => [\n            'driver'     => 'local',\n            'root'       => public_path('uploads'),\n            'visibility' => 'public',\n            'url'        => 'http://localhost:8000/uploads/',\n        ],\n\n        'qiniu' => [\n            'driver'  => 'qiniu',\n            'domains' => [\n                'default' => 'of8kfibjo.bkt.clouddn.com', //你的七牛域名\n                'https'   => 'dn-yourdomain.qbox.me',         //你的HTTPS域名\n                'custom'  => 'static.abc.com',                //你的自定义域名\n            ],\n            'access_key' => 'tIyz5h5IDT1-PQS22iRrI4dCBEktWj76O-ls856K',  //AccessKey\n            'secret_key' => 'TCU2GuSlbzxKgnixYO_-pdo4odbXttm1RNNvEwSD',  //SecretKey\n            'bucket'     => 'laravel',  //Bucket名字\n            'notify_url' => '',  //持久化处理回调地址\n        ],\n\n        'aliyun' => [\n            'driver'     => 'oss',\n            'access_id'  => 'LTAIsOQNIDQN78Jr',\n            'access_key' => 'ChsYewaCxm1mi7AIBPRniuncEbFHNO',\n            'bucket'     => 'laravel-admin',\n            'endpoint'   => 'oss-cn-shanghai.aliyuncs.com',\n        ],\n\n    ],\n\n];\n"
  },
  {
    "path": "tests/controllers/FileController.php",
    "content": "<?php\n\nnamespace Tests\\Controllers;\n\nuse Encore\\Admin\\Controllers\\AdminController;\nuse Encore\\Admin\\Form;\nuse Encore\\Admin\\Grid;\nuse Tests\\Models\\File;\n\nclass FileController extends AdminController\n{\n    protected $title = 'Files';\n\n    /**\n     * Make a grid builder.\n     *\n     * @return Grid\n     */\n    protected function grid()\n    {\n        $grid = new Grid(new File());\n\n        $grid->id('ID')->sortable();\n\n        $grid->created_at();\n        $grid->updated_at();\n\n        return $grid;\n    }\n\n    /**\n     * Make a form builder.\n     *\n     * @return Form\n     */\n    protected function form()\n    {\n        $form = new Form(new File());\n\n        $form->display('id', 'ID');\n\n        $form->file('file1');\n        $form->file('file2');\n        $form->file('file3');\n        $form->file('file4');\n        $form->file('file5');\n        $form->file('file6');\n\n        $form->display('created_at', 'Created At');\n        $form->display('updated_at', 'Updated At');\n\n        return $form;\n    }\n}\n"
  },
  {
    "path": "tests/controllers/ImageController.php",
    "content": "<?php\n\nnamespace Tests\\Controllers;\n\nuse Encore\\Admin\\Controllers\\AdminController;\nuse Encore\\Admin\\Form;\nuse Encore\\Admin\\Grid;\nuse Tests\\Models\\Image;\n\nclass ImageController extends AdminController\n{\n    protected $title = 'Images';\n\n    /**\n     * Make a grid builder.\n     *\n     * @return Grid\n     */\n    protected function grid()\n    {\n        $grid = new Grid(new Image());\n\n        $grid->id('ID')->sortable();\n\n        $grid->created_at();\n        $grid->updated_at();\n\n        $grid->disableFilter();\n\n        return $grid;\n    }\n\n    /**\n     * Make a form builder.\n     *\n     * @return Form\n     */\n    protected function form()\n    {\n        $form = new Form(new Image());\n\n        $form->display('id', 'ID');\n\n        $form->image('image1');\n        $form->image('image2')->rotate(90);\n        $form->image('image3')->flip('v');\n        $form->image('image4')->move(null, 'renamed.jpeg');\n        $form->image('image5')->name(function ($file) {\n            return 'asdasdasdasdasd.'.$file->guessExtension();\n        });\n        $form->image('image6')->uniqueName();\n\n        $form->display('created_at', 'Created At');\n        $form->display('updated_at', 'Updated At');\n\n        return $form;\n    }\n}\n"
  },
  {
    "path": "tests/controllers/MultipleImageController.php",
    "content": "<?php\n\nnamespace Tests\\Controllers;\n\nuse Encore\\Admin\\Controllers\\AdminController;\nuse Encore\\Admin\\Form;\nuse Encore\\Admin\\Grid;\nuse Tests\\Models\\MultipleImage;\n\nclass MultipleImageController extends AdminController\n{\n    protected $title = 'Images';\n\n    /**\n     * Make a grid builder.\n     *\n     * @return Grid\n     */\n    protected function grid()\n    {\n        $grid = new Grid(new MultipleImage());\n\n        $grid->id('ID')->sortable();\n\n        $grid->created_at();\n        $grid->updated_at();\n\n        $grid->disableFilter();\n\n        return $grid;\n    }\n\n    /**\n     * Make a form builder.\n     *\n     * @return Form\n     */\n    protected function form()\n    {\n        $form = new Form(new MultipleImage());\n\n        $form->display('id', 'ID');\n\n        $form->multipleImage('pictures');\n\n        $form->display('created_at', 'Created At');\n        $form->display('updated_at', 'Updated At');\n\n        return $form;\n    }\n}\n"
  },
  {
    "path": "tests/controllers/UserController.php",
    "content": "<?php\n\nnamespace Tests\\Controllers;\n\nuse Encore\\Admin\\Controllers\\AdminController;\nuse Encore\\Admin\\Form;\nuse Encore\\Admin\\Grid;\nuse Tests\\Models\\Tag;\nuse Tests\\Models\\User;\n\nclass UserController extends AdminController\n{\n    protected $title = 'Users';\n\n    /**\n     * Make a grid builder.\n     *\n     * @return Grid\n     */\n    protected function grid()\n    {\n        $grid = new Grid(new User());\n\n        $grid->id('ID')->sortable();\n\n        $grid->username();\n        $grid->email();\n        $grid->mobile();\n        $grid->full_name();\n        $grid->avatar()->display(function ($avatar) {\n            return \"<img src='{$avatar}' />\";\n        });\n        $grid->profile()->postcode('Post code');\n        $grid->profile()->address();\n        $grid->position('Position');\n        $grid->column('profile.color');\n        $grid->profile()->start_at('开始时间');\n        $grid->profile()->end_at('结束时间');\n        $grid->column('data->json->field', 'Json Field');\n\n        $grid->column('column1_not_in_table')->display(function () {\n            return 'full name:'.$this->full_name;\n        });\n\n        $grid->column('column2_not_in_table')->display(function () {\n            return $this->email.'#'.$this->profile['color'];\n        });\n\n        $grid->tags()->display(function ($tags) {\n            $tags = collect($tags)->map(function ($tag) {\n                return \"<code>{$tag['name']}</code>\";\n            })->toArray();\n\n            return implode('', $tags);\n        });\n\n        $grid->created_at();\n        $grid->updated_at();\n\n        $grid->filter(function ($filter) {\n            $filter->like('username');\n            $filter->like('email');\n            $filter->like('profile.postcode');\n            $filter->between('profile.start_at')->datetime();\n            $filter->between('profile.end_at')->datetime();\n        });\n\n        $grid->actions(function ($actions) {\n            if ($actions->getKey() % 2 == 0) {\n                $actions->append('<a href=\"/\" class=\"btn btn-xs btn-danger\">detail</a>');\n            }\n        });\n\n        return $grid;\n    }\n\n    /**\n     * Make a form builder.\n     *\n     * @return Form\n     */\n    protected function form()\n    {\n        Form::extend('map', Form\\Field\\Map::class);\n        Form::extend('editor', Form\\Field\\Editor::class);\n\n        $form = new Form(new User());\n\n        $form->display('id', 'ID');\n        $form->text('username');\n        $form->email('email')->rules('required');\n        $form->mobile('mobile');\n        $form->image('avatar')->help('上传头像', 'fa-image');\n        $form->ignore(['password_confirmation']);\n        $form->password('password')->rules('confirmed');\n        $form->password('password_confirmation');\n\n        $form->divider();\n\n        $form->text('profile.first_name');\n        $form->text('profile.last_name');\n        $form->text('profile.postcode')->help('Please input your postcode');\n        $form->textarea('profile.address')->rows(15);\n        $form->map('profile.latitude', 'profile.longitude', 'Position');\n        $form->color('profile.color');\n        $form->datetime('profile.start_at');\n        $form->datetime('profile.end_at');\n\n        $form->multipleSelect('tags', 'Tags')->options(Tag::all()->pluck('name', 'id')); //->rules('max:10|min:3');\n\n        $form->display('created_at', 'Created At');\n        $form->display('updated_at', 'Updated At');\n\n        $form->html('<a html-field>html...</a>');\n\n        return $form;\n    }\n}\n"
  },
  {
    "path": "tests/migrations/2016_11_22_093148_create_test_tables.php",
    "content": "<?php\n\nuse Illuminate\\Database\\Migrations\\Migration;\nuse Illuminate\\Database\\Schema\\Blueprint;\n\nclass CreateTestTables extends Migration\n{\n    /**\n     * Run the migrations.\n     *\n     * @return void\n     */\n    public function up()\n    {\n        Schema::create('test_images', function (Blueprint $table) {\n            $table->increments('id');\n            $table->string('image1');\n            $table->string('image2');\n            $table->string('image3');\n            $table->string('image4');\n            $table->string('image5');\n            $table->string('image6');\n            $table->timestamps();\n        });\n\n        Schema::create('test_multiple_images', function (Blueprint $table) {\n            $table->increments('id');\n            $table->text('pictures');\n            $table->timestamps();\n        });\n\n        Schema::create('test_files', function (Blueprint $table) {\n            $table->increments('id');\n            $table->string('file1');\n            $table->string('file2');\n            $table->string('file3');\n            $table->string('file4');\n            $table->string('file5');\n            $table->string('file6');\n            $table->timestamps();\n        });\n\n        Schema::create('test_users', function (Blueprint $table) {\n            $table->increments('id');\n            $table->string('username');\n            $table->string('email');\n            $table->string('mobile')->nullable();\n            $table->string('avatar')->nullable();\n            $table->string('password');\n            $table->json('data')->nullable();\n            $table->timestamps();\n        });\n\n        Schema::create('test_user_profiles', function (Blueprint $table) {\n            $table->increments('id');\n            $table->string('user_id');\n            $table->string('first_name')->nullable();\n            $table->string('last_name')->nullable();\n            $table->string('postcode')->nullable();\n            $table->string('address')->nullable();\n            $table->string('latitude')->nullable();\n            $table->string('longitude')->nullable();\n            $table->string('color')->nullable();\n            $table->timestamp('start_at')->nullable();\n            $table->timestamp('end_at')->nullable();\n\n            $table->timestamps();\n        });\n\n        Schema::create('test_tags', function (Blueprint $table) {\n            $table->increments('id');\n            $table->string('name');\n            $table->timestamps();\n        });\n\n        Schema::create('test_user_tags', function (Blueprint $table) {\n            $table->integer('user_id');\n            $table->integer('tag_id');\n            $table->index(['user_id', 'tag_id']);\n            $table->timestamps();\n        });\n    }\n\n    /**\n     * Reverse the migrations.\n     *\n     * @return void\n     */\n    public function down()\n    {\n        Schema::dropIfExists('test_images');\n        Schema::dropIfExists('test_multiple_images');\n        Schema::dropIfExists('test_files');\n        Schema::dropIfExists('test_users');\n        Schema::dropIfExists('test_user_profiles');\n        Schema::dropIfExists('test_tags');\n        Schema::dropIfExists('test_user_tags');\n    }\n}\n"
  },
  {
    "path": "tests/models/File.php",
    "content": "<?php\n\nnamespace Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass File extends Model\n{\n    protected $table = 'test_files';\n}\n"
  },
  {
    "path": "tests/models/Image.php",
    "content": "<?php\n\nnamespace Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass Image extends Model\n{\n    protected $table = 'test_images';\n}\n"
  },
  {
    "path": "tests/models/MultipleImage.php",
    "content": "<?php\n\nnamespace Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass MultipleImage extends Model\n{\n    protected $table = 'test_multiple_images';\n\n    public function setPicturesAttribute($pictures)\n    {\n        if (is_array($pictures)) {\n            $this->attributes['pictures'] = json_encode($pictures);\n        }\n    }\n\n    public function getPicturesAttribute($pictures)\n    {\n        return json_decode($pictures, true) ?: [];\n    }\n}\n"
  },
  {
    "path": "tests/models/Profile.php",
    "content": "<?php\n\nnamespace Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass Profile extends Model\n{\n    protected $table = 'test_user_profiles';\n\n    public function user()\n    {\n        return $this->belongsTo(User::class, 'user_id');\n    }\n}\n"
  },
  {
    "path": "tests/models/Tag.php",
    "content": "<?php\n\nnamespace Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass Tag extends Model\n{\n    protected $table = 'test_tags';\n\n    public function users()\n    {\n        return $this->belongsToMany(User::class, 'test_user_tags', 'tag_id', 'user_id');\n    }\n}\n"
  },
  {
    "path": "tests/models/Tree.php",
    "content": "<?php\n\nnamespace Tests\\Models;\n\nuse Encore\\Admin\\Traits\\ModelTree;\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass Tree extends Model\n{\n    use ModelTree;\n\n    /**\n     * Create a new Eloquent model instance.\n     *\n     * @param array $attributes\n     */\n    public function __construct(array $attributes = [])\n    {\n        $connection = config('admin.database.connection') ?: config('database.default');\n\n        $this->setConnection($connection);\n\n        $this->setTable(config('admin.database.menu_table'));\n\n        parent::__construct($attributes);\n    }\n}\n"
  },
  {
    "path": "tests/models/User.php",
    "content": "<?php\n\nnamespace Tests\\Models;\n\nuse Illuminate\\Database\\Eloquent\\Model;\n\nclass User extends Model\n{\n    protected $table = 'test_users';\n\n    protected $appends = ['full_name', 'position'];\n\n    protected $casts = ['data' => 'array'];\n\n    public function profile()\n    {\n        return $this->hasOne(Profile::class, 'user_id');\n    }\n\n    public function getFullNameAttribute()\n    {\n        return \"{$this->profile['first_name']} {$this->profile['last_name']}\";\n    }\n\n    public function getPositionAttribute()\n    {\n        return \"{$this->profile->latitude} {$this->profile->longitude}\";\n    }\n\n    public function tags()\n    {\n        return $this->belongsToMany(Tag::class, 'test_user_tags', 'user_id', 'tag_id');\n    }\n}\n"
  },
  {
    "path": "tests/routes.php",
    "content": "<?php\n\nRoute::group([\n    'prefix'     => config('admin.route.prefix'),\n    'namespace'  => 'Tests\\Controllers',\n    'middleware' => ['web', 'admin'],\n], function ($router) {\n    $router->resource('images', ImageController::class);\n    $router->resource('multiple-images', MultipleImageController::class);\n    $router->resource('files', FileController::class);\n    $router->resource('users', UserController::class);\n});\n"
  },
  {
    "path": "tests/seeds/UserTableSeeder.php",
    "content": "<?php\n\nnamespace Tests\\Seeds;\n\nuse Illuminate\\Database\\Seeder;\n\nclass UserTableSeeder extends Seeder\n{\n    public function run()\n    {\n        factory(\\Tests\\Models\\User::class, 50)\n            ->create()\n            ->each(function ($u) {\n                $u->profile()->save(factory(\\Tests\\Models\\Profile::class)->make());\n                $u->tags()->saveMany(factory(\\Tests\\Models\\Tag::class, 5)->make());\n                $u->data = ['json' => ['field' => random_int(0, 50)]];\n            });\n    }\n}\n"
  },
  {
    "path": "tests/seeds/factory.php",
    "content": "<?php\n\nuse Faker\\Generator as Faker;\nuse Illuminate\\Database\\Eloquent\\Factory;\n\n$factory = app(Factory::class);\n\n$factory->define(Tests\\Models\\User::class, function (Faker $faker) {\n    return [\n        'username' => $faker->userName,\n        'email'    => $faker->email,\n        'mobile'   => $faker->phoneNumber,\n        'avatar'   => $faker->imageUrl(),\n        'password' => '$2y$10$U2WSLymU6eKJclK06glaF.Gj3Sw/ieDE3n7mJYjKEgDh4nzUiSESO', // bcrypt(123456)\n    ];\n});\n\n$factory->define(Tests\\Models\\Profile::class, function (Faker $faker) {\n    return [\n        'first_name' => $faker->firstName,\n        'last_name'  => $faker->lastName,\n        'postcode'   => $faker->postcode,\n        'address'    => $faker->address,\n        'latitude'   => $faker->latitude,\n        'longitude'  => $faker->longitude,\n        'color'      => $faker->hexColor,\n        'start_at'   => $faker->dateTime,\n        'end_at'     => $faker->dateTime,\n    ];\n});\n\n$factory->define(Tests\\Models\\Tag::class, function (Faker $faker) {\n    return [\n        'name' => $faker->word,\n    ];\n});\n"
  }
]