Testing Alpha
This commit is contained in:
@ -0,0 +1,64 @@
|
||||
<div>
|
||||
<x-vuexy-admin::offcanvas.basic :id="$offcanvasId" :tag-name="$tagName">
|
||||
<x-vuexy-admin::form :id="$formId" :mode="$mode" wireSubmit="onSubmit">
|
||||
<x-slot name="actions">
|
||||
<x-vuexy-admin::button.offcanvas-buttons :mode="$mode" :tagName="$tagName" />
|
||||
</x-slot>
|
||||
|
||||
{{-- Sección: Identificación --}}
|
||||
<x-vuexy-admin::form.input :uid="$uniqueId" model="key" label="Clave del parámetro" required icon="ti ti-key" placeholder="Ej: ui.theme" />
|
||||
|
||||
<div class="row">
|
||||
<x-vuexy-admin::form.select :uid="$uniqueId" model="module" label="Categoría"
|
||||
:options="[
|
||||
'general' => 'General',
|
||||
'ui' => 'Interfaz',
|
||||
'mail' => 'Correo',
|
||||
'cfdi' => 'CFDI',
|
||||
]"
|
||||
placeholder="Selecciona una categoría"
|
||||
parentClass="col-md-6"
|
||||
/>
|
||||
<x-vuexy-admin::form.input :uid="$uniqueId" model="user_id" label="ID Usuario (Opcional)"
|
||||
type="number"
|
||||
parentClass="col-md-6"
|
||||
icon="ti ti-user"
|
||||
placeholder="ID del usuario asociado"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
{{-- Sección: Valores (solo llena uno) --}}
|
||||
<div class="alert" type="info" icon="ti ti-info-circle" class="mb-1">
|
||||
Puedes llenar **solo uno** de los valores siguientes según el tipo de configuración.
|
||||
</div>
|
||||
|
||||
<x-vuexy-admin::form.input :uid="$uniqueId" model="value_string" label="Valor (Texto Corto)" icon="ti ti-typography" placeholder="Ej: dark" />
|
||||
<x-vuexy-admin::form.input :uid="$uniqueId" model="value_integer" label="Valor (Entero)" type="number" icon="ti ti-hash" />
|
||||
<x-vuexy-admin::form.input :uid="$uniqueId" model="value_float" label="Valor (Decimal)" type="number" step="0.01" icon="ti ti-percentage" />
|
||||
<x-vuexy-admin::form.checkbox :uid="$uniqueId" model="value_boolean" label="Valor (Booleano)" />
|
||||
<x-vuexy-admin::form.textarea :uid="$uniqueId" model="value_text" label="Valor (Texto Largo)" placeholder="Valor largo o configuración avanzada en texto" rows="3" />
|
||||
|
||||
<hr>
|
||||
</x-vuexy-admin::form>
|
||||
</x-vuexy-admin::offcanvas.basic>
|
||||
</div>
|
||||
|
||||
@push('page-script')
|
||||
<script>
|
||||
// Evento para inicializar el formulario cuando se carga la página
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const initializeGlobalSettingsForm = () => {
|
||||
|
||||
};
|
||||
|
||||
var myOffcanvas = document.getElementById('{{ $offcanvasId }}');
|
||||
|
||||
myOffcanvas.addEventListener('show.bs.offcanvas', function () {
|
||||
initializeGlobalSettingsForm();
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
@endpush
|
@ -0,0 +1,9 @@
|
||||
<div>
|
||||
<x-vuexy-admin::table.bootstrap.manager :tagName="$tagName" :datatableConfig="$bt_datatable">
|
||||
<x-slot name="tools">
|
||||
<div class="mb-4 pr-2">
|
||||
<x-vuexy-admin::button.index-offcanvas :label="$singularName" :tagName="$tagName" />
|
||||
</div>
|
||||
</x-slot>
|
||||
</x-vuexy-admin::table.bootstrap.manager>
|
||||
</div>
|
@ -0,0 +1,39 @@
|
||||
<div>
|
||||
<x-vuexy-admin::offcanvas.basic :id="$offcanvasId" :tag-name="$tagName">
|
||||
<x-vuexy-admin::form :uid="$uniqueId" :id="$formId" :mode="$mode" wireSubmit="onSubmit">
|
||||
<x-slot name="actions">
|
||||
<x-vuexy-admin::button.offcanvas-buttons :mode="$mode" :tagName="$tagName" />
|
||||
</x-slot>
|
||||
{{-- Usuario --}}
|
||||
<x-vuexy-admin::form.input :uid="$uniqueId" model="name" label="Nombre(s)" />
|
||||
<x-vuexy-admin::form.input :uid="$uniqueId" model="last_name" label="Apellidos" />
|
||||
{{-- Correos electrónicos --}}
|
||||
<x-vuexy-admin::form.input type="email" :uid="$uniqueId" model="email" label="Correo electrónico" icon="ti ti-mail" autocomplete="email" inputmode="email" />
|
||||
|
||||
{{-- Contraseña --}}
|
||||
<x-vuexy-admin::form.input type="password" :uid="$uniqueId" model="password" label="Contraseña" icon="ti ti-lock" autocomplete="new-password" />
|
||||
|
||||
|
||||
<hr>
|
||||
|
||||
</x-vuexy-admin::form>
|
||||
</x-vuexy-admin::offcanvas.basic>
|
||||
</div>
|
||||
|
||||
@push('page-script')
|
||||
<script>
|
||||
// Evento para inicializar el formulario cuando se carga la página
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const initializeUserForm = () => {
|
||||
|
||||
};
|
||||
|
||||
var myOffcanvas = document.getElementById('{{ $offcanvasId }}');
|
||||
|
||||
myOffcanvas.addEventListener('show.bs.offcanvas', function () {
|
||||
initializeUserForm();
|
||||
});
|
||||
});
|
||||
|
||||
</script>
|
||||
@endpush
|
@ -0,0 +1,17 @@
|
||||
<div>
|
||||
<h2 class="text-xl font-bold">Gestión de Permisos</h2>
|
||||
|
||||
<div class="mb-4">
|
||||
<input type="text" wire:model="permissionName" placeholder="Nombre del permiso" class="border p-2">
|
||||
<button wire:click="createPermission" class="bg-blue-500 text-white px-4 py-2">Crear Permiso</button>
|
||||
</div>
|
||||
|
||||
<ul>
|
||||
@foreach($permissions as $permission)
|
||||
<li>
|
||||
{{ $permission->name }}
|
||||
<button wire:click="deletePermission({{ $permission->id }})" class="text-red-500">Eliminar</button>
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
@ -0,0 +1,7 @@
|
||||
<x-vuexy-admin::table.bootstrap.manager :tagName="$tagName" :datatableConfig="$bt_datatable">
|
||||
<x-slot name="tools">
|
||||
<div class="mb-4 pr-2">
|
||||
<x-vuexy-admin::button.index-offcanvas :label="$singularName" :tagName="$tagName" />
|
||||
</div>
|
||||
</x-slot>
|
||||
</x-vuexy-admin::table.bootstrap.manager>
|
46
resources/views/livewire/settings/rbac/roles/index.blade.php
Normal file
46
resources/views/livewire/settings/rbac/roles/index.blade.php
Normal file
@ -0,0 +1,46 @@
|
||||
<div>
|
||||
<h2 class="text-xl font-bold">Gestión de Roles</h2>
|
||||
|
||||
<!-- Crear Nuevo Rol -->
|
||||
<div class="mb-4">
|
||||
<input type="text" wire:model="roleName" placeholder="Nombre del rol" class="border p-2">
|
||||
<button wire:click="createRole" class="bg-blue-500 text-white px-4 py-2">Crear Rol</button>
|
||||
</div>
|
||||
|
||||
<!-- Tabla de Roles -->
|
||||
<table class="table-auto w-full border">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Nombre</th>
|
||||
<th>Acciones</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($roles as $role)
|
||||
<tr>
|
||||
<td>{{ $role->name }}</td>
|
||||
<td>
|
||||
<button wire:click="selectRole({{ $role->id }})" class="text-blue-500">Editar</button>
|
||||
<button wire:click="deleteRole({{ $role->id }})" class="text-red-500">Eliminar</button>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
{{ $roles->links() }}
|
||||
|
||||
<!-- Editar Permisos del Rol -->
|
||||
@if($selectedRole)
|
||||
<div class="mt-4">
|
||||
<h3>Permisos para {{ $selectedRole->name }}</h3>
|
||||
@foreach($availablePermissions as $permission)
|
||||
<label>
|
||||
<input type="checkbox" wire:model="permissions" value="{{ $permission->id }}">
|
||||
{{ $permission->name }}
|
||||
</label>
|
||||
@endforeach
|
||||
<button wire:click="updateRolePermissions" class="bg-green-500 text-white px-4 py-2 mt-2">Actualizar</button>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
@ -0,0 +1,347 @@
|
||||
<div>
|
||||
<p class="mb-4">Un rol proporciona acceso a menús y funciones predefinidas para que, según el rol asignado por un administrador, el usuario tener acceso a lo que necesite.</p>
|
||||
|
||||
<!-- Role cards -->
|
||||
<div class="row g-4">
|
||||
@foreach($roles as $role)
|
||||
<div class="col-xl-4 col-lg-6 col-md-6">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="d-flex justify-content-between">
|
||||
<h6 class="fw-normal mb-2">Total {{ $role->users->count() }} usuario{{ $role->users->count() == 1? '': 's' }}</h6>
|
||||
<ul class="list-unstyled d-flex align-items-center avatar-group mb-0">
|
||||
@foreach($role->users->take(10) as $user)
|
||||
<li data-bs-toggle="tooltip"
|
||||
data-popup="tooltip-custom"
|
||||
data-bs-placement="top"
|
||||
title="{{ $user->name }}"
|
||||
class="avatar avatar-sm pull-up">
|
||||
<img class="rounded-circle" src="{{ asset($user->profile_photo_url) }}" alt="Avatar" />
|
||||
</li>
|
||||
@endforeach
|
||||
</ul>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between align-items-end mt-1">
|
||||
<div class="role-heading">
|
||||
<h4 class="mb-1 role-name">{{ $role->name }}</h4>
|
||||
<span class="badge rounded-pill bg-label-{{ $role->style }}">Style: {{ $role->style }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<a href="javascript:;" data-bs-toggle="modal" data-bs-target="#roleModal" wire:click="loadRoleData('view', {{ $role->id }})"
|
||||
class="text-body ms-2"
|
||||
data-bs-toggle="tooltip"
|
||||
data-popup="tooltip-custom"
|
||||
data-bs-placement="top"
|
||||
title="Ver rol">
|
||||
<i class="fa-regular fa-eye"></i>
|
||||
</a>
|
||||
@can('system.roles.edit')
|
||||
@if ($role->name != 'SuperAdmin' && $role->name != 'Admin')
|
||||
<a href="javascript:;" data-bs-toggle="modal" data-bs-target="#roleModal" wire:click="loadRoleData('edit', {{ $role->id }})"
|
||||
class="text-body ms-2"
|
||||
data-bs-toggle="tooltip"
|
||||
data-popup="tooltip-custom"
|
||||
data-bs-placement="top"
|
||||
title="Editar rol">
|
||||
<i class="fa-regular fa-pen-to-square"></i>
|
||||
</a>
|
||||
@endif
|
||||
@endcan
|
||||
@can('system.roles.create')
|
||||
<a href="javascript:;" data-bs-toggle="modal" data-bs-target="#roleModal" wire:click="loadRoleData('clone', {{ $role->id }})"
|
||||
class="text-body ms-2"
|
||||
data-bs-toggle="tooltip"
|
||||
data-popup="tooltip-custom"
|
||||
data-bs-placement="top"
|
||||
title="Crear una copia">
|
||||
<i class="fa-regular fa-copy"></i>
|
||||
</a>
|
||||
@endcan
|
||||
@can('system.roles.delete')
|
||||
@if ($role->name != 'SuperAdmin' && $role->name != 'Admin')
|
||||
<a href="javascript:;" data-bs-toggle="modal" data-bs-target="#roleDeleteModal" data-id="{{ $role->id }}"
|
||||
class="role-delete-modal text-body ms-2"
|
||||
data-bs-toggle="tooltip"
|
||||
data-popup="tooltip-custom"
|
||||
data-bs-placement="top"
|
||||
title="Eliminar">
|
||||
<i class="fa-regular fa-trash-can"></i>
|
||||
</a>
|
||||
@endif
|
||||
@endcan
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
@can('system.roles.create')
|
||||
<div class="col-xl-4 col-lg-6 col-md-6">
|
||||
<div class="card h-100">
|
||||
<div class="row h-100">
|
||||
<div class="col-sm-5">
|
||||
<div class="d-flex align-items-end h-100 justify-content-center mt-sm-0 mt-3">
|
||||
<img src="{{ asset('vendor/vuexy-admin/img/illustrations/add-new-roles.png') }}" class="img-fluid mt-sm-4 mt-md-0" alt="add-new-roles" width="83">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-7">
|
||||
<div class="card-body text-sm-end text-center ps-sm-0">
|
||||
<button data-bs-target="#roleModal" data-bs-toggle="modal" class="btn btn-primary mb-2 text-nowrap add-new-role">
|
||||
<i class="fa-solid fa-plus me-1"></i> Nuevo rol
|
||||
</button>
|
||||
<p class="mb-0 mt-1">Agregar rol, si no existe</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endcan
|
||||
</div>
|
||||
<!--/ Role cards -->
|
||||
|
||||
<!-- Role Modals -->
|
||||
@include('vuexy-admin::roles._form_modal')
|
||||
@include('vuexy-admin::roles._delete_modal')
|
||||
<!-- / Role Modals -->
|
||||
<div>
|
||||
|
||||
@push('page-script')
|
||||
<script>
|
||||
// Función para obtener elementos del formulario
|
||||
const getFormElements = () => {
|
||||
const form = document.getElementById('roleForm');
|
||||
const formElements = form.querySelectorAll('input, select, textarea, button');
|
||||
|
||||
return {
|
||||
roleModal: document.getElementById('roleModal'),
|
||||
roleTitle: document.querySelector('.role-title'),
|
||||
form: form,
|
||||
inputId: document.querySelector('#roleForm input[name="id"]'),
|
||||
inputName: document.querySelector('#roleForm input[name="name"]'),
|
||||
formElements: formElements,
|
||||
addRoleButton: document.querySelector('.add-new-role'),
|
||||
selectAll: document.querySelector('#selectAll'),
|
||||
submitButton: document.querySelector('#roleForm button[type="submit"]'),
|
||||
deleteRoleButtons: document.querySelectorAll('.role-delete-modal'),
|
||||
deleteRoleModal: document.getElementById('roleDeleteModal'),
|
||||
deleteRoleForm: document.getElementById('deleteRoleForm'),
|
||||
deleteRoleText: document.querySelector('#roleDeleteModal .confirmation-text'),
|
||||
};
|
||||
};
|
||||
|
||||
// Función para habilitar o deshabilitar el formulario
|
||||
const habilitarForm = (enableForm = true) => {
|
||||
const { formElements, submitButton } = getFormElements();
|
||||
|
||||
formElements.forEach(element => {
|
||||
element.disabled = !enableForm;
|
||||
});
|
||||
|
||||
submitButton.disabled = !enableForm;
|
||||
}
|
||||
|
||||
// Función para resetear el formulario
|
||||
const resetForm = () => {
|
||||
const { roleTitle, form, submitButton } = getFormElements();
|
||||
|
||||
roleTitle.textContent = 'Agregar un nuevo rol';
|
||||
submitButton.textContent = 'Crear nuevo rol';
|
||||
|
||||
form.reset();
|
||||
|
||||
// Limpiar errores de validación
|
||||
form.querySelectorAll('.is-invalid').forEach(element => {
|
||||
element.classList.remove('is-invalid');
|
||||
});
|
||||
|
||||
// Restablecer mensajes de error
|
||||
form.querySelectorAll('.invalid-feedback').forEach(element => {
|
||||
element.textContent = '';
|
||||
});
|
||||
};
|
||||
|
||||
// Función para inicializar la validación del formulario
|
||||
const initializeFormValidation = (form) => {
|
||||
const { inputId, inputName } = getFormElements();
|
||||
|
||||
FormValidation.formValidation(form, {
|
||||
fields: {
|
||||
name: {
|
||||
validators: {
|
||||
notEmpty: {
|
||||
message: 'El nombre del rol es requerido'
|
||||
},
|
||||
// Agregar una regla personalizada para la validación AJAX
|
||||
remote: {
|
||||
url: '{{ route('admin.core.roles.check-unique-name') }}',
|
||||
data: function() {
|
||||
return {
|
||||
name: inputName.value,
|
||||
id: inputId.value,
|
||||
};
|
||||
},
|
||||
message: 'Este nombre de rol ya está en uso',
|
||||
method: 'GET'
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
trigger: new FormValidation.plugins.Trigger(),
|
||||
bootstrap5: new FormValidation.plugins.Bootstrap5({
|
||||
rowSelector: '.col-12'
|
||||
}),
|
||||
submitButton: new FormValidation.plugins.SubmitButton(),
|
||||
autoFocus: new FormValidation.plugins.AutoFocus(),
|
||||
}
|
||||
})
|
||||
.on('core.form.valid', function(e) {
|
||||
Livewire.dispatch('saveRole');
|
||||
});
|
||||
};
|
||||
|
||||
// Función para agregar el listener a un botón de eliminación de rol
|
||||
const addDeleteRoleListener = (button) => {
|
||||
button.addEventListener('click', function() {
|
||||
const { deleteRoleText } = getFormElements();
|
||||
|
||||
var roleText = '¿Está seguro que desea eliminar el rol "' + button.closest('.card').querySelector('.role-name').innerHTML.trim() + '"?';
|
||||
|
||||
@this.deleteRoleId = this.dataset.id;
|
||||
deleteRoleText.textContent = roleText;
|
||||
});
|
||||
}
|
||||
|
||||
// Función para cambiar el estado de los checkboxes de permisos
|
||||
const setPermissionCheckboxState = (input, state) => {
|
||||
if(!input)
|
||||
return false;
|
||||
|
||||
let modelName = input.getAttribute('wire:model');
|
||||
|
||||
modelName = modelName.split('.').pop();
|
||||
|
||||
if(modelName)
|
||||
@this.permissionsInputs[modelName] = state;
|
||||
}
|
||||
|
||||
// Inicialización
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
Livewire.on('reloadForm', () => {
|
||||
setTimeout(() => {
|
||||
const { form, selectAll, deleteRoleForm } = getFormElements();
|
||||
|
||||
// Seleccionar/deseleccionar todos los checkboxes
|
||||
selectAll.addEventListener('change', e => {
|
||||
Object.keys(@this.permissionsInputs).forEach(key => {
|
||||
@this.permissionsInputs[key] = e.target.checked;
|
||||
});
|
||||
});
|
||||
|
||||
const checkboxList = document.querySelectorAll('#roleForm .permission-row input[type="checkbox"]');
|
||||
|
||||
checkboxList.forEach(checkbox => {
|
||||
checkbox.addEventListener('change', e => {
|
||||
let permissionType = e.target.dataset.type,
|
||||
permissionsRow = e.target.closest('.permission-row');
|
||||
|
||||
if (permissionType == 'view' && !e.target.checked) {
|
||||
let permissionCheckboxView = permissionsRow.querySelector('input[data-type="view"]'),
|
||||
permissionCheckboxCreate = permissionsRow.querySelector('input[data-type="create"]'),
|
||||
permissionCheckboxEdit = permissionsRow.querySelector('input[data-type="edit"]'),
|
||||
permissionCheckboxCancel = permissionsRow.querySelector('input[data-type="cancel"]'),
|
||||
permissionCheckboxDelete = permissionsRow.querySelector('input[data-type="delete"]');
|
||||
|
||||
if(permissionCheckboxView)
|
||||
setPermissionCheckboxState(permissionCheckboxView, false);
|
||||
|
||||
if(permissionCheckboxCreate)
|
||||
setPermissionCheckboxState(permissionCheckboxCreate, false);
|
||||
|
||||
if(permissionCheckboxEdit)
|
||||
setPermissionCheckboxState(permissionCheckboxEdit, false);
|
||||
|
||||
if(permissionCheckboxCancel)
|
||||
setPermissionCheckboxState(permissionCheckboxCancel, false);
|
||||
|
||||
if(permissionCheckboxDelete)
|
||||
setPermissionCheckboxState(permissionCheckboxDelete, false);
|
||||
}
|
||||
|
||||
if ((permissionType == 'create' || permissionType == 'edit' || permissionType == 'cancel' || permissionType == 'delete') && e.target.checked) {
|
||||
let permissionCheckboxView = permissionsRow.querySelector('input[data-type="view"]');
|
||||
|
||||
setPermissionCheckboxState(permissionCheckboxView, true);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// Validación de formulario
|
||||
initializeFormValidation(form);
|
||||
|
||||
deleteRoleForm.addEventListener('submit', function(e) {
|
||||
e.preventDefault();
|
||||
Livewire.dispatch('deleteRole');
|
||||
});
|
||||
}, 1);
|
||||
});
|
||||
|
||||
Livewire.on('habilitarFormulario', () => {
|
||||
habilitarForm();
|
||||
})
|
||||
|
||||
Livewire.on('deshabilitarFormulario', () => {
|
||||
setTimeout(() => {
|
||||
habilitarForm(false);
|
||||
}, 1);
|
||||
})
|
||||
|
||||
Livewire.on('modalHide', () => {
|
||||
const { roleModal } = getFormElements();
|
||||
const modal = bootstrap.Modal.getInstance(roleModal);
|
||||
|
||||
modal.hide();
|
||||
});
|
||||
|
||||
Livewire.on('modalDeleteHide', () => {
|
||||
const { deleteRoleModal } = getFormElements();
|
||||
const modal = bootstrap.Modal.getInstance(deleteRoleModal);
|
||||
|
||||
modal.hide();
|
||||
});
|
||||
|
||||
Livewire.on('saveRole', () => {
|
||||
const { deleteRoleButtons } = getFormElements();
|
||||
|
||||
deleteRoleButtons.forEach(button => {
|
||||
addDeleteRoleListener(button);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
const { roleModal, addRoleButton, deleteRoleButtons } = getFormElements();
|
||||
|
||||
// Al agregar Rol
|
||||
addRoleButton.addEventListener('click', function() {
|
||||
const { form } = getFormElements();
|
||||
|
||||
resetForm();
|
||||
habilitarForm();
|
||||
});
|
||||
|
||||
// Al abrir el Modal Crear / Editar / Clonar
|
||||
roleModal.addEventListener('shown.bs.modal', function () {
|
||||
const { inputName } = getFormElements();
|
||||
|
||||
inputName.focus();
|
||||
});
|
||||
|
||||
// Eliminar
|
||||
deleteRoleButtons.forEach(button => {
|
||||
addDeleteRoleListener(button);
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
@endsection
|
@ -0,0 +1,86 @@
|
||||
<div x-data="{
|
||||
changeSmtpSettings: @entangle('change_smtp_settings'),
|
||||
saveButtonDisabled: @entangle('save_button_disabled'),
|
||||
}">
|
||||
<form id="smtp-settings-card">
|
||||
<div class="card mb-6">
|
||||
<h5 class="card-header">Servidor de correo saliente</h5>
|
||||
<div class="card-body">
|
||||
<div class="mb-3">
|
||||
<x-vuexy-admin::form.checkbox
|
||||
wire:model='change_smtp_settings'
|
||||
parent_class='form-switch'>
|
||||
Cambiar configuración
|
||||
</x-form.checkbox>
|
||||
</div>
|
||||
<div class="mb-3 fv-row">
|
||||
<label for="host" class="form-label">Servidor de correo saliente (SMTP)</label>
|
||||
<input type="text" name="host" id="host" wire:model='host' class="form-control" placeholder="Servidor de salida" :disabled="!changeSmtpSettings">
|
||||
@error('host') <span class="text-danger">{{ $message }}</span> @enderror
|
||||
</div>
|
||||
<div class="mb-3 fv-row">
|
||||
<label for="port" class="form-label">Puerto SMTP</label>
|
||||
<input type="number" name="port" id="port" wire:model='port' class="form-control" placeholder="Puerto SMTP" :disabled="!changeSmtpSettings">
|
||||
@error('port') <span class="text-danger">{{ $message }}</span> @enderror
|
||||
</div>
|
||||
<div class="mb-3 fv-row">
|
||||
<label for="encryption" class="form-label">Encriptación</label>
|
||||
<x-vuexy-admin::form.select
|
||||
wire:model='encryption'
|
||||
:options="$encryption_options"
|
||||
:disabled="!$change_smtp_settings"
|
||||
placeholder="Selecciona el método de encriptación" />
|
||||
@error('encryption') <span class="text-danger">{{ $message }}</span> @enderror
|
||||
</div>
|
||||
|
||||
<div class="mb-3 fv-row">
|
||||
<label for="username" class="form-label">Usuario</label>
|
||||
<input type="text" name="username" id="username" wire:model='username' class="form-control" placeholder="Usuario" autocomplete="username" :disabled="!changeSmtpSettings">
|
||||
@error('username') <span class="text-danger">{{ $message }}</span> @enderror
|
||||
</div>
|
||||
<div class="fv-row">
|
||||
<label for="password" class="form-label">Contraseña</label>
|
||||
<input type="password" name="password" id="password" wire:model='password' class="form-control" placeholder="Contraseña" autocomplete="current-password" :disabled="!changeSmtpSettings">
|
||||
@error('password') <span class="text-danger">{{ $message }}</span> @enderror
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
{{-- Botones --}}
|
||||
<div class="row my-4">
|
||||
<div class="col-lg-12 text-end">
|
||||
<button
|
||||
type="button"
|
||||
id="test_smtp_connection_button"
|
||||
class="btn btn-success btn-sm mt-2 mr-2 waves-effect waves-light"
|
||||
:disabled="!changeSmtpSettings"
|
||||
data-loading-text="Realizando prueba...">
|
||||
<i class="ti ti-flask mr-2"></i>
|
||||
Realizar una prueba
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
id="save_smtp_connection_button"
|
||||
class="btn btn-primary btn-sm mt-2 mr-2 waves-effect waves-light"
|
||||
:disabled="saveButtonDisabled"
|
||||
wire:click="save"
|
||||
data-loading-text="Guardando...">
|
||||
<i class="ti ti-device-floppy mr-2"></i>
|
||||
Guardar cambios
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
id="cancel_smtp_connection_button"
|
||||
class="btn btn-secondary btn-sm mt-2 mr-2 waves-effect waves-light"
|
||||
wire:click="loadSettings"
|
||||
:disabled="!changeSmtpSettings">
|
||||
<i class="ti ti-rotate-2 mr-2"></i>
|
||||
Cancelar
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{{-- Notifications --}}
|
||||
<div class="notification-container pt-4" wire:ignore></div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
45
resources/views/livewire/settings/users/form.blade.php
Normal file
45
resources/views/livewire/settings/users/form.blade.php
Normal file
@ -0,0 +1,45 @@
|
||||
<div>
|
||||
<x-vuexy-admin::form id="{{ $formId }}" :mode="$mode" wireSubmit="onSubmit" actionPosition="both">
|
||||
<x-slot name="actions">
|
||||
<x-vuexy-admin::button.form-buttons :mode="$mode" :label="$singularName" />
|
||||
</x-slot>
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
{{-- Identificación --}}
|
||||
<x-vuexy-admin::card.basic title="Identificación">
|
||||
<x-vuexy-admin::form.input :uid="$uniqueId" model="name" label="Nombre de usuario" />
|
||||
</x-vuexy-admin::card.basic>
|
||||
|
||||
{{-- Configuraciones --}}
|
||||
<x-vuexy-admin::card.basic title="Configuraciones">
|
||||
<x-vuexy-admin::form.checkbox uid="random" model="status" label="Habilitar sucursal" switch="true" />
|
||||
</x-vuexy-admin::card.basic>
|
||||
</div>
|
||||
<div class="col-lg-4">
|
||||
{{-- Información de contacto --}}
|
||||
<x-vuexy-admin::card.basic title="Información de contacto">
|
||||
<x-vuexy-admin::form.input type="email" :uid="$uniqueId" model="email" label="Correo electrónico" icon="ti ti-mail" autocomplete="email" inputmode="email" />
|
||||
</x-vuexy-admin::card.basic>
|
||||
</div>
|
||||
</div>
|
||||
</x-vuexy-admin::form>
|
||||
</div>
|
||||
|
||||
@push('page-script')
|
||||
<script>
|
||||
const initializeUserForm = (mode) => {
|
||||
|
||||
}
|
||||
|
||||
// Evento para inicializar el formulario
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
document.addEventListener('on-failed-validation-user', (event) => {
|
||||
setTimeout(() => {
|
||||
initializeUserForm('{{ $mode }}');
|
||||
}, 10);
|
||||
});
|
||||
|
||||
initializeUserForm('{{ $mode }}');
|
||||
});
|
||||
</script>
|
||||
@endpush
|
@ -0,0 +1,93 @@
|
||||
<div>
|
||||
<x-vuexy-admin::offcanvas.basic :id="$offcanvasId" :tag-name="$tagName">
|
||||
<x-vuexy-admin::form :uid="$uniqueId" :id="$formId" :mode="$mode" wireSubmit="onSubmit">
|
||||
<x-slot name="actions">
|
||||
<x-vuexy-admin::button.offcanvas-buttons :mode="$mode" :tagName="$tagName" />
|
||||
</x-slot>
|
||||
{{-- Usuario --}}
|
||||
<x-vuexy-admin::form.input :uid="$uniqueId" model="name" label="Nombre(s)" />
|
||||
<x-vuexy-admin::form.input :uid="$uniqueId" model="last_name" label="Apellidos" />
|
||||
{{-- Correos electrónicos --}}
|
||||
<x-vuexy-admin::form.input type="email" :uid="$uniqueId" model="email" label="Correo electrónico" icon="ti ti-mail" autocomplete="email" inputmode="email" />
|
||||
|
||||
{{-- Imágen de perfil --}}
|
||||
<div class="mb-4">
|
||||
<label class="form-label">Imágen de perfil</label>
|
||||
@if ($upload_profile_photo && in_array($upload_profile_photo->getMimeType(), ['image/jpeg', 'image/png', 'image/webp']))
|
||||
<div class="text-center mb-2">
|
||||
<img src="{{ $upload_profile_photo->temporaryUrl() }}" alt="Vista previa" class="img-thumbnail mx-auto" style="max-height: 300px;">
|
||||
</div>
|
||||
@endif
|
||||
<x-vuexy-admin::form.input type="file" :uid="$uniqueId" model="upload_profile_photo" accept="image/*" />
|
||||
</div>
|
||||
|
||||
{{-- Contraseña --}}
|
||||
<x-vuexy-admin::form.input-password :uid="$uniqueId" model="password" icon="ti ti-lock" />
|
||||
|
||||
{{-- Roles --}}
|
||||
<x-vuexy-admin::form.select :uid="$uniqueId" model="roles" label="Roles" multiple :options="$rolesOptions" class="select2 form-select" />
|
||||
<hr>
|
||||
</x-vuexy-admin::form>
|
||||
</x-vuexy-admin::offcanvas.basic>
|
||||
</div>
|
||||
|
||||
@push('page-script')
|
||||
<script>
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const uniqueId = '{{ $uniqueId }}';
|
||||
const offcanvasId = '{{ $offcanvasId }}';
|
||||
const tagName = '{{ Str::kebab($tagName) }}';
|
||||
const myOffcanvas = document.getElementById(offcanvasId);
|
||||
|
||||
// Asegúrate de no agregar múltiples veces el listener
|
||||
const hideAndReopen = () => {
|
||||
let myOffcanvas = document.getElementById(offcanvasId);
|
||||
let offcanvasInstance = bootstrap.Offcanvas.getOrCreateInstance(myOffcanvas);
|
||||
|
||||
const onHidden = () => {
|
||||
myOffcanvas.removeEventListener('hidden.bs.offcanvas', onHidden);
|
||||
offcanvasInstance.show();
|
||||
};
|
||||
|
||||
myOffcanvas.addEventListener('hidden.bs.offcanvas', onHidden);
|
||||
offcanvasInstance.hide();
|
||||
};
|
||||
|
||||
// Inizar Select2
|
||||
const initializeSelect2 = () => {
|
||||
let rolesSelect = document.getElementById(`roles_${uniqueId}`),
|
||||
myOffcanvas = document.getElementById(offcanvasId);
|
||||
|
||||
$(rolesSelect)
|
||||
.select2({
|
||||
dropdownAutoWidth: true,
|
||||
width: '100%',
|
||||
placeholder: 'Selecciona los roles',
|
||||
dropdownParent: myOffcanvas
|
||||
})
|
||||
.on('select2:clear', () => {
|
||||
@this.roles = [];
|
||||
})
|
||||
.on('select2:select', (e) => {
|
||||
@this.roles.push(e.params.data.id);
|
||||
});
|
||||
};
|
||||
|
||||
// Inicializar el formulario
|
||||
const initializeUserForm = () => {
|
||||
setTimeout(initializeSelect2, 10);
|
||||
};
|
||||
|
||||
|
||||
// Evento para inicializar el formulario cuando se abre el offcanvas
|
||||
myOffcanvas.addEventListener('show.bs.offcanvas', function () {
|
||||
initializeUserForm();
|
||||
attachPasswordToggles();
|
||||
});
|
||||
|
||||
|
||||
// Evento para recargar el formulario
|
||||
Livewire.on('refresh-user-form', hideAndReopen);
|
||||
});
|
||||
</script>
|
||||
@endpush
|
1674
resources/views/livewire/settings/users/show.blade.php
Normal file
1674
resources/views/livewire/settings/users/show.blade.php
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,15 @@
|
||||
<div>
|
||||
<x-vuexy-admin::table.bootstrap.manager :tagName="$tagName" :datatableConfig="$bt_datatable" >
|
||||
<x-slot name="tools">
|
||||
<div class="mb-4 pr-2">
|
||||
<x-vuexy-admin::button.index-offcanvas :label="$singularName" :tagName="$tagName" />
|
||||
</div>
|
||||
</x-slot>
|
||||
</x-vuexy-admin::table.bootstrap.manager>
|
||||
</div>
|
||||
|
||||
@push('page-script')
|
||||
<script>
|
||||
window.userRoleStyles = {!! $userRoleStyles !!};
|
||||
</script>
|
||||
@endpush
|
@ -0,0 +1,60 @@
|
||||
<div class="row g-4 mb-4 text-right">
|
||||
<div class="col-sm-6 col-xl-3"></div>
|
||||
<div class="col-sm-6 col-xl-3">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-start justify-content-between">
|
||||
<div class="content-left">
|
||||
<div class="d-flex align-items-center my-2">
|
||||
<h3 class="mb-0 mx-4">{{ $enabled }}</h3>
|
||||
</div>
|
||||
<p class="mb-0">Usuarios activos</p>
|
||||
</div>
|
||||
<div class="avatar">
|
||||
<span class="avatar-initial rounded bg-label-success">
|
||||
<i class="ti ti-user-plus ti-sm"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-xl-3">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-start justify-content-between">
|
||||
<div class="content-left">
|
||||
<div class="d-flex align-items-center my-2">
|
||||
<h3 class="mb-0 mx-4">{{ $disabled }}</h3>
|
||||
</div>
|
||||
<p class="mb-0">Usuarios suspendidos</p>
|
||||
</div>
|
||||
<div class="avatar">
|
||||
<span class="avatar-initial rounded bg-label-warning">
|
||||
<i class="ti ti-user-check ti-sm"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6 col-xl-3">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-start justify-content-between">
|
||||
<div class="content-left">
|
||||
<div class="d-flex align-items-center my-2">
|
||||
<h3 class="mb-0 mx-4">{{ $total }}</h3>
|
||||
</div>
|
||||
<p class="mb-0">Total de usuarios</p>
|
||||
</div>
|
||||
<div class="avatar">
|
||||
<span class="avatar-initial rounded bg-label-primary">
|
||||
<i class="ti ti-user ti-sm"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,93 @@
|
||||
<div x-data>
|
||||
<div id="vuexy-interface-index-card" class="form-custom-listener mb-4">
|
||||
{{-- Notificaciones --}}
|
||||
<div class="notification-container pt-4" wire:ignore></div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
{{-- Tema --}}
|
||||
<x-vuexy-admin::card.basic title="Ajustes de tema" class="mb-6">
|
||||
<x-vuexy-admin::form.select :uid="$uniqueId" model="vuexy_myTheme" label="Tema" :options="['theme-default' => 'Tema predeterminado', 'theme-bordered' => 'Tema bordeado', 'theme-semi-dark' => 'Tema semi-oscuro']" />
|
||||
<x-vuexy-admin::form.select :uid="$uniqueId" model="vuexy_myStyle" label="Estilo" :options="['light' => 'Claro', 'dark' => 'Oscuro', 'system' => 'Modo del sistema']" />
|
||||
</x-vuexy-admin::card.basic>
|
||||
|
||||
{{-- Diseño --}}
|
||||
<x-vuexy-admin::card.basic title="Ajustes de diseño" class="mb-6">
|
||||
<x-vuexy-admin::form.select :uid="$uniqueId" model="vuexy_authViewMode" label="Modo de vista de autenticación" :options="['cover' => 'Pantalla completa', 'basic' => 'Básico']" />
|
||||
<x-vuexy-admin::form.select :uid="$uniqueId" model="vuexy_contentLayout" label="Ancho predeterminado" :options="['compact' => 'Compacto', 'wide' => 'Ancho completo']" />
|
||||
<x-vuexy-admin::form.checkbox :uid="$uniqueId" model="vuexy_footerFixed" label="Fijar pie de página" switch />
|
||||
</x-vuexy-admin::card.basic>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
{{-- Ajustes de menú y barra superior --}}
|
||||
<x-vuexy-admin::card.basic title="Ajustes menú y barra superior" class="mb-6">
|
||||
{{-- Diseño (Layout) --}}
|
||||
<x-vuexy-admin::form.select :uid="$uniqueId" model="vuexy_myLayout" label="Diseño de menú" :options="['vertical' => 'Vertical', 'horizontal' => 'Horizontal']" />
|
||||
{{-- Horizontal layout --}}
|
||||
<div x-show="$wire.vuexy_myLayout === 'horizontal'" x-cloak x-transition>
|
||||
<x-vuexy-admin::form.select :uid="$uniqueId" model="vuexy_headerType" label="Tipo de barra superior" :options="['static' => 'Estático', 'fixed' => 'Fijo']" />
|
||||
</div>
|
||||
{{-- Vertical layout --}}
|
||||
<div x-show="$wire.vuexy_myLayout === 'vertical'" x-cloak x-transition>
|
||||
<x-vuexy-admin::form.select :uid="$uniqueId" model="vuexy_navbarType" label="Tipo de barra de navegación" :options="['sticky' => 'Fija', 'static' => 'Estática', 'hidden' => 'Oculta']" />
|
||||
</div>
|
||||
{{-- Personalizador activo --}}
|
||||
<div x-show="$wire.vuexy_myLayout === 'horizontal'" x-cloak x-transition>
|
||||
<x-vuexy-admin::form.checkbox :uid="$uniqueId" model="vuexy_showDropdownOnHover" label="Mostrar desplegable al pasar el mouse" switch />
|
||||
</div>
|
||||
{{-- Opciones para diseño vertical --}}
|
||||
<div x-show="$wire.vuexy_myLayout === 'vertical'" x-cloak x-transition>
|
||||
<x-vuexy-admin::form.checkbox :uid="$uniqueId" model="vuexy_menuFixed" label="Menú fijo" switch />
|
||||
<x-vuexy-admin::form.checkbox :uid="$uniqueId" model="vuexy_menuCollapsed" label="Menú colapsado" switch />
|
||||
</div>
|
||||
</x-vuexy-admin::card.basic>
|
||||
|
||||
{{-- Atajos --}}
|
||||
<div x-show="$wire.vuexy_myLayout === 'horizontal' || $wire.vuexy_navbarType !== 'hidden'" x-cloak x-transition>
|
||||
<x-vuexy-admin::card.basic title="Atajos" class="mb-6">
|
||||
<x-vuexy-admin::form.input type="number" :uid="$uniqueId" model="vuexy_maxQuickLinks" label="Máximo de enlaces rápidos" min="2" max="20" helperText="Selecciona un valor entre 2 y 20." />
|
||||
</x-vuexy-admin::card.basic>
|
||||
</div>
|
||||
|
||||
{{-- Personalizador de plantilla --}}
|
||||
<x-vuexy-admin::card.basic title="Personalizador de plantilla" class="mb-6">
|
||||
<x-vuexy-admin::form.checkbox :uid="$uniqueId" model="vuexy_hasCustomizer" label="Habilitar personalizador de plantilla" switch />
|
||||
<div x-show="$wire.vuexy_hasCustomizer" x-cloak x-transition>
|
||||
<x-vuexy-admin::form.checkbox :uid="$uniqueId" model="vuexy_displayCustomizer" label="Mostrar personalizador de plantilla" switch />
|
||||
</div>
|
||||
</x-vuexy-admin::card.basic>
|
||||
</div>
|
||||
</div>
|
||||
{{-- Acciones --}}
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-end">
|
||||
<x-vuexy-admin::button.basic wire:click="save" disabled variant="primary" icon="ti ti-check" label="Aplicar cambios" class="btn-save mb-2 mx-2" size="sm" waves />
|
||||
<x-vuexy-admin::button.basic wire:click="loadForm" disabled variant="secondary" icon="ti ti-rotate-2" label="Cancelar" class="btn-cancel mb-2 mx-2" size="sm" waves />
|
||||
</div>
|
||||
<div class="col-lg-12 text-end">
|
||||
<x-vuexy-admin::button.basic wire:click="clearCustomConfig" variant="success" icon="ti ti-adjustments-cog" label="Restaurar valores predeterminados" class="btn-reset mb-2 mx-2" size="sm" waves />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@push('page-script')
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
Livewire.on('refreshAndNotify', event => {
|
||||
const notification = {
|
||||
type: event.type || 'success',
|
||||
message: event.message || 'Configuraciones guardadas exitosamente.',
|
||||
target: event.target || '#vuexy-interface-index-card .notification-container',
|
||||
delay: event.delay || 6000
|
||||
};
|
||||
|
||||
// Guardar notificación en localStorage
|
||||
localStorage.setItem('vuexy_notification', JSON.stringify(notification));
|
||||
|
||||
// Refrescar la página
|
||||
window.location.reload();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@endpush
|
@ -0,0 +1,41 @@
|
||||
<div>
|
||||
<div id="app-description-card-card" class="form-custom-listener mb-4">
|
||||
<x-vuexy-admin::card.basic title="Datos de la aplicación" class="mb-4">
|
||||
<x-vuexy-admin::form.input
|
||||
label="Titulo de la aplicación"
|
||||
model="app_name"
|
||||
placeholder="Nombre corto" />
|
||||
<x-vuexy-admin::form.input
|
||||
label="Titulo del sitio"
|
||||
model="title"
|
||||
placeholder="Titulo del sitio" />
|
||||
<x-vuexy-admin::form.textarea
|
||||
label="Descripción del sitio"
|
||||
model="description"
|
||||
placeholder="Descripción del sitio" />
|
||||
</x-vuexy-admin::card.basic>
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-end">
|
||||
<x-vuexy-admin::button.basic
|
||||
variant="primary"
|
||||
size="sm"
|
||||
icon="ti ti-device-floppy"
|
||||
label="Guardar cambios"
|
||||
disabled
|
||||
wire:click="save"
|
||||
class="btn-save"
|
||||
waves />
|
||||
<x-vuexy-admin::button.basic
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
icon="ti ti-rotate-2"
|
||||
label="Cancelar"
|
||||
disabled
|
||||
wire:click="loadForm"
|
||||
class="btn-cancel"
|
||||
waves />
|
||||
</div>
|
||||
</div>
|
||||
<div class="notification-container pt-4" wire:ignore></div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,84 @@
|
||||
<div>
|
||||
<div id="app-favicon-card-card" class="mb-4">
|
||||
<x-vuexy-admin::card.basic title="Favicon" class="mb-2">
|
||||
<x-vuexy-admin::form.input
|
||||
type="file"
|
||||
label="Icono de navegador"
|
||||
model="upload_image_favicon"
|
||||
accept="image/*" />
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-6">
|
||||
<div class="text-center flex flex-col items-center">
|
||||
<div class="mb-3 text-center d-flex flex-column align-items-center">
|
||||
<div class="image-wrapper-16x16 d-flex justify-content-center align-items-center">
|
||||
<img src="{{ $upload_image_favicon ? $upload_image_favicon->temporaryUrl() : asset('storage/' . $admin_favicon_16x16) }}">
|
||||
</div>
|
||||
<span class="text-muted mt-1">Navegadores web (16x16)</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center flex flex-col items-center">
|
||||
<div class="mb-3 text-center d-flex flex-column align-items-center">
|
||||
<div class="image-wrapper-76x76 d-flex justify-content-center align-items-center">
|
||||
<img src="{{ $upload_image_favicon ? $upload_image_favicon->temporaryUrl() : asset('storage/' . $admin_favicon_76x76) }}">
|
||||
</div>
|
||||
<span class="text-muted mt-1">iPad sin Retina (76x76)</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center flex flex-col items-center">
|
||||
<div class="mb-3 text-center d-flex flex-column align-items-center">
|
||||
<div class="image-wrapper-120x120 d-flex justify-content-center align-items-center">
|
||||
<img src="{{ $upload_image_favicon ? $upload_image_favicon->temporaryUrl() : asset('storage/' . $admin_favicon_120x120) }}">
|
||||
</div>
|
||||
<span class="text-muted mt-1">iPhone (120x120)</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center flex flex-col items-center">
|
||||
<div class="mb-3 text-center d-flex flex-column align-items-center">
|
||||
<div class="image-wrapper-152x152 d-flex justify-content-center align-items-center">
|
||||
<img src="{{ $upload_image_favicon ? $upload_image_favicon->temporaryUrl() : asset('storage/' . $admin_favicon_152x152) }}">
|
||||
</div>
|
||||
<span class="text-muted mt-1">iPad (152x152)</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center flex flex-col items-center">
|
||||
<div class="mb-3 text-center d-flex flex-column align-items-center">
|
||||
<div class="image-wrapper-180x180 d-flex justify-content-center align-items-center">
|
||||
<img src="{{ $upload_image_favicon ? $upload_image_favicon->temporaryUrl() : asset('storage/' . $admin_favicon_180x180) }}">
|
||||
</div>
|
||||
<span class="text-muted mt-1">iPhone con Retina HD (180x180)</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-center flex flex-col items-center">
|
||||
<div class="mb-3 text-center d-flex flex-column align-items-center">
|
||||
<div class="image-wrapper-192x192 d-flex justify-content-center align-items-center">
|
||||
<img src="{{ $upload_image_favicon ? $upload_image_favicon->temporaryUrl() : asset('storage/' . $admin_favicon_192x192) }}">
|
||||
</div>
|
||||
<span class="text-muted mt-1">Android y otros dispositivos móviles (192x192)</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</x-vuexy-admin::card.basic>
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-end">
|
||||
<x-vuexy-admin::button.basic
|
||||
variant="primary"
|
||||
size="sm"
|
||||
icon="ti ti-device-floppy"
|
||||
label="Guardar cambios"
|
||||
wire:click="save"
|
||||
:disabled="$upload_image_favicon === null"
|
||||
class="btn-save mt-2 mr-2"
|
||||
waves />
|
||||
<x-vuexy-admin::button.basic
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
icon="ti ti-rotate-2"
|
||||
label="Cancelar"
|
||||
wire:click="loadForm"
|
||||
:disabled="$upload_image_favicon === null"
|
||||
class="btn-cancel mt-2 mr-2"
|
||||
waves />
|
||||
</div>
|
||||
</div>
|
||||
<div class="notification-container pt-4" wire:ignore></div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,39 @@
|
||||
<div>
|
||||
<div id="logo-on-dark-bg-card-card" class="mb-4">
|
||||
<x-vuexy-admin::card.basic title="Logotipo sobre fondo oscuro" class="mb-2">
|
||||
<x-vuexy-admin::form.input
|
||||
type="file"
|
||||
label="Logotipo sobre fondo oscuro"
|
||||
model="upload_image_logo_dark"
|
||||
accept="image/*" />
|
||||
<div class="mb-3 text-center align-items-center">
|
||||
<div class="justify-content-center align-items-center bg-slate-800 p-4">
|
||||
<img src="{{ $upload_image_logo_dark ? $upload_image_logo_dark->temporaryUrl() : asset('storage/' . $admin_image_logo_dark) }}">
|
||||
</div>
|
||||
</div>
|
||||
</x-vuexy-admin::card.basic>
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-end">
|
||||
<x-vuexy-admin::button.basic
|
||||
variant="primary"
|
||||
size="sm"
|
||||
icon="ti ti-device-floppy"
|
||||
disabled="{{ $upload_image_logo_dark === null }}"
|
||||
label="Guardar cambios"
|
||||
wire:click="save"
|
||||
class="btn-save mt-2 mr-2"
|
||||
waves />
|
||||
<x-vuexy-admin::button.basic
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
icon="ti ti-rotate-2"
|
||||
disabled="{{ $upload_image_logo_dark === null }}"
|
||||
label="Cancelar"
|
||||
wire:click="loadForm"
|
||||
class="btn-cancel mt-2 mr-2"
|
||||
waves />
|
||||
</div>
|
||||
</div>
|
||||
<div class="notification-container pt-4" wire:ignore></div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,39 @@
|
||||
<div>
|
||||
<div id="logo-on-light-bg-card-card" class="mb-4">
|
||||
<x-vuexy-admin::card.basic title="Logotipo sobre fondo claro" class="mb-2">
|
||||
<x-vuexy-admin::form.input
|
||||
type="file"
|
||||
label="Logotipo sobre fondo claro"
|
||||
model="upload_image_logo"
|
||||
accept="image/*" />
|
||||
<div class="mb-3 text-center align-items-center">
|
||||
<div class="justify-content-center align-items-center bg-slate-100 p-4">
|
||||
<img src="{{ $upload_image_logo ? $upload_image_logo->temporaryUrl() : asset('storage/' . $admin_image_logo) }}">
|
||||
</div>
|
||||
</div>
|
||||
</x-vuexy-admin::card.basic>
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-end">
|
||||
<x-vuexy-admin::button.basic
|
||||
variant="primary"
|
||||
size="sm"
|
||||
icon="ti ti-device-floppy"
|
||||
disabled="{{ $upload_image_logo === null }}"
|
||||
label="Guardar cambios"
|
||||
wire:click="save"
|
||||
class="btn-save mt-2 mr-2"
|
||||
waves />
|
||||
<x-vuexy-admin::button.basic
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
icon="ti ti-rotate-2"
|
||||
disabled="{{ $upload_image_logo === null }}"
|
||||
label="Cancelar"
|
||||
wire:click="loadForm"
|
||||
class="btn-cancel mt-2 mr-2"
|
||||
waves />
|
||||
</div>
|
||||
</div>
|
||||
<div class="notification-container pt-4" wire:ignore></div>
|
||||
</div>
|
||||
</div>
|
Reference in New Issue
Block a user