wiki features

This commit is contained in:
amazuecos
2025-02-23 00:14:07 +01:00
parent f270b6dee8
commit eea947e80b
13 changed files with 251 additions and 33 deletions

View File

@ -43,7 +43,9 @@ class WikiController extends BaseController
$section = $this->wikiSectionModel->where('slug', $slug)->first();
$this->viewData['slug'] = $slug;
$this->viewData['section'] = $section->withAll($this->locale);
$this->viewData['breadcrumb'] = [
['title' => lang("Wiki.".$section->slug), 'route' => route_to('showWikiPage',$slug), 'active' => true],
];
return view('themes/vuexy/wiki/pages/render', $this->viewData);
}
public function get_section(int $section_id)
@ -72,6 +74,24 @@ class WikiController extends BaseController
]);
return $this->response->setJSON(["data" => [], "message" => lang("App.global_alert_save_success")]);
}
public function store_publish_page(int $section_id)
{
$bodyData = $this->request->getPost();
$wikiSectionPage = $this->wikiSectionModel->find($section_id)->page();
if ($wikiSectionPage) {
$wikiPageId = $wikiSectionPage->id;
$this->wikiContentModel->update($wikiPageId,[
"locale" => $this->locale,
"page_id" => $wikiPageId,
"editor_data" => json_encode($bodyData),
"published_data" => json_encode($bodyData)
]);
$response = $this->response->setJSON(["data" => [], "message" => lang("App.global_alert_save_success")]);
} else {
$response = $this->response->setStatusCode(400)->setJSON(["data" => [], "error" => lang('Wiki.errors.publish_before_save')]);
}
return $response;
}
public function wiki_file_upload(int $section_id)
{
try {

View File

@ -27,6 +27,11 @@ class WikiSectionsMigration extends Migration
'constraint' => 255,
'default' => 'admin'
],
'icon' => [
'type' => 'VARCHAR',
'constraint' => 255,
'null' => true,
],
'parent_section_id' => [
'type' => 'INT',
'unsigned' => true,

View File

@ -0,0 +1,74 @@
<?php
namespace App\Database\Seeds;
use App\Models\Configuracion\ConfigVariableModel;
use App\Models\Wiki\WikiSectionModel;
use CodeIgniter\Database\Seeder;
class WikiSectionSeeder extends Seeder
{
protected array $data = [
[
"name" => 'Introducción',
"slug" => 'intro',
"icon" => 'ti ti-home-2'
],
[
"name" => 'Presupuesto',
"slug" => 'presupuesto-administrador',
"icon" => 'ti ti-currency-dollar'
],
[
"name" => 'Presupuesto cliente',
"slug" => 'presupuesto-cliente',
"role" => 'cliente',
"icon" => 'ti ti-currency-dollar'
],
[
"name" => 'Pedidos',
"slug" => 'pedidos',
"icon" => 'ti ti-file-description'
],
[
"name" => 'Facturación',
"slug" => 'facturacion',
"icon" => 'ti ti-file-dollar'
],
[
"name" => 'Logística',
"slug" => 'logistica',
"icon" => 'ti ti-truck'
],
[
"name" => 'Tarifas',
"slug" => 'tarifas',
"icon" => 'ti ti-receipt'
],
[
"name" => 'Configuración',
"slug" => 'config',
"icon" => 'ti ti-adjustments-horizontal'
],
[
"name" => 'Mensajería',
"slug" => 'messages',
"icon" => 'ti ti-message'
]
];
public function run()
{
$wikiSectionModel = model(WikiSectionModel::class);
foreach ($this->data as $key => $row) {
# code...
$wikiSectionModel->insert($row);
}
}
}

View File

@ -11,12 +11,14 @@ class WikiSectionEntity extends Entity
"name" => null,
"slug" => null,
"role" => null,
"icon" => null,
"parent_id" => null
];
protected $casts = [
"name" => "string",
"slug" => "string",
"role" => "string",
"icon" => "string",
"parent_id" => "int"
];

View File

@ -0,0 +1,18 @@
<?php
return [
'intro' => "Introduction",
'presupuesto-cliente' => "Cliente budget",
'presupuesto-administrador' => "Admin budget",
'pedidos' => "Orders",
'facturacion' => "Invoice",
'logistica' => "Logistic",
'tarifas' => "Tariff",
'config' => "Configuration",
'messages' => "Messages",
'errors' => [
'publish_before_save' => "You have to save before publish the content"
],
'published' => 'Released',
'not_published' => 'Not released'
];

View File

@ -0,0 +1,18 @@
<?php
return [
'intro' => "Introducción",
'presupuesto-cliente' => "Presupuesto cliente",
'presupuesto-administrador' => "Presupuesto admin",
'pedidos' => "Pedidos",
'facturacion' => "Facturación",
'logistica' => "Logística",
'tarifas' => "Tarifas",
'config' => "Configuración",
'messages' => "Mensajería",
'errors' => [
'publish_before_save' => "Es necesario guardar antes de publicar"
],
'published' => 'Publicado',
'not_published' => 'Sin publicar'
];

View File

@ -17,6 +17,7 @@ class WikiSectionModel extends Model
"name",
"slug",
"role",
"icon",
"parent_id"
];

