├── .editorconfig ├── .github ├── dependabot.yml └── workflows │ ├── front-lint.yml │ └── php-lint.yml ├── .gitignore ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── UPGRADING.md ├── composer.json ├── config └── nova-cards.php ├── dist ├── .vite │ └── manifest.json ├── css │ └── card.css └── js │ └── entry.js ├── duster.json ├── package.json ├── pint.json ├── postcss.config.cjs ├── resources ├── css │ └── card.css └── js │ ├── cards │ ├── Calendar.vue │ ├── Countdown.vue │ ├── Embed.vue │ ├── Environment.vue │ ├── Greeter.vue │ ├── Html.vue │ ├── Linkable.vue │ ├── Percentage.vue │ ├── ScheduledJobs.vue │ ├── Ssl.vue │ ├── SystemResources.vue │ ├── Versions.vue │ ├── Weather.vue │ └── WorldClock.vue │ ├── components │ ├── Card.vue │ ├── ToolbarButton.vue │ └── WorldClockTimer.vue │ ├── composables │ └── useCurrentTime.js │ └── entry.js ├── routes └── api.php ├── screenshots ├── cards-2-dark.png ├── cards-2.png ├── cards-dark.png ├── cards-mobile.png └── cards.png ├── src ├── Cards │ ├── CalendarCard.php │ ├── CountdownCard.php │ ├── EmbedCard.php │ ├── EnvironmentCard.php │ ├── GreeterCard.php │ ├── HtmlCard.php │ ├── LinkableCard.php │ ├── PercentageCard.php │ ├── ScheduledJobsCard.php │ ├── SslCard.php │ ├── SystemResourcesCard.php │ ├── VersionsCard.php │ ├── WeatherCard.php │ └── WorldClockCard.php ├── Http │ └── Controllers │ │ ├── ScheduledJobsController.php │ │ ├── SslController.php │ │ ├── SystemResourcesController.php │ │ ├── VersionsController.php │ │ ├── WeatherController.php │ │ └── WorldClockController.php ├── LaravelMarkdownConverter.php ├── MarkdownConverter.php ├── NovaCardsServiceProvider.php └── Traits │ └── PollingTrait.php ├── tailwind.config.js ├── vite.config.js └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | insert_final_newline = true 7 | indent_style = space 8 | indent_size = 4 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | [*.{yml,yaml}] 15 | indent_size = 2 16 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "composer" 4 | directory: "/" # Location of package manifests 5 | schedule: 6 | interval: "daily" 7 | 8 | - package-ecosystem: "npm" 9 | directory: "/" 10 | schedule: 11 | interval: "daily" 12 | # Always increase the version requirement 13 | # to match the new version. 14 | versioning-strategy: increase 15 | -------------------------------------------------------------------------------- /.github/workflows/front-lint.yml: -------------------------------------------------------------------------------- 1 | # .github/workflows/duster.yml 2 | name: Front lint 3 | 4 | on: 5 | push: 6 | branches: main 7 | pull_request: 8 | 9 | env: 10 | NODE_VERSION: 20.10.0 11 | 12 | jobs: 13 | application-test: 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v3 18 | 19 | - name: Setup Node 20 | uses: actions/setup-node@v3 21 | with: 22 | node-version: ${{env.NODE_VERSION}} 23 | cache: "npm" 24 | 25 | - name: "Setup PHP" 26 | uses: "shivammathur/setup-php@v2" 27 | with: 28 | php-version: "latest" 29 | 30 | - name: "composer install" 31 | run: composer install --no-cache --ignore-platform-reqs --no-interaction --prefer-dist --optimize-autoloader --apcu-autoloader 32 | 33 | 34 | - run: npm i 35 | - run: npm run nova:install 36 | - run: npm run build 37 | -------------------------------------------------------------------------------- /.github/workflows/php-lint.yml: -------------------------------------------------------------------------------- 1 | # .github/workflows/duster.yml 2 | name: PHP Lint 3 | 4 | on: 5 | push: 6 | branches: main 7 | pull_request: 8 | 9 | jobs: 10 | php-lint: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v3 15 | 16 | - name: "Setup PHP" 17 | uses: "shivammathur/setup-php@v2" 18 | with: 19 | php-version: "latest" 20 | 21 | - name: "composer install" 22 | run: composer install --no-cache --ignore-platform-reqs --no-interaction --prefer-dist --optimize-autoloader --apcu-autoloader 23 | 24 | - name: "duster" 25 | uses: tighten/duster-action@v2 26 | with: 27 | args: lint --using=phpstan,tlint,phpcs,pint 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # Mac OS X 4 | .DS_Store 5 | ._.* 6 | ._* 7 | 8 | # Ignore local editor 9 | .project 10 | .settings 11 | /.idea 12 | /.vscode 13 | *.swp 14 | tags 15 | nbproject/* 16 | 17 | # Windows 18 | Thumbs.db 19 | 20 | auth.json 21 | npm-debug.log 22 | yarn-error.log 23 | 24 | .env 25 | .env.backup 26 | phpunit.xml 27 | .phpunit.result.cache 28 | docker-compose.override.yml 29 | Homestead.json 30 | Homestead.yaml 31 | 32 | config/version.yml 33 | 34 | package-lock.json 35 | composer.phar 36 | composer.lock 37 | yarn.lock 38 | 39 | _ide_helper.php 40 | _ide_helper_models.php 41 | .phpstorm.meta.php 42 | lighthouse-audit* 43 | .nova 44 | 45 | /node_modules 46 | /vendor 47 | /packages 48 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Release Notes 2 | -------------------------------------------------------------------------------- /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-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer). 44 | 45 | - **Add tests!** - Your patch won't be accepted if it doesn't have tests. 46 | 47 | - **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date. 48 | 49 | - **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option. 50 | 51 | - **One pull request per feature** - If you want to do more than one thing, send multiple pull requests. 52 | 53 | - **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. 54 | 55 | **Happy coding**! 56 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # The MIT License (MIT) 2 | 3 | Copyright (c) 2022 Artem Stepanenko 4 | 5 | > Permission is hereby granted, free of charge, to any person obtaining a copy 6 | > of this software and associated documentation files (the "Software"), to deal 7 | > in the Software without restriction, including without limitation the rights 8 | > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | > copies of the Software, and to permit persons to whom the Software is 10 | > furnished to do so, subject to the following conditions: 11 | > 12 | > The above copyright notice and this permission notice shall be included in 13 | > all copies or substantial portions of the Software. 14 | > 15 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | > THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Cards for Laravel Nova 3 | 4 | [![Latest Version on Packagist](https://img.shields.io/packagist/v/stepanenko3/nova-cards.svg?style=flat-square)](https://packagist.org/packages/stepanenko3/nova-cards) 5 | [![Total Downloads](https://img.shields.io/packagist/dt/stepanenko3/nova-cards.svg?style=flat-square)](https://packagist.org/packages/stepanenko3/nova-cards) 6 | [![License](https://poser.pugx.org/stepanenko3/nova-cards/license)](https://packagist.org/packages/stepanenko3/nova-cards) 7 | 8 | ![screenshot of cards](screenshots/cards.png) 9 | ![screenshot of cards](screenshots/cards-2.png) 10 | 11 | ## List of Cards 12 | 13 | - BlockchainExchangeCard (deleted) 14 | - CacheCard (Use stepanenkoe/nova-command-runner for cache manipulations) 15 | - CountdownCard 16 | - EmbedCard 17 | - EnvironmentCard 18 | - HtmlCard 19 | - LinkableCard 20 | - PercentageCard 21 | - ScheduledJobsCard 22 | - SslCard 23 | - SystemResourcesCard 24 | - VersionsCard 25 | - WorldClockCard 26 | - WeatherCard 27 | - CalendarCard 28 | - NovaReleaseCard (Use stepanenko3/nova-health for outdated packages) 29 | - GreetingCard 30 | 31 | ## Requirements 32 | 33 | - `php: >=8.0` 34 | - `laravel/nova: ^4.0` 35 | 36 | ## Installation 37 | 38 | ```bash 39 | # Install the package 40 | composer require stepanenko3/nova-cards 41 | ``` 42 | 43 | Register the cards with Nova in the `cards()` method of the your Dashboards class: 44 | 45 | ```php 46 | // in app/Nova/Dashborads/Cards.php 47 | 48 | use Stepanenko3\NovaCards\Cards\GreetingCard; 49 | use Stepanenko3\NovaCards\Cards\CountdownCard; 50 | use Stepanenko3\NovaCards\Cards\EmbedCard; 51 | use Stepanenko3\NovaCards\Cards\EnvironmentCard; 52 | use Stepanenko3\NovaCards\Cards\HtmlCard; 53 | use Stepanenko3\NovaCards\Cards\LinkableCard; 54 | use Stepanenko3\NovaCards\Cards\PercentageCard; 55 | use Stepanenko3\NovaCards\Cards\ScheduledJobsCard; 56 | use Stepanenko3\NovaCards\Cards\SslCard; 57 | use Stepanenko3\NovaCards\Cards\SystemResourcesCard; 58 | use Stepanenko3\NovaCards\Cards\VersionsCard; 59 | use Stepanenko3\NovaCards\Cards\WorldClockCard; 60 | use Stepanenko3\NovaCards\Cards\WeatherCard; 61 | use Stepanenko3\NovaCards\Cards\CalendarCard; 62 | 63 | public function cards() 64 | { 65 | $user = auth()->user(); 66 | 67 | return [ 68 | GreeterCard::make() 69 | ->user( 70 | name: $user->name, 71 | title: 'Admin', 72 | ) 73 | ->message( 74 | text: 'Welcome back,', 75 | ) 76 | ->button( 77 | name: 'Profile', 78 | target: '/nova/resources/users/' . $user->id, 79 | ) 80 | ->button( 81 | name: 'Users', 82 | target: '/nova/resources/users', 83 | ) 84 | ->avatar( 85 | url: $user->avatar 86 | ? storage_url($user->avatar, 'public') 87 | : 'https://ui-avatars.com/api/?size=300&color=7F9CF5&background=EBF4FF&name=' . $user->name 88 | ), 89 | 90 | (new WeatherCard) 91 | ->pollingTime(60000) // Optional 92 | ->startPolling(), // Optional. Auto start polling 93 | 94 | (new CalendarCard), 95 | 96 | (new LinkableCard) 97 | ->title('Docs') // Required 98 | ->subtitle('subtitle') // Optional 99 | ->url('/') // Required 100 | ->target('_blank'), // Default: _self 101 | 102 | (new SystemResourcesCard), 103 | 104 | (new VersionsCard), 105 | 106 | (new ScheduledJobsCard) 107 | ->startPolling() // Optional. Auto start polling 108 | ->pollingTime(1000) 109 | ->width('1/2'), 110 | 111 | (new EnvironmentCard), 112 | 113 | (new SslCard) 114 | ->domain('test.com'), // Required 115 | 116 | (new SslCard) 117 | ->domain('laravel.com'), // Required 118 | 119 | (new HtmlCard) 120 | ->width('1/3') 121 | ->html('

Hello World!

