Merge branch 'feat/config-variables-app' into 'main'

feat: add config variable menu

See merge request jjimenez/safekat!342
This commit is contained in:
Alvaro
2024-10-02 18:37:49 +00:00
14 changed files with 599 additions and 3 deletions

View File

@ -85,6 +85,13 @@ $routes->group('configuracion', ['namespace' => 'App\Controllers\Configuracion']
$routes->get('delete/(:num)', 'FormasPago::delete/$1', ['as' => 'formasPagoDelete']);
$routes->post('datatable', 'FormasPago::datatable', ['as' => 'formasPagoDT']);
});
$routes->group("variables",["namespace" => 'App\Controllers\Configuracion'],function($routes){
$routes->get('', 'ConfigVariables::index', ['as' => 'variablesIndex']);
$routes->get('find/(:num)', 'ConfigVariables::get/$1', ['as' => 'variablesFind']);
$routes->post('edit/(:num)', 'ConfigVariables::updateVariable/$1', ['as' => 'updateVariable']);
$routes->delete('delete/(:num)', 'ConfigVariables::delete/$1', ['as' => 'deleteVariable']);
$routes->get('datatable', 'ConfigVariables::datatable', ['as' => 'datatableVariables']);
});
});

View File

@ -0,0 +1,92 @@
<?php
namespace App\Controllers\Configuracion;
use App\Controllers\BaseResourceController;
use App\Models\Collection;
use App\Models\Configuracion\ConfigVariableModel;
use CodeIgniter\HTTP\Response;
use Hermawan\DataTables\DataTable;
class ConfigVariables extends BaseResourceController
{
protected $modelName = ConfigVariableModel::class;
protected ConfigVariableModel $configVariableModel;
protected $format = 'json';
protected static $singularObjectName = 'Variables';
protected static $singularObjectNameCc = 'variables';
protected static $pluralObjectName = 'Variables';
protected static $pluralObjectNameCc = 'variables';
protected static $controllerSlug = 'variables';
protected static $viewPath = 'themes/vuexy/form/configuracion/variables/';
protected $indexRoute = 'viewVariablesList';
public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger)
{
parent::initController($request, $response, $logger);
$this->configVariableModel = model(ConfigVariableModel::class);
}
public function index()
{
$viewData = [
'currentModule' => static::$controllerSlug,
];
$viewData = array_merge($this->viewData, $viewData); // merge any possible values from the parent controller class
return view(static::$viewPath . $this->indexRoute, $viewData);
}
public function store(){
$data = [];
$variableCreated = $this->configVariableModel->store($data);
return $this->response->setJSON($variableCreated);
}
public function get(int $config_variable_id){
$data = $this->configVariableModel->find($config_variable_id);
return $this->response->setJSON($data);
}
public function updateVariable(int $config_variable_id){
$reqData = [];
if ($this->request->isAJAX()) {
$reqData = $this->request->getPost();
$status = $this->configVariableModel->update($config_variable_id,$reqData);
return $this->response->setJSON([
"message" => "Variable actualizada correctamente",
"status" => $status
]);
}
else {
return $this->failUnauthorized('Invalid request', 403);
}
}
public function deleteVariable(int $config_variable_id): Response
{
return $this->response->setJSON([]);
}
public function datatable(){
$query = $this->configVariableModel->builder()->select([
"id",
"name",
"value",
"description"])->orderBy("name","asc");
return DataTable::of($query)
->add("action",fn($q) => $q->id)
->toJson(true);
}
}

View File

@ -0,0 +1,61 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
use CodeIgniter\Database\RawSql;
class ConfigVariablesApp extends Migration
{
protected array $COLUMNS = [
"id" => [
"type" => "INT",
"unsigned" => true,
"auto_increment" => true
],
"name" => [
"type" => "VARCHAR",
"constraint" => '45',
"unique" => true,
],
"value" => [
"type" => "VARCHAR",
"constraint" => '255',
"null" => true
],
"description" => [
"type" => "TEXT",
"null" => true
],
];
public function up()
{
$this->forge->addField($this->COLUMNS);
$currenttime = new RawSql("CURRENT_TIMESTAMP");
$this->forge->addField([
"created_at" => [
"type" => "TIMESTAMP",
"default" => $currenttime,
],
"updated_at" => [
"type" => "TIMESTAMP",
"null" => true,
],
"deleted_at" => [
"type" => "TIMESTAMP",
"null" => true,
],
]);
$this->forge->addPrimaryKey('id');
$this->forge->createTable("config_variables_app", true);
}
public function down()
{
$this->forge->dropTable("config_variables_app");
}
}

View File