View File

@ -1,7 +1,7 @@
<!-- Messages -->
<li class="menu-item">
<a href="<?= route_to('wikiIndex') ?>" class="menu-link">
<a href="<?= route_to('showWikiPage','intro') ?>" class="menu-link">
<i class="menu-icon tf-icons ti ti-books"></i>
<?= lang("Wiki") ?>
</a>

View File

@ -107,18 +107,18 @@ $picture = "/assets/img/default-user.png";
<ul class="menu-inner py-1">
<li class="menu-item">
<!-- Iterate throught sections -->
<?php foreach ($wiki_sections as $key => $value) : ?>
<!-- Iterate throught sections -->
<?php foreach ($wiki_sections as $key => $value) : ?>
<li class="menu-item <?= $value->slug == $slug ? 'active' : "" ?>">
<!-- Check if user can view the section link -->
<?php if (auth()->user()->inGroup($value->role)): ?>
<a href="<?= site_url("wiki/render/".$value->slug) ?>" class="menu-link">
<i class="menu-icon tf-icons ti ti-book"></i>
<?= $value->name ?>
<?php if (auth()->user()->inGroup($value->role) || auth()->user()->inGroup('admin') ): ?>
<a href="<?= site_url("wiki/view/".$value->slug) ?>" class="menu-link" >
<i class="menu-icon tf-icons <?= $value->icon ?>"></i>
<?= lang("Wiki.".$value->slug) ?>
</a>
<?php endif; ?>
</li>
<?php endforeach; ?>
</li>
</ul>
</aside>

View File

@ -14,26 +14,38 @@
</div><!--//.card-header -->
<div class="card-body">
<div class="row">
<form action="POST" id="form-wiki">
<input type="hidden" name="slug" id="section-slug">
<input type="hidden" name="wiki_page_id" id="wiki-section-id" value="<?=$section->id?>">
<input type="hidden" name="wiki_page_id" id="wiki-page-id">
<input type="hidden" name="wiki_page_id" id="wiki-content-id">
</form>
<form action="POST" id="form-wiki">
<input type="hidden" name="slug" id="section-slug">
<input type="hidden" name="wiki_page_id" id="wiki-section-id" value="<?= $section->id ?>">
<input type="hidden" name="wiki_page_id" id="wiki-page-id">
<input type="hidden" name="wiki_page_id" id="wiki-content-id">
</form>
<?php if (auth()->user()->inGroup('admin')): ?>
<div class="col-md-10">
<div id="editorjs"></div>
</div>
<div class="col-md-2">
<div class="d-flex flex-column justify-content-center gap-3">
<button type="button" class="btn btn-primary btn-sm" id="save-editor"><i class="icon-base ti ti-device-floppy icon-xs me-2"></i><?= lang('App.global_save') ?></button>
<button type="button" class="btn btn-danger btn-sm" id="release-editor"><i class="icon-base ti ti-upload icon-xs me-2"></i>Publicar</button>
<button type="button" class="btn btn-secondary btn-sm d-none" id="preview-editor"><i class="icon-base ti ti-eye icon-xs me-2"></i>Vista previa</button>
<button type="button" class="btn btn-warning btn-sm" id="edit-editor"><i class="icon-base ti ti-pencil icon-xs me-2"></i>Editar</button>
<div class="col-md-12 d-flex flex-row justify-content-between align-items-center pb-2">
<div class="d-flex flex-row gap-2 justify-content-start align-items-center">
<?php if ($section->content()?->published_data): ?>
<span class="badge badge-center rounded-pill text-bg-success"><i class="ti ti-check"></i></span>
<strong><?= lang('Wiki.published') ?></strong>
<?php else: ?>
<span class="badge badge-center rounded-pill text-bg-danger"><i class="ti ti-alert-circle"></i></span>
<strong><?= lang('Wiki.not_published') ?></strong>
<?php endif; ?>
</div>
<div class="btn-group btn-group-sm" role="group">
<button type="button" class="btn btn-primary" id="save-editor"><i class="icon-base ti ti-device-floppy icon-xs me-2"></i><?= lang('App.global_save') ?></button>
<button type="button" class="btn btn-danger" id="release-editor"><i class="icon-base ti ti-upload icon-xs me-2"></i>Publicar</button>
<button type="button" class="btn btn-secondary d-none" id="preview-editor"><i class="icon-base ti ti-eye icon-xs me-2"></i>Vista previa</button>
<button type="button" class="btn btn-warning" id="edit-editor"><i class="icon-base ti ti-pencil icon-xs me-2"></i>Editar</button>
</div>
</div>
<div class="col-md-12">
<div id="editorjs"></div>
</div>
<?php else : ?>
<div class="col-md-12">
<div id="editorjs"></div>
</div>
@ -50,7 +62,7 @@
<?= $this->endSection() ?>
<?= $this->section('css') ?>
<link rel="stylesheet" href="<?= site_url('themes/vuexy/vendor/libs/sweetalert2/sweetalert2.css') ?>" />
<link rel="stylesheet" href="<?= site_url('themes/vuexy/vendor/libs/sweetalert2/sweetalert2.css') ?>" />
<?= $this->endSection() ?>
<?= $this->section("additionalExternalJs") ?>

