diff --git a/.vscode/sftp.json b/.vscode/sftp.json new file mode 100644 index 00000000..a4adf0e7 --- /dev/null +++ b/.vscode/sftp.json @@ -0,0 +1,12 @@ +{ + "name": "sk-jjo", + "host": "sk-jjo.imnavajas.es", + "protocol": "ftp", + "port": 21, + "username": "sk-jjo", + "password": "yuh1C^290", + "remotePath": "/", + "uploadOnSave": true, + "useTempFile": false, + "openSsh": false +} diff --git a/ci4/.env b/ci4/.env index c3da1f5a..f5a58fed 100644 --- a/ci4/.env +++ b/ci4/.env @@ -22,7 +22,8 @@ CI_ENVIRONMENT = development # APP #-------------------------------------------------------------------- -app.baseURL = 'https://sk-imn.imnavajas.es' +# app.baseURL = 'https://sk-imn.imnavajas.es' +app.baseURL = 'https://sk-jjo.imnavajas.es' # app.forceGlobalSecureRequests = false # app.sessionDriver = 'CodeIgniter\Session\Handlers\FileHandler' @@ -40,13 +41,21 @@ app.baseURL = 'https://sk-imn.imnavajas.es' #-------------------------------------------------------------------- database.default.hostname = localhost -database.default.database = sk_imn -database.default.username = sk_imn -database.default.password = Uyia19_87 +database.default.database = sk_jjo +database.default.username = sk_jjo +database.default.password = 61tv&G1Zf^XY database.default.DBDriver = MySQLi database.default.DBPrefix = database.default.dump = +# database.default.hostname = localhost +# database.default.database = sk_imn +# database.default.username = sk_imn +# database.default.password = Uyia19_87 +# database.default.DBDriver = MySQLi +# database.default.DBPrefix = +# database.default.dump = + # database.tests.hostname = localhost # database.tests.database = ci4 # database.tests.username = root diff --git a/ci4/app/Config/App.php b/ci4/app/Config/App.php index ac64b6bf..ede38fc8 100644 --- a/ci4/app/Config/App.php +++ b/ci4/app/Config/App.php @@ -462,4 +462,5 @@ class App extends BaseConfig * @var bool */ public $CSPEnabled = false; + } diff --git a/ci4/app/Config/Basics.php b/ci4/app/Config/Basics.php new file mode 100644 index 00000000..e7686d06 --- /dev/null +++ b/ci4/app/Config/Basics.php @@ -0,0 +1,91 @@ + 'English', + 'es' => 'Spanish', + ]; + + + public $languageFlags = [ + 'en' => 'us', + 'es' => 'es', + ]; + + + public $authImplemented = false; + + + + + public $theme = [ + 'name' => 'vuexy', + 'body-sm' => false, + 'navbar' => [ + 'bg' => 'gray', + 'type' => 'dark', + 'border' => true, + 'user' => [ + 'visible' => true, + 'shadow' => 0, + ], + ], + 'sidebar' => [ + 'type' => 'dark', + 'shadow' => 4, + 'border' => false, + 'compact' => true, + 'links' => [ + 'bg' => 'black', // only works with AdminLTE theme + 'shadow' => 1, + ], + 'brand' => [ + 'bg' => 'gray-dark', + 'logo' => [ + 'icon' => 'favicon.ico', // path to image | this example icon on public root folder. + 'text' => 'sk_test', + 'shadow' => 2, + ], + ], + 'user' => [ + 'visible' => true, + 'shadow' => 2, + ], + ], + 'footer' => [ + 'fixed' => false, + 'organization' => 'Your Awesome Company', + 'orglink' => 'https://www.ozar.net/', + ], + ]; + +} diff --git a/ci4/app/Config/Routes.php b/ci4/app/Config/Routes.php index b7722b94..d62e2352 100644 --- a/ci4/app/Config/Routes.php +++ b/ci4/app/Config/Routes.php @@ -45,19 +45,19 @@ $routes->group('', [], function($routes) { $routes->post('allmenuitems', 'Paises::allItemsSelect', ['as' => 'select2ItemsOfPaises']); $routes->post('menuitems', 'Paises::menuItems', ['as' => 'menuItemsOfPaises']); }); - + $routes->group('tarifaacabado', ['namespace' => 'App\Controllers\Tarifas'], function ($routes) { $routes->get('', 'Tarifaacabado::index', ['as' => 'tarifaacabadoList']); - $routes->get('index', 'Tarifaacabado::index', ['as' => 'tarifaacabadoIndex']); - $routes->get('list', 'Tarifaacabado::index', ['as' => 'tarifaacabadoList2']); $routes->get('add', 'Tarifaacabado::add', ['as' => 'newTarifaacabado']); $routes->post('add', 'Tarifaacabado::add', ['as' => 'createTarifaacabado']); - $routes->get('edit/(:num)', 'Tarifaacabado::edit/$1', ['as' => 'editTarifaacabado']); - $routes->post('edit/(:num)', 'Tarifaacabado::edit/$1', ['as' => 'updateTarifaacabado']); - $routes->get('delete/(:num)', 'Tarifaacabado::delete/$1', ['as' => 'deleteTarifaacabado']); + $routes->post('create', 'Tarifaacabado::create', ['as' => 'ajaxCreateTarifaacabado']); + $routes->put('(:num)/update', 'Tarifaacabado::update/$1', ['as' => 'ajaxUpdateTarifaacabado']); + $routes->post('(:num)/edit', 'Tarifaacabado::edit/$1', ['as' => 'updateTarifaacabado']); + $routes->post('datatable', 'Tarifaacabado::datatable', ['as' => 'dataTableOfTarifasacabado']); $routes->post('allmenuitems', 'Tarifaacabado::allItemsSelect', ['as' => 'select2ItemsOfTarifasacabado']); $routes->post('menuitems', 'Tarifaacabado::menuItems', ['as' => 'menuItemsOfTarifasacabado']); }); + $routes->resource('tarifaacabado', ['namespace' => 'App\Controllers\Tarifas', 'controller' => 'Tarifaacabado', 'except' => 'show,new,create,update']); $routes->group('users', ['namespace' => 'App\Controllers\Usuarios'], function ($routes) { $routes->get('', 'Users::index', ['as' => 'userList']); @@ -80,7 +80,7 @@ $routes->group('', [], function($routes) { $routes->get('delete/(:num)', 'Group::delete/$1', ['as' => 'deleteGroup']); $routes->get('add', 'Group::add', ['as' => 'newGroup']); }); - $routes->resource('group', ['namespace' => 'App\Controllers\Usuarios', 'controller' => 'UserGroups', 'except' => 'show,new,create,update']); + diff --git a/ci4/app/Controllers/GoBaseResourceController.php b/ci4/app/Controllers/GoBaseResourceController.php new file mode 100644 index 00000000..538428d4 --- /dev/null +++ b/ci4/app/Controllers/GoBaseResourceController.php @@ -0,0 +1,327 @@ +session = \Config\Services::session(); + + if ((!isset($this->viewData['pageTitle']) || empty($this->viewData['pageTitle'])) && isset(static::$pluralObjectName) && !empty(static::$pluralObjectName)) { + $this->viewData['pageTitle'] = ucfirst(static::$pluralObjectName); + } + + if ($this->usePageSubTitle) { + $this->pageSubTitle = config('Basics')->appName; + $this->viewData['pageSubTitle'] = ' ' . $this->pageSubTitle; + } + $this->viewData['errorMessage'] = $this->session->getFlashdata('errorMessage'); + $this->viewData['successMessage'] = $this->session->getFlashdata('successMessage'); + + if (isset(static::$controllerSlug) && empty(static::$controllerSlug)) { + $reflect = new \ReflectionClass($this); + $className = $reflect->getShortName(); + $this->viewData['currentModule'] = slugify(convertToSnakeCase(str_replace('Controller', '', $className))); + + } else { + $this->viewData['currentModule'] = strtolower(static::$controllerSlug); + } + + $this->viewData['usingSweetAlert'] = true; + + $this->viewData['viewPath'] = static::$viewPath; + + $this->viewData['currentLocale'] = $this->request->getLocale(); + } + + /** + * Convenience method to display the form of a module + * @param $forMethod + * @param null $objId + * @return string + */ + protected function displayForm($forMethod, $objId = null) + { + + helper('form'); + $this->viewData['usingSelect2'] = true; + + $validation = \Config\Services::validation(); + + $action = str_replace(static::class . '::', '', $forMethod); + $actionSuffix = ' '; + $formActionSuffix = ''; + + if ($action === 'add') { + $actionSuffix = empty(static::$singularObjectName) || stripos(static::$singularObjectName, 'new') === false ? ' a New ' : ' '; + } elseif ($action === 'edit' && $objId != null) { + $formActionSuffix = $objId . '/'; + } + + if (!isset($this->viewData['action'])) { + $this->viewData['action'] = $action; + } + + if (!isset($this->viewData['formAction'])) { + $this->viewData['formAction'] = base_url(strtolower($this->viewData['currentModule']) . '/' . $formActionSuffix . '/' . $action ); + } + + if ((!isset($this->viewData['boxTitle']) || empty($this->viewData['boxTitle'])) && isset(static::$singularObjectName) && !empty(static::$singularObjectName)) { + $this->viewData['boxTitle'] = ucfirst($action) . $actionSuffix . ucfirst(static::$singularObjectName); + } + + $this->viewData['validation'] = $validation; + + $viewFilePath = static::$viewPath . 'view' . ucfirst(static::$singularObjectNameCc) . 'Form'; + + return view($viewFilePath, $this->viewData); + } + + protected function redirect2listView($flashDataKey = null, $flashDataValue = null) + { + + if (isset($this->indexRoute) && !empty($this->indexRoute)) { + $uri = base_url(route_to($this->indexRoute)); + } else { + + $reflect = new \ReflectionClass($this); + $className = $reflect->getShortName(); + + $routes = \Config\Services::routes(); + $routesOptions = $routes->getRoutesOptions(); + + if (isset(static::$controllerSlug) && !empty(static::$controllerSlug)) { + + if (isset($routesOptions[static::$controllerSlug])) { + $namedRoute = $routesOptions[static::$controllerSlug]['as']; + $uri = route_to($namedRoute); + } else { + $getHandlingRoutes = $routes->getRoutes('get'); + + $indexMethod = array_search('\\App\\Controllers\\' . $className . '::index', $getHandlingRoutes); + if ($indexMethod) { + $uri = route_to('App\\Controllers\\' . $className . '::index'); + } else { + $uri = base_url(static::$controllerSlug); + } + } + } else { + $uri = base_url($className); + } + } + + if ($flashDataKey != null && $flashDataValue != null) { + return redirect()->to($uri)->with($flashDataKey, $flashDataValue); + } else { + return redirect()->to($uri); + } + } + + /** + * Delete the designated resource object from the model. + * + * @param int $id + * + * @return array an array + */ + public function delete($id = null) + { + if (!empty(static::$pluralObjectNameCc) && !empty(static::$singularObjectNameCc)) { + $objName = mb_strtolower(lang(ucfirst(static::$pluralObjectNameCc).'.'.static::$singularObjectNameCc)); + } else { + $objName = lang('Basic.global.record'); + } + + if (!$this->model->delete($id)) { + return $this->failNotFound(lang('Basic.global.deleteError', [$objName])); + } + + $message = lang('Basic.global.deleteSuccess', [$objName]); + $response = $this->respondDeleted(['id' => $id, 'msg' => $message]); + return $response; + } + + + /** + * Convenience method to validate form submission + * @return bool + */ + protected function canValidate() + { + + $validationRules = $this->model->validationRules ?? $this->formValidationRules ?? null; + + if ($validationRules == null) { + return true; + } + + $validationErrorMessages = $this->model->validationMessages ?? $this->formValidationErrorMessagess ?? null;; + + if ($validationErrorMessages != null) { + $valid = $this->validate($validationRules, $validationErrorMessages); + } else { + $valid = $this->validate($validationRules); + } + + $this->validationErrors = $valid ? '' : $this->validator->getErrors(); + + /* + // As of version 1.1.5 of CodeIgniter Wizard, the following is replaced by custom validation errors template supported by CodeIgniter 4 + // If you are not using Bootstrap templates, however, you might want to uncomment this block... + $validation = \Config\Services::validation(); + $this->validation = $validation; + if (!$valid) { + $this->viewData['errorMessage'] .= $validation->listErrors(); + } + */ + return $valid; + } + + /** + * Method for post(ed) input sanitization. Override this when you have custom transformation needs, etc. + * @param array|null $postData + * @return array + */ + protected function sanitized(array $postData = null, bool $nullIfEmpty = false) { + if ($postData == null) { + $postData = $this->request->getPost(); + } + $sanitizedData = []; + foreach ($postData as $k => $v) { + if ($k == csrf_token()) { + continue; + } + $sanitizationResult = goSanitize($v, $nullIfEmpty); + $sanitizedData[$k] = $sanitizationResult[0]; + } + return $sanitizedData; + } + + /** + * Custom fail method needed when CSRF token regeneration is on in security settings + * @param string|array $messages + * @param int $status + * @param string|null $code + * @param string $customMessage + * @return mixed + */ + protected function failWithNewToken($messages, int $status = 400, string $code = null, string $customMessage = '') { + + if (! is_array($messages)) + { + $messages = ['error' => $messages]; + } + $response = [ + 'status' => $status, + 'error' => $status, + 'messages' => $messages, + csrf_token() => csrf_hash() + ]; + + return $this->respond($response, $status); + } + + /** + * Used when a specified resource cannot be found and send back a new CSRF token. + * + * @param string $description + * @param string $code + * @param string $message + * + * @return mixed + */ + public function failNotFoundWithNewToken(string $description = 'Not Found', string $code = null, string $message = '') + { + return $this->failWithNewToken($description, $this->codes['resource_not_found'], $code, $message); + } + + /** + * Convenience method for common exception handling + * @param \Exception $e + */ + protected function dealWithException(\Exception $e) { + // using another try / catch block to prevent to avoid CodeIgniter bug throwing trivial exceptions for querying DB errors + try { + $query = $this->model->db->getLastQuery(); + $queryStr = !is_null($query) ? $query->getQuery() : ''; + $dbError = $this->model->db->error(); + $userFriendlyErrMsg = lang('Basic.global.persistErr1', [static::$singularObjectNameCc]); + if (isset($dbError['code']) && $dbError['code'] == 1062) : + $userFriendlyErrMsg .= PHP_EOL.lang('Basic.global.persistDuplErr', [static::$singularObjectNameCc]); + endif; + // $userFriendlyErrMsg = str_replace("'", "\'", $userFriendlyErrMsg); // Uncomment if experiencing unescaped single quote errors + log_message('error', $userFriendlyErrMsg.PHP_EOL.$e->getMessage().PHP_EOL.$queryStr); + if (isset($dbError['message']) && !empty($dbError['message'])) : + log_message('error', $dbError['code'].' : '.$dbError['message']); + endif; + $this->viewData['errorMessage'] = $userFriendlyErrMsg; + } catch (\Exception $e2) { + log_message('debug', 'You can probably safely ignore this: In attempt to check DB errors, CodeIgniter threw: '.PHP_EOL.$e2->getMessage()); + } + } +} \ No newline at end of file diff --git a/ci4/app/Controllers/Tarifas/Tarifaacabado.php b/ci4/app/Controllers/Tarifas/Tarifaacabado.php index 302d2f91..1bf43192 100644 --- a/ci4/app/Controllers/Tarifas/Tarifaacabado.php +++ b/ci4/app/Controllers/Tarifas/Tarifaacabado.php @@ -1,21 +1,27 @@ -viewData['pageTitle'] = lang('Tarifaacabado.moduleTitle'); - self::$viewPath = getenv('theme.path').'form/tarifas/acabado/'; - - + $this->viewData['usingSweetAlert'] = true; parent::initController($request, $response, $logger); - } + public function index() { + + helper('general'); - $this->viewData['usingClientSideDataTable'] = true; - - $this->viewData['pageSubTitle'] = lang('Basic.global.ManageAllRecords', [lang('Tarifaacabado.tarifaacabado')]); - - parent::index(); - + $viewData = [ + 'currentModule' => static::$controllerSlug, + 'pageSubTitle' => lang('Basic.global.ManageAllRecords', [lang('Tarifaacabado.tarifaacabado')]), + 'tarifaacabado_' => new TarifaacabadoEntity(), + 'usingServerSideDataTable' => true, + + ]; + + $viewData = array_merge($this->viewData, $viewData); // merge any possible values from the parent controller class + + return view(static::$viewPath.'viewTarifaacabadoList', $viewData); } + public function add() { @@ -51,12 +63,13 @@ class Tarifaacabado extends GoBaseController { $nullIfEmpty = true; // !(phpversion() >= '8.1'); $postData = $this->request->getPost(); + $sanitizedData = $this->sanitized($postData, $nullIfEmpty); $noException = true; - if ($successfulResult = $this->canValidate()) : // if ($successfulResult = $this->validate($this->formValidationRules) ) : - + $successfulResult = false; // for now + if ($this->canValidate()) : try { @@ -71,34 +84,34 @@ class Tarifaacabado extends GoBaseController { endif; $thenRedirect = true; // Change this to false if you want your user to stay on the form after submission - endif; + if ($noException && $successfulResult) : $id = $this->model->db->insertID(); $message = lang('Basic.global.saveSuccess', [mb_strtolower(lang('Tarifaacabado.tarifaacabado'))]).'.'; - $message .= anchor(route_to('editTarifaacabado', $id), lang('Basic.global.continueEditing').'?'); + $message .= anchor( "admin/tarifaacabado/{$id}/edit" , lang('Basic.global.continueEditing').'?'); $message = ucfirst(str_replace("'", "\'", $message)); if ($thenRedirect) : if (!empty($this->indexRoute)) : - return redirect()->to(route_to($this->indexRoute))->with('successMessage', $message); + return redirect()->to(route_to( $this->indexRoute ) )->with('sweet-success', $message); else: - return $this->redirect2listView('successMessage', $message); + return $this->redirect2listView('sweet-success', $message); endif; else: - $this->viewData['successMessage'] = $message; + $this->session->setFlashData('sweet-success', $message); endif; endif; // $noException && $successfulResult endif; // ($requestMethod === 'post') - $this->viewData['tarifaacabado_'] = isset($sanitizedData) ? new Tarifaacabado($sanitizedData) : new Tarifaacabado(); + $this->viewData['tarifaacabado_'] = isset($sanitizedData) ? new TarifaacabadoEntity($sanitizedData) : new TarifaacabadoEntity(); $this->viewData['formAction'] = route_to('createTarifaacabado'); - $this->viewData['boxTitle'] = lang('Basic.global.addNew').' '.lang('Tarifaacabado.tarifaacabado').' '.lang('Basic.global.addNewSuffix'); + $this->viewData['boxTitle'] = lang('Basic.global.addNew').' '.lang('Tarifaacabado.moduleTitle').' '.lang('Basic.global.addNewSuffix'); return $this->displayForm(__METHOD__); @@ -114,7 +127,7 @@ class Tarifaacabado extends GoBaseController { if ($tarifaacabado_ == false) : $message = lang('Basic.global.notFoundWithIdErr', [mb_strtolower(lang('Tarifaacabado.tarifaacabado')), $id]); - return $this->redirect2listView('errorMessage', $message); + return $this->redirect2listView('sweet-error', $message); endif; $requestMethod = $this->request->getMethod(); @@ -124,12 +137,13 @@ class Tarifaacabado extends GoBaseController { $nullIfEmpty = true; // !(phpversion() >= '8.1'); $postData = $this->request->getPost(); + $sanitizedData = $this->sanitized($postData, $nullIfEmpty); $noException = true; - if ($successfulResult = $this->canValidate()) : // if ($successfulResult = $this->validate($this->formValidationRules) ) : + $successfulResult = false; // for now @@ -149,21 +163,21 @@ class Tarifaacabado extends GoBaseController { $tarifaacabado_->fill($sanitizedData); $thenRedirect = true; - endif; + if ($noException && $successfulResult) : $id = $tarifaacabado_->id ?? $id; $message = lang('Basic.global.updateSuccess', [mb_strtolower(lang('Tarifaacabado.tarifaacabado'))]).'.'; - $message .= anchor(route_to('editTarifaacabado', $id), lang('Basic.global.continueEditing').'?'); + $message .= anchor( "admin/tarifaacabado/{$id}/edit" , lang('Basic.global.continueEditing').'?'); $message = ucfirst(str_replace("'", "\'", $message)); if ($thenRedirect) : if (!empty($this->indexRoute)) : - return redirect()->to(route_to($this->indexRoute))->with('successMessage', $message); + return redirect()->to(route_to( $this->indexRoute ) )->with('sweet-success', $message); else: - return $this->redirect2listView('successMessage', $message); + return $this->redirect2listView('sweet-success', $message); endif; else: - $this->viewData['successMessage'] = $message; + $this->session->setFlashData('sweet-success', $message); endif; endif; // $noException && $successfulResult @@ -171,15 +185,46 @@ class Tarifaacabado extends GoBaseController { $this->viewData['tarifaacabado_'] = $tarifaacabado_; - $this->viewData['formAction'] = route_to('updateTarifaacabado', $id); + $this->viewData['formAction'] = route_to('updateTarifaacabado', $id); - $this->viewData['boxTitle'] = lang('Basic.global.edit2').' '.lang('Tarifaacabado.tarifaacabado').' '.lang('Basic.global.edit3'); + $this->viewData['boxTitle'] = lang('Basic.global.edit2').' '.lang('Tarifaacabado.moduleTitle').' '.lang('Basic.global.edit3'); return $this->displayForm(__METHOD__, $id); } // end function edit(...) - + + + public function datatable() { + if ($this->request->isAJAX()) { + $reqData = $this->request->getPost(); + if (!isset($reqData['draw']) || !isset($reqData['columns']) ) { + $errstr = 'No data available in response to this specific request.'; + $response = $this->respond(Collection::datatable( [], 0, 0, $errstr ), 400, $errstr); + return $response; + } + $start = $reqData['start'] ?? 0; + $length = $reqData['length'] ?? 5; + $search = $reqData['search']['value']; + $requestedOrder = $reqData['order']['0']['column'] ?? 1; + $order = TarifaacabadoModel::SORTABLE[$requestedOrder > 0 ? $requestedOrder : 1]; + $dir = $reqData['order']['0']['dir'] ?? 'asc'; + + $resourceData = $this->model->getResource($search)->orderBy($order, $dir)->limit($length, $start)->get()->getResultObject(); + foreach ($resourceData as $item) : +if (isset($item->formula_price) && strlen($item->formula_price) > 100) : + $item->formula_price = character_limiter($item->formula_price, 100); +endif; + endforeach; + return $this->respond(Collection::datatable( + $resourceData, + $this->model->getResource()->countAllResults(), + $this->model->getResource($search)->countAllResults() + )); + } else { + return $this->failUnauthorized('Invalid request', 403); + } + } public function allItemsSelect() { if ($this->request->isAJAX()) { @@ -202,7 +247,7 @@ class Tarifaacabado extends GoBaseController { return $this->failUnauthorized('Invalid request', 403); } } - + public function menuItems() { if ($this->request->isAJAX()) { $searchStr = goSanitize($this->request->getPost('searchTerm'))[0]; @@ -228,5 +273,5 @@ class Tarifaacabado extends GoBaseController { return $this->failUnauthorized('Invalid request', 403); } } - + } diff --git a/ci4/app/Controllers/Usuarios/Group.php b/ci4/app/Controllers/Usuarios/Group.php index f0cec4a9..9e049f35 100644 --- a/ci4/app/Controllers/Usuarios/Group.php +++ b/ci4/app/Controllers/Usuarios/Group.php @@ -39,37 +39,65 @@ class Group extends \App\Controllers\GoBaseController public function add() { - helper('form'); + $requestMethod = $this->request->getMethod(); - $data['title'] = [ - 'module' => lang("App.group_add_title"), - 'page' => lang("App.group_add_subtitle"), - 'icon' => 'far fa-plus-square' - ]; + if ($requestMethod === 'post') : - $data['breadcrumb'] = [ - ['title' => lang("App.menu_dashboard"), 'route' => "/home", 'active' => false], - ['title' => lang("App.group_title"), 'route' => "/usuarios/group", 'active' => false], - ['title' => lang("App.group_add_title"), 'route' => "", 'active' => true] - ]; + $nullIfEmpty = true; // !(phpversion() >= '8.1'); - $data['btn_return'] = [ - 'title' => lang("App.global_come_back"), - 'route' => 'usuarios/group', - 'class' => 'btn btn-dark mr-1', - 'icon' => 'fas fa-angle-left' - ]; + $postData = $this->request->getPost(); + + $sanitizedData = $this->sanitized($postData, $nullIfEmpty); - $data['btn_submit'] = [ - 'title' => lang("App.global_save"), - 'route' => '', - 'class' => 'btn btn-primary mr-1', - 'icon' => 'fas fa-save' - ]; - echo view(getenv('theme.path').'main/header'); - echo view(getenv('theme.path').'form/group/form',$data); - echo view(getenv('theme.path').'main/footer'); + $noException = true; + if ($successfulResult = $this->canValidate()) : // if ($successfulResult = $this->validate($this->formValidationRules) ) : + + + if ($this->canValidate()) : + try { + $successfulResult = $this->model->skipValidation(true)->save($sanitizedData); + } catch (\Exception $e) { + $noException = false; + $this->dealWithException($e); + } + else: + $this->viewData['errorMessage'] = lang('Basic.global.formErr1', [mb_strtolower(lang('Group.userGroup'))]); + $this->session->setFlashdata('formErrors', $this->model->errors()); + endif; + + $thenRedirect = true; // Change this to false if you want your user to stay on the form after submission + endif; + if ($noException && $successfulResult) : + + $id = $this->model->db->insertID(); + + $message = lang('Basic.global.saveSuccess', [mb_strtolower(lang('Group.userGroup'))]).'.'; + $message .= anchor( "admin/user-groups/{$id}/edit" , lang('Basic.global.continueEditing').'?'); + $message = ucfirst(str_replace("'", "\'", $message)); + + if ($thenRedirect) : + if (!empty($this->indexRoute)) : + return redirect()->to(route_to( $this->indexRoute ) )->with('sweet-success', $message); + else: + return $this->redirect2listView('sweet-success', $message); + endif; + else: + $this->viewData['successMessage'] = $message; + endif; + + endif; // $noException && $successfulResult + + endif; // ($requestMethod === 'post') + + $this->viewData['group'] = isset($sanitizedData) ? new UserGroupModel($sanitizedData) : new UserGroupModel(); + + $this->viewData['formAction'] = route_to('createUserGroup'); + + $this->viewData['boxTitle'] = lang('Basic.global.addNew').' '.lang('Group.moduleTitle').' '.lang('Basic.global.addNewSuffix'); + + + return $this->displayForm(__METHOD__); } //public function edit($id) diff --git a/ci4/app/Entities/Tarifas/TarifaacabadoEntity.php b/ci4/app/Entities/Tarifas/TarifaacabadoEntity.php index bb217f9b..b4b85a2e 100644 --- a/ci4/app/Entities/Tarifas/TarifaacabadoEntity.php +++ b/ci4/app/Entities/Tarifas/TarifaacabadoEntity.php @@ -1,5 +1,5 @@ +endSection() ?> + +section('additionalInlineJs') ?> + + + + $('#select_all').on('click', function () { + $(':checkbox').each(function() { + this.checked = true; + }); + }); + $('#remove_all').on('click', function () { + $(':checkbox').each(function() { + this.checked = false; + }); + }); + + endSection() ?> \ No newline at end of file diff --git a/ci4/app/Views/themes/backend/vuexy/form/tarifas/acabado/viewTarifaacabadoForm.php b/ci4/app/Views/themes/backend/vuexy/form/tarifas/acabado/viewTarifaacabadoForm.php index 86812937..1aba3ba5 100644 --- a/ci4/app/Views/themes/backend/vuexy/form/tarifas/acabado/viewTarifaacabadoForm.php +++ b/ci4/app/Views/themes/backend/vuexy/form/tarifas/acabado/viewTarifaacabadoForm.php @@ -15,7 +15,7 @@ diff --git a/ci4/app/Views/themes/backend/vuexy/form/tarifas/acabado/viewTarifaacabadoList.php b/ci4/app/Views/themes/backend/vuexy/form/tarifas/acabado/viewTarifaacabadoList.php index fed2ada9..03f73bfa 100644 --- a/ci4/app/Views/themes/backend/vuexy/form/tarifas/acabado/viewTarifaacabadoList.php +++ b/ci4/app/Views/themes/backend/vuexy/form/tarifas/acabado/viewTarifaacabadoList.php @@ -1,6 +1,6 @@ include('themes/_commonPartialsBs/datatables') ?> +include('themes/_commonPartialsBs/sweetalert') ?> extend('themes/backend/vuexy/main/defaultlayout') ?> - section('content'); ?>
@@ -8,15 +8,15 @@

