diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..ed3b5ef --- /dev/null +++ b/.prettierrc @@ -0,0 +1,13 @@ +{ + "plugins": ["prettier-plugin-blade"], + "overrides": [ + { + "files": ["*.blade.php"], + "options": { + "parser": "blade" + } + } + ], + "singleQuote": true, + "tabWidth": 4 +} diff --git a/app/Bots/BotContract.php b/app/Bots/BotContract.php new file mode 100644 index 0000000..8379329 --- /dev/null +++ b/app/Bots/BotContract.php @@ -0,0 +1,9 @@ +client = new Client([ + 'base_uri' => rtrim(config('scheduler.mattermost.server_url'), '/') . '/api/v4/', + 'headers' => [ + 'Authorization' => 'Bearer ' . config('scheduler.mattermost.access_token'), + 'Accept' => 'application/json', + 'Content-Type' => 'application/json', + ], + ]); + } + + public function run(): void + { + try { + $request = new \GuzzleHttp\Psr7\Request( + $this->config['method'] ?? 'POST', + $this->config['endpoint'], + ['Content-Type' => 'application/json'], + json_encode($this->config['body'] ?? []) + ); + + $res = $this->client->send($request); + + // $res = $this->client->put('users/me/status/custom', [ + // 'json' => [ + // 'emoji' => 'house', + // 'text' => 'Working Home', + // 'status' => 'online', + // ] + // ]); + + if ($res->getStatusCode() === 200) { + Log::info("Mattermost home status updated successfully."); + } else { + Log::error("Failed to update Mattermost status. HTTP Status: " . $res->getStatusCode()); + } + } catch (\Exception $e) { + Log::error("Error updating Mattermost status: " . $e->getMessage()); + } + } + + public static function configSchema(): array + { + return [ + 'endpoint' => ['type' => 'string', 'label' => 'API Endpoint', 'rules' => [ + 'required', + 'string', + 'max:255', + ]], + 'method' => ['type' => 'string', 'label' => 'HTTP Method', 'default' => 'POST', 'rules' => [ + 'required', + 'in:GET,POST,PUT,DELETE,PATCH', + ]], + 'body' => ['type' => 'array', 'label' => 'Request Body (JSON)', 'rules' => [ + 'nullable', + 'array', + ]], + ]; + } +} diff --git a/app/Bots/Mattermost/RemoveStatus.php b/app/Bots/Mattermost/RemoveStatus.php new file mode 100644 index 0000000..2103e37 --- /dev/null +++ b/app/Bots/Mattermost/RemoveStatus.php @@ -0,0 +1,46 @@ +client = new Client([ + 'base_uri' => rtrim(config('scheduler.mattermost.server_url'), '/') . '/api/v4/', + 'headers' => [ + 'Authorization' => 'Bearer ' . config('scheduler.mattermost.access_token'), + ], + ]); + } + + public function run(): void + { + try { + $res = $this->client->delete('users/me/status/custom'); + + if ($res->getStatusCode() === 200) { + Log::info("Mattermost status cleared"); + } else { + Log::error("Failed to update Mattermost status. HTTP Status: " . $res->getStatusCode()); + } + } catch (\Exception $e) { + Log::error("Error updating Mattermost status: " . $e->getMessage()); + } + } + + public static function configSchema(): array + { + return [ + 'endpoint' => ['type' => 'string', 'label' => 'API Endpoint'], + 'method' => ['type' => 'string', 'label' => 'HTTP Method', 'default' => 'POST'], + 'body' => ['type' => 'array', 'label' => 'Request Body (JSON)'], + ]; + } +} diff --git a/app/Bots/Mattermost/WednesdayHomeStatus.php b/app/Bots/Mattermost/WednesdayHomeStatus.php new file mode 100644 index 0000000..168ad91 --- /dev/null +++ b/app/Bots/Mattermost/WednesdayHomeStatus.php @@ -0,0 +1,54 @@ +client = new Client([ + 'base_uri' => rtrim(config('scheduler.mattermost.server_url'), '/') . '/api/v4/', + 'headers' => [ + 'Authorization' => 'Bearer ' . config('scheduler.mattermost.access_token'), + 'Accept' => 'application/json', + 'Content-Type' => 'application/json', + ], + ]); + } + + public function run(): void + { + try { + $res = $this->client->put('users/me/status/custom', [ + 'json' => [ + 'emoji' => 'house', + 'text' => 'Working Home', + 'status' => 'online', + ] + ]); + + if ($res->getStatusCode() === 200) { + Log::info("Mattermost home status updated successfully."); + } else { + Log::error("Failed to update Mattermost status. HTTP Status: " . $res->getStatusCode()); + } + } catch (\Exception $e) { + Log::error("Error updating Mattermost status: " . $e->getMessage()); + } + } + + public static function configSchema(): array + { + return [ + 'endpoint' => ['type' => 'string', 'label' => 'API Endpoint'], + 'method' => ['type' => 'string', 'label' => 'HTTP Method', 'default' => 'POST'], + 'body' => ['type' => 'array', 'label' => 'Request Body (JSON)'], + ]; + } +} diff --git a/app/Http/Controllers/BotController.php b/app/Http/Controllers/BotController.php new file mode 100644 index 0000000..3527bd5 --- /dev/null +++ b/app/Http/Controllers/BotController.php @@ -0,0 +1,13 @@ +bots = \App\Models\Bot::all(); + } + + public function toggleBot($botId) + { + $bot = \App\Models\Bot::find($botId); + + if ($bot) { + $bot->enabled = !$bot->enabled; + $bot->save(); + $this->bots = \App\Models\Bot::all(); // Refresh the list + flash()->success("Bot '{$bot->name}' has been " . ($bot->enabled ? 'enabled' : 'disabled') . "."); + } + } + + public function render() + { + return view('livewire.bots-list'); + } +} diff --git a/app/Livewire/CreateEditBot.php b/app/Livewire/CreateEditBot.php new file mode 100644 index 0000000..2321f00 --- /dev/null +++ b/app/Livewire/CreateEditBot.php @@ -0,0 +1,164 @@ +routeName = URL::current() === route('bots.create') ? 'Create Bot' : 'Edit Bot'; + + $bot = \App\Models\Bot::find($bot); + if ($bot) { + $this->name = $bot->name; + $this->class = $bot->class; + $this->schedule = $bot->schedule; + $this->enabled = $bot->enabled; + $this->cron_text = \Lorisleiva\CronTranslator\CronTranslator::translate($bot->schedule); + } + + $basePath = $basePath ?? app_path('Bots'); + $baseNamespace = $baseNamespace ?? 'App\\Bots'; + + foreach (File::allFiles($basePath) as $file) { + // Convert file path → class name + $relativePath = str_replace([$basePath . DIRECTORY_SEPARATOR, '.php'], '', $file->getPathname()); + $relativeNamespace = str_replace(DIRECTORY_SEPARATOR, '\\', $relativePath); + $class = $baseNamespace . '\\' . $relativeNamespace; + + // Make sure class exists and implements BotContract + if (class_exists($class) && in_array(BotContract::class, class_implements($class))) { + $label = method_exists($class, 'label') + ? $class::label() + : class_basename($class); + + $this->classList[$label] = $class; + } + } + } + + public function updatedClass($value) + { + $this->class = $this->classList[$value]; + $this->configSchema = $this->classList[$value]::configSchema(); + } + + protected function rules(): array + { + $schemaRules = []; + + foreach ($this->configSchema as $field => $meta) { + $schemaRules["config.$field"] = $meta['rules'] ?? []; + } + + return array_merge([ + 'name' => [ + 'required', + 'string', + 'max:255', + Rule::unique('bots', 'name')->ignore($this->name, 'name'), + ], + 'class' => [ + 'required', + 'string', + 'max:255', + ], + 'schedule' => [ + 'required', + 'string', + 'max:255', + function ($attribute, $value, $fail) { + if (!CronExpression::isValidExpression($value)) { + $fail('The ' . $attribute . ' is not a valid cron expression.'); + } + }, + ], + 'enabled' => ['boolean'], + ], $schemaRules); + } + + public function save(): void + { + $this->validate(); + + if (!class_exists($this->class)) { + $this->addError('class', 'The specified class does not exist.'); + return; + } + + if (!in_array(\App\Bots\BotContract::class, class_implements($this->class))) { + $this->addError('class', 'The specified class does not exist.'); + return; + } + + if (URL::current() !== route('bots.create')) { + $bot = \App\Models\Bot::where('name', $this->name)->first(); + if ($bot) { + $bot->update([ + 'name' => $this->name, + 'class' => $this->class, + 'enabled' => $this->enabled, + 'schedule' => $this->schedule, + ]); + + flash()->success('Bot updated successfully.'); + + return; + } + } else { + \App\Models\Bot::create([ + 'name' => $this->name, + 'class' => $this->class, + 'enabled' => $this->enabled, + 'schedule' => $this->schedule, + ]); + } + + flash()->success('Bot created successfully.'); + + $this->reset(['name', 'namespace', 'class', 'enabled', 'schedule']); + } + + public function updatedSchedule($value) + { + try { + $this->cron_text = CronTranslator::translate($value); + $this->resetErrorBag('schedule'); + } catch (CronParsingException $e) { + $this->cron_text = ''; + } + } + + public function render() + { + return view('livewire.create-edit-bot'); + } +} diff --git a/app/Models/Bot.php b/app/Models/Bot.php new file mode 100644 index 0000000..31462c4 --- /dev/null +++ b/app/Models/Bot.php @@ -0,0 +1,39 @@ + 'array', + ]; + + public function nextDue(): Attribute + { + return Attribute::make( + get: function () { + $cron = new CronExpression($this->schedule); + return $cron->getNextRunDate()->format('Y-m-d H:i:s'); + } + ); + } + + public function cronToHuman(): Attribute + { + return Attribute::make( + get: fn () => CronTranslator::translate($this->schedule)); + } +} diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 452e6b6..a2e13ff 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -11,7 +11,9 @@ class AppServiceProvider extends ServiceProvider */ public function register(): void { - // + app()->singleton(\App\Services\BotService::class, function ($app) { + return new \App\Services\BotService(); + }); } /** diff --git a/app/Services/BotService.php b/app/Services/BotService.php new file mode 100644 index 0000000..62a4279 --- /dev/null +++ b/app/Services/BotService.php @@ -0,0 +1,33 @@ +get(); + + foreach ($bots as $bot) { + $cron = new CronExpression($bot->schedule); + if ($cron->isDue()) { + try { + $instance = app($bot->class, ['config' => $bot->config]); + + if ($instance instanceof BotContract) { + $instance->run(); + } + } catch (\Throwable $e) { + Log::error("Bot [{$bot->name}] failed: " . $e->getMessage()); + } + + Log::info("Bot [{$bot->name}] executed successfully."); + } + } + } +} diff --git a/composer.json b/composer.json index 90b6887..f1e5f01 100644 --- a/composer.json +++ b/composer.json @@ -10,10 +10,13 @@ "license": "MIT", "require": { "php": "^8.2", + "dragonmantank/cron-expression": "^3.4", "laravel/framework": "^12.0", "laravel/tinker": "^2.10.1", "livewire/flux": "^2.1.1", - "livewire/volt": "^1.7.0" + "livewire/volt": "^1.7.0", + "lorisleiva/cron-translator": "^0.4.6", + "yoeunes/toastr": "^3.1" }, "require-dev": { "fakerphp/faker": "^1.23", @@ -78,4 +81,4 @@ }, "minimum-stability": "stable", "prefer-stable": true -} \ No newline at end of file +} diff --git a/composer.lock b/composer.lock index dd7a632..59997ed 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "61eccc5dc89e08e92f1eea8940ff4dae", + "content-hash": "0e6fbc1b4cb99ff544ccd78faca75fd6", "packages": [ { "name": "brick/math", @@ -2221,6 +2221,62 @@ }, "time": "2025-08-06T15:40:50+00:00" }, + { + "name": "lorisleiva/cron-translator", + "version": "v0.4.6", + "source": { + "type": "git", + "url": "https://github.com/lorisleiva/cron-translator.git", + "reference": "082e3cd493de13bd5816bfdda484d07bb2326768" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/lorisleiva/cron-translator/zipball/082e3cd493de13bd5816bfdda484d07bb2326768", + "reference": "082e3cd493de13bd5816bfdda484d07bb2326768", + "shasum": "" + }, + "require": { + "php": "^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.5" + }, + "type": "library", + "autoload": { + "psr-4": { + "Lorisleiva\\CronTranslator\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Loris LEIVA", + "email": "loris.leiva@gmail.com", + "homepage": "https://lorisleiva.com" + } + ], + "description": "Makes CRON expressions human-readable", + "homepage": "https://github.com/lorisleiva/cron-translator", + "keywords": [ + "cron", + "expression", + "human" + ], + "support": { + "issues": "https://github.com/lorisleiva/cron-translator/issues", + "source": "https://github.com/lorisleiva/cron-translator/tree/v0.4.6" + }, + "funding": [ + { + "url": "https://github.com/lorisleiva", + "type": "github" + } + ], + "time": "2025-06-23T10:51:20+00:00" + }, { "name": "monolog/monolog", "version": "3.9.0", @@ -2725,6 +2781,294 @@ ], "time": "2025-05-08T08:14:37+00:00" }, + { + "name": "php-flasher/flasher", + "version": "v2.1.6", + "source": { + "type": "git", + "url": "https://github.com/php-flasher/flasher.git", + "reference": "054a209515d2eb1bb72467023d8614a29b5d2e60" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-flasher/flasher/zipball/054a209515d2eb1bb72467023d8614a29b5d2e60", + "reference": "054a209515d2eb1bb72467023d8614a29b5d2e60", + "shasum": "" + }, + "require": { + "php": ">=8.2" + }, + "type": "library", + "autoload": { + "files": [ + "functions.php", + "helpers.php" + ], + "psr-4": { + "Flasher\\Prime\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Younes ENNAJI", + "email": "younes.ennaji.pro@gmail.com", + "homepage": "https://www.linkedin.com/in/younes--ennaji/", + "role": "Developer" + } + ], + "description": "The foundational PHP library for PHPFlasher, enabling the creation of framework-agnostic flash notifications. Ideal for building custom integrations or for use in PHP projects.", + "homepage": "https://php-flasher.io", + "keywords": [ + "custom-integrations", + "flash-notifications", + "flasher-core", + "framework-agnostic", + "open-source", + "php" + ], + "support": { + "issues": "https://github.com/php-flasher/php-flasher/issues", + "source": "https://github.com/php-flasher/php-flasher" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/yoeunes", + "type": "custom" + }, + { + "url": "https://github.com/yoeunes", + "type": "github" + } + ], + "time": "2025-02-21T20:05:00+00:00" + }, + { + "name": "php-flasher/flasher-laravel", + "version": "v2.1.6", + "source": { + "type": "git", + "url": "https://github.com/php-flasher/flasher-laravel.git", + "reference": "7097ab207d602db59b241206048c9884aadc5c06" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-flasher/flasher-laravel/zipball/7097ab207d602db59b241206048c9884aadc5c06", + "reference": "7097ab207d602db59b241206048c9884aadc5c06", + "shasum": "" + }, + "require": { + "illuminate/support": "^11.0|^12.0", + "php": ">=8.2", + "php-flasher/flasher": "^2.1.6" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "Flasher": "Flasher\\Laravel\\Facade\\Flasher" + }, + "providers": [ + "Flasher\\Laravel\\FlasherServiceProvider" + ] + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "psr-4": { + "Flasher\\Laravel\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Younes ENNAJI", + "email": "younes.ennaji.pro@gmail.com", + "homepage": "https://www.linkedin.com/in/younes--ennaji/", + "role": "Developer" + } + ], + "description": "Seamlessly integrate flash notifications into your Laravel applications with PHPFlasher. Enhance user feedback and engagement with minimal setup.", + "homepage": "https://php-flasher.io", + "keywords": [ + "flash-notifications", + "laravel", + "open-source", + "php", + "phpflasher", + "user-feedback" + ], + "support": { + "issues": "https://github.com/php-flasher/php-flasher/issues", + "source": "https://github.com/php-flasher/php-flasher" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/yoeunes", + "type": "custom" + }, + { + "url": "https://github.com/yoeunes", + "type": "github" + } + ], + "time": "2025-02-21T20:05:00+00:00" + }, + { + "name": "php-flasher/flasher-toastr", + "version": "v2.1.6", + "source": { + "type": "git", + "url": "https://github.com/php-flasher/flasher-toastr.git", + "reference": "e9772b7d4e7a2780e41caf0e2f142e3c1670358f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-flasher/flasher-toastr/zipball/e9772b7d4e7a2780e41caf0e2f142e3c1670358f", + "reference": "e9772b7d4e7a2780e41caf0e2f142e3c1670358f", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "php-flasher/flasher": "^2.1.6" + }, + "type": "library", + "autoload": { + "files": [ + "functions.php", + "helpers.php" + ], + "psr-4": { + "Flasher\\Toastr\\Prime\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Younes ENNAJI", + "email": "younes.ennaji.pro@gmail.com", + "homepage": "https://www.linkedin.com/in/younes--ennaji/", + "role": "Developer" + } + ], + "description": "PHPFlasher Toastr - An extension for PHPFlasher to integrate Toastr notifications seamlessly in Laravel or Symfony. Enhances UX with elegant, responsive toast messages.", + "homepage": "https://php-flasher.io", + "keywords": [ + "customizable-alerts-php", + "flash-messages", + "interactive-web-notifications", + "laravel-notification", + "php-messaging-library", + "php-notification-system", + "php-user-interface", + "symfony-notification", + "user-engagement-php", + "user-feedback-tools", + "web-application-notifications" + ], + "support": { + "issues": "https://github.com/php-flasher/php-flasher/issues", + "source": "https://github.com/php-flasher/php-flasher" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/yoeunes", + "type": "custom" + }, + { + "url": "https://github.com/yoeunes", + "type": "github" + } + ], + "time": "2025-02-21T20:05:00+00:00" + }, + { + "name": "php-flasher/flasher-toastr-laravel", + "version": "v2.1.6", + "source": { + "type": "git", + "url": "https://github.com/php-flasher/flasher-toastr-laravel.git", + "reference": "db6c6d98405643236c47735b5352ee41f4e4691e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-flasher/flasher-toastr-laravel/zipball/db6c6d98405643236c47735b5352ee41f4e4691e", + "reference": "db6c6d98405643236c47735b5352ee41f4e4691e", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "php-flasher/flasher-laravel": "^2.1.6", + "php-flasher/flasher-toastr": "^2.1.6" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "Toastr": "Flasher\\Toastr\\Laravel\\Facade\\Toastr" + }, + "providers": [ + "Flasher\\Toastr\\Laravel\\FlasherToastrServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Flasher\\Toastr\\Laravel\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Younes ENNAJI", + "email": "younes.ennaji.pro@gmail.com", + "homepage": "https://www.linkedin.com/in/younes--ennaji/", + "role": "Developer" + } + ], + "description": "Leverage Toastr for stylish toast notifications in Laravel with PHPFlasher. Add Toastr's sleek notifications to your Laravel projects effortlessly.", + "homepage": "https://php-flasher.io", + "keywords": [ + "dynamic-notifications", + "flash-notifications", + "laravel", + "open-source", + "phpflasher", + "toastr", + "user-feedback" + ], + "support": { + "issues": "https://github.com/php-flasher/php-flasher/issues", + "source": "https://github.com/php-flasher/php-flasher" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/yoeunes", + "type": "custom" + }, + { + "url": "https://github.com/yoeunes", + "type": "github" + } + ], + "time": "2025-02-21T20:05:00+00:00" + }, { "name": "phpoption/phpoption", "version": "1.9.4", @@ -6236,6 +6580,67 @@ "source": "https://github.com/webmozarts/assert/tree/1.11.0" }, "time": "2022-06-03T18:03:27+00:00" + }, + { + "name": "yoeunes/toastr", + "version": "v3.1.1", + "source": { + "type": "git", + "url": "https://github.com/yoeunes/toastr.git", + "reference": "0e203a03c3144dcd72c913ee845970f118e65fa2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/yoeunes/toastr/zipball/0e203a03c3144dcd72c913ee845970f118e65fa2", + "reference": "0e203a03c3144dcd72c913ee845970f118e65fa2", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "php-flasher/flasher-toastr-laravel": "^2.1.6" + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Younes ENNAJI", + "email": "younes.ennaji.pro@gmail.com", + "homepage": "https://www.linkedin.com/in/younes--ennaji/", + "role": "Developer" + } + ], + "description": "toastr.js flush notifications for Laravel", + "homepage": "https://github.com/yoeunes/toastr", + "keywords": [ + "dynamic-notifications", + "flash-notifications", + "laravel", + "open-source", + "phpflasher", + "toastr", + "user-feedback" + ], + "support": { + "docs": "https://php-flasher.io", + "email": "younes.ennaji.pro@gmail.com", + "issues": "https://github.com/php-flasher/php-flasher/issues", + "source": "https://github.com/php-flasher/php-flasher" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/yoeunes", + "type": "custom" + }, + { + "url": "https://github.com/yoeunes", + "type": "github" + } + ], + "abandoned": "php-flasher/flasher-toastr-laravel", + "time": "2025-02-26T14:13:03+00:00" } ], "packages-dev": [ @@ -9535,12 +9940,12 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": true, "prefer-lowest": false, "platform": { "php": "^8.2" }, - "platform-dev": [], - "plugin-api-version": "2.2.0" + "platform-dev": {}, + "plugin-api-version": "2.6.0" } diff --git a/config/logging.php b/config/logging.php index 8d94292..2c583e8 100644 --- a/config/logging.php +++ b/config/logging.php @@ -59,7 +59,7 @@ return [ ], 'single' => [ - 'driver' => 'single', + 'driver' => 'daily', 'path' => storage_path('logs/laravel.log'), 'level' => env('LOG_LEVEL', 'debug'), 'replace_placeholders' => true, diff --git a/config/scheduler.php b/config/scheduler.php new file mode 100644 index 0000000..ceb76e8 --- /dev/null +++ b/config/scheduler.php @@ -0,0 +1,8 @@ + [ + 'server_url' => env('MATTERMOST_SERVER_URL', 'https://chat.example.com'), + 'access_token' => env('MATTERMOST_ACCESS_TOKEN', 'your_access_token'), + ] +]; diff --git a/database/migrations/2025_08_30_101757_create_bots_table.php b/database/migrations/2025_08_30_101757_create_bots_table.php new file mode 100644 index 0000000..d5da527 --- /dev/null +++ b/database/migrations/2025_08_30_101757_create_bots_table.php @@ -0,0 +1,32 @@ +id(); + $table->string('name'); + $table->string('class'); + $table->json('config')->nullable(); + $table->string('schedule')->default('* * * * *'); + $table->boolean('enabled')->default(true); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('bots'); + } +}; diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..5478cff --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,56 @@ +services: + laravel.test: + build: + context: './vendor/laravel/sail/runtimes/8.4' + dockerfile: Dockerfile + args: + WWWGROUP: '${WWWGROUP}' + image: 'sail-8.4/app' + extra_hosts: + - 'host.docker.internal:host-gateway' + ports: + - '${APP_PORT:-80}:80' + - '${VITE_PORT:-5173}:${VITE_PORT:-5173}' + environment: + WWWUSER: '${WWWUSER}' + LARAVEL_SAIL: 1 + XDEBUG_MODE: '${SAIL_XDEBUG_MODE:-off}' + XDEBUG_CONFIG: '${SAIL_XDEBUG_CONFIG:-client_host=host.docker.internal}' + IGNITION_LOCAL_SITES_PATH: '${PWD}' + volumes: + - '.:/var/www/html' + networks: + - sail + depends_on: + - mysql + mysql: + image: 'mysql/mysql-server:8.0' + ports: + - '${FORWARD_DB_PORT:-3306}:3306' + environment: + MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}' + MYSQL_ROOT_HOST: '%' + MYSQL_DATABASE: '${DB_DATABASE}' + MYSQL_USER: '${DB_USERNAME}' + MYSQL_PASSWORD: '${DB_PASSWORD}' + MYSQL_ALLOW_EMPTY_PASSWORD: 1 + MYSQL_EXTRA_OPTIONS: '${MYSQL_EXTRA_OPTIONS}' + volumes: + - 'sail-mysql:/var/lib/mysql' + - './vendor/laravel/sail/database/mysql/create-testing-database.sh:/docker-entrypoint-initdb.d/10-create-testing-database.sh' + networks: + - sail + healthcheck: + test: + - CMD + - mysqladmin + - ping + - '-p${DB_PASSWORD}' + retries: 3 + timeout: 5s +networks: + sail: + driver: bridge +volumes: + sail-mysql: + driver: local diff --git a/package-lock.json b/package-lock.json index 9004201..7b6e205 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "scheduler", + "name": "html", "lockfileVersion": 3, "requires": true, "packages": { @@ -10,6 +10,7 @@ "axios": "^1.7.4", "concurrently": "^9.0.1", "laravel-vite-plugin": "^2.0", + "prettier-plugin-blade": "^2.1.21", "tailwindcss": "^4.0.7", "vite": "^7.0.4" }, @@ -2053,6 +2054,34 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "license": "MIT" }, + "node_modules/prettier": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", + "license": "MIT", + "peer": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-plugin-blade": { + "version": "2.1.21", + "resolved": "https://registry.npmjs.org/prettier-plugin-blade/-/prettier-plugin-blade-2.1.21.tgz", + "integrity": "sha512-+BPBPvla/Ppr0MVrqMAO+FTwxpXUYo8zhQPIGC7psNuMbB24y84cGrJ4Uc02GHTQN0q8txeG4Y4MxyJWgOujyQ==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "prettier": ">=3" + } + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", diff --git a/package.json b/package.json index 963c417..70f18a5 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "axios": "^1.7.4", "concurrently": "^9.0.1", "laravel-vite-plugin": "^2.0", + "prettier-plugin-blade": "^2.1.21", "tailwindcss": "^4.0.7", "vite": "^7.0.4" }, diff --git a/phpunit.xml b/phpunit.xml index 61c031c..c09b5bc 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -22,8 +22,7 @@ - - + diff --git a/public/vendor/flasher/flasher-toastr.min.js b/public/vendor/flasher/flasher-toastr.min.js new file mode 100644 index 0000000..06f5c9b --- /dev/null +++ b/public/vendor/flasher/flasher-toastr.min.js @@ -0,0 +1 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("@flasher/flasher"),require("toastr")):"function"==typeof define&&define.amd?define(["@flasher/flasher","toastr"],t):(e="undefined"!=typeof globalThis?globalThis:e||self).toastr=t(e.flasher,e.toastr)}(this,(function(e,t){"use strict";class s{success(e,t,s){this.flash("success",e,t,s)}error(e,t,s){this.flash("error",e,t,s)}info(e,t,s){this.flash("info",e,t,s)}warning(e,t,s){this.flash("warning",e,t,s)}flash(e,t,s,r){if("object"==typeof e?(e=(r=e).type,t=r.message,s=r.title):"object"==typeof t?(t=(r=t).message,s=r.title):"object"==typeof s&&(s=(r=s).title),void 0===t)throw new Error("message option is required");const o={type:e,message:t,title:s||e,options:r||{},metadata:{plugin:""}};this.renderOptions(r||{}),this.renderEnvelopes([o])}}const r=new class extends s{renderEnvelopes(e){e.forEach((e=>{const{message:s,title:r,type:o,options:i}=e,n=t[o](s,r,i);n&&n.parent().attr("data-turbo-temporary","")}))}renderOptions(e){t.options=Object.assign({timeOut:e.timeOut||5e3,progressBar:e.progressBar||!0},e)}};return e.addPlugin("toastr",r),r})); diff --git a/public/vendor/flasher/flasher.min.css b/public/vendor/flasher/flasher.min.css new file mode 100644 index 0000000..188be96 --- /dev/null +++ b/public/vendor/flasher/flasher.min.css @@ -0,0 +1,2 @@ +:root{--background-color:#fff;--text-color:#4b5563;--dark-background-color:#0f172a;--dark-text-color:#fff;--success-color:#10b981;--info-color:#3b82f6;--warning-color:#f59e0b;--error-color:#ef4444;--success-color-light:#d4f7eb;--info-color-light:#d4e1f7;--warning-color-light:#fce8cf;--error-color-light:#f9d2d2}.fl-wrapper{position:fixed;-webkit-transition:all 1s ease-in-out;-moz-transition:all 1s ease-in-out;transition:all 1s ease-in-out;width:24em;z-index:10}@media only screen and (width <= 480px){.fl-wrapper{left:5%;right:5%;width:90%}}.fl-wrapper[data-position^=top-]{top:.5em}.fl-wrapper[data-position^=bottom-]{bottom:.5em}.fl-wrapper[data-position$=-right]{right:.5em}.fl-wrapper[data-position$=-right] .fl-container{-webkit-transform:translateX(110%);-moz-transform:translateX(110%);-ms-transform:translateX(110%);transform:translateX(110%)}.fl-wrapper[data-position$=-left]{left:.5em}.fl-wrapper[data-position$=-left] .fl-container{-webkit-transform:translateX(-110%);-moz-transform:translateX(-110%);-ms-transform:translateX(-110%);transform:translateX(-110%)}.fl-wrapper[data-position$=-center]{left:50%;-webkit-transform:translateX(-50%);-moz-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%)}.fl-wrapper[data-position=top-center] .fl-container{-webkit-transform:translateY(-100vh);-moz-transform:translateY(-100vh);-ms-transform:translateY(-100vh);transform:translateY(-100vh)}.fl-wrapper[data-position=bottom-center] .fl-container{-webkit-transform:translateY(100vh);-moz-transform:translateY(100vh);-ms-transform:translateY(100vh);transform:translateY(100vh)}.fl-container{color:var(--text-color);opacity:0;-webkit-transform:translateY(-20px);-moz-transform:translateY(-20px);-ms-transform:translateY(-20px);transform:translateY(-20px);-webkit-transition:all .5s ease-in-out;-moz-transition:all .5s ease-in-out;transition:all .5s ease-in-out}.fl-container.fl-show{opacity:1;-webkit-transform:translate(0)!important;-moz-transform:translate(0)!important;-ms-transform:translate(0)!important;transform:translate(0)!important}.fl-container.fl-rtl{direction:rtl}.fl-icon{border-radius:50%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;color:#fff;display:inline-block;height:1em;margin:0;min-height:1em;min-width:1em;position:relative;-webkit-transition:all 1s;-moz-transition:all 1s;transition:all 1s;width:1em}.fl-icon:after,.fl-icon:before{border-width:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;content:"";position:absolute;-webkit-transition:all 1s;-moz-transition:all 1s;transition:all 1s}.fl-success .fl-icon:after,.fl-success .fl-icon:before{background-color:currentcolor;border-radius:.1em;height:.6em;left:.35em;top:.6em;-webkit-transform:rotate(-135deg);-moz-transform:rotate(-135deg);-ms-transform:rotate(-135deg);transform:rotate(-135deg);-webkit-transform-origin:.08em .08em;-moz-transform-origin:.08em .08em;-ms-transform-origin:.08em .08em;transform-origin:.08em .08em;width:.16em}.fl-success .fl-icon:after{height:.16em;width:.4em}.fl-info .fl-icon:after,.fl-info .fl-icon:before{background-color:currentcolor;border-radius:.03em;left:50%;-webkit-transform:translateX(-50%);-moz-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);width:.15em}.fl-info .fl-icon:before{height:.38em;top:.4em}.fl-info .fl-icon:after{-webkit-box-shadow:-.06em .19em,-.06em .44em,.06em .44em;box-shadow:-.06em .19em,-.06em .44em,.06em .44em;height:.13em;top:.21em}.fl-warning .fl-icon:after,.fl-warning .fl-icon:before{background-color:currentcolor;border-radius:.03em;left:50%;-webkit-transform:translateX(-50%);-moz-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);width:.15em}.fl-warning .fl-icon:before{height:.38em;top:.21em}.fl-warning .fl-icon:after{height:.13em;top:.65em}.fl-error .fl-icon:after,.fl-error .fl-icon:before{background-color:currentcolor;border-radius:.1em;height:.7em;left:50%;top:50%;-webkit-transform:translate(-50%,-50%) rotate(-135deg);-moz-transform:translate(-50%,-50%) rotate(-135deg);-ms-transform:translate(-50%,-50%) rotate(-135deg);transform:translate(-50%,-50%) rotate(-135deg);width:.16em}.fl-error .fl-icon:after{-webkit-transform:translate(-50%,-50%) rotate(-45deg);-moz-transform:translate(-50%,-50%) rotate(-45deg);-ms-transform:translate(-50%,-50%) rotate(-45deg);transform:translate(-50%,-50%) rotate(-45deg)}.fl-success .fl-icon{background-color:var(--success-color)}.fl-info .fl-icon{background-color:var(--info-color)}.fl-warning .fl-icon{background-color:var(--warning-color)}.fl-error .fl-icon{background-color:var(--error-color)}.fl-progress-bar{bottom:0;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:flex;height:.125em;left:0;position:absolute;right:0}.fl-success .fl-progress-bar{background-color:var(--success-color-light)}.fl-success .fl-progress-bar .fl-progress{background-color:var(--success-color)}.fl-info .fl-progress-bar{background-color:var(--info-color-light)}.fl-info .fl-progress-bar .fl-progress{background-color:var(--info-color)}.fl-warning .fl-progress-bar{background-color:var(--warning-color-light)}.fl-warning .fl-progress-bar .fl-progress{background-color:var(--warning-color)}.fl-error .fl-progress-bar{background-color:var(--error-color-light)}.fl-error .fl-progress-bar .fl-progress{background-color:var(--error-color)} +body.fl-dark .fl-flasher,html.fl-dark .fl-flasher{--background-color:var(--dark-background-color);--text-color:var(--dark-text-color)}.fl-flasher{background-color:var(--background-color);border-bottom:none;-webkit-box-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -2px rgba(0,0,0,.05);box-shadow:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -2px rgba(0,0,0,.05);color:var(--text-color);line-height:1.5;margin:.75em 0;padding:.75em;position:relative;word-break:break-word}.fl-flasher.fl-rtl{border-radius:0 .375em .375em 0}.fl-flasher:not(.fl-rtl){border-radius:.375em 0 0 .375em}.fl-flasher .fl-content{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;align-items:center;display:-webkit-box;display:-webkit-flex;display:-moz-box;display:flex}.fl-flasher .fl-icon{font-size:2.5em}.fl-flasher .fl-message,.fl-flasher .fl-title{display:block;line-height:1.25em;margin-left:1em;margin-right:1em}.fl-flasher .fl-title{font-size:1em;font-weight:700}.fl-flasher .fl-message{font-size:.875em;margin-top:.25em}.fl-flasher .fl-close{-webkit-box-align:center;-webkit-align-items:center;-moz-box-align:center;align-items:center;background-color:transparent;border:none;color:#a8aaab;cursor:pointer;display:-webkit-inline-box;display:-webkit-inline-flex;display:-moz-inline-box;display:inline-flex;font-size:25px;-webkit-box-pack:center;-webkit-justify-content:center;-moz-box-pack:center;justify-content:center;line-height:0;margin:-.5rem;padding:.5rem;position:absolute;right:.5rem;top:1rem;-webkit-transition:color .3s ease,-webkit-transform .3s ease;transition:color .3s ease,-webkit-transform .3s ease;-moz-transition:color .3s ease,transform .3s ease,-moz-transform .3s ease;transition:color .3s ease,transform .3s ease;transition:color .3s ease,transform .3s ease,-webkit-transform .3s ease,-moz-transform .3s ease}.fl-flasher .fl-close:hover{color:#8e9192;-webkit-transform:scale(1.1);-moz-transform:scale(1.1);-ms-transform:scale(1.1);transform:scale(1.1)}.fl-flasher.fl-rtl .fl-close{left:.5rem;right:auto}.fl-flasher.fl-success{border-left:.8em solid var(--success-color)}.fl-flasher.fl-success.fl-rtl{border-left:none;border-right:.8em solid var(--success-color)}.fl-flasher.fl-success:not(.fl-rtl){border-left:.8em solid var(--success-color);border-right:none}.fl-flasher.fl-success .fl-title{color:var(--success-color)}.fl-flasher.fl-info{border-left:.8em solid var(--info-color)}.fl-flasher.fl-info.fl-rtl{border-left:none;border-right:.8em solid var(--info-color)}.fl-flasher.fl-info:not(.fl-rtl){border-left:.8em solid var(--info-color);border-right:none}.fl-flasher.fl-info .fl-title{color:var(--info-color)}.fl-flasher.fl-warning{border-left:.8em solid var(--warning-color)}.fl-flasher.fl-warning.fl-rtl{border-left:none;border-right:.8em solid var(--warning-color)}.fl-flasher.fl-warning:not(.fl-rtl){border-left:.8em solid var(--warning-color);border-right:none}.fl-flasher.fl-warning .fl-title{color:var(--warning-color)}.fl-flasher.fl-error{border-left:.8em solid var(--error-color)}.fl-flasher.fl-error.fl-rtl{border-left:none;border-right:.8em solid var(--error-color)}.fl-flasher.fl-error:not(.fl-rtl){border-left:.8em solid var(--error-color);border-right:none}.fl-flasher.fl-error .fl-title{color:var(--error-color)} \ No newline at end of file diff --git a/public/vendor/flasher/flasher.min.js b/public/vendor/flasher/flasher.min.js new file mode 100644 index 0000000..2804f95 --- /dev/null +++ b/public/vendor/flasher/flasher.min.js @@ -0,0 +1 @@ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).flasher=t()}(this,(function(){"use strict";function e(e,t,s,n){return new(s||(s=Promise))((function(o,i){function r(e){try{a(n.next(e))}catch(e){i(e)}}function l(e){try{a(n.throw(e))}catch(e){i(e)}}function a(e){var t;e.done?o(e.value):(t=e.value,t instanceof s?t:new s((function(e){e(t)}))).then(r,l)}a((n=n.apply(e,t||[])).next())}))}"function"==typeof SuppressedError&&SuppressedError;class t{success(e,t,s){this.flash("success",e,t,s)}error(e,t,s){this.flash("error",e,t,s)}info(e,t,s){this.flash("info",e,t,s)}warning(e,t,s){this.flash("warning",e,t,s)}flash(e,t,s,n){if("object"==typeof e?(e=(n=e).type,t=n.message,s=n.title):"object"==typeof t?(t=(n=t).message,s=n.title):"object"==typeof s&&(s=(n=s).title),void 0===t)throw new Error("message option is required");const o={type:e,message:t,title:s||e,options:n||{},metadata:{plugin:""}};this.renderOptions(n||{}),this.renderEnvelopes([o])}}class s extends t{constructor(e){super(),this.options={timeout:null,timeouts:{success:5e3,info:5e3,error:5e3,warning:5e3},fps:30,position:"top-right",direction:"top",rtl:!1,style:{},escapeHtml:!1},this.theme=e}renderEnvelopes(e){const t=()=>e.forEach((e=>{var t,s,n,o;const i=null!==(s=null!==(t=this.options.timeout)&&void 0!==t?t:this.options.timeouts[e.type])&&void 0!==s?s:5e3,r=Object.assign(Object.assign(Object.assign({},this.options),e.options),{timeout:null!==(n=e.options.timeout)&&void 0!==n?n:i,escapeHtml:null!==(o=e.options.escapeHtml)&&void 0!==o?o:this.options.escapeHtml});this.addToContainer(this.createContainer(r),e,r)}));"loading"===document.readyState?document.addEventListener("DOMContentLoaded",t):t()}renderOptions(e){this.options=Object.assign(Object.assign({},this.options),e)}createContainer(e){let t=document.querySelector(`.fl-wrapper[data-position="${e.position}"]`);return t||(t=document.createElement("div"),t.className="fl-wrapper",t.dataset.position=e.position,Object.entries(e.style).forEach((([e,s])=>t.style.setProperty(e,s))),document.body.appendChild(t)),t.dataset.turboTemporary="",t}addToContainer(e,t,s){var n;s.escapeHtml&&(t.title=this.escapeHtml(t.title),t.message=this.escapeHtml(t.message));const o=this.stringToHTML(this.theme.render(t));o.classList.add(...("fl-container"+(s.rtl?" fl-rtl":"")).split(" ")),"bottom"===s.direction?e.append(o):e.prepend(o),requestAnimationFrame((()=>o.classList.add("fl-show"))),null===(n=o.querySelector(".fl-close"))||void 0===n||n.addEventListener("click",(e=>{e.stopPropagation(),this.removeNotification(o)})),this.addProgressBar(o,s)}addProgressBar(e,{timeout:t,fps:s}){if(t<=0||s<=0)return;const n=e.querySelector(".fl-progress-bar");if(!n)return;const o=document.createElement("span");o.classList.add("fl-progress"),n.append(o);const i=1e3/s;let r=0;const l=()=>{r+=1;const s=100*(1-i*(r/t));o.style.width=`${s}%`,s<=0&&(clearInterval(a),this.removeNotification(e))};let a=window.setInterval(l,i);e.addEventListener("mouseout",(()=>a=window.setInterval(l,i))),e.addEventListener("mouseover",(()=>clearInterval(a)))}removeNotification(e){e.classList.remove("fl-show"),e.ontransitionend=()=>{var t,s;!(null===(t=e.parentElement)||void 0===t?void 0:t.hasChildNodes())&&(null===(s=e.parentElement)||void 0===s||s.remove()),e.remove()}}stringToHTML(e){const t=document.createElement("template");return t.innerHTML=e.trim(),t.content.firstElementChild}escapeHtml(e){return null==e?"":e.replace(/[&<>"'`=\/]/g,(e=>({"&":"&","<":"<",">":">",'"':""","'":"'","`":"`","=":"=","/":"/"}[e])))}}const n=new class extends t{constructor(){super(...arguments),this.defaultPlugin="flasher",this.plugins=new Map,this.themes=new Map}render(t){return e(this,void 0,void 0,(function*(){const e=this.resolveResponse(t);yield this.addAssets([{urls:e.styles,nonce:e.context.csp_style_nonce,type:"style"},{urls:e.scripts,nonce:e.context.csp_script_nonce,type:"script"}]),this.renderOptions(e.options),this.renderEnvelopes(e.envelopes)}))}renderEnvelopes(e){const t={};e.forEach((e=>{const s=this.resolvePluginAlias(e.metadata.plugin);t[s]=t[s]||[],t[s].push(e)})),Object.entries(t).forEach((([e,t])=>{this.use(e).renderEnvelopes(t)}))}renderOptions(e){Object.entries(e).forEach((([e,t])=>{this.use(e).renderOptions(t)}))}addPlugin(e,t){this.plugins.set(e,t)}addTheme(e,t){this.themes.set(e,t)}use(e){e=this.resolvePluginAlias(e),this.resolvePlugin(e);const t=this.plugins.get(e);if(!t)throw new Error(`Unable to resolve "${e}" plugin, did you forget to register it?`);return t}create(e){return this.use(e)}resolveResponse(e){const t=Object.assign({envelopes:[],options:{},scripts:[],styles:[],context:{}},e);return Object.entries(t.options).forEach((([e,s])=>{t.options[e]=this.resolveOptions(s)})),t.context.csp_style_nonce=t.context.csp_style_nonce||"",t.context.csp_script_nonce=t.context.csp_script_nonce||"",t.envelopes.forEach((s=>{s.metadata=s.metadata||{},s.metadata.plugin=this.resolvePluginAlias(s.metadata.plugin),this.addThemeStyles(t,s.metadata.plugin),s.options=this.resolveOptions(s.options),s.context=e.context})),t}resolveOptions(e){return Object.entries(e).forEach((([t,s])=>{e[t]=this.resolveFunction(s)})),e}resolveFunction(e){var t,s;if("string"!=typeof e)return e;const n=e.match(/^function\s*(\w*)\s*\(([^)]*)\)\s*\{([\s\S]*)\}$/)||e.match(/^\s*(\(([^)]*)\)|[^=]+)\s*=>\s*([\s\S]+)$/);if(!n)return e;const o=null!==(s=null===(t=n[2])||void 0===t?void 0:t.split(",").map((e=>e.trim())))&&void 0!==s?s:[];let i=n[3].trim();i.startsWith("{")||(i=`{ return ${i}; }`);try{return new Function(...o,i)}catch(t){return console.error("Error converting string to function:",t),e}}resolvePlugin(e){if(this.plugins.get(e)||!e.includes("theme."))return;const t=this.themes.get(e.replace("theme.",""));t&&this.addPlugin(e,new s(t))}resolvePluginAlias(e){return"flasher"===(e=e||this.defaultPlugin)?"theme.flasher":e}addAssets(t){return e(this,void 0,void 0,(function*(){for(const{urls:e,nonce:s,type:n}of t)for(const t of e)yield this.loadAsset(t,s,n)}))}loadAsset(t,s,n){return e(this,void 0,void 0,(function*(){if(document.querySelector(`${"style"===n?"link":"script"}[src="${t}"]`))return;const e=document.createElement("style"===n?"link":"script");return"style"===n?(e.rel="stylesheet",e.href=t):(e.type="text/javascript",e.src=t),s&&e.setAttribute("nonce",s),document.head.appendChild(e),new Promise(((s,n)=>{e.onload=()=>s(),e.onerror=()=>n(new Error(`Failed to load ${t}`))}))}))}addThemeStyles(e,t){var s;if("flasher"!==t&&!t.includes("theme."))return;t=t.replace("theme.","");const n=(null===(s=this.themes.get(t))||void 0===s?void 0:s.styles)||[];e.styles=Array.from(new Set([...e.styles,...n]))}};return n.addTheme("flasher",{render:e=>{const{type:t,title:s,message:n}=e,o="error"===t||"warning"===t;return`\n
\n
\n
\n
\n ${s}\n ${n}\n
\n \n
\n \n
`}}),n})); diff --git a/public/vendor/flasher/jquery.min.js b/public/vendor/flasher/jquery.min.js new file mode 100644 index 0000000..7f37b5d --- /dev/null +++ b/public/vendor/flasher/jquery.min.js @@ -0,0 +1,2 @@ +/*! jQuery v3.7.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(ie,e){"use strict";var oe=[],r=Object.getPrototypeOf,ae=oe.slice,g=oe.flat?function(e){return oe.flat.call(e)}:function(e){return oe.concat.apply([],e)},s=oe.push,se=oe.indexOf,n={},i=n.toString,ue=n.hasOwnProperty,o=ue.toString,a=o.call(Object),le={},v=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},y=function(e){return null!=e&&e===e.window},C=ie.document,u={type:!0,src:!0,nonce:!0,noModule:!0};function m(e,t,n){var r,i,o=(n=n||C).createElement("script");if(o.text=e,t)for(r in u)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[i.call(e)]||"object":typeof e}var t="3.7.1",l=/HTML$/i,ce=function(e,t){return new ce.fn.init(e,t)};function c(e){var t=!!e&&"length"in e&&e.length,n=x(e);return!v(e)&&!y(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+ge+")"+ge+"*"),x=new RegExp(ge+"|>"),j=new RegExp(g),A=new RegExp("^"+t+"$"),D={ID:new RegExp("^#("+t+")"),CLASS:new RegExp("^\\.("+t+")"),TAG:new RegExp("^("+t+"|[*])"),ATTR:new RegExp("^"+p),PSEUDO:new RegExp("^"+g),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+ge+"*(even|odd|(([+-]|)(\\d*)n|)"+ge+"*(?:([+-]|)"+ge+"*(\\d+)|))"+ge+"*\\)|)","i"),bool:new RegExp("^(?:"+f+")$","i"),needsContext:new RegExp("^"+ge+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+ge+"*((?:-\\d)?\\d*)"+ge+"*\\)|)(?=[^-]|$)","i")},N=/^(?:input|select|textarea|button)$/i,q=/^h\d$/i,L=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,H=/[+~]/,O=new RegExp("\\\\[\\da-fA-F]{1,6}"+ge+"?|\\\\([^\\r\\n\\f])","g"),P=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},M=function(){V()},R=J(function(e){return!0===e.disabled&&fe(e,"fieldset")},{dir:"parentNode",next:"legend"});try{k.apply(oe=ae.call(ye.childNodes),ye.childNodes),oe[ye.childNodes.length].nodeType}catch(e){k={apply:function(e,t){me.apply(e,ae.call(t))},call:function(e){me.apply(e,ae.call(arguments,1))}}}function I(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(V(e),e=e||T,C)){if(11!==p&&(u=L.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return k.call(n,a),n}else if(f&&(a=f.getElementById(i))&&I.contains(e,a)&&a.id===i)return k.call(n,a),n}else{if(u[2])return k.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&e.getElementsByClassName)return k.apply(n,e.getElementsByClassName(i)),n}if(!(h[t+" "]||d&&d.test(t))){if(c=t,f=e,1===p&&(x.test(t)||m.test(t))){(f=H.test(t)&&U(e.parentNode)||e)==e&&le.scope||((s=e.getAttribute("id"))?s=ce.escapeSelector(s):e.setAttribute("id",s=S)),o=(l=Y(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+Q(l[o]);c=l.join(",")}try{return k.apply(n,f.querySelectorAll(c)),n}catch(e){h(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return re(t.replace(ve,"$1"),e,n,r)}function W(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function F(e){return e[S]=!0,e}function $(e){var t=T.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function B(t){return function(e){return fe(e,"input")&&e.type===t}}function _(t){return function(e){return(fe(e,"input")||fe(e,"button"))&&e.type===t}}function z(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&R(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function X(a){return F(function(o){return o=+o,F(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function U(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}function V(e){var t,n=e?e.ownerDocument||e:ye;return n!=T&&9===n.nodeType&&n.documentElement&&(r=(T=n).documentElement,C=!ce.isXMLDoc(T),i=r.matches||r.webkitMatchesSelector||r.msMatchesSelector,r.msMatchesSelector&&ye!=T&&(t=T.defaultView)&&t.top!==t&&t.addEventListener("unload",M),le.getById=$(function(e){return r.appendChild(e).id=ce.expando,!T.getElementsByName||!T.getElementsByName(ce.expando).length}),le.disconnectedMatch=$(function(e){return i.call(e,"*")}),le.scope=$(function(){return T.querySelectorAll(":scope")}),le.cssHas=$(function(){try{return T.querySelector(":has(*,:jqfake)"),!1}catch(e){return!0}}),le.getById?(b.filter.ID=function(e){var t=e.replace(O,P);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(O,P);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):t.querySelectorAll(e)},b.find.CLASS=function(e,t){if("undefined"!=typeof t.getElementsByClassName&&C)return t.getElementsByClassName(e)},d=[],$(function(e){var t;r.appendChild(e).innerHTML="",e.querySelectorAll("[selected]").length||d.push("\\["+ge+"*(?:value|"+f+")"),e.querySelectorAll("[id~="+S+"-]").length||d.push("~="),e.querySelectorAll("a#"+S+"+*").length||d.push(".#.+[+~]"),e.querySelectorAll(":checked").length||d.push(":checked"),(t=T.createElement("input")).setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),r.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&d.push(":enabled",":disabled"),(t=T.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||d.push("\\["+ge+"*name"+ge+"*="+ge+"*(?:''|\"\")")}),le.cssHas||d.push(":has"),d=d.length&&new RegExp(d.join("|")),l=function(e,t){if(e===t)return a=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!le.sortDetached&&t.compareDocumentPosition(e)===n?e===T||e.ownerDocument==ye&&I.contains(ye,e)?-1:t===T||t.ownerDocument==ye&&I.contains(ye,t)?1:o?se.call(o,e)-se.call(o,t):0:4&n?-1:1)}),T}for(e in I.matches=function(e,t){return I(e,null,null,t)},I.matchesSelector=function(e,t){if(V(e),C&&!h[t+" "]&&(!d||!d.test(t)))try{var n=i.call(e,t);if(n||le.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){h(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(O,P),e[3]=(e[3]||e[4]||e[5]||"").replace(O,P),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||I.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&I.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return D.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&j.test(n)&&(t=Y(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(O,P).toLowerCase();return"*"===e?function(){return!0}:function(e){return fe(e,t)}},CLASS:function(e){var t=s[e+" "];return t||(t=new RegExp("(^|"+ge+")"+e+"("+ge+"|$)"))&&s(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=I.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function T(e,n,r){return v(n)?ce.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?ce.grep(e,function(e){return e===n!==r}):"string"!=typeof n?ce.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(ce.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||k,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:S.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof ce?t[0]:t,ce.merge(this,ce.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:C,!0)),w.test(r[1])&&ce.isPlainObject(t))for(r in t)v(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=C.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):v(e)?void 0!==n.ready?n.ready(e):e(ce):ce.makeArray(e,this)}).prototype=ce.fn,k=ce(C);var E=/^(?:parents|prev(?:Until|All))/,j={children:!0,contents:!0,next:!0,prev:!0};function A(e,t){while((e=e[t])&&1!==e.nodeType);return e}ce.fn.extend({has:function(e){var t=ce(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,Ce=/^$|^module$|\/(?:java|ecma)script/i;xe=C.createDocumentFragment().appendChild(C.createElement("div")),(be=C.createElement("input")).setAttribute("type","radio"),be.setAttribute("checked","checked"),be.setAttribute("name","t"),xe.appendChild(be),le.checkClone=xe.cloneNode(!0).cloneNode(!0).lastChild.checked,xe.innerHTML="",le.noCloneChecked=!!xe.cloneNode(!0).lastChild.defaultValue,xe.innerHTML="",le.option=!!xe.lastChild;var ke={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};function Se(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&fe(e,t)?ce.merge([e],n):n}function Ee(e,t){for(var n=0,r=e.length;n",""]);var je=/<|&#?\w+;/;function Ae(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function Re(e,t){return fe(e,"table")&&fe(11!==t.nodeType?t:t.firstChild,"tr")&&ce(e).children("tbody")[0]||e}function Ie(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function We(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Fe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(_.hasData(e)&&(s=_.get(e).events))for(i in _.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),C.head.appendChild(r[0])},abort:function(){i&&i()}}});var Jt,Kt=[],Zt=/(=)\?(?=&|$)|\?\?/;ce.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Kt.pop()||ce.expando+"_"+jt.guid++;return this[e]=!0,e}}),ce.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Zt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Zt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=v(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Zt,"$1"+r):!1!==e.jsonp&&(e.url+=(At.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||ce.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=ie[r],ie[r]=function(){o=arguments},n.always(function(){void 0===i?ce(ie).removeProp(r):ie[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Kt.push(r)),o&&v(i)&&i(o[0]),o=i=void 0}),"script"}),le.createHTMLDocument=((Jt=C.implementation.createHTMLDocument("").body).innerHTML="
",2===Jt.childNodes.length),ce.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(le.createHTMLDocument?((r=(t=C.implementation.createHTMLDocument("")).createElement("base")).href=C.location.href,t.head.appendChild(r)):t=C),o=!n&&[],(i=w.exec(e))?[t.createElement(i[1])]:(i=Ae([e],t,o),o&&o.length&&ce(o).remove(),ce.merge([],i.childNodes)));var r,i,o},ce.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(ce.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},ce.expr.pseudos.animated=function(t){return ce.grep(ce.timers,function(e){return t===e.elem}).length},ce.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=ce.css(e,"position"),c=ce(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=ce.css(e,"top"),u=ce.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),v(t)&&(t=t.call(e,n,ce.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},ce.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){ce.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===ce.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===ce.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=ce(e).offset()).top+=ce.css(e,"borderTopWidth",!0),i.left+=ce.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-ce.css(r,"marginTop",!0),left:t.left-i.left-ce.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===ce.css(e,"position"))e=e.offsetParent;return e||J})}}),ce.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;ce.fn[t]=function(e){return M(this,function(e,t,n){var r;if(y(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),ce.each(["top","left"],function(e,n){ce.cssHooks[n]=Ye(le.pixelPosition,function(e,t){if(t)return t=Ge(e,n),_e.test(t)?ce(e).position()[n]+"px":t})}),ce.each({Height:"height",Width:"width"},function(a,s){ce.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){ce.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return M(this,function(e,t,n){var r;return y(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?ce.css(e,t,i):ce.style(e,t,n,i)},s,n?e:void 0,n)}})}),ce.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){ce.fn[t]=function(e){return this.on(t,e)}}),ce.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.on("mouseenter",e).on("mouseleave",t||e)}}),ce.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){ce.fn[n]=function(e,t){return 0div{position:relative;pointer-events:auto;overflow:hidden;margin:0 0 6px;padding:15px 15px 15px 50px;width:300px;-moz-border-radius:3px;-webkit-border-radius:3px;border-radius:3px;background-position:15px center;background-repeat:no-repeat;-moz-box-shadow:0 0 12px #999;-webkit-box-shadow:0 0 12px #999;box-shadow:0 0 12px #999;color:#FFF;opacity:.8;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=80);filter:alpha(opacity=80)}#toast-container>div.rtl{direction:rtl;padding:15px 50px 15px 15px;background-position:right 15px center}#toast-container>div:hover{-moz-box-shadow:0 0 12px #000;-webkit-box-shadow:0 0 12px #000;box-shadow:0 0 12px #000;opacity:1;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=100);filter:alpha(opacity=100);cursor:pointer}#toast-container>.toast-info{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=)!important}#toast-container>.toast-error{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=)!important}#toast-container>.toast-success{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==)!important}#toast-container>.toast-warning{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=)!important}#toast-container.toast-bottom-center>div,#toast-container.toast-top-center>div{width:300px;margin-left:auto;margin-right:auto}#toast-container.toast-bottom-full-width>div,#toast-container.toast-top-full-width>div{width:96%;margin-left:auto;margin-right:auto}.toast{background-color:#030303}.toast-success{background-color:#51A351}.toast-error{background-color:#BD362F}.toast-info{background-color:#2F96B4}.toast-warning{background-color:#F89406}.toast-progress{position:absolute;left:0;bottom:0;height:4px;background-color:#000;opacity:.4;-ms-filter:progid:DXImageTransform.Microsoft.Alpha(Opacity=40);filter:alpha(opacity=40)}@media all and (max-width:240px){#toast-container>div{padding:8px 8px 8px 50px;width:11em}#toast-container>div.rtl{padding:8px 50px 8px 8px}#toast-container .toast-close-button{right:-.2em;top:-.2em}#toast-container .rtl .toast-close-button{left:-.2em;right:.2em}}@media all and (min-width:241px) and (max-width:480px){#toast-container>div{padding:8px 8px 8px 50px;width:18em}#toast-container>div.rtl{padding:8px 50px 8px 8px}#toast-container .toast-close-button{right:-.2em;top:-.2em}#toast-container .rtl .toast-close-button{left:-.2em;right:.2em}}@media all and (min-width:481px) and (max-width:768px){#toast-container>div{padding:15px 15px 15px 50px;width:25em}#toast-container>div.rtl{padding:15px 50px 15px 15px}} \ No newline at end of file diff --git a/public/vendor/flasher/toastr.min.js b/public/vendor/flasher/toastr.min.js new file mode 100644 index 0000000..06e4814 --- /dev/null +++ b/public/vendor/flasher/toastr.min.js @@ -0,0 +1,2 @@ +!function(e){e(["jquery"],function(e){return function(){function t(e,t,n){return g({type:O.error,iconClass:m().iconClasses.error,message:e,optionsOverride:n,title:t})}function n(t,n){return t||(t=m()),v=e("#"+t.containerId),v.length?v:(n&&(v=d(t)),v)}function o(e,t,n){return g({type:O.info,iconClass:m().iconClasses.info,message:e,optionsOverride:n,title:t})}function s(e){C=e}function i(e,t,n){return g({type:O.success,iconClass:m().iconClasses.success,message:e,optionsOverride:n,title:t})}function a(e,t,n){return g({type:O.warning,iconClass:m().iconClasses.warning,message:e,optionsOverride:n,title:t})}function r(e,t){var o=m();v||n(o),u(e,o,t)||l(o)}function c(t){var o=m();return v||n(o),t&&0===e(":focus",t).length?void h(t):void(v.children().length&&v.remove())}function l(t){for(var n=v.children(),o=n.length-1;o>=0;o--)u(e(n[o]),t)}function u(t,n,o){var s=!(!o||!o.force)&&o.force;return!(!t||!s&&0!==e(":focus",t).length)&&(t[n.hideMethod]({duration:n.hideDuration,easing:n.hideEasing,complete:function(){h(t)}}),!0)}function d(t){return v=e("
").attr("id",t.containerId).addClass(t.positionClass),v.appendTo(e(t.target)),v}function p(){return{tapToDismiss:!0,toastClass:"toast",containerId:"toast-container",debug:!1,showMethod:"fadeIn",showDuration:300,showEasing:"swing",onShown:void 0,hideMethod:"fadeOut",hideDuration:1e3,hideEasing:"swing",onHidden:void 0,closeMethod:!1,closeDuration:!1,closeEasing:!1,closeOnHover:!0,extendedTimeOut:1e3,iconClasses:{error:"toast-error",info:"toast-info",success:"toast-success",warning:"toast-warning"},iconClass:"toast-info",positionClass:"toast-top-right",timeOut:5e3,titleClass:"toast-title",messageClass:"toast-message",escapeHtml:!1,target:"body",closeHtml:'',closeClass:"toast-close-button",newestOnTop:!0,preventDuplicates:!1,progressBar:!1,progressClass:"toast-progress",rtl:!1}}function f(e){C&&C(e)}function g(t){function o(e){return null==e&&(e=""),e.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(//g,">")}function s(){c(),u(),d(),p(),g(),C(),l(),i()}function i(){var e="";switch(t.iconClass){case"toast-success":case"toast-info":e="polite";break;default:e="assertive"}I.attr("aria-live",e)}function a(){E.closeOnHover&&I.hover(H,D),!E.onclick&&E.tapToDismiss&&I.click(b),E.closeButton&&j&&j.click(function(e){e.stopPropagation?e.stopPropagation():void 0!==e.cancelBubble&&e.cancelBubble!==!0&&(e.cancelBubble=!0),E.onCloseClick&&E.onCloseClick(e),b(!0)}),E.onclick&&I.click(function(e){E.onclick(e),b()})}function r(){I.hide(),I[E.showMethod]({duration:E.showDuration,easing:E.showEasing,complete:E.onShown}),E.timeOut>0&&(k=setTimeout(b,E.timeOut),F.maxHideTime=parseFloat(E.timeOut),F.hideEta=(new Date).getTime()+F.maxHideTime,E.progressBar&&(F.intervalId=setInterval(x,10)))}function c(){t.iconClass&&I.addClass(E.toastClass).addClass(y)}function l(){E.newestOnTop?v.prepend(I):v.append(I)}function u(){if(t.title){var e=t.title;E.escapeHtml&&(e=o(t.title)),M.append(e).addClass(E.titleClass),I.append(M)}}function d(){if(t.message){var e=t.message;E.escapeHtml&&(e=o(t.message)),B.append(e).addClass(E.messageClass),I.append(B)}}function p(){E.closeButton&&(j.addClass(E.closeClass).attr("role","button"),I.prepend(j))}function g(){E.progressBar&&(q.addClass(E.progressClass),I.prepend(q))}function C(){E.rtl&&I.addClass("rtl")}function O(e,t){if(e.preventDuplicates){if(t.message===w)return!0;w=t.message}return!1}function b(t){var n=t&&E.closeMethod!==!1?E.closeMethod:E.hideMethod,o=t&&E.closeDuration!==!1?E.closeDuration:E.hideDuration,s=t&&E.closeEasing!==!1?E.closeEasing:E.hideEasing;if(!e(":focus",I).length||t)return clearTimeout(F.intervalId),I[n]({duration:o,easing:s,complete:function(){h(I),clearTimeout(k),E.onHidden&&"hidden"!==P.state&&E.onHidden(),P.state="hidden",P.endTime=new Date,f(P)}})}function D(){(E.timeOut>0||E.extendedTimeOut>0)&&(k=setTimeout(b,E.extendedTimeOut),F.maxHideTime=parseFloat(E.extendedTimeOut),F.hideEta=(new Date).getTime()+F.maxHideTime)}function H(){clearTimeout(k),F.hideEta=0,I.stop(!0,!0)[E.showMethod]({duration:E.showDuration,easing:E.showEasing})}function x(){var e=(F.hideEta-(new Date).getTime())/F.maxHideTime*100;q.width(e+"%")}var E=m(),y=t.iconClass||E.iconClass;if("undefined"!=typeof t.optionsOverride&&(E=e.extend(E,t.optionsOverride),y=t.optionsOverride.iconClass||y),!O(E,t)){T++,v=n(E,!0);var k=null,I=e("
"),M=e("
"),B=e("
"),q=e("
"),j=e(E.closeHtml),F={intervalId:null,hideEta:null,maxHideTime:null},P={toastId:T,state:"visible",startTime:new Date,options:E,map:t};return s(),r(),a(),f(P),E.debug&&console&&console.log(P),I}}function m(){return e.extend({},p(),b.options)}function h(e){v||(v=n()),e.is(":visible")||(e.remove(),e=null,0===v.children().length&&(v.remove(),w=void 0))}var v,C,w,T=0,O={error:"error",info:"info",success:"success",warning:"warning"},b={clear:r,remove:c,error:t,getContainer:n,info:o,options:{},subscribe:s,success:i,version:"2.1.4",warning:a};return b}()})}("function"==typeof define&&define.amd?define:function(e,t){"undefined"!=typeof module&&module.exports?module.exports=t(require("jquery")):window.toastr=t(window.jQuery)}); +//# sourceMappingURL=toastr.js.map diff --git a/resources/views/components/app-logo.blade.php b/resources/views/components/app-logo.blade.php index 2ccc081..47a7c38 100644 --- a/resources/views/components/app-logo.blade.php +++ b/resources/views/components/app-logo.blade.php @@ -1,6 +1,3 @@ -
- -
- Laravel Starter Kit + Scheduler
diff --git a/resources/views/components/layouts/app/sidebar.blade.php b/resources/views/components/layouts/app/sidebar.blade.php index 8dd5882..4f9277d 100644 --- a/resources/views/components/layouts/app/sidebar.blade.php +++ b/resources/views/components/layouts/app/sidebar.blade.php @@ -19,16 +19,6 @@ - - - {{ __('Repository') }} - - - - {{ __('Documentation') }} - - -