├── .auto-changelog ├── .editorconfig ├── .eslintrc ├── .gitignore ├── .nvmrc ├── .prettierrc ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── composer.json ├── config └── nova-button.php ├── dist ├── css │ └── field.css ├── js │ └── field.js └── mix-manifest.json ├── nova.mix.js ├── package.json ├── resources ├── css │ └── field.css ├── field.js └── js │ ├── components │ ├── ConfirmModal.vue │ ├── DetailField.vue │ ├── FormField.vue │ ├── IndexField.vue │ └── NovaButton.vue │ ├── field.js │ └── queue.js ├── routes └── api.php ├── src ├── Button.php ├── Events │ └── ButtonClick.php ├── FieldServiceProvider.php └── Http │ └── Controllers │ └── ButtonController.php ├── webpack.mix.js └── yarn.lock /.auto-changelog: -------------------------------------------------------------------------------- 1 | { 2 | "output": "CHANGELOG.md", 3 | "template": "keepachangelog", 4 | "unreleased": true, 5 | "commitLimit": false, 6 | "sortCommits": "date-desc" 7 | } 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | ; This file is for unifying the coding style for different editors and IDEs. 2 | ; More information at http://editorconfig.org 3 | 4 | root = true 5 | 6 | [*] 7 | charset = utf-8 8 | end_of_line = lf 9 | insert_final_newline = true 10 | indent_size = 4 11 | indent_style = space 12 | max_line_length = 120 13 | trim_trailing_whitespace = true 14 | 15 | [*.md] 16 | trim_trailing_whitespace = false 17 | 18 | [*.{js,vue}] 19 | indent_size = 2 20 | 21 | [*.yml] 22 | indent_size = 2 23 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "eslint:recommended", 4 | "plugin:vue/essential", 5 | "prettier" 6 | ], 7 | "parserOptions": { 8 | "ecmaVersion": 2017 9 | }, 10 | "globals": { 11 | "Nova": true, 12 | "_": true 13 | }, 14 | "env": { 15 | "browser": true, 16 | "node": true 17 | }, 18 | "rules": { 19 | "vue/html-indent": ["error", 2] 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /vendor 3 | /node_modules 4 | package-lock.json 5 | composer.phar 6 | composer.lock 7 | phpunit.xml 8 | .phpunit.result.cache 9 | .DS_Store 10 | Thumbs.db 11 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | v18.1.0 2 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "singleQuote": true, 4 | "tabWidth": 2, 5 | "trailingComma": "es5" 6 | } 7 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). 9 | 10 | ## [v1.0.27](https://github.com/sietse85/nova-button/compare/v1.0.26...v1.0.27) 11 | 12 | ### Commits 13 | 14 | - Update ButtonController.php [`ea7baa3`](https://github.com/sietse85/nova-button/commit/ea7baa3e8e95fb82d555c7cd60a1e8e3e7d34598) 15 | - Fix triggerAction crash when using soft deletes [`ef6bec7`](https://github.com/sietse85/nova-button/commit/ef6bec73a328fe068bd4898afc6f902726d9f57f) 16 | 17 | ## [v1.0.26](https://github.com/sietse85/nova-button/compare/v1.0.25...v1.0.26) - 2023-08-21 18 | 19 | ### Merged 20 | 21 | - Add UUID support for Nova Routes methods [`#31`](https://github.com/sietse85/nova-button/pull/31) 22 | 23 | ### Commits 24 | 25 | - updated changelog [`07a7984`](https://github.com/sietse85/nova-button/commit/07a7984f8e53282d3008a2f10c44a013b18fc3de) 26 | - Update version numbers [`23182a9`](https://github.com/sietse85/nova-button/commit/23182a94c36f15661759b3ff00cea348059c5da9) 27 | - Add ability to style confirm modal [`9d8a537`](https://github.com/sietse85/nova-button/commit/9d8a537e836953ccaa3f71c49b26a20ff3b4cfc6) 28 | - Change Detail and Edit function to allow strings [`65dc3b2`](https://github.com/sietse85/nova-button/commit/65dc3b24cf8246a4a596ca159d8ffeb56d9efdc8) 29 | 30 | ## [v1.0.25](https://github.com/sietse85/nova-button/compare/v1.0.24...v1.0.25) - 2023-01-06 31 | 32 | ### Commits 33 | 34 | - Navigate to link after action or event is run [`0f1efe0`](https://github.com/sietse85/nova-button/commit/0f1efe0040dc71797872b63e143d176b9008ab5a) 35 | 36 | ## [v1.0.24](https://github.com/sietse85/nova-button/compare/v1.0.23...v1.0.24) - 2022-12-23 37 | 38 | ### Commits 39 | 40 | - Add indexAlignRight function [`3793e53`](https://github.com/sietse85/nova-button/commit/3793e53cd557c20a56083d8a821c83880270a165) 41 | 42 | ## [v1.0.23](https://github.com/sietse85/nova-button/compare/v1.0.22...v1.0.23) - 2022-11-02 43 | 44 | ### Commits 45 | 46 | - Remove PHP 8 "mixed" usage from ButtonController.php [`900501b`](https://github.com/sietse85/nova-button/commit/900501b3a21626b264409ebf5d08d26f19baa2f1) 47 | 48 | ## [v1.0.22](https://github.com/sietse85/nova-button/compare/v1.0.21...v1.0.22) - 2022-10-10 49 | 50 | ### Commits 51 | 52 | - Fix publish tag [`ff40371`](https://github.com/sietse85/nova-button/commit/ff40371414e8ede214a537565cd825c6cdda75c7) 53 | 54 | ## [v1.0.21](https://github.com/sietse85/nova-button/compare/v1.0.20...v1.0.21) - 2022-09-30 55 | 56 | ### Commits 57 | 58 | - [FIX] Fix confirm modal overlay [`7e83ec3`](https://github.com/sietse85/nova-button/commit/7e83ec341bbd63154c90501978c60960c4392a55) 59 | 60 | ## [v1.0.20](https://github.com/sietse85/nova-button/compare/v1.0.19...v1.0.20) - 2022-08-30 61 | 62 | ## [v1.0.19](https://github.com/sietse85/nova-button/compare/v1.0.18...v1.0.19) - 2022-08-28 63 | 64 | ### Commits 65 | 66 | - shorten code handeClick [`fdf078b`](https://github.com/sietse85/nova-button/commit/fdf078bdd097274dd7456c5fff64d3304c3791ac) 67 | - Add support for redirect and openInNewTab Action responses [`c056c50`](https://github.com/sietse85/nova-button/commit/c056c50cfd08d0a6ff93e28e48c15c14ed342022) 68 | - Update NovaButton.vue [`dd3b919`](https://github.com/sietse85/nova-button/commit/dd3b919a9ac9a09fc080239c2c723ea9e7066c39) 69 | - Update NovaButton.vue [`23e3283`](https://github.com/sietse85/nova-button/commit/23e32839a9d84e75fc4838a769719e87d3042ba6) 70 | 71 | ## [v1.0.18](https://github.com/sietse85/nova-button/compare/v1.0.17...v1.0.18) - 2022-08-10 72 | 73 | ### Commits 74 | 75 | - V 1.0.18 [`3d0e80a`](https://github.com/sietse85/nova-button/commit/3d0e80ad583448b7b9e38b887c06a8682115d72e) 76 | - Allow public access to Button::route [`d0a5469`](https://github.com/sietse85/nova-button/commit/d0a5469d7c41a6155f68cc998e28d0046bad2d0d) 77 | 78 | ## [v1.0.17](https://github.com/sietse85/nova-button/compare/v1.0.16...v1.0.17) - 2022-08-01 79 | 80 | ### Commits 81 | 82 | - Resource should not be string type [`285cdf6`](https://github.com/sietse85/nova-button/commit/285cdf6ab8d18c88f7beecaa5f3ac11bb68b2861) 83 | - Updated incorrect Classes documentation [`6319b02`](https://github.com/sietse85/nova-button/commit/6319b02a9c2e7d16c1084a1c31521bcc536a91bb) 84 | 85 | ## [v1.0.16](https://github.com/sietse85/nova-button/compare/v1.0.15...v1.0.16) - 2022-07-07 86 | 87 | ### Commits 88 | 89 | - fix routing of Nova routes using Inertia [`ba303a7`](https://github.com/sietse85/nova-button/commit/ba303a7c8e67806a1e7f53461404112147940533) 90 | 91 | ## [v1.0.15](https://github.com/sietse85/nova-button/compare/v1.0.14...v1.0.15) - 2022-06-27 92 | 93 | ### Commits 94 | 95 | - Fix reloading. Use correct route method [`80b06c2`](https://github.com/sietse85/nova-button/commit/80b06c234bbd3529491f9f6e7030738d71bdbe7a) 96 | - Update package.json [`5b3028d`](https://github.com/sietse85/nova-button/commit/5b3028d64235bb1d3cc934dadca00fb7df4b1d4e) 97 | - Fix typo in getting buttonKey [`8473caf`](https://github.com/sietse85/nova-button/commit/8473caff120ad1a71c529a34c0d50090374cd02e) 98 | - Replace Vue Router to InertiaJS [`839fd72`](https://github.com/sietse85/nova-button/commit/839fd72e1bcc91086c8ee9e8e1ea519d2bb77cb6) 99 | 100 | ## [v1.0.14](https://github.com/sietse85/nova-button/compare/v1.0.13...v1.0.14) - 2022-06-08 101 | 102 | ### Commits 103 | 104 | - Fix property not nullable [`ea1c76c`](https://github.com/sietse85/nova-button/commit/ea1c76c5cd59d007d899561637e7abfcd202e6a3) 105 | - Update version [`bdaf9c8`](https://github.com/sietse85/nova-button/commit/bdaf9c8d18983f7f7e11137e9dd73d49eddc8bf7) 106 | - Fix exception when key is null given to default event [`abcf757`](https://github.com/sietse85/nova-button/commit/abcf757a4b887a24d6bf6aeeacaf0eda7e33b8bd) 107 | 108 | ## [v1.0.13](https://github.com/sietse85/nova-button/compare/v1.0.12...v1.0.13) - 2022-06-07 109 | 110 | ### Commits 111 | 112 | - Fix 'cannot use dynamic classname' [`4047b39`](https://github.com/sietse85/nova-button/commit/4047b39a2412556023bf65c1a84cd93bdd82fda2) 113 | - PHP 7.* Error fix: Cannot Use Dynamic Class Name [`afe4031`](https://github.com/sietse85/nova-button/commit/afe4031255f1ea9e4375ee6859f920e2ac123d9b) 114 | 115 | ## [v1.0.12](https://github.com/sietse85/nova-button/compare/v1.0.11...v1.0.12) - 2022-06-06 116 | 117 | ### Merged 118 | 119 | - Union return types not supported in PHP 7.* [`#6`](https://github.com/sietse85/nova-button/pull/6) 120 | 121 | ### Commits 122 | 123 | - update version [`cf6d60f`](https://github.com/sietse85/nova-button/commit/cf6d60f4881bf618889ef52e6777113ccc2b95c6) 124 | 125 | ## [v1.0.11](https://github.com/sietse85/nova-button/compare/v1.0.10...v1.0.11) - 2022-06-05 126 | 127 | ### Commits 128 | 129 | - Update version [`ad76df4`](https://github.com/sietse85/nova-button/commit/ad76df4c35695f81dc71cca770f55ce2982e3bc7) 130 | - Remove require of vue-toasted [`02ab5df`](https://github.com/sietse85/nova-button/commit/02ab5dfb8784eaec7fb11fa2d40075de8f013f9b) 131 | 132 | ## [v1.0.10](https://github.com/sietse85/nova-button/compare/v1.0.9...v1.0.10) - 2022-06-05 133 | 134 | ### Commits 135 | 136 | - update version [`bc168f8`](https://github.com/sietse85/nova-button/commit/bc168f8fe9aac4027699bf1c001e09d271617664) 137 | - Fix Collection given to Action, show Toasted message on completion [`0c8445e`](https://github.com/sietse85/nova-button/commit/0c8445ebb5d0feb1822309c3496ef189dbe217bb) 138 | 139 | ## [v1.0.9](https://github.com/sietse85/nova-button/compare/v1.0.8...v1.0.9) - 2022-06-05 140 | 141 | ### Commits 142 | 143 | - Update version [`4575dad`](https://github.com/sietse85/nova-button/commit/4575dadbe58b2db88838cf5d58e599925ef44af7) 144 | - Add action support [`ec6e7ac`](https://github.com/sietse85/nova-button/commit/ec6e7aca6d35715671fd35b2be845f9547820b57) 145 | 146 | ## [v1.0.8](https://github.com/sietse85/nova-button/compare/v1.0.7...v1.0.8) - 2022-06-02 147 | 148 | ### Commits 149 | 150 | - Update version [`bafb124`](https://github.com/sietse85/nova-button/commit/bafb124fea01bccdd0570f851318586f70f77124) 151 | - PHP 7.* compatibility [`2b16a7b`](https://github.com/sietse85/nova-button/commit/2b16a7bd86407606ed737059df66fb86cec9f983) 152 | 153 | ## [v1.0.7](https://github.com/sietse85/nova-button/compare/v1.0.6...v1.0.7) - 2022-05-31 154 | 155 | ### Commits 156 | 157 | - Changelog [`0bf96f7`](https://github.com/sietse85/nova-button/commit/0bf96f70c2bab25724c2e65d3df8f34892d1d2cd) 158 | - Authorize correctly [`16ebdfd`](https://github.com/sietse85/nova-button/commit/16ebdfd49e2fdb88c357e04ad3a04935b83c7bfd) 159 | - Not sure how that came in here [`d33c717`](https://github.com/sietse85/nova-button/commit/d33c717623e361c8bee13fc9be2621e1ab166f17) 160 | 161 | ## [v1.0.6](https://github.com/sietse85/nova-button/compare/v1.0.5...v1.0.6) - 2022-05-30 162 | 163 | ### Commits 164 | 165 | - Update version [`4124372`](https://github.com/sietse85/nova-button/commit/4124372adaa3e5ed31bdda492f33e9038f8be885) 166 | - Fix config not being published [`b5d235e`](https://github.com/sietse85/nova-button/commit/b5d235ef9744596f9edbdd15fef27c04893c44a0) 167 | 168 | ## [v1.0.5](https://github.com/sietse85/nova-button/compare/v1.0.4...v1.0.5) - 2022-05-27 169 | 170 | ### Commits 171 | 172 | - PSR-12 standard instead of PSR-2 [`46b086e`](https://github.com/sietse85/nova-button/commit/46b086e105629c820bb74486a0993100b1640286) 173 | - Add Nova version requirement [`d530ab9`](https://github.com/sietse85/nova-button/commit/d530ab9a5e95d8f069f6bc42046ea2ac528ab9ab) 174 | 175 | ## [v1.0.4](https://github.com/sietse85/nova-button/compare/v1.0.3...v1.0.4) - 2022-05-20 176 | 177 | ### Commits 178 | 179 | - Changelog [`15b2786`](https://github.com/sietse85/nova-button/commit/15b2786a7a1a10a8bcbabb0d3e1c847d1a8d8f6e) 180 | - Fix modal / confirm functionality [`9442a34`](https://github.com/sietse85/nova-button/commit/9442a34926d7c6a6225ca2b788e89991b195d416) 181 | 182 | ## [v1.0.3](https://github.com/sietse85/nova-button/compare/v1.0.2...v1.0.3) - 2022-05-20 183 | 184 | ### Commits 185 | 186 | - update changelog [`070865a`](https://github.com/sietse85/nova-button/commit/070865a89360fbec3f8c203d4a4714fa6bf51c0c) 187 | - Update version [`a7c724c`](https://github.com/sietse85/nova-button/commit/a7c724c0e8e4cd36a2f474505835a792434752ca) 188 | - Add new JS build [`0e7b07d`](https://github.com/sietse85/nova-button/commit/0e7b07dea84f125e64886eafa4e861fda1f0aa5c) 189 | - Prevent clicks from going through parent elements [`18bfcb0`](https://github.com/sietse85/nova-button/commit/18bfcb008eeb2963be24615c991d854360b72223) 190 | - Update changelog [`fc2f3c1`](https://github.com/sietse85/nova-button/commit/fc2f3c108933b21e3d68d590defccb427058fa9b) 191 | 192 | ## [v1.0.2](https://github.com/sietse85/nova-button/compare/v1.0.0...v1.0.2) - 2022-05-20 193 | 194 | ### Commits 195 | 196 | - Change PHP required version [`a6ab530`](https://github.com/sietse85/nova-button/commit/a6ab530e1d66244f769053c78afc7ce3ba66e84b) 197 | - Add new version [`a4368e9`](https://github.com/sietse85/nova-button/commit/a4368e9a130e5b36bdb303d910213c0eeab47622) 198 | - Add nova4 in description [`5af90d4`](https://github.com/sietse85/nova-button/commit/5af90d4aae4f8490c8dd2df8e32aeadcd607c6ee) 199 | 200 | ## v1.0.0 - 2022-05-20 201 | 202 | ### Commits 203 | 204 | - Add new version [`d1832ba`](https://github.com/sietse85/nova-button/commit/d1832ba268fed78ab0959fb44ce579e33c73835d) 205 | - Add Nova4 support [`3b3f7aa`](https://github.com/sietse85/nova-button/commit/3b3f7aaf6eacf8467d5beb79400f27a46a9447c5) 206 | - Build and empty formfield [`f8e8bd0`](https://github.com/sietse85/nova-button/commit/f8e8bd066e5b447fd66fd4c589a50108e72e60cf) 207 | - Rename button [`447e2a5`](https://github.com/sietse85/nova-button/commit/447e2a5b3ba70d3a5fa1e5e05215020341cb612b) 208 | - Add field basics [`bef651e`](https://github.com/sietse85/nova-button/commit/bef651ef4d656734ac6e4bda9c7d05c8905a5cb4) 209 | - initial [`aca0e3b`](https://github.com/sietse85/nova-button/commit/aca0e3ba128afb4e1559026b10c9d9228349b93f) 210 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Contributions are **welcome** and will be fully **credited**. 4 | 5 | Please read and understand the contribution guide before creating an issue or pull request. 6 | 7 | ## Etiquette 8 | 9 | This project is open source, and as such, the maintainers give their free time to build and maintain the source code 10 | held within. They make the code freely available in the hope that it will be of use to other developers. It would be 11 | extremely unfair for them to suffer abuse or anger for their hard work. 12 | 13 | Please be considerate towards maintainers when raising issues or presenting pull requests. Let's show the 14 | world that developers are civilized and selfless people. 15 | 16 | It's the duty of the maintainer to ensure that all submissions to the project are of sufficient 17 | quality to benefit the project. Many developers have different skillsets, strengths, and weaknesses. Respect the maintainer's decision, and do not be upset or abusive if your submission is not used. 18 | 19 | ## Viability 20 | 21 | When requesting or submitting new features, first consider whether it might be useful to others. Open 22 | source projects are used by many developers, who may have entirely different needs to your own. Think about 23 | whether or not your feature is likely to be used by other users of the project. 24 | 25 | ## Procedure 26 | 27 | Before filing an issue: 28 | 29 | - Attempt to replicate the problem, to ensure that it wasn't a coincidental incident. 30 | - Check to make sure your feature suggestion isn't already present within the project. 31 | - Check the pull requests tab to ensure that the bug doesn't have a fix in progress. 32 | - Check the pull requests tab to ensure that the feature isn't already in progress. 33 | 34 | Before submitting a pull request: 35 | 36 | - Check the codebase to ensure that your feature doesn't already exist. 37 | - Check the pull requests to ensure that another person hasn't already submitted the feature or fix. 38 | 39 | ## Requirements 40 | 41 | If the project maintainer has any additional requirements, you will find them listed here. 42 | 43 | - **PSR-12 Coding Standard** 44 | 45 | - **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date. 46 | 47 | - **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option. 48 | 49 | - **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. 50 | 51 | - **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please [squash them](http://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages) before submitting. 52 | 53 | **Happy coding**! 54 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Laravel Nova 4+ Button 2 | 3 | A Nova package for rendering buttons on index, detail and lens views. 4 | 5 | Use buttons to trigger backend events, navigate Nova routes or visit links. 6 | 7 | ![example-users](https://user-images.githubusercontent.com/57711725/152637226-e7047831-b726-4940-95c9-617db4d42de4.png) 8 | 9 | > **This package is a continuation of [dillingham/nova-button](https://github.com/dillingham/nova-button).** 10 | > 11 | > Created to be compatible with Nova 4.0+ 12 | 13 | ## Requirements 14 | 15 | | What | Minimum | 16 | |---------|---------| 17 | | PHP | \>=7.4 | 18 | | Laravel | \>=8.0 | 19 | | Nova | \>=4.0 | 20 | 21 | ## Installation 22 | 23 | You can install this package by running the following command: 24 | 25 | ```bash 26 | composer require sietse85/nova-button 27 | ``` 28 | 29 | To publish the config file, run the following command: 30 | 31 | ```bash 32 | php artisan vendor:publish --tag="nova-button-config" 33 | ``` 34 | 35 | ## Usage 36 | 37 | ```php 38 | use Sietse85\NovaButton\Button; 39 | ``` 40 | 41 | ```php 42 | public function fields(Request $request) 43 | { 44 | return [ 45 | ID::make('ID', 'id')->sortable(), 46 | Text::make('Name', 'name'), 47 | Button::make('Notify'), 48 | ]; 49 | } 50 | ``` 51 | 52 | ### Quick links 53 | 54 | * [Confirm](#confirm) 55 | * [Reload](#reload) 56 | * [Action](#action) 57 | * [Events](#events) 58 | * [Texts](#texts) 59 | * [State](#state) 60 | * [Feedback](#feedback) 61 | * [Nova routes](#nova-routes) 62 | * [Links](#links) 63 | * [Classes](#classes) 64 | * [Styles](#styles) 65 | * [Examples](#examples) 66 | 67 | --- 68 | 69 | ### Confirm 70 | 71 | You can require a confirmation for destructive actions: 72 | 73 | ```php 74 | Button::make('Cancel Account')->confirm('Are you sure?'), 75 | Button::make('Cancel Account')->confirm('Confirmation', 'Are you sure you want to cancel your account?'), 76 | Button::make('Cancel Account')->confirm('Confirmation', 'Are you sure you want to cancel your account?', 'Cancel'), 77 | ``` 78 | 79 | ### Reload 80 | 81 | You can reload the page after all events have finished. 82 | 83 | ```php 84 | Button::make('Notify')->reload() 85 | ``` 86 | If you click multiple buttons, reloading will wait for all buttons to finish. 87 | 88 | If an error occurs, the page will not be reloaded. 89 | 90 | ### Action 91 | 92 | You can trigger an action now. No ActionFields can be used. Will trigger for current resource only. Handle will be called immediately. 93 | 94 | ```php 95 | Button::make('Send mail')->action(SendConfirmationMail::class) 96 | ``` 97 | 98 | If for some reason the Model for the action is not resolved correctly you can use `modelForAction` to correct it. 99 | 100 | 101 | ### Events 102 | 103 | By default, clicking the button will trigger an event via AJAX. 104 | 105 | Default event: `Sietse85\NovaButton\Events\ButtonClick`. 106 | 107 | The event will receive the resource model it was triggered from and the key: 108 | 109 | * `$event->resource` = `model` 110 | * `$event->key` = `"notify"` 111 | 112 | You can override the key: 113 | 114 | ```php 115 | Button::make('Notify', 'notify-some-user') 116 | ``` 117 | 118 | And also the event: 119 | 120 | ```php 121 | Button::make('Notify')->event(App\Events\NotifyRequested::class) 122 | ``` 123 | 124 | You can listen to the event by creating a listener and registering it in your `EventServiceProvider`. 125 | 126 | ### Texts 127 | 128 | #### Title 129 | 130 | You can set the title attribute for the button: 131 | 132 | ```php 133 | Button::make('Notify')->title('Button title') 134 | ``` 135 | 136 | #### Label 137 | 138 | You can set the label for the button, which is shown on the detail, create and update views: 139 | 140 | ```php 141 | Button::make('Notify')->label('Button label') 142 | ``` 143 | 144 | #### Index name 145 | 146 | You can set the index name for the button, which is shown on the index view as the table header: 147 | 148 | ```php 149 | Button::make('Notify')->indexName('Actions') 150 | ``` 151 | 152 | Default is set to the button name. You can also pass `null` to have no index name. 153 | 154 | ### State 155 | 156 | #### Visibility 157 | 158 | You can conditionally show the button: 159 | 160 | ```php 161 | Button::make('Activate')->visible($this->is_active === false), 162 | Button::make('Deactivate')->visible($this->is_active === true), 163 | ``` 164 | 165 | Or, if you only want specific users to see the button: 166 | 167 | ```php 168 | Button::make('Notify')->visible($request->user()->can('notifyUser', $this)) 169 | ``` 170 | 171 | Of course you can also use Nova's builtin methods, like for [authorization](https://nova.laravel.com/docs/3.0/resources/authorization.html#fields) 172 | or to limit visibility to [specific views](https://nova.laravel.com/docs/3.0/resources/fields.html#showing-hiding-fields). 173 | 174 | If you want to show a button on the create or update views you can simply use Nova's builtin methods: 175 | 176 | ```php 177 | Button::make('Notify')->showOnCreating()->showOnUpdating() 178 | ``` 179 | 180 | #### Disabled 181 | 182 | You can disable the button: 183 | 184 | ```php 185 | Button::make('Notify')->disabled() 186 | Button::make('Notify')->disabled($this->is_complete === false) 187 | ``` 188 | 189 | ### Feedback 190 | 191 | When using events, you might want to provide visual feedback to the end user. This is especially useful for long running listeners. 192 | 193 | ```php 194 | Button::make('Notify') 195 | ->loadingText('Sending...') 196 | ->successText('Sent!') 197 | ->errorText('Something went wrong...') 198 | ``` 199 | 200 | There are 3 events and for each event you can provide the text and style: 201 | 202 | | Event | Text | Style | 203 | |-----------|------------------------------------------|----------------------------------| 204 | | `loading` | `->loadingText('Sending...')` | `->loadingStyle('grey-outline')` | 205 | | `success` | `->successText('Done!')` | `->successStyle('success')` | 206 | | `error` | `->errorText('Something went wrong...')` | `->errorStyle('danger')` | 207 | 208 | The defaults are defined in the [config file](https://github.com/sietse85/nova-button/blob/main/config/nova-button.php). 209 | 210 | ### Nova routes 211 | 212 | You can also choose to navigate to any Nova route: 213 | 214 | ```php 215 | Button::make('Text')->index(App\Nova\User::class) 216 | Button::make('Text')->detail(App\Nova\User::class, $this->user_id) 217 | Button::make('Text')->create(App\Nova\User::class) 218 | Button::make('Text')->edit(App\Nova\User::class, $this->user_id) 219 | Button::make('Text')->lens(App\Nova\User::class, 'users-without-confirmation') 220 | ``` 221 | 222 | It's also possible to use a resource's filters: 223 | 224 | ```php 225 | Button::make('Text') 226 | ->index(App\Nova\Order::class) 227 | ->withFilters([ 228 | App\Nova\Filters\UserOrders::class => $this->user_id, 229 | App\Nova\Filters\OrderStatus::class => 'active', 230 | ]) 231 | ``` 232 | 233 | ### Links 234 | 235 | You can configure the button to open external links: 236 | 237 | ```php 238 | Button::make('Text')->link('https://nova.laravel.com') 239 | Button::make('Text')->link('https://nova.laravel.com', '_self') 240 | ``` 241 | 242 | ### Classes 243 | 244 | The button uses the following classes that you can style to your liking: 245 | 246 | ```css 247 | .nova-button 248 | .nova-button-{resource-name} 249 | .nova-button-success 250 | .nova-button-error 251 | .nova-button-loading 252 | ``` 253 | 254 | You can also add more classes to a button: 255 | 256 | ```php 257 | // One class 258 | Button::make('Notify')->classes(['some-class']) 259 | 260 | // Or multiple classes 261 | Button::make('Notify')->classes(['some-class', 'another-class']) 262 | ``` 263 | 264 | You can also add more classes to the confirm-modal inner-div: 265 | 266 | ```php 267 | // One class 268 | Button::make('Notify')->confirm('sure?')->modalClasses(['some-class']) 269 | 270 | // Or multiple classes 271 | Button::make('Notify')->confirm('sure?')->modalClasses(['some-class', 'another-class']) 272 | ``` 273 | 274 | ### Styles 275 | 276 | This package uses [tailwind-css](https://tailwindcss.com) classes. The default class used is the `link` class. 277 | 278 | You can define the class the button should use: 279 | 280 | ```php 281 | Button::make('Delete')->style('danger') 282 | ``` 283 | 284 | The default available classes are as follows: 285 | 286 | | Fill | Outline | Link | 287 | |---------|-----------------|--------------| 288 | | primary | primary-outline | primary-link | 289 | | success | success-outline | success-link | 290 | | warning | warning-outline | warning-link | 291 | | danger | danger-outline | danger-link | 292 | | info | info-outline | info-link | 293 | | grey | grey-outline | grey-link | 294 | 295 | The passed key refers to one of the classes defined in the [config file](https://github.com/sietse85/nova-button/blob/main/config/nova-button.php). 296 | You are free to change these classes or add your own. 297 | 298 | ## Examples 299 | 300 | ### Lenses 301 | 302 | You can use a button with [lenses](https://nova.laravel.com/docs/3.0/lenses/defining-lenses.html). 303 | 304 | ![lens-example](https://user-images.githubusercontent.com/57711725/152637243-ebd753c2-5eda-4749-b8ba-c98ceb162e5b.png) 305 | 306 | First set up the lens: 307 | 308 | ```php 309 | select(['users.id', 'users.name']) 319 | ->whereNull('email_verified_at'); 320 | } 321 | 322 | public function fields(Request $request) 323 | { 324 | return [ 325 | ID::make('ID', 'id'), 326 | Text::make('Name', 'name'), 327 | Button::make('Mark As Confirmed'), 328 | ]; 329 | } 330 | } 331 | ``` 332 | 333 | Next, register a listener for the `Sietse85\NovaButton\Events\ButtonClick` event in your [EventServiceProvider](https://laravel.com/docs/7.x/events): 334 | 335 | ```php 336 | key == 'mark-as-confirmed') { 347 | $event->resource->email_verified_at = now(); 348 | $event->resource->save(); 349 | } 350 | } 351 | } 352 | ``` 353 | 354 | To confirm the event and event data used in above functionality, see the Telescope inspection below: 355 | 356 | ![telescope](https://user-images.githubusercontent.com/57711725/152637248-4bf65fa8-a270-48b9-aff3-08e6193eab6c.png) 357 | 358 | ## Changelog 359 | 360 | Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. 361 | 362 | ## Contributing 363 | 364 | Please see [CONTRIBUTING](CONTRIBUTING.md) for details. 365 | 366 | ## Credits 367 | 368 | - Nova 4 package [sietse85](https://github.com/sietse85) 369 | 370 | - Author of Nova 3 package: [dnwjn](https://github.com/dnwjn) 371 | 372 | - Author of original package: [dillingham](https://github.com/dillingham) 373 | 374 | ## License 375 | 376 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 377 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sietse85/nova-button", 3 | "description": "(Nova 4+) A Laravel Nova package for adding buttons to your resources.", 4 | "authors": [ 5 | { 6 | "name": "Sietse Sietsma", 7 | "email": "sietse85@gmail.com" 8 | }, 9 | { 10 | "name": "Danique Wijnalda", 11 | "email": "hello@dnwjn.dev" 12 | }, 13 | { 14 | "name": "Brian Dillingham", 15 | "email": "bdillingham88@gmail.com" 16 | } 17 | ], 18 | "keywords": [ 19 | "laravel", 20 | "nova", 21 | "button", 22 | "nova4", 23 | "field" 24 | ], 25 | "version": "1.0.28", 26 | "license": "MIT", 27 | "require": { 28 | "php": "^7.4|^8.0", 29 | "laravel/nova": "^4.0|^5.0" 30 | }, 31 | "autoload": { 32 | "psr-4": { 33 | "Sietse85\\NovaButton\\": "src/" 34 | } 35 | }, 36 | "extra": { 37 | "laravel": { 38 | "providers": [ 39 | "Sietse85\\NovaButton\\FieldServiceProvider" 40 | ] 41 | } 42 | }, 43 | "repositories": [ 44 | { 45 | "type": "composer", 46 | "url": "https://nova.laravel.com" 47 | } 48 | ], 49 | "config": { 50 | "sort-packages": true 51 | }, 52 | "minimum-stability": "dev", 53 | "prefer-stable": true 54 | } 55 | -------------------------------------------------------------------------------- /config/nova-button.php: -------------------------------------------------------------------------------- 1 | [ 16 | 'style' => 'link-primary', 17 | 'loadingStyle' => 'link-grey', 18 | 'loadingText' => 'Loading', 19 | 'successStyle' => 'link-success', 20 | 'successText' => 'Success', 21 | 'errorStyle' => 'link-danger', 22 | 'errorText' => 'Failed', 23 | ], 24 | 25 | /* 26 | |-------------------------------------------------------------------------- 27 | | Style options 28 | |-------------------------------------------------------------------------- 29 | | 30 | | These styles are all the styles that can be used in the frontend. You are 31 | | free to add, edit or delete to your likings. 32 | | 33 | | The CSS classes below come from Tailwind CSS, which is shipped with Nova. 34 | | 35 | */ 36 | 37 | 'styles' => [ 38 | // Fill 39 | 'success' => 'cursor-pointer p-2 rounded bg-green-500 text-white font-bold', 40 | 'primary' => 'cursor-pointer p-2 rounded bg-gray-50 text-black font-bold', 41 | 'warning' => 'cursor-pointer p-2 rounded bg-yellow-500 text-white font-bold', 42 | 'danger' => 'cursor-pointer p-2 rounded bg-red-500 text-white font-bold', 43 | 'info' => 'cursor-pointer p-2 rounded bg-blue-500 text-white font-bold', 44 | 'grey' => 'cursor-pointer p-2 rounded bg-gray-500 text-white font-bold', 45 | 46 | // Outline 47 | 'success-outline' => 'cursor-pointer p-2 rounded bg-green-500 text-white font-bold border-2', 48 | 'primary-outline' => 'cursor-pointer p-2 rounded bg-gray-50 text-black font-bold border-2', 49 | 'warning-outline' => 'cursor-pointer p-2 rounded bg-yellow-500 text-white font-bold border-2', 50 | 'danger-outline' => 'cursor-pointer p-2 rounded bg-red-500 text-white font-bold border-2', 51 | 'info-outline' => 'cursor-pointer p-2 rounded bg-blue-500 text-white font-bold border-2', 52 | 'gray-outline' => 'cursor-pointer p-2 rounded bg-gray-500 text-white font-bold border-2', 53 | 54 | // Link 55 | 'success-link' => 'cursor-pointer dim inline-block text-green-500 font-bold', 56 | 'primary-link' => 'cursor-pointer dim inline-block text-gray-50 font-bold', 57 | 'warning-link' => 'cursor-pointer dim inline-block text-yellow-500 font-bold', 58 | 'danger-link' => 'cursor-pointer dim inline-block text-red-500 font-bold btn', 59 | 'info-link' => 'cursor-pointer dim inline-block text-blue-500 font-bold btn', 60 | 'grey-link' => 'cursor-pointer dim inline-block text-gray-500 font-bold btn', 61 | 62 | // Custom 63 | 'custom' => 'bg-green-500', 64 | ], 65 | ]; 66 | -------------------------------------------------------------------------------- /dist/css/field.css: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /dist/js/field.js: -------------------------------------------------------------------------------- 1 | (()=>{var e,t={7757:(e,t,r)=>{e.exports=r(5666)},6511:(e,t,r)=>{"use strict";const n=Vue;var o={key:0},i=["disabled","innerHTML"];var a=r(2576);function s(e,t){for(var r=0;r{"use strict";r.d(t,{Z:()=>i});var n=r(3645),o=r.n(n)()((function(e){return e[1]}));o.push([e.id,".modal{background-color:rgba(0,0,0,.5);height:100%;left:0;position:fixed;top:0;width:100%;z-index:100}.modal-inner{background-color:#fff;left:50%;opacity:1;position:absolute;top:50%;transform:translate(-50%,-50%);z-index:100}",""]);const i=o},5563:(e,t,r)=>{"use strict";r.d(t,{Z:()=>i});var n=r(3645),o=r.n(n)()((function(e){return e[1]}));o.push([e.id,".nova-button{white-space:nowrap}.nova-button-error,.nova-button-loading,.nova-button-success{pointer-events:none}",""]);const i=o},3645:e=>{"use strict";e.exports=function(e){var t=[];return t.toString=function(){return this.map((function(t){var r=e(t);return t[2]?"@media ".concat(t[2]," {").concat(r,"}"):r})).join("")},t.i=function(e,r,n){"string"==typeof e&&(e=[[null,e,""]]);var o={};if(n)for(var i=0;i{},5666:e=>{var t=function(e){"use strict";var t,r=Object.prototype,n=r.hasOwnProperty,o="function"==typeof Symbol?Symbol:{},i=o.iterator||"@@iterator",a=o.asyncIterator||"@@asyncIterator",s=o.toStringTag||"@@toStringTag";function c(e,t,r){return Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}),e[t]}try{c({},"")}catch(e){c=function(e,t,r){return e[t]=r}}function l(e,t,r,n){var o=t&&t.prototype instanceof m?t:m,i=Object.create(o.prototype),a=new A(n||[]);return i._invoke=function(e,t,r){var n=f;return function(o,i){if(n===d)throw new Error("Generator is already running");if(n===h){if("throw"===o)throw i;return C()}for(r.method=o,r.arg=i;;){var a=r.delegate;if(a){var s=j(a,r);if(s){if(s===y)continue;return s}}if("next"===r.method)r.sent=r._sent=r.arg;else if("throw"===r.method){if(n===f)throw n=h,r.arg;r.dispatchException(r.arg)}else"return"===r.method&&r.abrupt("return",r.arg);n=d;var c=u(e,t,r);if("normal"===c.type){if(n=r.done?h:p,c.arg===y)continue;return{value:c.arg,done:r.done}}"throw"===c.type&&(n=h,r.method="throw",r.arg=c.arg)}}}(e,r,a),i}function u(e,t,r){try{return{type:"normal",arg:e.call(t,r)}}catch(e){return{type:"throw",arg:e}}}e.wrap=l;var f="suspendedStart",p="suspendedYield",d="executing",h="completed",y={};function m(){}function v(){}function g(){}var b={};c(b,i,(function(){return this}));var w=Object.getPrototypeOf,S=w&&w(w(N([])));S&&S!==r&&n.call(S,i)&&(b=S);var x=g.prototype=m.prototype=Object.create(b);function O(e){["next","throw","return"].forEach((function(t){c(e,t,(function(e){return this._invoke(t,e)}))}))}function E(e,t){function r(o,i,a,s){var c=u(e[o],e,i);if("throw"!==c.type){var l=c.arg,f=l.value;return f&&"object"==typeof f&&n.call(f,"__await")?t.resolve(f.__await).then((function(e){r("next",e,a,s)}),(function(e){r("throw",e,a,s)})):t.resolve(f).then((function(e){l.value=e,a(l)}),(function(e){return r("throw",e,a,s)}))}s(c.arg)}var o;this._invoke=function(e,n){function i(){return new t((function(t,o){r(e,n,t,o)}))}return o=o?o.then(i,i):i()}}function j(e,r){var n=e.iterator[r.method];if(n===t){if(r.delegate=null,"throw"===r.method){if(e.iterator.return&&(r.method="return",r.arg=t,j(e,r),"throw"===r.method))return y;r.method="throw",r.arg=new TypeError("The iterator does not provide a 'throw' method")}return y}var o=u(n,e.iterator,r.arg);if("throw"===o.type)return r.method="throw",r.arg=o.arg,r.delegate=null,y;var i=o.arg;return i?i.done?(r[e.resultName]=i.value,r.next=e.nextLoc,"return"!==r.method&&(r.method="next",r.arg=t),r.delegate=null,y):i:(r.method="throw",r.arg=new TypeError("iterator result is not an object"),r.delegate=null,y)}function k(e){var t={tryLoc:e[0]};1 in e&&(t.catchLoc=e[1]),2 in e&&(t.finallyLoc=e[2],t.afterLoc=e[3]),this.tryEntries.push(t)}function P(e){var t=e.completion||{};t.type="normal",delete t.arg,e.completion=t}function A(e){this.tryEntries=[{tryLoc:"root"}],e.forEach(k,this),this.reset(!0)}function N(e){if(e){var r=e[i];if(r)return r.call(e);if("function"==typeof e.next)return e;if(!isNaN(e.length)){var o=-1,a=function r(){for(;++o=0;--i){var a=this.tryEntries[i],s=a.completion;if("root"===a.tryLoc)return o("end");if(a.tryLoc<=this.prev){var c=n.call(a,"catchLoc"),l=n.call(a,"finallyLoc");if(c&&l){if(this.prev=0;--r){var o=this.tryEntries[r];if(o.tryLoc<=this.prev&&n.call(o,"finallyLoc")&&this.prev=0;--t){var r=this.tryEntries[t];if(r.finallyLoc===e)return this.complete(r.completion,r.afterLoc),P(r),y}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var r=this.tryEntries[t];if(r.tryLoc===e){var n=r.completion;if("throw"===n.type){var o=n.arg;P(r)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(e,r,n){return this.delegate={iterator:N(e),resultName:r,nextLoc:n},"next"===this.method&&(this.arg=t),y}},e}(e.exports);try{regeneratorRuntime=t}catch(e){"object"==typeof globalThis?globalThis.regeneratorRuntime=t:Function("r","regeneratorRuntime = r")(t)}},3379:(e,t,r)=>{"use strict";var n,o=function(){return void 0===n&&(n=Boolean(window&&document&&document.all&&!window.atob)),n},i=function(){var e={};return function(t){if(void 0===e[t]){var r=document.querySelector(t);if(window.HTMLIFrameElement&&r instanceof window.HTMLIFrameElement)try{r=r.contentDocument.head}catch(e){r=null}e[t]=r}return e[t]}}(),a=[];function s(e){for(var t=-1,r=0;r{"use strict";t.Z=(e,t)=>{const r=e.__vccOpts||e;for(const[e,n]of t)r[e]=n;return r}},2576:(e,t,r)=>{function n(e){return e&&"object"==typeof e&&"default"in e?e.default:e}var o=n(r(5653)),i=n(r(8139)),a=n(r(1857));function s(){return(s=Object.assign||function(e){for(var t=1;t{e.exports=r(4761)},5987:(e,t,r)=>{"use strict";var n=r(8947),o=r(8136),i=r(5746),a=r(6864),s=r(4575),c=r(168),l=r(2641),u=r(4970);e.exports=function(e){return new Promise((function(t,r){var f=e.data,p=e.headers;n.isFormData(f)&&delete p["Content-Type"],(n.isBlob(f)||n.isFile(f))&&f.type&&delete p["Content-Type"];var d=new XMLHttpRequest;if(e.auth){var h=e.auth.username||"",y=unescape(encodeURIComponent(e.auth.password))||"";p.Authorization="Basic "+btoa(h+":"+y)}var m=s(e.baseURL,e.url);if(d.open(e.method.toUpperCase(),a(m,e.params,e.paramsSerializer),!0),d.timeout=e.timeout,d.onreadystatechange=function(){if(d&&4===d.readyState&&(0!==d.status||d.responseURL&&0===d.responseURL.indexOf("file:"))){var n="getAllResponseHeaders"in d?c(d.getAllResponseHeaders()):null,i={data:e.responseType&&"text"!==e.responseType?d.response:d.responseText,status:d.status,statusText:d.statusText,headers:n,config:e,request:d};o(t,r,i),d=null}},d.onabort=function(){d&&(r(u("Request aborted",e,"ECONNABORTED",d)),d=null)},d.onerror=function(){r(u("Network Error",e,null,d)),d=null},d.ontimeout=function(){var t="timeout of "+e.timeout+"ms exceeded";e.timeoutErrorMessage&&(t=e.timeoutErrorMessage),r(u(t,e,"ECONNABORTED",d)),d=null},n.isStandardBrowserEnv()){var v=(e.withCredentials||l(m))&&e.xsrfCookieName?i.read(e.xsrfCookieName):void 0;v&&(p[e.xsrfHeaderName]=v)}if("setRequestHeader"in d&&n.forEach(p,(function(e,t){void 0===f&&"content-type"===t.toLowerCase()?delete p[t]:d.setRequestHeader(t,e)})),n.isUndefined(e.withCredentials)||(d.withCredentials=!!e.withCredentials),e.responseType)try{d.responseType=e.responseType}catch(t){if("json"!==e.responseType)throw t}"function"==typeof e.onDownloadProgress&&d.addEventListener("progress",e.onDownloadProgress),"function"==typeof e.onUploadProgress&&d.upload&&d.upload.addEventListener("progress",e.onUploadProgress),e.cancelToken&&e.cancelToken.promise.then((function(e){d&&(d.abort(),r(e),d=null)})),f||(f=null),d.send(f)}))}},4761:(e,t,r)=>{"use strict";var n=r(8947),o=r(5800),i=r(9129),a=r(1171);function s(e){var t=new i(e),r=o(i.prototype.request,t);return n.extend(r,i.prototype,t),n.extend(r,t),r}var c=s(r(8658));c.Axios=i,c.create=function(e){return s(a(c.defaults,e))},c.Cancel=r(6429),c.CancelToken=r(9454),c.isCancel=r(2363),c.all=function(e){return Promise.all(e)},c.spread=r(4533),e.exports=c,e.exports.default=c},6429:e=>{"use strict";function t(e){this.message=e}t.prototype.toString=function(){return"Cancel"+(this.message?": "+this.message:"")},t.prototype.__CANCEL__=!0,e.exports=t},9454:(e,t,r)=>{"use strict";var n=r(6429);function o(e){if("function"!=typeof e)throw new TypeError("executor must be a function.");var t;this.promise=new Promise((function(e){t=e}));var r=this;e((function(e){r.reason||(r.reason=new n(e),t(r.reason))}))}o.prototype.throwIfRequested=function(){if(this.reason)throw this.reason},o.source=function(){var e;return{token:new o((function(t){e=t})),cancel:e}},e.exports=o},2363:e=>{"use strict";e.exports=function(e){return!(!e||!e.__CANCEL__)}},9129:(e,t,r)=>{"use strict";var n=r(8947),o=r(6864),i=r(8100),a=r(5273),s=r(1171);function c(e){this.defaults=e,this.interceptors={request:new i,response:new i}}c.prototype.request=function(e){"string"==typeof e?(e=arguments[1]||{}).url=arguments[0]:e=e||{},(e=s(this.defaults,e)).method?e.method=e.method.toLowerCase():this.defaults.method?e.method=this.defaults.method.toLowerCase():e.method="get";var t=[a,void 0],r=Promise.resolve(e);for(this.interceptors.request.forEach((function(e){t.unshift(e.fulfilled,e.rejected)})),this.interceptors.response.forEach((function(e){t.push(e.fulfilled,e.rejected)}));t.length;)r=r.then(t.shift(),t.shift());return r},c.prototype.getUri=function(e){return e=s(this.defaults,e),o(e.url,e.params,e.paramsSerializer).replace(/^\?/,"")},n.forEach(["delete","get","head","options"],(function(e){c.prototype[e]=function(t,r){return this.request(s(r||{},{method:e,url:t}))}})),n.forEach(["post","put","patch"],(function(e){c.prototype[e]=function(t,r,n){return this.request(s(n||{},{method:e,url:t,data:r}))}})),e.exports=c},8100:(e,t,r)=>{"use strict";var n=r(8947);function o(){this.handlers=[]}o.prototype.use=function(e,t){return this.handlers.push({fulfilled:e,rejected:t}),this.handlers.length-1},o.prototype.eject=function(e){this.handlers[e]&&(this.handlers[e]=null)},o.prototype.forEach=function(e){n.forEach(this.handlers,(function(t){null!==t&&e(t)}))},e.exports=o},4575:(e,t,r)=>{"use strict";var n=r(3951),o=r(9814);e.exports=function(e,t){return e&&!n(t)?o(e,t):t}},4970:(e,t,r)=>{"use strict";var n=r(7562);e.exports=function(e,t,r,o,i){var a=new Error(e);return n(a,t,r,o,i)}},5273:(e,t,r)=>{"use strict";var n=r(8947),o=r(2441),i=r(2363),a=r(8658);function s(e){e.cancelToken&&e.cancelToken.throwIfRequested()}e.exports=function(e){return s(e),e.headers=e.headers||{},e.data=o(e.data,e.headers,e.transformRequest),e.headers=n.merge(e.headers.common||{},e.headers[e.method]||{},e.headers),n.forEach(["delete","get","head","post","put","patch","common"],(function(t){delete e.headers[t]})),(e.adapter||a.adapter)(e).then((function(t){return s(e),t.data=o(t.data,t.headers,e.transformResponse),t}),(function(t){return i(t)||(s(e),t&&t.response&&(t.response.data=o(t.response.data,t.response.headers,e.transformResponse))),Promise.reject(t)}))}},7562:e=>{"use strict";e.exports=function(e,t,r,n,o){return e.config=t,r&&(e.code=r),e.request=n,e.response=o,e.isAxiosError=!0,e.toJSON=function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:this.config,code:this.code}},e}},1171:(e,t,r)=>{"use strict";var n=r(8947);e.exports=function(e,t){t=t||{};var r={},o=["url","method","data"],i=["headers","auth","proxy","params"],a=["baseURL","transformRequest","transformResponse","paramsSerializer","timeout","timeoutMessage","withCredentials","adapter","responseType","xsrfCookieName","xsrfHeaderName","onUploadProgress","onDownloadProgress","decompress","maxContentLength","maxBodyLength","maxRedirects","transport","httpAgent","httpsAgent","cancelToken","socketPath","responseEncoding"],s=["validateStatus"];function c(e,t){return n.isPlainObject(e)&&n.isPlainObject(t)?n.merge(e,t):n.isPlainObject(t)?n.merge({},t):n.isArray(t)?t.slice():t}function l(o){n.isUndefined(t[o])?n.isUndefined(e[o])||(r[o]=c(void 0,e[o])):r[o]=c(e[o],t[o])}n.forEach(o,(function(e){n.isUndefined(t[e])||(r[e]=c(void 0,t[e]))})),n.forEach(i,l),n.forEach(a,(function(o){n.isUndefined(t[o])?n.isUndefined(e[o])||(r[o]=c(void 0,e[o])):r[o]=c(void 0,t[o])})),n.forEach(s,(function(n){n in t?r[n]=c(e[n],t[n]):n in e&&(r[n]=c(void 0,e[n]))}));var u=o.concat(i).concat(a).concat(s),f=Object.keys(e).concat(Object.keys(t)).filter((function(e){return-1===u.indexOf(e)}));return n.forEach(f,l),r}},8136:(e,t,r)=>{"use strict";var n=r(4970);e.exports=function(e,t,r){var o=r.config.validateStatus;r.status&&o&&!o(r.status)?t(n("Request failed with status code "+r.status,r.config,null,r.request,r)):e(r)}},2441:(e,t,r)=>{"use strict";var n=r(8947);e.exports=function(e,t,r){return n.forEach(r,(function(r){e=r(e,t)})),e}},8658:(e,t,r)=>{"use strict";var n=r(7061),o=r(8947),i=r(9324),a={"Content-Type":"application/x-www-form-urlencoded"};function s(e,t){!o.isUndefined(e)&&o.isUndefined(e["Content-Type"])&&(e["Content-Type"]=t)}var c,l={adapter:(("undefined"!=typeof XMLHttpRequest||void 0!==n&&"[object process]"===Object.prototype.toString.call(n))&&(c=r(5987)),c),transformRequest:[function(e,t){return i(t,"Accept"),i(t,"Content-Type"),o.isFormData(e)||o.isArrayBuffer(e)||o.isBuffer(e)||o.isStream(e)||o.isFile(e)||o.isBlob(e)?e:o.isArrayBufferView(e)?e.buffer:o.isURLSearchParams(e)?(s(t,"application/x-www-form-urlencoded;charset=utf-8"),e.toString()):o.isObject(e)?(s(t,"application/json;charset=utf-8"),JSON.stringify(e)):e}],transformResponse:[function(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(e){}return e}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,validateStatus:function(e){return e>=200&&e<300}};l.headers={common:{Accept:"application/json, text/plain, */*"}},o.forEach(["delete","get","head"],(function(e){l.headers[e]={}})),o.forEach(["post","put","patch"],(function(e){l.headers[e]=o.merge(a)})),e.exports=l},5800:e=>{"use strict";e.exports=function(e,t){return function(){for(var r=new Array(arguments.length),n=0;n{"use strict";var n=r(8947);function o(e){return encodeURIComponent(e).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}e.exports=function(e,t,r){if(!t)return e;var i;if(r)i=r(t);else if(n.isURLSearchParams(t))i=t.toString();else{var a=[];n.forEach(t,(function(e,t){null!=e&&(n.isArray(e)?t+="[]":e=[e],n.forEach(e,(function(e){n.isDate(e)?e=e.toISOString():n.isObject(e)&&(e=JSON.stringify(e)),a.push(o(t)+"="+o(e))})))})),i=a.join("&")}if(i){var s=e.indexOf("#");-1!==s&&(e=e.slice(0,s)),e+=(-1===e.indexOf("?")?"?":"&")+i}return e}},9814:e=>{"use strict";e.exports=function(e,t){return t?e.replace(/\/+$/,"")+"/"+t.replace(/^\/+/,""):e}},5746:(e,t,r)=>{"use strict";var n=r(8947);e.exports=n.isStandardBrowserEnv()?{write:function(e,t,r,o,i,a){var s=[];s.push(e+"="+encodeURIComponent(t)),n.isNumber(r)&&s.push("expires="+new Date(r).toGMTString()),n.isString(o)&&s.push("path="+o),n.isString(i)&&s.push("domain="+i),!0===a&&s.push("secure"),document.cookie=s.join("; ")},read:function(e){var t=document.cookie.match(new RegExp("(^|;\\s*)("+e+")=([^;]*)"));return t?decodeURIComponent(t[3]):null},remove:function(e){this.write(e,"",Date.now()-864e5)}}:{write:function(){},read:function(){return null},remove:function(){}}},3951:e=>{"use strict";e.exports=function(e){return/^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(e)}},2641:(e,t,r)=>{"use strict";var n=r(8947);e.exports=n.isStandardBrowserEnv()?function(){var e,t=/(msie|trident)/i.test(navigator.userAgent),r=document.createElement("a");function o(e){var n=e;return t&&(r.setAttribute("href",n),n=r.href),r.setAttribute("href",n),{href:r.href,protocol:r.protocol?r.protocol.replace(/:$/,""):"",host:r.host,search:r.search?r.search.replace(/^\?/,""):"",hash:r.hash?r.hash.replace(/^#/,""):"",hostname:r.hostname,port:r.port,pathname:"/"===r.pathname.charAt(0)?r.pathname:"/"+r.pathname}}return e=o(window.location.href),function(t){var r=n.isString(t)?o(t):t;return r.protocol===e.protocol&&r.host===e.host}}():function(){return!0}},9324:(e,t,r)=>{"use strict";var n=r(8947);e.exports=function(e,t){n.forEach(e,(function(r,n){n!==t&&n.toUpperCase()===t.toUpperCase()&&(e[t]=r,delete e[n])}))}},168:(e,t,r)=>{"use strict";var n=r(8947),o=["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"];e.exports=function(e){var t,r,i,a={};return e?(n.forEach(e.split("\n"),(function(e){if(i=e.indexOf(":"),t=n.trim(e.substr(0,i)).toLowerCase(),r=n.trim(e.substr(i+1)),t){if(a[t]&&o.indexOf(t)>=0)return;a[t]="set-cookie"===t?(a[t]?a[t]:[]).concat([r]):a[t]?a[t]+", "+r:r}})),a):a}},4533:e=>{"use strict";e.exports=function(e){return function(t){return e.apply(null,t)}}},8947:(e,t,r)=>{"use strict";var n=r(5800),o=Object.prototype.toString;function i(e){return"[object Array]"===o.call(e)}function a(e){return void 0===e}function s(e){return null!==e&&"object"==typeof e}function c(e){if("[object Object]"!==o.call(e))return!1;var t=Object.getPrototypeOf(e);return null===t||t===Object.prototype}function l(e){return"[object Function]"===o.call(e)}function u(e,t){if(null!=e)if("object"!=typeof e&&(e=[e]),i(e))for(var r=0,n=e.length;r{"use strict";var n=r(8750),o=r(4573),i=o(n("String.prototype.indexOf"));e.exports=function(e,t){var r=n(e,!!t);return"function"==typeof r&&i(e,".prototype.")>-1?o(r):r}},4573:(e,t,r)=>{"use strict";var n=r(132),o=r(8750),i=o("%Function.prototype.apply%"),a=o("%Function.prototype.call%"),s=o("%Reflect.apply%",!0)||n.call(a,i),c=o("%Object.getOwnPropertyDescriptor%",!0),l=o("%Object.defineProperty%",!0),u=o("%Math.max%");if(l)try{l({},"a",{value:1})}catch(e){l=null}e.exports=function(e){var t=s(n,a,arguments);if(c&&l){var r=c(t,"length");r.configurable&&l(t,"length",{value:1+u(0,e.length-(arguments.length-1))})}return t};var f=function(){return s(n,i,arguments)};l?l(e.exports,"apply",{value:f}):e.exports.apply=f},1857:e=>{"use strict";var t=function(e){return function(e){return!!e&&"object"==typeof e}(e)&&!function(e){var t=Object.prototype.toString.call(e);return"[object RegExp]"===t||"[object Date]"===t||function(e){return e.$$typeof===r}(e)}(e)};var r="function"==typeof Symbol&&Symbol.for?Symbol.for("react.element"):60103;function n(e,t){return!1!==t.clone&&t.isMergeableObject(e)?c((r=e,Array.isArray(r)?[]:{}),e,t):e;var r}function o(e,t,r){return e.concat(t).map((function(e){return n(e,r)}))}function i(e){return Object.keys(e).concat(function(e){return Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(e).filter((function(t){return e.propertyIsEnumerable(t)})):[]}(e))}function a(e,t){try{return t in e}catch(e){return!1}}function s(e,t,r){var o={};return r.isMergeableObject(e)&&i(e).forEach((function(t){o[t]=n(e[t],r)})),i(t).forEach((function(i){(function(e,t){return a(e,t)&&!(Object.hasOwnProperty.call(e,t)&&Object.propertyIsEnumerable.call(e,t))})(e,i)||(a(e,i)&&r.isMergeableObject(t[i])?o[i]=function(e,t){if(!t.customMerge)return c;var r=t.customMerge(e);return"function"==typeof r?r:c}(i,r)(e[i],t[i],r):o[i]=n(t[i],r))})),o}function c(e,r,i){(i=i||{}).arrayMerge=i.arrayMerge||o,i.isMergeableObject=i.isMergeableObject||t,i.cloneUnlessOtherwiseSpecified=n;var a=Array.isArray(r);return a===Array.isArray(e)?a?i.arrayMerge(e,r,i):s(e,r,i):n(r,i)}c.all=function(e,t){if(!Array.isArray(e))throw new Error("first argument should be an array");return e.reduce((function(e,r){return c(e,r,t)}),{})};var l=c;e.exports=l},8458:e=>{"use strict";var t="Function.prototype.bind called on incompatible ",r=Array.prototype.slice,n=Object.prototype.toString,o="[object Function]";e.exports=function(e){var i=this;if("function"!=typeof i||n.call(i)!==o)throw new TypeError(t+i);for(var a,s=r.call(arguments,1),c=function(){if(this instanceof a){var t=i.apply(this,s.concat(r.call(arguments)));return Object(t)===t?t:this}return i.apply(e,s.concat(r.call(arguments)))},l=Math.max(0,i.length-s.length),u=[],f=0;f{"use strict";var n=r(8458);e.exports=Function.prototype.bind||n},8750:(e,t,r)=>{"use strict";var n,o=SyntaxError,i=Function,a=TypeError,s=function(e){try{return i('"use strict"; return ('+e+").constructor;")()}catch(e){}},c=Object.getOwnPropertyDescriptor;if(c)try{c({},"")}catch(e){c=null}var l=function(){throw new a},u=c?function(){try{return l}catch(e){try{return c(arguments,"callee").get}catch(e){return l}}}():l,f=r(679)(),p=Object.getPrototypeOf||function(e){return e.__proto__},d={},h="undefined"==typeof Uint8Array?n:p(Uint8Array),y={"%AggregateError%":"undefined"==typeof AggregateError?n:AggregateError,"%Array%":Array,"%ArrayBuffer%":"undefined"==typeof ArrayBuffer?n:ArrayBuffer,"%ArrayIteratorPrototype%":f?p([][Symbol.iterator]()):n,"%AsyncFromSyncIteratorPrototype%":n,"%AsyncFunction%":d,"%AsyncGenerator%":d,"%AsyncGeneratorFunction%":d,"%AsyncIteratorPrototype%":d,"%Atomics%":"undefined"==typeof Atomics?n:Atomics,"%BigInt%":"undefined"==typeof BigInt?n:BigInt,"%Boolean%":Boolean,"%DataView%":"undefined"==typeof DataView?n:DataView,"%Date%":Date,"%decodeURI%":decodeURI,"%decodeURIComponent%":decodeURIComponent,"%encodeURI%":encodeURI,"%encodeURIComponent%":encodeURIComponent,"%Error%":Error,"%eval%":eval,"%EvalError%":EvalError,"%Float32Array%":"undefined"==typeof Float32Array?n:Float32Array,"%Float64Array%":"undefined"==typeof Float64Array?n:Float64Array,"%FinalizationRegistry%":"undefined"==typeof FinalizationRegistry?n:FinalizationRegistry,"%Function%":i,"%GeneratorFunction%":d,"%Int8Array%":"undefined"==typeof Int8Array?n:Int8Array,"%Int16Array%":"undefined"==typeof Int16Array?n:Int16Array,"%Int32Array%":"undefined"==typeof Int32Array?n:Int32Array,"%isFinite%":isFinite,"%isNaN%":isNaN,"%IteratorPrototype%":f?p(p([][Symbol.iterator]())):n,"%JSON%":"object"==typeof JSON?JSON:n,"%Map%":"undefined"==typeof Map?n:Map,"%MapIteratorPrototype%":"undefined"!=typeof Map&&f?p((new Map)[Symbol.iterator]()):n,"%Math%":Math,"%Number%":Number,"%Object%":Object,"%parseFloat%":parseFloat,"%parseInt%":parseInt,"%Promise%":"undefined"==typeof Promise?n:Promise,"%Proxy%":"undefined"==typeof Proxy?n:Proxy,"%RangeError%":RangeError,"%ReferenceError%":ReferenceError,"%Reflect%":"undefined"==typeof Reflect?n:Reflect,"%RegExp%":RegExp,"%Set%":"undefined"==typeof Set?n:Set,"%SetIteratorPrototype%":"undefined"!=typeof Set&&f?p((new Set)[Symbol.iterator]()):n,"%SharedArrayBuffer%":"undefined"==typeof SharedArrayBuffer?n:SharedArrayBuffer,"%String%":String,"%StringIteratorPrototype%":f?p(""[Symbol.iterator]()):n,"%Symbol%":f?Symbol:n,"%SyntaxError%":o,"%ThrowTypeError%":u,"%TypedArray%":h,"%TypeError%":a,"%Uint8Array%":"undefined"==typeof Uint8Array?n:Uint8Array,"%Uint8ClampedArray%":"undefined"==typeof Uint8ClampedArray?n:Uint8ClampedArray,"%Uint16Array%":"undefined"==typeof Uint16Array?n:Uint16Array,"%Uint32Array%":"undefined"==typeof Uint32Array?n:Uint32Array,"%URIError%":URIError,"%WeakMap%":"undefined"==typeof WeakMap?n:WeakMap,"%WeakRef%":"undefined"==typeof WeakRef?n:WeakRef,"%WeakSet%":"undefined"==typeof WeakSet?n:WeakSet},m=function e(t){var r;if("%AsyncFunction%"===t)r=s("async function () {}");else if("%GeneratorFunction%"===t)r=s("function* () {}");else if("%AsyncGeneratorFunction%"===t)r=s("async function* () {}");else if("%AsyncGenerator%"===t){var n=e("%AsyncGeneratorFunction%");n&&(r=n.prototype)}else if("%AsyncIteratorPrototype%"===t){var o=e("%AsyncGenerator%");o&&(r=p(o.prototype))}return y[t]=r,r},v={"%ArrayBufferPrototype%":["ArrayBuffer","prototype"],"%ArrayPrototype%":["Array","prototype"],"%ArrayProto_entries%":["Array","prototype","entries"],"%ArrayProto_forEach%":["Array","prototype","forEach"],"%ArrayProto_keys%":["Array","prototype","keys"],"%ArrayProto_values%":["Array","prototype","values"],"%AsyncFunctionPrototype%":["AsyncFunction","prototype"],"%AsyncGenerator%":["AsyncGeneratorFunction","prototype"],"%AsyncGeneratorPrototype%":["AsyncGeneratorFunction","prototype","prototype"],"%BooleanPrototype%":["Boolean","prototype"],"%DataViewPrototype%":["DataView","prototype"],"%DatePrototype%":["Date","prototype"],"%ErrorPrototype%":["Error","prototype"],"%EvalErrorPrototype%":["EvalError","prototype"],"%Float32ArrayPrototype%":["Float32Array","prototype"],"%Float64ArrayPrototype%":["Float64Array","prototype"],"%FunctionPrototype%":["Function","prototype"],"%Generator%":["GeneratorFunction","prototype"],"%GeneratorPrototype%":["GeneratorFunction","prototype","prototype"],"%Int8ArrayPrototype%":["Int8Array","prototype"],"%Int16ArrayPrototype%":["Int16Array","prototype"],"%Int32ArrayPrototype%":["Int32Array","prototype"],"%JSONParse%":["JSON","parse"],"%JSONStringify%":["JSON","stringify"],"%MapPrototype%":["Map","prototype"],"%NumberPrototype%":["Number","prototype"],"%ObjectPrototype%":["Object","prototype"],"%ObjProto_toString%":["Object","prototype","toString"],"%ObjProto_valueOf%":["Object","prototype","valueOf"],"%PromisePrototype%":["Promise","prototype"],"%PromiseProto_then%":["Promise","prototype","then"],"%Promise_all%":["Promise","all"],"%Promise_reject%":["Promise","reject"],"%Promise_resolve%":["Promise","resolve"],"%RangeErrorPrototype%":["RangeError","prototype"],"%ReferenceErrorPrototype%":["ReferenceError","prototype"],"%RegExpPrototype%":["RegExp","prototype"],"%SetPrototype%":["Set","prototype"],"%SharedArrayBufferPrototype%":["SharedArrayBuffer","prototype"],"%StringPrototype%":["String","prototype"],"%SymbolPrototype%":["Symbol","prototype"],"%SyntaxErrorPrototype%":["SyntaxError","prototype"],"%TypedArrayPrototype%":["TypedArray","prototype"],"%TypeErrorPrototype%":["TypeError","prototype"],"%Uint8ArrayPrototype%":["Uint8Array","prototype"],"%Uint8ClampedArrayPrototype%":["Uint8ClampedArray","prototype"],"%Uint16ArrayPrototype%":["Uint16Array","prototype"],"%Uint32ArrayPrototype%":["Uint32Array","prototype"],"%URIErrorPrototype%":["URIError","prototype"],"%WeakMapPrototype%":["WeakMap","prototype"],"%WeakSetPrototype%":["WeakSet","prototype"]},g=r(132),b=r(7492),w=g.call(Function.call,Array.prototype.concat),S=g.call(Function.apply,Array.prototype.splice),x=g.call(Function.call,String.prototype.replace),O=g.call(Function.call,String.prototype.slice),E=/[^%.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|%$))/g,j=/\\(\\)?/g,k=function(e){var t=O(e,0,1),r=O(e,-1);if("%"===t&&"%"!==r)throw new o("invalid intrinsic syntax, expected closing `%`");if("%"===r&&"%"!==t)throw new o("invalid intrinsic syntax, expected opening `%`");var n=[];return x(e,E,(function(e,t,r,o){n[n.length]=r?x(o,j,"$1"):t||e})),n},P=function(e,t){var r,n=e;if(b(v,n)&&(n="%"+(r=v[n])[0]+"%"),b(y,n)){var i=y[n];if(i===d&&(i=m(n)),void 0===i&&!t)throw new a("intrinsic "+e+" exists, but is not available. Please file an issue!");return{alias:r,name:n,value:i}}throw new o("intrinsic "+e+" does not exist!")};e.exports=function(e,t){if("string"!=typeof e||0===e.length)throw new a("intrinsic name must be a non-empty string");if(arguments.length>1&&"boolean"!=typeof t)throw new a('"allowMissing" argument must be a boolean');var r=k(e),n=r.length>0?r[0]:"",i=P("%"+n+"%",t),s=i.name,l=i.value,u=!1,f=i.alias;f&&(n=f[0],S(r,w([0,1],f)));for(var p=1,d=!0;p=r.length){var g=c(l,h);l=(d=!!g)&&"get"in g&&!("originalValue"in g.get)?g.get:l[h]}else d=b(l,h),l=l[h];d&&!u&&(y[s]=l)}}return l}},679:(e,t,r)=>{"use strict";var n="undefined"!=typeof Symbol&&Symbol,o=r(8186);e.exports=function(){return"function"==typeof n&&("function"==typeof Symbol&&("symbol"==typeof n("foo")&&("symbol"==typeof Symbol("bar")&&o())))}},8186:e=>{"use strict";e.exports=function(){if("function"!=typeof Symbol||"function"!=typeof Object.getOwnPropertySymbols)return!1;if("symbol"==typeof Symbol.iterator)return!0;var e={},t=Symbol("test"),r=Object(t);if("string"==typeof t)return!1;if("[object Symbol]"!==Object.prototype.toString.call(t))return!1;if("[object Symbol]"!==Object.prototype.toString.call(r))return!1;for(t in e[t]=42,e)return!1;if("function"==typeof Object.keys&&0!==Object.keys(e).length)return!1;if("function"==typeof Object.getOwnPropertyNames&&0!==Object.getOwnPropertyNames(e).length)return!1;var n=Object.getOwnPropertySymbols(e);if(1!==n.length||n[0]!==t)return!1;if(!Object.prototype.propertyIsEnumerable.call(e,t))return!1;if("function"==typeof Object.getOwnPropertyDescriptor){var o=Object.getOwnPropertyDescriptor(e,t);if(42!==o.value||!0!==o.enumerable)return!1}return!0}},7492:(e,t,r)=>{"use strict";var n=r(132);e.exports=n.call(Function.call,Object.prototype.hasOwnProperty)},6524:(e,t,r)=>{var n="function"==typeof Map&&Map.prototype,o=Object.getOwnPropertyDescriptor&&n?Object.getOwnPropertyDescriptor(Map.prototype,"size"):null,i=n&&o&&"function"==typeof o.get?o.get:null,a=n&&Map.prototype.forEach,s="function"==typeof Set&&Set.prototype,c=Object.getOwnPropertyDescriptor&&s?Object.getOwnPropertyDescriptor(Set.prototype,"size"):null,l=s&&c&&"function"==typeof c.get?c.get:null,u=s&&Set.prototype.forEach,f="function"==typeof WeakMap&&WeakMap.prototype?WeakMap.prototype.has:null,p="function"==typeof WeakSet&&WeakSet.prototype?WeakSet.prototype.has:null,d="function"==typeof WeakRef&&WeakRef.prototype?WeakRef.prototype.deref:null,h=Boolean.prototype.valueOf,y=Object.prototype.toString,m=Function.prototype.toString,v=String.prototype.match,g=String.prototype.slice,b=String.prototype.replace,w=String.prototype.toUpperCase,S=String.prototype.toLowerCase,x=RegExp.prototype.test,O=Array.prototype.concat,E=Array.prototype.join,j=Array.prototype.slice,k=Math.floor,P="function"==typeof BigInt?BigInt.prototype.valueOf:null,A=Object.getOwnPropertySymbols,N="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?Symbol.prototype.toString:null,C="function"==typeof Symbol&&"object"==typeof Symbol.iterator,T="function"==typeof Symbol&&Symbol.toStringTag&&(typeof Symbol.toStringTag===C||"symbol")?Symbol.toStringTag:null,L=Object.prototype.propertyIsEnumerable,I=("function"==typeof Reflect?Reflect.getPrototypeOf:Object.getPrototypeOf)||([].__proto__===Array.prototype?function(e){return e.__proto__}:null);function R(e,t){if(e===1/0||e===-1/0||e!=e||e&&e>-1e3&&e<1e3||x.call(/e/,t))return t;var r=/[0-9](?=(?:[0-9]{3})+(?![0-9]))/g;if("number"==typeof e){var n=e<0?-k(-e):k(e);if(n!==e){var o=String(n),i=g.call(t,o.length+1);return b.call(o,r,"$&_")+"."+b.call(b.call(i,/([0-9]{3})/g,"$&_"),/_$/,"")}}return b.call(t,r,"$&_")}var M=r(6553).custom,B=M&&_(M)?M:null;function F(e,t,r){var n="double"===(r.quoteStyle||t)?'"':"'";return n+e+n}function V(e){return b.call(String(e),/"/g,""")}function U(e){return!("[object Array]"!==q(e)||T&&"object"==typeof e&&T in e)}function _(e){if(C)return e&&"object"==typeof e&&e instanceof Symbol;if("symbol"==typeof e)return!0;if(!e||"object"!=typeof e||!N)return!1;try{return N.call(e),!0}catch(e){}return!1}e.exports=function e(t,r,n,o){var s=r||{};if(H(s,"quoteStyle")&&"single"!==s.quoteStyle&&"double"!==s.quoteStyle)throw new TypeError('option "quoteStyle" must be "single" or "double"');if(H(s,"maxStringLength")&&("number"==typeof s.maxStringLength?s.maxStringLength<0&&s.maxStringLength!==1/0:null!==s.maxStringLength))throw new TypeError('option "maxStringLength", if provided, must be a positive integer, Infinity, or `null`');var c=!H(s,"customInspect")||s.customInspect;if("boolean"!=typeof c&&"symbol"!==c)throw new TypeError("option \"customInspect\", if provided, must be `true`, `false`, or `'symbol'`");if(H(s,"indent")&&null!==s.indent&&"\t"!==s.indent&&!(parseInt(s.indent,10)===s.indent&&s.indent>0))throw new TypeError('option "indent" must be "\\t", an integer > 0, or `null`');if(H(s,"numericSeparator")&&"boolean"!=typeof s.numericSeparator)throw new TypeError('option "numericSeparator", if provided, must be `true` or `false`');var y=s.numericSeparator;if(void 0===t)return"undefined";if(null===t)return"null";if("boolean"==typeof t)return t?"true":"false";if("string"==typeof t)return $(t,s);if("number"==typeof t){if(0===t)return 1/0/t>0?"0":"-0";var w=String(t);return y?R(t,w):w}if("bigint"==typeof t){var x=String(t)+"n";return y?R(t,x):x}var k=void 0===s.depth?5:s.depth;if(void 0===n&&(n=0),n>=k&&k>0&&"object"==typeof t)return U(t)?"[Array]":"[Object]";var A=function(e,t){var r;if("\t"===e.indent)r="\t";else{if(!("number"==typeof e.indent&&e.indent>0))return null;r=E.call(Array(e.indent+1)," ")}return{base:r,prev:E.call(Array(t+1),r)}}(s,n);if(void 0===o)o=[];else if(W(o,t)>=0)return"[Circular]";function M(t,r,i){if(r&&(o=j.call(o)).push(r),i){var a={depth:s.depth};return H(s,"quoteStyle")&&(a.quoteStyle=s.quoteStyle),e(t,a,n+1,o)}return e(t,s,n+1,o)}if("function"==typeof t){var D=function(e){if(e.name)return e.name;var t=v.call(m.call(e),/^function\s*([\w$]+)/);if(t)return t[1];return null}(t),z=X(t,M);return"[Function"+(D?": "+D:" (anonymous)")+"]"+(z.length>0?" { "+E.call(z,", ")+" }":"")}if(_(t)){var K=C?b.call(String(t),/^(Symbol\(.*\))_[^)]*$/,"$1"):N.call(t);return"object"!=typeof t||C?K:G(K)}if(function(e){if(!e||"object"!=typeof e)return!1;if("undefined"!=typeof HTMLElement&&e instanceof HTMLElement)return!0;return"string"==typeof e.nodeName&&"function"==typeof e.getAttribute}(t)){for(var Y="<"+S.call(String(t.nodeName)),ee=t.attributes||[],te=0;te"}if(U(t)){if(0===t.length)return"[]";var re=X(t,M);return A&&!function(e){for(var t=0;t=0)return!1;return!0}(re)?"["+Q(re,A)+"]":"[ "+E.call(re,", ")+" ]"}if(function(e){return!("[object Error]"!==q(e)||T&&"object"==typeof e&&T in e)}(t)){var ne=X(t,M);return"cause"in t&&!L.call(t,"cause")?"{ ["+String(t)+"] "+E.call(O.call("[cause]: "+M(t.cause),ne),", ")+" }":0===ne.length?"["+String(t)+"]":"{ ["+String(t)+"] "+E.call(ne,", ")+" }"}if("object"==typeof t&&c){if(B&&"function"==typeof t[B])return t[B]();if("symbol"!==c&&"function"==typeof t.inspect)return t.inspect()}if(function(e){if(!i||!e||"object"!=typeof e)return!1;try{i.call(e);try{l.call(e)}catch(e){return!0}return e instanceof Map}catch(e){}return!1}(t)){var oe=[];return a.call(t,(function(e,r){oe.push(M(r,t,!0)+" => "+M(e,t))})),Z("Map",i.call(t),oe,A)}if(function(e){if(!l||!e||"object"!=typeof e)return!1;try{l.call(e);try{i.call(e)}catch(e){return!0}return e instanceof Set}catch(e){}return!1}(t)){var ie=[];return u.call(t,(function(e){ie.push(M(e,t))})),Z("Set",l.call(t),ie,A)}if(function(e){if(!f||!e||"object"!=typeof e)return!1;try{f.call(e,f);try{p.call(e,p)}catch(e){return!0}return e instanceof WeakMap}catch(e){}return!1}(t))return J("WeakMap");if(function(e){if(!p||!e||"object"!=typeof e)return!1;try{p.call(e,p);try{f.call(e,f)}catch(e){return!0}return e instanceof WeakSet}catch(e){}return!1}(t))return J("WeakSet");if(function(e){if(!d||!e||"object"!=typeof e)return!1;try{return d.call(e),!0}catch(e){}return!1}(t))return J("WeakRef");if(function(e){return!("[object Number]"!==q(e)||T&&"object"==typeof e&&T in e)}(t))return G(M(Number(t)));if(function(e){if(!e||"object"!=typeof e||!P)return!1;try{return P.call(e),!0}catch(e){}return!1}(t))return G(M(P.call(t)));if(function(e){return!("[object Boolean]"!==q(e)||T&&"object"==typeof e&&T in e)}(t))return G(h.call(t));if(function(e){return!("[object String]"!==q(e)||T&&"object"==typeof e&&T in e)}(t))return G(M(String(t)));if(!function(e){return!("[object Date]"!==q(e)||T&&"object"==typeof e&&T in e)}(t)&&!function(e){return!("[object RegExp]"!==q(e)||T&&"object"==typeof e&&T in e)}(t)){var ae=X(t,M),se=I?I(t)===Object.prototype:t instanceof Object||t.constructor===Object,ce=t instanceof Object?"":"null prototype",le=!se&&T&&Object(t)===t&&T in t?g.call(q(t),8,-1):ce?"Object":"",ue=(se||"function"!=typeof t.constructor?"":t.constructor.name?t.constructor.name+" ":"")+(le||ce?"["+E.call(O.call([],le||[],ce||[]),": ")+"] ":"");return 0===ae.length?ue+"{}":A?ue+"{"+Q(ae,A)+"}":ue+"{ "+E.call(ae,", ")+" }"}return String(t)};var D=Object.prototype.hasOwnProperty||function(e){return e in this};function H(e,t){return D.call(e,t)}function q(e){return y.call(e)}function W(e,t){if(e.indexOf)return e.indexOf(t);for(var r=0,n=e.length;rt.maxStringLength){var r=e.length-t.maxStringLength,n="... "+r+" more character"+(r>1?"s":"");return $(g.call(e,0,t.maxStringLength),t)+n}return F(b.call(b.call(e,/(['\\])/g,"\\$1"),/[\x00-\x1f]/g,z),"single",t)}function z(e){var t=e.charCodeAt(0),r={8:"b",9:"t",10:"n",12:"f",13:"r"}[t];return r?"\\"+r:"\\x"+(t<16?"0":"")+w.call(t.toString(16))}function G(e){return"Object("+e+")"}function J(e){return e+" { ? }"}function Z(e,t,r,n){return e+" ("+t+") {"+(n?Q(r,n):E.call(r,", "))+"}"}function Q(e,t){if(0===e.length)return"";var r="\n"+t.prev+t.base;return r+E.call(e,","+r)+"\n"+t.prev}function X(e,t){var r=U(e),n=[];if(r){n.length=e.length;for(var o=0;o{var t,r,n=e.exports={};function o(){throw new Error("setTimeout has not been defined")}function i(){throw new Error("clearTimeout has not been defined")}function a(e){if(t===setTimeout)return setTimeout(e,0);if((t===o||!t)&&setTimeout)return t=setTimeout,setTimeout(e,0);try{return t(e,0)}catch(r){try{return t.call(null,e,0)}catch(r){return t.call(this,e,0)}}}!function(){try{t="function"==typeof setTimeout?setTimeout:o}catch(e){t=o}try{r="function"==typeof clearTimeout?clearTimeout:i}catch(e){r=i}}();var s,c=[],l=!1,u=-1;function f(){l&&s&&(l=!1,s.length?c=s.concat(c):u=-1,c.length&&p())}function p(){if(!l){var e=a(f);l=!0;for(var t=c.length;t;){for(s=c,c=[];++u1)for(var r=1;r{"use strict";var t=String.prototype.replace,r=/%20/g,n="RFC1738",o="RFC3986";e.exports={default:o,formatters:{RFC1738:function(e){return t.call(e,r,"+")},RFC3986:function(e){return String(e)}},RFC1738:n,RFC3986:o}},8139:(e,t,r)=>{"use strict";var n=r(6360),o=r(9520),i=r(9771);e.exports={formats:i,parse:o,stringify:n}},9520:(e,t,r)=>{"use strict";var n=r(4330),o=Object.prototype.hasOwnProperty,i=Array.isArray,a={allowDots:!1,allowPrototypes:!1,allowSparse:!1,arrayLimit:20,charset:"utf-8",charsetSentinel:!1,comma:!1,decoder:n.decode,delimiter:"&",depth:5,ignoreQueryPrefix:!1,interpretNumericEntities:!1,parameterLimit:1e3,parseArrays:!0,plainObjects:!1,strictNullHandling:!1},s=function(e){return e.replace(/&#(\d+);/g,(function(e,t){return String.fromCharCode(parseInt(t,10))}))},c=function(e,t){return e&&"string"==typeof e&&t.comma&&e.indexOf(",")>-1?e.split(","):e},l=function(e,t,r,n){if(e){var i=r.allowDots?e.replace(/\.([^.[]+)/g,"[$1]"):e,a=/(\[[^[\]]*])/g,s=r.depth>0&&/(\[[^[\]]*])/.exec(i),l=s?i.slice(0,s.index):i,u=[];if(l){if(!r.plainObjects&&o.call(Object.prototype,l)&&!r.allowPrototypes)return;u.push(l)}for(var f=0;r.depth>0&&null!==(s=a.exec(i))&&f=0;--i){var a,s=e[i];if("[]"===s&&r.parseArrays)a=[].concat(o);else{a=r.plainObjects?Object.create(null):{};var l="["===s.charAt(0)&&"]"===s.charAt(s.length-1)?s.slice(1,-1):s,u=parseInt(l,10);r.parseArrays||""!==l?!isNaN(u)&&s!==l&&String(u)===l&&u>=0&&r.parseArrays&&u<=r.arrayLimit?(a=[])[u]=o:"__proto__"!==l&&(a[l]=o):a={0:o}}o=a}return o}(u,t,r,n)}};e.exports=function(e,t){var r=function(e){if(!e)return a;if(null!==e.decoder&&void 0!==e.decoder&&"function"!=typeof e.decoder)throw new TypeError("Decoder has to be a function.");if(void 0!==e.charset&&"utf-8"!==e.charset&&"iso-8859-1"!==e.charset)throw new TypeError("The charset option must be either utf-8, iso-8859-1, or undefined");var t=void 0===e.charset?a.charset:e.charset;return{allowDots:void 0===e.allowDots?a.allowDots:!!e.allowDots,allowPrototypes:"boolean"==typeof e.allowPrototypes?e.allowPrototypes:a.allowPrototypes,allowSparse:"boolean"==typeof e.allowSparse?e.allowSparse:a.allowSparse,arrayLimit:"number"==typeof e.arrayLimit?e.arrayLimit:a.arrayLimit,charset:t,charsetSentinel:"boolean"==typeof e.charsetSentinel?e.charsetSentinel:a.charsetSentinel,comma:"boolean"==typeof e.comma?e.comma:a.comma,decoder:"function"==typeof e.decoder?e.decoder:a.decoder,delimiter:"string"==typeof e.delimiter||n.isRegExp(e.delimiter)?e.delimiter:a.delimiter,depth:"number"==typeof e.depth||!1===e.depth?+e.depth:a.depth,ignoreQueryPrefix:!0===e.ignoreQueryPrefix,interpretNumericEntities:"boolean"==typeof e.interpretNumericEntities?e.interpretNumericEntities:a.interpretNumericEntities,parameterLimit:"number"==typeof e.parameterLimit?e.parameterLimit:a.parameterLimit,parseArrays:!1!==e.parseArrays,plainObjects:"boolean"==typeof e.plainObjects?e.plainObjects:a.plainObjects,strictNullHandling:"boolean"==typeof e.strictNullHandling?e.strictNullHandling:a.strictNullHandling}}(t);if(""===e||null==e)return r.plainObjects?Object.create(null):{};for(var u="string"==typeof e?function(e,t){var r,l={},u=t.ignoreQueryPrefix?e.replace(/^\?/,""):e,f=t.parameterLimit===1/0?void 0:t.parameterLimit,p=u.split(t.delimiter,f),d=-1,h=t.charset;if(t.charsetSentinel)for(r=0;r-1&&(m=i(m)?[m]:m),o.call(l,y)?l[y]=n.combine(l[y],m):l[y]=m}return l}(e,r):e,f=r.plainObjects?Object.create(null):{},p=Object.keys(u),d=0;d{"use strict";var n=r(5337),o=r(4330),i=r(9771),a=Object.prototype.hasOwnProperty,s={brackets:function(e){return e+"[]"},comma:"comma",indices:function(e,t){return e+"["+t+"]"},repeat:function(e){return e}},c=Array.isArray,l=String.prototype.split,u=Array.prototype.push,f=function(e,t){u.apply(e,c(t)?t:[t])},p=Date.prototype.toISOString,d=i.default,h={addQueryPrefix:!1,allowDots:!1,charset:"utf-8",charsetSentinel:!1,delimiter:"&",encode:!0,encoder:o.encode,encodeValuesOnly:!1,format:d,formatter:i.formatters[d],indices:!1,serializeDate:function(e){return p.call(e)},skipNulls:!1,strictNullHandling:!1},y={},m=function e(t,r,i,a,s,u,p,d,m,v,g,b,w,S,x){for(var O,E=t,j=x,k=0,P=!1;void 0!==(j=j.get(y))&&!P;){var A=j.get(t);if(k+=1,void 0!==A){if(A===k)throw new RangeError("Cyclic object value");P=!0}void 0===j.get(y)&&(k=0)}if("function"==typeof p?E=p(r,E):E instanceof Date?E=v(E):"comma"===i&&c(E)&&(E=o.maybeMap(E,(function(e){return e instanceof Date?v(e):e}))),null===E){if(a)return u&&!w?u(r,h.encoder,S,"key",g):r;E=""}if("string"==typeof(O=E)||"number"==typeof O||"boolean"==typeof O||"symbol"==typeof O||"bigint"==typeof O||o.isBuffer(E)){if(u){var N=w?r:u(r,h.encoder,S,"key",g);if("comma"===i&&w){for(var C=l.call(String(E),","),T="",L=0;L0?E.join(",")||null:void 0}];else if(c(p))I=p;else{var M=Object.keys(E);I=d?M.sort(d):M}for(var B=0;B0?w+b:""}},4330:(e,t,r)=>{"use strict";var n=r(9771),o=Object.prototype.hasOwnProperty,i=Array.isArray,a=function(){for(var e=[],t=0;t<256;++t)e.push("%"+((t<16?"0":"")+t.toString(16)).toUpperCase());return e}(),s=function(e,t){for(var r=t&&t.plainObjects?Object.create(null):{},n=0;n1;){var t=e.pop(),r=t.obj[t.prop];if(i(r)){for(var n=[],o=0;o=48&&u<=57||u>=65&&u<=90||u>=97&&u<=122||i===n.RFC1738&&(40===u||41===u)?c+=s.charAt(l):u<128?c+=a[u]:u<2048?c+=a[192|u>>6]+a[128|63&u]:u<55296||u>=57344?c+=a[224|u>>12]+a[128|u>>6&63]+a[128|63&u]:(l+=1,u=65536+((1023&u)<<10|1023&s.charCodeAt(l)),c+=a[240|u>>18]+a[128|u>>12&63]+a[128|u>>6&63]+a[128|63&u])}return c},isBuffer:function(e){return!(!e||"object"!=typeof e)&&!!(e.constructor&&e.constructor.isBuffer&&e.constructor.isBuffer(e))},isRegExp:function(e){return"[object RegExp]"===Object.prototype.toString.call(e)},maybeMap:function(e,t){if(i(e)){for(var r=[],n=0;n{"use strict";var n=r(8750),o=r(2737),i=r(6524),a=n("%TypeError%"),s=n("%WeakMap%",!0),c=n("%Map%",!0),l=o("WeakMap.prototype.get",!0),u=o("WeakMap.prototype.set",!0),f=o("WeakMap.prototype.has",!0),p=o("Map.prototype.get",!0),d=o("Map.prototype.set",!0),h=o("Map.prototype.has",!0),y=function(e,t){for(var r,n=e;null!==(r=n.next);n=r)if(r.key===t)return n.next=r.next,r.next=e.next,e.next=r,r};e.exports=function(){var e,t,r,n={assert:function(e){if(!n.has(e))throw new a("Side channel does not contain "+i(e))},get:function(n){if(s&&n&&("object"==typeof n||"function"==typeof n)){if(e)return l(e,n)}else if(c){if(t)return p(t,n)}else if(r)return function(e,t){var r=y(e,t);return r&&r.value}(r,n)},has:function(n){if(s&&n&&("object"==typeof n||"function"==typeof n)){if(e)return f(e,n)}else if(c){if(t)return h(t,n)}else if(r)return function(e,t){return!!y(e,t)}(r,n);return!1},set:function(n,o){s&&n&&("object"==typeof n||"function"==typeof n)?(e||(e=new s),u(e,n,o)):c?(t||(t=new c),d(t,n,o)):(r||(r={key:{},next:null}),function(e,t,r){var n=y(e,t);n?n.value=r:e.next={key:t,next:e.next,value:r}}(r,n,o))}};return n}},6553:()=>{}},r={};function n(e){var o=r[e];if(void 0!==o)return o.exports;var i=r[e]={id:e,exports:{}};return t[e](i,i.exports,n),i.exports}n.m=t,e=[],n.O=(t,r,o,i)=>{if(!r){var a=1/0;for(u=0;u=i)&&Object.keys(n.O).every((e=>n.O[e](r[c])))?r.splice(c--,1):(s=!1,i0&&e[u-1][2]>i;u--)e[u]=e[u-1];e[u]=[r,o,i]},n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={175:0,546:0};n.O.j=t=>0===e[t];var t=(t,r)=>{var o,i,[a,s,c]=r,l=0;if(a.some((t=>0!==e[t]))){for(o in s)n.o(s,o)&&(n.m[o]=s[o]);if(c)var u=c(n)}for(t&&t(r);ln(6511)));var o=n.O(void 0,[546],(()=>n(6381)));o=n.O(o)})(); -------------------------------------------------------------------------------- /dist/mix-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "/js/field.js": "/js/field.js", 3 | "/css/field.css": "/css/field.css" 4 | } 5 | -------------------------------------------------------------------------------- /nova.mix.js: -------------------------------------------------------------------------------- 1 | const mix = require('laravel-mix') 2 | const webpack = require('webpack') 3 | const path = require('path') 4 | 5 | class NovaExtension { 6 | name() { 7 | return 'nova-extension' 8 | } 9 | 10 | register(name) { 11 | this.name = name 12 | } 13 | 14 | webpackPlugins() { 15 | return new webpack.ProvidePlugin({ 16 | _: 'lodash', 17 | Errors: 'form-backend-validation', 18 | }) 19 | } 20 | 21 | webpackConfig(webpackConfig) { 22 | webpackConfig.externals = { 23 | vue: 'Vue', 24 | } 25 | 26 | webpackConfig.resolve.alias = { 27 | ...(webpackConfig.resolve.alias || {}), 28 | 'laravel-nova': path.join( 29 | __dirname, 30 | '../../vendor/laravel/nova/resources/js/mixins/packages.js' 31 | ), 32 | } 33 | 34 | webpackConfig.output = { 35 | uniqueName: this.name, 36 | } 37 | } 38 | } 39 | 40 | mix.extend('nova', new NovaExtension()) 41 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "version": "1.0.28", 4 | "scripts": { 5 | "dev": "npm run development", 6 | "development": "mix", 7 | "watch": "mix watch", 8 | "watch-poll": "mix watch -- --watch-options-poll=1000", 9 | "hot": "mix watch --hot", 10 | "prod": "npm run production", 11 | "production": "mix --production", 12 | "nova:install": "npm --prefix='../../vendor/laravel/nova' ci", 13 | "check-format": "prettier --list-different './resources/**/*.{js,vue}'", 14 | "format": "prettier --write './resources/**/*.{js,vue}'", 15 | "lint": "eslint resources/js --fix --ext js,vue", 16 | "version": "auto-changelog -p && git add CHANGELOG.md && composer update" 17 | }, 18 | "devDependencies": { 19 | "@vue/compiler-sfc": "^3.2.22", 20 | "auto-changelog": "^2.4.0", 21 | "eslint-config-prettier": "^8.4.0", 22 | "eslint-plugin-vue": "^8.7.1", 23 | "form-backend-validation": "^2.3.3", 24 | "laravel-mix": "^6.0.41", 25 | "laravel-nova": "^1.12.3", 26 | "lodash": "^4.17.21", 27 | "postcss": "^8.3.11", 28 | "prettier": "^2.5.1", 29 | "vue-loader": "^16.8.3" 30 | }, 31 | "dependencies": { 32 | "vue": "^3.0" 33 | }, 34 | "name": "nova-button", 35 | "repository": "git@github.com:sietse85/nova-button", 36 | "author": "Sietse Sietsma ", 37 | "license": "MIT" 38 | } 39 | -------------------------------------------------------------------------------- /resources/css/field.css: -------------------------------------------------------------------------------- 1 | /* Nova Field CSS */ 2 | -------------------------------------------------------------------------------- /resources/field.js: -------------------------------------------------------------------------------- 1 | import { Inertia } from '@inertiajs/inertia'; 2 | import { queue } from './js/queue'; 3 | 4 | export default { 5 | data() { 6 | return { 7 | isModalOpen: false, 8 | }; 9 | }, 10 | methods: { 11 | reload() { 12 | if (this.field.reload && queue.allowsReload()) { 13 | window.setTimeout(() => { 14 | Inertia.reload() 15 | }, 200); 16 | } 17 | }, 18 | modalReload() { 19 | window.setTimeout(() => { 20 | this.isModalOpen = false; 21 | this.reload(); 22 | }, 400); 23 | }, 24 | }, 25 | }; 26 | -------------------------------------------------------------------------------- /resources/js/components/ConfirmModal.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 46 | 47 | 68 | -------------------------------------------------------------------------------- /resources/js/components/DetailField.vue: -------------------------------------------------------------------------------- 1 | 42 | 43 | 54 | -------------------------------------------------------------------------------- /resources/js/components/FormField.vue: -------------------------------------------------------------------------------- 1 | 37 | 38 | 49 | -------------------------------------------------------------------------------- /resources/js/components/IndexField.vue: -------------------------------------------------------------------------------- 1 | 35 | 36 | 47 | -------------------------------------------------------------------------------- /resources/js/components/NovaButton.vue: -------------------------------------------------------------------------------- 1 | 16 | 17 | 28 | 29 | 204 | -------------------------------------------------------------------------------- /resources/js/field.js: -------------------------------------------------------------------------------- 1 | import IndexField from './components/IndexField'; 2 | import DetailField from './components/DetailField'; 3 | import FormField from './components/FormField'; 4 | import NovaButton from './components/NovaButton'; 5 | import Modal from './components/ConfirmModal'; 6 | 7 | Nova.booting((app) => { 8 | app.component('confirm-modal', Modal); 9 | app.component('nova-button', NovaButton); 10 | app.component('index-nova-button', IndexField); 11 | app.component('detail-nova-button', DetailField); 12 | app.component('form-nova-button', FormField); 13 | }); 14 | -------------------------------------------------------------------------------- /resources/js/queue.js: -------------------------------------------------------------------------------- 1 | class Queue { 2 | constructor() { 3 | this.items = []; 4 | this.hasSuccess = false; 5 | this.hasError = false; 6 | } 7 | 8 | add(id) { 9 | this.items.push(id); 10 | } 11 | 12 | remove(id) { 13 | this.items = this.items.filter((item) => { 14 | return id !== item; 15 | }); 16 | } 17 | 18 | count() { 19 | return this.items.length; 20 | } 21 | 22 | allowsReload() { 23 | return this.count() === 0 && this.hasSuccess && this.hasError === false; 24 | } 25 | } 26 | 27 | export let queue = new Queue(); 28 | -------------------------------------------------------------------------------- /routes/api.php: -------------------------------------------------------------------------------- 1 | text = $name; 88 | $this->key = $attribute ?? Str::kebab($name); 89 | $this->config = config('nova-button'); 90 | $this->indexName = $name; 91 | 92 | $this->addDefaultSettings(); 93 | } 94 | 95 | /** 96 | * Add default settings 97 | * 98 | * @return void 99 | */ 100 | protected function addDefaultSettings(): void 101 | { 102 | $this->addLinkFallbacks(); 103 | $this->style = Arr::get($this->config, 'defaults.style', 'link-primary'); 104 | $this->loadingText = Arr::get($this->config, 'defaults.loadingText', 'Loading'); 105 | $this->loadingStyle = Arr::get($this->config, 'defaults.loadingStyle', str_replace('primary', 'grey', $this->style)); 106 | $this->errorText = Arr::get($this->config, 'defaults.errorText', 'Error!'); 107 | $this->errorStyle = Arr::get($this->config, 'defaults.errorStyle', str_replace('primary', 'danger', $this->style)); 108 | $this->successText = Arr::get($this->config, 'defaults.successText', 'Success!'); 109 | $this->successStyle = Arr::get($this->config, 'defaults.successStyle', str_replace('primary', 'success', $this->style)); 110 | 111 | } 112 | 113 | /** 114 | * Add link fallbacks 115 | * 116 | * @return void 117 | */ 118 | protected function addLinkFallbacks(): void 119 | { 120 | if (!Arr::has($this->config, 'styles.link-primary')) { 121 | $this->config['styles']['link-primary'] = 'cursor-pointer inline-block text-gray-50 text-black font-bold'; 122 | } 123 | 124 | if (!Arr::has($this->config, 'styles.link-success')) { 125 | $this->config['styles']['link-success'] = 'cursor-pointer inline-block text-green-500 font-bold'; 126 | } 127 | 128 | if (!Arr::has($this->config, 'styles.link-grey')) { 129 | $this->config['styles']['link-grey'] = 'cursor-pointer inline-block text-grey-500 font-bold'; 130 | } 131 | 132 | if (!Arr::has($this->config, 'styles.link-danger')) { 133 | $this->config['styles']['link-danger'] = 'cursor-pointer inline-block text-red-500 font-bold'; 134 | } 135 | } 136 | 137 | /** 138 | * Resolve the field's value. 139 | * 140 | * @param mixed $resource 141 | * @param ?string $attribute 142 | * @return void 143 | */ 144 | public function resolve($resource, $attribute = null): void 145 | { 146 | parent::resolve($resource, $attribute); 147 | 148 | $this->model = get_class($resource); 149 | $this->classes[] = 'nova-button-' . strtolower(class_basename($resource)); 150 | $this->classes[] = Arr::get($this->config, "styles.$this->style"); 151 | $this->loadingClasses = Arr::get($this->config, "styles.$this->loadingStyle"); 152 | $this->successClasses = Arr::get($this->config, "styles.$this->successStyle"); 153 | $this->errorClasses = Arr::get($this->config, "styles.$this->errorStyle"); 154 | 155 | $this->withMeta([ 156 | 'text' => $this->text, 157 | 'action' => $this->action, 158 | 'key' => $this->key, 159 | 'loadingText' => $this->loadingText, 160 | 'model' => $this->model, 161 | 'successText' => $this->successText, 162 | 'errorText' => $this->errorText, 163 | 'confirm' => $this->confirm, 164 | 'reload' => $this->reload, 165 | 'event' => $this->event, 166 | 'visible' => $this->visible, 167 | 'disabled' => $this->disabled, 168 | 'title' => $this->title, 169 | 'label' => $this->label, 170 | 'indexName' => $this->indexName, 171 | 'classes' => $this->uniqueClasses(), 172 | 'type' => $this->type, 173 | 'route' => $this->route, 174 | 'link' => $this->link, 175 | 'indexAlign' => $this->indexAlign, 176 | 'modalClasses' => $this->modalClasses, 177 | 'loadingClasses' => $this->loadingClasses, 178 | 'successClasses' => $this->successClasses, 179 | 'errorClasses' => $this->errorClasses, 180 | ]); 181 | } 182 | 183 | /** 184 | * Enable the confirmation button type. 185 | * 186 | * @param ?string $message1 187 | * @param ?string $message2 188 | * @param ?string $cancelButtonText 189 | * @return $this 190 | */ 191 | public function confirm(?string $message1 = null, ?string $message2 = null, ?string $cancelButtonText = null): self 192 | { 193 | $this->confirm = [ 194 | 'title' => __('Confirmation'), 195 | 'body' => null, 196 | 'cancelButtonText' => $cancelButtonText ?: __('Cancel'), 197 | ]; 198 | 199 | if ($message1 !== null && $message2 === null) { 200 | $this->confirm['body'] = $message1; 201 | } 202 | 203 | if ($message1 !== null && $message2 !== null) { 204 | $this->confirm['title'] = $message1; 205 | $this->confirm['body'] = $message2; 206 | } 207 | 208 | return $this; 209 | } 210 | 211 | /** 212 | * Set the model class on which to trigger the action, use fully qualified name 213 | * 214 | * @param string|null $model 215 | * @return Button 216 | */ 217 | public function modelForAction(?string $model): self 218 | { 219 | $this->model = $model; 220 | 221 | return $this; 222 | } 223 | 224 | /** 225 | * Set an action to trigger 226 | * 227 | * @param string|null $action 228 | * @return Button 229 | */ 230 | public function action(?string $action): self 231 | { 232 | $this->action = $action; 233 | 234 | return $this; 235 | } 236 | 237 | /** 238 | * Enable the reload button type. 239 | * 240 | * @param bool $reload 241 | * @return $this 242 | */ 243 | public function reload(bool $reload = true): self 244 | { 245 | $this->reload = $reload; 246 | 247 | return $this; 248 | } 249 | 250 | /** 251 | * Enable the event button type. 252 | * 253 | * @param string $event 254 | * @return $this 255 | */ 256 | public function event(string $event): self 257 | { 258 | $this->event = $event; 259 | 260 | return $this; 261 | } 262 | 263 | /** 264 | * Set the button visibility. 265 | * 266 | * @param bool $condition 267 | * @return $this 268 | */ 269 | public function visible(bool $condition): self 270 | { 271 | $this->visible = $condition; 272 | 273 | return $this; 274 | } 275 | 276 | /** 277 | * Set the button disabled state. 278 | * 279 | * @param bool $condition 280 | * @return $this 281 | */ 282 | public function disabled(bool $condition = true): self 283 | { 284 | $this->disabled = $condition; 285 | 286 | return $this; 287 | } 288 | 289 | /** 290 | * Set the loading text. 291 | * 292 | * @param string $loadingText 293 | * @return $this 294 | */ 295 | public function loadingText(string $loadingText): self 296 | { 297 | $this->loadingText = $loadingText; 298 | 299 | return $this; 300 | } 301 | 302 | /** 303 | * Set the success text. 304 | * 305 | * @param string $successText 306 | * @return $this 307 | */ 308 | public function successText(string $successText): self 309 | { 310 | $this->successText = $successText; 311 | 312 | return $this; 313 | } 314 | 315 | /** 316 | * Set the error text. 317 | * 318 | * @param string $errorText 319 | * @return $this 320 | */ 321 | public function errorText(string $errorText): self 322 | { 323 | $this->errorText = $errorText; 324 | 325 | return $this; 326 | } 327 | 328 | /** 329 | * Set the title. 330 | * 331 | * @param string $title 332 | * @return $this 333 | */ 334 | public function title(string $title): self 335 | { 336 | $this->title = $title; 337 | 338 | return $this; 339 | } 340 | 341 | /** 342 | * Set the label. 343 | * 344 | * @param string $label 345 | * @return $this 346 | */ 347 | public function label(string $label): self 348 | { 349 | $this->label = $label; 350 | 351 | return $this; 352 | } 353 | 354 | /** 355 | * Set the index name. 356 | * 357 | * @param ?string $indexName 358 | * @return $this 359 | */ 360 | public function indexName(?string $indexName = null): self 361 | { 362 | $this->indexName = $indexName; 363 | 364 | return $this; 365 | } 366 | 367 | /** 368 | * Set the index alignment to the right. 369 | * 370 | * @param Closure|bool $enabled 371 | * @return $this 372 | */ 373 | public function indexAlignRight($enabled = true): self 374 | { 375 | $this->indexAlign = value($enabled) ? 'right' : 'left'; 376 | 377 | return $this; 378 | } 379 | 380 | /** 381 | * Set the classes. 382 | * 383 | * @param ...$classes 384 | * @return $this 385 | */ 386 | public function classes(...$classes): self 387 | { 388 | $this->classes = array_merge($this->classes, ...$classes); 389 | 390 | return $this; 391 | } 392 | 393 | /** 394 | * Set the classes. 395 | * 396 | * @param ...$classes 397 | * @return $this 398 | */ 399 | public function modalClasses(...$classes): self 400 | { 401 | $this->modalClasses = array_merge($this->modalClasses, ...$classes); 402 | 403 | return $this; 404 | } 405 | 406 | /** 407 | * Unique css classes 408 | * 409 | * @return string 410 | */ 411 | private function uniqueClasses(): string 412 | { 413 | $unique = []; 414 | foreach ($this->classes as $class) { 415 | if (!in_array($class, $unique)) { 416 | $unique[] = $class; 417 | } 418 | } 419 | 420 | return implode(' ', $unique); 421 | } 422 | 423 | /** 424 | * Set the style. 425 | * 426 | * @param string $style 427 | * @return $this 428 | */ 429 | public function style(string $style): self 430 | { 431 | $this->style = $style; 432 | 433 | return $this; 434 | } 435 | 436 | /** 437 | * Set the loading style. 438 | * 439 | * @param string $loadingStyle 440 | * @return $this 441 | */ 442 | public function loadingStyle(string $loadingStyle): self 443 | { 444 | $this->loadingStyle = $loadingStyle; 445 | 446 | return $this; 447 | } 448 | 449 | /** 450 | * Set the success style. 451 | * 452 | * @param string $successStyle 453 | * @return $this 454 | */ 455 | public function successStyle(string $successStyle): self 456 | { 457 | $this->successStyle = $successStyle; 458 | 459 | return $this; 460 | } 461 | 462 | /** 463 | * Set the error style. 464 | * 465 | * @param string $errorStyle 466 | * @return $this 467 | */ 468 | public function errorStyle(string $errorStyle): self 469 | { 470 | $this->errorStyle = $errorStyle; 471 | 472 | return $this; 473 | } 474 | 475 | /** 476 | * Set the index route. 477 | * 478 | * @param string $namespace 479 | * @return $this 480 | */ 481 | public function index(string $namespace): self 482 | { 483 | $this->route('index', [ 484 | 'resourceName' => $this->normalizeResourceName($namespace), 485 | ]); 486 | 487 | return $this; 488 | } 489 | 490 | /** 491 | * Set the detail route. 492 | * 493 | * @param string $namespace 494 | * @param int|string $id 495 | * @return $this 496 | */ 497 | public function detail(string $namespace, $id): self 498 | { 499 | $this->route('detail', [ 500 | 'resourceName' => $this->normalizeResourceName($namespace), 501 | 'resourceId' => $id, 502 | ]); 503 | 504 | return $this; 505 | } 506 | 507 | /** 508 | * Set the create route. 509 | * 510 | * @param string $namespace 511 | * @return $this 512 | */ 513 | public function create(string $namespace): self 514 | { 515 | $this->route('create', [ 516 | 'resourceName' => $this->normalizeResourceName($namespace), 517 | ]); 518 | 519 | return $this; 520 | } 521 | 522 | /** 523 | * Set the edit route. 524 | * 525 | * @param string $namespace 526 | * @param int|string $id 527 | * @return $this 528 | */ 529 | public function edit(string $namespace, $id): self 530 | { 531 | $this->route('edit', [ 532 | 'resourceName' => $this->normalizeResourceName($namespace), 533 | 'resourceId' => $id, 534 | ]); 535 | 536 | return $this; 537 | } 538 | 539 | /** 540 | * Set the lens route. 541 | * 542 | * @param string $namespace 543 | * @param string $key 544 | * @return $this 545 | */ 546 | public function lens(string $namespace, string $key): self 547 | { 548 | $this->route('lens', [ 549 | 'resourceName' => $this->normalizeResourceName($namespace), 550 | 'lens' => $key, 551 | ]); 552 | 553 | return $this; 554 | } 555 | 556 | /** 557 | * Set the link. 558 | * 559 | * @param string $href 560 | * @param string $target 561 | * @return $this 562 | */ 563 | public function link(string $href, string $target = '_blank'): self 564 | { 565 | $this->type = 'link'; 566 | $this->link = compact('href', 'target'); 567 | 568 | return $this; 569 | } 570 | 571 | /** 572 | * Set the route. 573 | * 574 | * @param string $name 575 | * @param array $params 576 | * @return $this 577 | */ 578 | public function route(string $name, array $params = []): self 579 | { 580 | $this->type = 'route'; 581 | $this->route = [ 582 | 'name' => $name, 583 | 'params' => $params, 584 | 'query' => [], 585 | ]; 586 | 587 | return $this; 588 | } 589 | 590 | /** 591 | * Set the route params. 592 | * 593 | * @param array $params 594 | * @return $this 595 | */ 596 | public function withParams(array $params): self 597 | { 598 | $this->route['query'] = array_merge($this->route['query'] ?? [], $params); 599 | 600 | return $this; 601 | } 602 | 603 | /** 604 | * Set the index filters. 605 | * 606 | * @param array $filters 607 | * @return $this 608 | */ 609 | public function withFilters(array $filters): self 610 | { 611 | $resourceName = $this->route['params']['resourceName'] ?? null; 612 | 613 | if ($resourceName === null) { 614 | return $this; 615 | } 616 | 617 | $key = $resourceName . '_filter'; 618 | 619 | $query = collect($filters) 620 | ->map(function ($value, $key) { 621 | return [ 622 | 'class' => $key, 623 | 'value' => $value, 624 | ]; 625 | })->values(); 626 | 627 | $this->route['query'][$key] = base64_encode(json_encode($query)); 628 | 629 | return $this; 630 | } 631 | 632 | /** 633 | * Normalize resourceName 634 | * 635 | * @param string $namespace 636 | * @return string 637 | */ 638 | protected function normalizeResourceName(string $namespace): string 639 | { 640 | return class_exists($namespace) && is_subclass_of($namespace, Resource::class) 641 | ? $namespace::uriKey() : $namespace; 642 | } 643 | } 644 | -------------------------------------------------------------------------------- /src/Events/ButtonClick.php: -------------------------------------------------------------------------------- 1 | resource = $resource; 18 | $this->key = $key; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/FieldServiceProvider.php: -------------------------------------------------------------------------------- 1 | routes(); 26 | } 27 | 28 | /** 29 | * Register the tool's routes. 30 | * 31 | * @return void 32 | */ 33 | protected function routes() 34 | { 35 | if ($this->app->routesAreCached()) { 36 | return; 37 | } 38 | 39 | Route::middleware(['nova', Authenticate::class]) 40 | ->prefix('nova-vendor/sietse85/nova-button') 41 | ->group(__DIR__.'/../routes/api.php'); 42 | } 43 | 44 | /** 45 | * Register any application services. 46 | * 47 | * @return void 48 | */ 49 | public function register() 50 | { 51 | if ($this->app->runningInConsole()) { 52 | $this->publishes([ 53 | __DIR__ . '/../config/' => config_path(), 54 | ], 'nova-button-config'); 55 | } 56 | 57 | $this->mergeConfigFrom(__DIR__ . '/../config/nova-button.php', 'nova-button'); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/Http/Controllers/ButtonController.php: -------------------------------------------------------------------------------- 1 | get('event'); 24 | 25 | try { 26 | $resource = $request->findModelQuery()->first(); 27 | } catch (NotFoundHttpException $e) { 28 | $resource = null; 29 | } 30 | 31 | event(new $event($resource, $request->route('buttonKey'))); 32 | 33 | return response('ok', 200); 34 | } 35 | 36 | /** 37 | * Trigger action 38 | * 39 | * @param NovaRequest $request 40 | * @return mixed 41 | */ 42 | public function triggerAction(NovaRequest $request) 43 | { 44 | $actionClass = $request->get('actionClass'); 45 | $resourceId = $request->get('resourceId'); 46 | $model = $request->get('model'); 47 | 48 | $query = $model::query(); 49 | if ($query->hasMacro('withTrashed')) $query->withTrashed(); 50 | $result = $query->find($resourceId); 51 | 52 | $action = new $actionClass; 53 | $actionFields = new ActionFields(collect(), collect()); 54 | 55 | return $action->handle($actionFields, collect([$result])); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /webpack.mix.js: -------------------------------------------------------------------------------- 1 | let mix = require('laravel-mix') 2 | let path = require('path') 3 | 4 | require('./nova.mix') 5 | 6 | mix 7 | .setPublicPath('dist') 8 | .js('resources/js/field.js', 'js') 9 | .vue({ version: 3 }) 10 | .css('resources/css/field.css', 'css') 11 | .nova('sietse85/nova-button') 12 | --------------------------------------------------------------------------------