Prepare modules
This commit is contained in:
66
Livewire/VuexyAdmin/AppDescriptionSettings.php
Normal file
66
Livewire/VuexyAdmin/AppDescriptionSettings.php
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Koneko\VuexyAdmin\Livewire\VuexyAdmin;
|
||||
|
||||
use Livewire\Component;
|
||||
use Koneko\VuexyAdmin\Services\SettingsService;
|
||||
use Koneko\VuexyAdmin\Services\AdminTemplateService;
|
||||
|
||||
class AppDescriptionSettings extends Component
|
||||
{
|
||||
private $targetNotify = "#app-description-settings-card .notification-container";
|
||||
|
||||
public $app_name,
|
||||
$title,
|
||||
$description;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->resetForm();
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
$this->validate([
|
||||
'app_name' => 'required|string|max:255',
|
||||
'title' => 'required|string|max:255',
|
||||
'description' => 'nullable|string|max:255',
|
||||
]);
|
||||
|
||||
// Guardar título del sitio en configuraciones
|
||||
$SettingsService = app(SettingsService::class);
|
||||
|
||||
$SettingsService->set('admin.app_name', $this->app_name, null, 'vuexy-admin');
|
||||
$SettingsService->set('admin.title', $this->title, null, 'vuexy-admin');
|
||||
$SettingsService->set('admin.description', $this->description, null, 'vuexy-admin');
|
||||
|
||||
// Limpiar cache de plantilla
|
||||
app(AdminTemplateService::class)->clearAdminVarsCache();
|
||||
|
||||
// Recargamos el formulario
|
||||
$this->resetForm();
|
||||
|
||||
// Notificación de éxito
|
||||
$this->dispatch(
|
||||
'notification',
|
||||
target: $this->targetNotify,
|
||||
type: 'success',
|
||||
message: 'Se han guardado los cambios en las configuraciones.'
|
||||
);
|
||||
}
|
||||
|
||||
public function resetForm()
|
||||
{
|
||||
// Obtener los valores de las configuraciones de la base de datos
|
||||
$settings = app(AdminTemplateService::class)->getAdminVars();
|
||||
|
||||
$this->app_name = $settings['app_name'];
|
||||
$this->title = $settings['title'];
|
||||
$this->description = $settings['description'];
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('vuexy-admin::livewire.vuexy.app-description-settings');
|
||||
}
|
||||
}
|
72
Livewire/VuexyAdmin/AppFaviconSettings.php
Normal file
72
Livewire/VuexyAdmin/AppFaviconSettings.php
Normal file
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace Koneko\VuexyAdmin\Livewire\VuexyAdmin;
|
||||
|
||||
use Livewire\Component;
|
||||
use Livewire\WithFileUploads;
|
||||
use Koneko\VuexyAdmin\Services\AdminSettingsService;
|
||||
use Koneko\VuexyAdmin\Services\AdminTemplateService;
|
||||
|
||||
class AppFaviconSettings extends Component
|
||||
{
|
||||
use WithFileUploads;
|
||||
|
||||
private $targetNotify = "#app-favicon-settings-card .notification-container";
|
||||
|
||||
public $admin_favicon_16x16,
|
||||
$admin_favicon_76x76,
|
||||
$admin_favicon_120x120,
|
||||
$admin_favicon_152x152,
|
||||
$admin_favicon_180x180,
|
||||
$admin_favicon_192x192;
|
||||
|
||||
public $upload_image_favicon;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->resetForm();
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
$this->validate([
|
||||
'upload_image_favicon' => 'required|image|mimes:jpeg,png,jpg,svg,webp|max:20480',
|
||||
]);
|
||||
|
||||
// Procesar favicon
|
||||
app(AdminSettingsService::class)->processAndSaveFavicon($this->upload_image_favicon);
|
||||
|
||||
// Limpiar cache de plantilla
|
||||
app(AdminTemplateService::class)->clearAdminVarsCache();
|
||||
|
||||
// Recargamos el formulario
|
||||
$this->resetForm();
|
||||
|
||||
// Notificación de éxito
|
||||
$this->dispatch(
|
||||
'notification',
|
||||
target: $this->targetNotify,
|
||||
type: 'success',
|
||||
message: 'Se han guardado los cambios en las configuraciones.'
|
||||
);
|
||||
}
|
||||
|
||||
public function resetForm()
|
||||
{
|
||||
// Obtener los valores de las configuraciones de la base de datos
|
||||
$settings = app(AdminTemplateService::class)->getAdminVars();
|
||||
|
||||
$this->upload_image_favicon = null;
|
||||
$this->admin_favicon_16x16 = $settings['favicon']['16x16'];
|
||||
$this->admin_favicon_76x76 = $settings['favicon']['76x76'];
|
||||
$this->admin_favicon_120x120 = $settings['favicon']['120x120'];
|
||||
$this->admin_favicon_152x152 = $settings['favicon']['152x152'];
|
||||
$this->admin_favicon_180x180 = $settings['favicon']['180x180'];
|
||||
$this->admin_favicon_192x192 = $settings['favicon']['192x192'];
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('vuexy-admin::livewire.vuexy.app-favicon-settings');
|
||||
}
|
||||
}
|
110
Livewire/VuexyAdmin/GlobalSettingOffCanvasForm.php
Normal file
110
Livewire/VuexyAdmin/GlobalSettingOffCanvasForm.php
Normal file
@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
namespace Koneko\VuexyAdmin\Livewire\VuexyAdmin;
|
||||
|
||||
use Illuminate\Validation\Rule;
|
||||
use Koneko\VuexyAdmin\Models\Setting;
|
||||
use Koneko\VuexyAdmin\Livewire\Form\AbstractFormOffCanvasComponent;
|
||||
|
||||
/**
|
||||
* Class GlobalSettingOffCanvasForm
|
||||
*
|
||||
* Componente Livewire para gestionar parámetros globales del sistema.
|
||||
* Permite almacenar configuraciones personalizadas y valores múltiples tipos.
|
||||
*
|
||||
* @package Koneko\VuexyAdmin\Livewire\Settings
|
||||
*/
|
||||
class GlobalSettingOffCanvasForm extends AbstractFormOffCanvasComponent
|
||||
{
|
||||
public $id, $key, $category, $user_id,
|
||||
$value_string, $value_integer, $value_boolean,
|
||||
$value_float, $value_text;
|
||||
|
||||
public $confirmDeletion;
|
||||
|
||||
protected $casts = [
|
||||
'value_boolean' => 'boolean',
|
||||
'value_integer' => 'integer',
|
||||
'value_float' => 'float',
|
||||
];
|
||||
|
||||
protected $listeners = [
|
||||
'editGlobalSetting' => 'loadFormModel',
|
||||
'confirmDeletionGlobalSetting' => 'loadFormModelForDeletion',
|
||||
];
|
||||
|
||||
protected function model(): string
|
||||
{
|
||||
return Setting::class;
|
||||
}
|
||||
|
||||
protected function fields(): array
|
||||
{
|
||||
return [
|
||||
'key', 'category', 'user_id',
|
||||
'value_string', 'value_integer', 'value_boolean',
|
||||
'value_float', 'value_text'
|
||||
];
|
||||
}
|
||||
|
||||
protected function defaults(): array
|
||||
{
|
||||
return [
|
||||
'category' => 'general',
|
||||
];
|
||||
}
|
||||
|
||||
protected function focusOnOpen(): string
|
||||
{
|
||||
return 'key';
|
||||
}
|
||||
|
||||
protected function dynamicRules(string $mode): array
|
||||
{
|
||||
if ($mode === 'delete') {
|
||||
return ['confirmDeletion' => 'accepted'];
|
||||
}
|
||||
|
||||
$uniqueRule = Rule::unique('settings', 'key')
|
||||
->where(fn ($q) => $q
|
||||
->where('user_id', $this->user_id)
|
||||
->where('category', $this->category)
|
||||
);
|
||||
|
||||
if ($mode === 'edit') {
|
||||
$uniqueRule = $uniqueRule->ignore($this->id);
|
||||
}
|
||||
|
||||
return [
|
||||
'key' => ['required', 'string', $uniqueRule],
|
||||
'category' => ['nullable', 'string', 'max:96'],
|
||||
'user_id' => ['nullable', 'integer', 'exists:users,id'],
|
||||
'value_string' => ['nullable', 'string', 'max:255'],
|
||||
'value_integer' => ['nullable', 'integer'],
|
||||
'value_boolean' => ['nullable', 'boolean'],
|
||||
'value_float' => ['nullable', 'numeric'],
|
||||
'value_text' => ['nullable', 'string'],
|
||||
];
|
||||
}
|
||||
|
||||
protected function attributes(): array
|
||||
{
|
||||
return [
|
||||
'key' => 'clave de configuración',
|
||||
'category' => 'categoría',
|
||||
];
|
||||
}
|
||||
|
||||
protected function messages(): array
|
||||
{
|
||||
return [
|
||||
'key.required' => 'La clave del parámetro es obligatoria.',
|
||||
'key.unique' => 'Ya existe una configuración con esta clave en esa categoría.',
|
||||
];
|
||||
}
|
||||
|
||||
protected function viewPath(): string
|
||||
{
|
||||
return 'vuexy-admin::livewire.global-settings.offcanvas-form';
|
||||
}
|
||||
}
|
103
Livewire/VuexyAdmin/GlobalSettingsIndex.php
Normal file
103
Livewire/VuexyAdmin/GlobalSettingsIndex.php
Normal file
@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace Koneko\VuexyAdmin\Livewire\VuexyAdmin;;
|
||||
|
||||
use Koneko\VuexyAdmin\Livewire\Table\AbstractIndexComponent;
|
||||
use Koneko\VuexyAdmin\Models\Setting;
|
||||
|
||||
/**
|
||||
* Listado de Configuraciones (settings), extiende la clase base AbstractIndexComponent
|
||||
* para reutilizar la lógica de configuración y renderizado de tablas.
|
||||
*/
|
||||
class GlobalSettingsIndex extends AbstractIndexComponent
|
||||
{
|
||||
/**
|
||||
* Define la clase o instancia del modelo a usar.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function model(): string
|
||||
{
|
||||
return Setting::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retorna las columnas (header) de la tabla.
|
||||
* Se eligen las columnas más relevantes para mantener una interfaz mobile-first.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function columns(): array
|
||||
{
|
||||
return [
|
||||
'action' => 'Acciones',
|
||||
'key' => 'Clave',
|
||||
'category' => 'Categoría',
|
||||
'user_fullname' => 'Usuario',
|
||||
'created_at' => 'Creado',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retorna el formato (formatter) para cada columna.
|
||||
* Se aplican formatters para resaltar la información y se establecen propiedades de alineación y visibilidad.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function format(): array
|
||||
{
|
||||
return [
|
||||
'action' => [
|
||||
'formatter' => 'settingActionFormatter',
|
||||
'onlyFormatter' => true,
|
||||
],
|
||||
'key' => [
|
||||
'formatter' => [
|
||||
'name' => 'dynamicBadgeFormatter',
|
||||
'params' => ['color' => 'primary'],
|
||||
],
|
||||
'align' => 'center',
|
||||
'switchable' => false,
|
||||
],
|
||||
'category' => [
|
||||
'switchable' => false,
|
||||
],
|
||||
'user_fullname' => [
|
||||
'switchable' => false,
|
||||
],
|
||||
'created_at' => [
|
||||
'formatter' => 'whitespaceNowrapFormatter',
|
||||
'align' => 'center',
|
||||
'visible' => false,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sobrescribe la configuración base de la tabla para ajustar
|
||||
* la vista y funcionalidades específicas del catálogo.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function bootstraptableConfig(): array
|
||||
{
|
||||
return array_merge(parent::bootstraptableConfig(), [
|
||||
'sortName' => 'key',
|
||||
'exportFileName' => 'Configuración',
|
||||
'showFullscreen' => false,
|
||||
'showPaginationSwitch' => false,
|
||||
'showRefresh' => false,
|
||||
'pagination' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retorna la vista a renderizar para este componente.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function viewPath(): string
|
||||
{
|
||||
return 'vuexy-admin::livewire.global-settings.index';
|
||||
}
|
||||
}
|
61
Livewire/VuexyAdmin/LogoOnDarkBgSettings.php
Normal file
61
Livewire/VuexyAdmin/LogoOnDarkBgSettings.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Koneko\VuexyAdmin\Livewire\VuexyAdmin;
|
||||
|
||||
use Livewire\Component;
|
||||
use Livewire\WithFileUploads;
|
||||
use Koneko\VuexyAdmin\Services\AdminSettingsService;
|
||||
use Koneko\VuexyAdmin\Services\AdminTemplateService;
|
||||
|
||||
class LogoOnDarkBgSettings extends Component
|
||||
{
|
||||
use WithFileUploads;
|
||||
|
||||
private $targetNotify = "#logo-on-dark-bg-settings-card .notification-container";
|
||||
|
||||
public $admin_image_logo_dark,
|
||||
$upload_image_logo_dark;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->resetForm();
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
$this->validate([
|
||||
'upload_image_logo_dark' => 'required|image|mimes:jpeg,png,jpg,svg,webp|max:20480',
|
||||
]);
|
||||
|
||||
// Procesar favicon si se ha cargado una imagen
|
||||
app(AdminSettingsService::class)->processAndSaveImageLogo($this->upload_image_logo_dark, 'dark');
|
||||
|
||||
// Limpiar cache de plantilla
|
||||
app(AdminTemplateService::class)->clearAdminVarsCache();
|
||||
|
||||
// Recargamos el formulario
|
||||
$this->resetForm();
|
||||
|
||||
// Notificación de éxito
|
||||
$this->dispatch(
|
||||
'notification',
|
||||
target: $this->targetNotify,
|
||||
type: 'success',
|
||||
message: 'Se han guardado los cambios en las configuraciones.'
|
||||
);
|
||||
}
|
||||
|
||||
public function resetForm()
|
||||
{
|
||||
// Obtener los valores de las configuraciones de la base de datos
|
||||
$settings = app(AdminTemplateService::class)->getAdminVars();
|
||||
|
||||
$this->upload_image_logo_dark = null;
|
||||
$this->admin_image_logo_dark = $settings['image_logo']['large_dark'];
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('vuexy-admin::livewire.vuexy.logo-on-dark-bg-settings');
|
||||
}
|
||||
}
|
61
Livewire/VuexyAdmin/LogoOnLightBgSettings.php
Normal file
61
Livewire/VuexyAdmin/LogoOnLightBgSettings.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
namespace Koneko\VuexyAdmin\Livewire\VuexyAdmin;
|
||||
|
||||
use Livewire\Component;
|
||||
use Livewire\WithFileUploads;
|
||||
use Koneko\VuexyAdmin\Services\AdminSettingsService;
|
||||
use Koneko\VuexyAdmin\Services\AdminTemplateService;
|
||||
|
||||
class LogoOnLightBgSettings extends Component
|
||||
{
|
||||
use WithFileUploads;
|
||||
|
||||
private $targetNotify = "#logo-on-light-bg-settings-card .notification-container";
|
||||
|
||||
public $admin_image_logo,
|
||||
$upload_image_logo;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->resetForm();
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
$this->validate([
|
||||
'upload_image_logo' => 'required|image|mimes:jpeg,png,jpg,svg,webp|max:20480',
|
||||
]);
|
||||
|
||||
// Procesar favicon si se ha cargado una imagen
|
||||
app(AdminSettingsService::class)->processAndSaveImageLogo($this->upload_image_logo);
|
||||
|
||||
// Limpiar cache de plantilla
|
||||
app(AdminTemplateService::class)->clearAdminVarsCache();
|
||||
|
||||
// Recargamos el formulario
|
||||
$this->resetForm();
|
||||
|
||||
// Notificación de éxito
|
||||
$this->dispatch(
|
||||
'notification',
|
||||
target: $this->targetNotify,
|
||||
type: 'success',
|
||||
message: 'Se han guardado los cambios en las configuraciones.'
|
||||
);
|
||||
}
|
||||
|
||||
public function resetForm()
|
||||
{
|
||||
// Obtener los valores de las configuraciones de la base de datos
|
||||
$settings = app(AdminTemplateService::class)->getAdminVars();
|
||||
|
||||
$this->upload_image_logo = null;
|
||||
$this->admin_image_logo = $settings['image_logo']['large'];
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('vuexy-admin::livewire.vuexy.logo-on-light-bg-settings');
|
||||
}
|
||||
}
|
87
Livewire/VuexyAdmin/QuickAccessWidget.php
Normal file
87
Livewire/VuexyAdmin/QuickAccessWidget.php
Normal file
@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace Koneko\VuexyAdmin\Livewire\VuexyAdmin;
|
||||
|
||||
use Livewire\Component;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
class QuickAccessWidget extends Component
|
||||
{
|
||||
public $quickAccessItems = [];
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$menuConfig = config('vuexy_menu');
|
||||
$this->quickAccessItems = $this->processMenu($menuConfig);
|
||||
}
|
||||
|
||||
private function processMenu(array $menu): array
|
||||
{
|
||||
$user = Auth::user();
|
||||
$accessItems = [];
|
||||
|
||||
foreach ($menu as $section => $items) {
|
||||
if (!isset($items['submenu']) || !is_array($items['submenu'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$categoryData = [
|
||||
'title' => $section,
|
||||
'icon' => $items['icon'] ?? 'ti ti-folder',
|
||||
'description' => $items['description'] ?? '',
|
||||
'submenu' => []
|
||||
];
|
||||
|
||||
$this->processSubmenu($items['submenu'], $categoryData['submenu'], $user);
|
||||
|
||||
if (!empty($categoryData['submenu'])) {
|
||||
$accessItems[] = $categoryData;
|
||||
}
|
||||
}
|
||||
|
||||
return $accessItems;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private function processSubmenu(array $submenu, array &$categorySubmenu, $user)
|
||||
{
|
||||
foreach ($submenu as $title => $item) {
|
||||
// Si el elemento NO tiene 'route' ni 'url' y SOLO contiene un submenu, no lo mostramos como acceso directo
|
||||
if (!isset($item['route']) && !isset($item['url']) && isset($item['submenu'])) {
|
||||
// Procesamos los submenús de este elemento sin agregarlo directamente a la lista
|
||||
$this->processSubmenu($item['submenu'], $categorySubmenu, $user);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Validar si el usuario tiene permiso
|
||||
$can = $item['can'] ?? null;
|
||||
if (!$can || $user->can($can)) {
|
||||
// Si tiene ruta y existe en Laravel, usarla; si no, usar url, y si tampoco hay, usar 'javascript:;'
|
||||
$routeExists = isset($item['route']) && Route::has($item['route']);
|
||||
$url = $routeExists ? route($item['route']) : ($item['url'] ?? 'javascript:;');
|
||||
|
||||
// Agregar elemento al submenu si tiene un destino válido
|
||||
$categorySubmenu[] = [
|
||||
'title' => $title,
|
||||
'icon' => $item['icon'] ?? 'ti ti-circle',
|
||||
'url' => $url,
|
||||
];
|
||||
}
|
||||
|
||||
// Si el elemento tiene un submenu, también lo procesamos
|
||||
if (isset($item['submenu']) && is_array($item['submenu'])) {
|
||||
$this->processSubmenu($item['submenu'], $categorySubmenu, $user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('vuexy-admin::livewire.vuexy.quick-access-widget', [
|
||||
'quickAccessItems' => $this->quickAccessItems,
|
||||
]);
|
||||
}
|
||||
}
|
172
Livewire/VuexyAdmin/SendmailSettings.php
Normal file
172
Livewire/VuexyAdmin/SendmailSettings.php
Normal file
@ -0,0 +1,172 @@
|
||||
<?php
|
||||
|
||||
namespace Koneko\VuexyAdmin\Livewire\VuexyAdmin;
|
||||
|
||||
use Livewire\Component;
|
||||
use Illuminate\Support\Facades\Config;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Symfony\Component\Mailer\Transport;
|
||||
use Symfony\Component\Mailer\Mailer;
|
||||
use Symfony\Component\Mime\Email;
|
||||
use Koneko\VuexyAdmin\Services\GlobalSettingsService;
|
||||
|
||||
|
||||
class SendmailSettings extends Component
|
||||
{
|
||||
private $targetNotify = "#sendmail-settings-card .notification-container";
|
||||
|
||||
public $change_smtp_settings,
|
||||
$host,
|
||||
$port,
|
||||
$encryption,
|
||||
$username,
|
||||
$password;
|
||||
|
||||
public $save_button_disabled;
|
||||
|
||||
protected $listeners = [
|
||||
'loadSettings',
|
||||
'testSmtpConnection',
|
||||
];
|
||||
|
||||
// the list of smtp_encryption values that can be stored in table
|
||||
const SMTP_ENCRYPTION_SSL = 'SSL';
|
||||
const SMTP_ENCRYPTION_TLS = 'TLS';
|
||||
const SMTP_ENCRYPTION_NONE = 'none';
|
||||
|
||||
public $encryption_options = [
|
||||
self::SMTP_ENCRYPTION_SSL => 'SSL (Secure Sockets Layer)',
|
||||
self::SMTP_ENCRYPTION_TLS => 'TLS (Transport Layer Security)',
|
||||
self::SMTP_ENCRYPTION_NONE => 'Sin encriptación (No recomendado)',
|
||||
];
|
||||
|
||||
public $rules = [
|
||||
[
|
||||
'host' => 'nullable|string|max:255',
|
||||
'port' => 'nullable|integer',
|
||||
'encryption' => 'nullable|string',
|
||||
'username' => 'nullable|string|max:255',
|
||||
'password' => 'nullable|string|max:255',
|
||||
],
|
||||
[
|
||||
'host.string' => 'El servidor SMTP debe ser una cadena de texto.',
|
||||
'host.max' => 'El servidor SMTP no puede exceder los 255 caracteres.',
|
||||
'port.integer' => 'El puerto SMTP debe ser un número entero.',
|
||||
'encryption.string' => 'El tipo de encriptación SMTP debe ser una cadena de texto.',
|
||||
'username.string' => 'El nombre de usuario SMTP debe ser una cadena de texto.',
|
||||
'username.max' => 'El nombre de usuario SMTP no puede exceder los 255 caracteres.',
|
||||
'password.string' => 'La contraseña SMTP debe ser una cadena de texto.',
|
||||
'password.max' => 'La contraseña SMTP no puede exceder los 255 caracteres.',
|
||||
]
|
||||
];
|
||||
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->loadSettings();
|
||||
}
|
||||
|
||||
public function loadSettings()
|
||||
{
|
||||
$settings = app(GlobalSettingsService::class)->getMailSystemConfig();
|
||||
|
||||
$this->change_smtp_settings = false;
|
||||
$this->save_button_disabled = true;
|
||||
|
||||
$this->host = $settings['mailers']['smtp']['host'];
|
||||
$this->port = $settings['mailers']['smtp']['port'];
|
||||
$this->encryption = $settings['mailers']['smtp']['encryption'];
|
||||
$this->username = $settings['mailers']['smtp']['username'];
|
||||
$this->password = null;
|
||||
}
|
||||
|
||||
public function save()
|
||||
{
|
||||
$this->validate($this->rules[0]);
|
||||
|
||||
$globalSettingsService = app(GlobalSettingsService::class);
|
||||
|
||||
// Guardar título del App en configuraciones
|
||||
$globalSettingsService->updateSetting('mail.mailers.smtp.host', $this->host);
|
||||
$globalSettingsService->updateSetting('mail.mailers.smtp.port', $this->port);
|
||||
$globalSettingsService->updateSetting('mail.mailers.smtp.encryption', $this->encryption);
|
||||
$globalSettingsService->updateSetting('mail.mailers.smtp.username', $this->username);
|
||||
$globalSettingsService->updateSetting('mail.mailers.smtp.password', Crypt::encryptString($this->password));
|
||||
|
||||
$globalSettingsService->clearMailSystemConfigCache();
|
||||
|
||||
$this->loadSettings();
|
||||
|
||||
$this->dispatch(
|
||||
'notification',
|
||||
target: $this->targetNotify,
|
||||
type: 'success',
|
||||
message: 'Se han guardado los cambios en las configuraciones.'
|
||||
);
|
||||
}
|
||||
|
||||
public function testSmtpConnection()
|
||||
{
|
||||
// Validar los datos del formulario
|
||||
$this->validate($this->rules[0]);
|
||||
|
||||
try {
|
||||
// Verificar la conexión SMTP
|
||||
if ($this->validateSMTPConnection()) {
|
||||
$this->save_button_disabled = false;
|
||||
|
||||
$this->dispatch(
|
||||
'notification',
|
||||
target: $this->targetNotify,
|
||||
type: 'success',
|
||||
message: 'Conexión SMTP exitosa, se guardó los cambios exitosamente.',
|
||||
);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
// Captura y maneja errores de conexión SMTP
|
||||
$this->dispatch(
|
||||
'notification',
|
||||
target: $this->targetNotify,
|
||||
type: 'danger',
|
||||
message: 'Error en la conexión SMTP: ' . $e->getMessage(),
|
||||
delay: 15000 // Timeout personalizado
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function validateSMTPConnection()
|
||||
{
|
||||
$dsn = sprintf(
|
||||
'smtp://%s:%s@%s:%s?encryption=%s',
|
||||
urlencode($this->username), // Codificar nombre de usuario
|
||||
urlencode($this->password), // Codificar contraseña
|
||||
$this->host, // Host SMTP
|
||||
$this->port, // Puerto SMTP
|
||||
$this->encryption // Encriptación (tls o ssl)
|
||||
);
|
||||
|
||||
// Crear el transportador usando el DSN
|
||||
$transport = Transport::fromDsn($dsn);
|
||||
|
||||
// Crear el mailer con el transportador personalizado
|
||||
$mailer = new Mailer($transport);
|
||||
|
||||
// Enviar un correo de prueba
|
||||
$email = (new Email())
|
||||
->from($this->username) // Dirección de correo del remitente
|
||||
->to(env('MAIL_SANDBOX')) // Dirección de correo de destino
|
||||
->subject(Config::get('app.name') . ' - Correo de prueba')
|
||||
->text('Este es un correo de prueba para verificar la conexión SMTP.');
|
||||
|
||||
// Enviar el correo
|
||||
$mailer->send($email);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('vuexy-admin::livewire.vuexy.sendmail-settings');
|
||||
}
|
||||
}
|
121
Livewire/VuexyAdmin/VuexyInterfaceSettings.php
Normal file
121
Livewire/VuexyAdmin/VuexyInterfaceSettings.php
Normal file
@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
namespace Koneko\VuexyAdmin\Livewire\VuexyAdmin;
|
||||
|
||||
use Livewire\Component;
|
||||
use Koneko\VuexyAdmin\Services\AdminTemplateService;
|
||||
use Koneko\VuexyAdmin\Services\GlobalSettingsService;
|
||||
use Koneko\VuexyAdmin\Services\SettingsService;
|
||||
|
||||
class VuexyInterfaceSettings extends Component
|
||||
{
|
||||
private $targetNotify = "#interface-settings-card .notification-container";
|
||||
|
||||
public $uniqueId;
|
||||
|
||||
public $vuexy_myLayout,
|
||||
$vuexy_myTheme,
|
||||
$vuexy_myStyle,
|
||||
$vuexy_hasCustomizer,
|
||||
$vuexy_displayCustomizer,
|
||||
$vuexy_contentLayout,
|
||||
$vuexy_navbarType,
|
||||
$vuexy_footerFixed,
|
||||
$vuexy_menuFixed,
|
||||
$vuexy_menuCollapsed,
|
||||
$vuexy_headerType,
|
||||
$vuexy_showDropdownOnHover,
|
||||
$vuexy_authViewMode,
|
||||
$vuexy_maxQuickLinks;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->uniqueId = uniqid();
|
||||
|
||||
$this->resetForm();
|
||||
}
|
||||
|
||||
|
||||
public function save()
|
||||
{
|
||||
$this->validate([
|
||||
'vuexy_maxQuickLinks' => 'required|integer|min:2|max:20',
|
||||
]);
|
||||
|
||||
// Guardar configuraciones utilizando SettingsService
|
||||
$SettingsService = app(SettingsService::class);
|
||||
|
||||
$SettingsService->set('config.vuexy.custom.myLayout', $this->vuexy_myLayout, null, 'vuexy-admin');
|
||||
$SettingsService->set('config.vuexy.custom.myTheme', $this->vuexy_myTheme, null, 'vuexy-admin');
|
||||
$SettingsService->set('config.vuexy.custom.myStyle', $this->vuexy_myStyle, null, 'vuexy-admin');
|
||||
$SettingsService->set('config.vuexy.custom.hasCustomizer', $this->vuexy_hasCustomizer, null, 'vuexy-admin');
|
||||
$SettingsService->set('config.vuexy.custom.displayCustomizer', ($this->vuexy_hasCustomizer? $this->vuexy_displayCustomizer: false), null, 'vuexy-admin');
|
||||
$SettingsService->set('config.vuexy.custom.contentLayout', $this->vuexy_contentLayout, null, 'vuexy-admin');
|
||||
$SettingsService->set('config.vuexy.custom.navbarType', ($this->vuexy_myLayout == 'vertical' ? $this->vuexy_navbarType: null), null, 'vuexy-admin');
|
||||
$SettingsService->set('config.vuexy.custom.footerFixed', $this->vuexy_footerFixed, null, 'vuexy-admin');
|
||||
$SettingsService->set('config.vuexy.custom.menuFixed', ($this->vuexy_myLayout == 'vertical' ? $this->vuexy_menuFixed: null), null, 'vuexy-admin');
|
||||
$SettingsService->set('config.vuexy.custom.menuCollapsed', ($this->vuexy_myLayout == 'vertical' ? $this->vuexy_menuCollapsed: null), null, 'vuexy-admin');
|
||||
$SettingsService->set('config.vuexy.custom.headerType', ($this->vuexy_myLayout == 'horizontal' ? $this->vuexy_headerType: null), null, 'vuexy-admin');
|
||||
$SettingsService->set('config.vuexy.custom.showDropdownOnHover', ($this->vuexy_myLayout == 'horizontal' ? $this->vuexy_showDropdownOnHover: null), null, 'vuexy-admin');
|
||||
$SettingsService->set('config.vuexy.custom.authViewMode', $this->vuexy_authViewMode, null, 'vuexy-admin');
|
||||
$SettingsService->set('config.vuexy.custom.maxQuickLinks', $this->vuexy_maxQuickLinks, null, 'vuexy-admin');
|
||||
|
||||
// Elimina la Cache de Configuraciones
|
||||
app(GlobalSettingsService::class)->clearSystemConfigCache();
|
||||
|
||||
// Refrescar el componente actual
|
||||
$this->dispatch('clearLocalStoregeTemplateCustomizer');
|
||||
|
||||
// Notificación de éxito
|
||||
$this->dispatch(
|
||||
'notification',
|
||||
target: $this->targetNotify,
|
||||
type: 'success',
|
||||
message: 'Se han guardado los cambios en las configuraciones.',
|
||||
deferReload: true
|
||||
);
|
||||
}
|
||||
|
||||
public function clearCustomConfig()
|
||||
{
|
||||
// Elimina las claves config.vuexy.* para cargar los valores por defecto
|
||||
app(GlobalSettingsService::class)->clearVuexyConfig();
|
||||
|
||||
// Refrescar el componente actual
|
||||
$this->dispatch('clearLocalStoregeTemplateCustomizer');
|
||||
|
||||
$this->dispatch(
|
||||
'notification',
|
||||
target: $this->targetNotify,
|
||||
type: 'success',
|
||||
message: 'Se han guardado los cambios en las configuraciones.',
|
||||
deferReload: true
|
||||
);
|
||||
}
|
||||
|
||||
public function resetForm()
|
||||
{
|
||||
// Obtener los valores de las configuraciones de la base de datos
|
||||
$settings = app(AdminTemplateService::class)->getVuexyCustomizerVars();
|
||||
|
||||
$this->vuexy_myLayout = $settings['myLayout'];
|
||||
$this->vuexy_myTheme = $settings['myTheme'];
|
||||
$this->vuexy_myStyle = $settings['myStyle'];
|
||||
$this->vuexy_hasCustomizer = $settings['hasCustomizer'];
|
||||
$this->vuexy_displayCustomizer = $settings['displayCustomizer'];
|
||||
$this->vuexy_contentLayout = $settings['contentLayout'];
|
||||
$this->vuexy_navbarType = $settings['navbarType'];
|
||||
$this->vuexy_footerFixed = $settings['footerFixed'];
|
||||
$this->vuexy_menuFixed = $settings['menuFixed'];
|
||||
$this->vuexy_menuCollapsed = $settings['menuCollapsed'];
|
||||
$this->vuexy_headerType = $settings['headerType'];
|
||||
$this->vuexy_showDropdownOnHover = $settings['showDropdownOnHover'];
|
||||
$this->vuexy_authViewMode = $settings['authViewMode'];
|
||||
$this->vuexy_maxQuickLinks = $settings['maxQuickLinks'];
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('vuexy-admin::livewire.vuexy.interface-settings');
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user