@ -0,0 +1,37 @@
<?php
namespace App\Database\Seeds;
use App\Models\Configuracion\ConfigVariableModel;
use CodeIgniter\Database\Seeder;
class DefaultConfigVariablesSeeder extends Seeder
{
protected array $data = [
[
"name" => "tamanio_solapas_min",
"value" => 50,
"description" => "Mínimo tamaño solapas"
],
[
"name" => "tamanio_solapas_max",
"value" => 150,
"description" => "Máximo tamaño solapas"
],
[
"name" => "limite_produccion_diaria",
"value" => 6000,
"description" => "Número de libros máximos que se puede producir al día"
],
];
public function run()
{
$variableModel = model(ConfigVariableModel::class);
foreach ($this->data as $row) {
if($variableModel->where("name",$row["name"])->first() == null){
$variableModel->insert($row);
}
}
}
}

View File

@ -670,7 +670,6 @@ return [
// MENUS
"menu_dashboard" => "Panel de control",
"menu_clientes" => "Clientes",
"menu_plantillas_tarifas_clientes" => "Plantillas Tarifas",
"menu_perfil_clientes" => "Perfil",
@ -680,6 +679,7 @@ return [
"menu_tarifacliente" => "Tarifas",
"menu_configuration" => "Configuración",
"menu_variables" => "Variables sistema",
"menu_calendario" => "Calendario",
"menu_paises" => "Paises",
"menu_correo" => "Correo",

View File

@ -0,0 +1,22 @@
<?php
return [
"cardTitle" => "Variables del sistema",
"modal" => [
"title" => "Editar variable"
],
"datatable" =>
[
"columns" => [
"name" => "Nombre",
"value" => "Valor",
"description" => "Descripción",
]
],
"form" =>
[
"name" => "Nombre",
"value" => "Valor",
"description" => "Descripción",
]
];

View File

@ -0,0 +1,50 @@
<?php
namespace App\Models\Configuracion;
use CodeIgniter\Model;
class ConfigVariableModel extends Model
{
protected $table = 'config_variables_app';
protected $primaryKey = 'id';
protected $useAutoIncrement = true;
protected $returnType = 'array';
protected $useSoftDeletes = false;
protected $protectFields = true;
protected $allowedFields = [
"name",
"value",
"description"
];
protected bool $allowEmptyInserts = false;
protected bool $updateOnlyChanged = true;
protected array $casts = [];
protected array $castHandlers = [];
// Dates
protected $useTimestamps = false;
protected $dateFormat = 'datetime';
protected $createdField = 'created_at';
protected $updatedField = 'updated_at';
protected $deletedField = 'deleted_at';
// Validation
protected $validationRules = [];
protected $validationMessages = [];
protected $skipValidation = false;
protected $cleanValidationRules = true;
// Callbacks
protected $allowCallbacks = true;
protected $beforeInsert = [];
protected $afterInsert = [];
protected $beforeUpdate = [];
protected $afterUpdate = [];
protected $beforeFind = [];
protected $afterFind = [];
protected $beforeDelete = [];
protected $afterDelete = [];
}

View File

@ -0,0 +1,78 @@
<?= $this->include('themes/_commonPartialsBs/select2bs5') ?>
<?= $this->include('themes/_commonPartialsBs/datatables') ?>
<?= $this->include('themes/_commonPartialsBs/_confirm2delete') ?>
<?= $this->extend('themes/vuexy/main/defaultlayout') ?>
<?= $this->section('content'); ?>
<div class="row">
<div class="col-md-12">
<div class="card card-info">
<div class="card-header">
<h3 class="card-title"><?= lang('ConfigVariables.cardTitle') ?></h3>
</div><!--//.card-header -->
<div class="card-body">
<?= view('themes/_commonPartialsBs/_alertBoxes'); ?>
<table id="tableConfigVariables" class="table table-striped table-hover" style="width: 100%;">
<thead>
<tr>
<th><?= lang('ConfigVariables.datatable.columns.name') ?></th>
<th><?= lang('ConfigVariables.datatable.columns.value') ?></th>
<th><?= lang('ConfigVariables.datatable.columns.description') ?></th>
<th class="text-nowrap"><?= lang('Basic.global.Action') ?></th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div><!--//.card-body -->
<div class="card-footer">
</div><!--//.card-footer -->
</div><!--//.card -->
</div><!--//.col -->
</div><!--//.row -->
<!-- Modal -->
<div class="modal fade" id="modalConfigVariableForm" tabindex="-1" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel1"><?= lang('ConfigVariables.modal.title') ?></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<form id="formEditConfigVariable">
<div class="form-group">
<div class="row">
<div class="col mb-4">
<label for="name" class="form-label"><?= lang('ConfigVariables.form.name') ?></label>
<input type="text" id="name" class="form-control" disabled>
</div>
</div>
<div class="row g-4">
<div class="col-12 mb-0">
<label for="value" class="form-label"><?= lang('ConfigVariables.form.value') ?></label>
<input type="number" min=0 id="value" class="form-control">
</div>
<div class="col-12 mb-0">
<label for="description" class="form-label"><?= lang('ConfigVariables.form.description') ?></label>
<textarea type="text" rows="4" cols="10" id="description" class="form-control"></textarea>
</div>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-label-secondary" data-bs-dismiss="modal"><?= lang('App.global_come_back') ?></button>
<button type="button" class="btn btn-primary btn-update-variable"><?= lang('App.global_save') ?></button>
</div>
</div>
</div>
</div>
<?= $this->endSection() ?>
<?= $this->section("additionalExternalJs") ?>
<script type="module" src="<?= site_url('assets/js/safekat/pages/configuracion/variables.js') ?>"></script>
<?= $this->endSection() ?>

View File

@ -1,4 +1,5 @@
<?php
/**
* MENU CONFIGURACION
*/
@ -12,13 +13,14 @@ if (
auth()->user()->can('usuarios.menu') ||
auth()->user()->can('roles-permisos.menu')
) {
?>
?>
<li class="menu-item">
<a href="javascript:void(0);" class="menu-link menu-toggle">
<i class="menu-icon tf-icons ti ti-adjustments-horizontal"></i>
<?= lang("App.menu_configuration") ?>
</a>
<ul class="menu-sub">
<?php if (auth()->user()->can('paises.menu')) { ?>
<li class="menu-item">
<a href="<?= route_to('paisList') ?>" class="menu-link">
@ -96,6 +98,13 @@ if (
</a>
</li>
<?php } ?>
<?php if (auth()->user()->inGroup('admin') || auth()->user()->inGroup('beta')) { ?>
<li class="menu-item">
<a href="<?= route_to('variablesIndex') ?>" class="menu-link">
<?= lang("App.menu_variables") ?>
</a>
</li>
<?php } ?>
</ul>
</li>
<?php } ?>

View File

@ -15,6 +15,7 @@
"codeigniter4/shield": "^1.0",
"dompdf/dompdf": "^2.0",
"firebase/php-jwt": "^6.10",
"hermawan/codeigniter4-datatables": "^0.7.2",
"nicolab/php-ftp-client": "^2.0",
"phpseclib/phpseclib": "~3.0"
},

104
ci4/composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "07ccee0168bf5671a274f48a2ba42e77",
"content-hash": "c0e2ec73d12ca7372057585d362765f7",
"packages": [
{
"name": "codeigniter4/framework",
@ -334,6 +334,108 @@
},
"time": "2024-05-18T18:05:11+00:00"
},
{
"name": "greenlion/php-sql-parser",
"version": "v4.6.0",
"source": {
"type": "git",
"url": "https://github.com/greenlion/PHP-SQL-Parser.git",
"reference": "f0e4645eb1612f0a295e3d35bda4c7740ae8c366"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/greenlion/PHP-SQL-Parser/zipball/f0e4645eb1612f0a295e3d35bda4c7740ae8c366",
"reference": "f0e4645eb1612f0a295e3d35bda4c7740ae8c366",
"shasum": ""
},
"require": {
"php": ">=5.3.2"
},
"require-dev": {
"analog/analog": "^1.0.6",
"phpunit/phpunit": "^9.5.13",
"squizlabs/php_codesniffer": "^1.5.1"
},
"type": "library",
"autoload": {
"psr-0": {
"PHPSQLParser\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Justin Swanhart",
"email": "greenlion@gmail.com",
"homepage": "http://code.google.com/u/greenlion@gmail.com/",
"role": "Owner"
},
{
"name": "André Rothe",
"email": "phosco@gmx.de",
"homepage": "https://www.phosco.info",
"role": "Committer"
}
],
"description": "A pure PHP SQL (non validating) parser w/ focus on MySQL dialect of SQL",
"homepage": "https://github.com/greenlion/PHP-SQL-Parser",
"keywords": [
"creator",
"mysql",
"parser",
"sql"
],
"support": {
"issues": "https://github.com/greenlion/PHP-SQL-Parser/issues",
"source": "https://github.com/greenlion/PHP-SQL-Parser"
},
"time": "2023-03-09T20:54:23+00:00"
},
{
"name": "hermawan/codeigniter4-datatables",
"version": "v0.7.2",
"source": {
"type": "git",
"url": "https://github.com/hermawanramadhan/CodeIgniter4-DataTables.git",
"reference": "54057bf0facc171f4be0c490a257dfa46eb7e0d9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/hermawanramadhan/CodeIgniter4-DataTables/zipball/54057bf0facc171f4be0c490a257dfa46eb7e0d9",
"reference": "54057bf0facc171f4be0c490a257dfa46eb7e0d9",
"shasum": ""
},
"require": {
"codeigniter4/framework": "^4",
"greenlion/php-sql-parser": ">=4.5",
"php": ">=7.3"
},
"type": "library",
"autoload": {
"psr-4": {
"Hermawan\\DataTables\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Hermawan Ramadhan",
"email": "hermawanramadhan@gmail.com"
}
],
"description": "Serverside Datatables library for CodeIgniter4",
"support": {
"issues": "https://github.com/hermawanramadhan/CodeIgniter4-DataTables/issues",
"source": "https://github.com/hermawanramadhan/CodeIgniter4-DataTables/tree/v0.7.2"
},
"time": "2024-04-27T07:44:11+00:00"
},
{
"name": "laminas/laminas-escaper",
"version": "2.13.0",

View File

@ -0,0 +1,118 @@
import Modal from "./modal.js";
import Ajax from "./ajax.js";
class ConfigVariableDatatable
{
constructor(domItem)
{
this.domItem = domItem
this.datatableItem = this.domItem
this.modalItem = $("#modalConfigVariableForm")
this.modalEdit = new Modal(this.modalItem)
this.tableActionEdit = this.domItem.find(".btn-variable-edit")
this.tableActionDelete = this.domItem.find(".btn-variable-delete")
this.formEdit = this.modalItem.find("#formEditConfigVariable")
}
init(){
this.datatable = this.datatableItem.DataTable({
processing: true,
dom: 'Brtip',
serverSide: true,
language: {
url: "/themes/vuexy/vendor/libs/datatables-sk/plugins/i18n/es-ES.json"
},
columns : [
{data : 'name',searchable:true,sortable:false},
{data : 'value',searchable:true,sortable:false},
{data : 'description',searchable:true,sortable:false},
{data : 'action',sortable:false,searchable:false,
render : (d,t) =>{
return `
<div class="btn-group btn-group-sm">
<a href="javascript:void(0)" data-id="${d}" class="edit-variable"><i class="ti ti-pencil ti-sm mx-2"></i></a>
</div>
`
}
},
],
ajax: '/configuracion/variables/datatable'
});
}
events()
{
this.modalItem.on("click",".btn-update-variable",this.handleUpdateVariable.bind(this))
this.datatableItem.on("click",".edit-variable",(e)=> {
e.preventDefault()
this.variableId = $(e.currentTarget).data("id")
this.handleGetVariable()
})
}
handleGetVariable()
{
const url = `/configuracion/variables/find/${this.variableId}`
let ajax = new Ajax(
url,null,null,
this.handleGetVariableSuccess.bind(this),
this.handleGetVariableError.bind(this)
)
ajax.get()
}
handleGetVariableSuccess(data){
this.formEdit[0].reset()
this.modalEdit.toggle()
this.nameInput = this.formEdit
.find("#name")
this.nameInput.val(data.name)
this.valueInput = this.formEdit
.find("#value")
this.valueInput.val(data.value)
this.descriptionInput = this.formEdit
.find("#description")
this.descriptionInput.val(data.description)
}
handleGetVariableError(err){}
handleUpdateVariable()
{
const url = `/configuracion/variables/edit/${this.variableId}`
const data = {
value : this.valueInput.val(),
description : this.descriptionInput.val(),
}
let ajax = new Ajax(
url,
data,
null,
this.handleUpdateVariableSucess.bind(this),
this.handleUpdateVariableError.bind(this)
)
ajax.post()
}
handleUpdateVariableSucess(data){
this.modalEdit.toggle()
this.datatable.ajax.reload()
}
handleUpdateVariableError(err){}
handleDeleteVariable()
{
const url = `/configuracion/variables/delete/${this.variableId}`
let ajax = new Ajax(
url,null,null,
this.handleDeleteVariableSucess.bind(this),
this.handleDeleteVariableError.bind(this)
)
ajax.post()
}
handleDeleteVariableSucess(data){
this.datatable.reload()
}
handleDeleteVariableError(err){}
}
export default ConfigVariableDatatable;

View File

@ -0,0 +1,14 @@
class Modal{
constructor(domItem){
this.item = domItem
}
toggle(){
this.item.modal('toggle');
}
show(){
this.item.modal('show');
}
}
export default Modal;

View File

@ -0,0 +1,5 @@
import ConfigVariableDatatable from "../../components/configVariableDatatable.js";
const item = new ConfigVariableDatatable($("#tableConfigVariables"))
item.init()
item.events()