Prepare component

This commit is contained in:
Arturo Corro 2025-05-30 01:07:33 -06:00
parent 3916c62935
commit cac9a5b121
263 changed files with 14456 additions and 1072 deletions

View File

@ -3,8 +3,8 @@ root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
indent_size = 4
insert_final_newline = true
trim_trailing_whitespace = true
@ -14,5 +14,8 @@ trim_trailing_whitespace = false
[*.{yml,yaml}]
indent_size = 2
[*.{js,json,ts,vue}]
indent_size = 2
[docker-compose.yml]
indent_size = 4

56
.gitattributes vendored
View File

@ -1,24 +1,40 @@
# Normaliza los saltos de línea en diferentes SO
# Normaliza los saltos de línea para todos los sistemas operativos
* text=auto eol=lf
# Reglas para archivos específicos
# Reglas de diferencia por tipo de archivo
*.blade.php diff=html
*.css diff=css
*.html diff=html
*.md diff=markdown
*.php diff=php
*.css diff=css
*.html diff=html
*.js diff=javascript
*.ts diff=typescript
*.vue diff=html
*.md diff=markdown
*.php diff=php
*.json diff=json
*.yml diff=yaml
*.yaml diff=yaml
*.stub diff=php
# Evitar que estos archivos se exporten con Composer create-project
/.github export-ignore
/.gitignore export-ignore
/.git export-ignore
.gitattributes export-ignore
.editorconfig export-ignore
.prettierrc.json export-ignore
.prettierignore export-ignore
.eslintrc.json export-ignore
CHANGELOG.md export-ignore
CONTRIBUTING.md export-ignore
README.md export-ignore
composer.lock export-ignore
package-lock.json export-ignore
# Archivos que NO deben exportarse con Composer create-project
/.github export-ignore
/.gitignore export-ignore
/.git export-ignore
.gitattributes export-ignore
.editorconfig export-ignore
.prettierrc.json export-ignore
.prettierignore export-ignore
.eslintrc.json export-ignore
CHANGELOG.md export-ignore
CONTRIBUTING.md export-ignore
README.md export-ignore
phpunit.xml export-ignore
phpunit.xml.dist export-ignore
composer.lock export-ignore
package-lock.json export-ignore
vite.config.js export-ignore
tailwind.config.js export-ignore
webpack.mix.js export-ignore
tests/ export-ignore
resources/assets/ export-ignore
resources/sass/ export-ignore
node_modules export-ignore

25
.github/CODEOWNERS vendored Normal file
View File

@ -0,0 +1,25 @@
# CODEOWNERS para koneko/laravel-vuexy-admin
# Asignar todos los archivos a Arturo Corro Pacheco (mantenedor principal)
* @koneko-mx
# Archivos legales y de documentación
/LICENSE* @koneko-mx
/NOTICE.md @koneko-mx
/README* @koneko-mx
/CHANGELOG* @koneko-mx
/.github/SECURITY.md @koneko-mx
/.github/CODE_OF_CONDUCT.md @koneko-mx
/.github/ISSUE_TEMPLATE/ @koneko-mx
/.github/PULL_REQUEST_TEMPLATE.md @koneko-mx
# Código principal
/src/ @koneko-mx
/config/ @koneko-mx
/resources/ @koneko-mx
/routes/ @koneko-mx
/tests/ @koneko-mx
# Archivos del paquete
/composer.json @koneko-mx
/package.json @koneko-mx

24
.github/CODE_OF_CONDUCT.md vendored Normal file
View File

@ -0,0 +1,24 @@
# Código de Conducta de Contribuyentes
Como participantes y colaboradores de este proyecto, nos comprometemos a fomentar una comunidad abierta, inclusiva, y respetuosa.
## Comportamiento Esperado
- Usar un lenguaje amable e inclusivo.
- Respetar diferentes puntos de vista y experiencias.
- Aceptar con gracia las críticas constructivas.
- Enfocarse en lo que es mejor para la comunidad.
## Comportamiento Inaceptable
- Uso de lenguaje ofensivo o insultante.
- Conducta de acoso en público o privado.
- Comentarios despectivos relacionados con género, raza, orientación, religión, discapacidad o condición médica.
## Aplicación
Las violaciones a este código pueden ser reportadas a: **arturo@koneko.mx**
Nos reservamos el derecho de advertir, suspender o expulsar a cualquier contribuyente que no respete este código.
Inspirado en el [Contributor Covenant](https://www.contributor-covenant.org/)

10
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,10 @@
---
name: "FUNDING.yml"
about: "Opciones de patrocinio del proyecto"
title: "Patrocinio"
labels: [funding]
assignees: []
---
Opciones de patrocinio del proyecto

30
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,30 @@
---
name: "🐛 Bug Report"
about: Reporta un error, fallo o comportamiento inesperado.
title: "[BUG] "
labels: [bug]
assignees: []
---
## Descripción
Describe claramente el problema.
## Pasos para reproducir
1. Ir a '...'
2. Hacer clic en '...'
3. Ver error '...'
## Comportamiento esperado
Una descripción clara y concisa de lo que debería pasar.
## Capturas de pantalla
(Si aplica, añade imágenes para ayudar a explicar tu problema.)
## Entorno
- Versión de Laravel:
- Versión del componente:
- Navegador / Sistema operativo:
## Información adicional
Agrega cualquier otro dato que consideres relevante.

View File

@ -0,0 +1,51 @@
---
name: "🧩 Feature Request"
about: Proponer una nueva funcionalidad o mejora para el sistema
title: "[Feature] "
labels: ["feature", "enhancement"]
assignees: []
---
## 📌 Descripción
Por favor, proporciona una descripción clara y concisa de la funcionalidad que deseas agregar.
---
## 🤔 Motivación
¿Cuál es el problema que esta nueva funcionalidad resolverá o qué mejora ofrecerá?
---
## 🧩 Solución Propuesta
Describe cómo debería funcionar la nueva característica. Si tienes una idea de la implementación técnica, inclúyela.
---
## 🛠️ Requisitos Técnicos (opcional)
- ¿Requiere cambios en base de datos?
- ¿Afecta al rendimiento?
- ¿Involucra cambios en la UI o API?
- ¿Es compatible con la versión actual del sistema?
---
## 💡 Alternativas consideradas
Si evaluaste otras soluciones, por favor menciónalas y explica por qué las descartaste.
---
## 📎 Recursos adicionales
Agrega enlaces, capturas de pantalla o documentación que respalden tu solicitud.
---
## 👤 Autor(a)
- GitHub: @<tu-usuario>

55
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,55 @@
# 📝 Pull Request
Gracias por tu contribución a **Koneko Laravel Vuexy Admin**.
Por favor, completa la siguiente información para ayudarnos a revisar tu PR.
---
## 📋 Descripción
<!-- Explica brevemente qué problema resuelve este PR o qué funcionalidad agrega -->
---
## 🚀 Cambios realizados
- [ ] Bugfix 🐞
- [ ] Nueva característica ✨
- [ ] Mejora/refactorización 🔧
- [ ] Documentación 📚
- [ ] Tests 🧪
- [ ] Otro (especificar):
---
## ✅ Checklist
- [ ] He probado los cambios localmente
- [ ] He ejecutado las migraciones correctamente (si aplica)
- [ ] No he incluido datos sensibles ni secretos
- [ ] Los tests existentes no fallan
- [ ] He actualizado documentación relevante (si aplica)
- [ ] Incluye etiquetas útiles (`good first issue`, `bug`, `enhancement`, etc.)
---
## 📎 Referencias
<!-- Indica si este PR está relacionado a algún issue o tarea -->
Closes #
---
## 🌍 Idioma base
- [ ] Español 🇲🇽
- [ ] Inglés 🌐
- [ ] Ambos
---
## 👤 Autor(a)
- GitHub: @<tu-usuario>
- Nombre opcional:

11
.github/SECURITY.md vendored Normal file
View File

@ -0,0 +1,11 @@
# Reporte de Vulnerabilidades de Seguridad
Agradecemos el interés por ayudarnos a mantener este proyecto seguro.
Si encuentras una vulnerabilidad de seguridad, por favor repórtala de manera responsable enviando un correo a:
**arturo@koneko.mx**
No abras un issue público hasta que hayamos tenido tiempo de analizar el reporte y preparar una solución.
Gracias por apoyar la seguridad del ecosistema Koneko ERP.

68
.gitignore vendored
View File

@ -1,10 +1,60 @@
/node_modules
/vendor
/.vscode
/.nova
/.fleet
/.phpactor.json
# ⚙️ Laravel Package Defaults
/vendor/
composer.lock
# 🧪 PHPUnit
.phpunit.result.cache
/.phpunit.cache
/.phpunit.result.cache
/.zed
/.idea
phpunit.xml
phpunit.xml.dist
# 🧹 Cache y logs
/.cache
/storage/*.key
/storage/pail
*.log
*.dump
*.bak
*.tmp
*.swp
# 🔐 Entornos y configuraciones
.env
.env.*
auth.json
.phpactor.json
.php-cs-fixer.cache
phpstan.neon.local
homestead.yaml
Homestead.json
# 🧱 Compilación frontend (Vite, Mix, Webpack, Tailwind)
/node_modules/
node_modules
public/build/
public/hot/
public/storage/
.vite
# 🧪 Tests y mocks (solo si generas temporalmente)
/coverage/
*.test.*
*.spec.*
# 🛠️ IDEs y herramientas de desarrollo
/.idea/
/.vscode/
/.nova/
/.zed/
/.fleet/
*.sublime-workspace
*.sublime-project
# 📦 Archivos del sistema
.DS_Store
Thumbs.db
# 🚀 Entornos de staging / producción
*.local.*
*.production.*
*.staging.*

View File

@ -1,39 +1,39 @@
# 📜 CHANGELOG - Laravel Vuexy Website Admin
# 📦 CHANGELOG
Este documento sigue el formato [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## [0.1.0] - ALPHA - 2024-03-05
### ✨ Added (Agregado)
- 🚀 Primera versión alpha de la librería.
- 🔹 Implementación inicial de [funcionalidad clave 1].
- 🔹 Integración con [dependencia o servicio principal].
- 🔹 Soporte para [Laravel/Vuexy Admin, si aplica].
### 🛠 Changed (Modificado)
- 🔄 Optimización de [código o estructura interna].
### 🐛 Fixed (Correcciones)
- 🐞 Correcciones iniciales en [migraciones, modelos, servicios, etc.].
Todos los cambios importantes de este proyecto se documentarán en este archivo.
Este proyecto sigue [Semantic Versioning](https://semver.org/lang/es/).
---
## 📅 Próximos Cambios Planeados
- 📊 **Mejoras en [feature futuro]**.
- 🏪 **Compatibilidad con [Laravel 11, Vuexy, etc.]**.
- 📍 **Integración con [API o funcionalidad esperada]**.
## 🧪 Versión en desarrollo (`dev-develop`)
Este módulo está en desarrollo activo. No se ha publicado una versión estable ni beta formal.
**Añadido**
- Registro de contenidos dinámicos en `website_contents`
- Sistema de perfiles SEO (`website_seo_profiles`) con soporte para JSON-LD, Open Graph y Twitter
- Menús públicos dinámicos (`website_menus`)
- Control de visibilidad por rol, flag, permisos y autenticación
- Soporte para múltiples sitios (`multi-site`) y variantes de página
- Soporte para `hreflang`, `manifest.json`, y sitemap
- Integración con módulos `vuexy-admin` y layouts frontales vía `template`, `variant`, `render_mode`
**Notas**
- Esta versión no es estable y está sujeta a cambios mayores.
- Compatibilidad mínima: Laravel 11.31, PHP 8.2
- Requiere `laravel-vuexy-admin` (`dev-develop`)
---
**📌 Nota:** Esta es una versión **ALPHA**, aún en desarrollo.
## 🚀 Planeación de versiones
- `1.0.0-beta`: Publicación de la versión beta inicial con funcionalidades completas del CMS
- `1.0.0`: Versión estable para producción
---
## 🔄 Sincronización de Cambios
Este `CHANGELOG.md` se actualiza primero en nuestro repositorio principal en **[Tea - Koneko Git](https://git.koneko.mx/koneko/laravel-vuexy-website-admin)** y luego se refleja en GitHub.
Los cambios recientes pueden verse antes en **Tea** que en **GitHub** debido a la sincronización automática.
---
📅 Última actualización: **2024-03-05**.
## 📁 Histórico
*Ninguna versión publicada aún.*

View File

@ -1,9 +1,77 @@
## 🔐 Acceso al Repositorio Privado
# 🤝 Guía para Contribuidores
Nuestro servidor Git en **Tea** tiene un registro cerrado. Para contribuir:
¡Gracias por tu interés en colaborar con **Koneko ERP**!
Este proyecto busca ofrecer una suite profesional de administración web y ERP orientado al mercado mexicano y LATAM, bajo licencia **Business Source License 1.1** con transición futura a MIT.
1. Abre un **Issue** en [GitHub](https://github.com/koneko-mx/laravel-vuexy-website-admin/issues) indicando tu interés en contribuir.
2. Alternativamente, envía un correo a **contacto@koneko.mx** solicitando acceso.
3. Una vez aprobado, recibirás una invitación para registrarte y clonar el repositorio.
---
Si solo necesitas acceso de lectura, puedes clonar la versión pública en **GitHub**.
## 📌 Requisitos básicos
* Conocimiento de **PHP 8.2+** y **Laravel 11**
* Respeto por las buenas prácticas, código limpio y trabajo en equipo
* Preferentemente, experiencia en:
* Livewire
* Spatie Permissions & Roles
* Laravel Fortify y Sanctum
* Desarrollo modular con Composer
---
## 🌱 Primeros pasos
1. **Forkea** este repositorio y clónalo localmente.
2. Instala las dependencias con Composer:
```bash
composer install
```
3. Copia el archivo `.env.example` a `.env` y ajusta tus credenciales locales:
```bash
cp .env.example .env
php artisan key:generate
```
4. Ejecuta las migraciones y seeders (si aplica):
```bash
php artisan migrate --seed
```
5. Inicia el servidor:
```bash
php artisan serve
```
---
## 📀 Convenciones del Proyecto
Antes de contribuir, asegúrate de leer nuestras
📁 [Convenciones de Componentes](CONVENTIONS.md),
donde definimos estructura de carpetas, estilo de código y otras buenas prácticas clave para mantener la consistencia del ecosistema **Koneko ERP**.
---
## 📝 Código de Conducta
Consulta nuestro [Código de Conducta](CODE_OF_CONDUCT.md) para conocer las expectativas y reglas que garantizan un ambiente colaborativo, profesional y respetuoso.
---
## 🚀 ¡Listo para colaborar!
Una vez que tengas tu entorno configurado:
* Busca issues etiquetados como `good first issue` o `help wanted`
* Lee el archivo [`CONTRIBUTING.md`](CONTRIBUTING.md) del módulo específico si estás trabajando en un subpaquete
* No olvides seguir las convenciones de estilo PSR-12 y usar `php-cs-fixer` si lo tienes disponible
---
Gracias por ser parte de **Koneko ERP** 💙
¡Esperamos tu contribución!

105
CONVENTIONS.md Normal file
View File

@ -0,0 +1,105 @@
# ![Koneko ERP](https://git.koneko.mx/koneko-st/koneko-st/raw/branch/main/logo-images/horizontal-05.png) Convenciones de Estructura de Componentes
📅 *Última actualización:* 2025-04-03
🔧 *Aplicable a todos los módulos Composer de Koneko ERP*
---
## 📁 Estructura General de un Componente
```plaintext
component-root/
├── config/ ← Configuraciones del módulo
├── Database/
│ ├── data/ ← Archivos JSON, CSV, XLSX
│ ├── factories/ ← Factories para testing y seeders
│ ├── migrations/ ← Migraciones del esquema del módulo
│ └── Seeders/ ← Seeders base y de datos fake
├── Enums/ ← Enums (PSR-4) usados por el módulo
├── Events/ ← Eventos del módulo
├── Http/
│ ├── Controllers/ ← Controladores
│ └── Middleware/ ← Middlewares específicos del módulo
├── Livewire/ ← Componentes Livewire organizados por dominio
├── Models/ ← Modelos Eloquent
├── Notifications/ ← Notificaciones personalizadas
├── Providers/ ← Service Providers del módulo
├── Services/ ← Servicios (lógica de negocio)
├── Support/
│ ├── Base/ ← Clases base abstractas
│ ├── Builders/ ← Configuradores de vistas tipo índice
│ ├── Macros/ ← Macros de Str, Collection, etc.
│ ├── Queries/ ← Query Builders avanzados
│ ├── Registries/ ← Registro dinámico de configuración
│ └── Validation/ ← Validaciones personalizadas
├── Traits/
│ ├── Audit/ ← Traits para auditoría y tracking
│ ├── Metadata/ ← Traits para metadatos del modelo
│ ├── Users/ ← Traits relacionados con usuarios
│ └── Indexing/ ← Traits usados por configuradores de índices
├── resources/
│ ├── assets/ ← JS, SCSS, íconos o fuentes específicos
│ ├── faker-images/ ← Imágenes utilizadas en datos de prueba
│ ├── lang/ ← Archivos de traducción
│ └── views/ ← Vistas Blade
├── routes/
│ └── admin.php ← Rutas internas del módulo
├── storage/ ← Recursos adicionales (ej. fuentes)
└── README.md ← Documentación del componente
```
---
## 🧠 Convenciones Generales
- Todos los módulos deben seguir PSR-4.
- Los archivos deben nombrarse en *PascalCase* excepto `config/*.php` y rutas.
- Los `Seeder` deben ser agrupados por módulo si el componente los agrupa (ej. `vuexyAdmin`, `vuexyWarehouse`).
- Los `Factory` deben ser compatibles con `SeederWithFakeImages`.
---
## 🖼️ Imágenes Faker
- Carpeta: `resources/faker-images/<dominio>`
- Subcarpetas válidas: `users/`, `stores/`, `products/`, etc.
- Las imágenes se usan exclusivamente para entornos de testing/demostración.
- Nunca se publican al frontend ni se exponen directamente.
---
## 🧪 Factories
- Todas las `factories` deben estar en `Database/factories/`.
- Si se extiende un modelo (`Koneko\VuexyAdmin\Models\User`), usar `new (User::class)` dinámico.
- Compatible con `SeederOrchestrator` y `config/seeder.php`.
---
## 📊 Configuradores de Índice
- Los index deben implementar `BaseModelIndexConfig` o su extensión.
- Pueden usar Traits como `HandlesFactory`, `HandlesIndexColumns`, `HandlesQueryBuilder`, etc.
- Se recomienda usar `Support/Builders/` para los configuradores y `Support/Registries/` si son extendibles.
---
## 📚 Traducciones
- Usar `resources/lang/es/` con archivos separados por dominio (`auth.php`, `validation.php`, etc.).
- `es_MX.json` puede usarse para traducciones inline.
---
## 📌 Tips
- Si un componente tiene `Service`, `Seeder`, `Factory` y `Livewire`, deben estar todos organizados en sus carpetas respectivas.
- La estructura del componente debe ser lo suficientemente clara para no depender de documentación externa.
---
## 🤝 ¿Dudas o sugerencias?
Este documento está en constante mejora. Si tienes sugerencias o deseas proponer mejoras, por favor abre un [issue de tipo mejora](.github/ISSUE_TEMPLATE/feature_request.md) o contribuye con un Pull Request.
---

View File

@ -1,19 +0,0 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Http\Controllers;
use App\Http\Controllers\Controller;
class ChatController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
return view('vuexy-website-admin::chat.index');
}
}

View File

@ -1,19 +0,0 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Http\Controllers;
use App\Http\Controllers\Controller;
class ContactFormController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
return view('vuexy-website-admin::contact-form.index');
}
}

View File

@ -1,19 +0,0 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Http\Controllers;
use App\Http\Controllers\Controller;
class ContactInfoController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
return view('vuexy-website-admin::contact-info.index');
}
}

View File

@ -1,19 +0,0 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Http\Controllers;
use App\Http\Controllers\Controller;
class FaqController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
return view('vuexy-website-admin::faq.index');
}
}

View File

@ -1,19 +0,0 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Http\Controllers;
use App\Http\Controllers\Controller;
class GoogleAnalyticsController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
return view('vuexy-website-admin::google-analytics.index');
}
}

View File

@ -1,19 +0,0 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Http\Controllers;
use App\Http\Controllers\Controller;
class ImagesController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
return view('vuexy-website-admin::images.index');
}
}

View File

@ -1,19 +0,0 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Http\Controllers;
use App\Http\Controllers\Controller;
class LegalNoticesController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
return view('vuexy-website-admin::legal-notices.index');
}
}

View File

@ -1,19 +0,0 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Http\Controllers;
use App\Http\Controllers\Controller;
class SitemapController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
return view('vuexy-website-admin::sitemap-manager.index');
}
}

View File

@ -1,19 +0,0 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Http\Controllers;
use App\Http\Controllers\Controller;
class SocialMediaController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
return view('vuexy-website-admin::social-media.index');
}
}

View File

@ -1,19 +0,0 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Http\Controllers;
use App\Http\Controllers\Controller;
class VuexyWebsiteAdminController extends Controller
{
/**
* Display a listing of the resource.
*
* @return \Illuminate\Http\Response
*/
public function index()
{
return view('vuexy-website-admin::general-settings.index');
}
}

73
LICENSE
View File