View File

@ -18,7 +18,7 @@
<li class="menu-item">
<?php foreach ($wiki_sections as $key => $value) :?>
<a href="<?= site_url("wiki/presupuesto")?>" class="menu-link menu-toggle">
<a href="<?= site_url("wiki/presupuesto")?>" class="menu-link menu-toggle" data-id="<?= $slug ?>">
<i class="menu-icon tf-icons ti ti-book"></i>
<?= lang("App.menu_presupuestos") ?>
</a>

View File

@ -17,7 +17,23 @@ export const alertConfirmationDelete = (title, type = "primary") => {
buttonsStyling: false
})
}
export const alertConfirmAction = (title, type = "primary") => {
return Swal.fire({
title: '¿Está seguro?',
text: title,
icon: 'info',
showCancelButton: true,
confirmButtonColor: '#3085d6',
cancelButtonColor: '#d33',
confirmButtonText: 'Sí',
cancelButtonText: 'Cancelar',
customClass: {
confirmButton: 'btn btn-success me-1',
cancelButton: 'btn btn-label-secondary'
},
buttonsStyling: false
})
}
export const alertSuccessMessage = (title, type = "primary") => {
return Swal.fire({
showCancelButton: false,

View File

@ -11,7 +11,7 @@ import '../../../../../themes/vuexy/js/editorjs/tune.js';
import Ajax from '../ajax.js'
import { alertError, alertSuccess, alertWarning } from '../alerts/sweetAlert.js';
import { alertConfirmAction, alertError, alertSuccess, alertWarning } from '../alerts/sweetAlert.js';
class WikiEditor {
constructor() {
@ -48,7 +48,6 @@ class WikiEditor {
class: Alert,
inlineToolbar: true,
tunes : ['alignment'],
shortcut: 'CMD+SHIFT+W',
config: {
alertTypes: ['primary', 'secondary', 'info', 'success', 'warning', 'danger', 'light', 'dark'],
defaultType: 'primary',
@ -102,19 +101,41 @@ class WikiEditor {
new DragDrop(this.editor);
/** Do anything you need after editor initialization */
$('#save-editor').on('click', () => {
this.editor.save().then(outputData => {
this.editor.readOnly.toggle()
console.log("Data saved", outputData)
this.handleSaveContent(outputData)
alertConfirmAction('Guardar contenido').then(result => {
if(result.isConfirmed){
this.handleSaveContent(outputData)
}
});
})
})
$('#release-editor').on('click', () => {
this.editor.save().then(outputData => {
this.editor.readOnly.toggle()
console.log("Data published", outputData)
alertConfirmAction('Publicar contenido').then(result => {
if(result.isConfirmed){
this.handlePublishContent(outputData)
}
});
})
})
$('#preview-editor').on('click', () => {
this.editor.readOnly.toggle()
$('#edit-editor').removeClass('d-none')
$('#preview-editor').addClass('d-none')
$('#release-editor').attr('disabled',null)
$('#save-editor').attr('disabled',null)
})
$('#edit-editor').on('click', () => {
$('#edit-editor').addClass('d-none')
$('#preview-editor').removeClass('d-none')
$('#release-editor').attr('disabled','disabled')
$('#save-editor').attr('disabled','disabled')
this.editor.readOnly.toggle()
})
this.handleGetData();
@ -143,6 +164,26 @@ class WikiEditor {
handleGetDataError(error) {
console.log(error)
}
handleGetDataPublished() {
const ajax = new Ajax(`/wiki/section/${this.sectionId}`,
null,
null,
this.handleGetDataSuccess.bind(this),
this.handleGetDataError.bind(this))
ajax.get()
}
handleGetDataPublishedSuccess(response) {
if (response.data.contents) {
alertSuccess(response.message).fire()
this.renderContent(response.data.contents.editor_data)
} else {
alertWarning('No hay contenido').fire()
}
}
handleGetDataPublishedError(error) {
alertError(error.error).fire()
}
renderContent(content) {
try {
let parsedContent = JSON.parse(content)
@ -162,7 +203,18 @@ class WikiEditor {
}
handleSaveContentSuccess(response) {
this.handleGetData()
// alertSuccess(response.message).fire()
}
handleSaveContentError(response) { }
handlePublishContent(data) {
const ajax = new Ajax(`/wiki/publish/${this.sectionId}`,
data,
null,
this.handleSaveContentSuccess.bind(this),
this.handleSaveContentError.bind(this))
ajax.post()
}
handleSaveContentSuccess(response) {
this.handleGetData()
}
handleSaveContentError(response) { }