- 'btn btn-primary float-end']); ?>
- +
- + + @@ -26,68 +26,176 @@ - - - - - - - - - - - - - - - - - - -
- id ?> - - nombre) || strlen($item->nombre) < 51 ? esc($item->nombre) : character_limiter(esc($item->nombre), 50) ?> - - tirada_min) ?> - - precio_min) ?> - - tirada_max) ?> - - precio_max) ?> - - ajuste) ?> - - formula_price) || strlen($item->formula_price) < 51 ? esc($item->formula_price) : character_limiter(esc($item->formula_price), 50) ?> - - user_created_id) ?> - - user_update_id) ?> - - deleted_at) ? '' : date('d/m/Y H:m:s', strtotime($item->deleted_at)) ?> - - created_at) ? '' : date('d/m/Y H:m:s', strtotime($item->created_at)) ?> - - updated_at) ? '' : date('d/m/Y H:m:s', strtotime($item->updated_at)) ?> - - id), lang('Basic.global.edit'), ['class'=>'btn btn-sm btn-warning btn-edit me-1', 'data-id'=>$item->id,]); ?> - 'btn btn-sm btn-danger btn-delete ms-1', 'data-href'=>route_to('deleteTarifaacabado', $item->id), 'data-bs-toggle'=>'modal', 'data-bs-target'=>'#confirm2delete']); ?> -
-endSection() ?> \ No newline at end of file +endSection() ?> + + +section('additionalInlineJs') ?> + + const lastColNr = $('#tableOfTarifasacabado').find("tr:first th").length - 1; + const actionBtns = function(data) { + return ` +
+ + +
+ `; + }; + theTable = $('#tableOfTarifasacabado').DataTable({ + processing: true, + serverSide: true, + autoWidth: true, + responsive: true, + scrollX: true, + lengthMenu: [ 5, 10, 25, 50, 75, 100, 250, 500, 1000, 2500 ], + pageLength: 10, + lengthChange: true, + "dom": 'lfrtipB', // 'lfBrtip', // you can try different layout combinations by uncommenting one or the other + // "dom": '<"top"lf><"clear">rt<"bottom"ipB><"clear">', // remember to comment this line if you uncomment the above + "buttons": [ + 'copy', 'csv', 'excel', 'print', { + extend: 'pdfHtml5', + orientation: 'landscape', + pageSize: 'A4' + } + ], + stateSave: true, + order: [[1, 'asc']], + language: { + //url: "/assets/dt/languages[$currentLocale] ?? config('Basics')->i18n ?>.json" + }, + ajax : $.fn.dataTable.pipeline( { + url: '', + method: 'POST', + headers: {'X-Requested-With': 'XMLHttpRequest'}, + async: true, + }), + columnDefs: [ + { + orderable: false, + searchable: false, + targets: [0,lastColNr] + } + ], + columns : [ + { 'data': actionBtns }, + { 'data': 'id' }, + { 'data': 'nombre' }, + { 'data': 'tirada_min' }, + { 'data': 'precio_min' }, + { 'data': 'tirada_max' }, + { 'data': 'precio_max' }, + { 'data': 'ajuste' }, + { 'data': 'formula_price' }, + { 'data': 'user_created_id' }, + { 'data': 'user_update_id' }, + { 'data': 'created_at' }, + { 'data': 'updated_at' }, + { 'data': actionBtns } + ] + }); + + + theTable.on( 'draw.dt', function () { + + const dateCols = [11, 12]; + const shortDateFormat = ''; + const dateTimeFormat = ''; + + for (let coln of dateCols) { + theTable.column(coln, { page: 'current' }).nodes().each( function (cell, i) { + const datestr = cell.innerHTML; + const dateStrLen = datestr.toString().trim().length; + if (dateStrLen > 0) { + let dateTimeParts= datestr.split(/[- :]/); // regular expression split that creates array with: year, month, day, hour, minutes, seconds values + dateTimeParts[1]--; // monthIndex begins with 0 for January and ends with 11 for December so we need to decrement by one + const d = new Date(...dateTimeParts); // new Date(datestr); + const md = moment(d); + const usingThisFormat = dateStrLen > 11 ? dateTimeFormat : shortDateFormat; + const formattedDateStr = md.format(usingThisFormat); + cell.innerHTML = formattedDateStr; + } + }); + } + }); + +$(document).on('click', '.btn-edit', function(e) { + window.location.href = `/${$(this).attr('data-id')}/edit`; + }); + +$(document).on('click', '.btn-delete', function(e) { + Swal.fire({ + title: '', + text: '', + icon: 'warning', + showCancelButton: true, + confirmButtonColor: '#3085d6', + confirmButtonText: '', + cancelButtonText: '', + cancelButtonColor: '#d33' + }) + .then((result) => { + const dataId = $(this).data('id'); + const row = $(this).closest('tr'); + if (result.value) { + $.ajax({ + url: `/${dataId}`, + method: 'DELETE', + }).done((data, textStatus, jqXHR) => { + Toast.fire({ + icon: 'success', + title: data.msg ?? jqXHR.statusText, + }); + + theTable.clearPipeline(); + theTable.row($(row)).invalidate().draw(); + }).fail((jqXHR, textStatus, errorThrown) => { + Toast.fire({ + icon: 'error', + title: jqXHR.responseJSON.messages.error, + }); + }) + } + }); + }); + + + + +endSection() ?> + + +section('css') ?> + +endSection() ?> + + +section('additionalExternalJs') ?> + + + + + + + + + + +endSection() ?> + diff --git a/ci4/app/Views/themes/backend/vuexy/form/user/_userFormItems.php b/ci4/app/Views/themes/backend/vuexy/form/user/_userFormItems.php index 3551a01e..3c102b53 100644 --- a/ci4/app/Views/themes/backend/vuexy/form/user/_userFormItems.php +++ b/ci4/app/Views/themes/backend/vuexy/form/user/_userFormItems.php @@ -70,7 +70,7 @@
- =1): ?> diff --git a/ci4/app/Views/themes/backend/vuexy/main/defaultlayout.php b/ci4/app/Views/themes/backend/vuexy/main/defaultlayout.php index e79c4059..321282d1 100644 --- a/ci4/app/Views/themes/backend/vuexy/main/defaultlayout.php +++ b/ci4/app/Views/themes/backend/vuexy/main/defaultlayout.php @@ -24,6 +24,7 @@ if (!empty($token) && $tfa == false) { data-template="vertical-menu-template-no-customizer" > + + @@ -90,6 +92,7 @@ if (!empty($token) && $tfa == false) { + @@ -511,61 +514,61 @@ if (!empty($token) && $tfa == false) { +