@ -1,9 +1,74 @@
Business Source License 1.1 (Koneko Custom Edition)
Licensor: Koneko Soluciones Tecnológicas
Licensed Work: laravel-vuexy-admin
License Effective Date: 2025-05-29
Change Date: 2028-05-29 (3 years after the Effective Date)
---
## 1. Definitions
**"Licensor"** refers to Koneko Soluciones Tecnológicas, represented legally by Arturo Corro Pacheco (RFC: COPA810622V65).
**"Licensed Work"** refers to the source code of the repository `koneko/laravel-vuexy-admin` hosted at [https://github.com/koneko-mx](https://github.com/koneko-mx) and [https://git.koneko.mx](https://git.koneko.mx).
**"Change Date"** is the date on which this license automatically transitions to the MIT license.
**"Use"**, **"Commercial Use"**, and other terms are interpreted according to common software licensing practices.
---
## 2. Usage Permissions
This software is provided under the Business Source License 1.1 with the following additional conditions:
* **Personal, Educational, Community, and Internal Development Use**: ALLOWED without restrictions.
* **Commercial Deployment**: ALLOWED ONLY under an active commercial license or a specific agreement with the Licensor.
* **Profit-oriented Projects (clients, product sales, SaaS, services)**: REQUIRE a commercial license.
* **Redistribution as part of a commercial product or automated service**: REQUIRES a commercial license.
---
## 3. Automatic Transition to MIT License
On the **Change Date**, this license automatically transitions to the standard MIT License:
```
MIT License
Copyright (c) 2025 Koneko Soluciones Tecnológicas
Permission is hereby granted, free of charge, to any person obtaining a copy...
```
Copyright (c) 2025 koneko
---
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
## 4. Contact and Commercial Licensing
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
For commercial licenses, partnerships, contributions, or specific agreements:
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
**Official Email:** [opensource@koneko.mx](mailto:opensource@koneko.mx)
**Website:** [https://koneko.mx](https://koneko.mx) / [https://erp.koneko.mx](https://erp.koneko.mx)
---
## 5. Important Disclaimers
* This project integrates the **Vuexy template**, which is a paid product. A **valid Themeforest license** is required to legally use it in production.
* This project does NOT distribute the template, it only facilitates its integration.
* The licensee is responsible for complying with the terms of use of said template and other third-party dependencies.
---
## 6. Disclaimer of Warranty
This software is provided "AS IS", without any warranty. The Licensor is not liable for any direct or indirect damages resulting from the use of this software.
---
## 7. Contributions
Contributions to this repository must follow the policies defined in `CONTRIBUTING.md`. By submitting code, you agree to license it under the same terms of this license.
---
Copyright (c) 2025 - Koneko Soluciones Tecnológicas

74
LICENSE.es.md Normal file
View File

@ -0,0 +1,74 @@
Licencia Business Source 1.1 (Edición Personalizada de Koneko)
Licenciante: Koneko Soluciones Tecnológicas
Trabajo Licenciado: laravel-vuexy-admin
Fecha de Entrada en Vigencia de la Licencia: 2025-05-29
Fecha de Cambio: 2028-05-29 (3 años después de la fecha de vigencia)
---
## 1. Definiciones
**"Licenciante"** se refiere a Koneko Soluciones Tecnológicas, representada legalmente por Arturo Corro Pacheco (RFC: COPA810622V65).
**"Trabajo Licenciado"** se refiere al código fuente del repositorio `koneko/laravel-vuexy-admin` alojado en [https://github.com/koneko-mx](https://github.com/koneko-mx) y [https://git.koneko.mx](https://git.koneko.mx).
**"Fecha de Cambio"** es la fecha en la que esta licencia se convierte automáticamente en la licencia MIT.
**"Uso"**, **"Uso Comercial"** y otros términos se interpretan conforme a las prácticas comunes en licenciamiento de software.
---
## 2. Permisos de Uso
Este software se proporciona bajo la Licencia Business Source 1.1 con las siguientes condiciones adicionales:
* **Uso Personal, Educativo, Comunitario o de Desarrollo Interno**: PERMITIDO sin restricciones.
* **Implementación Comercial**: PERMITIDO SOLO bajo una licencia comercial activa o un acuerdo específico con el Licenciante.
* **Proyectos con Fines de Lucro (clientes, ventas de productos, SaaS, servicios)**: REQUIEREN una licencia comercial.
* **Redistribución como parte de un producto comercial o servicio automatizado**: REQUIERE una licencia comercial.
---
## 3. Transición Automática a Licencia MIT
En la **Fecha de Cambio**, esta licencia se convierte automáticamente en la Licencia MIT estándar:
```
Licencia MIT
Copyright (c) 2025 Koneko Soluciones Tecnológicas
Se concede permiso, sin cargo, a cualquier persona que obtenga una copia...
```
---
## 4. Contacto y Licenciamiento Comercial
Para licencias comerciales, asociaciones, contribuciones o acuerdos específicos:
**Correo Oficial:** [opensource@koneko.mx](mailto:opensource@koneko.mx)
**Sitio Web:** [https://koneko.mx](https://koneko.mx) / [https://erp.koneko.mx](https://erp.koneko.mx)
---
## 5. Avisos Importantes
* Este proyecto integra el **template Vuexy**, que es un producto de pago. Se requiere una **licencia válida de Themeforest** para utilizarlo legalmente en producción.
* Este proyecto NO distribuye dicho template, solo facilita su integración.
* El licenciatario es responsable de cumplir con los términos de uso de dicho template y otras dependencias de terceros.
---
## 6. Renuncia de Garantía
Este software se proporciona "TAL CUAL", sin garantía de ningún tipo. El Licenciante no se hace responsable de ningún daño directo o indirecto derivado del uso de este software.
---
## 7. Contribuciones
Las contribuciones a este repositorio deben seguir las políticas definidas en `CONTRIBUTING.md`. Al enviar código, aceptas licenciarlo bajo los mismos términos de esta licencia.
---
Copyright (c) 2025 - Koneko Soluciones Tecnológicas

View File

@ -1,103 +0,0 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Livewire\Faq;
use Koneko\VuexyAdmin\Livewire\Table\AbstractIndexComponent;
use Koneko\VuexyWebsiteAdmin\Models\Faq;
class FaqIndex extends AbstractIndexComponent
{
/**
* Retorna la clase del modelo asociado.
*
* @return string
*/
protected function model(): string
{
return Faq::class;
}
/**
* Configura el encabezado (header) de la tabla (las columnas).
*
* @return array
*/
protected function columns(): array
{
return [
'action' => 'Acciones',
'status' => 'Estatus',
'created_at' => 'Fecha de Creación',
'updated_at' => 'Última Actualización',
];
}
/**
* Define los formatos de cada columna (se inyectará en $bt_datatable['format']).
*
* @return array
*/
protected function format(): array
{
return [
'action' => [
'formatter' => 'FaqActionFormatter',
'onlyFormatter' => true,
],
'status' => [
'formatter' => [
'name' => 'dynamicBooleanFormatter',
'params' => ['tag' => 'activo']
],
'align' => 'center',
],
'created_at' => [
'formatter' => 'textNowrapFormatter',
'align' => 'center',
'visible' => false,
],
'updated_at' => [
'formatter' => 'textNowrapFormatter',
'align' => 'center',
'visible' => false,
],
];
}
/**
* Retorna la configuración base (común) para la tabla Bootstrap Table.
*
* @return array
*/
protected function bootstraptableConfig(): array
{
return [
'sortName' => 'code',
'exportFileName' => 'Almacenes',
'showFullscreen' => false,
'showPaginationSwitch' => false,
'showRefresh' => false,
'pagination' => false,
];
}
/**
* Retorna la ruta de la vista Blade.
*
* @return string
*/
protected function viewPath(): string
{
// La vista que ya tienes creada para FaqIndex
return 'vuexy-website-admin::livewire.faq.index';
}
/**
* Métodos que necesites sobreescribir o extender.
*/
public function mount(): void
{
parent::mount();
}
}

View File

@ -1,104 +0,0 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Livewire\Images;
use Koneko\VuexyAdmin\Livewire\Table\AbstractIndexComponent;
use Koneko\VuexyWebsiteAdmin\Models\Faq;
use Koneko\VuexyWebsiteAdmin\Models\Images;
class ImagesIndex extends AbstractIndexComponent
{
/**
* Retorna la clase del modelo asociado.
*
* @return string
*/
protected function model(): string
{
return Faq::class;
}
/**
* Configura el encabezado (header) de la tabla (las columnas).
*
* @return array
*/
protected function columns(): array
{
return [
'action' => 'Acciones',
'status' => 'Estatus',
'created_at' => 'Fecha de Creación',
'updated_at' => 'Última Actualización',
];
}
/**
* Define los formatos de cada columna (se inyectará en $bt_datatable['format']).
*
* @return array
*/
protected function format(): array
{
return [
'action' => [
'formatter' => 'ImagesActionFormatter',
'onlyFormatter' => true,
],
'status' => [
'formatter' => [
'name' => 'dynamicBooleanFormatter',
'params' => ['tag' => 'activo']
],
'align' => 'center',
],
'created_at' => [
'formatter' => 'textNowrapFormatter',
'align' => 'center',
'visible' => false,
],
'updated_at' => [
'formatter' => 'textNowrapFormatter',
'align' => 'center',
'visible' => false,
],
];
}
/**
* Retorna la configuración base (común) para la tabla Bootstrap Table.
*
* @return array
*/
protected function bootstraptableConfig(): array
{
return [
'sortName' => 'code',
'exportFileName' => 'Almacenes',
'showFullscreen' => false,
'showPaginationSwitch' => false,
'showRefresh' => false,
'pagination' => false,
];
}
/**
* Retorna la ruta de la vista Blade.
*
* @return string
*/
protected function viewPath(): string
{
// La vista que ya tienes creada para ImagesIndex
return 'vuexy-website-admin::livewire.images.index';
}
/**
* Métodos que necesites sobreescribir o extender.
*/
public function mount(): void
{
parent::mount();
}
}

View File

@ -1,108 +0,0 @@
<?php
namespace Modules\Admin\App\Livewire\WebsiteSettings;
use Livewire\Component;
use App\Services\WebsiteTemplateService;
use Modules\Admin\App\Rules\NotEmptyHtml;
use Modules\Admin\App\Services\WebsiteSettingsService;
class LegalSettings extends Component
{
private $targetNotify = "#website-legal-settings-card .notification-container";
public $legalVars = [];
public $currentSection = null;
protected $listeners = [
'saveLegal' => 'save',
];
public function mount()
{
$this->loadSettings();
// Seleccionar la primera sección por defecto
$this->currentSection = array_key_first($this->legalVars);
}
function loadSettings()
{
$websiteTemplateService = app(WebsiteTemplateService::class);
switch ($this->currentSection) {
case 'legal_terminos_y_condiciones':
$this->legalVars['legal_terminos_y_condiciones'] = $websiteTemplateService->getLegalVars('legal_terminos_y_condiciones');
break;
case 'legal_aviso_de_privacidad':
$this->legalVars['legal_aviso_de_privacidad'] = $websiteTemplateService->getLegalVars('legal_aviso_de_privacidad');
break;
case 'legal_politica_de_devoluciones':
$this->legalVars['legal_politica_de_devoluciones'] = $websiteTemplateService->getLegalVars('legal_politica_de_devoluciones');
break;
case 'legal_politica_de_envios':
$this->legalVars['legal_politica_de_envios'] = $websiteTemplateService->getLegalVars('legal_politica_de_envios');
break;
case 'legal_politica_de_cookies':
$this->legalVars['legal_politica_de_cookies'] = $websiteTemplateService->getLegalVars('legal_politica_de_cookies');
break;
case 'legal_autorizaciones_y_licencias':
$this->legalVars['legal_autorizaciones_y_licencias'] = $websiteTemplateService->getLegalVars('legal_autorizaciones_y_licencias');
break;
case 'legal_informacion_comercial':
$this->legalVars['legal_informacion_comercial'] = $websiteTemplateService->getLegalVars('legal_informacion_comercial');
break;
case 'legal_consentimiento_para_el_login_de_terceros':
$this->legalVars['legal_consentimiento_para_el_login_de_terceros'] = $websiteTemplateService->getLegalVars('legal_consentimiento_para_el_login_de_terceros');
break;
case 'legal_leyendas_de_responsabilidad':
$this->legalVars['legal_leyendas_de_responsabilidad'] = $websiteTemplateService->getLegalVars('legal_leyendas_de_responsabilidad');
break;
default:
$this->legalVars = $websiteTemplateService->getLegalVars();
}
}
public function rules()
{
$rules = [];
if ($this->legalVars[$this->currentSection]['enabled']) {
$rules["legalVars.{$this->currentSection}.content"] = ['required', 'string', new NotEmptyHtml];
}
$rules["legalVars.{$this->currentSection}.enabled"] = 'boolean';
return $rules;
}
public function save()
{
$this->validate($this->rules());
$websiteSettingsService = app(WebsiteSettingsService::class);
$websiteSettingsService->updateSetting($this->currentSection . '_enabled', $this->legalVars[$this->currentSection]['enabled']);
$websiteSettingsService->updateSetting($this->currentSection . '_content', $this->legalVars[$this->currentSection]['content']);
$this->dispatch(
'notification',
target: $this->targetNotify,
type: 'success',
message: 'Se han guardado los cambios en las configuraciones.'
);
}
public function render()
{
return view('admin::livewire.website-settings.legal-settings');
}
}

View File

@ -1,33 +0,0 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Faq extends Model
{
use HasFactory;
protected $fillable = [
'category_id',
'question',
'answer',
'order',
'is_active',
];
protected $casts = [
'order' => 'integer',
'is_active' => 'boolean',
];
/**
* Categoría a la que pertenece esta FAQ.
*/
public function category(): BelongsTo
{
return $this->belongsTo(FaqCategory::class, 'category_id');
}
}

View File

@ -1,19 +0,0 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class SitemapUrl extends Model
{
use HasFactory;
protected $fillable = [
'url',
'changefreq',
'priority',
'lastmod',
'is_active',
];
}

View File

@ -1,97 +0,0 @@
<?php
namespace Koneko\VuexyWebsiteAdmin\Providers;
use Illuminate\Support\ServiceProvider;
use Livewire\Livewire;
use Koneko\VuexyWebsiteAdmin\Console\Commands\SitemapGenerate;
use Koneko\VuexyWebsiteAdmin\Livewire\Faq\{FaqIndex,FaqOffCanvasForm};
use Koneko\VuexyWebsiteAdmin\Livewire\Images\ImagesIndex;
use Koneko\VuexyWebsiteAdmin\Livewire\LegalNotices\{LegalNoticesIndex,LegalNoticeOffCanvasForm};
use Koneko\VuexyWebsiteAdmin\Livewire\SitemapManager\{SitemapManagerIndex,SitemapUrlOffcanvasForm};
use Koneko\VuexyWebsiteAdmin\Livewire\VuexyWebsiteAdmin\{WebsiteDescriptionSettings,WebsiteFaviconSettings,LogoOnLightBgSettings,LogoOnDarkBgSettings};
use Koneko\VuexyWebsiteAdmin\Livewire\VuexyWebsiteAdmin\{SocialMediaSettings,ChatSettings,GoogleAnalyticsSettings};
use Koneko\VuexyWebsiteAdmin\Livewire\VuexyWebsiteAdmin\{ContactInfoSettings,LocationSettings,ContactFormSettings};
class VuexyWebsiteAdminServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*/
public function register(): void
{
//
}
/**
* Bootstrap any application services.
*/
public function boot(): void
{
// Register the module's routes
$this->loadRoutesFrom(__DIR__.'/../routes/admin.php');
// Cargar vistas del paquete
$this->loadViewsFrom(__DIR__.'/../resources/views', 'vuexy-website-admin');
// Register the migrations
$this->loadMigrationsFrom(__DIR__ . '/../database/migrations');
// Registrar comandos de consola
if ($this->app->runningInConsole()) {
$this->commands([
SitemapGenerate::class,
]);
}
// Registrar Livewire Components
$components = [
// ajustes generales
'vuexy-website-admin::website-description-settings' => WebsiteDescriptionSettings::class,
'vuexy-website-admin::website-favicon-settings' => WebsiteFaviconSettings::class,
'vuexy-website-admin::logo-on-light-bg-settings' => LogoOnLightBgSettings::class,
'vuexy-website-admin::logo-on-dark-bg-settings' => LogoOnDarkBgSettings::class,
// Avisos legales
'vuexy-website-admin::legal-notices-index' => LegalNoticesIndex::class,
'vuexy-website-admin::legal-notice-offcanvas-form' => LegalNoticeOffCanvasForm::class,
// Preguntas frecuentes
'vuexy-website-admin::faq-index' => FaqIndex::class,
'vuexy-website-admin::faq-offcanvas-form' => FaqOffCanvasForm::class,
// Redes sociales
'vuexy-website-admin::social-media-settings' => SocialMediaSettings::class,
// Chat
'vuexy-website-admin::chat-settings' => ChatSettings::class,
// Galería de imágenes
'vuexy-website-admin::images-index' => ImagesIndex::class,
// Google Analytics
'vuexy-website-admin::google-analytics-settings' => GoogleAnalyticsSettings::class,
// Información de contacto
'vuexy-website-admin::contact-info-settings' => ContactInfoSettings::class,
'vuexy-website-admin::location-settings' => LocationSettings::class,
// Formulario de contacto
'vuexy-website-admin::contact-form-settings' => ContactFormSettings::class,
// Mapa del sitio
'vuexy-website-admin::sitemap-manager-index' => SitemapManagerIndex::class,
'vuexy-website-admin::sitemap-manager-offcanvas-form' => SitemapUrlOffcanvasForm::class,
];
foreach ($components as $alias => $component) {
Livewire::component($alias, $component);
}
}
}

118
README.en.md Normal file
View File

@ -0,0 +1,118 @@
# 🧩 Laravel Vuexy Website Admin
<p align="center">
<a href="https://koneko.mx" target="_blank">
<img src="https://git.koneko.mx/Koneko-ST/koneko-st/raw/branch/main/logo-images/horizontal-05.png" width="400" alt="Koneko Soluciones Tecnológicas Logo">
</a>
</p>
<p align="center">
<a href="https://koneko.mx"><img src="https://img.shields.io/badge/Website-koneko.mx-blue" alt="Website"></a>
<a href="https://packagist.org/packages/koneko/laravel-vuexy-website-admin"><img src="https://img.shields.io/packagist/v/koneko/laravel-vuexy-website-admin" alt="Latest Version"></a>
<a href="https://packagist.org/packages/koneko/laravel-vuexy-website-admin"><img src="https://img.shields.io/packagist/l/koneko/laravel-vuexy-website-admin" alt="License"></a>
<a href="https://github.com/koneko-mx/laravel-vuexy-website-admin"><img src="https://img.shields.io/github/issues/koneko-mx/laravel-vuexy-website-admin" alt="Issues"></a>
</p>
---
## 📌 Description
**Laravel Vuexy Website Admin** is a core plugin in the **Koneko ERP** ecosystem. Built on Laravel 11 and integrated with the official `laravel-vuexy-admin` system, this package provides a powerful content management interface for corporate and eCommerce websites.
It enables complete control over site configuration, SEO optimization, domain management, multilingual support, and template rendering. The module follows modern coding standards and is compatible with Redis, PostgreSQL, and multi-site deployments.
---
### 📦 Main Features
* Multi-site and multi-domain support
* Site-level settings and branding configuration
* SEO profile management with OpenGraph, Twitter Cards, JSON-LD, and canonical settings
* Sitemap, robots.txt, and manifest.json integration
* CMS with dynamic blocks, reusable menus, and content versioning
* Full page and block-based caching system
* Template selector and preview system
* Blog module with categories, tags, articles, and comment moderation
* API integration for Google, Meta, WhatsApp, Tawk.to, and more
* Translation and localization tools (DeepL, Google Translate)
---
### 🚀 Quick Installation
```bash
composer require koneko/laravel-vuexy-website-admin
php artisan migrate --seed
php artisan vendor:publish --tag=vuexy-website-admin-config
```
> You must have `laravel-vuexy-admin` installed before using this plugin.
---
### 📦 Included Commands
```bash
php artisan website:seo-helper
php artisan website:menu-helper
php artisan website:content-helper
php artisan website:cache-helper
php artisan website:sitemap-generate
```
---
### ⚙️ Publicación de archivos
This package publishes:
* Routes, views and Livewire components
* Configuration and permissions files (RBAC)
* Artisan commands and content generators
* Menu and modular system extensions
```bash
php artisan vendor:publish --tag=vuexy-website-admin-config
```
---
### 🔧 Uso y personalización
This module allows you to customize its structure and behavior using:
* Middlewares for web and content context
* Multisite configuration with support for dynamic templates
* Decoupled view system compatible with Blade, Vite and partial rendering
You can extend or override any published view, layout or Livewire component.
---
### 🛠️ Requirements
* PHP `^8.2`
* Laravel `^11.31`
* [koneko/laravel-vuexy-admin](https://github.com/koneko-mx/laravel-vuexy-admin) install and configured
---
## 📄 License
This package is licensed under the [custom Business Source License 1.1](LICENSE), transitioning to MIT after 3 years. For commercial usage, redistribution, or extended usage, please contact:
📧 [opensource@koneko.mx](mailto:opensource@koneko.mx)
---
## 📚 More Information
* [Vuexy Admin Core](https://github.com/koneko-mx/laravel-vuexy-admin)
* [Documentation in Spanish](README.md)
* [Koneko ST Official Website](https://koneko.mx)
* [Contact Email](mailto:opensource@koneko.mx)
---
<p align="center">
Made with ❤️ in Mexico by <a href="https://koneko.mx">Koneko Soluciones Tecnológicas</a>
</p>

157
README.md
View File

@ -1,133 +1,116 @@
# 🎨 Laravel Vuexy Website Admin - Vuexy Admin
# 🧩 Laravel Vuexy Website Admin
<p align="center">
<a href="https://koneko.mx" target="_blank"> <img src="https://git.koneko.mx/Koneko-ST/koneko-st/raw/branch/main/logo-images/horizontal-05.png" width="400" alt="Koneko Soluciones Tecnológicas Logo"> </a>
<a href="https://koneko.mx" target="_blank">
<img src="https://git.koneko.mx/Koneko-ST/koneko-st/raw/branch/main/logo-images/horizontal-05.png" width="400" alt="Koneko Soluciones Tecnológicas Logo">
</a>
</p>
<p align="center">
<a href="https://koneko.mx"><img src="https://img.shields.io/badge/Website-koneko.mx-blue" alt="Sitio Web"></a>
<a href="https://packagist.org/packages/koneko/laravel-vuexy-website-admin"><img src="https://img.shields.io/packagist/v/koneko/laravel-vuexy-website-admin" alt="Latest Stable Version"></a>
<a href="https://packagist.org/packages/koneko/laravel-vuexy-website-admin"><img src="https://img.shields.io/packagist/l/koneko/laravel-vuexy-website-admin" alt="License"></a>
<a href="https://git.koneko.mx/koneko"><img src="https://img.shields.io/badge/Git%20Server-Koneko%20Git-orange" alt="Servidor Git"></a>
<a href="https://github.com/koneko-mx/laravel-vuexy-website-admin/actions/workflows/tests.yml"><img src="https://github.com/koneko-mx/laravel-vuexy-website-admin/actions/workflows/tests.yml/badge.svg" alt="Build Status"></a>
<a href="https://github.com/koneko-mx/laravel-vuexy-website-admin/issues"><img src="https://img.shields.io/github/issues/koneko/laravel-vuexy-website-admin" alt="Issues"></a>
<a href="https://koneko.mx"><img src="https://img.shields.io/badge/Sitio%20Web-koneko.mx-blue" alt="Sitio Web"></a>
<a href="https://packagist.org/packages/koneko/laravel-vuexy-website-admin"><img src="https://img.shields.io/packagist/v/koneko/laravel-vuexy-website-admin" alt="Versión estable"></a>
<a href="https://packagist.org/packages/koneko/laravel-vuexy-website-admin"><img src="https://img.shields.io/packagist/l/koneko/laravel-vuexy-website-admin" alt="Licencia"></a>
<a href="https://github.com/koneko-mx/laravel-vuexy-website-admin"><img src="https://img.shields.io/github/issues/koneko-mx/laravel-vuexy-website-admin" alt="Issues"></a>
</p>
---
## 📌 Descripción
**Laravel Vuexy Website Admin** es un módulo diseñado para **Laravel Vuexy Admin**, proporcionando [breve descripción de la funcionalidad].
**Laravel Vuexy Website Admin** es un módulo del ecosistema **Koneko ERP** desarrollado en Laravel 11, orientado a la administración de contenido web multisitio, multidioma y multitemplate. Forma parte del stack web profesional de Koneko, integrando funcionalidades CMS, SEO, blog, renderización por bloques, cache HTML y plantillas dinámicas.
### ✨ Características:
- 🔹 Integración completa con Vuexy Admin.
- 🔹 Funcionalidad clave 1.
- 🔹 Funcionalidad clave 2.
Está diseñado para integrarse de forma transparente al backend Vuexy Admin y utilizarse con frontends basados en Vite y plantillas como **Porto, Landwind, Notus** y otras.
---
## 📦 Instalación
### 📦 Características
Instalar vía **Composer**:
* Gestión de múltiples sitios web y dominios
* Configuración contextual del sitio (branding, idioma, indexación, manifest.json, etc.)
* Editor de contenido por bloques y plantillas Blade
* Administración de menús, páginas, SEO y JSON-LD
* Blog con artículos, etiquetas, categorías y comentarios
* Sistema de caché de contenido completo y por bloque
* Integraciones con APIs externas como Google Analytics, Pixel Meta, Tawk.to, etc.
---
### 🚀 Instalación rápida
```bash
composer require koneko/laravel-vuexy-website-admin
```
Publicar archivos de configuración y migraciones (si aplica):
```bash
php artisan vendor:publish --tag=laravel-vuexy-website-admin-config
php artisan migrate
```
---
## 🚀 Uso básico
```php
use Koneko\NombreLibreria\Models\Model;
$model = Model::create([
'campo1' => 'Valor',
'campo2' => 'Otro valor',
]);
```
---
## 📚 Configuración adicional
Si necesitas personalizar la configuración del módulo, publica el archivo de configuración:
```bash
php artisan vendor:publish --tag=laravel-vuexy-website-admin-config
```
Esto generará `config/nombre_libreria.php`, donde puedes modificar valores predeterminados.
---
## 🛠 Dependencias
Este paquete requiere las siguientes dependencias:
- Laravel 11
- `koneko/laravel-vuexy-website-admin`
- Dependencias específicas de la librería
---
## 📦 Publicación de Assets y Configuraciones
Para publicar configuraciones y seeders:
```bash
php artisan vendor:publish --tag=laravel-vuexy-website-admin-config
php artisan vendor:publish --tag=laravel-vuexy-website-admin-seeders
php artisan migrate --seed
php artisan vendor:publish --tag=vuexy-website-admin-config
```
Para publicar imágenes del tema:
> Debes tener instalado `laravel-vuexy-admin` antes de usar este complemento.
---
### 📦 Comandos Incluidos
```bash
php artisan vendor:publish --tag=laravel-vuexy-website-admin-images
php artisan website:seo-helper
php artisan website:menu-helper
php artisan website:content-helper
php artisan website:cache-helper
php artisan website:sitemap-generate
```
---
## 🛠 Pruebas
### ⚙️ Publicación de archivos
Ejecuta los tests con:
Este paquete publica:
* Rutas, vistas y Livewire components
* Archivos de configuración y permisos (RBAC)
* Comandos Artisan y generadores de contenido
* Extensiones para menú y sistema modular
```bash
php artisan test
php artisan vendor:publish --tag=vuexy-website-admin-config
```
---
## 🌍 Repositorio Principal y Sincronización
### 🔧 Uso y personalización
Este repositorio es una **copia sincronizada** del repositorio principal alojado en **[Tea - Koneko Git](https://git.koneko.mx/koneko/laravel-vuexy-website-admin)**.
Este módulo permite personalizar su estructura y comportamiento utilizando:
### 🔄 Sincronización con GitHub
- **Repositorio Principal:** [git.koneko.mx](https://git.koneko.mx/koneko/laravel-vuexy-website-admin)
- **Repositorio en GitHub:** [github.com/koneko/laravel-vuexy-website-admin](https://github.com/koneko/laravel-vuexy-website-admin)
- **Los cambios pueden reflejarse primero en Tea antes de GitHub.**
* Middlewares para contexto web y contenido
* Configuración multisitio con soporte para templates dinámicos
* Sistema de vistas desacoplado compatible con Blade, Vite y renderizado parcial
### 🤝 Contribuciones
Si deseas contribuir:
1. Puedes abrir un **Issue** en [GitHub Issues](https://github.com/koneko/laravel-vuexy-website-admin/issues).
2. Para Pull Requests, **preferimos contribuciones en Tea**. Contacta a `admin@koneko.mx` para solicitar acceso.
⚠️ **Nota:** Algunos cambios pueden tardar en reflejarse en GitHub, ya que este repositorio se actualiza automáticamente desde Tea.
Puedes extender o sobreescribir cualquier vista, layout o componente Livewire publicado.
---
## 🏅 Licencia
## 🛠️ Requisitos
Este paquete es de código abierto bajo la licencia [MIT](LICENSE).
* PHP `^8.2`
* Laravel `^11.31`
* [koneko/laravel-vuexy-admin](https://github.com/koneko-mx/laravel-vuexy-admin) instalado y configurado
---
## 📄 Licencia
Este paquete se distribuye bajo la [Licencia Business Source 1.1 personalizada](LICENSE.es), con transición automática a MIT a los 3 años. Para uso comercial, redistribución o integraciones ampliadas, contacta a:
📧 [opensource@koneko.mx](mailto:opensource@koneko.mx)
---
## 📚 Más Información
* [Core Vuexy Admin](https://github.com/koneko-mx/laravel-vuexy-admin)
* [Documentación en inglés](README.en.md)
* [Sitio Oficial Koneko ST](https://koneko.mx)
* [Correo de Contacto](mailto:opensource@koneko.mx)
---
<p align="center">
Hecho con ❤️ por <a href="https://koneko.mx">Koneko Soluciones Tecnológicas</a>
Hecho con ❤️ en México por <a href="https://koneko.mx">Koneko Soluciones Tecnológicas</a>
</p>

30
SECURITY.md Normal file
View File

@ -0,0 +1,30 @@
# 🛡️ Política de Seguridad
Koneko Soluciones Tecnológicas se toma muy en serio la seguridad de este proyecto y de sus usuarios.
## 🔒 Reporte responsable de vulnerabilidades
Si encuentras alguna vulnerabilidad de seguridad, **no abras un issue público**. En lugar de ello, por favor repórtala de forma privada por cualquiera de los siguientes medios:
- 📧 Correo oficial: [opensource@koneko.mx](mailto:opensource@koneko.mx)
Por favor incluye los siguientes detalles:
- Descripción del problema
- Versión afectada del paquete
- Instrucciones claras para reproducir el fallo (si es posible)
Nos comprometemos a responder dentro de **5 días hábiles**.
## 🛡️ Alcance
Este procedimiento aplica únicamente al paquete:
- `koneko/laravel-vuexy-admin`
Y a sus repositorios relacionados dentro del ecosistema oficial Koneko.
## ✅ Reconocimientos
Se podrá otorgar reconocimiento público (con tu permiso) en futuras notas de versión a quienes reporten vulnerabilidades de manera responsable.
Gracias por ayudar a hacer más seguro el ecosistema de Koneko ERP.

View File

@ -1,17 +1,20 @@
{
"name": "koneko/laravel-vuexy-website-admin",
"description": "Laravel Vuexy Website Admin, un modulo de administracion de sitios web.",
"keywords": ["laravel", "koneko", "framework", "vuexy", "website", "admin", "mexico"],
"description": "Web content management module for Laravel projects, integrated with Vuexy Admin and optimized for professional sites in Mexico.",
"keywords": [
"laravel", "cms", "website-admin", "vuexy", "koneko", "mexico", "admin-panel",
"seo", "gestión de contenidos", "multi-site", "erp"
],
"type": "library",
"license": "MIT",
"license": "BUSL-1.1-custom",
"require": {
"php": "^8.2",
"koneko/laravel-vuexy-admin": "dev-main",
"koneko/laravel-vuexy-admin": "dev-develop",
"laravel/framework": "^11.31"
},
"autoload": {
"psr-4": {
"Koneko\\VuexyWebsiteAdmin\\": "./"
"Koneko\\VuexyWebsiteAdmin\\": "src/"
}
},
"extra": {
@ -31,5 +34,6 @@
"source": "https://github.com/koneko-mx/laravel-vuexy-website-admin",
"issues": "https://github.com/koneko-mx/laravel-vuexy-website-admin/issues"
},
"minimum-stability": "dev",
"prefer-stable": true
}

28
config/koneko-website.php Normal file
View File

@ -0,0 +1,28 @@
<?php
// Variables
return [
// ================== 📦 CACHE DE COMPONENTE ==================
'cache' => [
'enabled' => (bool) env('KONEKO_WEBSITE_CACHE_ENABLED', true),
'ttl' => (int) env('KONEKO_WEBSITE_CACHE_TTL', 20 * 24 * 60),
],
'menu' => [
'cache' => [
'enabled' => (bool) env('VUEXY_WEBSITE_MENU_CACHE_ENABLED', true),
'ttl' => (int) env('VUEXY_WEBSITE_MENU_CACHE_TTL', 3600),
],
'debug' => [
'show_broken_routes' => (bool) env('VUEXY_WEBSITE_MENU_DEBUG_SHOW_BROKEN_ROUTES', false),
'show_disallowed_links' => (bool) env('VUEXY_WEBSITE_MENU_DEBUG_SHOW_DISALLOWED_LINKS', false),
],
],
'html' => [
'cache' => [
'enabled' => (bool) env('VUEXY_WEBSITE_HTML_CACHE_ENABLED', true),
'ttl' => (int) env('VUEXY_WEBSITE_HTML_CACHE_TTL', 900),
],
'debug' => [
'mode' => (bool) env('VUEXY_WEBSITE_HTML_DEBUG_MODE', true),
]
]
];

View File

@ -0,0 +1,108 @@
<?php
// Este archivo **NO se registra como config**, es usado por
return [
// ======================= GOOGLE =======================
'google_analytics' => [
'name' => 'Google Analytics',
'slug' => 'google_analytics',
'provider' => ApiProvider::Google,
'auth_type' => ApiAuthType::OAuth2,
'environment' => ApiEnvironment::Production,
'base_url' => 'https://analytics.googleapis.com',
'scopes' => ['https://www.googleapis.com/auth/analytics.readonly'],
'credentials' => [
'client_id' => env('GOOGLE_ANALYTICS_CLIENT_ID'),
'client_secret' => env('GOOGLE_ANALYTICS_CLIENT_SECRET'),
'redirect_uri' => env('GOOGLE_ANALYTICS_REDIRECT_URI', url('/oauth2/callback')),
],
],
'google_translate' => [
'name' => 'Google Translate',
'slug' => 'google_translate',
'provider' => ApiProvider::Google,
'auth_type' => ApiAuthType::ApiKey,
'environment' => ApiEnvironment::Production,
'base_url' => 'https://translation.googleapis.com/language/translate/v2',
'credentials' => [
'api_key' => env('GOOGLE_TRANSLATE_API_KEY'),
],
],
'google_search_console' => [
'name' => 'Google Search Console',
'slug' => 'google_search_console',
'provider' => ApiProvider::Google,
'auth_type' => ApiAuthType::OAuth2,
'environment' => ApiEnvironment::Production,
'base_url' => 'https://searchconsole.googleapis.com',
'scopes' => ['https://www.googleapis.com/auth/webmasters.readonly'],
'credentials' => [
'client_id' => env('GOOGLE_SEARCH_CLIENT_ID'),
'client_secret' => env('GOOGLE_SEARCH_CLIENT_SECRET'),
'redirect_uri' => env('GOOGLE_SEARCH_REDIRECT_URI'),
],
],
'google_tag_manager' => [
'name' => 'Google Tag Manager',
'slug' => 'google_tag_manager',
'provider' => ApiProvider::Google,
'auth_type' => ApiAuthType::OAuth2,
'environment' => ApiEnvironment::Production,
'base_url' => 'https://www.googleapis.com/tagmanager/v2',
'scopes' => ['https://www.googleapis.com/auth/tagmanager.readonly'],
'credentials' => [
'client_id' => env('GOOGLE_TAG_CLIENT_ID'),
'client_secret' => env('GOOGLE_TAG_CLIENT_SECRET'),
'redirect_uri' => env('GOOGLE_TAG_REDIRECT_URI'),
],
],
// ======================= META / FACEBOOK =======================
'facebook_messenger' => [
'name' => 'Facebook Messenger',
'slug' => 'facebook_messenger',
'provider' => ApiProvider::Facebook,
'auth_type' => ApiAuthType::OAuth2,
'environment' => ApiEnvironment::Production,
'base_url' => 'https://graph.facebook.com/v17.0',
'scopes' => ['pages_messaging', 'pages_show_list'],
'credentials' => [
'app_id' => env('FACEBOOK_APP_ID'),
'app_secret' => env('FACEBOOK_APP_SECRET'),
'redirect_uri' => env('FACEBOOK_REDIRECT_URI'),
],
],
// ======================= X / TWITTER =======================
'twitter_api' => [
'name' => 'Twitter API v2',
'slug' => 'twitter_api',
'provider' => ApiProvider::Twitter,
'auth_type' => ApiAuthType::BearerToken,
'environment' => ApiEnvironment::Production,
'base_url' => 'https://api.twitter.com/2',
'credentials' => [
'bearer_token' => env('TWITTER_BEARER_TOKEN'),
],
],
// ======================= TAWK.TO =======================
'tawk_to' => [
'name' => 'Tawk.to Live Chat',
'slug' => 'tawk_to',
'provider' => ApiProvider::Custom,
'auth_type' => ApiAuthType::None,
'environment' => ApiEnvironment::Production,
'base_url' => 'https://embed.tawk.to',
'credentials' => [],
],
];

View File

@ -0,0 +1,339 @@
<?php
declare(strict_types=1);
// Este archivo **NO se registra como config**, es usado por VuexyMenuRegistry
return [
'Web & SEO' => [
'_meta' => [
'icon' => 'ti ti-settings',
'description' => 'Administra la configuración, contenido, integraciones y visibilidad de tu sitio web empresarial.',
'widget_label' => 'Sitio Web y SEO',
'priority' => 200,
],
'submenu' => [
'Configuración general' => [
'_meta' => [
'icon' => 'ti ti-settings',
'description' => 'Ajustes generales del sitio, redes sociales y configuración de indexado.',
'widget_label' => 'Configuración del Sitio Web',
'home_at_root' => true,
'priority' => 100,
],
'submenu' => [
'Ajustes generales' => [
'icon' => 'ti ti-settings',
'route' => 'admin.website-admin.settings.general.index',
'can' => 'admin.website-admin.settings.general.view',
'description' => 'Personaliza el título, favicon, y otros aspectos básicos del sitio.',
],
'Enlaces sociales' => [
'icon' => 'ti ti-share',
'route' => 'admin.website-admin.settings.social.index',
'can' => 'admin.website-admin.settings.social.view',
'description' => 'Administra los enlaces y metadatos de redes sociales.',
],
'Visibilidad en buscadores' => [
'icon' => 'ti ti-search',
'route' => 'admin.website-admin.settings.indexing.index',
'can' => 'admin.website-admin.settings.indexing.view',
'description' => 'Controla el indexado del sitio web por los motores de búsqueda.',
],
]
],
'Contacto' => [
'_meta' => [
'icon' => 'ti ti-device-mobile-question',
'description' => 'Información y formularios de contacto del sitio.',
'widget_label' => 'Información de contacto',
'home_at_root' => true,
'priority' => 200,
],
'submenu' => [
'Información de contacto' => [
'icon' => 'ti ti-device-mobile-message',
'route' => 'admin.website-admin.contact.info.index',
'can' => 'admin.website-admin.contact.info.view',
'description' => 'Dirección, teléfonos, correos y ubicación.',
],
'Formulario de contacto' => [
'icon' => 'ti ti-mail-cog',
'route' => 'admin.website-admin.contact.form.index',
'can' => 'admin.website-admin.contact.form.view',
'description' => 'Configuración y campos del formulario de contacto.',
],
]
],
'Chat & Comunicación' => [
'_meta' => [
'icon' => 'ti ti-message-dots',
'description' => 'Soporte al cliente y canales de comunicación directa.',
'widget_label' => 'Chat & Comunicación de Sitio Web',
'home_at_root' => true,
'priority' => 500,
],
'submenu' => [
'Facebook Messenger' => [
'icon' => 'ti ti-brand-messenger',
'route' => 'admin.website-admin.comunication.messenger.index',
'can' => 'admin.website-admin.comunication.messenger.view',
'description' => 'Activa el chat de Messenger en tu sitio.',
],
'Whatsapp Chat' => [
'icon' => 'ti ti-brand-whatsapp',
'route' => 'admin.website-admin.comunication.whatsapp.index',
'can' => 'admin.website-admin.comunication.whatsapp.view',
'description' => 'Integra un botón de chat directo con WhatsApp.',
],
'Tawk.to' => [
'icon' => 'ti ti-message-dots',
'route' => 'admin.website-admin.comunication.tawk-to.index',
'can' => 'admin.website-admin.comunication.tawk-to.view',
'description' => 'Agrega soporte en vivo con Tawk.to.',
],
'Twitter API' => [
'icon' => 'ti ti-brand-x',
'route' => 'admin.website-admin.comunication.twitter.index',
'can' => 'admin.website-admin.comunication.twitter.view',
'description' => 'Configura la integración con Twitter/X.',
],
]
],
'CMS - Gestor de Contenidos' => [
'_meta' => [
'icon' => 'ti ti-layout-grid-add',
'description' => 'Crea, edita y publica contenido dinámico basado en Blade para tu sitio web.',
'widget_label' => 'Administrador de Contenidos CMS',
'priority' => 250,
],
'submenu' => [
'Menús del sitio' => [
'icon' => 'ti ti-hierarchy-3',
'route' => 'admin.website-admin.cms.menus.index',
'can' => 'admin.website-admin.cms.menus.view',
'description' => 'Administra la estructura de navegación y menús dinámicos.',
],
'Perfil SEO' => [
'icon' => 'ti ti-settings',
'route' => 'admin.website-admin.cms.seo.index',
'can' => 'admin.website-admin.cms.seo.view',
'description' => 'Configura las metas y parámetros SEO del sitio.',
],
'Contenidos dinámicos' => [
'icon' => 'ti ti-file-text',
'route' => 'admin.website-admin.cms.contents.index',
'can' => 'admin.website-admin.cms.contents.view',
'description' => 'Administra páginas, bloques y parciales Blade de tu sitio.',
],
'Versiones de contenido' => [
'icon' => 'ti ti-clock-edit',
'route' => 'admin.website-admin.cms.versions.index',
'can' => 'admin.website-admin.cms.versions.view',
'description' => 'Gestiona las versiones de contenido y restauraciones.',
],
'Plantillas disponibles' => [
'icon' => 'ti ti-template',
'route' => 'admin.website-admin.cms.templates.index',
'can' => 'admin.website-admin.cms.templates.view',
'description' => 'Define y organiza los templates base disponibles.',
],
],
],
'Cache' => [
'_meta' => [
'icon' => 'ti ti-cpu',
'description' => 'Administración y limpieza de caché para mejorar el rendimiento.',
'widget_label' => 'Cache de Sitio Web',
'home_at_root' => true,
'priority' => 900,
],
'submenu' => [
'Cache HTML renderizado' => [
'icon' => 'ti ti-file-type-html',
'description' => 'Visualiza y limpia la caché de HTML completo del sitio web.',
'route' => 'admin.website-admin.cache.fullpage.index',
'can' => 'admin.website-admin.cache.fullpage.view',
],
'Previsualizaciones firmadas' => [
'icon' => 'ti ti-lock-access',
'description' => 'URLs de vista previa y control de firma temporal.',
'route' => 'admin.website-admin.cache.signed-previews.index',
'can' => 'admin.website-admin.cache.signed-previews.view',
],
]
],
'Traducciones e internacional' => [
'_meta' => [
'icon' => 'ti ti-language',
'description' => 'Herramientas para traducción automática del sitio.',
'widget_label' => 'Herramientas de traducción de Sitio Web',
'home_at_root' => true,
'priority' => 500,
],
'submenu' => [
'Google Translate' => [
'icon' => 'ti ti-language',
'route' => 'admin.website-admin.translate.google.index',
'can' => 'admin.website-admin.translate.google.view',
'description' => 'Activa la traducción automática con Google Translate.',
],
]
],
'Contenido' => [
'_meta' => [
'icon' => 'ti ti-hierarchy',
'description' => 'Maneja contenido informativo y visual.',
'widget_label' => 'Contenidos del Sitio Web',
'home_at_root' => true,
'priority' => 400,
],
'submenu' => [
'Preguntas frecuentes' => [
'icon' => 'ti ti-bubble-text',
'route' => 'admin.website-admin.content.faq.index',
'can' => 'admin.website-admin.content.faq.view',
'description' => 'Administra las preguntas frecuentes del sitio.',
],
'Galería de imágenes' => [
'icon' => 'ti ti-photo',
'route' => 'admin.website-admin.content.gallery.index',
'can' => 'admin.website-admin.content.gallery.view',
'description' => 'Agrega y organiza tus imágenes.',
],
'Avisos legales' => [
'icon' => 'ti ti-file-text-shield',
'route' => 'admin.website-admin.content.legal.index',
'can' => 'admin.website-admin.content.legal.view',
'description' => 'Documentos como Términos, Aviso de Privacidad, etc.',
],
]
],
'Analítica y seguimiento' => [
'_meta' => [
'icon' => 'ti ti-device-analytics',
'description' => 'Conecta tu sitio con herramientas de análisis y tracking.',
'widget_label' => 'Integraciones de analítica y seguimiento',
'home_at_root' => true,
'priority' => 300,
],
'submenu' => [
'Google Analytics' => [
'icon' => 'ti ti-chart-scatter-3d',
'route' => 'admin.website-admin.analytics.google-analytics.index',
'can' => 'admin.website-admin.analytics.google-analytics.view',
'description' => 'Integra tu cuenta de Google Analytics.',
],
'Google Tags' => [
'icon' => 'ti ti-tags',
'route' => 'admin.website-admin.analytics.google-tags.index',
'can' => 'admin.website-admin.analytics.google-tags.view',
'description' => 'Administra etiquetas de Google Tag Manager.',
],
'Google Search Console' => [
'icon' => 'ti ti-search',
'route' => 'admin.website-admin.analytics.google-search-console.index',
'can' => 'admin.website-admin.analytics.google-search-console.view',
'description' => 'Verifica y gestiona tu sitio con Search Console.',
],
'Pixel Meta' => [
'icon' => 'ti ti-device-analytics',
'route' => 'admin.website-admin.analytics.pixel-meta.index',
'can' => 'admin.website-admin.analytics.pixel-meta.view',
'description' => 'Integra el pixel de Meta (Facebook Ads).',
],
]
],
'Herramientas SEO' => [
'_meta' => [
'icon' => 'ti ti-code-dots',
'description' => 'Utilidades para mejorar la visibilidad en buscadores.',
'widget_label' => 'Herramientas SEO y Metadatos',
'home_at_root' => true,
'priority' => 500,
],
'submenu' => [
'Mapa del sitio' => [
'icon' => 'ti ti-hierarchy',
'route' => 'admin.website-admin.seo.sitemap.index',
'can' => 'admin.website-admin.seo.sitemap.view',
'description' => 'Genera y publica el sitemap.xml.',
],
'Google JSON-LD' => [
'icon' => 'ti ti-code-dots',
'route' => 'admin.website-admin.seo.jsonld.index',
'can' => 'admin.website-admin.seo.jsonld.view',
'description' => 'Configura el esquema estructurado para Google.',
],
'Robots.txt' => [
'icon' => 'ti ti-code',
'route' => 'admin.website-admin.seo.robots.index',
'can' => 'admin.website-admin.seo.robots.view',
'description' => 'Controla qué partes del sitio pueden ser indexadas.',
],
'manifest.json' => [
'icon' => 'ti ti-file-code',
'route' => 'admin.website-admin.seo.manifest.index',
'can' => 'admin.website-admin.seo.manifest.view',
'description' => 'Configura la compatibilidad como PWA.',
],
'Canonical URLs' => [
'icon' => 'ti ti-link',
'route' => 'admin.website-admin.seo.canonical.index',
'can' => 'admin.website-admin.seo.canonical.view',
'description' => 'Evita duplicidad de URLs con etiquetas canónicas.',
],
'Preview Social Cards' => [
'icon' => 'ti ti-brand-facebook',
'route' => 'admin.website-admin.seo.social-cards.index',
'can' => 'admin.website-admin.seo.social-cards.view',
'description' => 'Define títulos, imágenes y previews sociales.',
],
]
],
]
],
'Blog' => [
'_meta' => [
'icon' => 'ti ti-news',
'description' => 'Publica, edita y organiza artículos, categorías y comentarios de tu blog.',
'after_to' => 'Web & SEO',
],
'submenu' => [
'Categorias' => [
'icon' => 'ti ti-category',
'route' => 'admin.website-admin.blog.categories.index',
'can' => 'admin.website-admin.blog.categories.view',
],
'Etiquetas' => [
'icon' => 'ti ti-tags',
'route' => 'admin.website-admin.blog.tags.index',
'can' => 'admin.website-admin.blog.tags.view',
],
'Articulos' => [
'icon' => 'ti ti-news',
'route' => 'admin.website-admin.blog.articles.index',
'can' => 'admin.website-admin.blog.articles.view',
],
'Comentarios' => [
'icon' => 'ti ti-message',
'route' => 'admin.website-admin.blog.comments.index',
'can' => 'admin.website-admin.blog.comments.view',
],
]
],
'Plantillas' => [
'_meta' => [
'icon' => 'ti ti-template',
'description' => 'Gestiona las plantillas disponibles para tu sitio web.',
'after_to' => 'Blog',
],
'submenu' => [
'Plantillas' => [
'icon' => 'ti ti-template',
'route' => 'admin.website-admin.templates.index',
'can' => 'admin.website-admin.templates.view',
],
]
],
];

View File

@ -0,0 +1,218 @@
<?php
declare(strict_types=1);
// Este archivo **NO se registra como config**, es usado por VuexyMenuRegistry
return [
'Sitios Web' => [
'_meta' => [
'icon' => 'ti ti-world',
'description' => 'Administra múltiples sitios, dominios, plantillas y configuración global.',
'widget_label' => 'Sitios Web y Dominios',
'home_at_root' => true,
'priority' => 100,
],
'submenu' => [
'Todos los sitios' => [
'icon' => 'ti ti-world',
'route' => 'admin.website-admin.sites.index',
'can' => 'admin.website-admin.sites.view',
'description' => 'Listado general de sitios activos y configurables.',
],
'Crear nuevo sitio' => [
'icon' => 'ti ti-world-plus',
'route' => 'admin.website-admin.sites.create',
'can' => 'admin.website-admin.sites.create',
'description' => 'Inicia un nuevo sitio web desde cero.',
],
],
],
'Configuración del Sitio' => [
'_meta' => [
'icon' => 'ti ti-settings-cog',
'description' => 'Ajustes, branding, visibilidad y plantilla del sitio actual.',
'widget_label' => 'Configuración de Sitio Web',
'home_at_root' => true,
'priority' => 150,
],
'submenu' => [
'General y Branding' => [
'icon' => 'ti ti-tools',
'route' => 'admin.website-admin.settings.general.index',
'can' => 'admin.website-admin.settings.general.view',
'description' => 'Nombre, idioma, favicon, y plantilla activa.',
],
'Indexación y Robots' => [
'icon' => 'ti ti-search',
'route' => 'admin.website-admin.settings.indexing.index',
'can' => 'admin.website-admin.settings.indexing.view',
'description' => 'Controla el acceso de motores de búsqueda a tu sitio.',
],
'Canonical y manifest.json' => [
'icon' => 'ti ti-file-code',
'route' => 'admin.website-admin.settings.canonical.index',
'can' => 'admin.website-admin.settings.canonical.view',
'description' => 'Evita duplicados y mejora la visibilidad PWA.',
],
],
],
'SEO y Metadatos' => [
'_meta' => [
'icon' => 'ti ti-zoom-code',
'description' => 'Herramientas de optimización SEO, metadatos y JSON-LD.',
'widget_label' => 'SEO & Metadatos',
'home_at_root' => true,
'priority' => 200,
],
'submenu' => [
'Perfil SEO' => [
'icon' => 'ti ti-graph',
'route' => 'admin.website-admin.seo.profile.index',
'can' => 'admin.website-admin.seo.profile.view',
'description' => 'Define metadatos, OG y Twitter Cards del sitio.',
],
'JSON-LD y Schema.org' => [
'icon' => 'ti ti-code-dots',
'route' => 'admin.website-admin.seo.jsonld.index',
'can' => 'admin.website-admin.seo.jsonld.view',
'description' => 'Configura estructuras para Google y otros buscadores.',
],
'Mapa del sitio y Robots' => [
'icon' => 'ti ti-hierarchy',
'route' => 'admin.website-admin.seo.sitemap.index',
'can' => 'admin.website-admin.seo.sitemap.view',
'description' => 'Controla el sitemap.xml y robots.txt globalmente.',
],
],
],
'CMS Koneko' => [
'_meta' => [
'icon' => 'ti ti-layout-dashboard',
'description' => 'Gestión de contenido visual, bloques, menús y plantillas.',
'widget_label' => 'Editor de Contenido CMS',
'home_at_root' => true,
'priority' => 300,
],
'submenu' => [
'Páginas y bloques' => [
'icon' => 'ti ti-file-text',
'route' => 'admin.website-admin.cms.contents.index',
'can' => 'admin.website-admin.cms.contents.view',
'description' => 'Administra contenido dinámico estructurado por bloques.',
],
'Menús del sitio' => [
'icon' => 'ti ti-hierarchy-3',
'route' => 'admin.website-admin.cms.menus.index',
'can' => 'admin.website-admin.cms.menus.view',
'description' => 'Gestiona la navegación del sitio.',
],
'Versiones y previews' => [
'icon' => 'ti ti-clock-edit',
'route' => 'admin.website-admin.cms.versions.index',
'can' => 'admin.website-admin.cms.versions.view',
'description' => 'Historial de versiones de contenido y vista previa.',
],
'Plantillas' => [
'icon' => 'ti ti-template',
'route' => 'admin.website-admin.cms.templates.index',
'can' => 'admin.website-admin.cms.templates.view',
'description' => 'Gestiona y asigna plantillas de presentación.',
],
],
],
'Integraciones API' => [
'_meta' => [
'icon' => 'ti ti-plug',
'description' => 'Configura APIs y servicios externos como Analytics o Chat.',
'widget_label' => 'Extensiones y APIs',
'home_at_root' => true,
'priority' => 400,
],
'submenu' => [
'Google & Meta' => [
'icon' => 'ti ti-brand-google',
'route' => 'admin.website-admin.integrations.analytics.index',
'can' => 'admin.website-admin.integrations.analytics.view',
'description' => 'Google Analytics, Search Console, Pixel Meta, etc.',
],
'Chat y comunicación' => [
'icon' => 'ti ti-message-dots',
'route' => 'admin.website-admin.integrations.chat.index',
'can' => 'admin.website-admin.integrations.chat.view',
'description' => 'Messenger, WhatsApp, Tawk.to y más.',
],
'Traducción e idioma' => [
'icon' => 'ti ti-language',
'route' => 'admin.website-admin.integrations.translate.index',
'can' => 'admin.website-admin.integrations.translate.view',
'description' => 'Integraciones como Google Translate o DeepL.',
],
],
],
'Sistema de Cache' => [
'_meta' => [
'icon' => 'ti ti-database-cog',
'description' => 'Herramientas avanzadas de rendimiento y renderizado.',
'widget_label' => 'Motor de Cache',
'home_at_root' => true,
'priority' => 500,
],
'submenu' => [
'HTML completo' => [
'icon' => 'ti ti-file-type-html',
'route' => 'admin.website-admin.cache.full.index',
'can' => 'admin.website-admin.cache.full.view',
'description' => 'Gestiona caché render de páginas completas.',
],
'Bloques de contenido' => [
'icon' => 'ti ti-box-model',
'route' => 'admin.website-admin.cache.blocks.index',
'can' => 'admin.website-admin.cache.blocks.view',
'description' => 'Visualiza y limpia caché por bloques individuales.',
],
'Previews firmadas' => [
'icon' => 'ti ti-key',
'route' => 'admin.website-admin.cache.previews.index',
'can' => 'admin.website-admin.cache.previews.view',
'description' => 'Controla la vigencia y firma de URLs temporales.',
],
],
],
'Blog' => [
'_meta' => [
'icon' => 'ti ti-news',
'description' => 'Publica, edita y organiza artículos, categorías y comentarios de tu blog.',
'after_to' => 'Web & SEO',
],
'submenu' => [
'Categorias' => [
'icon' => 'ti ti-category',
'route' => 'admin.website-admin.blog.categories.index',
'can' => 'admin.website-admin.blog.categories.view',
],
'Etiquetas' => [
'icon' => 'ti ti-tags',
'route' => 'admin.website-admin.blog.tags.index',
'can' => 'admin.website-admin.blog.tags.view',
],
'Articulos' => [
'icon' => 'ti ti-news',
'route' => 'admin.website-admin.blog.articles.index',
'can' => 'admin.website-admin.blog.articles.view',
],
'Comentarios' => [
'icon' => 'ti ti-message',
'route' => 'admin.website-admin.blog.comments.index',
'can' => 'admin.website-admin.blog.comments.view',
],
]
],
'Plantillas' => [
'_meta' => [
'icon' => 'ti ti-template',
'description' => 'Gestiona las plantillas disponibles para tu sitio web.',
'after_to' => 'Blog',
]
],
];

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,280 @@
{
"SuperAdmin" : {
"permissions" : [
"admin.website-admin.settings.general.view",
"admin.website-admin.settings.social.view",
"admin.website-admin.settings.indexing.view",
"admin.website-admin.contact.info.view",
"admin.website-admin.contact.form.view",
"admin.website-admin.comunication.messenger.view",
"admin.website-admin.comunication.whatsapp.view",
"admin.website-admin.comunication.tawk-to.view",
"admin.website-admin.comunication.twitter.view",
"admin.website-admin.translate.google-translate.view",
"admin.website-admin.translate.google-translate.update",
"admin.website-admin.cms.menus.view",
"admin.website-admin.cms.menus.update",
"admin.website-admin.cms.seo.view",
"admin.website-admin.cms.seo.update",
"admin.website-admin.cms.contents.view",
"admin.website-admin.cms.contents.create",
"admin.website-admin.cms.contents.update",
"admin.website-admin.cms.contents.delete",
"admin.website-admin.cms.versions.view",
"admin.website-admin.cms.versions.reopen",
"admin.website-admin.cms.templates.view",
"admin.website-admin.cms.templates.update",
"admin.website-admin.website.cache.fullpage.view",
"admin.website-admin.website.cache.fullpage.clean",
"admin.website-admin.website.cache.signed-previews.view",
"admin.website-admin.website.cache.signed-previews.clean",
"admin.website-admin.content.faq.view",
"admin.website-admin.content.faq.create",
"admin.website-admin.content.faq.update",
"admin.website-admin.content.faq.delete",
"admin.website-admin.content.gallery.view",
"admin.website-admin.content.gallery.create",
"admin.website-admin.content.gallery.delete",
"admin.website-admin.content.legal.view",
"admin.website-admin.content.legal.update",
"admin.website-admin.analytics.google-analytics.view",
"admin.website-admin.analytics.google-tags.view",
"admin.website-admin.analytics.google-search-console.view",
"admin.website-admin.analytics.pixel-meta.view",
"admin.website-admin.seo-tools.sitemap.view",
"admin.website-admin.seo-tools.jsonld.view",
"admin.website-admin.seo-tools.robots.view",
"admin.website-admin.seo-tools.manifest.view",
"admin.website-admin.seo-tools.canonical.view",
"admin.website-admin.seo-tools.social-cards.view",
"admin.website-admin.blog.categories.view",
"admin.website-admin.blog.categories.create",
"admin.website-admin.blog.categories.update",
"admin.website-admin.blog.categories.delete",
"admin.website-admin.blog.tags.view",
"admin.website-admin.blog.tags.create",
"admin.website-admin.blog.tags.update",
"admin.website-admin.blog.tags.delete",
"admin.website-admin.blog.articles.view",
"admin.website-admin.blog.articles.create",
"admin.website-admin.blog.articles.update",
"admin.website-admin.blog.articles.delete",
"admin.website-admin.blog.articles.publish",
"admin.website-admin.blog.articles.archive",
"admin.website-admin.blog.comments.view",
"admin.website-admin.blog.comments.delete",
"admin.website-admin.blog.comments.approve",
"admin.website-admin.blog.comments.cancel"
]
},
"WebsiteAdmin": {
"_meta": {
"description": {
"es": "Gestiona contenidos, menús, SEO y configuración del sitio web.",
"en": "Manages contents, menus, SEO, and website settings."
},
"icon": "ti ti-world",
"style": "warning"
},
"permissions" : [
"admin.website-admin.settings.general.view",
"admin.website-admin.settings.social.view",
"admin.website-admin.settings.indexing.view",
"admin.website-admin.contact.info.view",
"admin.website-admin.contact.form.view",
"admin.website-admin.comunication.messenger.view",
"admin.website-admin.comunication.whatsapp.view",
"admin.website-admin.comunication.tawk-to.view",
"admin.website-admin.comunication.twitter.view",
"admin.website-admin.translate.google-translate.view",
"admin.website-admin.translate.google-translate.update",
"admin.website-admin.cms.menus.view",
"admin.website-admin.cms.menus.update",
"admin.website-admin.cms.seo.view",
"admin.website-admin.cms.seo.update",
"admin.website-admin.cms.contents.view",
"admin.website-admin.cms.contents.create",
"admin.website-admin.cms.contents.update",
"admin.website-admin.cms.contents.delete",
"admin.website-admin.cms.versions.view",
"admin.website-admin.cms.versions.reopen",
"admin.website-admin.cms.templates.view",
"admin.website-admin.cms.templates.update",
"admin.website-admin.website.cache.fullpage.view",
"admin.website-admin.website.cache.fullpage.clean",
"admin.website-admin.website.cache.signed-previews.view",
"admin.website-admin.website.cache.signed-previews.clean",
"admin.website-admin.content.faq.view",
"admin.website-admin.content.faq.create",
"admin.website-admin.content.faq.update",
"admin.website-admin.content.faq.delete",
"admin.website-admin.content.gallery.view",
"admin.website-admin.content.gallery.create",
"admin.website-admin.content.gallery.delete",
"admin.website-admin.content.legal.view",
"admin.website-admin.content.legal.update",
"admin.website-admin.analytics.google-analytics.view",
"admin.website-admin.analytics.google-tags.view",
"admin.website-admin.analytics.google-search-console.view",
"admin.website-admin.analytics.pixel-meta.view",
"admin.website-admin.seo-tools.sitemap.view",
"admin.website-admin.seo-tools.jsonld.view",
"admin.website-admin.seo-tools.robots.view",
"admin.website-admin.seo-tools.manifest.view",
"admin.website-admin.seo-tools.canonical.view",
"admin.website-admin.seo-tools.social-cards.view",
"admin.website-admin.blog.categories.view",
"admin.website-admin.blog.categories.create",
"admin.website-admin.blog.categories.update",
"admin.website-admin.blog.categories.delete",
"admin.website-admin.blog.tags.view",
"admin.website-admin.blog.tags.create",
"admin.website-admin.blog.tags.update",
"admin.website-admin.blog.tags.delete",
"admin.website-admin.blog.articles.view",
"admin.website-admin.blog.articles.create",
"admin.website-admin.blog.articles.update",
"admin.website-admin.blog.articles.delete",
"admin.website-admin.blog.articles.publish",
"admin.website-admin.blog.articles.archive",
"admin.website-admin.blog.comments.view",
"admin.website-admin.blog.comments.delete",
"admin.website-admin.blog.comments.approve",
"admin.website-admin.blog.comments.cancel"
]
},
"WebsiteContentEditor": {
"_meta": {
"description": {
"es": "Puede crear, editar y publicar contenidos y artículos del blog.",
"en": "Can create, edit, and publish content and blog posts."
},
"icon": "ti ti-article",
"style": "info"
},
"permissions": [
"admin.website-admin.cms.menus.view",
"admin.website-admin.cms.menus.update",
"admin.website-admin.cms.seo.view",
"admin.website-admin.cms.seo.update",
"admin.website-admin.cms.contents.view",
"admin.website-admin.cms.contents.create",
"admin.website-admin.cms.contents.update",
"admin.website-admin.cms.contents.delete",
"admin.website-admin.cms.versions.view",
"admin.website-admin.cms.templates.view",
"admin.website-admin.website.cache.fullpage.view",
"admin.website-admin.website.cache.fullpage.clean",
"admin.website-admin.website.cache.signed-previews.view",
"admin.website-admin.website.cache.signed-previews.clean",
"admin.website-admin.content.faq.view",
"admin.website-admin.content.faq.create",
"admin.website-admin.content.faq.update",
"admin.website-admin.content.faq.delete",
"admin.website-admin.content.gallery.view",
"admin.website-admin.content.gallery.create",
"admin.website-admin.content.gallery.delete",
"admin.website-admin.content.legal.view",
"admin.website-admin.content.legal.update",
"admin.website-admin.seo-tools.sitemap.view",
"admin.website-admin.seo-tools.jsonld.view",
"admin.website-admin.seo-tools.robots.view",
"admin.website-admin.seo-tools.manifest.view",
"admin.website-admin.seo-tools.canonical.view",
"admin.website-admin.seo-tools.social-cards.view" ]
},
"BlogEditor": {
"_meta": {
"description": {
"es": "Puede crear, editar y publicar contenidos y artículos del blog.",
"en": "Can create, edit, and publish content and blog posts."
},
"icon": "ti ti-article",
"style": "info"
},
"permissions": [
"admin.website-admin.blog.categories.view",
"admin.website-admin.blog.categories.create",
"admin.website-admin.blog.categories.update",
"admin.website-admin.blog.categories.delete",
"admin.website-admin.blog.tags.view",
"admin.website-admin.blog.tags.create",
"admin.website-admin.blog.tags.update",
"admin.website-admin.blog.tags.delete",
"admin.website-admin.blog.articles.view",
"admin.website-admin.blog.articles.create",
"admin.website-admin.blog.articles.update",
"admin.website-admin.blog.articles.delete",
"admin.website-admin.blog.articles.publish",
"admin.website-admin.blog.articles.archive",
"admin.website-admin.blog.comments.view",
"admin.website-admin.blog.comments.delete",
"admin.website-admin.blog.comments.approve",
"admin.website-admin.blog.comments.cancel"
]
},
"WebsiteSEO": {
"_meta": {
"description": {
"es": "Gestiona herramientas SEO, Sitemap, Robots y JSON-LD.",
"en": "Manages SEO tools, Sitemap, Robots, and JSON-LD."
},
"icon": "ti ti-chart-arcs",
"style": "warning"
},
"permissions": [
"admin.website-admin.settings.general.view",
"admin.website-admin.settings.indexing.view",
"admin.website-admin.analytics.google-analytics.view",
"admin.website-admin.analytics.google-tags.view",
"admin.website-admin.analytics.google-search-console.view",
"admin.website-admin.analytics.pixel-meta.view",
"admin.website-admin.seo-tools.sitemap.view",
"admin.website-admin.seo-tools.jsonld.view",
"admin.website-admin.seo-tools.robots.view",
"admin.website-admin.seo-tools.manifest.view",
"admin.website-admin.seo-tools.canonical.view",
"admin.website-admin.seo-tools.social-cards.view"
]
},
"Auditor" : {
"permissions" : [
"admin.website-admin.settings.general.view",
"admin.website-admin.settings.social.view",
"admin.website-admin.settings.indexing.view",
"admin.website-admin.contact.info.view",
"admin.website-admin.contact.form.view",
"admin.website-admin.comunication.messenger.view",
"admin.website-admin.comunication.whatsapp.view",
"admin.website-admin.comunication.tawk-to.view",
"admin.website-admin.comunication.twitter.view",
"admin.website-admin.translate.google-translate.view",
"admin.website-admin.cms.menus.view",
"admin.website-admin.cms.seo.view",
"admin.website-admin.cms.contents.view",
"admin.website-admin.cms.versions.view",
"admin.website-admin.cms.templates.view",
"admin.website-admin.website.cache.fullpage.view",
"admin.website-admin.website.cache.signed-previews.view",
"admin.website-admin.content.faq.view",
"admin.website-admin.content.gallery.view",
"admin.website-admin.content.legal.view",
"admin.website-admin.analytics.google-analytics.view",
"admin.website-admin.analytics.google-tags.view",
"admin.website-admin.analytics.google-search-console.view",
"admin.website-admin.analytics.pixel-meta.view",
"admin.website-admin.seo-tools.sitemap.view",
"admin.website-admin.seo-tools.jsonld.view",
"admin.website-admin.seo-tools.robots.view",
"admin.website-admin.seo-tools.manifest.view",
"admin.website-admin.seo-tools.canonical.view",
"admin.website-admin.seo-tools.social-cards.view",
"admin.website-admin.blog.categories.view",
"admin.website-admin.blog.tags.view",
"admin.website-admin.blog.articles.view",
"admin.website-admin.blog.comments.view"
]
}
}

View File

@ -0,0 +1,192 @@
[
{
"site_id": 1,
"title": "Agroform",
"slug": "",
"description": "Bienvenido a agroform, soluciones tecnológicas para empresas.",
"keywords": ["agroform", "erp", "tecnología", "soluciones"],
"template": "home",
"type": "page",
"is_partial": false,
"seo_profile_id": "inicio-agroform",
"seo_overrides": null,
"canonical_url": "https://agroform.com.mx",
"content_blocks": [
{"type": "hero", "title": "Soluciones Tecnológicas para tu Empresa", "subtitle": "Desde ERP hasta eCommerce", "image": "/images/hero.jpg"},
{"type": "features", "items": [{"icon": "ti ti-server", "label": "Infraestructura"}, {"icon": "ti ti-code", "label": "Desarrollo a medida"}]},
{"type": "cta", "text": "Solicita una demo sin costo", "button": "Agendar llamada"}
],
"is_draft": false,
"is_sensitive": false
},
{
"site_id": 1,
"title": "Nosotros",
"slug": "nosotros",
"description": "Conoce la historia, visión y equipo de Koneko.",
"keywords": ["nosotros", "equipo", "historia", "koneko"],
"template": "default",
"type": "page",
"is_partial": false,
"seo_profile_id": "inicio-agroform",
"seo_overrides": null,
"canonical_url": "https://agroform.com.mx/nosotros",
"content_blocks": [
{"type": "text", "heading": "¿Quiénes somos?", "content": "Somos una empresa de tecnología con sede en México..."},
{"type": "team", "members": [{"name": "Arturo", "role": "Director Técnico"}, {"name": "Laura", "role": "Marketing"}]}
],
"is_draft": false,
"is_sensitive": false
},
{
"site_id": 1,
"title": "Servicios",
"slug": "servicios",
"description": "Explora nuestros servicios: ERP, eCommerce, hosting y más.",
"keywords": ["erp", "servicios", "agroform", "sistemas"],
"template": "services",
"type": "page",
"is_partial": false,
"seo_profile_id": "servicios-agroform",
"seo_overrides": null,
"canonical_url": "https://agroform.com.mx/servicios",
"content_blocks": [
{"type": "service_list", "items": [
{"title": "ERP Agroform", "description": "Sistema de gestión empresarial completo"},
{"title": "Tienda Virtual", "description": "Ecommerce 100% administrable con SEO nativo"},
{"title": "Infraestructura", "description": "Servidores, VPS, Proxmox y más"}
]}
],
"is_draft": false,
"is_sensitive": false
},
{
"site_id": 1,
"title": "Contacto",
"slug": "contacto",
"description": "Contáctanos para resolver tus dudas o agendar una demo.",
"keywords": ["contacto", "soporte", "demo", "ayuda"],
"template": "contact",
"type": "page",
"is_partial": false,
"seo_profile_id": null,
"seo_overrides": null,
"canonical_url": "https://agroform.com.mx/contacto",
"content_blocks": [
{"type": "form", "fields": ["nombre", "email", "mensaje"], "submit_label": "Enviar mensaje"},
{"type": "map", "lat": 19.4326, "lng": -99.1332}
],
"is_draft": false,
"is_sensitive": false
},
{
"site_id": 1,
"title": "Aviso de Privacidad",
"slug": "aviso-privacidad",
"description": "Consulta nuestro aviso de privacidad actualizado.",
"keywords": ["legal", "privacidad", "datos personales"],
"template": "legal",
"type": "page",
"is_partial": false,
"seo_profile_id": null,
"seo_overrides": null,
"canonical_url": "https://agroform.com.mx/aviso-privacidad",
"content_blocks": [
{"type": "text", "heading": "Política de privacidad", "content": "Tus datos son importantes para nosotros..."}
],
"is_draft": false,
"is_sensitive": false
},
{
"site_id": 1,
"title": "Preguntas Frecuentes",
"slug": "faq",
"description": "Resuelve tus dudas rápidamente con nuestras respuestas frecuentes.",
"keywords": ["faq", "dudas", "soporte"],
"template": "faq",
"type": "page",
"is_partial": true,
"seo_profile_id": null,
"seo_overrides": null,
"canonical_url": null,
"content_blocks": [
{"type": "faq", "items": [
{"q": "¿Tienen soporte técnico?", "a": "Sí, disponible 24/7 para clientes activos."},
{"q": "¿Qué formas de pago aceptan?", "a": "Transferencia, tarjeta y criptomonedas."}
]}
],
"is_draft": false,
"is_sensitive": false
},
{
"site_id": 1,
"title": "Header Principal",
"slug": "header-principal",
"description": "Encabezado superior con navegación.",
"keywords": [],
"template": null,
"type": "partial",
"is_partial": true,
"seo_profile_id": 1,
"seo_overrides": null,
"canonical_url": null,
"content_blocks": [
{"type": "menu", "menu_slug": "principal"}
],
"is_draft": false,
"is_sensitive": false
},
{
"site_id": 1,
"title": "Footer General",
"slug": "footer-general",
"description": "Pie de página con enlaces y datos legales.",
"keywords": [],
"template": null,
"type": "partial",
"is_partial": true,
"seo_profile_id": null,
"seo_overrides": null,
"canonical_url": null,
"content_blocks": [
{"type": "footer", "links": ["inicio", "servicios", "contacto"]}
],
"is_draft": false,
"is_sensitive": false
},
{
"site_id": 1,
"title": "Categoría: Blog",
"slug": "blog",
"description": "Explora nuestros artículos de tecnología y negocios.",
"keywords": ["blog", "noticias", "tips", "artículos"],
"template": "blog_index",
"type": "category",
"is_partial": false,
"seo_profile_id": "blog",
"seo_overrides": null,
"canonical_url": "https://agroform.com.mx/blog",
"content_blocks": [],
"is_draft": false,
"is_sensitive": false
},
{
"site_id": 1,
"title": "Artículo: Ventajas del ERP",
"slug": "blog/ventajas-del-erp",
"description": "Descubre cómo un ERP puede transformar tu empresa.",
"keywords": ["erp", "ventajas", "productividad", "sistemas"],
"template": "blog_article",
"type": "blog",
"is_partial": false,
"seo_profile_id": "promocion-computadoras-gamer",
"seo_overrides": null,
"canonical_url": "https://agroform.com.mx/blog/ventajas-del-erp",
"content_blocks": [
{"type": "text", "heading": "Beneficios del ERP", "content": "Centralización de procesos, automatización..."},
{"type": "image", "src": "/images/blog/erp-benefits.jpg", "alt": "ERP y eficiencia empresarial"}
],
"is_draft": false,
"is_sensitive": false
}
]

View File

@ -0,0 +1,66 @@
[
{
"menu_slug": "main-header",
"title": {
"es": "Inicio",
"en": "Home"
},
"url": "/",
"type": "custom",
"target": "_self",
"order": 1,
"icon": "ti ti-home"
},
{
"menu_slug": "main-header",
"title": {
"es": "Artículos",
"en": "Articles"
},
"url": "/blog",
"type": "blog_article",
"target": "_self",
"order": 2,
"icon": "ti ti-news"
},
{
"menu_slug": "main-header",
"title": {
"es": "Categorías",
"en": "Categories"
},
"url": "/blog/categorias",
"type": "blog_category",
"target": "_self",
"order": 3,
"icon": "ti ti-list"
},
{
"menu_slug": "main-header",
"title": {
"es": "Iniciar Sesión",
"en": "Login"
},
"url": "/login",
"type": "custom",
"target": "_self",
"order": 4,
"icon": "ti ti-login",
"badge": "Nuevo",
"badge_color": "bg-success"
},
{
"menu_slug": "main-header",
"title": {
"es": "Cerrar Sesión",
"en": "Logout"
},
"url": "/logout",
"type": "action",
"target": "_self",
"order": 5,
"icon": "ti ti-logout",
"method": "POST",
"roles": ["authenticated"]
}
]

View File

@ -0,0 +1,192 @@
[
{
"site_id": 2,
"title": "Cleanfy",
"slug": "",
"description": "Bienvenido a cleanfy, soluciones tecnológicas para empresas.",
"keywords": ["cleanfy", "erp", "tecnología", "soluciones"],
"template": "home",
"type": "page",
"is_partial": false,
"seo_profile_id": "inicio-cleanfy",
"seo_overrides": null,
"canonical_url": "https://cleanfy.mx",
"content_blocks": [
{"type": "hero", "title": "Soluciones Tecnológicas para tu Empresa", "subtitle": "Desde ERP hasta eCommerce", "image": "/images/hero.jpg"},
{"type": "features", "items": [{"icon": "ti ti-server", "label": "Infraestructura"}, {"icon": "ti ti-code", "label": "Desarrollo a medida"}]},
{"type": "cta", "text": "Solicita una demo sin costo", "button": "Agendar llamada"}
],
"is_draft": false,
"is_sensitive": false
},
{
"site_id": 2,
"title": "Nosotros",
"slug": "nosotros",
"description": "Conoce la historia, visión y equipo de Koneko.",
"keywords": ["nosotros", "equipo", "historia", "koneko"],
"template": "default",
"type": "page",
"is_partial": false,
"seo_profile_id": "inicio-cleanfy",
"seo_overrides": null,
"canonical_url": "https://cleanfy.mx/nosotros",
"content_blocks": [
{"type": "text", "heading": "¿Quiénes somos?", "content": "Somos una empresa de tecnología con sede en México..."},
{"type": "team", "members": [{"name": "Arturo", "role": "Director Técnico"}, {"name": "Laura", "role": "Marketing"}]}
],
"is_draft": false,
"is_sensitive": false
},
{
"site_id": 2,
"title": "Servicios",
"slug": "servicios",
"description": "Explora nuestros servicios: ERP, eCommerce, hosting y más.",
"keywords": ["erp", "servicios", "cleanfy", "sistemas"],
"template": "services",
"type": "page",
"is_partial": false,
"seo_profile_id": "servicios-cleanfy",
"seo_overrides": null,
"canonical_url": "https://cleanfy.mx/servicios",
"content_blocks": [
{"type": "service_list", "items": [
{"title": "ERP Cleanfy", "description": "Sistema de gestión empresarial completo"},
{"title": "Tienda Virtual", "description": "Ecommerce 100% administrable con SEO nativo"},
{"title": "Infraestructura", "description": "Servidores, VPS, Proxmox y más"}
]}
],
"is_draft": false,
"is_sensitive": false
},
{
"site_id": 2,
"title": "Contacto",
"slug": "contacto",
"description": "Contáctanos para resolver tus dudas o agendar una demo.",
"keywords": ["contacto", "soporte", "demo", "ayuda"],
"template": "contact",
"type": "page",
"is_partial": false,
"seo_profile_id": null,
"seo_overrides": null,
"canonical_url": "https://cleanfy.mx/contacto",
"content_blocks": [
{"type": "form", "fields": ["nombre", "email", "mensaje"], "submit_label": "Enviar mensaje"},
{"type": "map", "lat": 19.4326, "lng": -99.1332}
],
"is_draft": false,
"is_sensitive": false
},
{
"site_id": 2,
"title": "Aviso de Privacidad",
"slug": "aviso-privacidad",
"description": "Consulta nuestro aviso de privacidad actualizado.",
"keywords": ["legal", "privacidad", "datos personales"],
"template": "legal",
"type": "page",
"is_partial": false,
"seo_profile_id": null,
"seo_overrides": null,
"canonical_url": "https://cleanfy.mx/aviso-privacidad",
"content_blocks": [
{"type": "text", "heading": "Política de privacidad", "content": "Tus datos son importantes para nosotros..."}
],
"is_draft": false,
"is_sensitive": false
},
{
"site_id": 2,
"title": "Preguntas Frecuentes",
"slug": "faq",
"description": "Resuelve tus dudas rápidamente con nuestras respuestas frecuentes.",
"keywords": ["faq", "dudas", "soporte"],
"template": "faq",
"type": "page",
"is_partial": true,
"seo_profile_id": null,
"seo_overrides": null,
"canonical_url": null,
"content_blocks": [
{"type": "faq", "items": [
{"q": "¿Tienen soporte técnico?", "a": "Sí, disponible 24/7 para clientes activos."},
{"q": "¿Qué formas de pago aceptan?", "a": "Transferencia, tarjeta y criptomonedas."}
]}
],
"is_draft": false,
"is_sensitive": false
},
{
"site_id": 2,
"title": "Header Principal",
"slug": "header-principal",
"description": "Encabezado superior con navegación.",
"keywords": [],
"template": null,
"type": "partial",
"is_partial": true,
"seo_profile_id": 1,
"seo_overrides": null,
"canonical_url": null,
"content_blocks": [
{"type": "menu", "menu_slug": "principal"}
],
"is_draft": false,
"is_sensitive": false
},
{
"site_id": 2,
"title": "Footer General",
"slug": "footer-general",
"description": "Pie de página con enlaces y datos legales.",
"keywords": [],
"template": null,
"type": "partial",
"is_partial": true,
"seo_profile_id": null,
"seo_overrides": null,
"canonical_url": null,
"content_blocks": [
{"type": "footer", "links": ["inicio", "servicios", "contacto"]}
],
"is_draft": false,
"is_sensitive": false
},
{
"site_id": 2,
"title": "Categoría: Blog",
"slug": "blog",
"description": "Explora nuestros artículos de tecnología y negocios.",
"keywords": ["blog", "noticias", "tips", "artículos"],
"template": "blog_index",
"type": "category",
"is_partial": false,
"seo_profile_id": "blog",
"seo_overrides": null,
"canonical_url": "https://cleanfy.mx/blog",
"content_blocks": [],
"is_draft": false,
"is_sensitive": false
},
{
"site_id": 2,
"title": "Artículo: Ventajas del ERP",
"slug": "blog/ventajas-del-erp",
"description": "Descubre cómo un ERP puede transformar tu empresa.",
"keywords": ["erp", "ventajas", "productividad", "sistemas"],
"template": "blog_article",
"type": "blog",
"is_partial": false,
"seo_profile_id": "promocion-computadoras-gamer",
"seo_overrides": null,
"canonical_url": "https://cleanfy.mx/blog/ventajas-del-erp",
"content_blocks": [
{"type": "text", "heading": "Beneficios del ERP", "content": "Centralización de procesos, automatización..."},
{"type": "image", "src": "/images/blog/erp-benefits.jpg", "alt": "ERP y eficiencia empresarial"}
],
"is_draft": false,
"is_sensitive": false
}
]

View File

@ -0,0 +1,74 @@
[
{
"menu_slug": "main-header",
"title": {
"es": "Inicio",
"en": "Home"
},
"route_name": "website.home",
"type": "custom",
"target": "_self",
"order": 1,
"icon": "ti ti-home"
},
{
"menu_slug": "main-header",
"title": {
"es": "Nosotros",
"en": "About Us"
},
"route_name": "website.about",
"type": "custom",
"target": "_self",
"order": 2,
"icon": "ti ti-users"
},
{
"menu_slug": "main-header",
"title": {
"es": "Servicios",
"en": "Services"
},
"route_name": "website.services",
"type": "custom",
"target": "_self",
"order": 3,
"icon": "ti ti-briefcase"
},
{
"menu_slug": "main-header",
"title": {
"es": "Portafolio",
"en": "Portfolio"
},
"route_name": "website.portfolio",
"type": "custom",
"target": "_self",
"order": 4,
"icon": "ti ti-photo"
},
{
"menu_slug": "main-header",
"title": {
"es": "Testimonios",
"en": "Testimonials"
},
"route_name": "website.testimonials",
"type": "custom",
"target": "_self",
"order": 5,
"icon": "ti ti-messages"
},
{
"menu_slug": "main-header",
"title": {
"es": "Contacto",
"en": "Contact"
},
"route_name": "website.contact",
"type": "custom",
"target": "_self",
"order": 6,
"icon": "ti ti-phone-call"
}
]

View File

@ -0,0 +1,44 @@
[
{
"site_id": 1,
"slug": "main-header",
"title": "Menú Principal",
"description": "Navegación principal del sitio web Cleanfy.",
"is_active": true
},
{
"site_id": 1,
"slug": "footer",
"title": "Menú Footer",
"description": "Navegación del footer del sitio web Cleanfy.",
"is_active": true
},
{
"site_id": 2,
"slug": "main-header",
"title": "Menú Principal",
"description": "Navegación principal del sitio web Agroform.",
"is_active": true
},
{
"site_id": 2,
"slug": "footer",
"title": "Menú Footer",
"description": "Navegación del footer del sitio web Agroform.",
"is_active": true
},
{
"site_id": 3,
"slug": "main-header",
"title": "Menú Principal",
"description": "Navegación principal del sitio web Realcity.",
"is_active": true
},
{
"site_id": 3,
"slug": "footer",
"title": "Menú Footer",
"description": "Navegación del footer del sitio web Realcity.",
"is_active": true
}
]

View File

@ -0,0 +1,192 @@
[
{
"site_id": 3,
"title": "Realcity",
"slug": "",
"description": "Bienvenido a realcity, soluciones tecnológicas para empresas.",
"keywords": ["realcity", "erp", "tecnología", "soluciones"],
"template": "home",
"type": "page",
"is_partial": false,
"seo_profile_id": "inicio-realcity",
"seo_overrides": null,
"canonical_url": "https://realcity.com.mx",
"content_blocks": [
{"type": "hero", "title": "Soluciones Tecnológicas para tu Empresa", "subtitle": "Desde ERP hasta eCommerce", "image": "/images/hero.jpg"},
{"type": "features", "items": [{"icon": "ti ti-server", "label": "Infraestructura"}, {"icon": "ti ti-code", "label": "Desarrollo a medida"}]},
{"type": "cta", "text": "Solicita una demo sin costo", "button": "Agendar llamada"}
],
"is_draft": false,
"is_sensitive": false
},
{
"site_id": 3,
"title": "Nosotros",
"slug": "nosotros",
"description": "Conoce la historia, visión y equipo de Koneko.",
"keywords": ["nosotros", "equipo", "historia", "koneko"],
"template": "default",
"type": "page",
"is_partial": false,
"seo_profile_id": "inicio-realcity",
"seo_overrides": null,
"canonical_url": "https://realcity.com.mx/nosotros",
"content_blocks": [
{"type": "text", "heading": "¿Quiénes somos?", "content": "Somos una empresa de tecnología con sede en México..."},
{"type": "team", "members": [{"name": "Arturo", "role": "Director Técnico"}, {"name": "Laura", "role": "Marketing"}]}
],
"is_draft": false,
"is_sensitive": false
},
{
"site_id": 3,
"title": "Servicios",
"slug": "servicios",
"description": "Explora nuestros servicios: ERP, eCommerce, hosting y más.",
"keywords": ["erp", "servicios", "realcity", "sistemas"],
"template": "services",
"type": "page",
"is_partial": false,
"seo_profile_id": "servicios-realcity",
"seo_overrides": null,
"canonical_url": "https://realcity.com.mx/servicios",
"content_blocks": [
{"type": "service_list", "items": [
{"title": "ERP Realcity", "description": "Sistema de gestión empresarial completo"},
{"title": "Tienda Virtual", "description": "Ecommerce 100% administrable con SEO nativo"},
{"title": "Infraestructura", "description": "Servidores, VPS, Proxmox y más"}
]}
],
"is_draft": false,
"is_sensitive": false
},
{
"site_id": 3,
"title": "Contacto",
"slug": "contacto",
"description": "Contáctanos para resolver tus dudas o agendar una demo.",
"keywords": ["contacto", "soporte", "demo", "ayuda"],
"template": "contact",
"type": "page",
"is_partial": false,
"seo_profile_id": null,
"seo_overrides": null,
"canonical_url": "https://realcity.com.mx/contacto",
"content_blocks": [
{"type": "form", "fields": ["nombre", "email", "mensaje"], "submit_label": "Enviar mensaje"},
{"type": "map", "lat": 19.4326, "lng": -99.1332}
],
"is_draft": false,
"is_sensitive": false
},
{
"site_id": 3,
"title": "Aviso de Privacidad",
"slug": "aviso-privacidad",
"description": "Consulta nuestro aviso de privacidad actualizado.",
"keywords": ["legal", "privacidad", "datos personales"],
"template": "legal",
"type": "page",
"is_partial": false,
"seo_profile_id": null,
"seo_overrides": null,
"canonical_url": "https://realcity.com.mx/aviso-privacidad",
"content_blocks": [
{"type": "text", "heading": "Política de privacidad", "content": "Tus datos son importantes para nosotros..."}
],
"is_draft": false,
"is_sensitive": false
},
{
"site_id": 3,
"title": "Preguntas Frecuentes",
"slug": "faq",
"description": "Resuelve tus dudas rápidamente con nuestras respuestas frecuentes.",
"keywords": ["faq", "dudas", "soporte"],
"template": "faq",
"type": "page",
"is_partial": true,
"seo_profile_id": null,
"seo_overrides": null,
"canonical_url": null,
"content_blocks": [
{"type": "faq", "items": [
{"q": "¿Tienen soporte técnico?", "a": "Sí, disponible 24/7 para clientes activos."},
{"q": "¿Qué formas de pago aceptan?", "a": "Transferencia, tarjeta y criptomonedas."}
]}
],
"is_draft": false,
"is_sensitive": false
},
{
"site_id": 3,
"title": "Header Principal",
"slug": "header-principal",
"description": "Encabezado superior con navegación.",
"keywords": [],
"template": null,
"type": "partial",
"is_partial": true,
"seo_profile_id": 1,
"seo_overrides": null,
"canonical_url": null,
"content_blocks": [
{"type": "menu", "menu_slug": "principal"}
],
"is_draft": false,
"is_sensitive": false
},
{
"site_id": 3,
"title": "Footer General",
"slug": "footer-general",
"description": "Pie de página con enlaces y datos legales.",
"keywords": [],
"template": null,
"type": "partial",
"is_partial": true,
"seo_profile_id": null,
"seo_overrides": null,
"canonical_url": null,
"content_blocks": [
{"type": "footer", "links": ["inicio", "servicios", "contacto"]}
],
"is_draft": false,
"is_sensitive": false
},
{
"site_id": 3,
"title": "Categoría: Blog",
"slug": "blog",
"description": "Explora nuestros artículos de tecnología y negocios.",
"keywords": ["blog", "noticias", "tips", "artículos"],
"template": "blog_index",
"type": "category",
"is_partial": false,
"seo_profile_id": "blog",
"seo_overrides": null,
"canonical_url": "https://realcity.com.mx/blog",
"content_blocks": [],
"is_draft": false,
"is_sensitive": false
},
{
"site_id": 3,
"title": "Artículo: Ventajas del ERP",
"slug": "blog/ventajas-del-erp",
"description": "Descubre cómo un ERP puede transformar tu empresa.",
"keywords": ["erp", "ventajas", "productividad", "sistemas"],
"template": "blog_article",
"type": "blog",
"is_partial": false,
"seo_profile_id": "promocion-computadoras-gamer",
"seo_overrides": null,
"canonical_url": "https://realcity.com.mx/blog/ventajas-del-erp",
"content_blocks": [
{"type": "text", "heading": "Beneficios del ERP", "content": "Centralización de procesos, automatización..."},
{"type": "image", "src": "/images/blog/erp-benefits.jpg", "alt": "ERP y eficiencia empresarial"}
],
"is_draft": false,
"is_sensitive": false
}
]

View File

@ -0,0 +1,92 @@
[
{
"menu_slug": "main-header",
"title": {
"es": "Inicio",
"en": "Home"
},
"type": "cms_page",
"order": 1,
"icon": "ti ti-home"
},
{
"menu_slug": "main-header",
"title": {
"es": "Nuestro corporativo",
"en": "About Us"
},
"type": "cms_page",
"order": 2,
"icon": "ti ti-users"
},
{
"menu_slug": "main-header",
"title": {
"es": "Soluciones y servicios",
"en": "Solutions and services"
},
"type": "cms_page",
"order": 3,
"icon": "ti ti-briefcase"
},
{
"menu_slug": "main-header",
"title": {
"es": "Valor y Beneficios",
"en": "Value and Benefits"
},
"type": "cms_page",
"order": 4,
"icon": "ti ti-briefcase"
},
{
"menu_slug": "main-header",
"title": {
"es": "Experiencia de éxito",
"en": "Success Experience"
},
"type": "cms_page",
"order": 5,
"icon": "ti ti-briefcase"
},
{
"menu_slug": "main-header",
"title": {
"es": "Blog y contenido",
"en": "Blog and content"
},
"type": "blog_article",
"order": 6,
"icon": "ti ti-news"
},
{
"menu_slug": "main-header",
"title": {
"es": "Residentes y usuarios",
"en": "Residents and users"
},
"type": "cms_page",
"order": 7,
"icon": "ti ti-users"
},
{
"menu_slug": "main-header",
"title": {
"es": "Contacto",
"en": "Contact"
},
"type": "action",
"order": 8,
"icon": "ti ti-phone-call"
},
{
"menu_slug": "main-header",
"title": {
"es": "Legales",
"en": "Legal"
},
"type": "cms_page",
"order": 9,
"icon": "ti ti-file"
}
]

View File

@ -0,0 +1,145 @@
[
{
"site_id": 1,
"type": "page",
"title": "AgroForm México | Jardinería Integral con Tecnología y Sostenibilidad",
"slug": "agroform-home",
"description": "AgroForm México transforma espacios verdes desde 2017 con servicios de jardinería, mantenimiento y diseño innovador. Combinamos sostenibilidad, tecnología y excelencia para embellecer y proteger tu inversión.",
"schema_org": {
"@context": "https://schema.org",
"@type": "Organization",
"name": "AgroForm México",
"url": "https://agroform.com.mx",
"logo": "https://agroform.com.mx/assets/logo.png",
"description": "Servicios de jardinería, mantenimiento de áreas verdes y paisajismo sostenible en México.",
"foundingDate": "2017",
"areaServed": "MX",
"sameAs": [
"https://www.facebook.com/agroformmx",
"https://www.instagram.com/agroformmx"
]
},
"noindex": false,
"nofollow": false,
"locale": "es-MX",
"geo_location": {
"geo.region": "MX",
"geo.placename": "México"
},
"og_type": "website",
"og_title": "AgroForm México | Jardinería Integral con Tecnología y Sostenibilidad",
"og_description": "Creamos y cuidamos jardines, parques y espacios verdes sostenibles con tecnología de punta y personal altamente capacitado.",
"og_image": "https://agroform.com.mx/assets/og-image.jpg",
"og_url": "https://agroform.com.mx",
"og_site_name": "AgroForm México",
"twitter_card": "summary_large_image",
"twitter_title": "AgroForm México",
"twitter_description": "Soluciones integrales en jardinería y paisajismo sostenible para parques y espacios verdes.",
"twitter_image": "https://agroform.com.mx/assets/twitter-card.jpg",
"twitter_site": "@agroformmx",
"twitter_creator": "@agroformmx",
"json_ld": {
"@context": "https://schema.org",
"@type": "WebPage",
"name": "AgroForm México",
"url": "https://agroform.com.mx",
"description": "Empresa mexicana líder en jardinería integral, mantenimiento de áreas verdes y paisajismo con enfoque tecnológico y sostenible."
},
"created_by": 1,
"updated_by": 1,
"created_at": "2025-05-24T17:00:00",
"updated_at": "2025-05-24T17:00:00"
},
{
"site_id": 2,
"type": "page",
"title": "CleanFy México | Soluciones Integrales de Limpieza y Sanitización",
"slug": "cleanfy-home",
"description": "CleanFy es tu socio estratégico en limpieza profesional y sanitización en México. Con personal capacitado, tecnología avanzada y enfoque sostenible, garantizamos espacios seguros, limpios y saludables.",
"schema_org": {
"@context": "https://schema.org",
"@type": "Organization",
"name": "CleanFy México",
"url": "https://cleanfy.mx",
"logo": "https://cleanfy.mx/assets/logo.png",
"description": "Empresa líder en soluciones integrales de limpieza, sanitización y mantenimiento para hogares, oficinas, industrias y más.",
"foundingDate": "2017",
"areaServed": "MX",
"sameAs": [
"https://www.facebook.com/cleanfymx",
"https://www.instagram.com/cleanfymx"
]
},
"noindex": false,
"nofollow": false,
"locale": "es-MX",
"geo_location": {
"geo.region": "MX",
"geo.placename": "México"
},
"og_type": "website",
"og_title": "CleanFy México | Soluciones Integrales de Limpieza y Sanitización",
"og_description": "Transformamos espacios en ambientes impecables y seguros. Limpieza profesional, protocolos tecnológicos, y compromiso con la calidad y la salud.",
"og_image": "https://cleanfy.mx/assets/og-image.jpg",
"og_url": "https://cleanfy.mx",
"og_site_name": "CleanFy México",
"twitter_card": "summary_large_image",
"twitter_title": "CleanFy México",
"twitter_description": "Empresa profesional de limpieza y sanitización con tecnología, compromiso y excelencia.",
"twitter_image": "https://cleanfy.mx/assets/twitter-card.jpg",
"twitter_site": "@cleanfymx",
"twitter_creator": "@cleanfymx",
"json_ld": {
"@context": "https://schema.org",
"@type": "WebPage",
"name": "CleanFy México",
"url": "https://cleanfy.mx",
"description": "Empresa mexicana especializada en limpieza y sanitización profesional para empresas, oficinas y hogares. Tecnología, personal capacitado y sostenibilidad al servicio de la salud y productividad."
}
}
,
{
"site_id": 3,
"type": "page",
"title": "RealCity México | Próximamente la Nueva Plataforma Inmobiliaria",
"slug": "realcity-coming-soon",
"description": "Prepárate para una experiencia inmobiliaria moderna y eficiente. RealCity está por llegar para transformar la forma de comprar, vender y rentar propiedades en México.",
"schema_org": {
"@context": "https://schema.org",
"@type": "Organization",
"name": "RealCity México",
"url": "https://realcity.com.mx",
"logo": "https://realcity.com.mx/assets/logo.png",
"description": "Plataforma inmobiliaria innovadora en México, especializada en conectar compradores, vendedores e inversionistas mediante tecnología moderna.",
"foundingDate": "2025",
"areaServed": "MX"
},
"noindex": false,
"nofollow": false,
"locale": "es-MX",
"geo_location": {
"geo.region": "MX",
"geo.placename": "México"
},
"og_type": "website",
"og_title": "RealCity México | Próximamente la Nueva Plataforma Inmobiliaria",
"og_description": "Muy pronto una nueva experiencia digital para el sector inmobiliario. Encuentra la propiedad ideal con RealCity México.",
"og_image": "https://realcity.com.mx/assets/og-image.jpg",
"og_url": "https://realcity.com.mx",
"og_site_name": "RealCity México",
"twitter_card": "summary_large_image",
"twitter_title": "RealCity México",
"twitter_description": "Innovación inmobiliaria en México. RealCity es la nueva forma de buscar, publicar y cerrar negocios en bienes raíces.",
"twitter_image": "https://realcity.com.mx/assets/twitter-card.jpg",
"twitter_site": "@realcitymx",
"twitter_creator": "@realcitymx",
"json_ld": {
"@context": "https://schema.org",
"@type": "WebPage",
"name": "RealCity México",
"url": "https://realcity.com.mx",
"description": "RealCity ofrece una plataforma tecnológica avanzada para transformar la experiencia inmobiliaria en México, con servicios digitales para compra, venta y renta de propiedades."
}
}
]

View File

@ -0,0 +1,220 @@
[
{
"name": "cleanfy.mx",
"slug": "cleanfy-mx",
"domain": "cleanfy.mx",
"template": "cleaning-services",
"status": "active",
"is_active": true,
"is_indexable": true,
"meta_title": "Limpieza Profesional - Cleanfy",
"meta_description": "Servicios de limpieza profesional y desinfección para empresas y hogares en México.",
"canonical_url": "https://cleanfy.mx",
"locale": "es-MX",
"robots_directives": "index,follow",
"config": {
"favicon": "/assets/cleanfy/favicon.ico",
"primary_color": "#27ae60",
"logo": "/assets/cleanfy/logo.svg"
},
"social": {
"og:title": "Cleanfy.mx",
"og:image": "/assets/cleanfy/og-image.jpg",
"twitter:card": "summary_large_image",
"twitter:site": "@cleanfymx"
}
},
{
"name": "agroform.com.mx",
"slug": "agroform-com-mx",
"domain": "agroform.com.mx",
"template": "renewable-energy",
"status": "coming_soon",
"is_active": true,
"is_indexable": false,
"meta_title": "AgroForm | Agricultura Inteligente",
"meta_description": "Soluciones tecnológicas para productores agrícolas: sensores, plataformas y más.",
"canonical_url": "https://agroform.com.mx",
"locale": "es-MX",
"robots_directives": "noindex,nofollow",
"config": {
"maintenance_page": "coming-soon",
"primary_color": "#388e3c",
"logo": "/assets/agroform/logo.svg"
},
"social": {
"og:title": "AgroForm",
"og:description": "Innovación para el campo mexicano.",
"twitter:site": "@agroformmx"
}
},
{
"name": "realcity.com.mx",
"slug": "realcity-com-mx",
"domain": "realcity.com.mx",
"template": "business-consulting-4",
"status": "active",
"is_active": true,
"is_indexable": true,
"meta_title": "RealCity | Bienes Raíces Premium",
"meta_description": "Compra y renta de propiedades en zonas exclusivas. Encuentra tu próximo hogar con RealCity.",
"canonical_url": "https://realcity.com.mx",
"locale": "es-MX",
"robots_directives": "index,follow",
"config": {
"template_variant": "real-estate",
"primary_color": "#34495e",
"logo": "/assets/realcity/logo.svg"
},
"social": {
"og:title": "RealCity",
"og:image": "/assets/realcity/og-image.jpg",
"og:type": "website",
"twitter:site": "@realcitymx"
}
},
{
"name": "anonymous.test",
"slug": "anonymous-test",
"domain": "anonymous.test",
"template": "anonymous",
"status": "active",
"is_active": true,
"is_indexable": true,
"meta_title": "Anonymous",
"meta_description": "Anonymous",
"canonical_url": "https://anonymous.test",
"locale": "es-MX",
"robots_directives": "index,follow",
"config": {
"primary_color": "#34495e",
"logo": "/assets/anonymous/logo.svg"
},
"social": {
"og:title": "Anonymous",
"og:image": "/assets/anonymous/og-image.jpg",
"og:type": "website",
"twitter:site": "@anonymousmx"
}
},
{
"name": "landwind.test",
"slug": "landwind-test",
"domain": "landwind.test",
"template": "landwind",
"status": "active",
"is_active": true,
"is_indexable": true,
"meta_title": "Landwind",
"meta_description": "Landwind",
"canonical_url": "https://landwind.test",
"locale": "es-MX",
"robots_directives": "index,follow",
"config": {
"primary_color": "#34495e",
"logo": "/assets/landwind/logo.svg"
},
"social": {
"og:title": "Landwind",
"og:image": "/assets/landwind/og-image.jpg",
"og:type": "website",
"twitter:site": "@landwindmx"
}
},
{
"name": "limaa-m.test",
"slug": "limaa-m-test",
"domain": "limaa-m.test",
"template": "limaa-m",
"status": "active",
"is_active": true,
"is_indexable": true,
"meta_title": "Limaa M",
"meta_description": "Limaa M",
"canonical_url": "https://limaa-m.test",
"locale": "es-MX",
"robots_directives": "index,follow",
"config": {
"primary_color": "#34495e",
"logo": "/assets/limaa-m/logo.svg"
},
"social": {
"og:title": "Limaa M",
"og:image": "/assets/limaa-m/og-image.jpg",
"og:type": "website",
"twitter:site": "@limaa-mmx"
}
},
{
"name": "maximus.test",
"slug": "maximus-test",
"domain": "maximus.test",
"template": "maximus",
"status": "active",
"is_active": true,
"is_indexable": true,
"meta_title": "Maximus",
"meta_description": "Maximus",
"canonical_url": "https://maximus.test",
"locale": "es-MX",
"robots_directives": "index,follow",
"config": {
"primary_color": "#34495e",
"logo": "/assets/maximus/logo.svg"
},
"social": {
"og:title": "Maximus",
"og:image": "/assets/maximus/og-image.jpg",
"og:type": "website",
"twitter:site": "@maximusmx"
}
},
{
"name": "notus.test",
"slug": "notus-test",
"domain": "notus.test",
"template": "notus",
"status": "active",
"is_active": true,
"is_indexable": true,
"meta_title": "Notus",
"meta_description": "Notus",
"canonical_url": "https://notus.test",
"locale": "es-MX",
"robots_directives": "index,follow",
"config": {
"primary_color": "#34495e",
"logo": "/assets/notus/logo.svg"
},
"social": {
"og:title": "Notus",
"og:image": "/assets/notus/og-image.jpg",
"og:type": "website",
"twitter:site": "@notusmx"
}
},
{
"name": "samuel-coming-soon.test",
"slug": "samuel-coming-soon-test",
"domain": "samuel-coming-soon.test",
"template": "samuel-coming-soon",
"status": "active",
"is_active": true,
"is_indexable": true,
"meta_title": "Samuel Coming Soon",
"meta_description": "Samuel Coming Soon",
"canonical_url": "https://samuel-coming-soon.test",
"locale": "es-MX",
"robots_directives": "index,follow",
"config": {
"primary_color": "#34495e",
"logo": "/assets/samuel-coming-soon/logo.svg"
},
"social": {
"og:title": "Samuel Coming Soon",
"og:image": "/assets/samuel-coming-soon/og-image.jpg",
"og:type": "website",
"twitter:site": "@samuelcomingsoonmx"
}
}
]

View File

@ -0,0 +1,77 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('website_seo_profiles', function (Blueprint $table) {
$table->smallIncrements('id');
$table->unsignedSmallInteger('site_id')->nullable()->index();
// Metadata
$table->string('type', 16)->default('page')->index(); // Enum: Content, Landing, Product, Category Blog
$table->string('title')->nullable()->index(); // Título del perfil
$table->string('slug')->unique();
$table->mediumText('description')->nullable(); // Descripción del perfil
// Tipos de schema adicionales
$table->json('schema_org')->nullable();
// Robots Directives
$table->boolean('noindex')->default(false);
$table->boolean('nofollow')->default(false);
// Idioma y Geolocalización
$table->string('locale', 8)->default('es-MX')->index(); // Para SEO internacional
$table->json('geo_location')->nullable(); // meta geo.region y geo.placename
// Open Graph
$table->string('og_type')->nullable();
$table->string('og_title')->nullable();
$table->text('og_description')->nullable();
$table->string('og_image')->nullable();
$table->string('og_url')->nullable();
$table->string('og_site_name')->nullable();
// Twitter Card
$table->string('twitter_card')->default('summary_large_image');
$table->string('twitter_title')->nullable();
$table->text('twitter_description')->nullable();
$table->string('twitter_image')->nullable();
$table->string('twitter_site')->nullable();
$table->string('twitter_creator')->nullable();
// JSON-LD opcional (almacenado como bloque JSON)
$table->json('json_ld')->nullable();
// Auditoria
$table->unsignedMediumInteger('created_by')->nullable();
$table->unsignedMediumInteger('updated_by')->nullable();
$table->timestamps();
// Indices
$table->index(['site_id', 'type']);
$table->index(['site_id', 'type', 'slug']);
// Relaciones
$table->foreign('created_by')->references('id')->on('users')->restrictOnDelete();
$table->foreign('updated_by')->references('id')->on('users')->restrictOnDelete();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('website_seo_profiles');
}
};

View File

@ -0,0 +1,64 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('website_sites', function (Blueprint $table) {
$table->smallIncrements('id');
// Identidad
$table->string('name')->index(); // Nombre visible en admin
$table->string('slug')->unique(); // Clave técnica
$table->string('domain')->unique(); // Dominio principal (sin protocolo)
$table->string('template')->nullable(); // Componente layout activo
// Estado
$table->string('status', 16)->default('active')->index(); // Estados especiales del sitio
$table->boolean('is_indexable')->default(true)->index(); // SEO: permitir indexado o no
// SEO
$table->unsignedSmallInteger('seo_profile_id')->nullable()->index();
$table->string('canonical_url')->nullable(); // Canonical para root
// Configuración
$table->json('config')->nullable(); // favicon, theme, brand, CDN, etc.
// Auditoría
$table->unsignedMediumInteger('created_by')->nullable()->index();
$table->unsignedMediumInteger('updated_by')->nullable()->index();
$table->timestamps();
// Indices
$table->index(['slug', 'status', 'is_indexable']);
// Relaciones
$table->foreign('seo_profile_id')->references('id')->on('website_seo_profiles')->nullOnDelete();
$table->foreign('created_by')->references('id')->on('users')->restrictOnDelete();
$table->foreign('updated_by')->references('id')->on('users')->restrictOnDelete();
});
Schema::table('website_seo_profiles', function (Blueprint $table) {
$table->foreign('site_id')->references('id')->on('website_sites')->cascadeOnDelete();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('website_sites');
Schema::table('website_seo_profiles', function (Blueprint $table) {
$table->dropForeign(['site_id']);
});
}
};

View File

@ -0,0 +1,48 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('website_menus', function (Blueprint $table) {
$table->smallIncrements('id');
$table->unsignedSmallInteger('site_id')->index();
$table->string('title')->index();
$table->string('slug')->unique();
$table->string('description')->nullable();
$table->boolean('is_active')->default(true)->index();
// Auditoría
$table->unsignedMediumInteger('created_by')->nullable()->index();
$table->unsignedMediumInteger('updated_by')->nullable()->index();
$table->timestamps();
// Indices
$table->index(['site_id', 'slug', 'is_active']);
// Relaciones
$table->foreign('site_id')->references('id')->on('website_sites')->cascadeOnDelete();
$table->foreign('created_by')->references('id')->on('users')->restrictOnDelete();
$table->foreign('updated_by')->references('id')->on('users')->restrictOnDelete();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('website_menus');
}
};

View File

@ -0,0 +1,75 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('website_menu_items', function (Blueprint $table) {
$table->smallIncrements('id');
$table->unsignedSmallInteger('menu_id')->index();
$table->unsignedSmallInteger('parent_id')->nullable()->index();
$table->json('title'); // i18n multilanguage
$table->string('type', 16)->default('cms_page')->index(); // Enum; cms_page | url | laravel_route | blog_article | Evento Json
// Construcción de enlace
$table->unsignedMediumInteger('linkable_id')->nullable()->index(); // Relación polimórfica con:
$table->string('linkable_type')->nullable()->index(); // páginas, entradas, productos, etc.
$table->string('laravel_route')->nullable()->index();
$table->string('url')->nullable()->index();
$table->string('method')->nullable();
$table->string('target', 16)->nullable(); // Enum _self, _blank, etc.
$table->string('js_event')->nullable();
// UI
$table->string('icon')->nullable();
$table->string('badge')->nullable();
$table->string('badge_color')->nullable();
// Visibilidad
$table->json('roles')->nullable();
$table->json('permissions')->nullable();
$table->boolean('hide_if_authenticated')->default(false)->index();
$table->boolean('hide_if_guest')->default(false)->index();
$table->timestamp('visible_from')->nullable();
$table->timestamp('visible_until')->nullable();
$table->unsignedSmallInteger('order')->default(0); // Para ordenar en el menú
$table->boolean('is_active')->default(true)->index();
// Auditoría
$table->unsignedMediumInteger('created_by')->nullable()->index();
$table->unsignedMediumInteger('updated_by')->nullable()->index();
$table->timestamps();
// Indices
$table->index(['menu_id', 'is_active']);
$table->index(['menu_id', 'parent_id', 'is_active']);
$table->index(['linkable_id', 'linkable_type']);
// Relaciones
$table->foreign('menu_id')->references('id')->on('website_menus')->cascadeOnDelete();
$table->foreign('parent_id')->references('id')->on('website_menu_items')->nullOnDelete();
$table->foreign('created_by')->references('id')->on('users')->restrictOnDelete();
$table->foreign('updated_by')->references('id')->on('users')->restrictOnDelete();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('website_menu_items');
}
};

View File

@ -0,0 +1,84 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('website_contents', function (Blueprint $table) {
$table->smallIncrements('id');
$table->unsignedSmallInteger('site_id')->index();
$table->unsignedSmallInteger('seo_profile_id')->nullable()->index();
// Metadata
$table->string('title')->index();
$table->string('slug')->unique();
$table->string('description');
$table->json('keywords')->nullable();
// Template & Type content
$table->string('template')->nullable();
$table->string('template_variant')->nullable();
$table->string('type', 16)->default('page')->index(); // Enum: Content, Landing, Product, Category Blog, Partial
$table->string('render_mode', 16)->default('static');
$table->string('block_mode', 16)->default('db');
$table->string('source', 16)->default('db');
$table->string('render_as')->nullable();
//canonical url
$table->string('canonical_url')->nullable();
// Content
$table->json('content_blocks')->nullable(); // Bloques estructurados
$table->json('seo_overrides')->nullable();
// Control
$table->boolean('is_draft')->default(true)->index();
$table->boolean('is_sensitive')->default(false)->index(); // Allow dangerous Blade content
$table->boolean('is_partial')->default(false)->index();
// Visibilidad
$table->json('roles')->nullable();
$table->json('permissions')->nullable();
$table->boolean('hide_if_authenticated')->default(false)->index();
$table->boolean('hide_if_guest')->default(false)->index();
$table->timestamp('visible_from')->nullable();
$table->timestamp('visible_until')->nullable();
// Cache
$table->boolean('enable_cache')->default(true)->index();
$table->unsignedSmallInteger('cache_ttl')->default(60); // minutos
// Auditoria
$table->unsignedMediumInteger('created_by')->nullable()->index();
$table->unsignedMediumInteger('updated_by')->nullable()->index();
$table->timestamps();
// Indices
$table->index(['site_id', 'type']);
$table->index(['site_id', 'type', 'slug']);
// Relaciones
$table->foreign('site_id')->references('id')->on('website_sites')->cascadeOnDelete();
$table->foreign('seo_profile_id')->references('id')->on('website_seo_profiles')->nullOnDelete();
$table->foreign('created_by')->references('id')->on('users')->restrictOnDelete();
$table->foreign('updated_by')->references('id')->on('users')->restrictOnDelete();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('website_contents');
}
};

View File

@ -0,0 +1,48 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('website_content_blocks', function (Blueprint $table) {
$table->smallIncrements('id');
$table->unsignedSmallInteger('content_id')->index();
$table->unsignedSmallInteger('parent_id')->nullable()->index();
$table->string('slug')->nullable();
$table->string('type', 32);
$table->string('mode', 16)->default('view');
$table->string('view_path')->nullable();
$table->string('component_class')->nullable();
$table->boolean('is_enabled')->default(true);
$table->boolean('enable_cache')->default(true);
$table->unsignedSmallInteger('cache_ttl')->default(60);
$table->json('settings')->nullable();
$table->json('data')->nullable();
$table->unsignedSmallInteger('order')->default(0);
$table->timestamps();
$table->foreign('content_id')->references('id')->on('website_contents')->cascadeOnDelete();
$table->foreign('parent_id')->references('id')->on('website_content_blocks')->nullOnDelete();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('website_content_blocks');
}
};

View File

@ -0,0 +1,42 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('website_content_versions', function (Blueprint $table) {
$table->smallIncrements('id');
$table->unsignedSmallInteger('website_content_id')->index();
$table->string('version_label')->nullable();
$table->longText('content');
$table->json('metadata')->nullable();
// Auditoria
$table->unsignedMediumInteger('created_by')->nullable();
$table->unsignedMediumInteger('updated_by')->nullable();
$table->timestamps();
// Relaciones
$table->foreign('website_content_id')->references('id')->on('website_contents')->cascadeOnDelete();
$table->foreign('created_by')->references('id')->on('users')->restrictOnDelete();
$table->foreign('updated_by')->references('id')->on('users')->restrictOnDelete();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('website_content_versions');
}
};

View File

@ -0,0 +1,44 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('sitemap_profiles', function (Blueprint $table) {
$table->smallIncrements('id');
$table->unsignedSmallInteger('site_id')->index(); // Soporte multisite
$table->string('name'); // Nombre del perfil: 'Productos', 'Páginas CMS'
$table->string('slug')->unique(); // Clave técnica
$table->string('entity_type')->nullable(); // Ej: App\Models\Product
$table->string('generator_class')->nullable(); // Clase que implementa SitemapUrlGeneratorInterface
$table->boolean('is_active')->default(true)->index();
// Auditoría
$table->unsignedMediumInteger('created_by')->nullable()->index();
$table->unsignedMediumInteger('updated_by')->nullable()->index();
$table->timestamps();
// Indices
$table->index(['site_id', 'slug']);
$table->index(['site_id', 'slug', 'is_active']);
// Relaciones
$table->foreign('site_id')->references('id')->on('website_sites')->cascadeOnDelete();
$table->foreign('created_by')->references('id')->on('users')->restrictOnDelete();
$table->foreign('updated_by')->references('id')->on('users')->restrictOnDelete();
});
}
public function down(): void
{
Schema::dropIfExists('sitemap_profiles');
}
};

View File

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('sitemap_rules', function (Blueprint $table) {
$table->mediumIncrements('id');
$table->unsignedSmallInteger('sitemap_profile_id')->index();
$table->string('rule_type'); // Ej: 'priority_override', 'exclude_flag', etc.
$table->json('rule_data'); // JSON con parámetros
$table->timestamps();
// Indices
$table->index(['sitemap_profile_id', 'rule_type']);
// Relaciones
$table->foreign('sitemap_profile_id')->references('id')->on('sitemap_profiles')->cascadeOnDelete();
});
}
public function down(): void
{
Schema::dropIfExists('sitemap_rules');
}
};

View File

@ -12,13 +12,26 @@ return new class extends Migration
public function up(): void
{
Schema::create('sitemap_urls', function (Blueprint $table) {
$table->id();
$table->mediumIncrements('id');
$table->unsignedSmallInteger('sitemap_profile_id')->index();
$table->string('url')->unique();
$table->enum('changefreq', ['always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly'])->default('weekly');
$table->string('changefreq', 16)->default('weekly'); // Enum
$table->decimal('priority', 2, 1)->default(0.5);
$table->timestamp('lastmod')->nullable();
$table->boolean('is_active')->default(true);
$table->boolean('is_active')->default(true)->index();
$table->json('alternate_locales')->nullable(); // SEO internacional
// Auditoría
$table->timestamps();
// Indices
$table->index(['sitemap_profile_id', 'is_active']);
// Relaciones
$table->foreign('sitemap_profile_id')->references('id')->on('sitemap_profiles')->cascadeOnDelete();
});
}

View File

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('sitemap_index_files', function (Blueprint $table) {
$table->mediumIncrements('id');
$table->unsignedSmallInteger('sitemap_profile_id')->index();
$table->string('file_name')->unique();
$table->string('url');
$table->timestamp('generated_at');
$table->integer('url_count')->default(0);
$table->boolean('is_current')->default(true);
$table->timestamps();
$table->foreign('sitemap_profile_id')->references('id')->on('sitemap_profiles')->cascadeOnDelete();
});
}
public function down(): void
{
Schema::dropIfExists('sitemap_index_files');
}
};

View File

@ -14,13 +14,27 @@ return new class extends Migration
Schema::create('faq_categories', function (Blueprint $table) {
$table->smallIncrements('id');
$table->string('name')->unique();
$table->unsignedSmallInteger('site_id')->index(); // Soporte multisite
$table->string('name')->index();
$table->string('icon')->nullable();
$table->unsignedInteger('order')->default(0)->index();
$table->boolean('is_active')->default(true)->index();
// Auditoria
$table->unsignedMediumInteger('created_by')->nullable()->index();
$table->unsignedMediumInteger('updated_by')->nullable()->index();
$table->timestamps();
// Indices
$table->unique(['name', 'site_id']);
$table->index(['name', 'is_active', 'site_id']);
// Relaciones
$table->foreign('site_id')->references('id')->on('website_sites')->cascadeOnDelete();
$table->foreign('created_by')->references('id')->on('users')->restrictOnDelete();
$table->foreign('updated_by')->references('id')->on('users')->restrictOnDelete();
});
}

View File

@ -12,7 +12,7 @@ return new class extends Migration
public function up(): void
{
Schema::create('faqs', function (Blueprint $table) {
$table->id();
$table->smallIncrements('id');
$table->unsignedSmallInteger('category_id')->nullable()->index();
$table->string('question');
@ -21,10 +21,18 @@ return new class extends Migration
$table->boolean('is_active')->default(true)->index();
// Auditoria
$table->unsignedMediumInteger('created_by')->nullable()->index();
$table->unsignedMediumInteger('updated_by')->nullable()->index();
$table->timestamps();
// Indices
$table->index(['category_id', 'is_active']);
// Relaciones
$table->foreign('category_id')->references('id')->on('faq_categories')->nullOnDelete();
$table->foreign('category_id')->references('id')->on('faq_categories')->restrictOnDelete();
$table->foreign('created_by')->references('id')->on('users')->restrictOnDelete();
$table->foreign('updated_by')->references('id')->on('users')->restrictOnDelete();
});
}

View File

@ -0,0 +1,60 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('blog_categories', function (Blueprint $table) {
$table->smallIncrements('id');
$table->unsignedSmallInteger('site_id')->index(); // Soporte multisite
$table->string('name')->index();
$table->string('slug')->index();
$table->string('full_slug')->nullable()->index(); // NUEVO: Ruta cacheada
$table->unsignedSmallInteger('parent_id')->nullable()->index();
$table->string('icon')->nullable(); // NUEVO: Soporte para icono
$table->string('group')->nullable()->index(); // NUEVO: Soporte para agrupación (ej: blog, noticias, promociones)
$table->text('description')->nullable();
$table->boolean('is_active')->default(true)->index();
// Auditoría
$table->unsignedMediumInteger('created_by')->nullable()->index();
$table->unsignedMediumInteger('updated_by')->nullable()->index();
$table->timestamps();
// Relaciones
$table->foreign('parent_id')->references('id')->on('blog_categories')->nullOnDelete();
// Indices
$table->index(['name', 'is_active', 'site_id']);
$table->unique(['slug', 'site_id']);
// Relaciones
$table->foreign('site_id')->references('id')->on('website_sites')->cascadeOnDelete();
$table->foreign('created_by')->references('id')->on('users')->restrictOnDelete();
$table->foreign('updated_by')->references('id')->on('users')->restrictOnDelete();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('blog_categories');
}
};

View File

@ -0,0 +1,48 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('blog_tags', function (Blueprint $table) {
$table->smallIncrements('id');
$table->unsignedSmallInteger('site_id')->index(); // Soporte multisite
$table->string('name')->index();
$table->string('slug')->index();
$table->boolean('is_active')->default(true)->index();
// Auditoria
$table->unsignedMediumInteger('created_by')->nullable()->index();
$table->unsignedMediumInteger('updated_by')->nullable()->index();
$table->timestamps();
// Indices
$table->unique(['slug', 'site_id']);
$table->index(['name', 'is_active']);
// Relaciones
$table->foreign('site_id')->references('id')->on('website_sites')->cascadeOnDelete();
$table->foreign('created_by')->references('id')->on('users')->restrictOnDelete();
$table->foreign('updated_by')->references('id')->on('users')->restrictOnDelete();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('blog_tags');
}
};

View File

@ -0,0 +1,53 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('blog_articles', function (Blueprint $table) {
$table->smallIncrements('id');
$table->unsignedSmallInteger('category_id')->index();
$table->string('title')->index();
$table->string('slug')->index();
$table->text('excerpt')->nullable();
$table->longText('content');
$table->json('metadata')->nullable();
$table->boolean('is_published')->default(false)->index();
$table->timestamp('published_at')->nullable()->index();
$table->unsignedMediumInteger('created_by')->index();
$table->unsignedMediumInteger('updated_by')->index();
// Auditoria
$table->timestamps();
// Indices
$table->unique(['slug', 'category_id']);
$table->index(['title', 'is_published']);
// Relaciones
$table->foreign('category_id')->references('id')->on('blog_categories')->restrictOnDelete();
$table->foreign('created_by')->references('id')->on('users')->restrictOnDelete();
$table->foreign('updated_by')->references('id')->on('users')->restrictOnDelete();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('blog_articles');
}
};

View File

@ -0,0 +1,39 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('blog_article_tag', function (Blueprint $table) {
$table->smallIncrements('id');
$table->unsignedSmallInteger('blog_article_id')->index();
$table->unsignedSmallInteger('blog_tag_id')->index();
// Auditoria
$table->timestamps();
// Indices
$table->index(['blog_article_id', 'blog_tag_id']);
// Relaciones
$table->foreign('blog_article_id')->references('id')->on('blog_articles')->cascadeOnDelete();
$table->foreign('blog_tag_id')->references('id')->on('blog_tags')->cascadeOnDelete();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('blog_article_tag');
}
};

View File

@ -0,0 +1,47 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('blog_comments', function (Blueprint $table) {
$table->mediumIncrements('id');
$table->unsignedSmallInteger('blog_article_id')->index();
$table->unsignedMediumInteger('author_id')->nullable()->index();
$table->string('author_name')->index();
$table->string('author_email')->index();
$table->text('comment');
$table->boolean('is_approved')->default(false)->index();
// Auditoria
$table->unsignedMediumInteger('updated_by')->index();
$table->timestamps();
// Indices
$table->index(['blog_article_id', 'is_approved']);
// Relaciones
$table->foreign('blog_article_id')->references('id')->on('blog_articles')->restrictOnDelete();
$table->foreign('author_id')->references('id')->on('users')->restrictOnDelete();
$table->foreign('updated_by')->references('id')->on('users')->restrictOnDelete();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('blog_comments');
}
};

View File

@ -1,23 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration{
public function up(): void
{
Schema::create('sitemap_configurations', function (Blueprint $table) {
$table->id();
$table->string('route');
$table->boolean('include')->default(true);
$table->decimal('priority', 2, 1)->default(0.5);
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('sitemap_configurations');
}
};

View File

@ -0,0 +1,70 @@
[
"admin.website-admin.settings.general.view",
"admin.website-admin.settings.general.update",
"admin.website-admin.settings.social.view",
"admin.website-admin.settings.social.update",
"admin.website-admin.settings.indexing.view",
"admin.website-admin.settings.indexing.update",
"admin.website-admin.contact.info.view",
"admin.website-admin.contact.info.update",
"admin.website-admin.contact.form.view",
"admin.website-admin.contact.form.update",
"admin.website-admin.analytics.google-analytics.view",
"admin.website-admin.analytics.google-analytics.update",
"admin.website-admin.analytics.google-tags.view",
"admin.website-admin.analytics.google-tags.update",
"admin.website-admin.analytics.google-search-console.view",
"admin.website-admin.analytics.google-search-console.update",
"admin.website-admin.analytics.pixel-meta.view",
"admin.website-admin.analytics.pixel-meta.update",
"admin.website-admin.comunication.messenger.view",
"admin.website-admin.comunication.messenger.update",
"admin.website-admin.comunication.whatsapp.view",
"admin.website-admin.comunication.whatsapp.update",
"admin.website-admin.comunication.tawk-to.view",
"admin.website-admin.comunication.tawk-to.update",
"admin.website-admin.comunication.twitter.view",
"admin.website-admin.comunication.twitter.update",
"admin.website-admin.translate.google.view",
"admin.website-admin.translate.google.update",
"admin.website-admin.content.faq.view",
"admin.website-admin.content.faq.update",
"admin.website-admin.content.faq.create",
"admin.website-admin.content.faq.delete",
"admin.website-admin.content.gallery.view",
"admin.website-admin.content.gallery.update",
"admin.website-admin.content.gallery.create",
"admin.website-admin.content.gallery.delete",
"admin.website-admin.content.legal.view",
"admin.website-admin.content.legal.update",
"admin.website-admin.content.legal.create",
"admin.website-admin.content.legal.delete",
"admin.website-admin.seo.sitemap.view",
"admin.website-admin.seo.sitemap.update",
"admin.website-admin.seo.jsonld.view",
"admin.website-admin.seo.jsonld.update",
"admin.website-admin.seo.robots.view",
"admin.website-admin.seo.robots.update",
"admin.website-admin.seo.manifest.view",
"admin.website-admin.seo.manifest.update",
"admin.website-admin.seo.canonical.view",
"admin.website-admin.seo.canonical.update",
"admin.website-admin.seo.social-cards.view",
"admin.website-admin.seo.social-cards.update",
"admin.website-admin.blog.categories.view",
"admin.website-admin.blog.categories.update",
"admin.website-admin.blog.categories.create",
"admin.website-admin.blog.categories.delete",
"admin.website-admin.blog.tags.view",
"admin.website-admin.blog.tags.update",
"admin.website-admin.blog.tags.create",
"admin.website-admin.blog.tags.delete",
"admin.website-admin.blog.articles.view",
"admin.website-admin.blog.articles.update",
"admin.website-admin.blog.articles.create",
"admin.website-admin.blog.articles.delete",
"admin.website-admin.blog.comments.view",
"admin.website-admin.blog.comments.update",
"admin.website-admin.blog.comments.create",
"admin.website-admin.blog.comments.delete"
]

View File

@ -0,0 +1,177 @@
{
"SuperAdmin" : {
"permissions" : [
"admin.website-admin.settings.general.view",
"admin.website-admin.settings.general.update",
"admin.website-admin.settings.social.view",
"admin.website-admin.settings.social.update",
"admin.website-admin.settings.indexing.view",
"admin.website-admin.settings.indexing.update",
"admin.website-admin.contact.info.view",
"admin.website-admin.contact.info.update",
"admin.website-admin.contact.form.view",
"admin.website-admin.contact.form.update",
"admin.website-admin.analytics.google-analytics.view",
"admin.website-admin.analytics.google-analytics.update",
"admin.website-admin.analytics.google-tags.view",
"admin.website-admin.analytics.google-tags.update",
"admin.website-admin.analytics.google-search-console.view",
"admin.website-admin.analytics.google-search-console.update",
"admin.website-admin.analytics.pixel-meta.view",
"admin.website-admin.analytics.pixel-meta.update",
"admin.website-admin.comunication.messenger.view",
"admin.website-admin.comunication.messenger.update",
"admin.website-admin.comunication.whatsapp.view",
"admin.website-admin.comunication.whatsapp.update",
"admin.website-admin.comunication.tawk-to.view",
"admin.website-admin.comunication.tawk-to.update",
"admin.website-admin.comunication.twitter.view",
"admin.website-admin.comunication.twitter.update",
"admin.website-admin.translate.google.view",
"admin.website-admin.translate.google.update",
"admin.website-admin.content.faq.view",
"admin.website-admin.content.faq.update",
"admin.website-admin.content.faq.create",
"admin.website-admin.content.faq.delete",
"admin.website-admin.content.gallery.view",
"admin.website-admin.content.gallery.update",
"admin.website-admin.content.gallery.create",
"admin.website-admin.content.gallery.delete",
"admin.website-admin.content.legal.view",
"admin.website-admin.content.legal.update",
"admin.website-admin.content.legal.create",
"admin.website-admin.content.legal.delete",
"admin.website-admin.seo.sitemap.view",
"admin.website-admin.seo.sitemap.update",
"admin.website-admin.seo.jsonld.view",
"admin.website-admin.seo.jsonld.update",
"admin.website-admin.seo.robots.view",
"admin.website-admin.seo.robots.update",
"admin.website-admin.seo.manifest.view",
"admin.website-admin.seo.manifest.update",
"admin.website-admin.seo.canonical.view",
"admin.website-admin.seo.canonical.update",
"admin.website-admin.seo.social-cards.view",
"admin.website-admin.seo.social-cards.update",
"admin.website-admin.blog.categories.view",
"admin.website-admin.blog.categories.update",
"admin.website-admin.blog.categories.create",
"admin.website-admin.blog.categories.delete",
"admin.website-admin.blog.tags.view",
"admin.website-admin.blog.tags.update",
"admin.website-admin.blog.tags.create",
"admin.website-admin.blog.tags.delete",
"admin.website-admin.blog.articles.view",
"admin.website-admin.blog.articles.update",
"admin.website-admin.blog.articles.create",
"admin.website-admin.blog.articles.delete",
"admin.website-admin.blog.comments.view",
"admin.website-admin.blog.comments.update",
"admin.website-admin.blog.comments.create",
"admin.website-admin.blog.comments.delete"
]
},
"Admin" : {
"permissions" : [
"admin.website-admin.settings.general.view",
"admin.website-admin.settings.general.update",
"admin.website-admin.settings.social.view",
"admin.website-admin.settings.social.update",
"admin.website-admin.settings.indexing.view",
"admin.website-admin.settings.indexing.update",
"admin.website-admin.contact.info.view",
"admin.website-admin.contact.info.update",
"admin.website-admin.contact.form.view",
"admin.website-admin.contact.form.update",
"admin.website-admin.analytics.google-analytics.view",
"admin.website-admin.analytics.google-analytics.update",
"admin.website-admin.analytics.google-tags.view",
"admin.website-admin.analytics.google-tags.update",
"admin.website-admin.analytics.google-search-console.view",
"admin.website-admin.analytics.google-search-console.update",
"admin.website-admin.analytics.pixel-meta.view",
"admin.website-admin.analytics.pixel-meta.update",
"admin.website-admin.comunication.messenger.view",
"admin.website-admin.comunication.messenger.update",
"admin.website-admin.comunication.whatsapp.view",
"admin.website-admin.comunication.whatsapp.update",
"admin.website-admin.comunication.tawk-to.view",
"admin.website-admin.comunication.tawk-to.update",
"admin.website-admin.comunication.twitter.view",
"admin.website-admin.comunication.twitter.update",
"admin.website-admin.translate.google.view",
"admin.website-admin.translate.google.update",
"admin.website-admin.content.faq.view",
"admin.website-admin.content.faq.update",
"admin.website-admin.content.faq.create",
"admin.website-admin.content.faq.delete",
"admin.website-admin.content.gallery.view",
"admin.website-admin.content.gallery.update",
"admin.website-admin.content.gallery.create",
"admin.website-admin.content.gallery.delete",
"admin.website-admin.content.legal.view",
"admin.website-admin.content.legal.update",
"admin.website-admin.content.legal.create",
"admin.website-admin.content.legal.delete",
"admin.website-admin.seo.sitemap.view",
"admin.website-admin.seo.sitemap.update",
"admin.website-admin.seo.jsonld.view",
"admin.website-admin.seo.jsonld.update",
"admin.website-admin.seo.robots.view",
"admin.website-admin.seo.robots.update",
"admin.website-admin.seo.manifest.view",
"admin.website-admin.seo.manifest.update",
"admin.website-admin.seo.canonical.view",
"admin.website-admin.seo.canonical.update",
"admin.website-admin.seo.social-cards.view",
"admin.website-admin.seo.social-cards.update",
"admin.website-admin.blog.categories.view",
"admin.website-admin.blog.categories.update",
"admin.website-admin.blog.categories.create",
"admin.website-admin.blog.categories.delete",
"admin.website-admin.blog.tags.view",
"admin.website-admin.blog.tags.update",
"admin.website-admin.blog.tags.create",
"admin.website-admin.blog.tags.delete",
"admin.website-admin.blog.articles.view",
"admin.website-admin.blog.articles.update",
"admin.website-admin.blog.articles.create",
"admin.website-admin.blog.articles.delete",
"admin.website-admin.blog.comments.view",
"admin.website-admin.blog.comments.update",
"admin.website-admin.blog.comments.create",
"admin.website-admin.blog.comments.delete"
]
},
"Auditor" : {
"permissions" : [
"admin.website-admin.settings.general.view",
"admin.website-admin.settings.social.view",
"admin.website-admin.settings.indexing.view",
"admin.website-admin.contact.info.view",
"admin.website-admin.contact.form.view",
"admin.website-admin.analytics.google-analytics.view",
"admin.website-admin.analytics.google-tags.view",
"admin.website-admin.analytics.google-search-console.view",
"admin.website-admin.analytics.pixel-meta.view",
"admin.website-admin.comunication.messenger.view",
"admin.website-admin.comunication.whatsapp.view",
"admin.website-admin.comunication.tawk-to.view",
"admin.website-admin.comunication.twitter.view",
"admin.website-admin.translate.google.view",
"admin.website-admin.content.faq.view",
"admin.website-admin.content.gallery.view",
"admin.website-admin.content.legal.view",
"admin.website-admin.seo.sitemap.view",
"admin.website-admin.seo.jsonld.view",
"admin.website-admin.seo.robots.view",
"admin.website-admin.seo.manifest.view",
"admin.website-admin.seo.canonical.view",
"admin.website-admin.seo.social-cards.view",
"admin.website-admin.blog.categories.view",
"admin.website-admin.blog.tags.view",
"admin.website-admin.blog.articles.view",
"admin.website-admin.blog.comments.view"
]
}
}

View File

@ -1,6 +1,6 @@
import '@vuexy-admin/notifications/LivewireNotification.js';
import FormCustomListener from '@vuexy-admin/forms/formCustomListener';
import registerLivewireHookOnce from '@vuexy-admin/livewire/registerLivewireHookOnce';
//import '@vuexy-admin/assets/js/notifications/LivewireNotification.js';
import FormCustomListener from '@vuexy-admin/assets/js/forms/formCustomListener';
//import registerLivewireHookOnce from '@vuexy-admin/assets/js/livewire/registerLivewireHookOnce';
// Inicializar formularios de ajustes de chat
window.ChatSettingsForm = new FormCustomListener({

View File

@ -1,10 +1,10 @@
import '@vuexy-admin/notifications/LivewireNotification.js';
import FormCustomListener from '@vuexy-admin/forms/formCustomListener';
import registerLivewireHookOnce from '@vuexy-admin/livewire/registerLivewireHookOnce';
//import '@vuexy-admin/assets/js/notifications/LivewireNotification.js';
import FormCustomListener from '@vuexy-admin/assets/js/forms/formCustomListener';
//import registerLivewireHookOnce from '@vuexy-admin/assets/js/livewire/registerLivewireHookOnce';
// Inicializar formularios de ajustes de Formularios de contacto
window.ContactFormSettingsForm = new FormCustomListener({
formSelector: '#website-contact-form-settings-card',
formSelector: '#website-contact-form-card-card',
buttonSelectors: ['.btn-save', '.btn-cancel'],
callbacks: [() => {}],
dispatchOnSubmit: 'save',
@ -81,6 +81,6 @@ window.ContactFormSettingsForm = new FormCustomListener({
}
});
registerLivewireHookOnce('morphed', 'vuexy-website-admin::contact-form-settings', (component) => {
registerLivewireHookOnce('morphed', 'vuexy-website-admin::contact-form-card', (component) => {
ContactFormSettingsForm.reloadValidation();
});
});

View File

@ -1,10 +1,10 @@
import '@vuexy-admin/notifications/LivewireNotification.js';
import FormCustomListener from '@vuexy-admin/forms/formCustomListener';
import registerLivewireHookOnce from '@vuexy-admin/livewire/registerLivewireHookOnce';
//import '@vuexy-admin/assets/js/notifications/LivewireNotification.js';
import FormCustomListener from '@vuexy-admin/assets/js/forms/formCustomListener';
//import registerLivewireHookOnce from '@vuexy-admin/assets/js/livewire/registerLivewireHookOnce';
// Inicializar formularios de ajustes de información de contacto
window.ContactInfoSettingsForm = new FormCustomListener({
formSelector: '#website-contact-info-settings-card',
formSelector: '#website-contact-info-card-card',
buttonSelectors: ['.btn-save', '.btn-cancel'],
callbacks: [() => {}],
dispatchOnSubmit: 'save',
@ -130,13 +130,13 @@ window.ContactInfoSettingsForm = new FormCustomListener({
}
});
registerLivewireHookOnce('morphed', 'vuexy-website-admin::contact-info-settings', (component) => {
registerLivewireHookOnce('morphed', 'vuexy-website-admin::contact-info-card', (component) => {
ContactInfoSettingsForm.reloadValidation();
});
// Inicializar formularios de ajustes de ubicación
window.LocationSettingsForm = new FormCustomListener({
formSelector: '#website-location-settings-card',
formSelector: '#website-location-card-card',
buttonSelectors: ['.btn-save', '.btn-cancel'],
callbacks: [() => {}],
dispatchOnSubmit: 'save',
@ -208,6 +208,6 @@ window.LocationSettingsForm = new FormCustomListener({
}
});
registerLivewireHookOnce('morphed', 'vuexy-website-admin::location-settings', (component) => {
registerLivewireHookOnce('morphed', 'vuexy-website-admin::location-card', (component) => {
LocationSettingsForm.reloadValidation();
});

View File

@ -1,6 +1,6 @@
import '@vuexy-admin/notifications/LivewireNotification.js';
import FormCustomListener from '@vuexy-admin/forms/formCustomListener';
import registerLivewireHookOnce from '@vuexy-admin/livewire/registerLivewireHookOnce';
//import '@vuexy-admin/assets/js/notifications/LivewireNotification.js';
import FormCustomListener from '@vuexy-admin/assets/js/forms/formCustomListener';
//import registerLivewireHookOnce from '@vuexy-admin/assets/js/livewire/registerLivewireHookOnce';
// Inicializar formularios de ajustes de análisis de datos
window.AnalyticsSettingsForm = new FormCustomListener({
@ -38,4 +38,4 @@ window.AnalyticsSettingsForm = new FormCustomListener({
registerLivewireHookOnce('morphed', 'vuexy-website-admin::analytics-index', (component) => {
AnalyticsSettingsForm.reloadValidation();
});
});

View File

@ -1,6 +1,6 @@
import '@vuexy-admin/notifications/LivewireNotification.js';
import FormCustomListener from '@vuexy-admin/forms/formCustomListener';
import registerLivewireHookOnce from '@vuexy-admin/livewire/registerLivewireHookOnce';
//import '@vuexy-admin/assets/js/notifications/LivewireNotification.js';
import FormCustomListener from '@vuexy-admin/assets/js/forms/formCustomListener';
//import registerLivewireHookOnce from '@vuexy-admin/assets/js/livewire/registerLivewireHookOnce';
// Inicializar formularios de ajustes de social media
window.SocialSettingsForm = new FormCustomListener({
@ -128,6 +128,6 @@ window.SocialSettingsForm = new FormCustomListener({
}
});
registerLivewireHookOnce('morphed', 'vuexy-website-admin::social-media-settings', (component) => {
registerLivewireHookOnce('morphed', 'vuexy-website-admin::social-card', (component) => {
SocialSettingsForm.reloadValidation();
});

View File

@ -17,13 +17,13 @@
@endsection
@push('page-script')
@vite('vendor/koneko/laravel-vuexy-website-admin/resources/js/google-analytics-settings-card.js')
@vite('vendor/koneko/laravel-vuexy-website-admin/resources/js/google-analytics-card-card.js')
@endpush
@section('content')
<div class="row">
<div class="col-md-6">
@livewire('vuexy-website-admin::google-analytics-settings')
@livewire('vuexy-website-admin::google-analytics-card')
</div>
</div>
@endsection

View File

@ -0,0 +1,11 @@
@extends('vuexy-admin::layouts.vuexy.layoutMaster')
@section('title', 'Google Search Console')
@section('content')
<div class="row">
<div class="col-md-6">
@livewire('vuexy-website-admin::google-search-console-card')
</div>
</div>
@endsection

View File

@ -0,0 +1,11 @@
@extends('vuexy-admin::layouts.vuexy.layoutMaster')
@section('title', 'Google Tags')
@section('content')
<div class="row">
<div class="col-md-6">
@livewire('vuexy-website-admin::google-tags-card')
</div>
</div>
@endsection

View File

@ -0,0 +1,11 @@
@extends('vuexy-admin::layouts.vuexy.layoutMaster')
@section('title', 'Pixel Meta')
@section('content')
<div class="row">
<div class="col-md-6">
@livewire('vuexy-website-admin::pixel-meta-card')
</div>
</div>
@endsection

View File

@ -0,0 +1,31 @@
@extends('vuexy-admin::layouts.vuexy.layoutMaster')
@section('title', 'Artículos del Blog')
@section('vendor-style')
@vite([
'vendor/koneko/laravel-vuexy-admin/resources/assets/vendor/libs/select2/select2.scss',
'vendor/koneko/laravel-vuexy-admin/resources/assets/vendor/libs/bootstrap-table/bootstrap-table.scss',
'vendor/koneko/laravel-vuexy-admin/resources/assets/vendor/fonts/bootstrap-icons.scss',
])
@endsection
@section('vendor-script')
@vite([
'vendor/koneko/laravel-vuexy-admin/resources/assets/vendor/libs/select2/select2.js',
])
@endsection
@push('page-script')
@vite([
'vendor/koneko/laravel-vuexy-admin/resources/assets/js/bootstrap-table/bootstrapTableManager.js',
'vendor/koneko/laravel-vuexy-admin/resources/assets/js/forms/formConvasHelper.js',
])
@endpush
@section('content')
@livewire('vuexy-website-admin::blog-articles-table')
<?php /*
@livewire('vuexy-website-admin::blog-article-offcanvas-form')
*/ ?>
@endsection

View File

@ -0,0 +1,31 @@
@extends('vuexy-admin::layouts.vuexy.layoutMaster')
@section('title', 'Categorías del Blog')
@section('vendor-style')
@vite([
'vendor/koneko/laravel-vuexy-admin/resources/assets/vendor/libs/select2/select2.scss',
'vendor/koneko/laravel-vuexy-admin/resources/assets/vendor/libs/bootstrap-table/bootstrap-table.scss',
'vendor/koneko/laravel-vuexy-admin/resources/assets/vendor/fonts/bootstrap-icons.scss',
])
@endsection
@section('vendor-script')
@vite([
'vendor/koneko/laravel-vuexy-admin/resources/assets/vendor/libs/select2/select2.js',
])
@endsection
@push('page-script')
@vite([
'vendor/koneko/laravel-vuexy-admin/resources/assets/js/bootstrap-table/bootstrapTableManager.js',
'vendor/koneko/laravel-vuexy-admin/resources/assets/js/forms/formConvasHelper.js',
])
@endpush
@section('content')
@livewire('vuexy-website-admin::blog-categories-table')
<?php /*
@livewire('vuexy-website-admin::blog-category-offcanvas-form')
*/ ?>
@endsection

View File

@ -0,0 +1,31 @@
@extends('vuexy-admin::layouts.vuexy.layoutMaster')
@section('title', 'Comentarios del Blog')
@section('vendor-style')
@vite([
'vendor/koneko/laravel-vuexy-admin/resources/assets/vendor/libs/select2/select2.scss',
'vendor/koneko/laravel-vuexy-admin/resources/assets/vendor/libs/bootstrap-table/bootstrap-table.scss',
'vendor/koneko/laravel-vuexy-admin/resources/assets/vendor/fonts/bootstrap-icons.scss',
])
@endsection
@section('vendor-script')
@vite([
'vendor/koneko/laravel-vuexy-admin/resources/assets/vendor/libs/select2/select2.js',
])
@endsection
@push('page-script')
@vite([
'vendor/koneko/laravel-vuexy-admin/resources/assets/js/bootstrap-table/bootstrapTableManager.js',
'vendor/koneko/laravel-vuexy-admin/resources/assets/js/forms/formConvasHelper.js',
])
@endpush
@section('content')
@livewire('vuexy-website-admin::blog-comments-table')
<?php /*
@livewire('vuexy-website-admin::blog-comment-offcanvas-form')
*/ ?>
@endsection

View File

@ -0,0 +1,31 @@
@extends('vuexy-admin::layouts.vuexy.layoutMaster')
@section('title', 'Etiquetas del Blog')
@section('vendor-style')
@vite([
'vendor/koneko/laravel-vuexy-admin/resources/assets/vendor/libs/select2/select2.scss',
'vendor/koneko/laravel-vuexy-admin/resources/assets/vendor/libs/bootstrap-table/bootstrap-table.scss',
'vendor/koneko/laravel-vuexy-admin/resources/assets/vendor/fonts/bootstrap-icons.scss',
])
@endsection
@section('vendor-script')
@vite([
'vendor/koneko/laravel-vuexy-admin/resources/assets/vendor/libs/select2/select2.js',
])
@endsection
@push('page-script')
@vite([
'vendor/koneko/laravel-vuexy-admin/resources/assets/js/bootstrap-table/bootstrapTableManager.js',
'vendor/koneko/laravel-vuexy-admin/resources/assets/js/forms/formConvasHelper.js',
])
@endpush
@section('content')
@livewire('vuexy-website-admin::blog-tags-table')
<?php /*
@livewire('vuexy-website-admin::blog-tag-offcanvas-form')
*/ ?>
@endsection

View File

@ -0,0 +1,11 @@
@extends('vuexy-admin::layouts.vuexy.layoutMaster')
@section('title', 'Facebook Messenger')
@section('content')
<div class="row">
<div class="col-md-6">
@livewire('vuexy-website-admin::messenger-card')
</div>
</div>
@endsection

View File

@ -0,0 +1,11 @@
@extends('vuexy-admin::layouts.vuexy.layoutMaster')
@section('title', 'Tawk-to Chat')
@section('content')
<div class="row">
<div class="col-md-6">
@livewire('vuexy-website-admin::tawk-to-card')
</div>
</div>
@endsection

View File

@ -1,6 +1,6 @@
@extends('vuexy-admin::layouts.vuexy.layoutMaster')
@section('title', 'Redes Sociales')
@section('title', 'Twitter API')
@section('vendor-style')
@vite([
@ -17,9 +17,13 @@
@endsection
@push('page-script')
@vite('vendor/koneko/laravel-vuexy-website-admin/resources/js/website-settings-card.js')
@vite('vendor/koneko/laravel-vuexy-website-admin/resources/js/google-analytics-card-card.js')
@endpush
@section('content')
@livewire('vuexy-website-admin::social-media-settings')
<div class="row">
<div class="col-md-6">
@livewire('vuexy-website-admin::twitter-card')
</div>
</div>
@endsection

View File

@ -1,6 +1,6 @@
@extends('vuexy-admin::layouts.vuexy.layoutMaster')
@section('title', 'Chat')
@section('title', 'Whatsapp Chat')
@section('vendor-style')
@vite([
@ -23,7 +23,7 @@
@section('content')
<div class="row">
<div class="col-md-6">
@livewire('vuexy-website-admin::chat-settings')
@livewire('vuexy-website-admin::whatsapp-card')
</div>
</div>
@endsection

View File

@ -17,13 +17,13 @@
@endsection
@push('page-script')
@vite('vendor/koneko/laravel-vuexy-website-admin/resources/js/contact-form-settings-card.js')
@vite('vendor/koneko/laravel-vuexy-website-admin/resources/js/contact-form-card-card.js')
@endpush
@section('content')
<div class="row">
<div class="col-md-6">
@livewire('vuexy-website-admin::contact-form-settings')
@livewire('vuexy-website-admin::contact-form-card')
</div>
</div>
@endsection

View File

@ -17,16 +17,16 @@
@endsection
@push('page-script')
@vite('vendor/koneko/laravel-vuexy-website-admin/resources/js/contact-info-settings-card.js')
@vite('vendor/koneko/laravel-vuexy-website-admin/resources/js/contact-info-card-card.js')
@endpush
@section('content')
<div class="row">
<div class="col-md-6">
@livewire('vuexy-website-admin::contact-info-settings')
@livewire('vuexy-website-admin::contact-info-card')
</div>
<div class="col-md-6">
@livewire('vuexy-website-admin::location-settings')
@livewire('vuexy-website-admin::contact-location-card')
</div>
</div>
@endsection

View File

@ -7,5 +7,5 @@
@endpush
@section('content')
@livewire('vuexy-website-admin::images-index')
@livewire('vuexy-website-admin::gallery-index')
@endsection

View File

@ -3,5 +3,5 @@
@section('title', 'Avisos Legales')
@section('content')
@livewire('vuexy-website-admin::legal-notices-index')
@livewire('vuexy-website-admin::legal-index')
@endsection

View File

@ -20,9 +20,11 @@
@endsection
@section('page-script')
@vite('modules/Admin/Resources/js/website-settings/legal-settings-scripts.js')
@vite([
//'modules/Admin/Resources/js/website-settings/legal-settings-scripts.js'
])
@endsection
@section('content')
@livewire('website-legal-settings')
@livewire('legal-index')
@endsection

View File

@ -0,0 +1,72 @@
{{-- SEO HEAD - Generado automáticamente por SeoProfileService --}}
@php($_seo = $_seo ?? [])
{{-- Canonical + Fonts --}}
<link rel="canonical" href="{{ $_seo['canonical'] ?? url()->current() }}" />
<link rel="preconnect" href="https://fonts.googleapis.com" crossorigin>
<link rel="preload" as="style" href="https://fonts.googleapis.com/css2?family=Poppins&display=swap" />
{{-- Charset (el viewport va en layout, no en SEO) --}}
<meta charset="utf-8">
{{-- hreflang alternates (multi-language SEO) --}}
@foreach ($_seo['hreflangs'] ?? [] as $lang => $url)
<link rel="alternate" hreflang="{{ $lang }}" href="{{ $url }}" />
@endforeach
{{-- Título + SEO Meta --}}
<title>{{ $_seo['title'] ?? config('app.name') }}</title>
<meta name="description" content="{{ $_seo['description'] ?? '' }}">
<meta name="robots" content="{{ $_seo['robots'] ?? 'index, follow' }}">
<meta name="language" content="{{ $_seo['language'] ?? app()->getLocale() }}">
<meta name="author" content="{{ $_seo['author'] ?? 'Koneko Team' }}">
<meta name="keywords" content="{{ $_seo['keywords'] ?? '' }}">
<meta name="distribution" content="global">
<meta name="revisit-after" content="7 days">
<meta name="copyright" content="{{ $_seo['author'] ?? 'Koneko' }}">
{{-- CSRF (Laravel) --}}
<meta name="csrf-token" content="{{ csrf_token() }}">
{{-- OpenGraph --}}
<meta property="og:title" content="{{ $_seo['og:title'] ?? $_seo['title'] ?? '' }}">
<meta property="og:site_name" content="{{ $_seo['og:site_name'] ?? config('app.name') }}">
<meta property="og:url" content="{{ $_seo['og:url'] ?? url()->current() }}">
<meta property="og:description" content="{{ $_seo['og:description'] ?? $_seo['description'] ?? '' }}">
<meta property="og:type" content="{{ $_seo['og:type'] ?? 'website' }}">
<meta property="og:image" content="{{ $_seo['og:image'] ?? '' }}">
{{-- Twitter Card --}}
<meta name="twitter:card" content="{{ $_seo['twitter:card'] ?? 'summary_large_image' }}">
<meta name="twitter:title" content="{{ $_seo['twitter:title'] ?? $_seo['title'] ?? '' }}">
<meta name="twitter:description" content="{{ $_seo['twitter:description'] ?? $_seo['description'] ?? '' }}">
<meta name="twitter:image" content="{{ $_seo['twitter:image'] ?? $_seo['og:image'] ?? '' }}">
<meta name="twitter:site" content="{{ $_seo['twitter:site'] ?? '' }}">
<meta name="twitter:creator" content="{{ $_seo['twitter:creator'] ?? '' }}">
{{-- Favicons dinámicos --}}
@foreach ($_seo['favicon'] ?? [] as $size => $path)
@php($fullPath = Str::startsWith($path, ['http://', 'https://']) ? $path : asset('storage/' . $path))
@switch(true)
@case(Str::endsWith($path, '.svg'))
<link rel="icon" type="image/svg+xml" sizes="{{ $size }}" href="{{ $fullPath }}">
@break
@case(Str::endsWith($path, '.apng'))
<link rel="icon" type="image/apng" sizes="{{ $size }}" href="{{ $fullPath }}">
@break
@case(Str::startsWith($size, 'apple'))
<link rel="apple-touch-icon" sizes="{{ Str::after($size, 'apple-') }}" href="{{ $fullPath }}">
@break
@default
<link rel="icon" type="image/png" sizes="{{ $size }}" href="{{ $fullPath }}">
@endswitch
@endforeach
{{-- Web App Manifest --}}
<link rel="manifest" href="{{ $_seo['manifest'] ?? asset('site.webmanifest') }}">
<meta name="theme-color" content="{{ $_seo['theme-color'] ?? '#ffffff' }}">
{{-- JSON-LD Structured Data --}}
@if (!empty($_seo['ld+json']))
<script type="application/ld+json">@json($_seo['ld+json'])</script>
@endif

View File

@ -0,0 +1,34 @@
<div x-data="{ googleanalyticsEnabled: @entangle('google_analytics_enabled') }">
<x-vuexy-admin::form.form id="website-analytics-settings-card" class="form-custom-listener mb-4" whitOutId whitOutMode>
<x-vuexy-admin::card.basic title="Google Analytics" class="mb-2">
<div class="mb-6">
<a href="https://analytics.google.com/analytics/web/">https://analytics.google.com/analytics/web/</a>
</div>
<x-vuexy-admin::form.checkbox model="google_analytics_enabled" label="Habilitar Google Analytics" switch />
<x-vuexy-admin::form.input model="google_analytics_id" label="ID de medición de Google Analytics" icon="fab fa-google" placeholder="XX-12345678901" x-bind:disabled='!googleanalyticsEnabled' />
</x-vuexy-admin::card.basic>
<div class="row">
<div class="col-lg-12 text-end">
<x-vuexy-admin::button.basic
type="submit"
variant="primary"
size="sm"
icon="ti ti-device-floppy"
label="Guardar cambios"
disabled
class="btn-save mt-2 mr-2 waves-effect waves-light"
waves
data-loading-text="Guardando..." />
<x-vuexy-admin::button.basic
variant="secondary"
size="sm"
icon="ti ti-rotate-2"
label="Cancelar"
wire:click="resetForm"
class="btn-cancel mt-2 mr-2 waves-effect waves-light"
waves />
</div>
</div>
<div class="notification-container pt-4" wire:ignore></div>
</x-vuexy-admin::form.form>
</div>

View File

@ -0,0 +1,34 @@
<div x-data="{ googleanalyticsEnabled: @entangle('google_analytics_enabled') }">
<x-vuexy-admin::form.form id="website-analytics-settings-card" class="form-custom-listener mb-4" whitOutId whitOutMode>
<x-vuexy-admin::card.basic title="Google Analytics" class="mb-2">
<div class="mb-6">
<a href="https://analytics.google.com/analytics/web/">https://analytics.google.com/analytics/web/</a>
</div>
<x-vuexy-admin::form.checkbox model="google_analytics_enabled" label="Habilitar Google Analytics" switch />
<x-vuexy-admin::form.input model="google_analytics_id" label="ID de medición de Google Analytics" icon="fab fa-google" placeholder="XX-12345678901" x-bind:disabled='!googleanalyticsEnabled' />
</x-vuexy-admin::card.basic>
<div class="row">
<div class="col-lg-12 text-end">
<x-vuexy-admin::button.basic
type="submit"
variant="primary"
size="sm"
icon="ti ti-device-floppy"
label="Guardar cambios"
disabled
class="btn-save mt-2 mr-2 waves-effect waves-light"
waves
data-loading-text="Guardando..." />
<x-vuexy-admin::button.basic
variant="secondary"
size="sm"
icon="ti ti-rotate-2"
label="Cancelar"
wire:click="resetForm"
class="btn-cancel mt-2 mr-2 waves-effect waves-light"
waves />
</div>
</div>
<div class="notification-container pt-4" wire:ignore></div>
</x-vuexy-admin::form.form>
</div>

View File

@ -0,0 +1,34 @@
<div x-data="{ googleanalyticsEnabled: @entangle('google_analytics_enabled') }">
<x-vuexy-admin::form.form id="website-analytics-settings-card" class="form-custom-listener mb-4" whitOutId whitOutMode>
<x-vuexy-admin::card.basic title="Google Analytics" class="mb-2">
<div class="mb-6">
<a href="https://analytics.google.com/analytics/web/">https://analytics.google.com/analytics/web/</a>
</div>
<x-vuexy-admin::form.checkbox model="google_analytics_enabled" label="Habilitar Google Analytics" switch />
<x-vuexy-admin::form.input model="google_analytics_id" label="ID de medición de Google Analytics" icon="fab fa-google" placeholder="XX-12345678901" x-bind:disabled='!googleanalyticsEnabled' />
</x-vuexy-admin::card.basic>
<div class="row">
<div class="col-lg-12 text-end">
<x-vuexy-admin::button.basic
type="submit"
variant="primary"
size="sm"
icon="ti ti-device-floppy"
label="Guardar cambios"
disabled
class="btn-save mt-2 mr-2 waves-effect waves-light"
waves
data-loading-text="Guardando..." />
<x-vuexy-admin::button.basic
variant="secondary"
size="sm"
icon="ti ti-rotate-2"
label="Cancelar"
wire:click="resetForm"
class="btn-cancel mt-2 mr-2 waves-effect waves-light"
waves />
</div>
</div>
<div class="notification-container pt-4" wire:ignore></div>
</x-vuexy-admin::form.form>
</div>

Some files were not shown because too many files have changed in this diff Show More