'), // Required 122 | 123 | (new HtmlCard) 124 | ->width('1/3') 125 | ->markdown('# Hello World!'), // Required 126 | 127 | (new HtmlCard) 128 | ->width('1/3') 129 | ->view('cards.hello', ['name' => 'World']), // Required 130 | 131 | (new PercentageCard) 132 | ->name('Demo percents') // Optional 133 | ->label('$') // Optional 134 | ->count(33) // Required 135 | ->total(1000) // Required 136 | ->percentagePrecision(2), // Default: 2 137 | 138 | (new CountdownCard) 139 | ->to(now()->addDays(30)) // Required 140 | ->title('30 Days Later') // Optional 141 | ->label('30 Days Later'), // Optional 142 | 143 | (new WorldClockCard()) 144 | ->timezones([ // Required 145 | 'Europe/Kiev', 146 | 'Asia/Tehran', 147 | 'America/new_york', 148 | 'America/los_angeles', 149 | ]) 150 | ->title(__('World Clock')), // Optional 151 | 152 | // A most simple embed 153 | (new EmbedCard) 154 | ->url('https://www.youtube.com/embed/WhWc3b3KhnY'), // Required 155 | 156 | // A more complex embed of raw HTML 157 | (new EmbedCard) 158 | ->withoutPadding() // Optional remove padding in card 159 | ->url('https://www.youtube.com/embed/WhWc3b3KhnY'), // Required 160 | ]; 161 | } 162 | ``` 163 | 164 | ## Usage 165 | 166 | Open your Dashboard in your Nova app to see the cards. 167 | 168 | ## Screenshots 169 | 170 | ![screenshot of cards](screenshots/cards-dark.png) 171 | ![screenshot of cards](screenshots/cards-2-dark.png) 172 | ![screenshot of cards](screenshots/cards-mobile.png) 173 | 174 | ## Credits 175 | 176 | - [Artem Stepanenko](https://github.com/stepanenko3) 177 | 178 | ## Contributing 179 | 180 | Thank you for considering contributing to this package! Please create a pull request with your contributions with detailed explanation of the changes you are proposing. 181 | 182 | ## License 183 | 184 | This package is open-sourced software licensed under the [MIT license](LICENSE.md). 185 | -------------------------------------------------------------------------------- /UPGRADING.md: -------------------------------------------------------------------------------- 1 | # Upgrading 2 | 3 | ## To 1.0.0 4 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "stepanenko3/nova-cards", 3 | "description": "A Laravel Nova info cards.", 4 | "keywords": [ 5 | "laravel", 6 | "nova", 7 | "cards" 8 | ], 9 | "license": "MIT", 10 | "require": { 11 | "php": ">=8.0", 12 | "erusev/parsedown": "^1.7", 13 | "laravel/framework": "^10.0|^11.0|^12.0", 14 | "laravel/nova": "^5.0", 15 | "spatie/ssl-certificate": "^2.0", 16 | "stepanenko3/laravel-system-resources": "^1.1.1", 17 | "stepanenko3/laravel-helpers": "^1.3.2" 18 | }, 19 | "autoload": { 20 | "psr-4": { 21 | "Stepanenko3\\NovaCards\\": "src/" 22 | } 23 | }, 24 | "extra": { 25 | "laravel": { 26 | "providers": [ 27 | "Stepanenko3\\NovaCards\\NovaCardsServiceProvider" 28 | ] 29 | } 30 | }, 31 | "config": { 32 | "sort-packages": true 33 | }, 34 | "minimum-stability": "dev", 35 | "prefer-stable": true, 36 | "repositories": [ 37 | { 38 | "type": "composer", 39 | "url": "https://laravelsatis.com" 40 | } 41 | ], 42 | "require-dev": { 43 | "phpstan/phpstan": "^2.0", 44 | "tightenco/duster": "^3.0" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /config/nova-cards.php: -------------------------------------------------------------------------------- 1 | env('OPENWAETHER_API_KEY', env('OPEN_WEATHER_TOKEN', '')), 5 | ]; 6 | -------------------------------------------------------------------------------- /dist/.vite/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "resources/js/entry.js": { 3 | "file": "js/entry.js", 4 | "name": "entry", 5 | "src": "resources/js/entry.js", 6 | "isEntry": true 7 | }, 8 | "style.css": { 9 | "file": "css/card.css", 10 | "src": "style.css" 11 | } 12 | } -------------------------------------------------------------------------------- /dist/css/card.css: -------------------------------------------------------------------------------- 1 | .nova-cards :is(.sr-only){position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0}.nova-cards :is(.invisible){visibility:hidden}.nova-cards :is(.absolute){position:absolute}.nova-cards :is(.relative){position:relative}.nova-cards :is(.isolate){isolation:isolate}.nova-cards :is(.mx-auto){margin-left:auto;margin-right:auto}.nova-cards :is(.mb-1){margin-bottom:.25rem}.nova-cards :is(.mb-2){margin-bottom:.5rem}.nova-cards :is(.mb-4){margin-bottom:1rem}.nova-cards :is(.mr-1){margin-right:.25rem}.nova-cards :is(.mr-1\.5){margin-right:.375rem}.nova-cards :is(.mr-2){margin-right:.5rem}.nova-cards :is(.mr-6){margin-right:1.5rem}.nova-cards :is(.mt-1){margin-top:.25rem}.nova-cards :is(.mt-3){margin-top:.75rem}.nova-cards :is(.mt-4){margin-top:1rem}.nova-cards :is(.mt-6){margin-top:1.5rem}.nova-cards :is(.flex){display:flex}.nova-cards :is(.inline-flex){display:inline-flex}.nova-cards :is(.table){display:table}.nova-cards :is(.grid){display:grid}.nova-cards :is(.h-20){height:5rem}.nova-cards :is(.h-5){height:1.25rem}.nova-cards :is(.h-8){height:2rem}.nova-cards :is(.h-auto){height:auto}.nova-cards :is(.h-full){height:100%}.nova-cards :is(.min-h-40){min-height:10rem}.nova-cards :is(.w-20){width:5rem}.nova-cards :is(.w-5){width:1.25rem}.nova-cards :is(.w-8){width:2rem}.nova-cards :is(.w-full){width:100%}.nova-cards :is(.flex-shrink-0){flex-shrink:0}.nova-cards :is(.flex-grow){flex-grow:1}.nova-cards :is(.transform){transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.nova-cards :is(.grid-cols-1){grid-template-columns:repeat(1,minmax(0,1fr))}.nova-cards :is(.grid-cols-3){grid-template-columns:repeat(3,minmax(0,1fr))}.nova-cards :is(.grid-cols-4){grid-template-columns:repeat(4,minmax(0,1fr))}.nova-cards :is(.flex-row){flex-direction:row}.nova-cards :is(.flex-col){flex-direction:column}.nova-cards :is(.flex-wrap){flex-wrap:wrap}.nova-cards :is(.items-center){align-items:center}.nova-cards :is(.justify-center){justify-content:center}.nova-cards :is(.justify-between){justify-content:space-between}.nova-cards :is(.gap-6){gap:1.5rem}.nova-cards :is(.space-x-4>:not([hidden])~:not([hidden])){--tw-space-x-reverse: 0;margin-right:calc(1rem * var(--tw-space-x-reverse));margin-left:calc(1rem * calc(1 - var(--tw-space-x-reverse)))}.nova-cards :is(.space-y-4>:not([hidden])~:not([hidden])){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.nova-cards :is(.divide-x>:not([hidden])~:not([hidden])){--tw-divide-x-reverse: 0;border-right-width:calc(1px * var(--tw-divide-x-reverse));border-left-width:calc(1px * calc(1 - var(--tw-divide-x-reverse)))}.nova-cards :is(.divide-y>:not([hidden])~:not([hidden])){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.nova-cards :is(.divide-y-0>:not([hidden])~:not([hidden])){--tw-divide-y-reverse: 0;border-top-width:calc(0px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(0px * var(--tw-divide-y-reverse))}.nova-cards :is(.divide-gray-200>:not([hidden])~:not([hidden])){--tw-divide-opacity: 1;border-color:rgb(229 231 235 / var(--tw-divide-opacity))}.nova-cards :is(.overflow-hidden){overflow:hidden}.nova-cards :is(.rounded-full){border-radius:9999px}.nova-cards :is(.rounded-lg){border-radius:.5rem}.nova-cards :is(.border-t){border-top-width:1px}.nova-cards :is(.border-gray-200){--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity))}.nova-cards :is(.bg-gray-50){--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity))}.nova-cards :is(.bg-white){--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity))}.nova-cards :is(.\!p-0){padding:0!important}.nova-cards :is(.p-2){padding:.5rem}.nova-cards :is(.p-3){padding:.75rem}.nova-cards :is(.p-4){padding:1rem}.nova-cards :is(.px-2){padding-left:.5rem;padding-right:.5rem}.nova-cards :is(.px-6){padding-left:1.5rem;padding-right:1.5rem}.nova-cards :is(.py-2){padding-top:.5rem;padding-bottom:.5rem}.nova-cards :is(.py-3){padding-top:.75rem;padding-bottom:.75rem}.nova-cards :is(.py-4){padding-top:1rem;padding-bottom:1rem}.nova-cards :is(.pr-2){padding-right:.5rem}.nova-cards :is(.text-left){text-align:left}.nova-cards :is(.text-center){text-align:center}.nova-cards :is(.align-baseline){vertical-align:baseline}.nova-cards :is(.text-2xl){font-size:1.5rem;line-height:2rem}.nova-cards :is(.text-3xl){font-size:1.875rem;line-height:2.25rem}.nova-cards :is(.text-4xl){font-size:2.25rem;line-height:2.5rem}.nova-cards :is(.text-lg){font-size:1.125rem;line-height:1.75rem}.nova-cards :is(.text-sm){font-size:.875rem;line-height:1.25rem}.nova-cards :is(.text-xl){font-size:1.25rem;line-height:1.75rem}.nova-cards :is(.text-xs){font-size:.75rem;line-height:1rem}.nova-cards :is(.font-bold){font-weight:700}.nova-cards :is(.font-medium){font-weight:500}.nova-cards :is(.font-semibold){font-weight:600}.nova-cards :is(.uppercase){text-transform:uppercase}.nova-cards :is(.capitalize){text-transform:capitalize}.nova-cards :is(.italic){font-style:italic}.nova-cards :is(.tracking-wide){letter-spacing:.025em}.nova-cards :is(.text-gray-500){--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity))}.nova-cards :is(.text-gray-600){--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity))}.nova-cards :is(.text-gray-900){--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity))}.nova-cards :is(.text-green-400){--tw-text-opacity: 1;color:rgb(74 222 128 / var(--tw-text-opacity))}.nova-cards :is(.text-green-500){--tw-text-opacity: 1;color:rgb(34 197 94 / var(--tw-text-opacity))}.nova-cards :is(.text-red-500){--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity))}.nova-cards :is(.text-white){--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.nova-cards :is(.text-yellow-500){--tw-text-opacity: 1;color:rgb(234 179 8 / var(--tw-text-opacity))}.nova-cards :is(.shadow){--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / .1), 0 1px 2px -1px rgb(0 0 0 / .1);--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.nova-cards :is(.hover\:opacity-50:hover){opacity:.5}.nova-cards :is(.focus\:outline-none:focus){outline:2px solid transparent;outline-offset:2px}.nova-cards :is(.focus\:ring:focus){--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.nova-cards :is(.dark\:divide-gray-700:is(.dark *)>:not([hidden])~:not([hidden])){--tw-divide-opacity: 1;border-color:rgb(55 65 81 / var(--tw-divide-opacity))}.nova-cards :is(.dark\:border-gray-700:is(.dark *)){--tw-border-opacity: 1;border-color:rgb(55 65 81 / var(--tw-border-opacity))}.nova-cards :is(.dark\:bg-gray-800:is(.dark *)){--tw-bg-opacity: 1;background-color:rgb(31 41 55 / var(--tw-bg-opacity))}.nova-cards :is(.dark\:bg-gray-800\/25:is(.dark *)){background-color:#1f293740}.nova-cards :is(.dark\:text-gray-300:is(.dark *)){--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity))}.nova-cards :is(.dark\:text-gray-400:is(.dark *)){--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity))}.nova-cards :is(.dark\:text-green-500:is(.dark *)){--tw-text-opacity: 1;color:rgb(34 197 94 / var(--tw-text-opacity))}@media (min-width: 768px){.nova-cards :is(.md\:col-span-4){grid-column:span 4 / span 4}.nova-cards :is(.md\:ml-2){margin-left:.5rem}} 2 | -------------------------------------------------------------------------------- /dist/js/entry.js: -------------------------------------------------------------------------------- 1 | (function(e,m){typeof exports=="object"&&typeof module<"u"?m(require("vue"),require("LaravelNova")):typeof define=="function"&&define.amd?define(["vue","LaravelNova"],m):(e=typeof globalThis<"u"?globalThis:e||self,m(e.Vue,e.LaravelNova))})(this,function(e,m){"use strict";const y={class:"nova-cards relative overflow-hidden bg-white dark:bg-gray-800 rounded-lg shadow isolate px-6 py-4 md:col-span-4 min-h-40 h-full"},k={key:0,class:"flex items-center justify-between mb-2 font-bold"},C={key:0,class:"md:ml-2 inline-flex items-center shadow rounded-lg bg-white dark:bg-gray-800 px-2 h-8"},N={class:"card-overflow"},E=e.defineComponent({__name:"Card",props:{heading:{default:""},headingClass:{default:""},showRefresh:{type:Boolean,default:!1},showPolling:{type:Boolean,default:!1},loading:{type:Boolean,default:!1},polling:{type:Boolean,default:!1},pollingInterval:{default:3e3}},emits:["refresh","update:polling"],setup(s,{emit:a}){const o=s,{__:t}=m.useLocalization(),l=e.ref(0),n=a;function r(){i(),o.polling&&c()}function c(){l.value=setInterval(async()=>{await n("refresh")},o.pollingInterval)}function i(){l.value&&(clearInterval(l.value),l.value=0)}e.watch(()=>o.polling,d=>{d?r():i()},{immediate:!0});async function p(){await n("refresh"),r()}return e.onMounted(async()=>{(o.showPolling||o.polling)&&await n("refresh"),o.polling&&c()}),e.onUnmounted(()=>{i()}),(d,_)=>{const h=e.resolveComponent("NovaCardsToolbarButton"),f=e.resolveDirective("tooltip");return e.openBlock(),e.createElementBlock("div",y,[d.heading?(e.openBlock(),e.createElementBlock("div",k,[e.createElementVNode("span",{class:e.normalizeClass([d.headingClass,"word-wrap: break-word"])},e.toDisplayString(d.heading),3),d.showRefresh||d.showPolling?(e.openBlock(),e.createElementBlock("div",C,[d.showRefresh?e.withDirectives((e.openBlock(),e.createBlock(h,{key:0,type:"refresh",loading:d.loading,onClick:e.withModifiers(p,["prevent"])},null,8,["loading"])),[[f,e.unref(t)("Refresh")]]):e.createCommentVNode("",!0),d.showPolling?e.withDirectives((e.openBlock(),e.createBlock(h,{key:1,type:"clock",onClick:_[0]||(_[0]=e.withModifiers(At=>n("update:polling",!d.polling),["prevent"])),class:e.normalizeClass([{"text-green-500":d.polling,"text-gray-500":!d.polling},"w-8 h-8"])},null,8,["class"])),[[f,e.unref(t)(d.polling?"Stop polling":"Start polling")]]):e.createCommentVNode("",!0)])):e.createCommentVNode("",!0)])):e.createCommentVNode("",!0),e.createElementVNode("div",N,[e.renderSlot(d.$slots,"default")])])}}}),w=(s=null)=>{const a=e.ref(g(s)),o=e.ref(a.value.toISOString().match(/(\d{4}\-\d{2}\-\d{2})T(\d{2}:\d{2}:\d{2})/)),l=setInterval(()=>{a.value=g(s),o.value=a.value.toISOString().match(/(\d{4}\-\d{2}\-\d{2})T(\d{2}:\d{2}:\d{2})/)},1e3);return e.onBeforeUnmount(()=>{clearInterval(l)}),{currentTime:a,iso:o}};function g(s=null){return s?new Date(new Date().toLocaleString("en-US",{timeZone:s})):new Date}const V={class:"py-2 pr-2 font-bold"},B={class:"p-2"},$={class:"p-2"},b=e.defineComponent({__name:"WorldClockTimer",props:{timezone:{}},setup(s){const a=s,{currentTime:o,iso:t}=w(a.timezone);function l(n){const r=n.getHours();return r>6&&r<20}return(n,r)=>{const c=e.resolveComponent("Icon");return e.openBlock(),e.createElementBlock("tr",null,[e.createElementVNode("td",V,e.toDisplayString(a.timezone),1),e.createElementVNode("td",B,e.toDisplayString(e.unref(t)[2]||"-"),1),e.createElementVNode("td",$,[e.createVNode(c,{class:"text-primary-500",type:l(e.unref(o))?"sun":"moon"},null,8,["type"])])])}}}),S={key:0,class:"w-full text-left table-collapse"},D={class:"align-baseline"},x={class:"py-2 pr-2 font-bold"},T={class:"p-2"},L={class:"text-xs"},z={class:"text-xs"},I={key:0},P={class:"py-2 pr-2 font-bold"},R={class:"p-2"},u={class:"text-xs"},j={class:"text-xs"},M={class:"py-2 pr-2 font-bold"},U={class:"p-2"},F=e.createElementVNode("br",null,null,-1),q={class:"text-xs"},W={key:1},A=e.defineComponent({__name:"SystemResources",props:{card:{}},setup(s){const{__:a}=m.useLocalization(),o=e.ref(!1),t=e.ref(!0),l=e.ref();async function n(){o.value=!0,await fetch("/nova-vendor/stepanenko3/nova-cards/system-resources").then(r=>r.json()).then(r=>{l.value=r}).catch(r=>{console.error(r)}).finally(()=>{o.value=!1})}return(r,c)=>{const i=e.resolveComponent("NovaCardsCard");return e.openBlock(),e.createBlock(i,{heading:r.card.title||e.unref(a)("Server Metrics"),showPolling:r.card?.polling||!1,showRefresh:r.card?.refresh||!0,loading:o.value,polling:t.value,pollingInterval:1e4,"onUpdate:polling":c[0]||(c[0]=p=>t.value=p),onRefresh:n},{default:e.withCtx(()=>[l.value&&l.value.disk_space?(e.openBlock(),e.createElementBlock("table",S,[e.createElementVNode("tbody",D,[e.createElementVNode("tr",null,[e.createElementVNode("td",x,e.toDisplayString(e.unref(a)("Disk Space")),1),e.createElementVNode("td",T,[e.createTextVNode(e.toDisplayString(l.value.disk_space.use_percentage)+"% "+e.toDisplayString(e.unref(a)("Used"))+" ( "+e.toDisplayString(l.value.disk_space.used.memory)+" ",1),e.createElementVNode("span",L,e.toDisplayString(l.value.disk_space.used.unit.toLowerCase()),1),e.createTextVNode(" / "+e.toDisplayString(l.value.disk_space.total.memory)+" ",1),e.createElementVNode("span",z,e.toDisplayString(l.value.disk_space.total.unit.toLowerCase()),1),e.createTextVNode(" ) ")])]),l.value.memory_usage?(e.openBlock(),e.createElementBlock("tr",I,[e.createElementVNode("td",P,e.toDisplayString(e.unref(a)("Memory Usage")),1),e.createElementVNode("td",R,[e.createTextVNode(e.toDisplayString(l.value.memory_usage.use_percentage)+"% "+e.toDisplayString(e.unref(a)("Used"))+" ( "+e.toDisplayString(l.value.memory_usage.used.memory)+" ",1),e.createElementVNode("span",u,e.toDisplayString(l.value.memory_usage.used.unit.toLowerCase()),1),e.createTextVNode(" / "+e.toDisplayString(l.value.memory_usage.total.memory)+" ",1),e.createElementVNode("span",j,e.toDisplayString(l.value.memory_usage.total.unit.toLowerCase()),1),e.createTextVNode(" ) ")])])):e.createCommentVNode("",!0),e.createElementVNode("tr",null,[e.createElementVNode("td",M,e.toDisplayString(e.unref(a)("CPU Usage")),1),e.createElementVNode("td",U,[e.createTextVNode(e.toDisplayString(l.value.cpu_usage.use_percentage)+"% "+e.toDisplayString(e.unref(a)("Used"))+" ",1),F,e.createElementVNode("span",q,e.toDisplayString(l.value.cpu_usage.name),1)])])])])):(e.openBlock(),e.createElementBlock("div",W,e.toDisplayString(e.unref(a)("No Data")),1))]),_:1},8,["heading","showPolling","showRefresh","loading","polling"])}}}),H={key:0,class:"w-full text-left table-collapse"},O={class:"align-baseline"},G={class:"py-2 pr-2 font-bold"},K={class:"p-2"},Z={class:"py-2 pr-2 font-bold"},J={class:"p-2"},Y={class:"py-2 pr-2 font-bold"},Q={class:"p-2"},X={class:"py-2 pr-2 font-bold"},v={class:"p-2"},ee={class:"py-2 pr-2 font-bold"},te={class:"p-2"},oe=e.defineComponent({__name:"Versions",props:{card:{}},setup(s){const a=e.ref(!1),o=e.ref(!1),t=e.ref();async function l(){a.value=!0,await fetch("/nova-vendor/stepanenko3/nova-cards/versions").then(n=>n.json()).then(n=>{t.value=n}).catch(n=>{console.error("Error fetching weather:",n)}),a.value=!1}return(n,r)=>{const c=e.resolveComponent("NovaCardsCard");return e.openBlock(),e.createBlock(c,{heading:n.card.title||n.__("System Versions"),showPolling:n.card?.polling||!1,showRefresh:n.card?.refresh||!0,loading:a.value,polling:o.value,pollingInterval:1e4,"onUpdate:polling":r[0]||(r[0]=i=>o.value=i),onRefresh:l},{default:e.withCtx(()=>[t.value?(e.openBlock(),e.createElementBlock("table",H,[e.createElementVNode("tbody",O,[e.createElementVNode("tr",null,[e.createElementVNode("td",G,e.toDisplayString(n.__("OS")),1),e.createElementVNode("td",K,e.toDisplayString(t.value.os||"-"),1)]),e.createElementVNode("tr",null,[e.createElementVNode("td",Z,e.toDisplayString(n.__("PHP")),1),e.createElementVNode("td",J,e.toDisplayString(t.value.php||"-"),1)]),e.createElementVNode("tr",null,[e.createElementVNode("td",Y,e.toDisplayString(n.__("Database")),1),e.createElementVNode("td",Q,e.toDisplayString(t.value.database||"-"),1)]),e.createElementVNode("tr",null,[e.createElementVNode("td",X,e.toDisplayString(n.__("Laravel")),1),e.createElementVNode("td",v,e.toDisplayString(t.value.laravel||"-"),1)]),e.createElementVNode("tr",null,[e.createElementVNode("td",ee,e.toDisplayString(n.__("Nova")),1),e.createElementVNode("td",te,e.toDisplayString(t.value.nova||"-"),1)])])])):e.createCommentVNode("",!0)]),_:1},8,["heading","showPolling","showRefresh","loading","polling"])}}}),ne=["innerHTML"],ae=e.defineComponent({__name:"Html",props:{card:{}},setup(s){const a=s,o=e.computed(()=>{let t="";return a.card.center&&(t+=" flex flex-col justify-center text-center"),t});return(t,l)=>{const n=e.resolveComponent("NovaCardsCard");return t.card.withoutCardStyles?(e.openBlock(),e.createElementBlock("div",{key:0,class:e.normalizeClass(["h-full",o.value]),innerHTML:t.card.content},null,10,ne)):(e.openBlock(),e.createBlock(n,{key:1,class:e.normalizeClass(o.value),innerHTML:t.card.content},null,8,["class","innerHTML"]))}}}),le={key:0},se={key:1,class:"w-full text-left table-collapse"},re={class:"align-baseline"},ce=["item"],ie={class:"py-2 pr-2 font-bold",style:{"word-wrap":"anywhere"}},de={class:"p-2"},pe={class:"p-2"},me=e.defineComponent({__name:"ScheduledJobs",props:{card:{}},setup(s){const{__:a}=m.useLocalization(),o=e.ref(!1),t=e.ref(!0),l=e.ref();async function n(){o.value=!0,await fetch("/nova-vendor/stepanenko3/nova-cards/scheduled-jobs").then(r=>r.json()).then(r=>{l.value=r}).catch(r=>{console.error("Error fetching weather:",r)}),o.value=!1}return(r,c)=>{const i=e.resolveComponent("NovaCardsCard");return e.openBlock(),e.createBlock(i,{heading:r.card.title||e.unref(a)("Scheduled Jobs"),showPolling:r.card?.polling||!1,showRefresh:r.card?.refresh||!0,loading:o.value,polling:t.value,pollingInterval:1e4,"onUpdate:polling":c[0]||(c[0]=p=>t.value=p),onRefresh:n},{default:e.withCtx(()=>[l.value.length?e.createCommentVNode("",!0):(e.openBlock(),e.createElementBlock("p",le,e.toDisplayString(e.unref(a)(o.value?"Loading...":"No Data")),1)),l.value.length?(e.openBlock(),e.createElementBlock("table",se,[e.createElementVNode("tbody",re,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(l.value,(p,d)=>(e.openBlock(),e.createElementBlock("tr",{item:p},[e.createElementVNode("td",ie,e.toDisplayString(p.command),1),e.createElementVNode("td",de,e.toDisplayString(p.expression),1),e.createElementVNode("td",pe,e.toDisplayString(p.humanReadableNextRun),1)],8,ce))),256))])])):e.createCommentVNode("",!0)]),_:1},8,["heading","showPolling","showRefresh","loading","polling"])}}}),_e={class:"flex items-center text-4xl mb-4"},fe={key:0},he={key:1},ge={class:"flex items-center"},ye={class:"text-80 font-bold"},ke={key:0},Ce={key:1},Ne=e.defineComponent({__name:"Percentage",props:{card:{}},setup(s){const a=s,{__:o}=m.useLocalization(),t=e.computed(()=>(a.card.count/a.card.total*100).toFixed(a.card.percentagePrecision));return(l,n)=>{const r=e.resolveComponent("NovaCardsCard");return e.openBlock(),e.createBlock(r,{heading:l.card.title,class:"flex flex-col items-center justify-center text-center"},{default:e.withCtx(()=>[e.createElementVNode("p",_e,[t.value!==null?(e.openBlock(),e.createElementBlock("span",fe,e.toDisplayString(t.value)+"% ",1)):(e.openBlock(),e.createElementBlock("span",he,"-"))]),e.createElementVNode("div",ge,[e.withDirectives(e.createElementVNode("p",ye,[l.card.count!==null?(e.openBlock(),e.createElementBlock("span",ke,e.toDisplayString(l.card.count),1)):e.createCommentVNode("",!0),e.createTextVNode(" "+e.toDisplayString(e.unref(o)("of"))+" ",1),l.total!==null?(e.openBlock(),e.createElementBlock("span",Ce,e.toDisplayString(l.card.total),1)):e.createCommentVNode("",!0),e.createTextVNode(" "+e.toDisplayString(l.card.label),1)],512),[[e.vShow,t.value!==null]]),e.withDirectives(e.createElementVNode("p",{class:"text-80 font-bold mt-4"},e.toDisplayString(e.unref(o)("No Data")),513),[[e.vShow,t.value===null]])])]),_:1},8,["heading"])}}}),Ee=["href","target"],we={key:0,calss:"text-basic font-semibold"},Ve=e.defineComponent({__name:"Linkable",props:{card:{}},setup(s){return(a,o)=>{const t=e.resolveComponent("NovaCardsCard");return e.openBlock(),e.createElementBlock("a",{class:"h-auto hover:opacity-50",href:a.card.url,target:a.card.target},[e.createVNode(t,{class:"flex flex-col items-center justify-center",heading:a.card.title,headingClass:"text-2xl font-bold"},{default:e.withCtx(()=>[a.card.subtitle?(e.openBlock(),e.createElementBlock("div",we,e.toDisplayString(a.card.subtitle),1)):e.createCommentVNode("",!0)]),_:1},8,["heading"])],8,Ee)}}}),Be={key:0},$e={key:1,class:"w-full text-left table-collapse"},be={class:"align-baseline"},Se={class:"py-2 pr-2 font-bold"},De={class:"p-2"},xe={class:"py-2 pr-2 font-bold"},Te={class:"p-2"},Le={class:"italic"},ze={key:2},Ie=e.defineComponent({__name:"Ssl",props:{card:{}},setup(s){const a=s,{__:o}=m.useLocalization(),t=e.ref(!1),l=e.ref(!1),n=e.ref(),r=e.ref(null);async function c(){t.value=!0,await fetch("/nova-vendor/stepanenko3/nova-cards/ssl?domain="+a.card.domain).then(i=>i.json()).then(i=>{n.value=i}).catch(i=>{r.value=i}),t.value=!1}return(i,p)=>{const d=e.resolveComponent("NovaCardsCard");return e.openBlock(),e.createBlock(d,{heading:i.card.domain+" - "+e.unref(o)(n.value?.is_valid?"Valid Certificate":"Invalid Certificate"),headingClass:{"text-green-500":n.value?.is_valid,"text-red-500":!n.value?.is_valid},showPolling:i.card?.polling||!1,showRefresh:i.card?.refresh||!0,loading:t.value,polling:l.value,pollingInterval:1e4,"onUpdate:polling":p[0]||(p[0]=_=>l.value=_),onRefresh:c},{default:e.withCtx(()=>[!n.value&&t.value?(e.openBlock(),e.createElementBlock("div",Be,e.toDisplayString(e.unref(o)("Loading...")),1)):n.value&&!r.value?(e.openBlock(),e.createElementBlock("table",$e,[e.createElementVNode("tbody",be,[e.createElementVNode("tr",null,[e.createElementVNode("td",Se,e.toDisplayString(e.unref(o)("Issuer")),1),e.createElementVNode("td",De,e.toDisplayString(n.value.issuer),1)]),e.createElementVNode("tr",null,[e.createElementVNode("td",xe,e.toDisplayString(e.unref(o)("Expiration")),1),e.createElementVNode("td",Te,[e.createTextVNode(e.toDisplayString(n.value.expiration_date)+" ( ",1),e.createElementVNode("strong",Le,e.toDisplayString(parseInt(n.value.expiration_date_in_days))+" days ",1),e.createTextVNode(" ) ")])])])])):(e.openBlock(),e.createElementBlock("div",ze,e.toDisplayString(r.value||""),1))]),_:1},8,["heading","headingClass","showPolling","showRefresh","loading","polling"])}}}),Pe={class:"flex items-center text-4xl mb-4"},Re={key:0,class:"text-center"},ue=e.defineComponent({__name:"Countdown",props:{card:{}},setup(s){const a=s,{__:o}=m.useLocalization(),t=e.ref("00:00:00:00"),l=e.ref(0),n=e.ref(0),r=e.ref(0),c=e.ref(0),i=e.ref(0);e.onMounted(()=>{l.value=a.card.to-new Date().getTime(),l.value>0&&window.requestAnimationFrame(d),window.addEventListener("focus",()=>{l.value<1e3&&(t.value="00:00:00:00",window.cancelAnimationFrame(d))})});const p=_=>("0"+Math.floor(_)).slice(-2),d=()=>{l.value=a.card.to-new Date().getTime(),n.value=p(l.value%(1e3*60)/1e3),r.value=p(l.value%(1e3*60*60)/(1e3*60)),c.value=p(l.value%(1e3*60*60*24)/(1e3*60*60)),i.value=p(l.value/(1e3*60*60*24)),l.value>=1e3?(t.value=`${i.value}:${c.value}:${r.value}:${n.value}`,window.requestAnimationFrame(d)):(window.cancelAnimationFrame(d),t.value="00:00:00:00")};return(_,h)=>{const f=e.resolveComponent("NovaCardsCard");return e.openBlock(),e.createBlock(f,{heading:_.card.title||e.unref(o)("Countdown"),class:"flex flex-col items-center justify-center text-center"},{default:e.withCtx(()=>[e.createElementVNode("p",Pe,e.toDisplayString(t.value),1),_.card.label?(e.openBlock(),e.createElementBlock("div",Re,e.toDisplayString(_.card.label),1)):e.createCommentVNode("",!0)]),_:1},8,["heading"])}}}),je={class:"card-overflow"},Me={key:0,class:"w-full text-left table-collapse"},Ue={class:"align-baseline"},Fe=e.defineComponent({__name:"WorldClock",props:{card:{}},setup(s){const{__:a}=m.useLocalization();return(o,t)=>{const l=e.resolveComponent("WorldClockTimer"),n=e.resolveComponent("NovaCardsCard");return e.openBlock(),e.createBlock(n,{class:"flex flex-col items-center justify-center text-center",heading:o.card.title||e.unref(a)("World Clock")},{default:e.withCtx(()=>[e.createElementVNode("div",je,[o.card.timezones.length>0?(e.openBlock(),e.createElementBlock("table",Me,[e.createElementVNode("tbody",Ue,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(o.card.timezones,r=>(e.openBlock(),e.createBlock(l,{timezone:r},null,8,["timezone"]))),256))])])):e.createCommentVNode("",!0)])]),_:1},8,["heading"])}}}),qe={class:"text-basic text-center mb-2"},We={key:0,class:"mr-2"},Ae=e.defineComponent({__name:"Environment",props:{card:{}},setup(s){const{__:a}=m.useLocalization();return(o,t)=>{const l=e.resolveComponent("NovaCardsCard");return e.openBlock(),e.createBlock(l,{class:"flex flex-col items-center justify-center"},{default:e.withCtx(()=>[e.createElementVNode("div",qe,e.toDisplayString(o.card.title||e.unref(a)("Current Environment")),1),e.createElementVNode("div",{class:e.normalizeClass(["flex items-center w-full text-lg font-bold uppercase",{"text-yellow-500":o.card.env!=="production","text-green-500":o.card.env==="production"}])},[o.card.env!=="production"?(e.openBlock(),e.createElementBlock("span",We," ( ! ) ")):e.createCommentVNode("",!0),e.createTextVNode(" "+e.toDisplayString(o.card.env),1)],2)]),_:1})}}}),He=["src"],Oe=e.defineComponent({__name:"Embed",props:{card:{}},setup(s){return(a,o)=>{const t=e.resolveComponent("NovaCardsCard");return e.openBlock(),e.createBlock(t,{class:e.normalizeClass(["h-auto overflow-hidden",{"p-3":a.card.hasPadding,"!p-none !p-0":!a.card.hasPadding}])},{default:e.withCtx(()=>[e.createElementVNode("iframe",{class:"w-full h-full",src:a.card.url,allow:"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture",allowfullscreen:""},null,8,He)]),_:1},8,["class"])}}}),Ge={class:"flex items-center mb-2"},Ke=["src","alt"],Ze={class:"text-xl font-bold"},Je={class:"text-lg font-bold mb-4"},Ye={class:"grid grid-cols-4 gap-6 text-sm"},Qe={class:"flex flex-col"},Xe=e.createElementVNode("span",{class:"mb-1"}," Feels like ",-1),ve={class:"flex flex-col"},et=e.createElementVNode("span",{class:"mb-1"}," Humidity ",-1),tt={class:"flex flex-col"},ot=e.createElementVNode("span",{class:"mb-1"}," Sunrise ",-1),nt={class:"flex flex-col"},at=e.createElementVNode("span",null," Sunset ",-1),lt=e.defineComponent({__name:"Weather",props:{card:{}},setup(s){const a=s,{__:o}=m.useLocalization(),t=e.ref(!1),l=e.ref(!1),n=e.ref();async function r(){t.value=!0;const c=new URLSearchParams({q:a.card.city||"Kiev ",lang:a.card?.lang||""}).toString();await fetch("/nova-vendor/stepanenko3/nova-cards/weather"+(c?`?${c}`:"")).then(i=>i.json()).then(i=>{n.value=i}).catch(i=>{console.error("Error fetching weather:",i)}),t.value=!1}return(c,i)=>{const p=e.resolveComponent("NovaCardsCard"),d=e.resolveDirective("tooltip");return e.openBlock(),e.createBlock(p,{heading:n.value&&n.value.sys?`${n.value.name}, ${n.value.sys.country}`:e.unref(o)("Weather"),showPolling:c.card?.polling||!1,showRefresh:c.card?.refresh||!0,loading:t.value,polling:l.value,pollingInterval:1e4,"onUpdate:polling":i[0]||(i[0]=_=>l.value=_),onRefresh:r},{default:e.withCtx(()=>[n.value&&n.value.sys?(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[e.createElementVNode("div",Ge,[e.withDirectives(e.createElementVNode("img",{class:"mr-2",src:`http://openweathermap.org/img/wn/${n.value.weather[0].icon}@2x.png`,alt:n.value.weather[0].icon,width:"50",height:"50"},null,8,Ke),[[d,n.value.weather[0].description.charAt(0).toUpperCase()+n.value.weather[0].description.substring(1)]]),e.createElementVNode("div",Ze,e.toDisplayString(Math.round(n.value.main.temp))+" °C ",1)]),e.createElementVNode("div",Je,e.toDisplayString(n.value.weather[0].description.charAt(0).toUpperCase()+n.value.weather[0].description.substring(1)),1),e.createElementVNode("div",Ye,[e.createElementVNode("div",Qe,[Xe,e.createElementVNode("b",null,e.toDisplayString(Math.round(n.value.main.feels_like))+" °C ",1)]),e.createElementVNode("div",ve,[et,e.createElementVNode("b",null,e.toDisplayString(n.value.main.humidity)+"% ",1)]),e.createElementVNode("div",tt,[ot,e.createElementVNode("b",null,e.toDisplayString(new Date(n.value.sys.sunrise*1e3).toLocaleString("en-GB",{hour:"2-digit",minute:"2-digit",timeZone:"Europe/Kiev"})),1)]),e.createElementVNode("div",nt,[at,e.createElementVNode("b",null,e.toDisplayString(new Date(n.value.sys.sunset*1e3).toLocaleString("en-GB",{hour:"2-digit",minute:"2-digit",timeZone:"Europe/Kiev"})),1)])])],64)):e.createCommentVNode("",!0)]),_:1},8,["heading","showPolling","showRefresh","loading","polling"])}}}),st={class:"w-full text-left table-collapse"},rt={class:"align-baseline"},ct={class:"py-2 pr-2 font-bold"},it={class:"p-2"},dt={class:"py-2 pr-2 font-bold"},pt={class:"p-2"},mt={class:"py-2 pr-2 font-bold"},_t={class:"p-2"},ft={class:"py-2 pr-2 font-bold"},ht={class:"p-2"},gt={class:"py-2 pr-2 font-bold"},yt={class:"p-2"},kt=e.defineComponent({__name:"Calendar",props:{card:{}},setup(s){const{__:a}=m.useLocalization();return(o,t)=>{const l=e.resolveComponent("NovaCardsCard");return e.openBlock(),e.createBlock(l,{heading:`${o.card.day.name} ${o.card.day.withMonth}`},{default:e.withCtx(()=>[e.createElementVNode("table",st,[e.createElementVNode("tbody",rt,[e.createElementVNode("tr",null,[e.createElementVNode("td",ct,e.toDisplayString(e.unref(a)("Year")),1),e.createElementVNode("td",it,e.toDisplayString(o.card.year),1)]),e.createElementVNode("tr",null,[e.createElementVNode("td",dt,e.toDisplayString(e.unref(a)("Day of year")),1),e.createElementVNode("td",pt,e.toDisplayString(o.card.dayOfYear),1)]),e.createElementVNode("tr",null,[e.createElementVNode("td",mt,e.toDisplayString(e.unref(a)("Days in month")),1),e.createElementVNode("td",_t,e.toDisplayString(o.card.daysInMonth),1)]),e.createElementVNode("tr",null,[e.createElementVNode("td",ft,e.toDisplayString(e.unref(a)("Qarter")),1),e.createElementVNode("td",ht,e.toDisplayString(o.card.quarter),1)]),e.createElementVNode("tr",null,[e.createElementVNode("td",gt,e.toDisplayString(e.unref(a)("Timezone")),1),e.createElementVNode("td",yt,e.toDisplayString(o.card.timezone),1)])])])]),_:1},8,["heading"])}}}),Ct={class:"flex items-center justify-between flex-grow"},Nt={class:"flex items-center space-x-4"},Et={key:0,class:"flex-shrink-0"},wt=["src","alt"],Vt={key:1,class:"flex-shrink-0 text-3xl h-20 w-20 rounded-full bg-primary-500 tracking-wide text-white flex items-center justify-center"},Bt={class:"text-left"},$t={class:"text-sm font-medium text-gray-600 dark:text-gray-400"},bt={class:"font-bold text-xl"},St={key:0,class:"text-sm font-medium text-gray-600 dark:text-gray-400"},Dt={key:1,class:"mt-6 flex flex-col mt-1 flex-row flex-wrap"},xt={class:"sr-only"},Tt={class:"mt-3 flex justify-center text-sm text-gray-500 dark:text-gray-300 font-medium mr-6 mt-1 capitalize"},Lt=e.createElementVNode("svg",{xmlns:"http://www.w3.org/2000/svg",fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor",class:"flex-shrink-0 mr-1.5 h-5 w-5 text-green-400 dark:text-green-500","aria-hidden":"true"},[e.createElementVNode("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z"})],-1),zt={key:0,class:"space-y-4 flex flex-col"},It={key:0,class:"border-t border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800/25 grid grid-cols-1 divide-y divide-gray-200 dark:divide-gray-700 grid-cols-3 divide-y-0 divide-x"},Pt={class:"text-gray-900 dark:text-gray-300"},Rt={class:"text-gray-600 dark:text-gray-400"},ut=e.defineComponent({__name:"Greeter",props:{card:{}},setup(s){const{__:a}=m.useLocalization();function o(t){return t.match(/(\b\S)?/g).join("").match(/(^\S|\S$)?/g).join("").toUpperCase()}return(t,l)=>{const n=e.resolveComponent("OutlineButtonInertiaLink"),r=e.resolveComponent("NovaCardsCard");return e.openBlock(),e.createBlock(r,{class:"h-auto flex items-center p-4"},{default:e.withCtx(()=>[e.createElementVNode("div",Ct,[e.createElementVNode("div",Nt,[t.card.avatar?(e.openBlock(),e.createElementBlock("div",Et,[e.createElementVNode("img",{class:"mx-auto h-20 w-20 rounded-full",src:t.card.avatar_url,alt:t.card.user_name},null,8,wt)])):(e.openBlock(),e.createElementBlock("div",Vt,e.toDisplayString(o(t.card.user_name)),1)),e.createElementVNode("div",Bt,[e.createElementVNode("p",$t,e.toDisplayString(t.card.message??e.unref(a)("Welcome back,")),1),e.createElementVNode("p",bt,e.toDisplayString(t.card.user_name),1),t.card.user_title?(e.openBlock(),e.createElementBlock("p",St,e.toDisplayString(t.card.user_title),1)):e.createCommentVNode("",!0),t.card.verified?(e.openBlock(),e.createElementBlock("dl",Dt,[e.createElementVNode("dt",xt,e.toDisplayString(t.card.verified_text??e.unref(a)("Verified Account")),1),e.createElementVNode("dd",Tt,[Lt,e.createTextVNode(" "+e.toDisplayString(t.card.verified_text??e.unref(a)("Verified Account")),1)])])):e.createCommentVNode("",!0)])]),t.card.buttons.length>0?(e.openBlock(),e.createElementBlock("div",zt,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.card.buttons,c=>(e.openBlock(),e.createBlock(n,{href:c.target},{default:e.withCtx(()=>[e.createTextVNode(e.toDisplayString(c.name),1)]),_:2},1032,["href"]))),256))])):e.createCommentVNode("",!0)]),t.card.stats?(e.openBlock(),e.createElementBlock("div",It,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(t.card.stats,c=>(e.openBlock(),e.createElementBlock("div",{key:c.label,class:"px-6 py-3 text-sm font-medium text-center"},[e.createElementVNode("span",Pt,e.toDisplayString(c.value),1),e.createElementVNode("span",Rt,e.toDisplayString(c.label),1)]))),128))])):e.createCommentVNode("",!0)]),_:1})}}}),jt=(s,a)=>{const o=s.__vccOpts||s;for(const[t,l]of a)o[t]=l;return o},Mt={props:{type:{type:String,required:!1},processing:{type:Boolean,required:!1},loading:{type:Boolean,required:!1}}},Ut={type:"button",class:"relative inline-flex items-center justify-center w-8 h-8 focus:outline-none focus:ring rounded-lg"},Ft={key:0,class:"absolute",style:{top:"50%",left:"50%",transform:"translate(-50%, -50%)"}};function qt(s,a,o,t,l,n){const r=e.resolveComponent("Icon"),c=e.resolveComponent("Loader");return e.openBlock(),e.createElementBlock("button",Ut,[e.createElementVNode("span",{class:e.normalizeClass({invisible:o.processing||o.loading})},[e.renderSlot(s.$slots,"default"),o.type?(e.openBlock(),e.createBlock(r,{key:0,solid:"",type:o.type},null,8,["type"])):e.createCommentVNode("",!0)],2),o.processing||o.loading?(e.openBlock(),e.createElementBlock("span",Ft,[e.createVNode(c,{class:"text-gray-500",width:"32"})])):e.createCommentVNode("",!0)])}const Wt=jt(Mt,[["render",qt]]);Nova.booting(s=>{s.component("NovaCardsCard",E),s.component("NovaCardsToolbarButton",Wt),s.component("WorldClockTimer",b),s.component("system-resources-card",A),s.component("versions-card",oe),s.component("html-card",ae),s.component("scheduled-jobs-card",me),s.component("percentage-card",Ne),s.component("linkable-card",Ve),s.component("ssl-card",Ie),s.component("countdown-card",ue),s.component("world-clock-card",Fe),s.component("environment-card",Ae),s.component("embed-card",Oe),s.component("cache-card",Cache),s.component("weather-card",lt),s.component("calendar-card",kt),s.component("greeter-card",ut)})}); 2 | -------------------------------------------------------------------------------- /duster.json: -------------------------------------------------------------------------------- 1 | { 2 | "exclude": [ 3 | "bootstrap", 4 | "config" 5 | ], 6 | "scripts": { 7 | "lint": { 8 | "phpstan": [ 9 | "./vendor/bin/phpstan", 10 | "analyse", 11 | "src", 12 | "--memory-limit=1G" 13 | ] 14 | } 15 | }, 16 | "processTimeout": 120 17 | } 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "vite build --watch", 5 | "build": "vite build", 6 | "nova:install": "npm --prefix='vendor/laravel/nova' ci" 7 | }, 8 | "devDependencies": { 9 | "@inertiajs/inertia": "^0.11.1", 10 | "@inertiajs/inertia-vue3": "^0.6.0", 11 | "@vitejs/plugin-vue": "^5.2.1", 12 | "@vue/compiler-sfc": "^3.5.13", 13 | "postcss": "^8.4.49", 14 | "vite": "^6.2.1" 15 | }, 16 | "dependencies": { 17 | "autoprefixer": "^10.4.21", 18 | "tailwindcss": "^4.0.13" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /pint.json: -------------------------------------------------------------------------------- 1 | { 2 | "preset": "laravel", 3 | "rules": { 4 | "@PSR12": true, 5 | "@PSR12:risky": true, 6 | "@PHP80Migration": true, 7 | "@PHP80Migration:risky": true, 8 | "@PHP81Migration": true, 9 | "align_multiline_comment": { 10 | "comment_type": "phpdocs_only" 11 | }, 12 | "array_indentation": true, 13 | "array_syntax": { 14 | "syntax": "short" 15 | }, 16 | "blank_line_after_namespace": true, 17 | "blank_line_after_opening_tag": true, 18 | "blank_line_before_statement": { 19 | "statements": [ 20 | "break", 21 | "case", 22 | "continue", 23 | "declare", 24 | "default", 25 | "exit", 26 | "goto", 27 | "include", 28 | "include_once", 29 | "phpdoc", 30 | "require", 31 | "require_once", 32 | "return", 33 | "switch", 34 | "throw", 35 | "try", 36 | "yield", 37 | "yield_from" 38 | ] 39 | }, 40 | "blank_line_between_import_groups": true, 41 | "braces": { 42 | "allow_single_line_anonymous_class_with_empty_body": true, 43 | "allow_single_line_closure": true 44 | }, 45 | "cast_spaces": { 46 | "space": "single" 47 | }, 48 | "class_attributes_separation": { 49 | "elements": { 50 | "method": "one" 51 | } 52 | }, 53 | "class_definition": { 54 | "single_line": true, 55 | "space_before_parenthesis": true 56 | }, 57 | "class_reference_name_casing": true, 58 | "clean_namespace": true, 59 | "combine_consecutive_issets": true, 60 | "combine_consecutive_unsets": true, 61 | "compact_nullable_typehint": true, 62 | "concat_space": { 63 | "spacing": "one" 64 | }, 65 | "constant_case": { 66 | "case": "lower" 67 | }, 68 | "declare_equal_normalize": { 69 | "space": "single" 70 | }, 71 | "echo_tag_syntax": true, 72 | "elseif": true, 73 | "empty_loop_body": true, 74 | "empty_loop_condition": true, 75 | "encoding": true, 76 | "escape_implicit_backslashes": true, 77 | "explicit_indirect_variable": true, 78 | "explicit_string_variable": true, 79 | "full_opening_tag": true, 80 | "fully_qualified_strict_types": true, 81 | "function_declaration": true, 82 | "function_typehint_space": true, 83 | "general_phpdoc_tag_rename": { 84 | "replacements": { 85 | "inheritDocs": "inheritDoc" 86 | } 87 | }, 88 | "heredoc_to_nowdoc": true, 89 | "include": true, 90 | "increment_style": { 91 | "style": "post" 92 | }, 93 | "indentation_type": true, 94 | "integer_literal_case": true, 95 | "lambda_not_used_import": true, 96 | "line_ending": true, 97 | "linebreak_after_opening_tag": true, 98 | "lowercase_cast": true, 99 | "lowercase_keywords": true, 100 | "lowercase_static_reference": true, 101 | "magic_constant_casing": true, 102 | "magic_method_casing": true, 103 | "method_argument_space": { 104 | "on_multiline": "ensure_single_line", 105 | "after_heredoc": true, 106 | "keep_multiple_spaces_after_comma": true 107 | }, 108 | "method_chaining_indentation": true, 109 | "multiline_comment_opening_closing": true, 110 | "multiline_whitespace_before_semicolons": { 111 | "strategy": "no_multi_line" 112 | }, 113 | "native_function_casing": true, 114 | "native_function_type_declaration_casing": true, 115 | "new_with_braces": { 116 | "anonymous_class": true, 117 | "named_class": true 118 | }, 119 | "no_alias_language_construct_call": true, 120 | "no_alternative_syntax": true, 121 | "no_binary_string": true, 122 | "no_blank_lines_after_class_opening": true, 123 | "no_blank_lines_after_phpdoc": true, 124 | "no_break_comment": true, 125 | "no_closing_tag": true, 126 | "no_empty_phpdoc": true, 127 | "no_empty_statement": true, 128 | "no_extra_blank_lines": { 129 | "tokens": [ 130 | "attribute", 131 | "break", 132 | "case", 133 | "continue", 134 | "curly_brace_block", 135 | "default", 136 | "extra", 137 | "parenthesis_brace_block", 138 | "return", 139 | "square_brace_block", 140 | "switch", 141 | "throw", 142 | "use" 143 | ] 144 | }, 145 | "no_leading_import_slash": true, 146 | "no_leading_namespace_whitespace": true, 147 | "no_mixed_echo_print": true, 148 | "no_multiline_whitespace_around_double_arrow": true, 149 | "no_null_property_initialization": true, 150 | "no_short_bool_cast": true, 151 | "no_singleline_whitespace_before_semicolons": true, 152 | "no_space_around_double_colon": true, 153 | "no_spaces_after_function_name": true, 154 | "no_spaces_around_offset": true, 155 | "no_spaces_inside_parenthesis": true, 156 | "no_superfluous_elseif": true, 157 | "no_superfluous_phpdoc_tags": { 158 | "allow_mixed": true, 159 | "allow_unused_params": true 160 | }, 161 | "no_trailing_comma_in_singleline": true, 162 | "no_trailing_whitespace": true, 163 | "no_trailing_whitespace_in_comment": true, 164 | "no_unneeded_control_parentheses": { 165 | "statements": [ 166 | "break", 167 | "clone", 168 | "continue", 169 | "echo_print", 170 | "negative_instanceof", 171 | "others", 172 | "return", 173 | "switch_case", 174 | "yield", 175 | "yield_from" 176 | ] 177 | }, 178 | "no_unneeded_curly_braces": { 179 | "namespaces": true 180 | }, 181 | "no_unneeded_import_alias": true, 182 | "no_unset_cast": true, 183 | "no_unused_imports": true, 184 | "no_useless_else": true, 185 | "no_useless_nullsafe_operator": true, 186 | "no_useless_return": true, 187 | "no_whitespace_before_comma_in_array": true, 188 | "no_whitespace_in_blank_line": true, 189 | "normalize_index_brace": true, 190 | "object_operator_without_whitespace": true, 191 | "operator_linebreak": { 192 | "position": "beginning", 193 | "only_booleans": true 194 | }, 195 | "ordered_class_elements": true, 196 | "ordered_interfaces": true, 197 | "ordered_imports": true, 198 | "phpdoc_add_missing_param_annotation": true, 199 | "phpdoc_align": { 200 | "align": "left" 201 | }, 202 | "phpdoc_annotation_without_dot": true, 203 | "phpdoc_indent": true, 204 | "phpdoc_inline_tag_normalizer": true, 205 | "phpdoc_no_access": true, 206 | "phpdoc_no_alias_tag": true, 207 | "phpdoc_no_empty_return": true, 208 | "phpdoc_no_package": true, 209 | "phpdoc_no_useless_inheritdoc": true, 210 | "phpdoc_order": { 211 | "order": [ 212 | "param", 213 | "throws", 214 | "return" 215 | ] 216 | }, 217 | "phpdoc_order_by_value": true, 218 | "phpdoc_return_self_reference": true, 219 | "phpdoc_scalar": true, 220 | "phpdoc_separation": true, 221 | "phpdoc_single_line_var_spacing": true, 222 | "phpdoc_summary": true, 223 | "phpdoc_tag_type": { 224 | "tags": { 225 | "inheritDoc": "inline" 226 | } 227 | }, 228 | "phpdoc_to_comment": true, 229 | "phpdoc_trim": true, 230 | "phpdoc_trim_consecutive_blank_line_separation": true, 231 | "phpdoc_types": true, 232 | "phpdoc_types_order": true, 233 | "phpdoc_var_annotation_correct_order": true, 234 | "phpdoc_var_without_name": true, 235 | "protected_to_private": true, 236 | "return_assignment": true, 237 | "return_type_declaration": true, 238 | "semicolon_after_instruction": true, 239 | "short_scalar_cast": true, 240 | "simple_to_complex_string_variable": true, 241 | "single_blank_line_at_eof": true, 242 | "single_blank_line_before_namespace": false, 243 | "single_class_element_per_statement": true, 244 | "single_import_per_statement": true, 245 | "single_line_after_imports": true, 246 | "single_line_comment_spacing": true, 247 | "single_line_comment_style": true, 248 | "single_line_throw": true, 249 | "single_quote": { 250 | "strings_containing_single_quote_chars": true 251 | }, 252 | "single_space_after_construct": { 253 | "constructs": [ 254 | "abstract", 255 | "as", 256 | "attribute", 257 | "break", 258 | "case", 259 | "catch", 260 | "class", 261 | "clone", 262 | "comment", 263 | "const", 264 | "const_import", 265 | "continue", 266 | "do", 267 | "echo", 268 | "else", 269 | "elseif", 270 | "enum", 271 | "extends", 272 | "final", 273 | "finally", 274 | "for", 275 | "foreach", 276 | "function", 277 | "function_import", 278 | "global", 279 | "goto", 280 | "if", 281 | "implements", 282 | "include", 283 | "include_once", 284 | "instanceof", 285 | "insteadof", 286 | "interface", 287 | "match", 288 | "named_argument", 289 | "namespace", 290 | "new", 291 | "open_tag_with_echo", 292 | "php_doc", 293 | "php_open", 294 | "print", 295 | "private", 296 | "protected", 297 | "public", 298 | "readonly", 299 | "require", 300 | "require_once", 301 | "return", 302 | "static", 303 | "switch", 304 | "throw", 305 | "trait", 306 | "try", 307 | "type_colon", 308 | "use", 309 | "use_lambda", 310 | "use_trait", 311 | "var", 312 | "while", 313 | "yield", 314 | "yield_from" 315 | ] 316 | }, 317 | "single_trait_insert_per_statement": true, 318 | "space_after_semicolon": { 319 | "remove_in_empty_for_expressions": true 320 | }, 321 | "standardize_increment": true, 322 | "standardize_not_equals": true, 323 | "switch_case_semicolon_to_colon": true, 324 | "switch_case_space": true, 325 | "switch_continue_to_break": true, 326 | "ternary_operator_spaces": true, 327 | "trailing_comma_in_multiline": true, 328 | "trim_array_spaces": true, 329 | "types_spaces": { 330 | "space": "single" 331 | }, 332 | "unary_operator_spaces": true, 333 | "visibility_required": { 334 | "elements": [ 335 | "property", 336 | "method", 337 | "const" 338 | ] 339 | }, 340 | "whitespace_after_comma_in_array": { 341 | "ensure_single_space": true 342 | }, 343 | "array_push": true, 344 | "combine_nested_dirname": true, 345 | "comment_to_phpdoc": true, 346 | "dir_constant": true, 347 | "ereg_to_preg": true, 348 | "error_suppression": true, 349 | "final_internal_class": true, 350 | "fopen_flag_order": true, 351 | "fopen_flags": { 352 | "b_mode": false 353 | }, 354 | "function_to_constant": true, 355 | "implode_call": true, 356 | "is_null": true, 357 | "logical_operators": true, 358 | "modernize_types_casting": true, 359 | "native_constant_invocation": { 360 | "fix_built_in": false, 361 | "include": [ 362 | "DIRECTORY_SEPARATOR", 363 | "PHP_INT_SIZE", 364 | "PHP_SAPI", 365 | "PHP_VERSION_ID" 366 | ], 367 | "scope": "namespaced", 368 | "strict": true 369 | }, 370 | "no_alias_functions": { 371 | "sets": [ 372 | "@all" 373 | ] 374 | }, 375 | "no_homoglyph_names": true, 376 | "no_php4_constructor": true, 377 | "no_trailing_whitespace_in_string": true, 378 | "no_unneeded_final_method": true, 379 | "no_unreachable_default_argument_value": true, 380 | "no_unset_on_property": true, 381 | "no_useless_sprintf": true, 382 | "ordered_traits": true, 383 | "pow_to_exponentiation": true, 384 | "psr_autoloading": true, 385 | "self_accessor": true, 386 | "set_type_to_cast": true, 387 | "string_length_to_empty": true, 388 | "ternary_to_elvis_operator": true, 389 | 390 | 391 | 392 | 393 | "declare_strict_types": false, 394 | "yoda_style": false, 395 | "group_import": false, 396 | "not_operator_with_successor_space": false, 397 | "simplified_null_return": true, 398 | "nullable_type_declaration_for_default_null_value": { 399 | "use_nullable_type_declaration": true 400 | }, 401 | "assign_null_coalescing_to_coalesce_equal": true, 402 | "ternary_to_null_coalescing": true, 403 | "get_class_to_class_keyword": true 404 | } 405 | } 406 | -------------------------------------------------------------------------------- /postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /resources/css/card.css: -------------------------------------------------------------------------------- 1 | @tailwind components; 2 | @tailwind utilities; 3 | -------------------------------------------------------------------------------- /resources/js/cards/Calendar.vue: -------------------------------------------------------------------------------- 1 | 73 | 74 | 97 | -------------------------------------------------------------------------------- /resources/js/cards/Countdown.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 71 | -------------------------------------------------------------------------------- /resources/js/cards/Embed.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 25 | -------------------------------------------------------------------------------- /resources/js/cards/Environment.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 32 | -------------------------------------------------------------------------------- /resources/js/cards/Greeter.vue: -------------------------------------------------------------------------------- 1 | 92 | 93 | 122 | -------------------------------------------------------------------------------- /resources/js/cards/Html.vue: -------------------------------------------------------------------------------- 1 | 5 | 6 | 27 | -------------------------------------------------------------------------------- /resources/js/cards/Linkable.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 31 | -------------------------------------------------------------------------------- /resources/js/cards/Percentage.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 47 | -------------------------------------------------------------------------------- /resources/js/cards/ScheduledJobs.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 67 | -------------------------------------------------------------------------------- /resources/js/cards/Ssl.vue: -------------------------------------------------------------------------------- 1 | 54 | 55 | 91 | -------------------------------------------------------------------------------- /resources/js/cards/SystemResources.vue: -------------------------------------------------------------------------------- 1 | 75 | 76 | 110 | -------------------------------------------------------------------------------- /resources/js/cards/Versions.vue: -------------------------------------------------------------------------------- 1 | 58 | 59 | 89 | -------------------------------------------------------------------------------- /resources/js/cards/Weather.vue: -------------------------------------------------------------------------------- 1 | 86 | 87 | 129 | -------------------------------------------------------------------------------- /resources/js/cards/WorldClock.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 34 | -------------------------------------------------------------------------------- /resources/js/components/Card.vue: -------------------------------------------------------------------------------- 1 | 44 | 45 | 132 | -------------------------------------------------------------------------------- /resources/js/components/ToolbarButton.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 39 | -------------------------------------------------------------------------------- /resources/js/components/WorldClockTimer.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 33 | -------------------------------------------------------------------------------- /resources/js/composables/useCurrentTime.js: -------------------------------------------------------------------------------- 1 | import { ref, onBeforeUnmount } from "vue"; 2 | 3 | export const useCurrentTime = (timezone = null) => { 4 | const currentTime = ref(getDate(timezone)); 5 | const iso = ref(currentTime.value.toISOString().match(/(\d{4}\-\d{2}\-\d{2})T(\d{2}:\d{2}:\d{2})/)); 6 | 7 | const updateCurrentTime = () => { 8 | currentTime.value = getDate(timezone); 9 | iso.value = currentTime.value.toISOString().match(/(\d{4}\-\d{2}\-\d{2})T(\d{2}:\d{2}:\d{2})/); 10 | }; 11 | 12 | const updateTimeInterval = setInterval(updateCurrentTime, 1000); 13 | 14 | onBeforeUnmount(() => { 15 | clearInterval(updateTimeInterval); 16 | }); 17 | 18 | return { 19 | currentTime, 20 | iso, 21 | }; 22 | }; 23 | 24 | function getDate(timezone = null) { 25 | return timezone 26 | ? new Date( 27 | new Date().toLocaleString('en-US', { 28 | timeZone: timezone, 29 | }), 30 | ) 31 | : new Date(); 32 | } 33 | -------------------------------------------------------------------------------- /resources/js/entry.js: -------------------------------------------------------------------------------- 1 | import '../css/card.css' 2 | 3 | import Card from './components/Card.vue' 4 | import WorldClockTimer from './components/WorldClockTimer.vue' 5 | // 6 | import SystemResources from './cards/SystemResources.vue' 7 | import Versions from './cards/Versions.vue' 8 | import Html from './cards/Html.vue' 9 | import ScheduledJobs from './cards/ScheduledJobs.vue' 10 | import Percentage from './cards/Percentage.vue' 11 | import Linkable from './cards/Linkable.vue' 12 | import Ssl from './cards/Ssl.vue' 13 | import Countdown from './cards/Countdown.vue' 14 | import WorldClock from './cards/WorldClock.vue' 15 | import Environment from './cards/Environment.vue' 16 | import Embed from './cards/Embed.vue' 17 | import Weather from './cards/Weather.vue' 18 | import Calendar from './cards/Calendar.vue' 19 | import Greeter from './cards/Greeter.vue' 20 | import ToolbarButton from './components/ToolbarButton.vue' 21 | 22 | Nova.booting((Vue) => { 23 | Vue.component('NovaCardsCard', Card); 24 | Vue.component('NovaCardsToolbarButton', ToolbarButton); 25 | Vue.component('WorldClockTimer', WorldClockTimer); 26 | // 27 | Vue.component('system-resources-card', SystemResources); 28 | Vue.component('versions-card', Versions); 29 | Vue.component('html-card', Html); 30 | Vue.component('scheduled-jobs-card', ScheduledJobs); 31 | Vue.component('percentage-card', Percentage); 32 | Vue.component('linkable-card', Linkable); 33 | Vue.component('ssl-card', Ssl); 34 | Vue.component('countdown-card', Countdown); 35 | Vue.component('world-clock-card', WorldClock); 36 | Vue.component('environment-card', Environment); 37 | Vue.component('embed-card', Embed); 38 | Vue.component('cache-card', Cache); 39 | Vue.component('weather-card', Weather); 40 | Vue.component('calendar-card', Calendar); 41 | Vue.component('greeter-card', Greeter); 42 | }); 43 | -------------------------------------------------------------------------------- /routes/api.php: -------------------------------------------------------------------------------- 1 | withMeta([ 17 | 'day' => [ 18 | 'name' => $now->dayName, 19 | 'shortName' => $now->minDayName, 20 | 'number' => $now->day, 21 | 'withMonth' => $now->isoFormat('Do MMMM'), 22 | ], 23 | 'month' => [ 24 | 'name' => $now->monthName, 25 | 'name2' => $now->getTranslatedMonthName('Do MMMM'), 26 | 'shortName' => $now->shortMonthName, 27 | 'number' => $now->month, 28 | 'withDay' => $now->isoFormat('Do MMMM'), 29 | ], 30 | 'year' => $now->year, 31 | 'dayOfWeek' => $now->dayOfWeek, 32 | 'dayOfYear' => $now->dayOfYear, 33 | 'weekOfMonth' => $now->weekOfMonth, 34 | 'weekOfYear' => $now->weekOfYear, 35 | 'daysInMonth' => $now->daysInMonth, 36 | 'quarter' => $now->quarter, 37 | 'timestamp' => $now->timestamp, 38 | 'timezone' => $now->timezoneName, 39 | ]); 40 | } 41 | 42 | public function component(): string 43 | { 44 | return 'calendar-card'; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/Cards/CountdownCard.php: -------------------------------------------------------------------------------- 1 | withMeta([ 16 | 'label' => $label, 17 | ]); 18 | } 19 | 20 | public function title( 21 | string $title = '', 22 | ): self { 23 | return $this->withMeta([ 24 | 'title' => $title, 25 | ]); 26 | } 27 | 28 | public function to( 29 | Carbon $date, 30 | ): self { 31 | return $this->withMeta([ 32 | 'to' => $date->timestamp * 1000, 33 | ]); 34 | } 35 | 36 | public function component(): string 37 | { 38 | return 'countdown-card'; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/Cards/EmbedCard.php: -------------------------------------------------------------------------------- 1 | withMeta([ 15 | 'url' => false, 16 | 'hasPadding' => true, 17 | ]); 18 | } 19 | 20 | public function url( 21 | string $url, 22 | ): self { 23 | return $this->withMeta([ 24 | 'url' => $url, 25 | ]); 26 | } 27 | 28 | public function withoutPadding(): self 29 | { 30 | return $this->withMeta([ 31 | 'hasPadding' => false, 32 | ]); 33 | } 34 | 35 | public function component(): string 36 | { 37 | return 'embed-card'; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/Cards/EnvironmentCard.php: -------------------------------------------------------------------------------- 1 | withMeta([ 17 | 'env' => config('app.env'), 18 | ]); 19 | } 20 | 21 | public function title( 22 | string $title = '', 23 | ): self { 24 | return $this->withMeta([ 25 | 'title' => $title, 26 | ]); 27 | } 28 | 29 | public function component(): string 30 | { 31 | return 'environment-card'; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/Cards/GreeterCard.php: -------------------------------------------------------------------------------- 1 | withMeta([ 22 | 'user_name' => auth()->user()?->name ?? __('Dear User'), 23 | 'buttons' => $this->buttons, 24 | ]); 25 | } 26 | 27 | public function user( 28 | ?string $name = null, 29 | ?string $title = null, 30 | ): self { 31 | return $this->withMeta([ 32 | 'user_name' => $name ?? (auth()->user()?->name ?? __('Dear User')), 33 | 'user_title' => $title, 34 | ]); 35 | } 36 | 37 | public function message( 38 | string $text, 39 | ): self { 40 | return $this->withMeta([ 41 | 'message' => $text, 42 | ]); 43 | } 44 | 45 | public function avatar( 46 | string $url, 47 | ): self { 48 | return $this->withMeta([ 49 | 'avatar' => true, 50 | 'avatar_url' => $url, 51 | ]); 52 | } 53 | 54 | public function button( 55 | string $name, 56 | string $target, 57 | ?string $style = null, 58 | ): self { 59 | $this->buttons[] = [ 60 | 'name' => $name, 61 | 'target' => $target, 62 | 'style' => $style, 63 | ]; 64 | 65 | return $this->withMeta([ 66 | 'buttons' => $this->buttons, 67 | ]); 68 | } 69 | 70 | public function stats( 71 | array $stats, 72 | ): self { 73 | if (count($stats) > 3) { 74 | $stats = array_slice($stats, 0, 3); 75 | } 76 | 77 | return $this->withMeta([ 78 | 'stats' => $stats, 79 | ]); 80 | } 81 | 82 | public function verified( 83 | bool $verified = true, 84 | ?string $text = null, 85 | ): self { 86 | return $this->withMeta([ 87 | 'verified' => $verified, 88 | 'verified_text' => $text, 89 | ]); 90 | } 91 | 92 | public function style( 93 | ?string $extend = null, 94 | ?string $override = null, 95 | ): self { 96 | return $this->withMeta([ 97 | 'style_extend' => $extend, 98 | 'style_override' => $override, 99 | ]); 100 | } 101 | 102 | public function component(): string 103 | { 104 | return 'greeter-card'; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/Cards/HtmlCard.php: -------------------------------------------------------------------------------- 1 | withMeta([ 19 | 'center' => false, 20 | 'withoutCardStyles' => false, 21 | 'content' => '', 22 | ]); 23 | } 24 | 25 | public function html( 26 | string $htmlContent, 27 | ): self { 28 | return $this->withMeta([ 29 | 'content' => $htmlContent, 30 | ]); 31 | } 32 | 33 | public function markdown( 34 | string $markdownContent, 35 | ): self { 36 | $htmlContent = App::make(MarkdownConverter::class)::parse($markdownContent) 37 | ->toHtml(); 38 | 39 | return $this->html( 40 | htmlContent: $htmlContent, 41 | ); 42 | } 43 | 44 | public function view( 45 | string $view, 46 | array $viewData = [], 47 | ): self { 48 | $htmlContent = view($view, $viewData) 49 | ->render(); 50 | 51 | return $this->html( 52 | htmlContent: $htmlContent, 53 | ); 54 | } 55 | 56 | public function center( 57 | bool $centerContent = true, 58 | ): self { 59 | return $this->withMeta([ 60 | 'center' => $centerContent, 61 | ]); 62 | } 63 | 64 | public function withoutCardStyles( 65 | bool $withoutStyles = true, 66 | ): self { 67 | return $this->withMeta([ 68 | 'withoutCardStyles' => $withoutStyles, 69 | ]); 70 | } 71 | 72 | public function component(): string 73 | { 74 | return 'html-card'; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/Cards/LinkableCard.php: -------------------------------------------------------------------------------- 1 | withMeta([ 15 | 'url' => '/', 16 | 'title' => 'Linkable Card', 17 | 'subtitle' => '', 18 | 'target' => '_self', 19 | ]); 20 | } 21 | 22 | public function url( 23 | string $url, 24 | ): self { 25 | return $this->withMeta([ 26 | 'url' => $url, 27 | ]); 28 | } 29 | 30 | public function title( 31 | string $title, 32 | ): self { 33 | return $this->withMeta([ 34 | 'title' => $title, 35 | ]); 36 | } 37 | 38 | public function subtitle( 39 | string $subtitle, 40 | ): self { 41 | return $this->withMeta([ 42 | 'subtitle' => $subtitle, 43 | ]); 44 | } 45 | 46 | public function target( 47 | string $target, 48 | ): self { 49 | return $this->withMeta([ 50 | 'target' => $target, 51 | ]); 52 | } 53 | 54 | public function component(): string 55 | { 56 | return 'linkable-card'; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/Cards/PercentageCard.php: -------------------------------------------------------------------------------- 1 | withMeta([ 17 | 'name' => '', 18 | 'label' => '', 19 | 'count' => 0, 20 | 'total' => 0, 21 | 'percentagePrecision' => 2, 22 | ]); 23 | } 24 | 25 | public function name( 26 | string $text, 27 | ): self { 28 | return $this->withMeta([ 29 | 'name' => $text, 30 | ]); 31 | } 32 | 33 | public function label( 34 | string $text, 35 | ): self { 36 | return $this->withMeta([ 37 | 'label' => $text, 38 | ]); 39 | } 40 | 41 | public function count( 42 | int $count, 43 | ): self { 44 | return $this->withMeta([ 45 | 'count' => $count, 46 | ]); 47 | } 48 | 49 | public function total( 50 | int $count, 51 | ): self { 52 | return $this->withMeta([ 53 | 'total' => $count, 54 | ]); 55 | } 56 | 57 | public function percentagePrecision( 58 | int $precision, 59 | ): self { 60 | return $this->withMeta([ 61 | 'percentagePrecision' => $precision, 62 | ]); 63 | } 64 | 65 | public function component(): string 66 | { 67 | return 'percentage-card'; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/Cards/ScheduledJobsCard.php: -------------------------------------------------------------------------------- 1 | initPolling(); 20 | } 21 | 22 | public function title( 23 | string $title = '', 24 | ): self { 25 | return $this->withMeta([ 26 | 'title' => $title, 27 | ]); 28 | } 29 | 30 | public function component(): string 31 | { 32 | return 'scheduled-jobs-card'; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Cards/SslCard.php: -------------------------------------------------------------------------------- 1 | initPolling(); 20 | } 21 | 22 | public function domain( 23 | ?string $domain = null 24 | ): self { 25 | $domain = $domain ?: request()->getHost(); 26 | 27 | return $this->withMeta([ 28 | 'domain' => $domain, 29 | ]); 30 | } 31 | 32 | public function component(): string 33 | { 34 | return 'ssl-card'; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/Cards/SystemResourcesCard.php: -------------------------------------------------------------------------------- 1 | initPolling(); 20 | } 21 | 22 | public function title( 23 | string $title = '', 24 | ): self { 25 | return $this->withMeta([ 26 | 'title' => $title, 27 | ]); 28 | } 29 | 30 | public function component(): string 31 | { 32 | return 'system-resources-card'; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Cards/VersionsCard.php: -------------------------------------------------------------------------------- 1 | initPolling(); 20 | } 21 | 22 | public function title( 23 | string $title = '', 24 | ): self { 25 | return $this->withMeta([ 26 | 'title' => $title, 27 | ]); 28 | } 29 | 30 | public function component(): string 31 | { 32 | return 'versions-card'; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Cards/WeatherCard.php: -------------------------------------------------------------------------------- 1 | initPolling(); 20 | } 21 | 22 | public function city( 23 | string $cityName, 24 | ): self { 25 | return $this->withMeta([ 26 | 'city' => $cityName, 27 | ]); 28 | } 29 | 30 | public function lang( 31 | string $lang, 32 | ): self { 33 | return $this->withMeta([ 34 | 'lang' => $lang, 35 | ]); 36 | } 37 | 38 | public function component(): string 39 | { 40 | return 'weather-card'; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Cards/WorldClockCard.php: -------------------------------------------------------------------------------- 1 | withMeta([ 15 | 'timezones' => $timezones, 16 | ]); 17 | } 18 | 19 | public function title( 20 | string $title = '', 21 | ): self { 22 | return $this->withMeta([ 23 | 'title' => $title, 24 | ]); 25 | } 26 | 27 | public function component(): string 28 | { 29 | return 'world-clock-card'; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Http/Controllers/ScheduledJobsController.php: -------------------------------------------------------------------------------- 1 | events()) 22 | ->map(function ($event) use ($timezone) { 23 | $nextDueDate = $this->getNextDueDateForEvent( 24 | event: $event, 25 | timezone: $timezone, 26 | ); 27 | 28 | preg_match('/artisan.*?\\s(.*)/', $event->command, $matches); 29 | 30 | $command = $matches[1] ?? null; 31 | 32 | return [ 33 | 'command' => $command, 34 | 'description' => $event->description, 35 | 'expression' => $event->expression, 36 | 'humanReadableExpression' => $nextDueDate->diffForHumans(), 37 | 'nextRunAt' => $nextDueDate->toIso8601String(), 38 | 'humanReadableNextRun' => $nextDueDate->diffForHumans(), 39 | 'timezone' => $timezone, 40 | 'withoutOverlapping' => $event->withoutOverlapping, 41 | 'onOneServer' => $event->onOneServer, 42 | ]; 43 | }); 44 | 45 | // $scheduler = app(\Illuminate\Console\Scheduling\Schedule::class); 46 | // $events = $scheduler->events(); 47 | 48 | // foreach ($events as $event) { 49 | // preg_match('/artisan.*?\\s(.*)/', $event->command, $matches); 50 | // $command = $matches[1] ?? null; // Extract the command if available 51 | 52 | // $nextDueDate = $event->nextRunDate(); 53 | // $timezone = $event->timezone ?: config('app.timezone'); 54 | 55 | // $this->info(json_encode([ 56 | // 'command' => $command, 57 | // 'description' => $event->description, 58 | // 'expression' => $event->expression, 59 | // 'humanReadableExpression' => $nextDueDate->diffForHumans(), 60 | // 'nextRunAt' => $nextDueDate->toIso8601String(), 61 | // 'humanReadableNextRun' => $nextDueDate->diffForHumans(), 62 | // 'timezone' => $timezone, 63 | // 'withoutOverlapping' => $event->withoutOverlapping, 64 | // 'onOneServer' => $event->onOneServer, 65 | // ])); 66 | // } 67 | 68 | return response()->json($jobs); 69 | } 70 | 71 | private function getNextDueDateForEvent( 72 | Event $event, 73 | DateTimeZone $timezone 74 | ): Carbon { 75 | return Carbon::instance( 76 | date: (new CronExpression($event->expression)) 77 | ->getNextRunDate( 78 | currentTime: Carbon::now() 79 | ->setTimezone($event->timezone), 80 | ) 81 | ->setTimezone($timezone) 82 | ); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/Http/Controllers/SslController.php: -------------------------------------------------------------------------------- 1 | domain, 17 | ); 18 | 19 | return response()->json([ 20 | 'issuer' => $certificate->getIssuer(), 21 | 'is_valid' => $certificate->isValid(), 22 | 'expiration_date' => $certificate->expirationDate()->diffForHumans(), 23 | 'expiration_date_in_days' => $certificate->expirationDate()->diffInDays(), 24 | ]); 25 | } catch (Exception $e) { 26 | return response()->json([ 27 | 'error' => $e->getMessage(), 28 | ], 404); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/Http/Controllers/SystemResourcesController.php: -------------------------------------------------------------------------------- 1 | json([ 24 | 'disk_space' => [ 25 | 'total' => formatMemory( 26 | size: $diskTotal, 27 | level: 0, 28 | asArray: true, 29 | base: 1024, 30 | ), 31 | 'used' => formatMemory( 32 | size: $diskUsed, 33 | level: 0, 34 | asArray: true, 35 | base: 1024, 36 | ), 37 | 'use_percentage' => round($disk, 1), 38 | ], 39 | 'memory_usage' => [ 40 | 'total' => formatMemory( 41 | size: $ramTotal * 1024, 42 | level: 0, 43 | asArray: true, 44 | base: 1024, 45 | ), 46 | 'used' => formatMemory( 47 | size: $ramUsed * 1024, 48 | level: 0, 49 | asArray: true, 50 | base: 1024, 51 | ), 52 | 'use_percentage' => round($ram, 1), 53 | ], 54 | 'cpu_usage' => [ 55 | 'name' => $cpuName, 56 | 'use_percentage' => $cpu, 57 | ], 58 | ]); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Http/Controllers/VersionsController.php: -------------------------------------------------------------------------------- 1 | php_uname('s') . ' (' . php_uname('r') . ' - ' . php_uname('v') . ')', 14 | 'php' => PHP_VERSION, 15 | 'database' => $this->getDatabase(), 16 | 'laravel' => app()->version(), 17 | 'nova' => Nova::version(), 18 | ]; 19 | } 20 | 21 | private function getDatabase(): string 22 | { 23 | $knownDatabases = [ 24 | 'sqlite', 25 | 'mysql', 26 | 'pgsql', 27 | 'sqlsrv', 28 | ]; 29 | 30 | if (!in_array(config('database.default'), $knownDatabases)) { 31 | return 'Unkown'; 32 | } 33 | 34 | $results = DB::select('select version()'); 35 | 36 | return config('database.default') . ' ' . ((array) $results[0])['version()']; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Http/Controllers/WeatherController.php: -------------------------------------------------------------------------------- 1 | input('q', 'Kiev'), 17 | $request->input('units', 'metric'), 18 | $request->input('lang', config('app.locale')), 19 | ]), 20 | ttl: 10, 21 | callback: fn () => Http::get( 22 | url: 'https://api.openweathermap.org/data/2.5/weather', 23 | query: [ 24 | 'q' => $request->input('q', 'Kiev'), 25 | 'appid' => config('nova-cards.open_weather_api_key'), 26 | 'units' => $request->input('units', 'metric'), 27 | 'lang' => $request->input('lang', config('app.locale')), 28 | ], 29 | )->json(), 30 | ); 31 | 32 | return response()->json($data); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Http/Controllers/WorldClockController.php: -------------------------------------------------------------------------------- 1 | input('timezones', []) as $timezone) { 16 | $time = Carbon::now($timezone); 17 | $night = (int) $time->format('H') > 17; 18 | $name = explode('/', $time->getTimezone()->getName())[1]; 19 | $name = str_replace('_', ' ', $name); 20 | 21 | $times[] = [ 22 | 'name' => __(ucwords($name)), 23 | 'time' => $time->format($request->input('timeFormat', 'H:i:s')), 24 | 'night' => $night, 25 | ]; 26 | } 27 | 28 | return $times; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/LaravelMarkdownConverter.php: -------------------------------------------------------------------------------- 1 | config(); 15 | 16 | $this->app->booted(function (): void { 17 | $this->routes(); 18 | }); 19 | 20 | Nova::serving(function (ServingNova $event): void { 21 | Nova::script('nova-cards', __DIR__ . '/../dist/js/entry.js'); 22 | Nova::style('nova-cards', __DIR__ . '/../dist/css/card.css'); 23 | }); 24 | } 25 | 26 | public function register(): void 27 | { 28 | $this->app->singleton(MarkdownConverter::class, LaravelMarkdownConverter::class); 29 | } 30 | 31 | protected function routes(): void 32 | { 33 | if ($this->app->routesAreCached()) { 34 | return; 35 | } 36 | 37 | Route::middleware(['nova']) 38 | ->prefix('nova-vendor/stepanenko3/nova-cards') 39 | ->group(__DIR__ . '/../routes/api.php'); 40 | } 41 | 42 | private function config(): void 43 | { 44 | if ($this->app->runningInConsole()) { 45 | // Publish config 46 | $this->publishes([ 47 | __DIR__ . '/../config/' => config_path(), 48 | ], 'config'); 49 | } 50 | 51 | $this->mergeConfigFrom( 52 | __DIR__ . '/../config/nova-cards.php', 53 | 'nova-cards' 54 | ); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/Traits/PollingTrait.php: -------------------------------------------------------------------------------- 1 | withMeta([ 10 | 'polling' => true, 11 | 'pollingStart' => false, 12 | 'pollingTime' => 5000, 13 | ]); 14 | } 15 | 16 | public function startPolling(): static 17 | { 18 | return $this->withMeta([ 19 | 'pollingStart' => true, 20 | ]); 21 | } 22 | 23 | public function pollingTime( 24 | int $ms = 1000, 25 | ): static { 26 | return $this->withMeta([ 27 | 'pollingTime' => $ms, 28 | ]); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ['./resources/js/**/*.{vue,js,ts,jsx,tsx}'], 4 | theme: { 5 | extend: {}, 6 | }, 7 | important: '.nova-cards', 8 | plugins: [], 9 | darkMode: 'class' 10 | }; 11 | -------------------------------------------------------------------------------- /vite.config.js: -------------------------------------------------------------------------------- 1 | import vue from "@vitejs/plugin-vue"; 2 | import { resolve } from "path"; 3 | import { defineConfig } from "vite"; 4 | 5 | export default defineConfig({ 6 | plugins: [vue()], 7 | 8 | define: { 9 | "process.env": process.env, // Vite ditched process.env, so we need to pass it in 10 | }, 11 | 12 | build: { 13 | outDir: resolve(__dirname, "dist"), 14 | emptyOutDir: true, 15 | target: "ES2022", 16 | minify: true, 17 | manifest: true, 18 | lib: { 19 | entry: resolve(__dirname, "resources/js/entry.js"), 20 | name: "cards", 21 | formats: ["umd"], 22 | fileName: () => "js/entry.js", 23 | }, 24 | rollupOptions: { 25 | input: resolve(__dirname, "resources/js/entry.js"), 26 | external: ["vue", "Nova", "LaravelNova"], 27 | output: { 28 | globals: { 29 | vue: "Vue", 30 | nova: "Nova", 31 | "laravel-nova": "LaravelNova", 32 | }, 33 | assetFileNames: "css/card.css", 34 | }, 35 | }, 36 | }, 37 | 38 | optimizeDeps: { 39 | include: ["vue", "@inertiajs/inertia", "@inertiajs/inertia-vue3", "axios"], 40 | }, 41 | }); 42 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/helper-string-parser@^7.25.9": 6 | version "7.25.9" 7 | resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c" 8 | integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== 9 | 10 | "@babel/helper-validator-identifier@^7.25.9": 11 | version "7.25.9" 12 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" 13 | integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== 14 | 15 | "@babel/parser@^7.25.3": 16 | version "7.26.3" 17 | resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.3.tgz#8c51c5db6ddf08134af1ddbacf16aaab48bac234" 18 | integrity sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA== 19 | dependencies: 20 | "@babel/types" "^7.26.3" 21 | 22 | "@babel/types@^7.26.3": 23 | version "7.26.3" 24 | resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.3.tgz#37e79830f04c2b5687acc77db97fbc75fb81f3c0" 25 | integrity sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA== 26 | dependencies: 27 | "@babel/helper-string-parser" "^7.25.9" 28 | "@babel/helper-validator-identifier" "^7.25.9" 29 | 30 | "@esbuild/aix-ppc64@0.25.0": 31 | version "0.25.0" 32 | resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz#499600c5e1757a524990d5d92601f0ac3ce87f64" 33 | integrity sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ== 34 | 35 | "@esbuild/android-arm64@0.25.0": 36 | version "0.25.0" 37 | resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz#b9b8231561a1dfb94eb31f4ee056b92a985c324f" 38 | integrity sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g== 39 | 40 | "@esbuild/android-arm@0.25.0": 41 | version "0.25.0" 42 | resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.0.tgz#ca6e7888942505f13e88ac9f5f7d2a72f9facd2b" 43 | integrity sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g== 44 | 45 | "@esbuild/android-x64@0.25.0": 46 | version "0.25.0" 47 | resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.0.tgz#e765ea753bac442dfc9cb53652ce8bd39d33e163" 48 | integrity sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg== 49 | 50 | "@esbuild/darwin-arm64@0.25.0": 51 | version "0.25.0" 52 | resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz#fa394164b0d89d4fdc3a8a21989af70ef579fa2c" 53 | integrity sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw== 54 | 55 | "@esbuild/darwin-x64@0.25.0": 56 | version "0.25.0" 57 | resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz#91979d98d30ba6e7d69b22c617cc82bdad60e47a" 58 | integrity sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg== 59 | 60 | "@esbuild/freebsd-arm64@0.25.0": 61 | version "0.25.0" 62 | resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz#b97e97073310736b430a07b099d837084b85e9ce" 63 | integrity sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w== 64 | 65 | "@esbuild/freebsd-x64@0.25.0": 66 | version "0.25.0" 67 | resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz#f3b694d0da61d9910ec7deff794d444cfbf3b6e7" 68 | integrity sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A== 69 | 70 | "@esbuild/linux-arm64@0.25.0": 71 | version "0.25.0" 72 | resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz#f921f699f162f332036d5657cad9036f7a993f73" 73 | integrity sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg== 74 | 75 | "@esbuild/linux-arm@0.25.0": 76 | version "0.25.0" 77 | resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz#cc49305b3c6da317c900688995a4050e6cc91ca3" 78 | integrity sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg== 79 | 80 | "@esbuild/linux-ia32@0.25.0": 81 | version "0.25.0" 82 | resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz#3e0736fcfab16cff042dec806247e2c76e109e19" 83 | integrity sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg== 84 | 85 | "@esbuild/linux-loong64@0.25.0": 86 | version "0.25.0" 87 | resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz#ea2bf730883cddb9dfb85124232b5a875b8020c7" 88 | integrity sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw== 89 | 90 | "@esbuild/linux-mips64el@0.25.0": 91 | version "0.25.0" 92 | resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz#4cababb14eede09248980a2d2d8b966464294ff1" 93 | integrity sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ== 94 | 95 | "@esbuild/linux-ppc64@0.25.0": 96 | version "0.25.0" 97 | resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz#8860a4609914c065373a77242e985179658e1951" 98 | integrity sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw== 99 | 100 | "@esbuild/linux-riscv64@0.25.0": 101 | version "0.25.0" 102 | resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz#baf26e20bb2d38cfb86ee282dff840c04f4ed987" 103 | integrity sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA== 104 | 105 | "@esbuild/linux-s390x@0.25.0": 106 | version "0.25.0" 107 | resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz#8323afc0d6cb1b6dc6e9fd21efd9e1542c3640a4" 108 | integrity sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA== 109 | 110 | "@esbuild/linux-x64@0.25.0": 111 | version "0.25.0" 112 | resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz#08fcf60cb400ed2382e9f8e0f5590bac8810469a" 113 | integrity sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw== 114 | 115 | "@esbuild/netbsd-arm64@0.25.0": 116 | version "0.25.0" 117 | resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz#935c6c74e20f7224918fbe2e6c6fe865b6c6ea5b" 118 | integrity sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw== 119 | 120 | "@esbuild/netbsd-x64@0.25.0": 121 | version "0.25.0" 122 | resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz#414677cef66d16c5a4d210751eb2881bb9c1b62b" 123 | integrity sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA== 124 | 125 | "@esbuild/openbsd-arm64@0.25.0": 126 | version "0.25.0" 127 | resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz#8fd55a4d08d25cdc572844f13c88d678c84d13f7" 128 | integrity sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw== 129 | 130 | "@esbuild/openbsd-x64@0.25.0": 131 | version "0.25.0" 132 | resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz#0c48ddb1494bbc2d6bcbaa1429a7f465fa1dedde" 133 | integrity sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg== 134 | 135 | "@esbuild/sunos-x64@0.25.0": 136 | version "0.25.0" 137 | resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz#86ff9075d77962b60dd26203d7352f92684c8c92" 138 | integrity sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg== 139 | 140 | "@esbuild/win32-arm64@0.25.0": 141 | version "0.25.0" 142 | resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz#849c62327c3229467f5b5cd681bf50588442e96c" 143 | integrity sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw== 144 | 145 | "@esbuild/win32-ia32@0.25.0": 146 | version "0.25.0" 147 | resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz#f62eb480cd7cca088cb65bb46a6db25b725dc079" 148 | integrity sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA== 149 | 150 | "@esbuild/win32-x64@0.25.0": 151 | version "0.25.0" 152 | resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz#c8e119a30a7c8d60b9d2e22d2073722dde3b710b" 153 | integrity sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ== 154 | 155 | "@inertiajs/inertia-vue3@^0.6.0": 156 | version "0.6.0" 157 | resolved "https://registry.npmjs.org/@inertiajs/inertia-vue3/-/inertia-vue3-0.6.0.tgz" 158 | integrity sha512-qhPBtd/G0VS7vVVbYw1rrqKB6JqRusxqt+5ec2GLmK6t7fTlBBnZ3KsakmGZLSM1m1OGkNcfn4ifmCk3zfA8RQ== 159 | dependencies: 160 | lodash.clonedeep "^4.5.0" 161 | lodash.isequal "^4.5.0" 162 | 163 | "@inertiajs/inertia@^0.11.1": 164 | version "0.11.1" 165 | resolved "https://registry.npmjs.org/@inertiajs/inertia/-/inertia-0.11.1.tgz" 166 | integrity sha512-btmV53c54oW4Z9XF0YyTdIUnM7ue0ONy3/KJOz6J1C5CYIwimiKfDMpz8ZbGJuxS+SPdOlNsqj2ZhlHslpJRZg== 167 | dependencies: 168 | axios "^0.21.1" 169 | deepmerge "^4.0.0" 170 | qs "^6.9.0" 171 | 172 | "@jridgewell/sourcemap-codec@^1.5.0": 173 | version "1.5.0" 174 | resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" 175 | integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== 176 | 177 | "@rollup/rollup-android-arm-eabi@4.34.8": 178 | version "4.34.8" 179 | resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.8.tgz#731df27dfdb77189547bcef96ada7bf166bbb2fb" 180 | integrity sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw== 181 | 182 | "@rollup/rollup-android-arm64@4.34.8": 183 | version "4.34.8" 184 | resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.8.tgz#4bea6db78e1f6927405df7fe0faf2f5095e01343" 185 | integrity sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q== 186 | 187 | "@rollup/rollup-darwin-arm64@4.34.8": 188 | version "4.34.8" 189 | resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.8.tgz#a7aab77d44be3c44a20f946e10160f84e5450e7f" 190 | integrity sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q== 191 | 192 | "@rollup/rollup-darwin-x64@4.34.8": 193 | version "4.34.8" 194 | resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.8.tgz#c572c024b57ee8ddd1b0851703ace9eb6cc0dd82" 195 | integrity sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw== 196 | 197 | "@rollup/rollup-freebsd-arm64@4.34.8": 198 | version "4.34.8" 199 | resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.8.tgz#cf74f8113b5a83098a5c026c165742277cbfb88b" 200 | integrity sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA== 201 | 202 | "@rollup/rollup-freebsd-x64@4.34.8": 203 | version "4.34.8" 204 | resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.8.tgz#39561f3a2f201a4ad6a01425b1ff5928154ecd7c" 205 | integrity sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q== 206 | 207 | "@rollup/rollup-linux-arm-gnueabihf@4.34.8": 208 | version "4.34.8" 209 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.8.tgz#980d6061e373bfdaeb67925c46d2f8f9b3de537f" 210 | integrity sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g== 211 | 212 | "@rollup/rollup-linux-arm-musleabihf@4.34.8": 213 | version "4.34.8" 214 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.8.tgz#f91a90f30dc00d5a64ac2d9bbedc829cd3cfaa78" 215 | integrity sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA== 216 | 217 | "@rollup/rollup-linux-arm64-gnu@4.34.8": 218 | version "4.34.8" 219 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.8.tgz#fac700fa5c38bc13a0d5d34463133093da4c92a0" 220 | integrity sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A== 221 | 222 | "@rollup/rollup-linux-arm64-musl@4.34.8": 223 | version "4.34.8" 224 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.8.tgz#f50ecccf8c78841ff6df1706bc4782d7f62bf9c3" 225 | integrity sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q== 226 | 227 | "@rollup/rollup-linux-loongarch64-gnu@4.34.8": 228 | version "4.34.8" 229 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.8.tgz#5869dc0b28242da6553e2b52af41374f4038cd6e" 230 | integrity sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ== 231 | 232 | "@rollup/rollup-linux-powerpc64le-gnu@4.34.8": 233 | version "4.34.8" 234 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.8.tgz#5cdd9f851ce1bea33d6844a69f9574de335f20b1" 235 | integrity sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw== 236 | 237 | "@rollup/rollup-linux-riscv64-gnu@4.34.8": 238 | version "4.34.8" 239 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.8.tgz#ef5dc37f4388f5253f0def43e1440ec012af204d" 240 | integrity sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw== 241 | 242 | "@rollup/rollup-linux-s390x-gnu@4.34.8": 243 | version "4.34.8" 244 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.8.tgz#7dbc3ccbcbcfb3e65be74538dfb6e8dd16178fde" 245 | integrity sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA== 246 | 247 | "@rollup/rollup-linux-x64-gnu@4.34.8": 248 | version "4.34.8" 249 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.8.tgz#5783fc0adcab7dc069692056e8ca8d83709855ce" 250 | integrity sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA== 251 | 252 | "@rollup/rollup-linux-x64-musl@4.34.8": 253 | version "4.34.8" 254 | resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.8.tgz#00b6c29b298197a384e3c659910b47943003a678" 255 | integrity sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ== 256 | 257 | "@rollup/rollup-win32-arm64-msvc@4.34.8": 258 | version "4.34.8" 259 | resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.8.tgz#cbfee01f1fe73791c35191a05397838520ca3cdd" 260 | integrity sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ== 261 | 262 | "@rollup/rollup-win32-ia32-msvc@4.34.8": 263 | version "4.34.8" 264 | resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.8.tgz#95cdbdff48fe6c948abcf6a1d500b2bd5ce33f62" 265 | integrity sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w== 266 | 267 | "@rollup/rollup-win32-x64-msvc@4.34.8": 268 | version "4.34.8" 269 | resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.8.tgz#4cdb2cfae69cdb7b1a3cc58778e820408075e928" 270 | integrity sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g== 271 | 272 | "@types/estree@1.0.6": 273 | version "1.0.6" 274 | resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" 275 | integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== 276 | 277 | "@vitejs/plugin-vue@^5.2.1": 278 | version "5.2.1" 279 | resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-5.2.1.tgz#d1491f678ee3af899f7ae57d9c21dc52a65c7133" 280 | integrity sha512-cxh314tzaWwOLqVes2gnnCtvBDcM1UMdn+iFR+UjAn411dPT3tOmqrJjbMd7koZpMAmBM/GqeV4n9ge7JSiJJQ== 281 | 282 | "@vue/compiler-core@3.5.13": 283 | version "3.5.13" 284 | resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.5.13.tgz#b0ae6c4347f60c03e849a05d34e5bf747c9bda05" 285 | integrity sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q== 286 | dependencies: 287 | "@babel/parser" "^7.25.3" 288 | "@vue/shared" "3.5.13" 289 | entities "^4.5.0" 290 | estree-walker "^2.0.2" 291 | source-map-js "^1.2.0" 292 | 293 | "@vue/compiler-dom@3.5.13": 294 | version "3.5.13" 295 | resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz#bb1b8758dbc542b3658dda973b98a1c9311a8a58" 296 | integrity sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA== 297 | dependencies: 298 | "@vue/compiler-core" "3.5.13" 299 | "@vue/shared" "3.5.13" 300 | 301 | "@vue/compiler-sfc@^3.5.13": 302 | version "3.5.13" 303 | resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz#461f8bd343b5c06fac4189c4fef8af32dea82b46" 304 | integrity sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ== 305 | dependencies: 306 | "@babel/parser" "^7.25.3" 307 | "@vue/compiler-core" "3.5.13" 308 | "@vue/compiler-dom" "3.5.13" 309 | "@vue/compiler-ssr" "3.5.13" 310 | "@vue/shared" "3.5.13" 311 | estree-walker "^2.0.2" 312 | magic-string "^0.30.11" 313 | postcss "^8.4.48" 314 | source-map-js "^1.2.0" 315 | 316 | "@vue/compiler-ssr@3.5.13": 317 | version "3.5.13" 318 | resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz#e771adcca6d3d000f91a4277c972a996d07f43ba" 319 | integrity sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA== 320 | dependencies: 321 | "@vue/compiler-dom" "3.5.13" 322 | "@vue/shared" "3.5.13" 323 | 324 | "@vue/shared@3.5.13": 325 | version "3.5.13" 326 | resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.5.13.tgz#87b309a6379c22b926e696893237826f64339b6f" 327 | integrity sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ== 328 | 329 | autoprefixer@^10.4.21: 330 | version "10.4.21" 331 | resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.21.tgz#77189468e7a8ad1d9a37fbc08efc9f480cf0a95d" 332 | integrity sha512-O+A6LWV5LDHSJD3LjHYoNi4VLsj/Whi7k6zG12xTYaU4cQ8oxQGckXNX8cRHK5yOZ/ppVHe0ZBXGzSV9jXdVbQ== 333 | dependencies: 334 | browserslist "^4.24.4" 335 | caniuse-lite "^1.0.30001702" 336 | fraction.js "^4.3.7" 337 | normalize-range "^0.1.2" 338 | picocolors "^1.1.1" 339 | postcss-value-parser "^4.2.0" 340 | 341 | axios@^0.21.1: 342 | version "0.21.4" 343 | resolved "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz" 344 | integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== 345 | dependencies: 346 | follow-redirects "^1.14.0" 347 | 348 | browserslist@^4.24.4: 349 | version "4.24.4" 350 | resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.4.tgz#c6b2865a3f08bcb860a0e827389003b9fe686e4b" 351 | integrity sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A== 352 | dependencies: 353 | caniuse-lite "^1.0.30001688" 354 | electron-to-chromium "^1.5.73" 355 | node-releases "^2.0.19" 356 | update-browserslist-db "^1.1.1" 357 | 358 | call-bind@^1.0.0: 359 | version "1.0.2" 360 | resolved "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz" 361 | integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== 362 | dependencies: 363 | function-bind "^1.1.1" 364 | get-intrinsic "^1.0.2" 365 | 366 | caniuse-lite@^1.0.30001688, caniuse-lite@^1.0.30001702: 367 | version "1.0.30001703" 368 | resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001703.tgz#977cb4920598c158f491ecf4f4f2cfed9e354718" 369 | integrity sha512-kRlAGTRWgPsOj7oARC9m1okJEXdL/8fekFVcxA8Hl7GH4r/sN4OJn/i6Flde373T50KS7Y37oFbMwlE8+F42kQ== 370 | 371 | deepmerge@^4.0.0: 372 | version "4.3.1" 373 | resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz" 374 | integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== 375 | 376 | electron-to-chromium@^1.5.73: 377 | version "1.5.73" 378 | resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.73.tgz#f32956ce40947fa3c8606726a96cd8fb5bb5f720" 379 | integrity sha512-8wGNxG9tAG5KhGd3eeA0o6ixhiNdgr0DcHWm85XPCphwZgD1lIEoi6t3VERayWao7SF7AAZTw6oARGJeVjH8Kg== 380 | 381 | entities@^4.5.0: 382 | version "4.5.0" 383 | resolved "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz" 384 | integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== 385 | 386 | esbuild@^0.25.0: 387 | version "0.25.0" 388 | resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.0.tgz#0de1787a77206c5a79eeb634a623d39b5006ce92" 389 | integrity sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw== 390 | optionalDependencies: 391 | "@esbuild/aix-ppc64" "0.25.0" 392 | "@esbuild/android-arm" "0.25.0" 393 | "@esbuild/android-arm64" "0.25.0" 394 | "@esbuild/android-x64" "0.25.0" 395 | "@esbuild/darwin-arm64" "0.25.0" 396 | "@esbuild/darwin-x64" "0.25.0" 397 | "@esbuild/freebsd-arm64" "0.25.0" 398 | "@esbuild/freebsd-x64" "0.25.0" 399 | "@esbuild/linux-arm" "0.25.0" 400 | "@esbuild/linux-arm64" "0.25.0" 401 | "@esbuild/linux-ia32" "0.25.0" 402 | "@esbuild/linux-loong64" "0.25.0" 403 | "@esbuild/linux-mips64el" "0.25.0" 404 | "@esbuild/linux-ppc64" "0.25.0" 405 | "@esbuild/linux-riscv64" "0.25.0" 406 | "@esbuild/linux-s390x" "0.25.0" 407 | "@esbuild/linux-x64" "0.25.0" 408 | "@esbuild/netbsd-arm64" "0.25.0" 409 | "@esbuild/netbsd-x64" "0.25.0" 410 | "@esbuild/openbsd-arm64" "0.25.0" 411 | "@esbuild/openbsd-x64" "0.25.0" 412 | "@esbuild/sunos-x64" "0.25.0" 413 | "@esbuild/win32-arm64" "0.25.0" 414 | "@esbuild/win32-ia32" "0.25.0" 415 | "@esbuild/win32-x64" "0.25.0" 416 | 417 | escalade@^3.2.0: 418 | version "3.2.0" 419 | resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" 420 | integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== 421 | 422 | estree-walker@^2.0.2: 423 | version "2.0.2" 424 | resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz" 425 | integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== 426 | 427 | follow-redirects@^1.14.0: 428 | version "1.15.0" 429 | resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.0.tgz" 430 | integrity sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ== 431 | 432 | fraction.js@^4.3.7: 433 | version "4.3.7" 434 | resolved "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz" 435 | integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew== 436 | 437 | fsevents@~2.3.2, fsevents@~2.3.3: 438 | version "2.3.3" 439 | resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz" 440 | integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== 441 | 442 | function-bind@^1.1.1: 443 | version "1.1.2" 444 | resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz" 445 | integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== 446 | 447 | get-intrinsic@^1.0.2: 448 | version "1.1.1" 449 | resolved "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz" 450 | integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== 451 | dependencies: 452 | function-bind "^1.1.1" 453 | has "^1.0.3" 454 | has-symbols "^1.0.1" 455 | 456 | has-symbols@^1.0.1: 457 | version "1.0.3" 458 | resolved "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz" 459 | integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== 460 | 461 | has@^1.0.3: 462 | version "1.0.3" 463 | resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" 464 | integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== 465 | dependencies: 466 | function-bind "^1.1.1" 467 | 468 | lodash.clonedeep@^4.5.0: 469 | version "4.5.0" 470 | resolved "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz" 471 | integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ== 472 | 473 | lodash.isequal@^4.5.0: 474 | version "4.5.0" 475 | resolved "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz" 476 | integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== 477 | 478 | magic-string@^0.30.11: 479 | version "0.30.17" 480 | resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.17.tgz#450a449673d2460e5bbcfba9a61916a1714c7453" 481 | integrity sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA== 482 | dependencies: 483 | "@jridgewell/sourcemap-codec" "^1.5.0" 484 | 485 | nanoid@^3.3.8: 486 | version "3.3.8" 487 | resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf" 488 | integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w== 489 | 490 | node-releases@^2.0.19: 491 | version "2.0.19" 492 | resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314" 493 | integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== 494 | 495 | normalize-range@^0.1.2: 496 | version "0.1.2" 497 | resolved "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz" 498 | integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= 499 | 500 | object-inspect@^1.9.0: 501 | version "1.12.0" 502 | resolved "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz" 503 | integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== 504 | 505 | picocolors@^1.1.0, picocolors@^1.1.1: 506 | version "1.1.1" 507 | resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" 508 | integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== 509 | 510 | postcss-value-parser@^4.2.0: 511 | version "4.2.0" 512 | resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz" 513 | integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== 514 | 515 | postcss@^8.4.48, postcss@^8.4.49, postcss@^8.5.3: 516 | version "8.5.3" 517 | resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.3.tgz#1463b6f1c7fb16fe258736cba29a2de35237eafb" 518 | integrity sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A== 519 | dependencies: 520 | nanoid "^3.3.8" 521 | picocolors "^1.1.1" 522 | source-map-js "^1.2.1" 523 | 524 | qs@^6.9.0: 525 | version "6.10.3" 526 | resolved "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz" 527 | integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== 528 | dependencies: 529 | side-channel "^1.0.4" 530 | 531 | rollup@^4.30.1: 532 | version "4.34.8" 533 | resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.34.8.tgz#e859c1a51d899aba9bcf451d4eed1d11fb8e2a6e" 534 | integrity sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ== 535 | dependencies: 536 | "@types/estree" "1.0.6" 537 | optionalDependencies: 538 | "@rollup/rollup-android-arm-eabi" "4.34.8" 539 | "@rollup/rollup-android-arm64" "4.34.8" 540 | "@rollup/rollup-darwin-arm64" "4.34.8" 541 | "@rollup/rollup-darwin-x64" "4.34.8" 542 | "@rollup/rollup-freebsd-arm64" "4.34.8" 543 | "@rollup/rollup-freebsd-x64" "4.34.8" 544 | "@rollup/rollup-linux-arm-gnueabihf" "4.34.8" 545 | "@rollup/rollup-linux-arm-musleabihf" "4.34.8" 546 | "@rollup/rollup-linux-arm64-gnu" "4.34.8" 547 | "@rollup/rollup-linux-arm64-musl" "4.34.8" 548 | "@rollup/rollup-linux-loongarch64-gnu" "4.34.8" 549 | "@rollup/rollup-linux-powerpc64le-gnu" "4.34.8" 550 | "@rollup/rollup-linux-riscv64-gnu" "4.34.8" 551 | "@rollup/rollup-linux-s390x-gnu" "4.34.8" 552 | "@rollup/rollup-linux-x64-gnu" "4.34.8" 553 | "@rollup/rollup-linux-x64-musl" "4.34.8" 554 | "@rollup/rollup-win32-arm64-msvc" "4.34.8" 555 | "@rollup/rollup-win32-ia32-msvc" "4.34.8" 556 | "@rollup/rollup-win32-x64-msvc" "4.34.8" 557 | fsevents "~2.3.2" 558 | 559 | side-channel@^1.0.4: 560 | version "1.0.4" 561 | resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz" 562 | integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== 563 | dependencies: 564 | call-bind "^1.0.0" 565 | get-intrinsic "^1.0.2" 566 | object-inspect "^1.9.0" 567 | 568 | source-map-js@^1.2.0, source-map-js@^1.2.1: 569 | version "1.2.1" 570 | resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" 571 | integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== 572 | 573 | tailwindcss@^4.0.13: 574 | version "4.0.13" 575 | resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-4.0.13.tgz#093935db2e4b80d245386f69da580528ac5b1b3c" 576 | integrity sha512-gbvFrB0fOsTv/OugXWi2PtflJ4S6/ctu6Mmn3bCftmLY/6xRsQVEJPgIIpABwpZ52DpONkCA3bEj5b54MHxF2Q== 577 | 578 | update-browserslist-db@^1.1.1: 579 | version "1.1.1" 580 | resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz#80846fba1d79e82547fb661f8d141e0945755fe5" 581 | integrity sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A== 582 | dependencies: 583 | escalade "^3.2.0" 584 | picocolors "^1.1.0" 585 | 586 | vite@^6.2.1: 587 | version "6.2.1" 588 | resolved "https://registry.yarnpkg.com/vite/-/vite-6.2.1.tgz#ae865d4bb93a11844be1bc647c8b2dd1856ea180" 589 | integrity sha512-n2GnqDb6XPhlt9B8olZPrgMD/es/Nd1RdChF6CBD/fHW6pUyUTt2sQW2fPRX5GiD9XEa6+8A6A4f2vT6pSsE7Q== 590 | dependencies: 591 | esbuild "^0.25.0" 592 | postcss "^8.5.3" 593 | rollup "^4.30.1" 594 | optionalDependencies: 595 | fsevents "~2.3.3" 596 | --------------------------------------------------------------------------------