From 719f2d73147bd8808639e575107b41ecb48401c8 Mon Sep 17 00:00:00 2001 From: Paolo Date: Tue, 17 Dec 2019 13:35:41 +0100 Subject: [PATCH 001/216] - Changed controller system/FAS_UDF, less busy now - Method execReadOnlyQuery of DB_Model less strict check against SQL statements - Added new public method setup to DB_Model to setup the model after initialization - Added new constants to UDFLib - Added new private method _printEndUDFBlock and _printEndUDFBlock to UDFLib - Added new public methods setUDFUniqueId, getSession, getSessionElement, setSession, setSessionElement, saveUDFs and isAllowed to UDFLib - Removed model system/FAS_UDF_model - View views/system/fas_udf now uses the view templates/FHC-Header - Added new parameter udfs to view templates/FHC-Header - Added new properties to UDFWidget - Added new private methods _initUDFWidget, _checkParameters and _startUDFWidget to UDFWidget --- application/controllers/system/FAS_UDF.php | 82 +--- application/controllers/widgets/UDF.php | 102 +++++ application/core/DB_Model.php | 20 +- application/libraries/UDFLib.php | 385 +++++++++++++----- application/models/system/FAS_UDF_model.php | 169 -------- application/views/system/fas_udf.php | 100 ++--- application/views/templates/FHC-Header.php | 4 + application/widgets/udf/DropdownWidgetUDF.php | 24 +- application/widgets/udf/UDFWidget.php | 151 ++++++- public/js/UDFWidget.js | 100 +++++ 10 files changed, 686 insertions(+), 451 deletions(-) create mode 100644 application/controllers/widgets/UDF.php delete mode 100644 application/models/system/FAS_UDF_model.php create mode 100644 public/js/UDFWidget.js diff --git a/application/controllers/system/FAS_UDF.php b/application/controllers/system/FAS_UDF.php index cd78d64d2..7f39543c7 100644 --- a/application/controllers/system/FAS_UDF.php +++ b/application/controllers/system/FAS_UDF.php @@ -24,43 +24,15 @@ class FAS_UDF extends Auth_Controller */ public function index() { - $fasUdfSession = getSession(self::FAS_UDF_SESSION_NAME); - $person_id = $this->input->get('person_id'); - if (isset($fasUdfSession['person_id'])) - { - if (!isset($person_id)) - { - $person_id = $fasUdfSession['person_id']; - } - unset($fasUdfSession['person_id']); - } - $prestudent_id = $this->input->get('prestudent_id'); - if (isset($fasUdfSession['prestudent_id'])) - { - if (!isset($prestudent_id)) - { - $prestudent_id = $fasUdfSession['prestudent_id']; - } - unset($fasUdfSession['prestudent_id']); - } - - $result = null; - if (isset($fasUdfSession['result'])) - { - $result = clone $fasUdfSession['result']; - setSessionElement(self::FAS_UDF_SESSION_NAME, 'result', null); - } - - $data = array('result' => $result); if (isset($person_id) && is_numeric($person_id)) { if ($this->PersonModel->hasUDF()) { $personUdfs = $this->PersonModel->getUDFs($person_id); - $personUdfs['person_id'] = $person_id; + $data['person_id'] = $person_id; $data['personUdfs'] = $personUdfs; } } @@ -70,61 +42,11 @@ class FAS_UDF extends Auth_Controller if ($this->PrestudentModel->hasUDF()) { $prestudentUdfs = $this->PrestudentModel->getUDFs($prestudent_id); - $prestudentUdfs['prestudent_id'] = $prestudent_id; + $data['prestudent_id'] = $prestudent_id; $data['prestudentUdfs'] = $prestudentUdfs; } } $this->load->view('system/fas_udf', $data); } - - /** - * - */ - public function saveUDF() - { - $udfs = $this->input->post(); - $validation = $this->_validate($udfs); - - $userdata = array( - 'person_id' => $this->input->post('person_id'), - 'prestudent_id' => $this->input->post('prestudent_id') - ); - - if (isSuccess($validation)) - { - // Load model UDF_model - $this->load->model('system/FAS_UDF_model', 'FASUDFModel'); - - $result = $this->FASUDFModel->saveUDFs($udfs); - - $userdata['result'] = $result; - } - else - { - $userdata['result'] = $validation; - } - - setSessionElement(self::FAS_UDF_SESSION_NAME, 'person_id', $userdata['person_id']); - setSessionElement(self::FAS_UDF_SESSION_NAME, 'prestudent_id', $userdata['prestudent_id']); - setSessionElement(self::FAS_UDF_SESSION_NAME, 'result', $userdata['result']); - - redirect('system/FAS_UDF'); - } - - /** - * - */ - private function _validate($udfs) - { - $validation = error('person_id or prestudent_id is missing'); - - if((isset($udfs['person_id']) && !(is_null($udfs['person_id'])) && ($udfs['person_id'] != '')) - || (isset($udfs['prestudent_id']) && !(is_null($udfs['prestudent_id'])) && ($udfs['prestudent_id'] != ''))) - { - $validation = success(true); - } - - return $validation; - } } diff --git a/application/controllers/widgets/UDF.php b/application/controllers/widgets/UDF.php new file mode 100644 index 000000000..c71eba73a --- /dev/null +++ b/application/controllers/widgets/UDF.php @@ -0,0 +1,102 @@ +load->library('AuthLib'); + + // Loads the UDFLib with HTTP GET/POST parameters + $this->_loadUDFLib(); + + // Checks if the caller is allow to read this data + $this->_isAllowed(); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * Retrieves data about the current filter from the session and will be written on the output in JSON format + */ + public function saveUDFs() + { + $udfUniqueId = $this->input->post(self::UDF_UNIQUE_ID); + $udfs = $this->input->post(UDFLib::UDFS_ARG_NAME); + + if (!isEmptyString($udfs)) + { + $jsonDecodedUDF = json_decode($udfs); + if ($jsonDecodedUDF != null) + { + $this->outputJson($this->udflib->saveUDFs($udfUniqueId, $jsonDecodedUDF)); + } + else + { + $this->outputJsonError('No valid JSON format for UDF values'); + } + } + else + { + $this->outputJsonError('UDFUniqueId, schema, table name, primary key name and primary key value are mandatory paramenters'); + } + } + + //------------------------------------------------------------------------------------------------------------------ + // Private methods + + /** + * Checks if the user is allowed to use this filter + */ + private function _isAllowed() + { + if (!$this->udflib->isAllowed()) + { + $this->terminateWithJsonError('You are not allowed to access to this content'); + } + } + + /** + * Loads the tablewidgetlib with the UDF_UNIQUE_ID parameter + * If the parameter UDF_UNIQUE_ID is not given then the execution of the controller is terminated and + * an error message is printed + */ + private function _loadUDFLib() + { + // If the parameter UDF_UNIQUE_ID is present in the HTTP GET or POST + if (isset($_GET[self::UDF_UNIQUE_ID]) || isset($_POST[self::UDF_UNIQUE_ID])) + { + // If it is present in the HTTP GET + if (isset($_GET[self::UDF_UNIQUE_ID])) + { + $udfUniqueId = $this->input->get(self::UDF_UNIQUE_ID); // is retrieved from the HTTP GET + } + elseif (isset($_POST[self::UDF_UNIQUE_ID])) // Else if it is present in the HTTP POST + { + $udfUniqueId = $this->input->post(self::UDF_UNIQUE_ID); // is retrieved from the HTTP POST + } + + // Loads the tablewidgetlib that contains all the used logic + $this->load->library('UDFLib'); + + $this->udflib->setUDFUniqueId($udfUniqueId); + } + else // Otherwise an error will be written in the output + { + $this->terminateWithJsonError('Parameter "'.self::UDF_UNIQUE_ID.'" not provided!'); + } + } +} diff --git a/application/core/DB_Model.php b/application/core/DB_Model.php index ca760c662..667ff00ca 100644 --- a/application/core/DB_Model.php +++ b/application/core/DB_Model.php @@ -60,6 +60,20 @@ class DB_Model extends CI_Model // ------------------------------------------------------------------------------------------ // Public methods + /** + * This method provides a way to setup a database model without declaring one + */ + public function setup($schema, $table, $primaryKey, $hasSequence = true) + { + // + if (!isEmptyString($schema) && !isEmptyString($table) && !isEmptyString($primaryKey) && is_bool($hasSequence)) + { + $this->dbTable = $schema.'.'.$table; + $this->pk = $primaryKey; + $this->hasSequence = $hasSequence; + } + } + /** * Insert Data into DB-Table * @@ -690,7 +704,7 @@ class DB_Model extends CI_Model */ public function hasUDF() { - if($this->fieldExists(UDFLib::COLUMN_NAME)) + if ($this->fieldExists(UDFLib::COLUMN_NAME)) { $resultUDFsDefinitions = $this->UDFModel->getUDFsDefinitions($this->dbTable); if (hasData($resultUDFsDefinitions)) @@ -727,8 +741,8 @@ class DB_Model extends CI_Model $cleanedQuery = trim(preg_replace('/\t|\n|\r|;/', '', $query)); // // - if (stripos($cleanedQuery, 'SELECT') == 0 - && (stripos($cleanedQuery, 'INSERT') > 0 || stripos($cleanedQuery, 'INSERT') == false) + if ( + (stripos($cleanedQuery, 'INSERT') > 0 || stripos($cleanedQuery, 'INSERT') == false) && (stripos($cleanedQuery, 'UPDATE') > 0 || stripos($cleanedQuery, 'UPDATE') == false) && (stripos($cleanedQuery, 'CREATE') > 0 || stripos($cleanedQuery, 'CREATE') == false) && (stripos($cleanedQuery, 'DELETE') > 0 || stripos($cleanedQuery, 'DELETE') == false) diff --git a/application/libraries/UDFLib.php b/application/libraries/UDFLib.php index 6166b44a9..edd11fd99 100644 --- a/application/libraries/UDFLib.php +++ b/application/libraries/UDFLib.php @@ -7,6 +7,10 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); */ class UDFLib { + const UDF_UNIQUE_ID = 'udfUniqueId'; + + const SESSION_NAME = 'FHC_UDF_WIDGET'; + const WIDGET_NAME = 'UDFWidget'; const SCHEMA_ARG_NAME = 'schema'; const TABLE_ARG_NAME = 'table'; @@ -22,6 +26,16 @@ class UDFLib const FE_REGEX_LANGUAGE = 'js'; // UDF javascript regex language attribute (front end) const BE_REGEX_LANGUAGE = 'php'; // UDF php regex language attribute (back end) + // ...to specify permissions that are needed to use this TableWidget + const REQUIRED_PERMISSIONS_PARAMETER = 'requiredPermissions'; + + // ... + const PRIMARY_KEY_NAME = 'primaryKeyName'; + const PRIMARY_KEY_VALUE = 'primaryKeyValue'; + + const PERMISSION_TABLE_METHOD = 'UDFWidget'; // Name for fake method to be checked by the PermissionLib + const PERMISSION_TYPE = 'rw'; + // HTML components const LABEL = 'title'; const TITLE = 'description'; @@ -47,6 +61,8 @@ class UDFLib private $_ci; // Code igniter instance + private $_udfUniqueId; // + /** * Loads fhc helper */ @@ -63,8 +79,8 @@ class UDFLib */ public function UDFWidget($args, $htmlArgs = array()) { - if ((isset($args[UDFLib::SCHEMA_ARG_NAME]) && !isEmptyString($args[UDFLib::SCHEMA_ARG_NAME])) - && (isset($args[UDFLib::TABLE_ARG_NAME]) && !isEmptyString($args[UDFLib::TABLE_ARG_NAME]))) + if ((isset($args[self::SCHEMA_ARG_NAME]) && !isEmptyString($args[self::SCHEMA_ARG_NAME])) + && (isset($args[self::TABLE_ARG_NAME]) && !isEmptyString($args[self::TABLE_ARG_NAME]))) { // Loads the widget library $this->_ci->load->library('WidgetLib'); @@ -73,26 +89,26 @@ class UDFLib loadResource(APPPATH.'widgets/udf'); // Default external block is true - if (!isset($args[UDFLib::FIELD_ARG_NAME]) && !isset($htmlArgs[HTMLWidget::EXTERNAL_BLOCK])) + if (!isset($args[self::FIELD_ARG_NAME]) && !isset($htmlArgs[HTMLWidget::EXTERNAL_BLOCK])) { $htmlArgs[HTMLWidget::EXTERNAL_BLOCK] = true; } return $this->_ci->widgetlib->widget( - UDFLib::WIDGET_NAME, + self::WIDGET_NAME, $args, $htmlArgs ); } else { - if (!isset($args[UDFLib::SCHEMA_ARG_NAME]) || isEmptyString($args[UDFLib::SCHEMA_ARG_NAME])) + if (!isset($args[self::SCHEMA_ARG_NAME]) || isEmptyString($args[self::SCHEMA_ARG_NAME])) { - show_error(UDFLib::SCHEMA_ARG_NAME.' parameter is missing!'); + show_error(self::SCHEMA_ARG_NAME.' parameter is missing!'); } - if (!isset($args[UDFLib::TABLE_ARG_NAME]) || isEmptyString($args[UDFLib::TABLE_ARG_NAME])) + if (!isset($args[self::TABLE_ARG_NAME]) || isEmptyString($args[self::TABLE_ARG_NAME])) { - show_error(UDFLib::TABLE_ARG_NAME.' parameter is missing!'); + show_error(self::TABLE_ARG_NAME.' parameter is missing!'); } } } @@ -105,12 +121,12 @@ class UDFLib */ public function displayUDFWidget(&$widgetData) { - $schema = $widgetData[UDFLib::SCHEMA_ARG_NAME]; // schema attribute - $table = $widgetData[UDFLib::TABLE_ARG_NAME]; // table attribute + $schema = $widgetData[self::SCHEMA_ARG_NAME]; // schema attribute + $table = $widgetData[self::TABLE_ARG_NAME]; // table attribute - if (isset($widgetData[UDFLib::FIELD_ARG_NAME])) + if (isset($widgetData[self::FIELD_ARG_NAME])) { - $field = $widgetData[UDFLib::FIELD_ARG_NAME]; // UDF name + $field = $widgetData[self::FIELD_ARG_NAME]; // UDF name } $udfResults = $this->_loadUDF($schema, $table); // loads UDF definition @@ -122,6 +138,9 @@ class UDFLib $jsonSchemas = json_decode($udf->jsons); // decode the json schema if (is_object($jsonSchemas) || is_array($jsonSchemas)) { + // + $this->_printStartUDFBlock($widgetData); + // If the schema is an object then convert it into an array if (is_object($jsonSchemas)) { @@ -140,18 +159,18 @@ class UDFLib foreach ($jsonSchemasArray as $jsonSchema) { // If the type property is not present then show an error - if (!isset($jsonSchema->{UDFLib::TYPE})) + if (!isset($jsonSchema->{self::TYPE})) { show_error(sprintf('%s.%s: Attribute "type" not present in the json schema', $schema, $table)); } // If the name property is not present then show an error - if (!isset($jsonSchema->{UDFLib::NAME})) + if (!isset($jsonSchema->{self::NAME})) { show_error(sprintf('%s.%s: Attribute "name" not present in the json schema', $schema, $table)); } // If a UDF is specified and is present in the json schemas list or no UDF is specified - if ((isset($field) && $field == $jsonSchema->{UDFLib::NAME}) || !isset($field)) + if ((isset($field) && $field == $jsonSchema->{self::NAME}) || !isset($field)) { // Set attributes using phrases $this->_setAttributesWithPhrases($jsonSchema, $widgetData[HTMLWidget::HTML_ARG_NAME]); @@ -166,7 +185,7 @@ class UDFLib $this->_render($jsonSchema, $widgetData); // If a UDf is specified and it was found then stop looking through this list - if (isset($field) && $field == $jsonSchema->{UDFLib::NAME}) + if (isset($field) && $field == $jsonSchema->{self::NAME}) { $found = true; break; @@ -179,6 +198,9 @@ class UDFLib { show_error(sprintf('%s.%s: No schema present for field: %s', $schema, $table, $field)); } + + // + $this->_printEndUDFBlock(); } else // not a valid schema { @@ -218,7 +240,7 @@ class UDFLib // Decodes json that define the UDFs for this table $decodedUDFDefinitions = json_decode( - $resultUDFsDefinitions->retval[0]->{UDFLib::COLUMN_JSON_DESCRIPTION} + $resultUDFsDefinitions->retval[0]->{self::COLUMN_JSON_DESCRIPTION} ); // Loops through the UDFs definitions @@ -232,28 +254,28 @@ class UDFLib $tmpValidate = success(true); // temporary variable used to store the returned value from _validateUDFs // If this is the definition of this UDF - if ($decodedUDFDefinition->{UDFLib::NAME} == $key) + if ($decodedUDFDefinition->{self::NAME} == $key) { - if (isset($decodedUDFDefinition->{UDFLib::VALIDATION})) // If validation rules are present for this UDF + if (isset($decodedUDFDefinition->{self::VALIDATION})) // If validation rules are present for this UDF { // Checks if the given UDF is required and the result will be stored in $chkRequiredPassed // If $chkRequiredPassed == true => required check passed // If $chkRequiredPassed == false => required check NOT passed $chkRequiredPassed = true; // If required property is present in the UDF description and it is true - if (isset($decodedUDFDefinition->{UDFLib::VALIDATION}->{UDFLib::REQUIRED}) - && $decodedUDFDefinition->{UDFLib::VALIDATION}->{UDFLib::REQUIRED} === true) + if (isset($decodedUDFDefinition->{self::VALIDATION}->{self::REQUIRED}) + && $decodedUDFDefinition->{self::VALIDATION}->{self::REQUIRED} === true) { // If this UDF is a checkbox and the given value is false // OR - // if this UDF is NOT a checkbox and the given value is null - if (($decodedUDFDefinition->{UDFLib::TYPE} == UDFLib::CHKBOX_TYPE && $val === false) - || ($decodedUDFDefinition->{UDFLib::TYPE} != UDFLib::CHKBOX_TYPE && $val == null)) + // if this UD7F is NOT a checkbox and the given value is null + if (($decodedUDFDefinition->{self::TYPE} == self::CHKBOX_TYPE && $val === false) + || ($decodedUDFDefinition->{self::TYPE} != self::CHKBOX_TYPE && $val == null)) { $chkRequiredPassed = false; // not passed // A new error is generated and added to array $requiredUDFsArray - $requiredUDFsArray[$decodedUDFDefinition->{UDFLib::NAME}] = error( - $decodedUDFDefinition->{UDFLib::NAME}, + $requiredUDFsArray[$decodedUDFDefinition->{self::NAME}] = error( + $decodedUDFDefinition->{self::NAME}, EXIT_VALIDATION_UDF_REQUIRED ); } @@ -267,22 +289,22 @@ class UDFLib // If $toBeValidated == false => validation is NOT performed $toBeValidated = false; // If this UDF is NOT a checkbox - if ($decodedUDFDefinition->{UDFLib::TYPE} != UDFLib::CHKBOX_TYPE) + if ($decodedUDFDefinition->{self::TYPE} != self::CHKBOX_TYPE) { // If required property is NOT present in the UDF description - if (!isset($decodedUDFDefinition->{UDFLib::VALIDATION}->{UDFLib::REQUIRED})) + if (!isset($decodedUDFDefinition->{self::VALIDATION}->{self::REQUIRED})) { $toBeValidated = true; } // If required property is present in the UDF description and it is true - if (isset($decodedUDFDefinition->{UDFLib::VALIDATION}->{UDFLib::REQUIRED}) - && $decodedUDFDefinition->{UDFLib::VALIDATION}->{UDFLib::REQUIRED} === true) + if (isset($decodedUDFDefinition->{self::VALIDATION}->{self::REQUIRED}) + && $decodedUDFDefinition->{self::VALIDATION}->{self::REQUIRED} === true) { $toBeValidated = true; } // If required property is present in the UDF description and it is true and the given value is null - if (isset($decodedUDFDefinition->{UDFLib::VALIDATION}->{UDFLib::REQUIRED}) - && $decodedUDFDefinition->{UDFLib::VALIDATION}->{UDFLib::REQUIRED} === false + if (isset($decodedUDFDefinition->{self::VALIDATION}->{self::REQUIRED}) + && $decodedUDFDefinition->{self::VALIDATION}->{self::REQUIRED} === false && $val != null) { $toBeValidated = true; @@ -292,8 +314,8 @@ class UDFLib if ($toBeValidated === true) // Checks if validation should be performed { $tmpValidate = $this->_validateUDFs( - $decodedUDFDefinition->{UDFLib::VALIDATION}, - $decodedUDFDefinition->{UDFLib::NAME}, + $decodedUDFDefinition->{self::VALIDATION}, + $decodedUDFDefinition->{self::NAME}, $val ); } @@ -341,7 +363,7 @@ class UDFLib if ($encodedToBeStoredUDFs !== false) // if encode was ok { // Save the supplied UDFs values - $data[UDFLib::COLUMN_NAME] = $encodedToBeStoredUDFs; + $data[self::COLUMN_NAME] = $encodedToBeStoredUDFs; } } else // otherwise the returning value will be the list of UDFs validation errors @@ -360,8 +382,8 @@ class UDFLib { $isUDFColumn = false; - if (substr($columnName, 0, strlen(UDFLib::COLUMN_PREFIX)) == UDFLib::COLUMN_PREFIX - && $columnType == UDFLib::COLUMN_TYPE) + if (substr($columnName, 0, strlen(self::COLUMN_PREFIX)) == self::COLUMN_PREFIX + && $columnType == self::COLUMN_TYPE) { $isUDFColumn = true; } @@ -369,9 +391,148 @@ class UDFLib return $isUDFColumn; } + /** + * Set the _udfUniqueId property + */ + public function setUDFUniqueId($udfUniqueId) + { + $this->_udfUniqueId = $udfUniqueId; + } + + /** + * Return an unique string that identify this filter widget + * NOTE: The default value is the URI where the FilterWidget is called + * If the fhc_controller_id is present then is also used + */ + public function setUDFUniqueIdByParams($params) + { + if ($params != null + && is_array($params) + && isset($params[self::UDF_UNIQUE_ID]) + && !isEmptyString($params[self::UDF_UNIQUE_ID])) + { + $udfUniqueId = $this->_ci->router->directory.$this->_ci->router->class.'/'. + $this->_ci->router->method.'/'. + $params[self::UDF_UNIQUE_ID]; + + $this->setUDFUniqueId($udfUniqueId); + } + } + + /** + * Wrapper method to the session helper funtions to retrieve the whole session for this filter + */ + public function getSession() + { + return getSessionElement(self::SESSION_NAME, $this->_udfUniqueId); + } + + /** + * Wrapper method to the session helper funtions to retrieve one element from the session of this filter + */ + public function getSessionElement($name) + { + $session = getSessionElement(self::SESSION_NAME, $this->_udfUniqueId); + + if (isset($session[$name])) + { + return $session[$name]; + } + + return null; + } + + /** + * Wrapper method to the session helper funtions to set the whole session for this filter + */ + public function setSession($data) + { + setSessionElement(self::SESSION_NAME, $this->_udfUniqueId, $data); + } + + /** + * Wrapper method to the session helper funtions to set one element in the session for this filter + */ + public function setSessionElement($name, $value) + { + $session = getSessionElement(self::SESSION_NAME, $this->_udfUniqueId); + + $session[$name] = $value; + + setSessionElement(self::SESSION_NAME, $this->_udfUniqueId, $session); // stores the single value + } + + /** + * Save UDFs + */ + public function saveUDFs($udfUniqueId, $udfs) + { + // Read the all session for this udf widget + $session = $this->getSession(); + + if ($session == null) return error('No UDFWidget loaded'); + + // Workaround + $this->_ci->load->model('system/UDF_model', 'UDFModel'); + + // + $dbModel = new DB_Model(); + + $dbModel->setup( + $session[self::SCHEMA_ARG_NAME], // + $session[self::TABLE_ARG_NAME], // + $session[self::PRIMARY_KEY_NAME] // + ); + + return $dbModel->update( + array($session[self::PRIMARY_KEY_NAME] => $session[self::PRIMARY_KEY_VALUE]), + (array)$udfs + ); + } + // ------------------------------------------------------------------------------------------------- // Private methods + /** + * + */ + private function _printStartUDFBlock($widgetData) + { + $startBlock = '
'."\n"; + + echo sprintf( + $startBlock, + self::WIDGET_NAME, + $widgetData[self::UDF_UNIQUE_ID] + ); + } + + /** + * + */ + private function _printEndUDFBlock() + { + echo '
'."\n"; + } + + /** + * Checks if at least one of the permissions given as parameter (requiredPermissions) belongs + * to the authenticated user, if confirmed then is allowed to use this FilterWidget. + * If the parameter requiredPermissions is NOT given or is not present in the session, + * then NO one is allow to use this FilterWidget + * Wrapper method to permissionlib->hasAtLeastOne + */ + public function isAllowed($requiredPermissions = null) + { + $this->_ci->load->library('PermissionLib'); // Load permission library + + // Gets the required permissions from the session if they are not provided as parameter + $rq = $requiredPermissions; + if ($rq == null) $rq = $this->getSessionElement(self::REQUIRED_PERMISSIONS_PARAMETER); + + return $this->_ci->permissionlib->hasAtLeastOne($rq, self::PERMISSION_TABLE_METHOD, self::PERMISSION_TYPE); + } + /** * Move UDFs from $data to $UDFs */ @@ -381,7 +542,7 @@ class UDFLib foreach ($data as $key => $val) { - if (substr($key, 0, 4) == UDFLib::COLUMN_PREFIX) + if (substr($key, 0, 4) == self::COLUMN_PREFIX) { $udfsParameters[$key] = $val; // stores UDF value into property UDFs unset($data[$key]); // remove from data @@ -416,8 +577,8 @@ class UDFLib { // If min value attribute is present in the validation for this UDF, // then checks if the value of this UDF is compliant to this attribute - if (isset($decodedUDFValidation->{UDFLib::MIN_VALUE}) - && $udfVal < $decodedUDFValidation->{UDFLib::MIN_VALUE}) + if (isset($decodedUDFValidation->{self::MIN_VALUE}) + && $udfVal < $decodedUDFValidation->{self::MIN_VALUE}) { // validation is failed and the error is stored in $returnArrayValidation $returnArrayValidation[] = error($udfName, EXIT_VALIDATION_UDF_MIN_VALUE); @@ -425,8 +586,8 @@ class UDFLib // If max value attribute is present in the validation for this UDF, // then checks if the value of this UDF is compliant to this attribute - if (isset($decodedUDFValidation->{UDFLib::MAX_VALUE}) - && $udfVal > $decodedUDFValidation->{UDFLib::MAX_VALUE}) + if (isset($decodedUDFValidation->{self::MAX_VALUE}) + && $udfVal > $decodedUDFValidation->{self::MAX_VALUE}) { // validation is failed and the error is stored in $returnArrayValidation $returnArrayValidation[] = error($udfName, EXIT_VALIDATION_UDF_MAX_VALUE); @@ -436,8 +597,8 @@ class UDFLib $strUdfVal = strval($udfVal); // store in $strUdfVal the string conversion of $udfVal // If min length attribute is present in the validation for this UDF, // then checks if the value of this UDF is compliant to this attribute - if (isset($decodedUDFValidation->{UDFLib::MIN_LENGTH}) && isset($strUdfVal) - && strlen($strUdfVal) < $decodedUDFValidation->{UDFLib::MIN_LENGTH}) + if (isset($decodedUDFValidation->{self::MIN_LENGTH}) && isset($strUdfVal) + && strlen($strUdfVal) < $decodedUDFValidation->{self::MIN_LENGTH}) { // validation is failed and the error is stored in $returnArrayValidation $returnArrayValidation[] = error($udfName, EXIT_VALIDATION_UDF_MIN_LENGTH); @@ -445,8 +606,8 @@ class UDFLib // If max length attribute is present in the validation for this UDF, // then checks if the value of this UDF is compliant to this attribute - if (isset($decodedUDFValidation->{UDFLib::MAX_LENGTH}) && isset($strUdfVal) - && strlen($strUdfVal) > $decodedUDFValidation->{UDFLib::MAX_LENGTH}) + if (isset($decodedUDFValidation->{self::MAX_LENGTH}) && isset($strUdfVal) + && strlen($strUdfVal) > $decodedUDFValidation->{self::MAX_LENGTH}) { // validation is failed and the error is stored in $returnArrayValidation $returnArrayValidation[] = error($udfName, EXIT_VALIDATION_UDF_MAX_LENGTH); @@ -457,12 +618,12 @@ class UDFLib { // Search for a php regular expression in the validation of this UDF, if one is found // then checks if the value of this UDF is compliant to this attribute - if (isset($decodedUDFValidation->{UDFLib::REGEX}) - && is_array($decodedUDFValidation->{UDFLib::REGEX})) + if (isset($decodedUDFValidation->{self::REGEX}) + && is_array($decodedUDFValidation->{self::REGEX})) { - foreach ($decodedUDFValidation->{UDFLib::REGEX} as $regexIndx => $regex) + foreach ($decodedUDFValidation->{self::REGEX} as $regexIndx => $regex) { - if ($regex->language == UDFLib::BE_REGEX_LANGUAGE) + if ($regex->language == self::BE_REGEX_LANGUAGE) { if (preg_match($regex->expression, $udfVal) != 1) { @@ -494,8 +655,8 @@ class UDFLib */ private function _setNameAndId($jsonSchema, &$htmlParameters) { - $htmlParameters[HTMLWidget::HTML_ID] = $jsonSchema->{UDFLib::NAME}; - $htmlParameters[HTMLWidget::HTML_NAME] = $jsonSchema->{UDFLib::NAME}; + $htmlParameters[HTMLWidget::HTML_ID] = $jsonSchema->{self::NAME}; + $htmlParameters[HTMLWidget::HTML_NAME] = $jsonSchema->{self::NAME}; } /** @@ -504,20 +665,20 @@ class UDFLib private function _sortJsonSchemas(&$jsonSchemasArray) { usort($jsonSchemasArray, function ($a, $b) { - if (!isset($a->{UDFLib::SORT})) + if (!isset($a->{self::SORT})) { - $a->{UDFLib::SORT} = 9999; + $a->{self::SORT} = 9999; } - if (!isset($b->{UDFLib::SORT})) + if (!isset($b->{self::SORT})) { - $b->{UDFLib::SORT} = 9999; + $b->{self::SORT} = 9999; } - if ($a->{UDFLib::SORT} == $b->{UDFLib::SORT}) + if ($a->{self::SORT} == $b->{self::SORT}) { return 0; } - return ($a->{UDFLib::SORT} < $b->{UDFLib::SORT}) ? -1 : 1; + return ($a->{self::SORT} < $b->{self::SORT}) ? -1 : 1; }); } @@ -565,32 +726,32 @@ class UDFLib private function _render($jsonSchema, &$widgetData) { // Checkbox - if ($jsonSchema->{UDFLib::TYPE} == 'checkbox') + if ($jsonSchema->{self::TYPE} == 'checkbox') { $this->_renderCheckbox($jsonSchema, $widgetData); } // Textfield - elseif ($jsonSchema->{UDFLib::TYPE} == 'textfield') + elseif ($jsonSchema->{self::TYPE} == 'textfield') { $this->_renderTextfield($jsonSchema, $widgetData); } // Textarea - elseif ($jsonSchema->{UDFLib::TYPE} == 'textarea') + elseif ($jsonSchema->{self::TYPE} == 'textarea') { $this->_renderTextarea($jsonSchema, $widgetData); } // Date - elseif ($jsonSchema->{UDFLib::TYPE} == 'date') + elseif ($jsonSchema->{self::TYPE} == 'date') { // To be done } // Dropdown - elseif ($jsonSchema->{UDFLib::TYPE} == 'dropdown') + elseif ($jsonSchema->{self::TYPE} == 'dropdown') { $this->_renderDropdown($jsonSchema, $widgetData); } // Multiple dropdown - elseif ($jsonSchema->{UDFLib::TYPE} == 'multipledropdown') + elseif ($jsonSchema->{self::TYPE} == 'multipledropdown') { $this->_renderDropdown($jsonSchema, $widgetData, true); } @@ -602,29 +763,29 @@ class UDFLib private function _renderDropdown($jsonSchema, &$widgetData, $multiple = false) { // Selected element/s - if (isset($widgetData[UDFLib::UDFS_ARG_NAME]) - && isset($widgetData[UDFLib::UDFS_ARG_NAME][$jsonSchema->{UDFLib::NAME}])) + if (isset($widgetData[self::UDFS_ARG_NAME]) + && isset($widgetData[self::UDFS_ARG_NAME][$jsonSchema->{self::NAME}])) { - $widgetData[DropdownWidget::SELECTED_ELEMENT] = $widgetData[UDFLib::UDFS_ARG_NAME][$jsonSchema->{UDFLib::NAME}]; + $widgetData[DropdownWidget::SELECTED_ELEMENT] = $widgetData[self::UDFS_ARG_NAME][$jsonSchema->{self::NAME}]; } else { $widgetData[DropdownWidget::SELECTED_ELEMENT] = null; } - $dropdownWidgetUDF = new DropdownWidgetUDF(UDFLib::WIDGET_NAME, $widgetData); + $dropdownWidgetUDF = new DropdownWidgetUDF(self::WIDGET_NAME, $widgetData); $parameters = array(); // If the list of values to show is an array - if (isset($jsonSchema->{UDFLib::LIST_VALUES}->enum)) + if (isset($jsonSchema->{self::LIST_VALUES}->enum)) { - $parameters = $jsonSchema->{UDFLib::LIST_VALUES}->enum; + $parameters = $jsonSchema->{self::LIST_VALUES}->enum; } // If the list of values to show should be retrieved with a SQL statement - elseif (isset($jsonSchema->{UDFLib::LIST_VALUES}->sql)) + elseif (isset($jsonSchema->{self::LIST_VALUES}->sql)) { // UDFModel is loaded in method _loadUDF that is called before the current method - $queryResult = $this->_ci->UDFModel->execReadOnlyQuery($jsonSchema->{UDFLib::LIST_VALUES}->sql); + $queryResult = $this->_ci->UDFModel->execReadOnlyQuery($jsonSchema->{self::LIST_VALUES}->sql); if (hasData($queryResult)) { $parameters = $queryResult->retval; @@ -645,13 +806,13 @@ class UDFLib private function _renderTextarea($jsonSchema, &$widgetData) { $text = null; // text value - $textareaUDF = new TextareaWidgetUDF(UDFLib::WIDGET_NAME, $widgetData); + $textareaUDF = new TextareaWidgetUDF(self::WIDGET_NAME, $widgetData); // Set text value if present in the DB - if (isset($widgetData[UDFLib::UDFS_ARG_NAME]) - && isset($widgetData[UDFLib::UDFS_ARG_NAME][$jsonSchema->{UDFLib::NAME}])) + if (isset($widgetData[self::UDFS_ARG_NAME]) + && isset($widgetData[self::UDFS_ARG_NAME][$jsonSchema->{self::NAME}])) { - $text = $widgetData[UDFLib::UDFS_ARG_NAME][$jsonSchema->{UDFLib::NAME}]; + $text = $widgetData[self::UDFS_ARG_NAME][$jsonSchema->{self::NAME}]; } $textareaUDF->render($text); @@ -663,13 +824,13 @@ class UDFLib private function _renderTextfield($jsonSchema, &$widgetData) { $text = null; // text value - $textareaUDF = new TextfieldWidgetUDF(UDFLib::WIDGET_NAME, $widgetData); + $textareaUDF = new TextfieldWidgetUDF(self::WIDGET_NAME, $widgetData); // Set text value if present in the DB - if (isset($widgetData[UDFLib::UDFS_ARG_NAME]) - && isset($widgetData[UDFLib::UDFS_ARG_NAME][$jsonSchema->{UDFLib::NAME}])) + if (isset($widgetData[self::UDFS_ARG_NAME]) + && isset($widgetData[self::UDFS_ARG_NAME][$jsonSchema->{self::NAME}])) { - $text = $widgetData[UDFLib::UDFS_ARG_NAME][$jsonSchema->{UDFLib::NAME}]; + $text = $widgetData[self::UDFS_ARG_NAME][$jsonSchema->{self::NAME}]; } $textareaUDF->render($text); @@ -681,17 +842,17 @@ class UDFLib private function _renderCheckbox($jsonSchema, &$widgetData) { // Set checkbox value if present in the DB - if (isset($widgetData[UDFLib::UDFS_ARG_NAME]) - && isset($widgetData[UDFLib::UDFS_ARG_NAME][$jsonSchema->{UDFLib::NAME}])) + if (isset($widgetData[self::UDFS_ARG_NAME]) + && isset($widgetData[self::UDFS_ARG_NAME][$jsonSchema->{self::NAME}])) { - $widgetData[CheckboxWidget::VALUE_FIELD] = $widgetData[UDFLib::UDFS_ARG_NAME][$jsonSchema->{UDFLib::NAME}]; + $widgetData[CheckboxWidget::VALUE_FIELD] = $widgetData[self::UDFS_ARG_NAME][$jsonSchema->{self::NAME}]; } else { $widgetData[CheckboxWidget::VALUE_FIELD] = CheckboxWidget::HTML_DEFAULT_VALUE; } - $checkboxWidgetUDF = new CheckboxWidgetUDF(UDFLib::WIDGET_NAME, $widgetData); + $checkboxWidgetUDF = new CheckboxWidgetUDF(self::WIDGET_NAME, $widgetData); $checkboxWidgetUDF->render(); } @@ -707,21 +868,21 @@ class UDFLib $htmlParameters[HTMLWidget::PLACEHOLDER] = null; // Description, title and placeholder - if (isset($jsonSchema->{UDFLib::LABEL}) - || isset($jsonSchema->{UDFLib::TITLE}) - || isset($jsonSchema->{UDFLib::PLACEHOLDER})) + if (isset($jsonSchema->{self::LABEL}) + || isset($jsonSchema->{self::TITLE}) + || isset($jsonSchema->{self::PLACEHOLDER})) { // Loads phrases library $this->_ci->load->library('PhrasesLib'); // If is set the label property in the json schema - if (isset($jsonSchema->{UDFLib::LABEL})) + if (isset($jsonSchema->{self::LABEL})) { // Load the related phrase $tmpResult = $this->_ci->phraseslib->getPhrases( - UDFLib::PHRASES_APP_NAME, + self::PHRASES_APP_NAME, getUserLanguage(), - $jsonSchema->{UDFLib::LABEL}, + $jsonSchema->{self::LABEL}, null, null, 'no' @@ -733,13 +894,13 @@ class UDFLib } // If is set the title property in the json schema - if (isset($jsonSchema->{UDFLib::TITLE})) + if (isset($jsonSchema->{self::TITLE})) { // Load the related phrase $tmpResult = $this->_ci->phraseslib->getPhrases( - UDFLib::PHRASES_APP_NAME, + self::PHRASES_APP_NAME, getUserLanguage(), - $jsonSchema->{UDFLib::TITLE}, + $jsonSchema->{self::TITLE}, null, null, 'no' @@ -751,13 +912,13 @@ class UDFLib } // If is set the placeholder property in the json schema - if (isset($jsonSchema->{UDFLib::PLACEHOLDER})) + if (isset($jsonSchema->{self::PLACEHOLDER})) { // Load the related phrase $tmpResult = $this->_ci->phraseslib->getPhrases( - UDFLib::PHRASES_APP_NAME, + self::PHRASES_APP_NAME, getUserLanguage(), - $jsonSchema->{UDFLib::PLACEHOLDER}, + $jsonSchema->{self::PLACEHOLDER}, null, null, 'no' @@ -784,17 +945,17 @@ class UDFLib $htmlParameters[HTMLWidget::MAX_LENGTH] = null; // If validation property is present in the json schema - if (isset($jsonSchema->{UDFLib::VALIDATION})) + if (isset($jsonSchema->{self::VALIDATION})) { - $jsonSchemaValidation =& $jsonSchema->{UDFLib::VALIDATION}; // Reference for a better code readability + $jsonSchemaValidation =& $jsonSchema->{self::VALIDATION}; // Reference for a better code readability // Front-end regex - if (isset($jsonSchemaValidation->{UDFLib::REGEX}) - && is_array($jsonSchemaValidation->{UDFLib::REGEX})) + if (isset($jsonSchemaValidation->{self::REGEX}) + && is_array($jsonSchemaValidation->{self::REGEX})) { - foreach ($jsonSchemaValidation->{UDFLib::REGEX} as $regex) + foreach ($jsonSchemaValidation->{self::REGEX} as $regex) { - if ($regex->language === UDFLib::FE_REGEX_LANGUAGE) + if ($regex->language === self::FE_REGEX_LANGUAGE) { $htmlParameters[HTMLWidget::REGEX] = $regex->expression; } @@ -802,33 +963,33 @@ class UDFLib } // Required - if (isset($jsonSchemaValidation->{UDFLib::REQUIRED})) + if (isset($jsonSchemaValidation->{self::REQUIRED})) { - $htmlParameters[HTMLWidget::REQUIRED] = $jsonSchemaValidation->{UDFLib::REQUIRED}; + $htmlParameters[HTMLWidget::REQUIRED] = $jsonSchemaValidation->{self::REQUIRED}; } // Min value - if (isset($jsonSchemaValidation->{UDFLib::MIN_VALUE})) + if (isset($jsonSchemaValidation->{self::MIN_VALUE})) { - $htmlParameters[HTMLWidget::MIN_VALUE] = $jsonSchemaValidation->{UDFLib::MIN_VALUE}; + $htmlParameters[HTMLWidget::MIN_VALUE] = $jsonSchemaValidation->{self::MIN_VALUE}; } // Max value - if (isset($jsonSchemaValidation->{UDFLib::MAX_VALUE})) + if (isset($jsonSchemaValidation->{self::MAX_VALUE})) { - $htmlParameters[HTMLWidget::MAX_VALUE] = $jsonSchemaValidation->{UDFLib::MAX_VALUE}; + $htmlParameters[HTMLWidget::MAX_VALUE] = $jsonSchemaValidation->{self::MAX_VALUE}; } // Min length - if (isset($jsonSchemaValidation->{UDFLib::MIN_LENGTH})) + if (isset($jsonSchemaValidation->{self::MIN_LENGTH})) { - $htmlParameters[HTMLWidget::MIN_LENGTH] = $jsonSchemaValidation->{UDFLib::MIN_LENGTH}; + $htmlParameters[HTMLWidget::MIN_LENGTH] = $jsonSchemaValidation->{self::MIN_LENGTH}; } // Max length - if (isset($jsonSchemaValidation->{UDFLib::MAX_LENGTH})) + if (isset($jsonSchemaValidation->{self::MAX_LENGTH})) { - $htmlParameters[HTMLWidget::MAX_LENGTH] = $jsonSchemaValidation->{UDFLib::MAX_LENGTH}; + $htmlParameters[HTMLWidget::MAX_LENGTH] = $jsonSchemaValidation->{self::MAX_LENGTH}; } } } diff --git a/application/models/system/FAS_UDF_model.php b/application/models/system/FAS_UDF_model.php deleted file mode 100644 index aee49d431..000000000 --- a/application/models/system/FAS_UDF_model.php +++ /dev/null @@ -1,169 +0,0 @@ -load->model('person/Person_model', 'PersonModel'); - - $result = $this->load(array('public', 'tbl_person')); - if (isSuccess($result) && count($result->retval) == 1) - { - $jsons = json_decode($result->retval[0]->jsons); - } - - $udfs = $this->_fillMissingTextUDF($udfs, $jsons); - $udfs = $this->_fillMissingChkboxUDF($udfs, $jsons); - $udfs = $this->_fillMissingDropdownUDF($udfs, $jsons); - - $resultPerson = $this->PersonModel->update($person_id, $udfs); - } - - // - if (isset($prestudent_id)) - { - // Load model Prestudent_model - $this->load->model('crm/Prestudent_model', 'PrestudentModel'); - - $result = $this->load(array('public', 'tbl_prestudent')); - if (isSuccess($result) && count($result->retval) == 1) - { - $jsons = json_decode($result->retval[0]->jsons); - } - - $udfs = $this->_fillMissingTextUDF($udfs, $jsons); - $udfs = $this->_fillMissingChkboxUDF($udfs, $jsons); - $udfs = $this->_fillMissingDropdownUDF($udfs, $jsons); - - $resultPrestudent = $this->PrestudentModel->update($prestudent_id, $udfs); - } - - if (isSuccess($resultPerson) && isSuccess($resultPrestudent)) - { - $result = success(array($resultPerson->retval, $resultPrestudent->retval)); - } - else if(isError($resultPerson)) - { - $result = $resultPerson; - } - else if(isError($resultPrestudent)) - { - $result = $resultPrestudent; - } - - return $result; - } - - /** - * - */ - private function _fillMissingChkboxUDF($udfs, $jsons) - { - $_fillMissingChkboxUDF = $udfs; - - foreach($jsons as $udfDescription) - { - if ($udfDescription->{UDFLib::TYPE} == UDFLib::CHKBOX_TYPE) - { - if (!isset($_fillMissingChkboxUDF[$udfDescription->{UDFLib::NAME}])) - { - $_fillMissingChkboxUDF[$udfDescription->{UDFLib::NAME}] = false; - } - else - { - if ($_fillMissingChkboxUDF[$udfDescription->{UDFLib::NAME}] == UDF_model::STRING_FALSE) - { - $_fillMissingChkboxUDF[$udfDescription->{UDFLib::NAME}] = false; - } - else if ($_fillMissingChkboxUDF[$udfDescription->{UDFLib::NAME}] == UDF_model::STRING_TRUE) - { - $_fillMissingChkboxUDF[$udfDescription->{UDFLib::NAME}] = true; - } - } - } - } - - return $_fillMissingChkboxUDF; - } - - /** - * - */ - private function _fillMissingDropdownUDF($udfs, $jsons) - { - $_fillMissingDropdownUDF = $udfs; - - foreach($jsons as $udfDescription) - { - if ($udfDescription->{UDFLib::TYPE} == UDF_model::UDF_DROPDOWN_TYPE - || $udfDescription->{UDFLib::TYPE} == UDF_model::UDF_MULTIPLEDROPDOWN_TYPE) - { - if (!isset($_fillMissingDropdownUDF[$udfDescription->{UDFLib::NAME}])) - { - $_fillMissingDropdownUDF[$udfDescription->{UDFLib::NAME}] = null; - } - else if($_fillMissingDropdownUDF[$udfDescription->{UDFLib::NAME}] == UDF_model::STRING_NULL) - { - $_fillMissingDropdownUDF[$udfDescription->{UDFLib::NAME}] = null; - } - } - } - - return $_fillMissingDropdownUDF; - } - - /** - * - */ - private function _fillMissingTextUDF($udfs, $jsons) - { - $_fillMissingTextUDF = $udfs; - - foreach($jsons as $udfDescription) - { - if ($udfDescription->{UDFLib::TYPE} == 'textarea' - || $udfDescription->{UDFLib::TYPE} == 'textfield') - { - if (!isset($_fillMissingTextUDF[$udfDescription->{UDFLib::NAME}])) - { - $_fillMissingTextUDF[$udfDescription->{UDFLib::NAME}] = null; - } - else if(trim($_fillMissingTextUDF[$udfDescription->{UDFLib::NAME}]) == '') - { - $_fillMissingTextUDF[$udfDescription->{UDFLib::NAME}] = null; - } - } - } - - return $_fillMissingTextUDF; - } -} diff --git a/application/views/system/fas_udf.php b/application/views/system/fas_udf.php index d4a01b9e9..1ffa4b272 100644 --- a/application/views/system/fas_udf.php +++ b/application/views/system/fas_udf.php @@ -1,54 +1,28 @@ -load->view("templates/header", array("title" => "UDF", "widgetsCSS" => true)); ?> +load->view( + 'templates/FHC-Header', + array( + 'title' => 'InfocenterDetails', + 'jquery' => true, + 'bootstrap' => true, + 'fontawesome' => true, + 'jqueryui' => true, + 'dialoglib' => true, + 'ajaxlib' => true, + 'udfs' => true, + 'sbadmintemplate' => true, + 'customCSSs' => array( + 'public/css/sbadmin2/admintemplate.css' + ), + 'customJSs' => array( + 'public/js/bootstrapper.js' + ) + ) + ); +?> - -
- Saved! -
- -
- -
- Error while saving! -
-
-
-retval; - if(is_array($errors)) - { - foreach ($errors as $error) - { - foreach ($error as $fieldError) - { - echo $fieldError->code . ': ' . $fieldError->retval . '
'; - } - } - } - else - echo $result->retval; -?> -
- -
-
-
- -
-
@@ -69,8 +43,12 @@ udflib->UDFWidget( array( + UDFLib::UDF_UNIQUE_ID => 'fasPersonUDFs', + UDFLib::REQUIRED_PERMISSIONS_PARAMETER => 'basis/person', UDFLib::SCHEMA_ARG_NAME => 'public', UDFLib::TABLE_ARG_NAME => 'tbl_person', + UDFLib::PRIMARY_KEY_NAME => 'person_id', + UDFLib::PRIMARY_KEY_VALUE => $person_id, UDFLib::UDFS_ARG_NAME => $personUdfs ) ); @@ -90,8 +68,12 @@ udflib->UDFWidget( array( + UDFLib::UDF_UNIQUE_ID => 'fasPrestudentUDFs', + UDFLib::REQUIRED_PERMISSIONS_PARAMETER => 'basis/person', UDFLib::SCHEMA_ARG_NAME => 'public', UDFLib::TABLE_ARG_NAME => 'tbl_prestudent', + UDFLib::PRIMARY_KEY_NAME => 'prestudent_id', + UDFLib::PRIMARY_KEY_VALUE => $prestudent_id, UDFLib::UDFS_ARG_NAME => $prestudentUdfs ) ); @@ -120,31 +102,9 @@ -
- -
- - - - - - - - - load->view("templates/footer"); ?> diff --git a/application/views/templates/FHC-Header.php b/application/views/templates/FHC-Header.php index 3c1327d5f..49a77fe17 100644 --- a/application/views/templates/FHC-Header.php +++ b/application/views/templates/FHC-Header.php @@ -33,6 +33,7 @@ $tablewidget = isset($tablewidget) ? $tablewidget : false; $tabulator = isset($tabulator) ? $tabulator : false; $tinymce = isset($tinymce) ? $tinymce : false; + $udfs = isset($udfs) ? $udfs : false; ?> @@ -176,6 +177,9 @@ // Tinymce JS if ($tinymce === true) generateJSsInclude('vendor/tinymce/tinymce/tinymce.min.js'); + // Tinymce JS + if ($udfs === true) generateJSsInclude('public/js/UDFWidget.js'); + // SB Admin 2 template JS if ($sbadmintemplate === true) { diff --git a/application/widgets/udf/DropdownWidgetUDF.php b/application/widgets/udf/DropdownWidgetUDF.php index 04552e953..8a55f71f6 100644 --- a/application/widgets/udf/DropdownWidgetUDF.php +++ b/application/widgets/udf/DropdownWidgetUDF.php @@ -12,7 +12,7 @@ class DropdownWidgetUDF extends DropdownWidget { // Array that will contains the elements to be displayed in the dropdown $tmpNewElements = array(); - + // Loops through the given parameters foreach($parameters as $parameter) { @@ -29,27 +29,27 @@ class DropdownWidgetUDF extends DropdownWidget // If the single element is an array of two element if (is_array($parameter) && count($parameter) == 2) { - $newElement->{DropdownWidget::ID_FIELD} = $parameter[0]; // - $newElement->{DropdownWidget::DESCRIPTION_FIELD} = $parameter[1]; // + $newElement->{DropdownWidget::ID_FIELD} = $parameter[0]; // + $newElement->{DropdownWidget::DESCRIPTION_FIELD} = $parameter[1]; // } // If the single element is a string or a number else if (is_string($parameter) || is_numeric($parameter)) { - $newElement->{DropdownWidget::ID_FIELD} = $parameter; // - $newElement->{DropdownWidget::DESCRIPTION_FIELD} = $parameter; // + $newElement->{DropdownWidget::ID_FIELD} = $parameter; // + $newElement->{DropdownWidget::DESCRIPTION_FIELD} = $parameter; // } // If the single element is an object with two properties: id and description else if (is_object($parameter) && isset($parameter->{DropdownWidget::ID_FIELD}) && isset($parameter->{DropdownWidget::DESCRIPTION_FIELD})) { - $newElement->{DropdownWidget::ID_FIELD} = $parameter->{DropdownWidget::ID_FIELD}; // - $newElement->{DropdownWidget::DESCRIPTION_FIELD} = $parameter->{DropdownWidget::DESCRIPTION_FIELD}; // + $newElement->{DropdownWidget::ID_FIELD} = $parameter->{DropdownWidget::ID_FIELD}; // + $newElement->{DropdownWidget::DESCRIPTION_FIELD} = $parameter->{DropdownWidget::DESCRIPTION_FIELD}; // } - + array_push($tmpNewElements, $newElement); // Add $newElement into $tmpNewElements } } - + // Set the list of elements $this->setElementsArray( success($tmpNewElements), @@ -57,9 +57,9 @@ class DropdownWidgetUDF extends DropdownWidget $this->htmlParameters[HTMLWidget::PLACEHOLDER], 'No data found for this UDF' ); - + $this->loadDropDownView(); - + echo $this->content(); } -} \ No newline at end of file +} diff --git a/application/widgets/udf/UDFWidget.php b/application/widgets/udf/UDFWidget.php index 756df4765..b3bf82470 100644 --- a/application/widgets/udf/UDFWidget.php +++ b/application/widgets/udf/UDFWidget.php @@ -6,14 +6,155 @@ */ class UDFWidget extends HTMLWidget { + private $_requiredPermissions; // + + private $_schema; + private $_table; + private $_primaryKeyName; + private $_primaryKeyValue; + + /** + * Initialize the UDFWidget and starts the execution of the logic + */ + public function __construct($name, $args = array()) + { + parent::__construct($name, $args); // calls the parent's constructor + + $this->load->library('UDFLib'); // Loads the UDFLib that contains all the used logic + + $this->udflib->setUDFUniqueIdByParams($args); + + $this->_initUDFWidget($args); // checks parameters and initialize properties + + // Let's start if it's allowed + // NOTE: If it is NOT allowed then no data are loaded + if ($this->udflib->isAllowed($this->_requiredPermissions)) + { + $this->_startUDFWidget($args[UDFLib::UDF_UNIQUE_ID]); + } + } + /** * Called by the WidgetLib, it renders the HTML of the UDF */ public function display($widgetData) { - // _ci is the instance of Code Igniter and the library UDFLib was previously loaded, - // so now is it possibile to call the method displayUDFWidget of UDFLib - // to render the HTML of this UDF - $this->_ci->udflib->displayUDFWidget($widgetData); + // Let's start if it's allowed + // NOTE: If it is NOT allowed then no data are loaded + if ($this->_ci->udflib->isAllowed($this->_requiredPermissions)) + { + $this->_ci->udflib->displayUDFWidget($widgetData); + } } -} \ No newline at end of file + + //------------------------------------------------------------------------------------------------------------------ + // Private methods + + /** + * Checks parameters and initialize all the properties of this UDFWidget + */ + private function _initUDFWidget($args) + { + $this->_checkParameters($args); + + // If here then everything is ok + + // Initialize class properties + $this->_requiredPermissions = null; + $this->_schema = null; + $this->_table = null; + $this->_primaryKeyName = null; + $this->_primaryKeyValue = null; + + // Retrieved the required permissions parameter if present + if (isset($args[UDFLib::REQUIRED_PERMISSIONS_PARAMETER])) + { + $this->_requiredPermissions = $args[UDFLib::REQUIRED_PERMISSIONS_PARAMETER]; + } + + // Retrieved the + if (isset($args[UDFLib::SCHEMA_ARG_NAME])) + { + $this->_schema = $args[UDFLib::SCHEMA_ARG_NAME]; + } + + // Retrieved the + if (isset($args[UDFLib::TABLE_ARG_NAME])) + { + $this->_table = $args[UDFLib::TABLE_ARG_NAME]; + } + + // Retrieved the + if (isset($args[UDFLib::PRIMARY_KEY_NAME])) + { + $this->_primaryKeyName = $args[UDFLib::PRIMARY_KEY_NAME]; + } + + // Retrieved the + if (isset($args[UDFLib::PRIMARY_KEY_VALUE])) + { + $this->_primaryKeyValue = $args[UDFLib::PRIMARY_KEY_VALUE]; + } + } + + /** + * Checks the required parameters used to call this UDFWidget + */ + private function _checkParameters($args) + { + if (!is_array($args) || (is_array($args) && count($args) == 0)) + { + show_error('Second parameter of the widget call must be a NOT empty associative array'); + } + else + { + if (!isset($args[UDFLib::UDF_UNIQUE_ID])) + { + show_error('The parameter "'.UDFLib::UDF_UNIQUE_ID.'" must be specified'); + } + + if (!isset($args[UDFLib::REQUIRED_PERMISSIONS_PARAMETER])) + { + show_error('The parameter "'.UDFLib::REQUIRED_PERMISSIONS_PARAMETER.'" must be specified'); + } + + if (!isset($args[UDFLib::SCHEMA_ARG_NAME])) + { + show_error('The parameter "'.UDFLib::SCHEMA_ARG_NAME.'" must be specified'); + } + + if (!isset($args[UDFLib::TABLE_ARG_NAME])) + { + show_error('The parameter "'.UDFLib::TABLE_ARG_NAME.'" must be specified'); + } + + if (!isset($args[UDFLib::PRIMARY_KEY_NAME])) + { + show_error('The parameter "'.UDFLib::PRIMARY_KEY_NAME.'" must be specified'); + } + + if (!isset($args[UDFLib::PRIMARY_KEY_VALUE])) + { + show_error('The parameter "'.UDFLib::PRIMARY_KEY_VALUE.'" must be specified'); + } + } + } + + /** + * Contains all the logic used to load all the data needed to the UDFWidget + */ + private function _startUDFWidget($udfUniqueId) + { + // Stores an array that contains all the data useful for + $this->udflib->setSession( + array( + UDFLib::UDF_UNIQUE_ID => $udfUniqueId, // table unique id + UDFLib::REQUIRED_PERMISSIONS_PARAMETER => $this->_requiredPermissions, // + UDFLib::SCHEMA_ARG_NAME => $this->_schema, // + UDFLib::TABLE_ARG_NAME => $this->_table, // + UDFLib::PRIMARY_KEY_NAME => $this->_primaryKeyName, // + UDFLib::PRIMARY_KEY_VALUE => $this->_primaryKeyValue // + ) + ); + } +} diff --git a/public/js/UDFWidget.js b/public/js/UDFWidget.js new file mode 100644 index 000000000..dc04fe0d5 --- /dev/null +++ b/public/js/UDFWidget.js @@ -0,0 +1,100 @@ +/** + * UDFWidget JS magic + */ + +/** + * FHC_UDFWidget this object is used to render the GUI of a table widget and to operate with it + */ +var FHC_UDFWidget = { + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * To display the TableWidget using the loaded data prenset in the session + */ + display: function() { + + $("div[type*='UDFWidget']").each(function(i, udfWidgetDiv) { + + var saveButton = $(''); + + saveButton.on('click', function() { + + var udfs = {}; + + $("div[udfUniqueId*='" + udfWidgetDiv.attributes["udfUniqueId"].nodeValue + "']").find("[name^='udf_']").each(function(i, udf) { + + if (udf.type == 'checkbox') + { + udfs[udf.id] = udf.checked == true; + } + else if (udf.type == 'select-one' || udf.type == 'select-multiple') + { + udfs[udf.id] = null; + + if (!isNaN(udf.value) && udf.value.trim() != '') + { + udfs[udf.id] = Number(udf.value); + } + } + else + { + udfs[udf.id] = udf.value; + } + }); + + FHC_AjaxClient.ajaxCallPost( + "widgets/UDF/saveUDFs", + { + udfUniqueId: FHC_UDFWidget._getUDFUniqueIdPrefix() + "/" + udfWidgetDiv.attributes["udfUniqueId"].nodeValue, + udfs: JSON.stringify(udfs) + }, + { + successCallback: function(data, textStatus, jqXHR) { + + if (FHC_AjaxClient.hasData(data)) + { + FHC_DialogLib.alertSuccess('Done!'); + } + else + { + console.log(FHC_AjaxClient.getError(data)); + } + } + }, + { + errorCallback: function(data, textStatus, jqXHR) { + console.log('Contact the administrator'); + } + } + ); + + }); + + saveButton.appendTo(udfWidgetDiv); + + }); + + }, + + //------------------------------------------------------------------------------------------------------------------ + // Private methods + + /** + * To retrive the page where the TableWidget is used, using the FHC_JS_DATA_STORAGE_OBJECT + */ + _getUDFUniqueIdPrefix: function() { + + return FHC_JS_DATA_STORAGE_OBJECT.called_path + "/" + FHC_JS_DATA_STORAGE_OBJECT.called_method; + } +}; + +/** + * When JQuery is up + */ +$(document).ready(function() { + + FHC_UDFWidget.display(); + +}); From e509f7acd17e7d6cdf4e6fd82462d20ed73e5dfd Mon Sep 17 00:00:00 2001 From: Paolo Date: Tue, 17 Dec 2019 16:57:02 +0100 Subject: [PATCH 002/216] Added comments and cleaned code --- application/controllers/widgets/Filters.php | 4 +- application/controllers/widgets/Tables.php | 4 +- application/controllers/widgets/UDF.php | 21 +++-- application/core/DB_Model.php | 2 +- application/libraries/UDFLib.php | 86 +++++++++++---------- application/views/templates/FHC-Header.php | 2 +- application/widgets/udf/UDFWidget.php | 12 +-- 7 files changed, 70 insertions(+), 61 deletions(-) diff --git a/application/controllers/widgets/Filters.php b/application/controllers/widgets/Filters.php index b5cbc07ea..748272f09 100644 --- a/application/controllers/widgets/Filters.php +++ b/application/controllers/widgets/Filters.php @@ -4,7 +4,7 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); /** * This controller operates between (interface) the JS (GUI) and the FilterWidgetLib (back-end) - * Provides data to the ajax get calls about the filter + * Provides data to the ajax get calls about the filter widget * Accepts ajax post calls to change the filter data * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON * NOTE: extends the FHC_Controller instead of the Auth_Controller because the FilterWidget has its @@ -12,7 +12,7 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); */ class Filters extends FHC_Controller { - const FILTER_UNIQUE_ID = 'filterUniqueId'; + const FILTER_UNIQUE_ID = 'filterUniqueId'; // Name of the filter widget unique id /** * Calls the parent's constructor and loads the FilterWidgetLib diff --git a/application/controllers/widgets/Tables.php b/application/controllers/widgets/Tables.php index 21161ff9f..b3ea7d5a5 100644 --- a/application/controllers/widgets/Tables.php +++ b/application/controllers/widgets/Tables.php @@ -4,7 +4,7 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); /** * This controller operates between (interface) the JS (GUI) and the tablewidgetlib (back-end) - * Provides data to the ajax get calls about the filter + * Provides data to the ajax get calls about the table widget * Accepts ajax post calls to change the filter data * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON * NOTE: extends the FHC_Controller instead of the Auth_Controller because the TableWidget has its @@ -12,7 +12,7 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); */ class Tables extends FHC_Controller { - const TABLE_UNIQUE_ID = 'tableUniqueId'; + const TABLE_UNIQUE_ID = 'tableUniqueId'; // Name of the table widget unique id /** * Calls the parent's constructor and loads the tablewidgetlib diff --git a/application/controllers/widgets/UDF.php b/application/controllers/widgets/UDF.php index c71eba73a..5b4c45776 100644 --- a/application/controllers/widgets/UDF.php +++ b/application/controllers/widgets/UDF.php @@ -3,14 +3,19 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); /** - * This controller... + * This controller operates between (interface) the JS (GUI) and the UDFLib (back-end) + * Provides data to the ajax get calls about the UDF widget + * Accepts ajax post calls to save UDFs + * This controller works with JSON calls on the HTTP GET or POST and the output is always JSON + * NOTE: extends the FHC_Controller instead of the Auth_Controller because the UDFWidget has its + * own permissions check */ class UDF extends FHC_Controller { - const UDF_UNIQUE_ID = 'udfUniqueId'; + const UDF_UNIQUE_ID = 'udfUniqueId'; // Name of the udf widget unique id /** - * Calls the parent's constructor and loads the + * Calls the parent's constructor and loads the UDFLib */ public function __construct() { @@ -22,7 +27,7 @@ class UDF extends FHC_Controller // Loads the UDFLib with HTTP GET/POST parameters $this->_loadUDFLib(); - // Checks if the caller is allow to read this data + // Checks if the caller is allow to use this UDF widget $this->_isAllowed(); } @@ -30,7 +35,7 @@ class UDF extends FHC_Controller // Public methods /** - * Retrieves data about the current filter from the session and will be written on the output in JSON format + * Save data about the current UDFs and the result will be written on the output in JSON format */ public function saveUDFs() { @@ -59,7 +64,7 @@ class UDF extends FHC_Controller // Private methods /** - * Checks if the user is allowed to use this filter + * Checks if the user is allowed to use this UDFWidget */ private function _isAllowed() { @@ -70,7 +75,7 @@ class UDF extends FHC_Controller } /** - * Loads the tablewidgetlib with the UDF_UNIQUE_ID parameter + * Loads the UDFLib with the UDF_UNIQUE_ID parameter * If the parameter UDF_UNIQUE_ID is not given then the execution of the controller is terminated and * an error message is printed */ @@ -89,7 +94,7 @@ class UDF extends FHC_Controller $udfUniqueId = $this->input->post(self::UDF_UNIQUE_ID); // is retrieved from the HTTP POST } - // Loads the tablewidgetlib that contains all the used logic + // Loads the UDFLib that contains all the used logic $this->load->library('UDFLib'); $this->udflib->setUDFUniqueId($udfUniqueId); diff --git a/application/core/DB_Model.php b/application/core/DB_Model.php index 667ff00ca..4b89ae5bf 100644 --- a/application/core/DB_Model.php +++ b/application/core/DB_Model.php @@ -61,7 +61,7 @@ class DB_Model extends CI_Model // Public methods /** - * This method provides a way to setup a database model without declaring one + * This method provides a way to setup a database model without declaring one that extends this class */ public function setup($schema, $table, $primaryKey, $hasSequence = true) { diff --git a/application/libraries/UDFLib.php b/application/libraries/UDFLib.php index edd11fd99..b9247fc4e 100644 --- a/application/libraries/UDFLib.php +++ b/application/libraries/UDFLib.php @@ -3,19 +3,20 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); /** - * Library to manage UDF + * Library to manage UDFs */ class UDFLib { - const UDF_UNIQUE_ID = 'udfUniqueId'; + const UDF_UNIQUE_ID = 'udfUniqueId'; // Name of the UDF widget unique id - const SESSION_NAME = 'FHC_UDF_WIDGET'; + const SESSION_NAME = 'FHC_UDF_WIDGET'; // Name of the session area used for UDFs - const WIDGET_NAME = 'UDFWidget'; - const SCHEMA_ARG_NAME = 'schema'; - const TABLE_ARG_NAME = 'table'; - const FIELD_ARG_NAME = 'field'; - const UDFS_ARG_NAME = 'udfs'; + // Parameters names + const WIDGET_NAME = 'UDFWidget'; // UDFWidget name + const SCHEMA_ARG_NAME = 'schema'; // Schema parameter name + const TABLE_ARG_NAME = 'table'; // Table parameter name + const FIELD_ARG_NAME = 'field'; // Field parameter name + const UDFS_ARG_NAME = 'udfs'; // UDFs parameter name // UDF json schema attributes const NAME = 'name'; // UDF name attribute @@ -29,7 +30,7 @@ class UDFLib // ...to specify permissions that are needed to use this TableWidget const REQUIRED_PERMISSIONS_PARAMETER = 'requiredPermissions'; - // ... + // ...to specify the primary key name and value const PRIMARY_KEY_NAME = 'primaryKeyName'; const PRIMARY_KEY_VALUE = 'primaryKeyValue'; @@ -61,10 +62,10 @@ class UDFLib private $_ci; // Code igniter instance - private $_udfUniqueId; // + private $_udfUniqueId; // Property that contains the UDF widget unique id /** - * Loads fhc helper + * Gets CI instance */ public function __construct() { @@ -400,7 +401,7 @@ class UDFLib } /** - * Return an unique string that identify this filter widget + * Return an unique string that identify this UDF widget * NOTE: The default value is the URI where the FilterWidget is called * If the fhc_controller_id is present then is also used */ @@ -420,7 +421,7 @@ class UDFLib } /** - * Wrapper method to the session helper funtions to retrieve the whole session for this filter + * Wrapper method to the session helper funtions to retrieve the whole session for this UDF widget */ public function getSession() { @@ -428,7 +429,7 @@ class UDFLib } /** - * Wrapper method to the session helper funtions to retrieve one element from the session of this filter + * Wrapper method to the session helper funtions to retrieve one element from the session of this UDF widget */ public function getSessionElement($name) { @@ -443,7 +444,7 @@ class UDFLib } /** - * Wrapper method to the session helper funtions to set the whole session for this filter + * Wrapper method to the session helper funtions to set the whole session for this UDF widget */ public function setSession($data) { @@ -451,7 +452,7 @@ class UDFLib } /** - * Wrapper method to the session helper funtions to set one element in the session for this filter + * Wrapper method to the session helper funtions to set one element in the session for this UDF widget */ public function setSessionElement($name, $value) { @@ -470,31 +471,52 @@ class UDFLib // Read the all session for this udf widget $session = $this->getSession(); + // If session is empty then return an error if ($session == null) return error('No UDFWidget loaded'); - // Workaround + // Workaround to load CI $this->_ci->load->model('system/UDF_model', 'UDFModel'); - // + // Initialize a new DB_Model $dbModel = new DB_Model(); + // Setup the new dbModel object with... $dbModel->setup( - $session[self::SCHEMA_ARG_NAME], // - $session[self::TABLE_ARG_NAME], // - $session[self::PRIMARY_KEY_NAME] // + $session[self::SCHEMA_ARG_NAME], // ... schema... + $session[self::TABLE_ARG_NAME], // ...table... + $session[self::PRIMARY_KEY_NAME] // ...and primary key name ); + // Returns the result of the database update operation to save UDFs return $dbModel->update( array($session[self::PRIMARY_KEY_NAME] => $session[self::PRIMARY_KEY_VALUE]), (array)$udfs ); } + /** + * Checks if at least one of the permissions given as parameter (requiredPermissions) belongs + * to the authenticated user, if confirmed then is allowed to use this UDFWidget. + * If the parameter requiredPermissions is NOT given or is not present in the session, + * then NO one is allow to use this UDFWidget + * Wrapper method to permissionlib->hasAtLeastOne + */ + public function isAllowed($requiredPermissions = null) + { + $this->_ci->load->library('PermissionLib'); // Load permission library + + // Gets the required permissions from the session if they are not provided as parameter + $rq = $requiredPermissions; + if ($rq == null) $rq = $this->getSessionElement(self::REQUIRED_PERMISSIONS_PARAMETER); + + return $this->_ci->permissionlib->hasAtLeastOne($rq, self::PERMISSION_TABLE_METHOD, self::PERMISSION_TYPE); + } + // ------------------------------------------------------------------------------------------------- // Private methods /** - * + * Print the block for UDFs */ private function _printStartUDFBlock($widgetData) { @@ -508,31 +530,13 @@ class UDFLib } /** - * + * Print the end of the UDFs block */ private function _printEndUDFBlock() { echo '
'."\n"; } - /** - * Checks if at least one of the permissions given as parameter (requiredPermissions) belongs - * to the authenticated user, if confirmed then is allowed to use this FilterWidget. - * If the parameter requiredPermissions is NOT given or is not present in the session, - * then NO one is allow to use this FilterWidget - * Wrapper method to permissionlib->hasAtLeastOne - */ - public function isAllowed($requiredPermissions = null) - { - $this->_ci->load->library('PermissionLib'); // Load permission library - - // Gets the required permissions from the session if they are not provided as parameter - $rq = $requiredPermissions; - if ($rq == null) $rq = $this->getSessionElement(self::REQUIRED_PERMISSIONS_PARAMETER); - - return $this->_ci->permissionlib->hasAtLeastOne($rq, self::PERMISSION_TABLE_METHOD, self::PERMISSION_TYPE); - } - /** * Move UDFs from $data to $UDFs */ diff --git a/application/views/templates/FHC-Header.php b/application/views/templates/FHC-Header.php index 49a77fe17..127575c2b 100644 --- a/application/views/templates/FHC-Header.php +++ b/application/views/templates/FHC-Header.php @@ -177,7 +177,7 @@ // Tinymce JS if ($tinymce === true) generateJSsInclude('vendor/tinymce/tinymce/tinymce.min.js'); - // Tinymce JS + // User Defined Fields if ($udfs === true) generateJSsInclude('public/js/UDFWidget.js'); // SB Admin 2 template JS diff --git a/application/widgets/udf/UDFWidget.php b/application/widgets/udf/UDFWidget.php index b3bf82470..7af3dd926 100644 --- a/application/widgets/udf/UDFWidget.php +++ b/application/widgets/udf/UDFWidget.php @@ -6,12 +6,12 @@ */ class UDFWidget extends HTMLWidget { - private $_requiredPermissions; // + private $_requiredPermissions; // The required permissions to use this UDF widget - private $_schema; - private $_table; - private $_primaryKeyName; - private $_primaryKeyValue; + private $_schema; // Schema name + private $_table; // Table name + private $_primaryKeyName; // Primary key name + private $_primaryKeyValue; // Primary key value /** * Initialize the UDFWidget and starts the execution of the logic @@ -22,7 +22,7 @@ class UDFWidget extends HTMLWidget $this->load->library('UDFLib'); // Loads the UDFLib that contains all the used logic - $this->udflib->setUDFUniqueIdByParams($args); + $this->udflib->setUDFUniqueIdByParams($args); // sets the unique id for this UDF $this->_initUDFWidget($args); // checks parameters and initialize properties From b270e65d2e147fab81d6d4a9fd3de2fcba00fccc Mon Sep 17 00:00:00 2001 From: Cris Date: Tue, 28 Jan 2020 12:26:08 +0100 Subject: [PATCH 003/216] Extended FHC_TableWidget with column picker, header & footer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added standard behaviour to FHC_TableWidget: . Added column picker to new TableWidgetHeader div. . Moved former footerElement (including Alle aus-/abwählen buttons, CSV Downloads) from single specific files to new TableWidgetFooter divs. . Adapted other files to work with new FHC_TableWidget behaviour --- .../lehrauftrag/acceptLehrauftragData.php | 61 ++--- .../lehrauftrag/approveLehrauftragData.php | 53 ++-- .../lehrauftrag/cancelledLehrauftragData.php | 23 +- .../lehre/lehrauftrag/orderLehrauftrag.php | 9 +- .../lehrauftrag/orderLehrauftragData.php | 80 +++--- application/views/widgets/table/table.php | 12 +- public/js/TableWidget.js | 229 +++++++++++++++++- .../js/lehre/lehrauftrag/acceptLehrauftrag.js | 72 ++---- .../lehre/lehrauftrag/approveLehrauftrag.js | 74 ++---- .../js/lehre/lehrauftrag/orderLehrauftrag.js | 73 ++---- 10 files changed, 417 insertions(+), 269 deletions(-) diff --git a/application/views/lehre/lehrauftrag/acceptLehrauftragData.php b/application/views/lehre/lehrauftrag/acceptLehrauftragData.php index 27a348ae7..08cc94e5f 100644 --- a/application/views/lehre/lehrauftrag/acceptLehrauftragData.php +++ b/application/views/lehre/lehrauftrag/acceptLehrauftragData.php @@ -326,10 +326,12 @@ $filterWidgetArray = array( 'Angenommen von' ), 'datasetRepOptions' => '{ - height: 550, - layout: "fitColumns", // fit columns to width of table - responsiveLayout: "hide", // hide columns that dont fit on the table - movableColumns: true, // allows changing column + height: func_height(this), + layout: "fitColumns", // fit columns to width of table + persistentLayout:true, // enables persistence (default store in localStorage if available, else in cookie) + persistenceID: "acceptLehrauftrag", // TableWidget unique id to store persistence data seperately for multiple tables + autoResize: false, // prevent auto resizing of table (false to allow adapting table size when cols are (de-)activated + movableColumns: true, // allows changing column placeholder: func_placeholder(), headerFilterPlaceholder: " ", index: "row_index", // assign specific column as unique id (important for row indexing) @@ -339,7 +341,6 @@ $filterWidgetArray = array( selectableCheck: function(row){ return func_selectableCheck(row); }, - footerElement: func_footerElement(), rowUpdated:function(row){ func_rowUpdated(row); }, @@ -357,40 +358,44 @@ $filterWidgetArray = array( }, renderStarted:function(){ func_renderStarted(this); - } + }, + tableWidgetFooter: { + selectButtons: true + } }', // tabulator properties 'datasetRepFieldsDefs' => '{ row_index: {visible:false}, // necessary for row indexing - lehreinheit_id: {headerFilter:"input", bottomCalc:"count", bottomCalcFormatter:function(cell){return "Anzahl: " + cell.getValue();}, width: "7%"}, - lehrveranstaltung_id: {headerFilter:"input", width: "5%"}, - projektarbeit_id: {visible: false}, - studiensemester_kurzbz: {visible: false}, - studiengang_kz: {visible: false}, - stg_typ_kurzbz: {headerFilter:"input", width: "5%"}, + lehreinheit_id: {headerFilter:"input", bottomCalc:"count", bottomCalcFormatter:function(cell){return "Anzahl: " + cell.getValue();}}, + lehrveranstaltung_id: {headerFilter:"input"}, + projektarbeit_id: {visible: false, headerFilter:"input"}, + studiensemester_kurzbz: {visible: false, headerFilter:"input"}, + studiengang_kz: {visible: false, headerFilter:"input"}, + stg_typ_kurzbz: {headerFilter:"input"}, semester: {headerFilter:"input"}, orgform_kurzbz: {headerFilter:"input"}, - person_id: {visible: false}, - typ: {headerFilter:"input", width: "7%"}, - auftrag: {headerFilter:"input", width: "15%"}, - lv_oe_kurzbz: {headerFilter:"input", width: "8%"}, - gruppe: {headerFilter:"input", width: "5%"}, + person_id: {visible: false, headerFilter:"input"}, + typ: {headerFilter:"input"}, + auftrag: {headerFilter:"input"}, + lv_oe_kurzbz: {headerFilter:"input"}, + gruppe: {headerFilter:"input"}, stunden: {align:"right", formatter: form_formatNulltoStringNumber, formatterParams:{precision:1}, headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator, - bottomCalc:"sum", bottomCalcParams:{precision:1}, width: "5%"}, - betrag: {align:"right", width: "6%", formatter: form_formatNulltoStringNumber, + bottomCalc:"sum", bottomCalcParams:{precision:1} + }, + betrag: {align:"right", formatter: form_formatNulltoStringNumber, headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator, - bottomCalc:"sum", bottomCalcParams:{precision:2}, bottomCalcFormatter:"money", bottomCalcFormatterParams:{decimal: ",", thousand: ".", symbol:"€"}, - width: "8%"}, + bottomCalc:"sum", bottomCalcParams:{precision:2}, bottomCalcFormatter:"money", bottomCalcFormatterParams:{decimal: ",", thousand: ".", symbol:"€"} + }, vertrag_id: {visible: false}, vertrag_stunden: {visible: false}, vertrag_betrag: {visible: false}, - mitarbeiter_uid: {visible: false}, - bestellt: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: bestellt_tooltip, width: "8%"}, - erteilt: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: erteilt_tooltip, width: "8%"}, - akzeptiert: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: akzeptiert_tooltip, width: "8%"}, - bestellt_von: {visible: false}, - erteilt_von: {visible: false}, - akzeptiert_von: {visible: false} + mitarbeiter_uid: {visible: false, headerFilter:"input"}, + bestellt: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: bestellt_tooltip}, + erteilt: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: erteilt_tooltip}, + akzeptiert: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: akzeptiert_tooltip}, + bestellt_von: {visible: false, headerFilter:"input"}, + erteilt_von: {visible: false, headerFilter:"input"}, + akzeptiert_von: {visible: false, headerFilter:"input"} }', // col properties ); diff --git a/application/views/lehre/lehrauftrag/approveLehrauftragData.php b/application/views/lehre/lehrauftrag/approveLehrauftragData.php index fbc30db1c..111e7bd01 100644 --- a/application/views/lehre/lehrauftrag/approveLehrauftragData.php +++ b/application/views/lehre/lehrauftrag/approveLehrauftragData.php @@ -337,14 +337,17 @@ $filterWidgetArray = array( 'Angenommen von' ), 'datasetRepOptions' => '{ - height: 700, - layout: "fitColumns", // fit columns to width of table - responsiveLayout: "hide", // hide columns that dont fit on the table - movableColumns: true, // allows changing column + height: func_height(this), + layout: "fitColumns", // fit columns to width of table + layoutColumnsOnNewData: true, // ajust column widths to the data each time TableWidget is loaded + persistentLayout:true, // enables persistence (default store in localStorage if available, else in cookie) + persistenceID: "approveLehrauftrag", // TableWidget unique id to store persistence data seperately for multiple tables + autoResize: false, // prevent auto resizing of table (false to allow adapting table size when cols are (de-)activated + movableColumns: true, // allows changing column placeholder: func_placeholder(), headerFilterPlaceholder: " ", groupBy:"lehrveranstaltung_id", - groupToggleElement:"header", //toggle group on click anywhere in the group header + groupToggleElement:"header", //toggle group on click anywhere in the group header groupHeader: function(value, count, data, group){ return func_groupHeader(data); }, @@ -357,7 +360,6 @@ $filterWidgetArray = array( return func_selectableCheck(row); }, initialFilter: func_initialFilter(), - footerElement: func_footerElement(), rowUpdated:function(row){ func_rowUpdated(row); }, @@ -373,44 +375,47 @@ $filterWidgetArray = array( }, tableBuilt: function(){ func_tableBuilt(this); - } + }, + tableWidgetFooter: { + selectButtons: true + } }', // tabulator properties 'datasetRepFieldsDefs' => '{ // column status is built dynamically in funcTableBuilt(), row_index: {visible:false}, // necessary for row indexing - personalnummer: {visible: false}, - lehreinheit_id: {headerFilter:"input", bottomCalc:"count", width: "7%", + personalnummer: {visible: false, headerFilter:"input"}, + lehreinheit_id: {headerFilter:"input", bottomCalc:"count", bottomCalcFormatter:function(cell){return "Anzahl: " + cell.getValue();},}, lehrveranstaltung_id: {headerFilter:"input"}, - lv_bezeichnung: {visible: false}, - projektarbeit_id: {visible: false}, + lv_bezeichnung: {visible: false, headerFilter:"input"}, + projektarbeit_id: {visible: false, headerFilter:"input"}, studiensemester_kurzbz: {headerFilter:"input"}, - studiengang_kz: {visible: false}, - stg_typ_kurzbz: {headerFilter:"input", width: "5%"}, + studiengang_kz: {visible: false, headerFilter:"input"}, + stg_typ_kurzbz: {headerFilter:"input"}, semester: {headerFilter:"input"}, orgform_kurzbz: {headerFilter:"input"}, - person_id: {visible: false}, + person_id: {visible: false, headerFilter:"input"}, typ: {headerFilter:"input"}, - auftrag: {headerFilter:"input", width:"20%"}, + auftrag: {headerFilter:"input"}, lv_oe_kurzbz: {headerFilter:"input"}, gruppe: {headerFilter:"input"}, - lektor: {headerFilter:"input", widthGrow: 3}, + lektor: {headerFilter:"input"}, stunden: {align:"right", formatter: form_formatNulltoStringNumber, formatterParams:{precision:1}, headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator, bottomCalc:"sum", bottomCalcParams:{precision:1}}, - betrag: {align:"right", width: "8%", formatter: form_formatNulltoStringNumber, + betrag: {align:"right", formatter: form_formatNulltoStringNumber, headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator, bottomCalc:"sum", bottomCalcParams:{precision:2}, bottomCalcFormatter:"money", bottomCalcFormatterParams:{decimal: ",", thousand: ".", symbol:"€"}}, vertrag_id: {visible: false}, vertrag_stunden: {visible: false}, vertrag_betrag: {visible: false}, - mitarbeiter_uid: {visible: false}, - bestellt: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: bestellt_tooltip, width: "8%"}, - erteilt: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: erteilt_tooltip, width: "8%"}, - akzeptiert: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: akzeptiert_tooltip, width: "8%"}, - bestellt_von: {visible: false}, - erteilt_von: {visible: false}, - akzeptiert_von: {visible: false}, + mitarbeiter_uid: {visible: false, headerFilter:"input"}, + bestellt: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: bestellt_tooltip}, + erteilt: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: erteilt_tooltip}, + akzeptiert: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: akzeptiert_tooltip}, + bestellt_von: {visible: false, headerFilter:"input"}, + erteilt_von: {visible: false, headerFilter:"input"}, + akzeptiert_von: {visible: false, headerFilter:"input"}, }', // col properties ); diff --git a/application/views/lehre/lehrauftrag/cancelledLehrauftragData.php b/application/views/lehre/lehrauftrag/cancelledLehrauftragData.php index 04d314636..20629cb84 100644 --- a/application/views/lehre/lehrauftrag/cancelledLehrauftragData.php +++ b/application/views/lehre/lehrauftrag/cancelledLehrauftragData.php @@ -64,8 +64,11 @@ $tableWidgetArray = array( 'Storniert am' ), 'datasetRepOptions' => '{ - layout: "fitColumns", // fit columns to width of table - responsiveLayout: "hide", // hide columns that dont fit on the table + layout: "fitColumns", // fit columns to width of table + layoutColumnsOnNewData: true, // ajust column widths to the data each time TableWidget is loaded + persistentLayout: true, // enables persistence (default store in localStorage if available, else in cookie) + persistenceID: "cancelledLehrauftrag", // TableWidget unique id to store persistence data seperately for multiple tables + autoResize: false, // prevent auto resizing of table (false to allow adapting table size when cols are (de-)activated movableColumns: true, // allows changing column placeholder: func_placeholder(), rowFormatter:function(row){ @@ -79,22 +82,24 @@ $tableWidgetArray = array( }, tableBuilt: function(){ func_tableBuilt(this); - } + }, }', // tabulator properties 'datasetRepFieldsDefs' => '{ vertrag_id: {visible: false}, - vertragsstunden_studiensemester_kurzbz: {visible: false}, - vertragstyp_kurzbz: {widthGrow: 2}, - bezeichnung: {widthGrow: 2}, + vertragsstunden_studiensemester_kurzbz: {visible: false, widthShrink:1}, + vertragstyp_kurzbz: {minWidth: 300}, + bezeichnung: {minWidth: 400}, vertragsstunden: { align:"right", formatter: form_formatNulltoStringNumber, formatterParams:{precision:1}, - bottomCalc:"sum", bottomCalcParams:{precision:1} + bottomCalc:"sum", bottomCalcParams:{precision:1}, + minWidth: 300 }, betrag: { align:"right", formatter: form_formatNulltoStringNumber, - bottomCalc:"sum", bottomCalcParams:{precision:2}, bottomCalcFormatter:"money", bottomCalcFormatterParams:{decimal: ",", thousand: ".", symbol:"€"} + bottomCalc:"sum", bottomCalcParams:{precision:2}, bottomCalcFormatter:"money", bottomCalcFormatterParams:{decimal: ",", thousand: ".", symbol:"€"}, + minWidth: 200 }, - storniert: {align:"center", mutator: mut_formatStringDate, tooltip: storniert_tooltip}, + storniert: {align:"center", mutator: mut_formatStringDate, tooltip: storniert_tooltip, minWidth: 200}, storniert_von: {visible: false}, letzterStatus_vorStorniert: {visible: false} }', // col properties diff --git a/application/views/lehre/lehrauftrag/orderLehrauftrag.php b/application/views/lehre/lehrauftrag/orderLehrauftrag.php index b04aa7985..27793e8ba 100644 --- a/application/views/lehre/lehrauftrag/orderLehrauftrag.php +++ b/application/views/lehre/lehrauftrag/orderLehrauftrag.php @@ -35,7 +35,7 @@ $this->load->view(
-
-
- load->view('lehre/lehrauftrag/orderLehrauftragData.php'); ?> -
-
-
+ load->view('lehre/lehrauftrag/orderLehrauftragData.php'); ?>
diff --git a/application/views/lehre/lehrauftrag/orderLehrauftragData.php b/application/views/lehre/lehrauftrag/orderLehrauftragData.php index b2fa3ac2f..d78f5ecfe 100644 --- a/application/views/lehre/lehrauftrag/orderLehrauftragData.php +++ b/application/views/lehre/lehrauftrag/orderLehrauftragData.php @@ -371,20 +371,22 @@ $filterWidgetArray = array( 'Angenommen von' ), 'datasetRepOptions' => '{ - height: 700, - layout:"fitColumns", // fit columns to width of table - responsiveLayout:"hide", // hide columns that dont fit on the table - movableColumns: true, // allows changing column - placeholder: func_placeholder(), - headerFilterPlaceholder: " ", - groupBy:"lehrveranstaltung_id", - groupToggleElement:"header", //toggle group on click anywhere in the group header - groupHeader: function(value, count, data, group){ - return func_groupHeader(data); - }, - footerElement: func_footerElement(), - columnCalcs:"both", // show column calculations at top and bottom of table and in groups - index: "row_index", // assign specific column as unique id (important for row indexing) + height: func_height(this), + layout:"fitColumns", // fit columns to width of table + layoutColumnsOnNewData: true, // ajust column widths to the data each time TableWidget is loaded + persistentLayout:true, // enables persistence (default store in localStorage if available, else in cookie) + persistenceID: "orderLehrauftrag", // TableWidget unique id to store persistence data seperately for multiple tables + autoResize: false, // prevent auto resizing of table (false to allow adapting table size when cols are (de-)activated + movableColumns: true, // allows changing column order + placeholder: func_placeholder(), // shown on empty table (no data) + headerFilterPlaceholder: " ", + groupBy:"lehrveranstaltung_id", + groupToggleElement:"header", //toggle group on click anywhere in the group header + groupHeader: function(value, count, data, group){ + return func_groupHeader(data); + }, + columnCalcs:"both", // show column calculations at top and bottom of table and in groups + index: "row_index", // assign specific column as unique id (important for row indexing) selectable: true, // allows row selection selectableRangeMode: "click", // allows range selection using shift end click on end of range selectablePersistence:false, // deselect previously selected rows when table is filtered, sorted or paginated @@ -409,46 +411,50 @@ $filterWidgetArray = array( dataLoaded: function(data){ func_dataLoaded(data, this); }, + tableWidgetFooter: { + selectButtons: true + } }', // tabulator properties 'datasetRepFieldsDefs' => '{ // column status is built dynamically in funcTableBuilt() row_index: {visible: false}, - personalnummer: {visible: false}, - lehreinheit_id: {headerFilter:"input", bottomCalc:"count", width: "7%", + personalnummer: {visible: false, headerFilter:"input"}, + lehreinheit_id: {headerFilter:"input", bottomCalc:"count", minWidth: 115, bottomCalcFormatter:function(cell){return "Anzahl: " + cell.getValue();}}, lehrveranstaltung_id: {headerFilter:"input"}, - lv_bezeichnung: {visible: false}, - projektarbeit_id: {visible: false}, + lv_bezeichnung: {visible: false, headerFilter:"input"}, + projektarbeit_id: {visible: false, headerFilter:"input"}, studiensemester_kurzbz: {headerFilter:"input"}, - studiengang_kz: {visible: false}, - stg_typ_kurzbz: {headerFilter:"input", width: "5%"}, + studiengang_kz: {visible: false, headerFilter:"input"}, + stg_typ_kurzbz: {headerFilter:"input", minWidth: 70}, semester: {headerFilter:"input"}, - studienplan_bezeichnung: {headerFilter:"input", width: "7%"}, + studienplan_bezeichnung: {headerFilter:"input"}, orgform_kurzbz: {headerFilter:"input"}, - person_id: {visible: false}, - typ: {headerFilter:"input"}, - auftrag: {headerFilter:"input", width:"15%"}, - lv_oe_kurzbz: {headerFilter:"input"}, - gruppe: {headerFilter:"input"}, + person_id: {visible: false, headerFilter:"input"}, + typ: {headerFilter:"input", minWidth:100}, + auftrag: {headerFilter:"input", minWidth:280}, + lv_oe_kurzbz: {headerFilter:"input", minWidth:80}, + gruppe: {headerFilter:"input", minWidth:120}, lektor: {headerFilter:"input", widthGrow: 3}, - stunden: {align:"right", formatter: form_formatNulltoStringNumber, formatterParams:{precision:1}, + stunden: {align:"right", minWidth: 80, formatter: form_formatNulltoStringNumber, formatterParams:{precision:1}, headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator, bottomCalc:"sum", bottomCalcParams:{precision:1}}, - stundensatz: {visible: false}, - betrag: {align:"right", width: "8%", formatter: form_formatNulltoStringNumber, + stundensatz: {visible: false, align:"right", minWidth: 100, formatter: form_formatNulltoStringNumber, + headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator}, + betrag: {align:"right", minWidth: 120, formatter: form_formatNulltoStringNumber, headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator, bottomCalc:"sum", bottomCalcParams:{precision:2}, bottomCalcFormatter:"money", bottomCalcFormatterParams:{decimal: ",", thousand: ".", symbol:"€"}}, - vertrag_id: {visible: false}, + vertrag_id: {visible: false, headerFilter:"input"}, vertrag_stunden: {visible: false}, vertrag_betrag: {visible: false}, - mitarbeiter_uid: {visible: false}, - bestellt: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: bestellt_tooltip, width: "8%"}, - erteilt: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: erteilt_tooltip, width: "8%"}, - akzeptiert: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: akzeptiert_tooltip, width: "8%"}, - bestellt_von: {visible: false}, - erteilt_von: {visible: false}, - akzeptiert_von: {visible: false} + mitarbeiter_uid: {visible: false, headerFilter:"input"}, + bestellt: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: bestellt_tooltip, minWidth: 100}, + erteilt: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: erteilt_tooltip, minWidth: 100}, + akzeptiert: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: akzeptiert_tooltip, minWidth: 100}, + bestellt_von: {visible: false, headerFilter:"input"}, + erteilt_von: {visible: false, headerFilter:"input"}, + akzeptiert_von: {visible: false, headerFilter:"input"} }', // col properties ); diff --git a/application/views/widgets/table/table.php b/application/views/widgets/table/table.php index e73aec335..936c32dc8 100644 --- a/application/views/widgets/table/table.php +++ b/application/views/widgets/table/table.php @@ -1,17 +1,21 @@ - +
+ +
+
-
- -
+
+ +
+
diff --git a/public/js/TableWidget.js b/public/js/TableWidget.js index 89e7cf3d5..575ad6b12 100644 --- a/public/js/TableWidget.js +++ b/public/js/TableWidget.js @@ -182,11 +182,90 @@ var FHC_TableWidget = { */ _turnOnEvents: function(tableWidgetDiv) { + var tableUniqueId = tableWidgetDiv.attr('tableUniqueId'); + // If the choosen dataset representation is tablesorter if (FHC_TableWidget._datasetRepresentation == DATASET_REP_TABLESORTER) { FHC_TableWidget._enableTableSorter(tableWidgetDiv); // enable the tablesorter } + + // If the choosen dataset representation is tabulator + if (FHC_TableWidget._datasetRepresentation == DATASET_REP_TABULATOR) + { + // --------------------------------------------------------------------------------------------------------- + // Add events to the elements + // --------------------------------------------------------------------------------------------------------- + + // Click-Event to download csv + tableWidgetDiv.find('#download-csv').on('click', function() + { + // BOM for correct UTF-8 char output + tableWidgetDiv.find("#tableWidgetTabulator").tabulator("download", "csv", "data.csv", {bom:true}); + }) + + // Click-Event to collapse settings div + tableWidgetDiv.find('#settings').on('click', function() + { + + //... auch unteren event für settings hier hinein + $('#tabulatorSettings-' + tableUniqueId).collapse('toggle'); + + $(this).toggleClass('active focus'); + + // De/activate and un/focus on clicked settings button + if(!$(this).hasClass('active focus')) + { + $(this).css({'background-color': 'white', 'border-color' : '#ccc', 'outline': 'none'}); + } + else + { + $(this).css({'background-color': '#e6e6e6'}); + } + }) + + /** + * Click-Event to select all rows + * Default is ALL rows. This can be modified via hook tableWidgetHook_selectAllButton. + */ + if (typeof tableWidgetHook_selectAllButton == 'function') + { + tableWidgetDiv.find('#select-all').on('click', function() { + tableWidgetHook_selectAllButton(tableWidgetDiv); + }); + } + else + { + tableWidgetDiv.find('#select-all').on('click', function() { + tableWidgetDiv.find("#tableWidgetTabulator").tabulator('selectRow', true); + }); + } + + // Click-Event to deselect all rows + tableWidgetDiv.find('#deselect-all').on('click', function() + { + tableWidgetDiv.find("#tableWidgetTabulator").tabulator('deselectRow'); + }) + + // Click-Event to toggle column-picker columns + tableWidgetDiv.find('.btn-select-col').on('click', function() + { + var selected = this.value; + + tableWidgetDiv.find("#tableWidgetTabulator").tabulator('toggleColumn', selected); + + $(this).toggleClass('active'); + + if(!$(this).hasClass('active')) + { + $(this).css('background-color', 'white'); + } + else + { + $(this).css('background-color', '#e6e6e6'); + } + }) + } }, _renderDataset: function(tableWidgetDiv, data) { @@ -443,11 +522,43 @@ var FHC_TableWidget = { options.columns = arrayTabulatorColumns; options.data = data.dataset; - + options.rowSelectionChanged = function(data, rows){ + _func_rowSelectionChanged(data, rows); + }; + options.columnVisibilityChanged = function(column, visible) { + _func_columnVisibilityChanged(column, visible); + }; + // Renders the tabulator tableWidgetDiv.find("#tableWidgetTabulator").tabulator(options); } } + + // ------------------------------------------------------------------------------------------------------------- + // Render TableWidget Header and -Footer + // ------------------------------------------------------------------------------------------------------------- + + // Render tableWidgetHeader + var tabulatorHeaderHTML = _renderTabulatorHeaderHTML(tableWidgetDiv); + tableWidgetDiv.find('#tableWidgetHeader').append(tabulatorHeaderHTML); + + // Render the collapsable div triggered by button in tableWidgetHeader + var tabulatorHeaderCollapseHTML = _renderTabulatorHeaderCollapseHTML(tableWidgetDiv); + tableWidgetDiv.find('#tableWidgetHeader').after(tabulatorHeaderCollapseHTML); + + /** + * tableWidgetFooter is NOT rendered by default. + * tableWidgetFooter is rendered, if tableWidgetFooter is set in tabulators datasetRepOptions. + * Setup options like this: + * tableWidgetFooter: { + * selectButtons: true // tableWidgetFooter properties are checked in _renderTabulatorFooterHTML function + * } + */ + if (options.tableWidgetFooter != 'undefined' && options.tableWidgetFooter != null) + { + var tabulatorFooterHTML = _renderTabulatorFooterHTML(options.tableWidgetFooter); + tableWidgetDiv.find('#tableWidgetFooter').append(tabulatorFooterHTML); + } }, /** @@ -584,6 +695,122 @@ var FHC_TableWidget = { } }; +//********************************************************************************************************************** +// Render functions +//********************************************************************************************************************** +/* + * Processed when row selection changed. + * Displays number of selected rows on row selection change. + */ +function _func_rowSelectionChanged (data, rows){ + + $('#number-selected').html("Ausgewählte Zeilen: " + rows.length + ""); +} + +/* Processed when columns visibility changed (e.g. using the column picker). + * Redraws the table to expand columns to table width. + */ +function _func_columnVisibilityChanged(column, visible){ + + var table = column.getTable(); + + table.redraw(); +} + +// Returns TableWidget Header HTML (download-, setting button...) +function _renderTabulatorHeaderHTML(tableWidgetDiv){ + + var tableUniqueId = tableWidgetDiv.attr('tableUniqueId'); + + var tabulatorHeaderHTML = ''; + tabulatorHeaderHTML += ''; + + return tabulatorHeaderHTML; +} + +// Returns collapsable HTML element for TableWidget header buttons +function _renderTabulatorHeaderCollapseHTML(tableWidgetDiv){ + + var tableUniqueId = tableWidgetDiv.attr('tableUniqueId'); + + var tabulatorHeaderCollapseHTML = ''; + tabulatorHeaderCollapseHTML += '
'; + tabulatorHeaderCollapseHTML += '
'; + tabulatorHeaderCollapseHTML += '
'; + tabulatorHeaderCollapseHTML += '
'; + + tabulatorHeaderCollapseHTML += '
'; + tabulatorHeaderCollapseHTML += ''; // end panel-heading + tabulatorHeaderCollapseHTML += '
'; + tabulatorHeaderCollapseHTML += '
'; + tabulatorHeaderCollapseHTML += '
'; + + // Create column picker (Spalten einstellen) + tableWidgetDiv.find('#tableWidgetTabulator').tabulator('getColumns').forEach(function(column) + { + var field = column.getField(); + var title = column.getDefinition().title; + var active_status = column.getVisibility() ? 'active' : ''; + + // If certain columns should be excluded from the column picker (define them in a blacklist array) + if (typeof tableWidgetBlacklistArray_columnUnselectable != 'undefined' && + Array.isArray(tableWidgetBlacklistArray_columnUnselectable) && + tableWidgetBlacklistArray_columnUnselectable.length) + { + if ($.inArray(field, tableWidgetBlacklistArray_columnUnselectable) < 0) + { + tabulatorHeaderCollapseHTML += ''; + } + } + // Else provide all tabulator fields as pickable columns + else + { + tabulatorHeaderCollapseHTML += ''; + } + }); + + tabulatorHeaderCollapseHTML += '
'; // end btn-group + tabulatorHeaderCollapseHTML += '
'; // end panel-body + tabulatorHeaderCollapseHTML += '
'; // end panel-collapse + tabulatorHeaderCollapseHTML += '
'; // end panel + + tabulatorHeaderCollapseHTML += '
'; // end panel-group + tabulatorHeaderCollapseHTML += '
'; // end col + tabulatorHeaderCollapseHTML += '
'; // end row + + return tabulatorHeaderCollapseHTML; +} + +// Returns TableWidget Footer HTML (de-/select buttons,...) +function _renderTabulatorFooterHTML(tableWidgetFooterOptions){ + + var tabulatorFooterHTML = ''; + + // If property selectButtons is true, render 'Alle auswaehlen / Alle abwaehlen' buttons + if (tableWidgetFooterOptions.selectButtons != 'undefined' && tableWidgetFooterOptions.selectButtons == true) + { + tabulatorFooterHTML += ''; + tabulatorFooterHTML += '

'; + } + + return tabulatorFooterHTML; +} + /** * When JQuery is up */ diff --git a/public/js/lehre/lehrauftrag/acceptLehrauftrag.js b/public/js/lehre/lehrauftrag/acceptLehrauftrag.js index 03c72e2f2..31ade57fa 100644 --- a/public/js/lehre/lehrauftrag/acceptLehrauftrag.js +++ b/public/js/lehre/lehrauftrag/acceptLehrauftrag.js @@ -19,6 +19,18 @@ const ICON_LEHRAUFTRAG_APPROVED = ''; const ICON_LEHRAUFTRAG_CANCELLED = ''; +// Fields that should not be provided in the column picker +var tableWidgetBlacklistArray_columnUnselectable = [ + 'status', + 'row_index', + 'betrag', + 'vertrag_id', + 'vertrag_stunden', + 'vertrag_betrag', + 'storniert_von', // fields from cancelledLehrauftragData + 'letzterStatus_vorStorniert' // fields from cancelledLehrauftragData +]; + // ----------------------------------------------------------------------------------------------------------------- // Mutators - setter methods to manipulate table data when entering the tabulator // ----------------------------------------------------------------------------------------------------------------- @@ -254,66 +266,22 @@ function func_renderComplete(table){ ); } -// Tabulator footer element +// TableWidget Footer element // ----------------------------------------------------------------------------------------------------------------- -// Adds a footer with buttons select all / deselect all / download -function func_footerElement(){ - - var footer_html = '
'; - footer_html += '
'; - - footer_html += ''; - - footer_html += ''; - - footer_html += '
'; - footer_html += '
'; - - return footer_html; -} - -// Performs download CSV -function footer_downloadCSV(){ - $('#tableWidgetTabulator').tabulator("download", "csv", "data.csv", {bom:true}); // BOM for correct UTF-8 char output -} - /* - * Performs select all + * Hook to overwrite TableWigdgets select-all-button behaviour * Select all (filtered) rows and ignore rows that are bestellt and erteilt */ -function footer_selectAll(){ - $('#tableWidgetTabulator').tabulator('getRows', true) - .filter(row => row.getData().bestellt != null && // bestellt - row.getData().erteilt != null && // AND erteilt - row.getData().akzeptiert == null && // AND NOT akzeptiert - row.getData().status != 'Geändert') // AND NOT geändert +function tableWidgetHook_selectAllButton(tableWidgetDiv){ + tableWidgetDiv.find("#tableWidgetTabulator").tabulator('getRows', true) + .filter(row => row.getData().bestellt != null && // bestellt + row.getData().erteilt != null && // AND erteilt + row.getData().akzeptiert == null && // AND NOT akzeptiert + row.getData().status != 'Geändert') // AND NOT geändert .forEach((row => row.select())); } -/* - * Performs deselect all - * Deselect all (filtered) rows - */ -function footer_deselectAll(){ - $('#tableWidgetTabulator').tabulator('deselectRow'); -} - -// Displays number of selected rows on row selection change -function func_rowSelectionChanged(data, rows){ - $('#number-selected').html("Für Annehmen ausgewählt: " + rows.length + ""); -} - // ----------------------------------------------------------------------------------------------------------------- // Tabulator columns format functions // ----------------------------------------------------------------------------------------------------------------- diff --git a/public/js/lehre/lehrauftrag/approveLehrauftrag.js b/public/js/lehre/lehrauftrag/approveLehrauftrag.js index 94e6af473..f38d251c0 100644 --- a/public/js/lehre/lehrauftrag/approveLehrauftrag.js +++ b/public/js/lehre/lehrauftrag/approveLehrauftrag.js @@ -19,6 +19,17 @@ const ICON_LEHRAUFTRAG_ORDERED = ''; const ICON_LEHRAUFTRAG_CHANGED = ''; +// Fields that should not be provided in the column picker +var tableWidgetBlacklistArray_columnUnselectable = [ + 'status', + 'row_index', + 'personalnummer', + 'betrag', + 'vertrag_id', + 'vertrag_stunden', + 'vertrag_betrag' +]; + // ----------------------------------------------------------------------------------------------------------------- // Mutators - setter methods to manipulate table data when entering the tabulator // ----------------------------------------------------------------------------------------------------------------- @@ -301,65 +312,20 @@ function func_rowUpdated(row){ row.getElement().style["pointerEvents"] = "none"; } - -// Tabulator footer element +// TableWidget Footer element // ----------------------------------------------------------------------------------------------------------------- -// Adds a footer with buttons select all / deselect all / download -function func_footerElement(){ - - var footer_html = '
'; - footer_html += '
'; - - footer_html += ''; - - footer_html += ''; - - footer_html += '
'; - footer_html += '
'; - - return footer_html; -} - -// Performs download CSV -function footer_downloadCSV(){ - $('#tableWidgetTabulator').tabulator("download", "csv", "data.csv", {bom:true}); // BOM for correct UTF-8 char output -} - /* - * Performs select all + * Hook to overwrite TableWigdgets select-all-button behaviour * Select all (filtered) rows that are bestellt */ -function footer_selectAll(){ - $('#tableWidgetTabulator').tabulator('getRows', true) - .filter(row => row.getData().personalnummer >= 0 && // NOT dummies - row.getData().bestellt != null && // AND bestellt - row.getData().erteilt == null && // AND NOT erteilt - row.getData().status != 'Geändert') // AND NOT geaendert - .forEach((row => row.select())); -} - -/* - * Performs deselect all - * Deselect all (filtered) rows - */ -function footer_deselectAll(){ - $('#tableWidgetTabulator').tabulator('deselectRow'); -} - -// Displays number of selected rows on row selection change -function func_rowSelectionChanged(data, rows){ - $('#number-selected').html("Für Erteilung ausgewählt: " + rows.length + ""); +function tableWidgetHook_selectAllButton(tableWidgetDiv){ + tableWidgetDiv.find("#tableWidgetTabulator").tabulator('getRows', true) + .filter(row => row.getData().personalnummer >= 0 && // NOT dummies + row.getData().bestellt != null && // AND bestellt + row.getData().erteilt == null && // AND NOT erteilt + row.getData().status != 'Geändert') // AND NOT geaendert + .forEach((row => row.select())); } // ----------------------------------------------------------------------------------------------------------------- diff --git a/public/js/lehre/lehrauftrag/orderLehrauftrag.js b/public/js/lehre/lehrauftrag/orderLehrauftrag.js index 4e58272e5..a9a59efbb 100644 --- a/public/js/lehre/lehrauftrag/orderLehrauftrag.js +++ b/public/js/lehre/lehrauftrag/orderLehrauftrag.js @@ -18,6 +18,17 @@ const ICON_LEHRAUFTRAG_ORDERED = ''; const ICON_LEHRAUFTRAG_CHANGED = ''; +// Fields that should not be provided in the column picker +var tableWidgetBlacklistArray_columnUnselectable = [ + 'status', + 'row_index', + 'personalnummer', + 'betrag', + 'vertrag_id', + 'vertrag_stunden', + 'vertrag_betrag' +]; + // ----------------------------------------------------------------------------------------------------------------- // Mutators - setter methods to manipulate table data when entering the tabulator // ----------------------------------------------------------------------------------------------------------------- @@ -309,64 +320,20 @@ function func_rowUpdated(row){ row.getElement().style["pointerEvents"] = "none"; } -// Tabulator footer element +// TableWidget Footer element // ----------------------------------------------------------------------------------------------------------------- -// Adds a footer with buttons select all / deselect all / download -function func_footerElement(){ - - var footer_html = '
'; - footer_html += '
'; - - footer_html += ''; - - footer_html += ''; - - footer_html += '
'; - footer_html += '
'; - - return footer_html; -} - -// Performs download CSV -function footer_downloadCSV(){ - $('#tableWidgetTabulator').tabulator("download", "csv", "data.csv", {bom:true}); // BOM for correct UTF-8 char output -} - /* - * Performs select all + * Hook to overwrite TableWigdgets select-all-button behaviour * Select all (filtered) rows and ignore rows which have status bestellt */ -function footer_selectAll(){ - $('#tableWidgetTabulator').tabulator('getRows', true) - .filter(row => row.getData().personalnummer >= 0 && // NOT dummies - row.getData().bestellt == null || // AND neu - row.getData().bestellt != null && // OR (bestellt - row.getData().status == 'Geändert') // AND geaendert) - .forEach((row => row.select())); -} - -/* - * Performs deselect all - * Deselect all (filtered) rows - */ -function footer_deselectAll(){ - $('#tableWidgetTabulator').tabulator('deselectRow'); -} - -// Displays number of selected rows on row selection change -function func_rowSelectionChanged(data, rows){ - $('#number-selected').html("Für Bestellung ausgewählt: " + rows.length + ""); +function tableWidgetHook_selectAllButton(tableWidgetDiv){ + tableWidgetDiv.find("#tableWidgetTabulator").tabulator('getRows', true) + .filter(row => row.getData().personalnummer >= 0 && // NOT dummies + row.getData().bestellt == null || // AND neu + row.getData().bestellt != null && // OR (bestellt + row.getData().status == 'Geändert') // AND geaendert) + .forEach((row => row.select())); } // ----------------------------------------------------------------------------------------------------------------- From 198a3eb2d541cd80512ce88060790289fb51516e Mon Sep 17 00:00:00 2001 From: Cris Date: Tue, 28 Jan 2020 12:29:18 +0100 Subject: [PATCH 004/216] Adjusted tabulator size to window screen size --- public/js/lehre/lehrauftrag/acceptLehrauftrag.js | 12 ++++++++++++ public/js/lehre/lehrauftrag/approveLehrauftrag.js | 11 +++++++++++ public/js/lehre/lehrauftrag/orderLehrauftrag.js | 11 +++++++++++ 3 files changed, 34 insertions(+) diff --git a/public/js/lehre/lehrauftrag/acceptLehrauftrag.js b/public/js/lehre/lehrauftrag/acceptLehrauftrag.js index 31ade57fa..c3d89ac52 100644 --- a/public/js/lehre/lehrauftrag/acceptLehrauftrag.js +++ b/public/js/lehre/lehrauftrag/acceptLehrauftrag.js @@ -93,6 +93,11 @@ function hf_filterStringnumberWithOperator(headerValue, rowValue, rowData){ // Tabulator table format functions // ----------------------------------------------------------------------------------------------------------------- +// Returns relative height (depending on screen size) +function func_height(table){ + return $(window).height() * 0.50; +} + // Displays text when table is empty function func_placeholder() { @@ -432,6 +437,13 @@ storniert_tooltip = function(cell){ } $(function() { + + // Redraw table on resize to fit tabulators height to windows height + window.addEventListener('resize', function(){ + $('#tableWidgetTabulator').tabulator('setHeight', $(window).height() * 0.50); + $('#tableWidgetTabulator').tabulator('redraw', true); + }); + // Show all rows $("#show-all").click(function(){ $('#tableWidgetTabulator').tabulator('clearFilter'); diff --git a/public/js/lehre/lehrauftrag/approveLehrauftrag.js b/public/js/lehre/lehrauftrag/approveLehrauftrag.js index f38d251c0..29e2d9651 100644 --- a/public/js/lehre/lehrauftrag/approveLehrauftrag.js +++ b/public/js/lehre/lehrauftrag/approveLehrauftrag.js @@ -106,6 +106,11 @@ function func_initialFilter(){ // Tabulator table format functions // ----------------------------------------------------------------------------------------------------------------- +// Returns relative height (depending on screen size) +function func_height(table){ + return $(window).height() * 0.50; +} + // Displays text when table is empty function func_placeholder() { @@ -492,6 +497,12 @@ akzeptiert_tooltip = function(cell){ } $(function() { + // Redraw table on resize to fit tabulators height to windows height + window.addEventListener('resize', function(){ + $('#tableWidgetTabulator').tabulator('setHeight', $(window).height() * 0.50); + $('#tableWidgetTabulator').tabulator('redraw', true); + }); + // Show all rows $("#show-all").click(function(){ $('#tableWidgetTabulator').tabulator('clearFilter'); diff --git a/public/js/lehre/lehrauftrag/orderLehrauftrag.js b/public/js/lehre/lehrauftrag/orderLehrauftrag.js index a9a59efbb..6471d988f 100644 --- a/public/js/lehre/lehrauftrag/orderLehrauftrag.js +++ b/public/js/lehre/lehrauftrag/orderLehrauftrag.js @@ -111,6 +111,11 @@ function func_dataLoaded(data, table){ // Tabulator table format functions // ----------------------------------------------------------------------------------------------------------------- +// Returns relative height (depending on screen size) +function func_height(table){ + return $(window).height() * 0.50; +} + // Displays text when table is empty function func_placeholder() { @@ -509,6 +514,12 @@ akzeptiert_tooltip = function(cell){ $(function() { + // Redraw table on resize to fit tabulators height to windows height + window.addEventListener('resize', function(){ + $('#tableWidgetTabulator').tabulator('setHeight', $(window).height() * 0.50); + $('#tableWidgetTabulator').tabulator('redraw', true); + }); + // Show all rows $("#show-all").click(function(){ $('#tableWidgetTabulator').tabulator('clearFilter'); From f22931ffa8939449e4a0d77d050957c18faadb2e Mon Sep 17 00:00:00 2001 From: Cris Date: Tue, 28 Jan 2020 12:33:23 +0100 Subject: [PATCH 005/216] Adapted row color when hovering on selected rows Before row color was changing from selected-blue to grey, although row was still selected, which was somehow confusing for the user. Now color stays blue. --- public/css/Tabulator.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/public/css/Tabulator.css b/public/css/Tabulator.css index 359f29e72..eac315f93 100644 --- a/public/css/Tabulator.css +++ b/public/css/Tabulator.css @@ -12,3 +12,8 @@ .tabulator-page.active { color: #337ab7 !important; } + +/* Avoid confusing color change when hovering over selected rows */ +.tabulator-row.tabulator-selected:hover { + background-color: #769bcc !important; +} \ No newline at end of file From 2e30841b0daa98a1b8d179833f5116c00e81dc15 Mon Sep 17 00:00:00 2001 From: alex Date: Tue, 28 Jan 2020 17:21:47 +0100 Subject: [PATCH 006/216] - added UDF prestudent dropdown to infocenterDetails - crm/Prestudent_model: improved code, e.g. replaced ->retval --- .../system/infocenter/InfoCenter.php | 24 +++++--- application/models/crm/Prestudent_model.php | 56 +++++++++++++------ .../models/organisation/Studienjahr_model.php | 2 +- .../system/infocenter/infocenterDetails.php | 1 + .../views/system/infocenter/zgvpruefungen.php | 48 ++++++++++------ public/js/infocenter/infocenterDetails.js | 36 +++++++----- 6 files changed, 108 insertions(+), 59 deletions(-) diff --git a/application/controllers/system/infocenter/InfoCenter.php b/application/controllers/system/infocenter/InfoCenter.php index d085e7db0..3f65ed605 100644 --- a/application/controllers/system/infocenter/InfoCenter.php +++ b/application/controllers/system/infocenter/InfoCenter.php @@ -1271,7 +1271,7 @@ class InfoCenter extends Auth_Controller show_error(getError($prestudentWithZgv)); } - $zgvpruefung = $prestudentWithZgv->retval[0]; + $zgvpruefung = getData($prestudentWithZgv); if (isset($zgvpruefung->prestudentstatus)) { @@ -1296,11 +1296,15 @@ class InfoCenter extends Auth_Controller $zgvpruefung->isRtFreigegeben = false; $zgvpruefung->isStgFreigegeben = false; $zgvpruefung->sendStgFreigabeMsg = true;//wether Stgudiengangfreigabemessage can be sent (for "exceptions", Studiengänge with no message sending) - $this->PrestudentstatusModel->addSelect('bestaetigtam, statusgrund_id, tbl_status_grund.bezeichnung_mehrsprachig AS bezeichnung_statusgrund'); - $this->PrestudentstatusModel->addJoin('public.tbl_status_grund', 'statusgrund_id', 'LEFT'); - $isFreigegeben = $this->PrestudentstatusModel->loadWhere(array('studiensemester_kurzbz' => $zgvpruefung->prestudentstatus->studiensemester_kurzbz, - 'tbl_prestudentstatus.status_kurzbz' => self::INTERESSENTSTATUS, 'prestudent_id' => $prestudent->prestudent_id)); + $isFreigegeben = null; + if (isset($zgvpruefung->prestudentstatus->studiensemester_kurzbz)) + { + $this->PrestudentstatusModel->addSelect('bestaetigtam, statusgrund_id, tbl_status_grund.bezeichnung_mehrsprachig AS bezeichnung_statusgrund'); + $this->PrestudentstatusModel->addJoin('public.tbl_status_grund', 'statusgrund_id', 'LEFT'); + $isFreigegeben = $this->PrestudentstatusModel->loadWhere(array('studiensemester_kurzbz' => $zgvpruefung->prestudentstatus->studiensemester_kurzbz, + 'tbl_prestudentstatus.status_kurzbz' => self::INTERESSENTSTATUS, 'prestudent_id' => $prestudent->prestudent_id)); + } if (hasData($isFreigegeben)) { @@ -1457,9 +1461,10 @@ class InfoCenter extends Auth_Controller show_error(getError($prestudent)); } - $person_id = $prestudent->retval[0]->person_id; - $studiengang_kurzbz = $prestudent->retval[0]->studiengang; - $studiengang_bezeichnung = $prestudent->retval[0]->studiengangbezeichnung; + $prestudentdata = getData($prestudent); + $person_id = $prestudentdata->person_id; + $studiengang_kurzbz = $prestudentdata->studiengang; + $studiengang_bezeichnung = $prestudentdata->studiengangbezeichnung; return array('person_id' => $person_id, 'studiengang_kurzbz' => $studiengang_kurzbz, 'studiengang_bezeichnung' => $studiengang_bezeichnung); } @@ -1502,7 +1507,8 @@ class InfoCenter extends Auth_Controller private function _sendFreigabeMail($prestudent_id) { //get data - $prestudent = $this->PrestudentModel->getPrestudentWithZgv($prestudent_id)->retval[0]; + $prestudent = $this->PrestudentModel->getPrestudentWithZgv($prestudent_id); + $prestudent = getData($prestudent); $prestudentstatus = $prestudent->prestudentstatus; $person_id = $prestudent->person_id; $person = $this->PersonModel->getPersonStammdaten($person_id, true)->retval; diff --git a/application/models/crm/Prestudent_model.php b/application/models/crm/Prestudent_model.php index d5c52a3c3..250b68099 100644 --- a/application/models/crm/Prestudent_model.php +++ b/application/models/crm/Prestudent_model.php @@ -209,6 +209,9 @@ class Prestudent_model extends DB_Model if (!hasData($prestudent)) return error('prestudent could not be loaded'); + $prestudentdata = getData($prestudent); + $prestudentdata = $prestudentdata[0]; + //Prestudentstatus $lastStatus = $this->PrestudentstatusModel->getLastStatus($prestudent_id); @@ -217,32 +220,41 @@ class Prestudent_model extends DB_Model return $lastStatus; } - if (count($lastStatus->retval) > 0) + if (hasData($lastStatus)) { + $lastStatusData = getData($lastStatus); + $lastStatusData = $lastStatusData[0]; //get Studiengangname from Studienplan and -ordnung $studienordnung = $this->PrestudentstatusModel->getStudienordnungFromPrestudent($prestudent_id); if ($studienordnung->error) return $studienordnung; - if (count($studienordnung->retval) > 0) + if (hasData($studienordnung)) { - $lastStatus->retval[0]->studiengang_kz = $studienordnung->retval[0]->studiengang_kz; - $lastStatus->retval[0]->studiengangkurzbzlang = $studienordnung->retval[0]->studiengangkurzbzlang; - $lastStatus->retval[0]->studiengangbezeichnung = $studienordnung->retval[0]->studiengangbezeichnung; - $lastStatus->retval[0]->studiengangbezeichnung_englisch = $studienordnung->retval[0]->studiengangbezeichnung_englisch; - $lastStatus->retval[0]->regelstudiendauer = $studienordnung->retval[0]->regelstudiendauer; + $studienordnungdata = getData($studienordnung); + $studienordnungdata = $studienordnungdata[0]; + + $lastStatusData->studiengang_kz = $studienordnungdata->studiengang_kz; + $lastStatusData->studiengangkurzbzlang = $studienordnungdata->studiengangkurzbzlang; + $lastStatusData->studiengangbezeichnung = $studienordnungdata->studiengangbezeichnung; + $lastStatusData->studiengangbezeichnung_englisch = $studienordnungdata->studiengangbezeichnung_englisch; + $lastStatusData->regelstudiendauer = $studienordnungdata->regelstudiendauer; } //get Sprache $this->load->model('system/sprache_model', 'SpracheModel'); $this->SpracheModel->addSelect('sprache, locale, bezeichnung'); - $language = $this->SpracheModel->load($lastStatus->retval[0]->sprache); + $language = $this->SpracheModel->load($lastStatusData->sprache); if ($language->error) return $language; - if (count($language->retval) > 0) - $lastStatus->retval[0]->sprachedetails = $language->retval[0]; + if (hasData($language)) + { + $languagedata = getData($language); + $languagedata = $languagedata[0]; + $lastStatusData->sprachedetails = $languagedata; + } //get Bewerbungsfrist $this->load->model('crm/bewerbungstermine_model', 'BewerbungstermineModel'); @@ -251,24 +263,32 @@ class Prestudent_model extends DB_Model $this->BewerbungstermineModel->addLimit(1); $bewerbungstermin = $this->BewerbungstermineModel->loadWhere( array( - 'studienplan_id' => $lastStatus->retval[0]->studienplan_id, - 'studiensemester_kurzbz' => $lastStatus->retval[0]->studiensemester_kurzbz, - 'studiengang_kz' => $prestudent->retval[0]->studiengang_kz + 'studienplan_id' => $lastStatusData->studienplan_id, + 'studiensemester_kurzbz' => $lastStatusData->studiensemester_kurzbz, + 'studiengang_kz' => $prestudentdata->studiengang_kz ) ); if ($bewerbungstermin->error) return $bewerbungstermin; - if (count($bewerbungstermin->retval) > 0) + if (hasData($bewerbungstermin)) { - $lastStatus->retval[0]->bewerbungstermin = $bewerbungstermin->retval[0]->ende; - $lastStatus->retval[0]->bewerbungsnachfrist = $bewerbungstermin->retval[0]->nachfrist_ende; + $bewerbungstermindata = getData($bewerbungstermin); + $bewerbungstermindata = $bewerbungstermindata[0]; + $lastStatusData->bewerbungstermin = $bewerbungstermindata->ende; + $lastStatusData->bewerbungsnachfrist = $bewerbungstermindata->nachfrist_ende; } - $prestudent->retval[0]->prestudentstatus = $lastStatus->retval[0]; + $prestudentdata->prestudentstatus = $lastStatusData; + + + if ($this->hasUDF()) + { + $prestudentdata->prestudentUdfs = $this->getUDFs($prestudent_id); + } } - return success($prestudent->retval); + return success($prestudentdata); } /** diff --git a/application/models/organisation/Studienjahr_model.php b/application/models/organisation/Studienjahr_model.php index 36784a280..3bbe3a07f 100644 --- a/application/models/organisation/Studienjahr_model.php +++ b/application/models/organisation/Studienjahr_model.php @@ -14,7 +14,7 @@ class Studienjahr_model extends DB_Model } /** - * Gets current Studienjahr, as determined by its start and enddate + * Gets current Studienjahr, as determined by start and enddate of current semester * @return array|null */ public function getCurrStudienjahr() diff --git a/application/views/system/infocenter/infocenterDetails.php b/application/views/system/infocenter/infocenterDetails.php index ab4e3533e..326c38035 100644 --- a/application/views/system/infocenter/infocenterDetails.php +++ b/application/views/system/infocenter/infocenterDetails.php @@ -14,6 +14,7 @@ 'sbadmintemplate' => true, 'addons' => true, 'navigationwidget' => true, + 'udfs' => true, 'customCSSs' => array( 'public/css/sbadmin2/admintemplate.css', 'public/css/sbadmin2/tablesort_bootstrap.css', diff --git a/application/views/system/infocenter/zgvpruefungen.php b/application/views/system/infocenter/zgvpruefungen.php index 86344d06b..5accd22a4 100644 --- a/application/views/system/infocenter/zgvpruefungen.php +++ b/application/views/system/infocenter/zgvpruefungen.php @@ -118,8 +118,7 @@
-
+
@@ -302,21 +301,38 @@
- -
-
- -
-
- -
-
- + +
+
+ +
+
+ +
+
+ +
+ prestudentUdfs)) + { + echo $this->udflib->UDFWidget( + array( + UDFLib::UDF_UNIQUE_ID => 'infocenterPrestudentUDFs_'.$zgvpruefung->prestudent_id, + UDFLib::REQUIRED_PERMISSIONS_PARAMETER => 'infocenter', + UDFLib::SCHEMA_ARG_NAME => 'public', + UDFLib::TABLE_ARG_NAME => 'tbl_prestudent', + UDFLib::PRIMARY_KEY_NAME => 'prestudent_id', + UDFLib::PRIMARY_KEY_VALUE => $zgvpruefung->prestudent_id, + UDFLib::UDFS_ARG_NAME => $zgvpruefung->prestudentUdfs + ) + ); + } + ?>
Date: Wed, 29 Jan 2020 12:09:10 +0100 Subject: [PATCH 007/216] Added border to tabulator / tabulator header cells --- public/css/Tabulator.css | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/public/css/Tabulator.css b/public/css/Tabulator.css index eac315f93..ffbeed606 100644 --- a/public/css/Tabulator.css +++ b/public/css/Tabulator.css @@ -16,4 +16,18 @@ /* Avoid confusing color change when hovering over selected rows */ .tabulator-row.tabulator-selected:hover { background-color: #769bcc !important; +} + +/* Frame the table */ +.tabulator { + border: 1px solid lightgrey; + border-bottom: none; + margin-top: 20px; + border-top-left-radius: 0.5em; + border-top-right-radius: 0.5em; +} + +/* Frame the header cells */ +.tabulator-col:not(:first-of-type) { + border-left: 0.5px solid lightgrey; } \ No newline at end of file From bc1c33432f9ace5a0398bf195cd26c02814051a2 Mon Sep 17 00:00:00 2001 From: Cris Date: Thu, 30 Jan 2020 12:24:28 +0100 Subject: [PATCH 008/216] Avoid of triple points at end of header title (more space) --- public/css/Tabulator.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/public/css/Tabulator.css b/public/css/Tabulator.css index ffbeed606..718295f4e 100644 --- a/public/css/Tabulator.css +++ b/public/css/Tabulator.css @@ -30,4 +30,9 @@ /* Frame the header cells */ .tabulator-col:not(:first-of-type) { border-left: 0.5px solid lightgrey; +} + +/* More space for header title (avoids triple points at the end) */ +.tabulator .tabulator-header .tabulator-col .tabulator-col-content .tabulator-col-title { + overflow: initial; } \ No newline at end of file From 3b2b279bf99b4b1e23fdbd439d90c32c82860ef1 Mon Sep 17 00:00:00 2001 From: Cris Date: Thu, 30 Jan 2020 12:27:13 +0100 Subject: [PATCH 009/216] Changed default visibility / order of columns Now fitted to the users primary needs. Columns can be displayed/hidden via Columnpicker by user afterwards. --- .../lehrauftrag/acceptLehrauftragData.php | 35 ++++++------ .../lehrauftrag/approveLehrauftragData.php | 40 +++++++------- .../lehrauftrag/orderLehrauftragData.php | 55 ++++++++++--------- 3 files changed, 69 insertions(+), 61 deletions(-) diff --git a/application/views/lehre/lehrauftrag/acceptLehrauftragData.php b/application/views/lehre/lehrauftrag/acceptLehrauftragData.php index 08cc94e5f..3211e86a9 100644 --- a/application/views/lehre/lehrauftrag/acceptLehrauftragData.php +++ b/application/views/lehre/lehrauftrag/acceptLehrauftragData.php @@ -9,19 +9,19 @@ $query = ' SELECT /* provide extra row index for tabulator, because no other column has unique ids */ ROW_NUMBER() OVER () AS "row_index", + auftrag, + stg_typ_kurzbz, + gruppe, + typ, lehreinheit_id, lehrveranstaltung_id, projektarbeit_id, studiensemester_kurzbz, studiengang_kz, - stg_typ_kurzbz, semester, orgform_kurzbz, person_id, - typ, - auftrag, lv_oe_kurzbz, - gruppe, stunden, betrag, vertrag_id, @@ -299,19 +299,19 @@ $filterWidgetArray = array( 'reloadDataset' => true, // reload query on page refresh 'columnsAliases' => array( // TODO: use phrasen 'Status', // alias for row_index, because row_index is formatted to display the status icons + 'LV- / Projektbezeichnung', + 'Studiengang', + 'Gruppe', + 'Typ', 'LV-Teil', 'LV-ID', 'PA-ID', 'Studiensemester', 'Studiengang-KZ', - 'Studiengang', 'Semester', 'OrgForm', 'Person-ID', - 'Typ', - 'LV- / Projektbezeichnung', 'Organisationseinheit', - 'Gruppe', 'Stunden', 'Betrag', 'Vertrag-ID', @@ -365,19 +365,22 @@ $filterWidgetArray = array( }', // tabulator properties 'datasetRepFieldsDefs' => '{ row_index: {visible:false}, // necessary for row indexing - lehreinheit_id: {headerFilter:"input", bottomCalc:"count", bottomCalcFormatter:function(cell){return "Anzahl: " + cell.getValue();}}, - lehrveranstaltung_id: {headerFilter:"input"}, + auftrag: { + headerFilter:"input", widthGrow: 3, + bottomCalc:"count", bottomCalcFormatter:function(cell){return "Anzahl: " + cell.getValue();} + }, + stg_typ_kurzbz: {headerFilter:"input"}, + gruppe: {headerFilter:"input"}, + typ: {headerFilter:"input"}, + lehreinheit_id: {visible: false, headerFilter:"input"}, + lehrveranstaltung_id: {visible: false, headerFilter:"input"}, projektarbeit_id: {visible: false, headerFilter:"input"}, studiensemester_kurzbz: {visible: false, headerFilter:"input"}, studiengang_kz: {visible: false, headerFilter:"input"}, - stg_typ_kurzbz: {headerFilter:"input"}, semester: {headerFilter:"input"}, - orgform_kurzbz: {headerFilter:"input"}, + orgform_kurzbz: {visible: false, headerFilter:"input"}, person_id: {visible: false, headerFilter:"input"}, - typ: {headerFilter:"input"}, - auftrag: {headerFilter:"input"}, - lv_oe_kurzbz: {headerFilter:"input"}, - gruppe: {headerFilter:"input"}, + lv_oe_kurzbz: {visible: false, headerFilter:"input"}, stunden: {align:"right", formatter: form_formatNulltoStringNumber, formatterParams:{precision:1}, headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator, bottomCalc:"sum", bottomCalcParams:{precision:1} diff --git a/application/views/lehre/lehrauftrag/approveLehrauftragData.php b/application/views/lehre/lehrauftrag/approveLehrauftragData.php index 111e7bd01..4ad03e138 100644 --- a/application/views/lehre/lehrauftrag/approveLehrauftragData.php +++ b/application/views/lehre/lehrauftrag/approveLehrauftragData.php @@ -9,20 +9,20 @@ SELECT /* provide extra row index for tabulator, because no other column has unique ids */ ROW_NUMBER() OVER () AS "row_index", personalnummer, + auftrag, + stg_typ_kurzbz, + gruppe, + typ, lehreinheit_id, lehrveranstaltung_id, lv_bezeichnung, projektarbeit_id, studiensemester_kurzbz, studiengang_kz, - stg_typ_kurzbz, semester, orgform_kurzbz, person_id, - typ, - auftrag, lv_oe_kurzbz, - gruppe, lektor, stunden, betrag, @@ -308,20 +308,20 @@ $filterWidgetArray = array( 'columnsAliases' => array( // TODO: use phrasen 'Status', // alias for row_index, because row_index is formatted to display the status icons 'Personalnummer', + 'LV- / Projektbezeichnung', + 'Studiengang', + 'Gruppe', + 'Typ', 'LV-Teil', 'LV-ID', 'LV', 'PA-ID', 'Studiensemester', 'Studiengang-KZ', - 'Studiengang', 'Semester', 'OrgForm', 'Person-ID', - 'Typ', - 'LV- / Projektbezeichnung', 'Organisationseinheit', - 'Gruppe', 'Lektor', 'Stunden', 'Betrag', @@ -384,22 +384,24 @@ $filterWidgetArray = array( // column status is built dynamically in funcTableBuilt(), row_index: {visible:false}, // necessary for row indexing personalnummer: {visible: false, headerFilter:"input"}, - lehreinheit_id: {headerFilter:"input", bottomCalc:"count", - bottomCalcFormatter:function(cell){return "Anzahl: " + cell.getValue();},}, - lehrveranstaltung_id: {headerFilter:"input"}, + auftrag: { + headerFilter:"input", widthGrow: 2, + bottomCalc:"count", bottomCalcFormatter:function(cell){return "Anzahl: " + cell.getValue();} + }, + stg_typ_kurzbz: {headerFilter:"input"}, + gruppe: {headerFilter:"input"}, + typ: {headerFilter:"input"}, + lehreinheit_id: {visible: false, headerFilter:"input"}, + lehrveranstaltung_id: {visible: false, headerFilter:"input"}, lv_bezeichnung: {visible: false, headerFilter:"input"}, projektarbeit_id: {visible: false, headerFilter:"input"}, - studiensemester_kurzbz: {headerFilter:"input"}, + studiensemester_kurzbz: {visible: false, headerFilter:"input"}, studiengang_kz: {visible: false, headerFilter:"input"}, - stg_typ_kurzbz: {headerFilter:"input"}, semester: {headerFilter:"input"}, - orgform_kurzbz: {headerFilter:"input"}, + orgform_kurzbz: {visible: false, headerFilter:"input"}, person_id: {visible: false, headerFilter:"input"}, - typ: {headerFilter:"input"}, - auftrag: {headerFilter:"input"}, - lv_oe_kurzbz: {headerFilter:"input"}, - gruppe: {headerFilter:"input"}, - lektor: {headerFilter:"input"}, + lv_oe_kurzbz: {visible: false, headerFilter:"input"}, + lektor: {headerFilter:"input", widthGrow: 2}, stunden: {align:"right", formatter: form_formatNulltoStringNumber, formatterParams:{precision:1}, headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator, bottomCalc:"sum", bottomCalcParams:{precision:1}}, diff --git a/application/views/lehre/lehrauftrag/orderLehrauftragData.php b/application/views/lehre/lehrauftrag/orderLehrauftragData.php index d78f5ecfe..5576e7886 100644 --- a/application/views/lehre/lehrauftrag/orderLehrauftragData.php +++ b/application/views/lehre/lehrauftrag/orderLehrauftragData.php @@ -9,13 +9,16 @@ SELECT /* provide extra row index for tabulator, because no other column has unique ids */ ROW_NUMBER() OVER () AS "row_index", personalnummer, + auftrag, + stg_typ_kurzbz, + gruppe, + typ, lehreinheit_id, lehrveranstaltung_id, lv_bezeichnung, projektarbeit_id, studiensemester_kurzbz, studiengang_kz, - stg_typ_kurzbz, semester, /* get valid STPL(s), to which the lehrveranstaltung is assigned to (can be more) */ /* therefore join over lv, studiensemester and semester */ @@ -49,10 +52,7 @@ SELECT ) AS "studienplan_bezeichnung", orgform_kurzbz, person_id, - typ, - auftrag, lv_oe_kurzbz, - gruppe, lektor, stunden, stundensatz, @@ -340,21 +340,22 @@ $filterWidgetArray = array( 'columnsAliases' => array( // TODO: use phrasen 'Status', // alias for row_index, because row_index is formatted to display the status icons 'Personalnummer', + 'LV- / Projektbezeichnung', + 'Studiengang', + 'Gruppe', + 'Typ', 'LV-Teil', 'LV-ID', 'LV', 'PA-ID', 'Studiensemester', 'Studiengang-KZ', - 'Studiengang', + 'Semester', 'Studienplan', 'OrgForm', 'Person-ID', - 'Typ', - 'LV- / Projektbezeichnung', 'Organisationseinheit', - 'Gruppe', 'Lektor', 'Stunden', 'Stundensatz', @@ -419,29 +420,31 @@ $filterWidgetArray = array( // column status is built dynamically in funcTableBuilt() row_index: {visible: false}, personalnummer: {visible: false, headerFilter:"input"}, - lehreinheit_id: {headerFilter:"input", bottomCalc:"count", minWidth: 115, - bottomCalcFormatter:function(cell){return "Anzahl: " + cell.getValue();}}, - lehrveranstaltung_id: {headerFilter:"input"}, + auftrag: { + headerFilter:"input", widthGrow: 2, + bottomCalc:"count", bottomCalcFormatter:function(cell){return "Anzahl: " + cell.getValue();} + }, + stg_typ_kurzbz: {headerFilter:"input"}, + gruppe: {headerFilter:"input"}, + typ: {headerFilter:"input"}, + lehreinheit_id: {visible: false, headerFilter:"input"}, + lehrveranstaltung_id: {visible: false, headerFilter:"input"}, lv_bezeichnung: {visible: false, headerFilter:"input"}, projektarbeit_id: {visible: false, headerFilter:"input"}, - studiensemester_kurzbz: {headerFilter:"input"}, + studiensemester_kurzbz: {visible: false, headerFilter:"input"}, studiengang_kz: {visible: false, headerFilter:"input"}, - stg_typ_kurzbz: {headerFilter:"input", minWidth: 70}, semester: {headerFilter:"input"}, - studienplan_bezeichnung: {headerFilter:"input"}, - orgform_kurzbz: {headerFilter:"input"}, + studienplan_bezeichnung: {visible: false, headerFilter:"input"}, + orgform_kurzbz: {visible: false, headerFilter:"input", widthGrow: 2}, person_id: {visible: false, headerFilter:"input"}, - typ: {headerFilter:"input", minWidth:100}, - auftrag: {headerFilter:"input", minWidth:280}, - lv_oe_kurzbz: {headerFilter:"input", minWidth:80}, - gruppe: {headerFilter:"input", minWidth:120}, - lektor: {headerFilter:"input", widthGrow: 3}, - stunden: {align:"right", minWidth: 80, formatter: form_formatNulltoStringNumber, formatterParams:{precision:1}, + lv_oe_kurzbz: {headerFilter:"input"}, + lektor: {headerFilter:"input", widthGrow: 2}, + stunden: {align:"right", formatter: form_formatNulltoStringNumber, formatterParams:{precision:1}, headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator, bottomCalc:"sum", bottomCalcParams:{precision:1}}, - stundensatz: {visible: false, align:"right", minWidth: 100, formatter: form_formatNulltoStringNumber, + stundensatz: {visible: false, align:"right", formatter: form_formatNulltoStringNumber, headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator}, - betrag: {align:"right", minWidth: 120, formatter: form_formatNulltoStringNumber, + betrag: {align:"right", formatter: form_formatNulltoStringNumber, headerFilter:"input", headerFilterFunc: hf_filterStringnumberWithOperator, bottomCalc:"sum", bottomCalcParams:{precision:2}, bottomCalcFormatter:"money", bottomCalcFormatterParams:{decimal: ",", thousand: ".", symbol:"€"}}, @@ -449,9 +452,9 @@ $filterWidgetArray = array( vertrag_stunden: {visible: false}, vertrag_betrag: {visible: false}, mitarbeiter_uid: {visible: false, headerFilter:"input"}, - bestellt: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: bestellt_tooltip, minWidth: 100}, - erteilt: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: erteilt_tooltip, minWidth: 100}, - akzeptiert: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: akzeptiert_tooltip, minWidth: 100}, + bestellt: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: bestellt_tooltip}, + erteilt: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: erteilt_tooltip}, + akzeptiert: {align:"center", headerFilter:"input", mutator: mut_formatStringDate, tooltip: akzeptiert_tooltip}, bestellt_von: {visible: false, headerFilter:"input"}, erteilt_von: {visible: false, headerFilter:"input"}, akzeptiert_von: {visible: false, headerFilter:"input"} From 8c36b0b67a5a1303de3a89ccf0b1f527f837af37 Mon Sep 17 00:00:00 2001 From: Cris Date: Thu, 30 Jan 2020 12:28:51 +0100 Subject: [PATCH 010/216] =?UTF-8?q?Reduced=20default=20minimum=20size=20of?= =?UTF-8?q?=20columns=20in=20Stornierte=20Lehrauftr=C3=A4ge?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../views/lehre/lehrauftrag/cancelledLehrauftragData.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/application/views/lehre/lehrauftrag/cancelledLehrauftragData.php b/application/views/lehre/lehrauftrag/cancelledLehrauftragData.php index 20629cb84..2dbecbb69 100644 --- a/application/views/lehre/lehrauftrag/cancelledLehrauftragData.php +++ b/application/views/lehre/lehrauftrag/cancelledLehrauftragData.php @@ -87,12 +87,12 @@ $tableWidgetArray = array( 'datasetRepFieldsDefs' => '{ vertrag_id: {visible: false}, vertragsstunden_studiensemester_kurzbz: {visible: false, widthShrink:1}, - vertragstyp_kurzbz: {minWidth: 300}, - bezeichnung: {minWidth: 400}, + vertragstyp_kurzbz: {minWidth: 200}, + bezeichnung: {minWidth: 200}, vertragsstunden: { align:"right", formatter: form_formatNulltoStringNumber, formatterParams:{precision:1}, bottomCalc:"sum", bottomCalcParams:{precision:1}, - minWidth: 300 + minWidth: 200 }, betrag: { align:"right", formatter: form_formatNulltoStringNumber, From e1df2cbf23ed86db046736cc1514d46e72bd47bc Mon Sep 17 00:00:00 2001 From: Cris Date: Thu, 30 Jan 2020 12:30:26 +0100 Subject: [PATCH 011/216] Added tooltips on column headers (displaying title) in TableWidget Now this is a standard behaviour of TableWidget. --- public/js/TableWidget.js | 1 + 1 file changed, 1 insertion(+) diff --git a/public/js/TableWidget.js b/public/js/TableWidget.js index 575ad6b12..7c1b01b93 100644 --- a/public/js/TableWidget.js +++ b/public/js/TableWidget.js @@ -522,6 +522,7 @@ var FHC_TableWidget = { options.columns = arrayTabulatorColumns; options.data = data.dataset; + options.tooltipsHeader = true; // set header tooltip with column title options.rowSelectionChanged = function(data, rows){ _func_rowSelectionChanged(data, rows); }; From 6897ccdd6b4973e260ebbb355c0f751dc0dc7f10 Mon Sep 17 00:00:00 2001 From: Cris Date: Thu, 30 Jan 2020 12:43:50 +0100 Subject: [PATCH 012/216] Moved empty table placeholder text to TableWidget Now this is a standard behaviour of TableWidget. --- .../views/lehre/lehrauftrag/acceptLehrauftragData.php | 1 - .../views/lehre/lehrauftrag/approveLehrauftragData.php | 1 - .../views/lehre/lehrauftrag/cancelledLehrauftragData.php | 1 - .../views/lehre/lehrauftrag/orderLehrauftragData.php | 1 - public/js/TableWidget.js | 8 ++++++++ public/js/lehre/lehrauftrag/acceptLehrauftrag.js | 6 ------ public/js/lehre/lehrauftrag/approveLehrauftrag.js | 6 ------ public/js/lehre/lehrauftrag/orderLehrauftrag.js | 6 ------ 8 files changed, 8 insertions(+), 22 deletions(-) diff --git a/application/views/lehre/lehrauftrag/acceptLehrauftragData.php b/application/views/lehre/lehrauftrag/acceptLehrauftragData.php index 3211e86a9..3fa2c603c 100644 --- a/application/views/lehre/lehrauftrag/acceptLehrauftragData.php +++ b/application/views/lehre/lehrauftrag/acceptLehrauftragData.php @@ -332,7 +332,6 @@ $filterWidgetArray = array( persistenceID: "acceptLehrauftrag", // TableWidget unique id to store persistence data seperately for multiple tables autoResize: false, // prevent auto resizing of table (false to allow adapting table size when cols are (de-)activated movableColumns: true, // allows changing column - placeholder: func_placeholder(), headerFilterPlaceholder: " ", index: "row_index", // assign specific column as unique id (important for row indexing) selectable: true, // allow row selection diff --git a/application/views/lehre/lehrauftrag/approveLehrauftragData.php b/application/views/lehre/lehrauftrag/approveLehrauftragData.php index 4ad03e138..7cc5bd533 100644 --- a/application/views/lehre/lehrauftrag/approveLehrauftragData.php +++ b/application/views/lehre/lehrauftrag/approveLehrauftragData.php @@ -344,7 +344,6 @@ $filterWidgetArray = array( persistenceID: "approveLehrauftrag", // TableWidget unique id to store persistence data seperately for multiple tables autoResize: false, // prevent auto resizing of table (false to allow adapting table size when cols are (de-)activated movableColumns: true, // allows changing column - placeholder: func_placeholder(), headerFilterPlaceholder: " ", groupBy:"lehrveranstaltung_id", groupToggleElement:"header", //toggle group on click anywhere in the group header diff --git a/application/views/lehre/lehrauftrag/cancelledLehrauftragData.php b/application/views/lehre/lehrauftrag/cancelledLehrauftragData.php index 2dbecbb69..cbf7d8b55 100644 --- a/application/views/lehre/lehrauftrag/cancelledLehrauftragData.php +++ b/application/views/lehre/lehrauftrag/cancelledLehrauftragData.php @@ -70,7 +70,6 @@ $tableWidgetArray = array( persistenceID: "cancelledLehrauftrag", // TableWidget unique id to store persistence data seperately for multiple tables autoResize: false, // prevent auto resizing of table (false to allow adapting table size when cols are (de-)activated movableColumns: true, // allows changing column - placeholder: func_placeholder(), rowFormatter:function(row){ func_rowFormatter(row); }, diff --git a/application/views/lehre/lehrauftrag/orderLehrauftragData.php b/application/views/lehre/lehrauftrag/orderLehrauftragData.php index 5576e7886..f4a122deb 100644 --- a/application/views/lehre/lehrauftrag/orderLehrauftragData.php +++ b/application/views/lehre/lehrauftrag/orderLehrauftragData.php @@ -379,7 +379,6 @@ $filterWidgetArray = array( persistenceID: "orderLehrauftrag", // TableWidget unique id to store persistence data seperately for multiple tables autoResize: false, // prevent auto resizing of table (false to allow adapting table size when cols are (de-)activated movableColumns: true, // allows changing column order - placeholder: func_placeholder(), // shown on empty table (no data) headerFilterPlaceholder: " ", groupBy:"lehrveranstaltung_id", groupToggleElement:"header", //toggle group on click anywhere in the group header diff --git a/public/js/TableWidget.js b/public/js/TableWidget.js index 7c1b01b93..7b914cc60 100644 --- a/public/js/TableWidget.js +++ b/public/js/TableWidget.js @@ -523,6 +523,7 @@ var FHC_TableWidget = { options.columns = arrayTabulatorColumns; options.data = data.dataset; options.tooltipsHeader = true; // set header tooltip with column title + options.placeholder = _func_placeholder(); // display text when table is empty options.rowSelectionChanged = function(data, rows){ _func_rowSelectionChanged(data, rows); }; @@ -718,6 +719,13 @@ function _func_columnVisibilityChanged(column, visible){ table.redraw(); } +/* + * Displays text when table is empty + */ +function _func_placeholder(){ + return "

Keine Daten vorhanden.

"; +} + // Returns TableWidget Header HTML (download-, setting button...) function _renderTabulatorHeaderHTML(tableWidgetDiv){ diff --git a/public/js/lehre/lehrauftrag/acceptLehrauftrag.js b/public/js/lehre/lehrauftrag/acceptLehrauftrag.js index c3d89ac52..341a325fc 100644 --- a/public/js/lehre/lehrauftrag/acceptLehrauftrag.js +++ b/public/js/lehre/lehrauftrag/acceptLehrauftrag.js @@ -98,12 +98,6 @@ function func_height(table){ return $(window).height() * 0.50; } -// Displays text when table is empty -function func_placeholder() -{ - return "

Keine Daten vorhanden.

"; -} - // Formats the rows function func_rowFormatter(row){ var bestellt = row.getData().bestellt; diff --git a/public/js/lehre/lehrauftrag/approveLehrauftrag.js b/public/js/lehre/lehrauftrag/approveLehrauftrag.js index 29e2d9651..7326a95c1 100644 --- a/public/js/lehre/lehrauftrag/approveLehrauftrag.js +++ b/public/js/lehre/lehrauftrag/approveLehrauftrag.js @@ -111,12 +111,6 @@ function func_height(table){ return $(window).height() * 0.50; } -// Displays text when table is empty -function func_placeholder() -{ - return "

Keine Daten vorhanden.

"; -} - // Formats the group header function func_groupHeader(data){ return data[0].lv_bezeichnung + "  " + ' ( LV-ID: ' + data[0].lehrveranstaltung_id + ' )'; // change name to lehrveranstaltung; diff --git a/public/js/lehre/lehrauftrag/orderLehrauftrag.js b/public/js/lehre/lehrauftrag/orderLehrauftrag.js index 6471d988f..379a02b6a 100644 --- a/public/js/lehre/lehrauftrag/orderLehrauftrag.js +++ b/public/js/lehre/lehrauftrag/orderLehrauftrag.js @@ -116,12 +116,6 @@ function func_height(table){ return $(window).height() * 0.50; } -// Displays text when table is empty -function func_placeholder() -{ - return "

Keine Daten vorhanden.

"; -} - // Formats the group header function func_groupHeader(data) { return data[0].lv_bezeichnung + "  " + ' ( LV-ID: ' + data[0].lehrveranstaltung_id + ' )'; // change name to lehrveranstaltung; From bce7f60df43509875467378ecf89c4ec7e986bbc Mon Sep 17 00:00:00 2001 From: Cris Date: Thu, 30 Jan 2020 13:22:49 +0100 Subject: [PATCH 013/216] Moved layout options to TableWidget Now this is a standard behaviour of TableWidget. --- .../views/lehre/lehrauftrag/acceptLehrauftragData.php | 3 --- .../views/lehre/lehrauftrag/approveLehrauftragData.php | 3 --- .../views/lehre/lehrauftrag/cancelledLehrauftragData.php | 6 ------ .../views/lehre/lehrauftrag/orderLehrauftragData.php | 3 --- public/js/TableWidget.js | 7 +++++-- 5 files changed, 5 insertions(+), 17 deletions(-) diff --git a/application/views/lehre/lehrauftrag/acceptLehrauftragData.php b/application/views/lehre/lehrauftrag/acceptLehrauftragData.php index 3fa2c603c..7b9443edb 100644 --- a/application/views/lehre/lehrauftrag/acceptLehrauftragData.php +++ b/application/views/lehre/lehrauftrag/acceptLehrauftragData.php @@ -328,10 +328,7 @@ $filterWidgetArray = array( 'datasetRepOptions' => '{ height: func_height(this), layout: "fitColumns", // fit columns to width of table - persistentLayout:true, // enables persistence (default store in localStorage if available, else in cookie) - persistenceID: "acceptLehrauftrag", // TableWidget unique id to store persistence data seperately for multiple tables autoResize: false, // prevent auto resizing of table (false to allow adapting table size when cols are (de-)activated - movableColumns: true, // allows changing column headerFilterPlaceholder: " ", index: "row_index", // assign specific column as unique id (important for row indexing) selectable: true, // allow row selection diff --git a/application/views/lehre/lehrauftrag/approveLehrauftragData.php b/application/views/lehre/lehrauftrag/approveLehrauftragData.php index 7cc5bd533..5e1ae27b6 100644 --- a/application/views/lehre/lehrauftrag/approveLehrauftragData.php +++ b/application/views/lehre/lehrauftrag/approveLehrauftragData.php @@ -340,10 +340,7 @@ $filterWidgetArray = array( height: func_height(this), layout: "fitColumns", // fit columns to width of table layoutColumnsOnNewData: true, // ajust column widths to the data each time TableWidget is loaded - persistentLayout:true, // enables persistence (default store in localStorage if available, else in cookie) - persistenceID: "approveLehrauftrag", // TableWidget unique id to store persistence data seperately for multiple tables autoResize: false, // prevent auto resizing of table (false to allow adapting table size when cols are (de-)activated - movableColumns: true, // allows changing column headerFilterPlaceholder: " ", groupBy:"lehrveranstaltung_id", groupToggleElement:"header", //toggle group on click anywhere in the group header diff --git a/application/views/lehre/lehrauftrag/cancelledLehrauftragData.php b/application/views/lehre/lehrauftrag/cancelledLehrauftragData.php index cbf7d8b55..ba7b0d4f6 100644 --- a/application/views/lehre/lehrauftrag/cancelledLehrauftragData.php +++ b/application/views/lehre/lehrauftrag/cancelledLehrauftragData.php @@ -64,12 +64,6 @@ $tableWidgetArray = array( 'Storniert am' ), 'datasetRepOptions' => '{ - layout: "fitColumns", // fit columns to width of table - layoutColumnsOnNewData: true, // ajust column widths to the data each time TableWidget is loaded - persistentLayout: true, // enables persistence (default store in localStorage if available, else in cookie) - persistenceID: "cancelledLehrauftrag", // TableWidget unique id to store persistence data seperately for multiple tables - autoResize: false, // prevent auto resizing of table (false to allow adapting table size when cols are (de-)activated - movableColumns: true, // allows changing column rowFormatter:function(row){ func_rowFormatter(row); }, diff --git a/application/views/lehre/lehrauftrag/orderLehrauftragData.php b/application/views/lehre/lehrauftrag/orderLehrauftragData.php index f4a122deb..ca671fbd4 100644 --- a/application/views/lehre/lehrauftrag/orderLehrauftragData.php +++ b/application/views/lehre/lehrauftrag/orderLehrauftragData.php @@ -375,10 +375,7 @@ $filterWidgetArray = array( height: func_height(this), layout:"fitColumns", // fit columns to width of table layoutColumnsOnNewData: true, // ajust column widths to the data each time TableWidget is loaded - persistentLayout:true, // enables persistence (default store in localStorage if available, else in cookie) - persistenceID: "orderLehrauftrag", // TableWidget unique id to store persistence data seperately for multiple tables autoResize: false, // prevent auto resizing of table (false to allow adapting table size when cols are (de-)activated - movableColumns: true, // allows changing column order headerFilterPlaceholder: " ", groupBy:"lehrveranstaltung_id", groupToggleElement:"header", //toggle group on click anywhere in the group header diff --git a/public/js/TableWidget.js b/public/js/TableWidget.js index 7b914cc60..204d69280 100644 --- a/public/js/TableWidget.js +++ b/public/js/TableWidget.js @@ -522,8 +522,11 @@ var FHC_TableWidget = { options.columns = arrayTabulatorColumns; options.data = data.dataset; - options.tooltipsHeader = true; // set header tooltip with column title - options.placeholder = _func_placeholder(); // display text when table is empty + options.persistentLayout = true; // enables persistence (default store in localStorage if available, else in cookie) + options.persistenceID = data.tableUniqueId; // TableWidget unique id to store persistence data seperately for multiple tables + options.movableColumns = true; // allows changing column order + options.tooltipsHeader = true; // set header tooltip with column title + options.placeholder = _func_placeholder(); // display text when table is empty options.rowSelectionChanged = function(data, rows){ _func_rowSelectionChanged(data, rows); }; From b2542b5fcca581f37a9f9ef1794009edefd06e09 Mon Sep 17 00:00:00 2001 From: Cris Date: Thu, 30 Jan 2020 17:09:31 +0100 Subject: [PATCH 014/216] Added HELP button and collapsable help-info to TableWidget [ALPHA VERSION] Now this is a standard behaviour of TableWidget. Removed also table related help information from general Hilfe-zu-dieser-Seite help. [ALPHA VERSION]: minor issue to be fixed: button color not toggling correctly when opening help then settings (and way round) --- .../lehre/lehrauftrag/acceptLehrauftrag.php | 22 ----- .../lehre/lehrauftrag/approveLehrauftrag.php | 22 ----- .../lehre/lehrauftrag/orderLehrauftrag.php | 23 ------ public/css/Tabulator.css | 1 - public/js/TableWidget.js | 82 ++++++++++++++++++- 5 files changed, 81 insertions(+), 69 deletions(-) diff --git a/application/views/lehre/lehrauftrag/acceptLehrauftrag.php b/application/views/lehre/lehrauftrag/acceptLehrauftrag.php index 14ebacecb..15de019e5 100644 --- a/application/views/lehre/lehrauftrag/acceptLehrauftrag.php +++ b/application/views/lehre/lehrauftrag/acceptLehrauftrag.php @@ -83,28 +83,6 @@ $this->load->view(

- -

Auswahl

-
-
    -
  • Einzeln auswählen: Strg + Klick auf einzelne Zeile(n)
  • -
  • Bereich auswählen: Shift + Klick auf Anfangs- und Endzeile
  • -
  • Alle auswählen: Button 'Alle auswählen'
  • -
-
-
- -

Ansicht

-
- Spaltenbreite verändern -

- Um die Spaltenbreite zu verändern, fährt man im Spaltenkopf langsam mit dem Mauszeiger auf - den rechten Rand der entprechenden Spalte.
- Sobald sich der Mauszeiger in einen Doppelpfeil verwandelt, wird die Maustaste geklickt und - mit gedrückter Maustaste die Spalte nach rechts erweitert oder nach links verkleinert. -

-
-
diff --git a/application/views/lehre/lehrauftrag/approveLehrauftrag.php b/application/views/lehre/lehrauftrag/approveLehrauftrag.php index f36ae7dc7..ed1852654 100644 --- a/application/views/lehre/lehrauftrag/approveLehrauftrag.php +++ b/application/views/lehre/lehrauftrag/approveLehrauftrag.php @@ -123,28 +123,6 @@ $this->load->view(
-

Auswahl

-
-
    -
  • Einzeln auswählen: Strg + Klick auf einzelne Zeile(n)
  • -
  • Bereich auswählen: Shift + Klick auf Anfangs- und Endzeile
  • -
  • Alle auswählen: Button 'Alle auswählen'
  • -
-
-
- -

Ansicht

-
- Spaltenbreite verändern -

- Um die Spaltenbreite zu verändern, fährt man im Spaltenkopf langsam mit dem Mauszeiger auf - den rechten Rand der entprechenden Spalte.
- Sobald sich der Mauszeiger in einen Doppelpfeil verwandelt, wird die Maustaste geklickt und - mit gedrückter Maustaste die Spalte nach rechts erweitert oder nach links verkleinert. -

-
-
- diff --git a/application/views/lehre/lehrauftrag/orderLehrauftrag.php b/application/views/lehre/lehrauftrag/orderLehrauftrag.php index 27793e8ba..1e79bee0d 100644 --- a/application/views/lehre/lehrauftrag/orderLehrauftrag.php +++ b/application/views/lehre/lehrauftrag/orderLehrauftrag.php @@ -124,29 +124,6 @@ $this->load->view(
- -

Auswahl

-
-
    -
  • Einzeln auswählen: Strg + Klick auf einzelne Zeile(n)
  • -
  • Bereich auswählen: Shift + Klick auf Anfangs- und Endzeile
  • -
  • Alle auswählen: Button 'Alle auswählen'
  • -
-
-
- -

Ansicht

-
- Spaltenbreite verändern -

- Um die Spaltenbreite zu verändern, fährt man im Spaltenkopf langsam mit dem Mauszeiger auf - den rechten Rand der entprechenden Spalte.
- Sobald sich der Mauszeiger in einen Doppelpfeil verwandelt, wird die Maustaste geklickt und - mit gedrückter Maustaste die Spalte nach rechts erweitert oder nach links verkleinert. -

-
-
- diff --git a/public/css/Tabulator.css b/public/css/Tabulator.css index 718295f4e..0545101c9 100644 --- a/public/css/Tabulator.css +++ b/public/css/Tabulator.css @@ -22,7 +22,6 @@ .tabulator { border: 1px solid lightgrey; border-bottom: none; - margin-top: 20px; border-top-left-radius: 0.5em; border-top-right-radius: 0.5em; } diff --git a/public/js/TableWidget.js b/public/js/TableWidget.js index 204d69280..bc49b8c69 100644 --- a/public/js/TableWidget.js +++ b/public/js/TableWidget.js @@ -204,6 +204,32 @@ var FHC_TableWidget = { tableWidgetDiv.find("#tableWidgetTabulator").tabulator("download", "csv", "data.csv", {bom:true}); }) + // Click-Event to collapse help div + tableWidgetDiv.find('#help').on('click', function() + { + + //... auch unteren event für settings hier hinein + $('#tabulatorHelp-' + tableUniqueId).collapse('toggle'); + + $(this).toggleClass('active focus'); + + // De/activate and un/focus on clicked settings button + if(!$(this).hasClass('active focus')) + { + $(this).css({'background-color': 'white', 'border-color' : '#ccc', 'outline': 'none'}); + } + else + { + $(this).css({'background-color': '#e6e6e6'}); + } + + if($('#tabulatorSettings-' + tableUniqueId).hasClass('collapse in')) + { + $('#tabulatorSettings-' + tableUniqueId).removeClass('in'); + // $('#settings').toggleClass('active focus'); + } + }) + // Click-Event to collapse settings div tableWidgetDiv.find('#settings').on('click', function() { @@ -222,6 +248,12 @@ var FHC_TableWidget = { { $(this).css({'background-color': '#e6e6e6'}); } + + if($('#tabulatorHelp-' + tableUniqueId).hasClass('collapse in')) + { + $('#tabulatorHelp-' + tableUniqueId).removeClass('in'); + // $('#help').toggleClass('active focus'); + } }) /** @@ -738,7 +770,8 @@ function _renderTabulatorHeaderHTML(tableWidgetDiv){ tabulatorHeaderHTML += ''; @@ -751,6 +784,8 @@ function _renderTabulatorHeaderCollapseHTML(tableWidgetDiv){ var tableUniqueId = tableWidgetDiv.attr('tableUniqueId'); var tabulatorHeaderCollapseHTML = ''; + + // CollapseHTML 'Settings' tabulatorHeaderCollapseHTML += '
'; tabulatorHeaderCollapseHTML += '
'; tabulatorHeaderCollapseHTML += '
'; @@ -799,6 +834,51 @@ function _renderTabulatorHeaderCollapseHTML(tableWidgetDiv){ tabulatorHeaderCollapseHTML += '
'; // end col tabulatorHeaderCollapseHTML += '
'; // end row + // CollapseHTML 'Help' + tabulatorHeaderCollapseHTML += '
'; + tabulatorHeaderCollapseHTML += '
'; + tabulatorHeaderCollapseHTML += '
'; + tabulatorHeaderCollapseHTML += '
'; + + tabulatorHeaderCollapseHTML += '

Tabelleneinstellungen

'; + tabulatorHeaderCollapseHTML += '
'; + tabulatorHeaderCollapseHTML += 'Spalten ein- und ausblenden'; + tabulatorHeaderCollapseHTML += '

'; + tabulatorHeaderCollapseHTML += '

    '; + tabulatorHeaderCollapseHTML += '
  • Mit einem Klick auf ' + + 'werden die Einstellungen geöffnet.
  • '; + tabulatorHeaderCollapseHTML += '
  • Auf Spalteneinstellungen klicken
  • '; + tabulatorHeaderCollapseHTML += '
  • Durch (wiederholtes) Klicken auf die einzelnen Spaltennamen können ' + + 'diese in der Tabelle beliebig oft aktiviert / deaktiviert werden.
  • '; + tabulatorHeaderCollapseHTML += '
  • Mit einem Klick auf ' + + 'werden die Einstellungen wieder geschlossen.
  • '; + tabulatorHeaderCollapseHTML += '
'; + tabulatorHeaderCollapseHTML += '

'; + tabulatorHeaderCollapseHTML += 'Spaltenbreite verändern'; + tabulatorHeaderCollapseHTML += '

Um die Spaltenbreite zu verändern, fährt man im Spaltenkopf langsam ' + + 'mit dem Mauszeiger auf den rechten Rand der entprechenden Spalte.
' + + 'Sobald sich der Mauszeiger in einen Doppelpfeil verwandelt, wird die Maustaste geklickt und ' + + 'mit gedrückter Maustaste die Spalte nach rechts erweitert oder nach links verkleinert.'; + tabulatorHeaderCollapseHTML += '

'; + tabulatorHeaderCollapseHTML += '
INFO: Alle individuellen Tabelleneinstellungen werden in ' + + 'Ihrem Browser Cache gespeichert. Wenn Sie Ihren Browser Cache löschen, werden Ihre Einstellungen zurückgesetzt und ' + + 'müssen gegebenenfalls neu eingestellt werden.'; + tabulatorHeaderCollapseHTML += '
'; + tabulatorHeaderCollapseHTML += '

'; // end panel-body + + tabulatorHeaderCollapseHTML += '

Zeilen auswählen

'; + tabulatorHeaderCollapseHTML += '
'; + tabulatorHeaderCollapseHTML += '
    '; + tabulatorHeaderCollapseHTML += '
  • Einzeln auswählen: Strg + Klick auf einzelne Zeile(n)
  • '; + tabulatorHeaderCollapseHTML += '
  • Bereich auswählen: Shift + Klick auf Anfangs- und Endzeile
  • '; + tabulatorHeaderCollapseHTML += '
  • Alle auswählen: Button \'Alle auswählen\'
  • '; + tabulatorHeaderCollapseHTML += '
'; + tabulatorHeaderCollapseHTML += '

'; // end panel-body + + tabulatorHeaderCollapseHTML += '
'; // end well + tabulatorHeaderCollapseHTML += '
'; // end col collapse + tabulatorHeaderCollapseHTML += '
'; // end row + return tabulatorHeaderCollapseHTML; } From 3a8e7427a7683f9413336e81ed078644ef814a35 Mon Sep 17 00:00:00 2001 From: Cris Date: Tue, 11 Feb 2020 08:59:23 +0100 Subject: [PATCH 015/216] Enhanced active status behaviour of button group Active status of button help / settings was not clear before. This is corrected now. --- public/js/TableWidget.js | 63 +++++++++++++++------------------------- 1 file changed, 24 insertions(+), 39 deletions(-) diff --git a/public/js/TableWidget.js b/public/js/TableWidget.js index bc49b8c69..eebe5265c 100644 --- a/public/js/TableWidget.js +++ b/public/js/TableWidget.js @@ -204,57 +204,40 @@ var FHC_TableWidget = { tableWidgetDiv.find("#tableWidgetTabulator").tabulator("download", "csv", "data.csv", {bom:true}); }) - // Click-Event to collapse help div + // Click-Event to toggle the collapsable help panel tableWidgetDiv.find('#help').on('click', function() { + // Hide the collapsable settings panel, if it actually shown + $('#tabulatorSettings-' + tableUniqueId).collapse('hide'); - //... auch unteren event für settings hier hinein + // Toggle the collapsable help panel $('#tabulatorHelp-' + tableUniqueId).collapse('toggle'); - - $(this).toggleClass('active focus'); - - // De/activate and un/focus on clicked settings button - if(!$(this).hasClass('active focus')) - { - $(this).css({'background-color': 'white', 'border-color' : '#ccc', 'outline': 'none'}); - } - else - { - $(this).css({'background-color': '#e6e6e6'}); - } - - if($('#tabulatorSettings-' + tableUniqueId).hasClass('collapse in')) - { - $('#tabulatorSettings-' + tableUniqueId).removeClass('in'); - // $('#settings').toggleClass('active focus'); - } }) - // Click-Event to collapse settings div + // Click-Event to toggle the collapsable settings panel tableWidgetDiv.find('#settings').on('click', function() { + // Hide the collapsable help panel, if it actually shown + $('#tabulatorHelp-' + tableUniqueId).collapse('hide'); - //... auch unteren event für settings hier hinein + // Toggle the collapsable settings panel $('#tabulatorSettings-' + tableUniqueId).collapse('toggle'); + }) - $(this).toggleClass('active focus'); - - // De/activate and un/focus on clicked settings button - if(!$(this).hasClass('active focus')) + /* Beautify button group behaviour + * Let buttons stay active even until they are clicked again to close the collapsable help- oder setting panels + * Also remove the disturbing button focus behaviour + */ + $(".btn-group > .btn").click(function(){ + if ($(this).hasClass("active")) { - $(this).css({'background-color': 'white', 'border-color' : '#ccc', 'outline': 'none'}); + $(this).removeClass('active').css('outline', 'none'); } else { - $(this).css({'background-color': '#e6e6e6'}); + $(this).addClass("active").css('outline', 'none').siblings().removeClass("active"); } - - if($('#tabulatorHelp-' + tableUniqueId).hasClass('collapse in')) - { - $('#tabulatorHelp-' + tableUniqueId).removeClass('in'); - // $('#help').toggleClass('active focus'); - } - }) + }); /** * Click-Event to select all rows @@ -774,6 +757,7 @@ function _renderTabulatorHeaderHTML(tableWidgetDiv){ tabulatorHeaderHTML += ''; tabulatorHeaderHTML += ''; tabulatorHeaderHTML += ''; + tabulatorHeaderHTML += '


'; return tabulatorHeaderHTML; } @@ -786,7 +770,6 @@ function _renderTabulatorHeaderCollapseHTML(tableWidgetDiv){ var tabulatorHeaderCollapseHTML = ''; // CollapseHTML 'Settings' - tabulatorHeaderCollapseHTML += '
'; tabulatorHeaderCollapseHTML += '
'; tabulatorHeaderCollapseHTML += '
'; tabulatorHeaderCollapseHTML += '
'; @@ -794,10 +777,13 @@ function _renderTabulatorHeaderCollapseHTML(tableWidgetDiv){ tabulatorHeaderCollapseHTML += '
'; tabulatorHeaderCollapseHTML += ''; // end panel-heading - tabulatorHeaderCollapseHTML += '
'; + tabulatorHeaderCollapseHTML += '
'; tabulatorHeaderCollapseHTML += '
'; tabulatorHeaderCollapseHTML += '
'; @@ -835,7 +821,6 @@ function _renderTabulatorHeaderCollapseHTML(tableWidgetDiv){ tabulatorHeaderCollapseHTML += '
'; // end row // CollapseHTML 'Help' - tabulatorHeaderCollapseHTML += '
'; tabulatorHeaderCollapseHTML += '
'; tabulatorHeaderCollapseHTML += '
'; tabulatorHeaderCollapseHTML += '
'; From 30c6f10d8091b8ce460e1b79c0052fae30f815e6 Mon Sep 17 00:00:00 2001 From: Paolo Date: Wed, 4 Mar 2020 15:54:23 +0100 Subject: [PATCH 016/216] First proposal --- application/config/jqm.php | 6 ++ .../controllers/system/JobsQueueMonitor.php | 56 +++++++++++++++++++ application/core/JQW_Controller.php | 56 +++++++++++++++++++ application/libraries/JobsQueueLib.php | 56 +++++++++++++++++++ 4 files changed, 174 insertions(+) create mode 100644 application/config/jqm.php create mode 100644 application/controllers/system/JobsQueueMonitor.php create mode 100644 application/core/JQW_Controller.php create mode 100644 application/libraries/JobsQueueLib.php diff --git a/application/config/jqm.php b/application/config/jqm.php new file mode 100644 index 000000000..5890241ae --- /dev/null +++ b/application/config/jqm.php @@ -0,0 +1,6 @@ + 'monitoring:r', + 'getJobsByStatus' => 'monitoring:r', + 'getJobsByCreationTime' => 'monitoring:r' + ) + ); + + // Loads JobsQueueLib + $this->load->library('JobsQueueLib'); + } + + /** + * + */ + public function getJobsByType() + { + $jobType = $this->input->get(JobsQueueLib::PARAM_JOB_TYPE); + + $this->outputJson($this->jobsqueuelib->getJobsByType($jobType)); + } + + /** + * + */ + public function getJobsByStatus() + { + $jobStatus = $this->input->get(JobsQueueLib::PARAM_JOB_STATUS); + + $this->outputJson($this->jobsqueuelib->getJobsByStatus($jobStatus)); + } + + /** + * + */ + public function getJobsByCreationTime() + { + $jobCreationTime = $this->input->get(JobsQueueLib::PARAM_JOB_CREATION_TIME); + + $this->outputJson($this->jobsqueuelib->getJobsByCreationTime($jobCreationTime)); + } +} diff --git a/application/core/JQW_Controller.php b/application/core/JQW_Controller.php new file mode 100644 index 000000000..9cb058f6b --- /dev/null +++ b/application/core/JQW_Controller.php @@ -0,0 +1,56 @@ +load->library('LogLib', array( + 'classIndex' => 5, + 'functionIndex' => 5, + 'lineIndex' => 4, + 'dbLogType' => 'job', // required + 'dbExecuteUser' => 'Jobs queue system' + )); + + // Loads JobsQueueLib + $this->load->library('JobsQueueLib'); + } + + // ------------------------------------------------------------------------------------------------------------ + // Protected methods to read/write the jobs queue + + /** + * + */ + protected function getJobsByType($jobType) + { + $jobs = $this->jobsqueuelib->getJobsByType($jobType); + + if (isError($jobs)) $this->logError(getError($jobs), $jobType); + + return $jobs; + } + + /** + * + */ + protected function addNewJobsToQueue($jobType, $jobs) + { + $result = $this->jobsqueuelib->addNewJobsToQueue($jobType, $jobs); + + if (isError($result)) $this->logError(getError($result), $jobType); + + return $result; + } +} diff --git a/application/libraries/JobsQueueLib.php b/application/libraries/JobsQueueLib.php new file mode 100644 index 000000000..0c7e44274 --- /dev/null +++ b/application/libraries/JobsQueueLib.php @@ -0,0 +1,56 @@ +_ci =& get_instance(); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * + */ + public function getJobsByType() + { + } + + /** + * + */ + public function addNewJobsToQueue() + { + } + + /** + * + */ + public function getJobsByStatus() + { + } +} From cd815acdbff64ab4797ec95d5661936cea17137b Mon Sep 17 00:00:00 2001 From: Paolo Date: Thu, 5 Mar 2020 15:57:06 +0100 Subject: [PATCH 017/216] - Added new constant BEGINNING_OF_TIME - Added new config entry job_type_permissions_white_list in jqm.php - Added new navigation entry jobsqueueviewer - Added new model application/models/system/JobsQueue_model.php - Added new option in FilterWidget for hours comparison with dates - Added new filter core-jq-lastHour to system/filtersupdate.php - Added new statements to system/dbupdate_3.3.php to create tables system.tbl_jobstatuses, system.tbl_jobtypes and system.tbl_jobstatuses - Added new views application/views/system/jq/jobsQueueViewer.php and application/views/system/jq/jobsQueueViewerData.php --- application/config/constants.php | 7 + application/config/jqm.php | 14 +- application/config/navigation.php | 7 + .../controllers/system/JobsQueueMonitor.php | 56 -------- application/controllers/system/LogsViewer.php | 2 +- .../system/jq/JobsQueueManager.php | 51 +++++++ .../controllers/system/jq/JobsQueueViewer.php | 48 +++++++ application/core/JQW_Controller.php | 33 +++-- application/libraries/FilterWidgetLib.php | 7 +- application/libraries/JobsQueueLib.php | 30 ++-- application/models/system/JobsQueue_model.php | 15 ++ .../views/system/jq/jobsQueueViewer.php | 47 +++++++ .../views/system/jq/jobsQueueViewerData.php | 67 +++++++++ application/views/system/logs/logsViewer.php | 4 +- system/dbupdate_3.3.php | 131 ++++++++++++++++++ system/filtersupdate.php | 31 +++++ 16 files changed, 462 insertions(+), 88 deletions(-) delete mode 100644 application/controllers/system/JobsQueueMonitor.php create mode 100644 application/controllers/system/jq/JobsQueueManager.php create mode 100644 application/controllers/system/jq/JobsQueueViewer.php create mode 100644 application/models/system/JobsQueue_model.php create mode 100644 application/views/system/jq/jobsQueueViewer.php create mode 100644 application/views/system/jq/jobsQueueViewerData.php diff --git a/application/config/constants.php b/application/config/constants.php index ef4cdaf2c..f21b6c962 100644 --- a/application/config/constants.php +++ b/application/config/constants.php @@ -31,6 +31,13 @@ define('EXIT_VALIDATION_UDF_NOT_VALID_VAL', 17); // UDF validation has been fail define('EXIT_AUTO_MIN', 1000); // lowest automatically-assigned error code define('EXIT_AUTO_MAX', 2000); // highest automatically-assigned error code +/* +|-------------------------------------------------------------------------- +| General purpose +|-------------------------------------------------------------------------- +*/ +define('BEGINNING_OF_TIME', '1970-01-01'); + /* |-------------------------------------------------------------------------- | Authentication constants diff --git a/application/config/jqm.php b/application/config/jqm.php index 5890241ae..579fc6987 100644 --- a/application/config/jqm.php +++ b/application/config/jqm.php @@ -2,5 +2,15 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); -// -$config['addable_jobs_black_list'] = array('doomsday', 'sudo rm -fR /', 'sudo mv / /dev/null'); +// White list of permissions that are able to store a spcific job type in database +$config['job_type_permissions_white_list'] = array( + 'SAPStammdatenUpdate' => array( + 'admin' + ), + 'OEHPayment' => array( + 'admin' + ), + 'SAPPayment' => array( + 'admin' + ) +); diff --git a/application/config/navigation.php b/application/config/navigation.php index 9253c87a1..f44b297a5 100644 --- a/application/config/navigation.php +++ b/application/config/navigation.php @@ -102,6 +102,13 @@ $config['navigation_header'] = array( 'expand' => true, 'sort' => 20, 'requiredPermissions' => 'system/developer:r' + ), + 'jobsqueueviewer' => array( + 'link' => site_url('system/jq/JobsQueueViewer'), + 'description' => 'Jobs Queue Viewer', + 'expand' => true, + 'sort' => 20, + 'requiredPermissions' => 'system/developer:r' ) ) ) diff --git a/application/controllers/system/JobsQueueMonitor.php b/application/controllers/system/JobsQueueMonitor.php deleted file mode 100644 index affb59bef..000000000 --- a/application/controllers/system/JobsQueueMonitor.php +++ /dev/null @@ -1,56 +0,0 @@ - 'monitoring:r', - 'getJobsByStatus' => 'monitoring:r', - 'getJobsByCreationTime' => 'monitoring:r' - ) - ); - - // Loads JobsQueueLib - $this->load->library('JobsQueueLib'); - } - - /** - * - */ - public function getJobsByType() - { - $jobType = $this->input->get(JobsQueueLib::PARAM_JOB_TYPE); - - $this->outputJson($this->jobsqueuelib->getJobsByType($jobType)); - } - - /** - * - */ - public function getJobsByStatus() - { - $jobStatus = $this->input->get(JobsQueueLib::PARAM_JOB_STATUS); - - $this->outputJson($this->jobsqueuelib->getJobsByStatus($jobStatus)); - } - - /** - * - */ - public function getJobsByCreationTime() - { - $jobCreationTime = $this->input->get(JobsQueueLib::PARAM_JOB_CREATION_TIME); - - $this->outputJson($this->jobsqueuelib->getJobsByCreationTime($jobCreationTime)); - } -} diff --git a/application/controllers/system/LogsViewer.php b/application/controllers/system/LogsViewer.php index 8caf9f3a7..4e39db5e3 100644 --- a/application/controllers/system/LogsViewer.php +++ b/application/controllers/system/LogsViewer.php @@ -35,7 +35,7 @@ class LogsViewer extends Auth_Controller // Public methods /** - * Main page of the InfoCenter tool + * Everything has a beginning */ public function index() { diff --git a/application/controllers/system/jq/JobsQueueManager.php b/application/controllers/system/jq/JobsQueueManager.php new file mode 100644 index 000000000..4e82ff44e --- /dev/null +++ b/application/controllers/system/jq/JobsQueueManager.php @@ -0,0 +1,51 @@ + 'admin:r', + 'addNewJobsToQueue' => 'admin:rw' + ) + ); + + // Loads JobsQueueLib + $this->load->library('JobsQueueLib'); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * To get all the most recently added jobs using the given job type + */ + public function getLastJobs() + { + $type = $this->input->get(JobsQueueLib::PARAM_JOB_TYPE); + + $this->outputJson($this->jobsqueuelib->getLastJobs($type)); + } + + /** + * Add new jobs in the jobs queue with the given type + * jobs is an array of job objects + */ + public function addNewJobsToQueue() + { + $type = $this->input->post(JobsQueueLib::PARAM_JOB_TYPE); + $jobs = $this->input->post(JobsQueueLib::PARAM_JOBS); + + $this->outputJson($this->jobsqueuelib->addNewJobsToQueue($type, $jobs)); + } +} diff --git a/application/controllers/system/jq/JobsQueueViewer.php b/application/controllers/system/jq/JobsQueueViewer.php new file mode 100644 index 000000000..7e8760209 --- /dev/null +++ b/application/controllers/system/jq/JobsQueueViewer.php @@ -0,0 +1,48 @@ + 'system/developer:r' + ) + ); + + // Loads WidgetLib + $this->load->library('WidgetLib'); + + // Loads phrases system + $this->loadPhrases( + array( + 'global', + 'ui', + 'filter' + ) + ); + } + + //------------------------------------------------------------------------------------------------------------------ + // Public methods + + /** + * Everything has a beginning + */ + public function index() + { + $this->load->view('system/jq/jobsQueueViewer.php'); + } +} diff --git a/application/core/JQW_Controller.php b/application/core/JQW_Controller.php index 9cb058f6b..616eaf4fd 100644 --- a/application/core/JQW_Controller.php +++ b/application/core/JQW_Controller.php @@ -3,18 +3,22 @@ if (!defined("BASEPATH")) exit("No direct script access allowed"); /** + * Job Queue Worker * + * This controller acts as interface of the JobsQueueLib that contains all the needed functionalities to operate with + * the Jobs Queue System + * This is an abstract class that provide basic functionalities, it has to be extended to broaden its logic */ abstract class JQW_Controller extends JOB_Controller { /** - * + * Constructor */ public function __construct() { parent::__construct(); - // Loads LogLib with different ... + // Loads LogLib with different parameters $this->load->library('LogLib', array( 'classIndex' => 5, 'functionIndex' => 5, @@ -23,33 +27,36 @@ abstract class JQW_Controller extends JOB_Controller 'dbExecuteUser' => 'Jobs queue system' )); - // Loads JobsQueueLib + // Loads JobsQueueLib library $this->load->library('JobsQueueLib'); } - // ------------------------------------------------------------------------------------------------------------ - // Protected methods to read/write the jobs queue + //------------------------------------------------------------------------------------------------------------------ + // Protected methods /** - * + * To get all the most recently added jobs using the given job type */ - protected function getJobsByType($jobType) + protected function getLastJobs($type) { - $jobs = $this->jobsqueuelib->getJobsByType($jobType); + $jobs = $this->jobsqueuelib->getLastJobs($type); - if (isError($jobs)) $this->logError(getError($jobs), $jobType); + // If an error occurred then log it in database + if (isError($jobs)) $this->logError(getError($jobs), $type); return $jobs; } /** - * + * Add new jobs in the jobs queue with the given type + * jobs is an array of job objects */ - protected function addNewJobsToQueue($jobType, $jobs) + protected function addNewJobsToQueue($type, $jobs) { - $result = $this->jobsqueuelib->addNewJobsToQueue($jobType, $jobs); + $result = $this->jobsqueuelib->addNewJobsToQueue($type, $jobs); - if (isError($result)) $this->logError(getError($result), $jobType); + // If an error occurred then log it in database + if (isError($result)) $this->logError(getError($result), $type); return $result; } diff --git a/application/libraries/FilterWidgetLib.php b/application/libraries/FilterWidgetLib.php index 6e87833bd..f909c7083 100644 --- a/application/libraries/FilterWidgetLib.php +++ b/application/libraries/FilterWidgetLib.php @@ -93,6 +93,7 @@ class FilterWidgetLib const OP_NOT_SET = 'nset'; // Filter options values + const OPT_HOURS = 'hours'; const OPT_DAYS = 'days'; const OPT_MONTHS = 'months'; @@ -884,7 +885,8 @@ class FilterWidgetLib // It it's a date type if (is_numeric($filterDefinition->condition) && isset($filterDefinition->option) - && ($filterDefinition->option == self::OPT_DAYS + && ($filterDefinition->option == self::OPT_HOURS + || $filterDefinition->option == self::OPT_DAYS || $filterDefinition->option == self::OPT_MONTHS)) { $condition = '< (NOW() - \''.$filterDefinition->condition.' '.$filterDefinition->option.'\'::interval)'; @@ -899,7 +901,8 @@ class FilterWidgetLib // It it's a date type if (is_numeric($filterDefinition->condition) && isset($filterDefinition->option) - && ($filterDefinition->option == self::OPT_DAYS + && ($filterDefinition->option == self::OPT_HOURS + || $filterDefinition->option == self::OPT_DAYS || $filterDefinition->option == self::OPT_MONTHS)) { $condition = '> (NOW() - \''.$filterDefinition->condition.' '.$filterDefinition->option.'\'::interval)'; diff --git a/application/libraries/JobsQueueLib.php b/application/libraries/JobsQueueLib.php index 0c7e44274..fe73b40c6 100644 --- a/application/libraries/JobsQueueLib.php +++ b/application/libraries/JobsQueueLib.php @@ -2,27 +2,33 @@ if (!defined('BASEPATH')) exit('No direct script access allowed'); +/** + * Library that contains all the needed functionalities to operate with the Jobs Queue System + */ class JobsQueueLib { - // - const STATUS_RUNNING = 'running'; - const STATUS_NEW = 'new'; - const STATUS_DONE = 'done'; - - // - const PARAM_JOB_TYPE = 'jobType'; - const PARAM_JOB_STATUS = 'jobStatus'; - const PARAM_JOB_CREATION_TIME = 'jobCreatinTime'; - - // + // Job types + // SAP const JOB_TYPE_SAP_STAMMDATEN_UPDATE = 'SAPStammdatenUpdate'; const JOB_TYPE_SAP_PAYMENT = 'SAPPayment'; + // DVUH const JOB_TYPE_OEH_PAYMENT = 'OEHPayment'; + // Job statuses + const STATUS_NEW = 'new'; + const STATUS_RUNNING = 'running'; + const STATUS_DONE = 'done'; + const STATUS_FAILED = 'failed'; + + // Parameter names + const PARAM_JOB_TYPE = 'type'; + const PARAM_JOB_STATUS = 'status'; + const PARAM_JOBS = 'jobs'; + private $_ci; // CI instance /** - * Construct + * Constructor */ public function __construct($authenticate = true) { diff --git a/application/models/system/JobsQueue_model.php b/application/models/system/JobsQueue_model.php new file mode 100644 index 000000000..e35b45cb3 --- /dev/null +++ b/application/models/system/JobsQueue_model.php @@ -0,0 +1,15 @@ +dbTable = 'system.tbl_jobsqueue'; + $this->pk = 'jobid'; + } +} diff --git a/application/views/system/jq/jobsQueueViewer.php b/application/views/system/jq/jobsQueueViewer.php new file mode 100644 index 000000000..6d92d610b --- /dev/null +++ b/application/views/system/jq/jobsQueueViewer.php @@ -0,0 +1,47 @@ +load->view( + 'templates/FHC-Header', + array( + 'title' => 'Jobs Queue Viewer', + 'jquery' => true, + 'jqueryui' => true, + 'bootstrap' => true, + 'fontawesome' => true, + 'sbadmintemplate' => true, + 'tablesorter' => true, + 'ajaxlib' => true, + 'filterwidget' => true, + 'navigationwidget' => true, + 'phrases' => array( + 'global' => array('mailAnXversandt'), + 'ui' => array('bitteEintragWaehlen') + ), + 'customCSSs' => 'public/css/sbadmin2/tablesort_bootstrap.css', + 'customJSs' => array('public/js/bootstrapper.js') + ) + ); +?> + + +
+ + widgetlib->widget('NavigationWidget'); ?> + +
+
+
+
+ +
+
+
+ load->view('system/jq/jobsQueueViewerData.php'); ?> +
+
+
+
+ + +load->view('templates/FHC-Footer'); ?> diff --git a/application/views/system/jq/jobsQueueViewerData.php b/application/views/system/jq/jobsQueueViewerData.php new file mode 100644 index 000000000..be09e0baf --- /dev/null +++ b/application/views/system/jq/jobsQueueViewerData.php @@ -0,0 +1,67 @@ + ' + SELECT jq.jobid AS "JobId", + jq.creationtime AS "CreationTime", + jq.type AS "Type", + jq.status AS "Status", + jq.starttime AS "StartTime", + jq.endtime AS "EndTime", + jq.insertvon AS "UserService" + FROM system.tbl_jobsqueue jq + ORDER BY jq.creationtime DESC, jq.starttime DESC, jq.endtime DESC + ', + 'requiredPermissions' => 'admin', + 'datasetRepresentation' => 'tablesorter', + 'columnsAliases' => array( + 'Job id', + 'Creation time', + 'Type', + 'Status', + 'Start time', + 'End time', + 'User/Service' + ), + 'formatRow' => function($datasetRaw) { + + $datasetRaw->CreationTime = date_format(date_create($datasetRaw->CreationTime), 'd.m.Y H:i:s'); + $datasetRaw->StartTime = date_format(date_create($datasetRaw->StartTime), 'd.m.Y H:i:s'); + $datasetRaw->EndTime = date_format(date_create($datasetRaw->EndTime), 'd.m.Y H:i:s'); + + return $datasetRaw; + }, + 'markRow' => function($datasetRaw) { + + $mark = ''; + + if ($datasetRaw->Status == 'Failed') + { + $mark = 'text-red'; + } + + if ($datasetRaw->Status == 'Done') + { + $mark = 'text-green'; + } + + if ($datasetRaw->Status == 'Running') + { + $mark = 'text-orange'; + } + + if ($datasetRaw->Status == 'New') + { + $mark = 'text-info'; + } + + return $mark; + } + ); + + $filterWidgetArray['app'] = 'core'; + $filterWidgetArray['datasetName'] = 'jq'; + $filterWidgetArray['filter_id'] = $this->input->get('filter_id'); + + echo $this->widgetlib->widget('FilterWidget', $filterWidgetArray); +?> diff --git a/application/views/system/logs/logsViewer.php b/application/views/system/logs/logsViewer.php index 96790b479..86423006b 100644 --- a/application/views/system/logs/logsViewer.php +++ b/application/views/system/logs/logsViewer.php @@ -2,7 +2,7 @@ $this->load->view( 'templates/FHC-Header', array( - 'title' => 'Logs viewer', + 'title' => 'Logs Viewer', 'jquery' => true, 'jqueryui' => true, 'bootstrap' => true, @@ -32,7 +32,7 @@
diff --git a/system/dbupdate_3.3.php b/system/dbupdate_3.3.php index 623ea7ac7..0440ee5ff 100644 --- a/system/dbupdate_3.3.php +++ b/system/dbupdate_3.3.php @@ -3842,6 +3842,134 @@ if ($result = $db->db_query("SELECT 1 FROM pg_class WHERE relname = 'unq_idx_abl } } +// Creates table system.tbl_jobstatuses if it doesn't exist and grants privileges +if (!$result = @$db->db_query('SELECT 1 FROM system.tbl_jobstatuses LIMIT 1')) +{ + $qry = 'CREATE TABLE system.tbl_jobstatuses ( + status character varying NOT NULL + ); + + COMMENT ON TABLE system.tbl_jobstatuses IS \'All possible job statuses\'; + COMMENT ON COLUMN system.tbl_jobstatuses.status IS \'Job status value and primary key\'; + + ALTER TABLE ONLY system.tbl_jobstatuses ADD CONSTRAINT pk_jobstatuses PRIMARY KEY (status); + '; + + if (!$db->db_query($qry)) + echo 'system.tbl_jobstatuses: '.$db->db_last_error().'
'; + else + echo '
system.tbl_jobstatuses table created'; + + $qry = 'GRANT SELECT ON TABLE system.tbl_jobstatuses TO web;'; + if (!$db->db_query($qry)) + echo 'system.tbl_jobstatuses: '.$db->db_last_error().'
'; + else + echo '
Granted privileges to web on system.tbl_jobstatuses'; + + $qry = 'GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE system.tbl_jobstatuses TO vilesci;'; + if (!$db->db_query($qry)) + echo 'system.tbl_jobstatuses: '.$db->db_last_error().'
'; + else + echo '
Granted privileges to vilesci on system.tbl_jobstatuses'; +} + +// Creates table system.tbl_jobtypes if it doesn't exist and grants privileges +if (!$result = @$db->db_query('SELECT 1 FROM system.tbl_jobtypes LIMIT 1')) +{ + $qry = 'CREATE TABLE system.tbl_jobtypes ( + type character varying(256) NOT NULL, + description text NOT NULL + ); + + COMMENT ON TABLE system.tbl_jobtypes IS \'All possible job types\'; + COMMENT ON COLUMN system.tbl_jobtypes.type IS \'Job type value and primary key\'; + COMMENT ON COLUMN system.tbl_jobtypes.description IS \'Job type description\'; + + ALTER TABLE ONLY system.tbl_jobtypes ADD CONSTRAINT pk_jobtypes PRIMARY KEY (type); + '; + + if (!$db->db_query($qry)) + echo 'system.tbl_jobtypes: '.$db->db_last_error().'
'; + else + echo '
system.tbl_jobtypes table created'; + + $qry = 'GRANT SELECT ON TABLE system.tbl_jobtypes TO web;'; + if (!$db->db_query($qry)) + echo 'system.tbl_jobtypes: '.$db->db_last_error().'
'; + else + echo '
Granted privileges to web on system.tbl_jobtypes'; + + $qry = 'GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE system.tbl_jobtypes TO vilesci;'; + if (!$db->db_query($qry)) + echo 'system.tbl_jobtypes: '.$db->db_last_error().'
'; + else + echo '
Granted privileges to vilesci on system.tbl_jobtypes'; +} + +// Creates table system.tbl_jobsqueue if it doesn't exist and grants privileges +if (!$result = @$db->db_query('SELECT 1 FROM system.tbl_jobsqueue LIMIT 1')) +{ + $qry = 'CREATE TABLE system.tbl_jobsqueue ( + jobid integer NOT NULL, + type character varying(256) NOT NULL, + creationtime timestamp without time zone DEFAULT now(), + status character varying(64) NOT NULL, + input jsonb, + output jsonb, + starttime timestamp without time zone, + endtime timestamp without time zone, + insertvon character varying(32), + insertamum timestamp without time zone DEFAULT now() + ); + + COMMENT ON TABLE system.tbl_jobsqueue IS \'Table to schedule/manage the jobs queue\'; + COMMENT ON COLUMN system.tbl_jobsqueue.jobid IS \'Primary key\'; + COMMENT ON COLUMN system.tbl_jobsqueue.type IS \'Job type\'; + COMMENT ON COLUMN system.tbl_jobsqueue.creationtime IS \'Job creation timestamp\'; + COMMENT ON COLUMN system.tbl_jobsqueue.status IS \'Job current status\'; + COMMENT ON COLUMN system.tbl_jobsqueue.input IS \'Job input in JSON format\'; + COMMENT ON COLUMN system.tbl_jobsqueue.output IS \'Job output in JSON format\'; + COMMENT ON COLUMN system.tbl_jobsqueue.starttime IS \'Job start timestamp\'; + COMMENT ON COLUMN system.tbl_jobsqueue.endtime IS \'Job end timestamp\'; + COMMENT ON COLUMN system.tbl_jobsqueue.insertvon IS \'User/Service who/that inserted this record\'; + COMMENT ON COLUMN system.tbl_jobsqueue.insertamum IS \'Record insert time stamp\'; + + CREATE SEQUENCE system.seq_jobsqueue_jobid + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + ALTER SEQUENCE system.seq_jobsqueue_jobid OWNED BY system.tbl_jobsqueue.jobid; + + ALTER TABLE ONLY system.tbl_jobsqueue ALTER COLUMN jobid SET DEFAULT nextval(\'system.seq_jobsqueue_jobid\'::regclass); + + ALTER TABLE ONLY system.tbl_jobsqueue ADD CONSTRAINT pk_jobsqueue PRIMARY KEY (jobid); + + ALTER TABLE ONLY system.tbl_jobsqueue ADD CONSTRAINT fk_jobsqueue_status FOREIGN KEY (status) REFERENCES system.tbl_jobstatuses(status) ON UPDATE CASCADE ON DELETE RESTRICT; + + ALTER TABLE ONLY system.tbl_jobsqueue ADD CONSTRAINT fk_jobsqueue_type FOREIGN KEY (type) REFERENCES system.tbl_jobtypes(type) ON UPDATE CASCADE ON DELETE RESTRICT; + '; + + if (!$db->db_query($qry)) + echo 'system.tbl_jobsqueue: '.$db->db_last_error().'
'; + else + echo '
system.tbl_jobsqueue table created'; + + $qry = 'GRANT SELECT ON TABLE system.tbl_jobsqueue TO web;'; + if (!$db->db_query($qry)) + echo 'system.tbl_jobsqueue: '.$db->db_last_error().'
'; + else + echo '
Granted privileges to web on system.tbl_jobsqueue'; + + $qry = 'GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE system.tbl_jobsqueue TO vilesci;'; + if (!$db->db_query($qry)) + echo 'system.tbl_jobsqueue: '.$db->db_last_error().'
'; + else + echo '
Granted privileges to vilesci on system.tbl_jobsqueue'; +} + // *** Pruefung und hinzufuegen der neuen Attribute und Tabellen echo '

Pruefe Tabellen und Attribute!

'; @@ -4100,6 +4228,9 @@ $tabellen=array( "system.tbl_log" => array("log_id","person_id","zeitpunkt","app","oe_kurzbz","logtype_kurzbz","logdata","insertvon","taetigkeit_kurzbz"), "system.tbl_logtype" => array("logtype_kurzbz", "data_schema"), "system.tbl_filters" => array("filter_id","app","dataset_name","filter_kurzbz","person_id","description","sort","default_filter","filter","oe_kurzbz","statistik_kurzbz"), + "system.tbl_jobsqueue" => array("jobid", "type", "creationtime", "status", "input", "output", "starttime", "endtime", "insertvon", "insertamum"), + "system.tbl_jobstatuses" => array("status"), + "system.tbl_jobtypes" => array("type", "description"), "system.tbl_phrase" => array("phrase_id","app","phrase","insertamum","insertvon","category"), "system.tbl_phrasentext" => array("phrasentext_id","phrase_id","sprache","orgeinheit_kurzbz","orgform_kurzbz","text","description","insertamum","insertvon"), "system.tbl_rolle" => array("rolle_kurzbz","beschreibung"), diff --git a/system/filtersupdate.php b/system/filtersupdate.php index d05a39aab..9c648a572 100644 --- a/system/filtersupdate.php +++ b/system/filtersupdate.php @@ -631,6 +631,37 @@ $filters = array( } ', 'oe_kurzbz' => null, + ), + array( + 'app' => 'core', + 'dataset_name' => 'jq', + 'filter_kurzbz' => 'lastHour', + 'description' => '{Last hour queued jobs}', + 'sort' => 1, + 'default_filter' => true, + 'filter' => ' + { + "name": "All jobs queued in the last hour", + "columns": [ + {"name": "JobId"}, + {"name": "CreationTime"}, + {"name": "Type"}, + {"name": "Status"}, + {"name": "StartTime"}, + {"name": "EndTime"}, + {"name": "UserService"} + ], + "filters": [ + { + "name": "CreationTime", + "operation": "lt", + "condition": "1", + "option": "hours" + } + ] + } + ', + 'oe_kurzbz' => null, ) ); From 3bfe1cdeea79322d4d0c4b52264d24ddd2307250 Mon Sep 17 00:00:00 2001 From: Paolo Date: Thu, 5 Mar 2020 18:48:26 +0100 Subject: [PATCH 018/216] - Fixed messages and comments in PermissionLib - JobsQueueManager->addNewJobsToQueue now checks permission to write new jobs in the queue - Added statuses for system.tbl_jobstatuses in system/dbupdate_3.3.php - Added permission access type (read/write) in configuration file application/config/jqm.php --- application/config/jqm.php | 13 +++++-------- .../system/jq/JobsQueueManager.php | 19 +++++++++++++++++-- application/libraries/PermissionLib.php | 6 +++--- system/dbupdate_3.3.php | 5 +++++ 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/application/config/jqm.php b/application/config/jqm.php index 579fc6987..77d9bb35d 100644 --- a/application/config/jqm.php +++ b/application/config/jqm.php @@ -2,15 +2,12 @@ if (! defined('BASEPATH')) exit('No direct script access allowed'); -// White list of permissions that are able to store a spcific job type in database +// White list of permissions (write mode have to be set) that are able to store a specific job type in database $config['job_type_permissions_white_list'] = array( 'SAPStammdatenUpdate' => array( - 'admin' + 'admin:rw', + 'developer:rw' ), - 'OEHPayment' => array( - 'admin' - ), - 'SAPPayment' => array( - 'admin' - ) + 'OEHPayment' => 'developer:rw', + 'SAPPayment' => 'developer:rw' ); diff --git a/application/controllers/system/jq/JobsQueueManager.php b/application/controllers/system/jq/JobsQueueManager.php index 4e82ff44e..9275fa845 100644 --- a/application/controllers/system/jq/JobsQueueManager.php +++ b/application/controllers/system/jq/JobsQueueManager.php @@ -8,6 +8,9 @@ if (!defined('BASEPATH')) exit('No direct script access allowed'); */ class JobsQueueManager extends Auth_Controller { + // Config entry name for White list of permissions... + const JOB_TYPE_PERMISSIONS_WHITE_LIST = 'job_type_permissions_white_list'; + /** * Constructor */ @@ -15,7 +18,7 @@ class JobsQueueManager extends Auth_Controller { parent::__construct( array( - 'getJobsByType' => 'admin:r', + 'getLastJobs' => 'admin:r', 'addNewJobsToQueue' => 'admin:rw' ) ); @@ -46,6 +49,18 @@ class JobsQueueManager extends Auth_Controller $type = $this->input->post(JobsQueueLib::PARAM_JOB_TYPE); $jobs = $this->input->post(JobsQueueLib::PARAM_JOBS); - $this->outputJson($this->jobsqueuelib->addNewJobsToQueue($type, $jobs)); + // Loads permission lib + $this->load->library('PermissionLib'); + + // Checks if the caller has the permissions to add new jobs with the given type in the queue + if (!$this->permissionlib->isEntitled($this->config->item(self::JOB_TYPE_PERMISSIONS_WHITE_LIST), $type)) + { + // Permissions NOT valid + $this->outputJsonError('You are not allowed to access to this content'); + } + else // Otherwise call JobsQueueLib library + { + $this->outputJson($this->jobsqueuelib->addNewJobsToQueue($type, $jobs)); + } } } diff --git a/application/libraries/PermissionLib.php b/application/libraries/PermissionLib.php index 348c8b87b..09f89abee 100644 --- a/application/libraries/PermissionLib.php +++ b/application/libraries/PermissionLib.php @@ -147,7 +147,7 @@ class PermissionLib $accessType = ''; - // Checks if the required access type is compliant with the HTTP method (GET => r, POST => w) + // Set the access type if (strpos($requiredAccessType, PermissionLib::READ_RIGHT) !== false) { $accessType = PermissionLib::SELECT_RIGHT; // S @@ -184,12 +184,12 @@ class PermissionLib } else { - show_error('The given permission array does not contain the called method or is not correctly set'); + show_error('The given permission array does not contain the given method or is not correctly set'); } } else { - show_error('You must give the permissions array as parameter to the constructor of the controller'); + show_error('The given permissions is not a valid array or it is an empty one'); } return $checkPermissions; diff --git a/system/dbupdate_3.3.php b/system/dbupdate_3.3.php index 0440ee5ff..42a1b531a 100644 --- a/system/dbupdate_3.3.php +++ b/system/dbupdate_3.3.php @@ -3853,6 +3853,11 @@ if (!$result = @$db->db_query('SELECT 1 FROM system.tbl_jobstatuses LIMIT 1')) COMMENT ON COLUMN system.tbl_jobstatuses.status IS \'Job status value and primary key\'; ALTER TABLE ONLY system.tbl_jobstatuses ADD CONSTRAINT pk_jobstatuses PRIMARY KEY (status); + + INSERT INTO system.tbl_jobstatuses(status) VALUES('new'); + INSERT INTO system.tbl_jobstatuses(status) VALUES('running'); + INSERT INTO system.tbl_jobstatuses(status) VALUES('done'); + INSERT INTO system.tbl_jobstatuses(status) VALUES('failed'); '; if (!$db->db_query($qry)) From ba566ab459d6e752b09636cb64fad85749c1eddf Mon Sep 17 00:00:00 2001 From: Paolo Date: Fri, 6 Mar 2020 14:13:25 +0100 Subject: [PATCH 019/216] Added new models system/JobStatuses_model and system/JobTypes_model --- application/models/system/JobStatuses_model.php | 16 ++++++++++++++++ application/models/system/JobTypes_model.php | 16 ++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 application/models/system/JobStatuses_model.php create mode 100644 application/models/system/JobTypes_model.php diff --git a/application/models/system/JobStatuses_model.php b/application/models/system/JobStatuses_model.php new file mode 100644 index 000000000..82d1ee31b --- /dev/null +++ b/application/models/system/JobStatuses_model.php @@ -0,0 +1,16 @@ +dbTable = 'system.tbl_jobstatuses'; + $this->pk = 'status'; + $this->hasSequence = false; + } +} diff --git a/application/models/system/JobTypes_model.php b/application/models/system/JobTypes_model.php new file mode 100644 index 000000000..1d578bcab --- /dev/null +++ b/application/models/system/JobTypes_model.php @@ -0,0 +1,16 @@ +dbTable = 'system.tbl_jobtypes'; + $this->pk = 'type'; + $this->hasSequence = false; + } +} From d2e7336f2ce6b91246a065158fcebe0783e6312e Mon Sep 17 00:00:00 2001 From: Paolo Date: Fri, 6 Mar 2020 14:14:11 +0100 Subject: [PATCH 020/216] Granted permission to user fhcomplete and vilesci for sequence seq_jobsqueue_jobid --- system/dbupdate_3.3.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/system/dbupdate_3.3.php b/system/dbupdate_3.3.php index 42a1b531a..5bccd5e1a 100644 --- a/system/dbupdate_3.3.php +++ b/system/dbupdate_3.3.php @@ -3950,6 +3950,9 @@ if (!$result = @$db->db_query('SELECT 1 FROM system.tbl_jobsqueue LIMIT 1')) ALTER TABLE ONLY system.tbl_jobsqueue ALTER COLUMN jobid SET DEFAULT nextval(\'system.seq_jobsqueue_jobid\'::regclass); + GRANT SELECT, UPDATE ON SEQUENCE system.seq_jobsqueue_jobid TO vilesci; + GRANT SELECT, UPDATE ON SEQUENCE system.seq_jobsqueue_jobid TO fhcomplete; + ALTER TABLE ONLY system.tbl_jobsqueue ADD CONSTRAINT pk_jobsqueue PRIMARY KEY (jobid); ALTER TABLE ONLY system.tbl_jobsqueue ADD CONSTRAINT fk_jobsqueue_status FOREIGN KEY (status) REFERENCES system.tbl_jobstatuses(status) ON UPDATE CASCADE ON DELETE RESTRICT; From e92880b79a76d0003968c4e82ff88aa1e9721da5 Mon Sep 17 00:00:00 2001 From: Paolo Date: Fri, 6 Mar 2020 14:15:10 +0100 Subject: [PATCH 021/216] - Added new private methods _checkPermissions and _convertJobs to controller system/jq/JobsQueueManager - Added new public method updateJobsQueue to controller system/jq/JobsQueueManager - system/jq/JobsQueueManager->getLastJobs now checks permissions - Added new public method updateJobsQueue to JQW_Controller - Less redundant constansts in Library JobsQueueLib - JobsQueueLib constructor now loads models JobsQueueModel, JobTypesModel and JobStatusesModel - Added new public methods getLastJobs, addNewJobsToQueue and updateJobsQueue to JobsQueueLib - Added new private methods _checkNewJobStructure, _checkUpdateJobStructure, _checkJobType, _checkJobStatus, _inArray, _dropNotAllowedPropertiesNewJob and _dropNotAllowedPropertiesUpdateJob to --- .../system/jq/JobsQueueManager.php | 83 +++++- application/core/JQW_Controller.php | 14 + application/libraries/JobsQueueLib.php | 255 ++++++++++++++++-- 3 files changed, 324 insertions(+), 28 deletions(-) diff --git a/application/controllers/system/jq/JobsQueueManager.php b/application/controllers/system/jq/JobsQueueManager.php index 9275fa845..b6e4efe29 100644 --- a/application/controllers/system/jq/JobsQueueManager.php +++ b/application/controllers/system/jq/JobsQueueManager.php @@ -10,6 +10,8 @@ class JobsQueueManager extends Auth_Controller { // Config entry name for White list of permissions... const JOB_TYPE_PERMISSIONS_WHITE_LIST = 'job_type_permissions_white_list'; + // Parameter names + const PARAM_JOBS = 'jobs'; /** * Constructor @@ -19,12 +21,15 @@ class JobsQueueManager extends Auth_Controller parent::__construct( array( 'getLastJobs' => 'admin:r', - 'addNewJobsToQueue' => 'admin:rw' + 'addNewJobsToQueue' => 'admin:rw', + 'updateJobsQueue' => 'admin:rw' ) ); // Loads JobsQueueLib $this->load->library('JobsQueueLib'); + // Loads permission lib + $this->load->library('PermissionLib'); } //------------------------------------------------------------------------------------------------------------------ @@ -35,7 +40,9 @@ class JobsQueueManager extends Auth_Controller */ public function getLastJobs() { - $type = $this->input->get(JobsQueueLib::PARAM_JOB_TYPE); + $type = $this->input->get(JobsQueueLib::PROPERTY_TYPE); + + $this->_checkPermissions($type); $this->outputJson($this->jobsqueuelib->getLastJobs($type)); } @@ -46,21 +53,75 @@ class JobsQueueManager extends Auth_Controller */ public function addNewJobsToQueue() { - $type = $this->input->post(JobsQueueLib::PARAM_JOB_TYPE); - $jobs = $this->input->post(JobsQueueLib::PARAM_JOBS); + $type = $this->input->post(JobsQueueLib::PROPERTY_TYPE); + $jobs = $this->input->post(self::PARAM_JOBS); - // Loads permission lib - $this->load->library('PermissionLib'); + $this->_checkPermissions($type); + // Otherwise convert jobs from json to php and call JobsQueueLib library + $this->outputJson($this->jobsqueuelib->addNewJobsToQueue($type, $this->_convertJobs($jobs))); + } + + /** + * Add new jobs in the jobs queue with the given type + * jobs is an array of job objects + */ + public function updateJobsQueue() + { + $type = $this->input->post(JobsQueueLib::PROPERTY_TYPE); + $jobs = $this->input->post(self::PARAM_JOBS); + + $this->_checkPermissions($type); + + // Otherwise convert jobs from json to php and call JobsQueueLib library + $this->outputJson($this->jobsqueuelib->updateJobsQueue($type, $this->_convertJobs($jobs))); + } + + //------------------------------------------------------------------------------------------------------------------ + // Private methods + + /** + * + */ + private function _checkPermissions($type) + { // Checks if the caller has the permissions to add new jobs with the given type in the queue if (!$this->permissionlib->isEntitled($this->config->item(self::JOB_TYPE_PERMISSIONS_WHITE_LIST), $type)) { // Permissions NOT valid - $this->outputJsonError('You are not allowed to access to this content'); - } - else // Otherwise call JobsQueueLib library - { - $this->outputJson($this->jobsqueuelib->addNewJobsToQueue($type, $jobs)); + $this->terminateWithJsonError('You are not allowed to access to this content'); } } + + /** + * + */ + private function _convertJobs($jobs) + { + if (isEmptyArray($jobs)) return null; // if not a valid array then return null + + $convertedJobsArray = array(); // returned values + + // Loops through all the provided jobs + foreach ($jobs as $job) + { + $tmpObj = json_decode($job); // Try to decode json to php + + // If decode was a success + if ($tmpObj != null) + { + $convertedJobsArray[] = $tmpObj; // then store the decoded object in the result array + } + else // otherwise + { + // Create a new object and store the error message in it + $tmpObj = new stdClass(); + $tmpObj->{JobsQueueLib::PROPERTY_ERROR} = 'A not valid json was provided'; + + $convertedJobsArray[] = $tmpObj; // store this object into the result array + } + } + + return $convertedJobsArray; + } } diff --git a/application/core/JQW_Controller.php b/application/core/JQW_Controller.php index 616eaf4fd..c6d2362e3 100644 --- a/application/core/JQW_Controller.php +++ b/application/core/JQW_Controller.php @@ -60,4 +60,18 @@ abstract class JQW_Controller extends JOB_Controller return $result; } + + /** + * Updates jobs already present in the jobs queue + * jobs is an array of job objects + */ + protected function updateJobsQueue($type, $jobs) + { + $result = $this->jobsqueuelib->updateJobsQueue($type, $jobs); + + // If an error occurred then log it in database + if (isError($result)) $this->logError(getError($result), $type); + + return $result; + } } diff --git a/application/libraries/JobsQueueLib.php b/application/libraries/JobsQueueLib.php index fe73b40c6..ac0e38786 100644 --- a/application/libraries/JobsQueueLib.php +++ b/application/libraries/JobsQueueLib.php @@ -7,23 +7,22 @@ if (!defined('BASEPATH')) exit('No direct script access allowed'); */ class JobsQueueLib { - // Job types - // SAP - const JOB_TYPE_SAP_STAMMDATEN_UPDATE = 'SAPStammdatenUpdate'; - const JOB_TYPE_SAP_PAYMENT = 'SAPPayment'; - // DVUH - const JOB_TYPE_OEH_PAYMENT = 'OEHPayment'; - // Job statuses const STATUS_NEW = 'new'; const STATUS_RUNNING = 'running'; const STATUS_DONE = 'done'; const STATUS_FAILED = 'failed'; - // Parameter names - const PARAM_JOB_TYPE = 'type'; - const PARAM_JOB_STATUS = 'status'; - const PARAM_JOBS = 'jobs'; + // Job object properties + const PROPERTY_JOBID = 'jobid'; + const PROPERTY_CREATIONTIME = 'creationtime'; + const PROPERTY_TYPE = 'type'; + const PROPERTY_STATUS = 'status'; + const PROPERTY_INPUT = 'input'; + const PROPERTY_OUTPUT = 'output'; + const PROPERTY_START_TIME = 'starttime'; + const PROPERTY_END_TIME = 'endtime'; + const PROPERTY_ERROR = 'error'; private $_ci; // CI instance @@ -34,29 +33,251 @@ class JobsQueueLib { // Gets CI instance $this->_ci =& get_instance(); + + // Loads JQM configuration + $this->_ci->config->load('jqm'); + + // Loads all needed models + $this->_ci->load->model('system/JobsQueue_model', 'JobsQueueModel'); + $this->_ci->load->model('system/JobTypes_model', 'JobTypesModel'); + $this->_ci->load->model('system/JobStatuses_model', 'JobStatusesModel'); } //------------------------------------------------------------------------------------------------------------------ // Public methods /** - * + * To get all the most recently added jobs using the given job type */ - public function getJobsByType() + public function getLastJobs($type) { + $this->_ci->JobsQueueModel->resetQuery(); + + $this->_ci->JobsQueueModel->addOrder('creationtime', 'DESC'); + + return $this->_ci->JobsQueueModel->loadWhere(array('status' => self::STATUS_NEW, 'type' => $type)); } /** - * + * Add new jobs in the jobs queue with the given type + * jobs is an array of job objects */ - public function addNewJobsToQueue() + public function addNewJobsToQueue($type, $jobs) { + // Checks parameters + if (isEmptyString($type)) return error('The provided type parameter is not a valid string'); + if (isEmptyArray($jobs)) return error('The provided jobs parameter is not a valid array'); + + // Get all the job types + $dbResult = $this->_ci->JobTypesModel->load(); + if (isError($dbResult)) return $dbResult; + $types = getData($dbResult); + + // If the given type is not present in database + if (!$this->_checkJobType($type, $types)) return error('The provided type parameter is not valid'); + + $results = $jobs; // returned values + $errorOccurred = false; // very optimistic + + // Get all the job statuses + $dbResult = $this->_ci->JobStatusesModel->load(); + if (isError($dbResult)) return $dbResult; + $statuses = getData($dbResult); + + // Loops through all the provided jobs + foreach ($results as $job) + { + // If the structure of the job object is valid AND the type is valid AND the status is valid + if ($this->_checkNewJobStructure($job) && $this->_checkJobStatus($job, $statuses)) + { + $this->_dropNotAllowedPropertiesNewJob($job); // remove the black listed properties from this object + + $job->{self::PROPERTY_TYPE} = $type; // What you asked is what you get! + + // Try to insert the single job into database + $dbResult = $this->_ci->JobsQueueModel->insert($job); + + // If an error occurred during while inserting in database + if (isError($dbResult)) + { + $job->{self::PROPERTY_ERROR} = getError($dbResult); // retrieve the cause and store it in job object + $errorOccurred = true; // set error occurred flag + } + else // otherwise + { + $job->{self::PROPERTY_JOBID} = getData($dbResult); // get the jobid and store it in job object + } + } + else // otherwise + { + $errorOccurred = true; // set error occurred flag + } + } + + // If an error occurred then returns the results in an error object + if ($errorOccurred) return error($results); + + return success($results); // otherwise return results in a success object } /** - * + * Updates jobs already present in the jobs queue + * jobs is an array of job objects */ - public function getJobsByStatus() + public function updateJobsQueue($type, $jobs) { + // Checks parameters + if (isEmptyArray($jobs)) return error('The provided jobs parameter is not a valid array'); + + $results = $jobs; // returned values + $errorOccurred = false; // very optimistic + + // Get all the job statuses + $dbResult = $this->_ci->JobStatusesModel->load(); + if (isError($dbResult)) return $dbResult; + $statuses = getData($dbResult); + + // Loops through all the provided jobs + foreach ($results as $job) + { + // If the structure of the job object is valid + if ($this->_checkUpdateJobStructure($job) && $this->_checkJobStatus($job, $statuses)) + { + $this->_dropNotAllowedPropertiesUpdateJob($job); // remove the black listed properties from this object + + $job->{self::PROPERTY_TYPE} = $type; // What you asked is what you get! + + // Try to update the single job into database + $dbResult = $this->_ci->JobsQueueModel->update($job->{self::PROPERTY_JOBID}, (array)$job); + + // If an error occurred during while updating in database + if (isError($dbResult)) + { + $job->{self::PROPERTY_ERROR} = getError($dbResult); // retrieve the cause and store it in job object + $errorOccurred = true; // set error occurred flag + } + } + else // otherwise + { + $errorOccurred = true; // set error occurred flag + } + } + + // If an error occurred then returns the results in an error object + if ($errorOccurred) return error($results); + + return success($results); // otherwise return results in a success object + } + + //------------------------------------------------------------------------------------------------------------------ + // Private methods + + /** + * Checks the job object structure when needed for insert + */ + private function _checkNewJobStructure(&$job) + { + // If job is a valid object and contains the required properties AND does NOT already contain the property error + if (is_object($job) + && property_exists($job, self::PROPERTY_STATUS) + && !property_exists($job, self::PROPERTY_ERROR)) + { + return true; // it is valid! + } + + // If not object then object it! + if (!is_object($job)) $job = new stdClass(); + + // If an error property was not already previously stored then store an error message in job object + if (!property_exists($job, self::PROPERTY_ERROR)) + { + $job->{self::PROPERTY_ERROR} = 'The structure of the provided job is not valid'; + } + + return false; // better sorry than wrong + } + + /** + * Checks the job object structure when needed for update + */ + private function _checkUpdateJobStructure(&$job) + { + // If job is a valid object + if (is_object($job) && property_exists($job, self::PROPERTY_JOBID)) return true; // it is valid! + + // If not object then object it! + if (!is_object($job)) $job = new stdClass(); + + // If an error property was not already previously stored then store an error message in job object + if (!property_exists($job, self::PROPERTY_ERROR)) + { + $job->{self::PROPERTY_ERROR} = 'The structure of the provided job is not valid'; + } + + return false; // better sorry than wrong + } + + /** + * Checks if the given job contains a valid type + */ + private function _checkJobType($type, $types) + { + return $this->_inArray($type, $types, self::PROPERTY_TYPE); + } + + /** + * Checks if the given job contains a valid status + */ + private function _checkJobStatus(&$job, $statuses) + { + $found = $this->_inArray($job->{self::PROPERTY_STATUS}, $statuses, self::PROPERTY_STATUS); + + // No status was not found and does NOT already contain the property error + if (!$found && !property_exists($job, self::PROPERTY_ERROR)) + { + $job->{self::PROPERTY_ERROR} = 'The provided status of this job is not valid'; // store the error message in the object + } + + return $found; + } + + /** + * Search in an array the given value + * The elements of the given array are objects + * The given value is compared with the property specified by the $propertyName parameter of each object of the given array + */ + private function _inArray($value, $array, $propertyName) + { + $found = false; + + foreach ($array as $element) + { + if ($value == $element->{$propertyName}) + { + $found = true; + break; + } + } + + return $found; + } + + /** + * Drop not allowed properties from the given job + */ + private function _dropNotAllowedPropertiesNewJob(&$job) + { + unset($job->{self::PROPERTY_JOBID}); + unset($job->{self::PROPERTY_CREATIONTIME}); + unset($job->{self::PROPERTY_TYPE}); + } + + /** + * Drop not allowed properties from the given job + */ + private function _dropNotAllowedPropertiesUpdateJob(&$job) + { + unset($job->{self::PROPERTY_CREATIONTIME}); + unset($job->{self::PROPERTY_TYPE}); } } From 6b0bf895928e2e4ddb26af8f8e67ff23b8f7d4c8 Mon Sep 17 00:00:00 2001 From: Paolo Date: Fri, 6 Mar 2020 14:25:52 +0100 Subject: [PATCH 022/216] Removed load config loads in JobsQueueLib --- application/libraries/JobsQueueLib.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/application/libraries/JobsQueueLib.php b/application/libraries/JobsQueueLib.php index ac0e38786..ea79e099e 100644 --- a/application/libraries/JobsQueueLib.php +++ b/application/libraries/JobsQueueLib.php @@ -34,9 +34,6 @@ class JobsQueueLib // Gets CI instance $this->_ci =& get_instance(); - // Loads JQM configuration - $this->_ci->config->load('jqm'); - // Loads all needed models $this->_ci->load->model('system/JobsQueue_model', 'JobsQueueModel'); $this->_ci->load->model('system/JobTypes_model', 'JobTypesModel'); From 8363f0d26c6bc76d1753310c034d4406ddce6468 Mon Sep 17 00:00:00 2001 From: Paolo Date: Fri, 6 Mar 2020 14:30:52 +0100 Subject: [PATCH 023/216] Fixed marker in JobsQueueViewer --- application/controllers/system/jq/JobsQueueViewer.php | 3 +++ application/views/system/jq/jobsQueueViewerData.php | 8 ++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/application/controllers/system/jq/JobsQueueViewer.php b/application/controllers/system/jq/JobsQueueViewer.php index 7e8760209..2698d79d1 100644 --- a/application/controllers/system/jq/JobsQueueViewer.php +++ b/application/controllers/system/jq/JobsQueueViewer.php @@ -25,6 +25,9 @@ class JobsQueueViewer extends Auth_Controller // Loads WidgetLib $this->load->library('WidgetLib'); + // Loads JobsQueueLib + $this->load->library('JobsQueueLib'); + // Loads phrases system $this->loadPhrases( array( diff --git a/application/views/system/jq/jobsQueueViewerData.php b/application/views/system/jq/jobsQueueViewerData.php index be09e0baf..023ec5406 100644 --- a/application/views/system/jq/jobsQueueViewerData.php +++ b/application/views/system/jq/jobsQueueViewerData.php @@ -35,22 +35,22 @@ $mark = ''; - if ($datasetRaw->Status == 'Failed') + if ($datasetRaw->Status == JobsQueueLib::STATUS_FAILED) { $mark = 'text-red'; } - if ($datasetRaw->Status == 'Done') + if ($datasetRaw->Status == JobsQueueLib::STATUS_DONE) { $mark = 'text-green'; } - if ($datasetRaw->Status == 'Running') + if ($datasetRaw->Status == JobsQueueLib::STATUS_RUNNING) { $mark = 'text-orange'; } - if ($datasetRaw->Status == 'New') + if ($datasetRaw->Status == JobsQueueLib::STATUS_NEW) { $mark = 'text-info'; } From 4d1dbdfae98b4a51fd22613bbcf6cb7dcad0154a Mon Sep 17 00:00:00 2001 From: Paolo Date: Thu, 12 Mar 2020 18:51:26 +0100 Subject: [PATCH 024/216] - Added new model system/JobTriggers_model - Loads jqm configuration in controller system/jq/JobsQueueManager - Added new table system.tbl_jobtriggers to system/dbupdate_3.3.php - Added new privacy method _addNewTriggeredJobToQueue to JobsQueueLib - JobsQueueLib is called by addNewJobsToQueue and updateJobsQueue --- .../system/jq/JobsQueueManager.php | 3 + application/libraries/JobsQueueLib.php | 64 +++++++++++++++++-- .../models/system/JobTriggers_model.php | 32 ++++++++++ system/dbupdate_3.3.php | 56 ++++++++++++++-- 4 files changed, 144 insertions(+), 11 deletions(-) create mode 100644 application/models/system/JobTriggers_model.php diff --git a/application/controllers/system/jq/JobsQueueManager.php b/application/controllers/system/jq/JobsQueueManager.php index b6e4efe29..e72607675 100644 --- a/application/controllers/system/jq/JobsQueueManager.php +++ b/application/controllers/system/jq/JobsQueueManager.php @@ -26,6 +26,9 @@ class JobsQueueManager extends Auth_Controller ) ); + // Loading config file jqm + $this->config->load('jqm'); + // Loads JobsQueueLib $this->load->library('JobsQueueLib'); // Loads permission lib diff --git a/application/libraries/JobsQueueLib.php b/application/libraries/JobsQueueLib.php index ea79e099e..9aafc808d 100644 --- a/application/libraries/JobsQueueLib.php +++ b/application/libraries/JobsQueueLib.php @@ -38,6 +38,7 @@ class JobsQueueLib $this->_ci->load->model('system/JobsQueue_model', 'JobsQueueModel'); $this->_ci->load->model('system/JobTypes_model', 'JobTypesModel'); $this->_ci->load->model('system/JobStatuses_model', 'JobStatusesModel'); + $this->_ci->load->model('system/JobTriggers_model', 'JobTriggersModel'); } //------------------------------------------------------------------------------------------------------------------ @@ -92,17 +93,21 @@ class JobsQueueLib $job->{self::PROPERTY_TYPE} = $type; // What you asked is what you get! // Try to insert the single job into database - $dbResult = $this->_ci->JobsQueueModel->insert($job); + $dbNewJobResult = $this->_ci->JobsQueueModel->insert($job); // If an error occurred during while inserting in database - if (isError($dbResult)) + if (isError($dbNewJobResult)) { - $job->{self::PROPERTY_ERROR} = getError($dbResult); // retrieve the cause and store it in job object + $job->{self::PROPERTY_ERROR} = getError($dbNewJobResult); // retrieve the cause and store it in job object $errorOccurred = true; // set error occurred flag } else // otherwise { - $job->{self::PROPERTY_JOBID} = getData($dbResult); // get the jobid and store it in job object + $job->{self::PROPERTY_JOBID} = getData($dbNewJobResult); // get the jobid and store it in job object + + $dbNewTriggeredJobResult = $this->_addNewTriggeredJobToQueue($type, $job, array(self::STATUS_NEW)); + // If an error occurred during while inserting in database + if (isError($dbNewTriggeredJobResult)) return $dbNewTriggeredJobResult; } } else // otherwise @@ -137,6 +142,8 @@ class JobsQueueLib // Loops through all the provided jobs foreach ($results as $job) { + // TODO: find if present in database or not!!! + // If the structure of the job object is valid if ($this->_checkUpdateJobStructure($job) && $this->_checkJobStatus($job, $statuses)) { @@ -153,6 +160,16 @@ class JobsQueueLib $job->{self::PROPERTY_ERROR} = getError($dbResult); // retrieve the cause and store it in job object $errorOccurred = true; // set error occurred flag } + else // otherwise + { + $dbNewTriggeredJobResult = $this->_addNewTriggeredJobToQueue( + $type, + $job, + array($job->status) + ); + // If an error occurred during while inserting in database + if (isError($dbNewTriggeredJobResult)) return $dbNewTriggeredJobResult; + } } else // otherwise { @@ -277,4 +294,43 @@ class JobsQueueLib unset($job->{self::PROPERTY_CREATIONTIME}); unset($job->{self::PROPERTY_TYPE}); } + + /** + * Add e new triggered job to the jobs queue + * NOTE: + * - In this method there are less checks compared to addNewJobsToQueue method because + * the new jobs that will be added are generate in this method + * - Job ids in this case are not returned, therefore the caller is not going to be informed about these new jobs + */ + private function _addNewTriggeredJobToQueue($type, $job, $triggeredStatuses) + { + // Get all the job trigggers for the given type and for the given statuses + $dbTriggersResult = $this->_ci->JobTriggersModel->getJobtriggersByTypeStatuses($type, $triggeredStatuses); + + // If an error occurred while getting job triggers from database then return it + if (isError($dbTriggersResult)) return $dbTriggersResult; + if (hasData($dbTriggersResult)) // If triggers were retrieved + { + // The output of the trigging job is the input of the trigged job + $triggeredJobInput = null; + if (isset($job->{self::PROPERTY_OUTPUT})) $triggeredJobInput = $job->{self::PROPERTY_OUTPUT}; + + // For each trigger + foreach (getData($dbTriggersResult) as $trigger) + { + $triggeredJob = array( + self::PROPERTY_TYPE => $trigger->following_type, // the new type is the one defined in tbl_jobtriggers + self::PROPERTY_STATUS => self::STATUS_NEW, // new job status is new + self::PROPERTY_INPUT => $triggeredJobInput // new job input + ); + + // Try to insert the single job into database + $dbNewJob = $this->_ci->JobsQueueModel->insert($triggeredJob); + // If an error occurred during while inserting in database + if (isError($dbNewJob)) return $dbNewJob; + } + } + + return success(); // if here then it was a success! + } } diff --git a/application/models/system/JobTriggers_model.php b/application/models/system/JobTriggers_model.php new file mode 100644 index 000000000..176b4f5b1 --- /dev/null +++ b/application/models/system/JobTriggers_model.php @@ -0,0 +1,32 @@ +dbTable = 'system.tbl_jobtriggers'; + $this->pk = array('type', 'status', 'followingType'); + $this->hasSequence = false; + } + + /** + * + */ + public function getJobtriggersByTypeStatuses($type, $triggeredStatuses) + { + $query = 'SELECT jt.type, + jt.status, + jt.following_type + FROM system.tbl_jobtriggers jt + WHERE jt.type = ? + AND jt.status IN ? + ORDER BY jt.type, jt.status'; + + return $this->execQuery($query, array($type, $triggeredStatuses)); + } +} diff --git a/system/dbupdate_3.3.php b/system/dbupdate_3.3.php index 5bccd5e1a..b54b28373 100644 --- a/system/dbupdate_3.3.php +++ b/system/dbupdate_3.3.php @@ -3846,7 +3846,7 @@ if ($result = $db->db_query("SELECT 1 FROM pg_class WHERE relname = 'unq_idx_abl if (!$result = @$db->db_query('SELECT 1 FROM system.tbl_jobstatuses LIMIT 1')) { $qry = 'CREATE TABLE system.tbl_jobstatuses ( - status character varying NOT NULL + status character varying(64) NOT NULL ); COMMENT ON TABLE system.tbl_jobstatuses IS \'All possible job statuses\'; @@ -3854,10 +3854,10 @@ if (!$result = @$db->db_query('SELECT 1 FROM system.tbl_jobstatuses LIMIT 1')) ALTER TABLE ONLY system.tbl_jobstatuses ADD CONSTRAINT pk_jobstatuses PRIMARY KEY (status); - INSERT INTO system.tbl_jobstatuses(status) VALUES('new'); - INSERT INTO system.tbl_jobstatuses(status) VALUES('running'); - INSERT INTO system.tbl_jobstatuses(status) VALUES('done'); - INSERT INTO system.tbl_jobstatuses(status) VALUES('failed'); + INSERT INTO system.tbl_jobstatuses(status) VALUES(\'new\'); + INSERT INTO system.tbl_jobstatuses(status) VALUES(\'running\'); + INSERT INTO system.tbl_jobstatuses(status) VALUES(\'done\'); + INSERT INTO system.tbl_jobstatuses(status) VALUES(\'failed\'); '; if (!$db->db_query($qry)) @@ -3882,7 +3882,7 @@ if (!$result = @$db->db_query('SELECT 1 FROM system.tbl_jobstatuses LIMIT 1')) if (!$result = @$db->db_query('SELECT 1 FROM system.tbl_jobtypes LIMIT 1')) { $qry = 'CREATE TABLE system.tbl_jobtypes ( - type character varying(256) NOT NULL, + type character varying(128) NOT NULL, description text NOT NULL ); @@ -3916,7 +3916,7 @@ if (!$result = @$db->db_query('SELECT 1 FROM system.tbl_jobsqueue LIMIT 1')) { $qry = 'CREATE TABLE system.tbl_jobsqueue ( jobid integer NOT NULL, - type character varying(256) NOT NULL, + type character varying(128) NOT NULL, creationtime timestamp without time zone DEFAULT now(), status character varying(64) NOT NULL, input jsonb, @@ -3978,6 +3978,47 @@ if (!$result = @$db->db_query('SELECT 1 FROM system.tbl_jobsqueue LIMIT 1')) echo '
Granted privileges to vilesci on system.tbl_jobsqueue'; } +// Creates table system.tbl_jobtriggers if it doesn't exist and grants privileges +if (!$result = @$db->db_query('SELECT 1 FROM system.tbl_jobtriggers LIMIT 1')) +{ + $qry = 'CREATE TABLE system.tbl_jobtriggers ( + type character varying(128) NOT NULL, + status character varying(64) NOT NULL, + following_type character varying(128) NOT NULL + ); + + COMMENT ON TABLE system.tbl_jobtriggers IS \'Table to manage the job triggers\'; + COMMENT ON COLUMN system.tbl_jobtriggers.type IS \'Job type\'; + COMMENT ON COLUMN system.tbl_jobtriggers.status IS \'Job status\'; + COMMENT ON COLUMN system.tbl_jobtriggers.following_type IS \'New job type\'; + + ALTER TABLE ONLY system.tbl_jobtriggers ADD CONSTRAINT pk_jobtriggers PRIMARY KEY (type, status, following_type); + + ALTER TABLE ONLY system.tbl_jobtriggers ADD CONSTRAINT fk_jobtriggers_status FOREIGN KEY (status) REFERENCES system.tbl_jobstatuses(status) ON UPDATE CASCADE ON DELETE RESTRICT; + + ALTER TABLE ONLY system.tbl_jobtriggers ADD CONSTRAINT fk_jobtriggers_type FOREIGN KEY (type) REFERENCES system.tbl_jobtypes(type) ON UPDATE CASCADE ON DELETE RESTRICT; + + ALTER TABLE ONLY system.tbl_jobtriggers ADD CONSTRAINT fk_jobtriggers_following_type FOREIGN KEY (following_type) REFERENCES system.tbl_jobtypes(type) ON UPDATE CASCADE ON DELETE RESTRICT; + '; + + if (!$db->db_query($qry)) + echo 'system.tbl_jobtriggers: '.$db->db_last_error().'
'; + else + echo '
system.tbl_jobtriggers table created'; + + $qry = 'GRANT SELECT ON TABLE system.tbl_jobtriggers TO web;'; + if (!$db->db_query($qry)) + echo 'system.tbl_jobtriggers: '.$db->db_last_error().'
'; + else + echo '
Granted privileges to web on system.tbl_jobtriggers'; + + $qry = 'GRANT SELECT, UPDATE, INSERT, DELETE ON TABLE system.tbl_jobtriggers TO vilesci;'; + if (!$db->db_query($qry)) + echo 'system.tbl_jobtriggers: '.$db->db_last_error().'
'; + else + echo '
Granted privileges to vilesci on system.tbl_jobtriggers'; +} + // *** Pruefung und hinzufuegen der neuen Attribute und Tabellen echo '

Pruefe Tabellen und Attribute!

'; @@ -4238,6 +4279,7 @@ $tabellen=array( "system.tbl_filters" => array("filter_id","app","dataset_name","filter_kurzbz","person_id","description","sort","default_filter","filter","oe_kurzbz","statistik_kurzbz"), "system.tbl_jobsqueue" => array("jobid", "type", "creationtime", "status", "input", "output", "starttime", "endtime", "insertvon", "insertamum"), "system.tbl_jobstatuses" => array("status"), + "system.tbl_jobtriggers" => array("type", "status", "following_type"), "system.tbl_jobtypes" => array("type", "description"), "system.tbl_phrase" => array("phrase_id","app","phrase","insertamum","insertvon","category"), "system.tbl_phrasentext" => array("phrasentext_id","phrase_id","sprache","orgeinheit_kurzbz","orgform_kurzbz","text","description","insertamum","insertvon"), From 0245bff11c66c962fe37a7a0ae49e9aa13fff212 Mon Sep 17 00:00:00 2001 From: alex Date: Fri, 13 Mar 2020 19:23:50 +0100 Subject: [PATCH 025/216] =?UTF-8?q?admin/edit=5Fgebiet:=20Offsetpunkte=20w?= =?UTF-8?q?erden=20aufgerundet=20statt=20kaufm=C3=A4nnisch=20gerundet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cis/testtool/admin/edit_gebiet.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cis/testtool/admin/edit_gebiet.php b/cis/testtool/admin/edit_gebiet.php index 2fe6af39f..405c908cf 100644 --- a/cis/testtool/admin/edit_gebiet.php +++ b/cis/testtool/admin/edit_gebiet.php @@ -265,7 +265,7 @@ if ($gebiet_id != '') { $offsetwarnung = strlen($gebiet->errormsg) > 0 ? ' (HINWEIS: '.$gebiet->errormsg.')' : ''; - $offsethinweis = ' empfohlene Offsetpunkteanzahl: '.round($offsetpunkte).(round($offsetpunkte) != $offsetpunkte ? ' ('.$offsetpunkte.' gerundet)' : '').''; + $offsethinweis = ' empfohlene Offsetpunkteanzahl: '.ceil($offsetpunkte).(ceil($offsetpunkte) != $offsetpunkte ? ' ('.$offsetpunkte.' gerundet)' : '').''; $offsethinweis .= ''.$offsetwarnung.''; } echo 'Offsetpunkte (maximale Negativpunkte)'.$offsethinweis.''; From d00aec9a726e8ca43360873d2e614f9a9ddd4686 Mon Sep 17 00:00:00 2001 From: alex Date: Fri, 13 Mar 2020 19:25:25 +0100 Subject: [PATCH 026/216] =?UTF-8?q?auswertung=5Ffhtw.php:=20-=20multiselec?= =?UTF-8?q?t=20von=20Reihungstests=20m=C3=B6glich=20-=20css=20in=20public/?= =?UTF-8?q?auswertung=5Ffhtw.css=20ausgelagert?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/css/tools/auswertung_fhtw.css | 178 ++++++++ vilesci/stammdaten/auswertung_fhtw.php | 598 +++++++++++++++---------- 2 files changed, 541 insertions(+), 235 deletions(-) create mode 100644 public/css/tools/auswertung_fhtw.css diff --git a/public/css/tools/auswertung_fhtw.css b/public/css/tools/auswertung_fhtw.css new file mode 100644 index 000000000..d50927ef1 --- /dev/null +++ b/public/css/tools/auswertung_fhtw.css @@ -0,0 +1,178 @@ +.info +{ + color: #0c5460; + background-color: #d1ecf1; + padding: .75rem 1.25rem; + border: 1px solid #bee5eb;; +} +.warning +{ + color: #856404; + background-color: #fff3cd; + padding: .75rem 1.25rem; + border: 1px solid #ffeeba; +} +.error +{ + color: #721c24; + background-color: #f8d7da; + padding: .75rem 1.25rem; + border: 1px solid #f5c6cb; +} +.loaderIcon +{ + border: 8px solid #f3f3f3; /* Light grey */ + border-top: 8px solid #3498db; /* Blue */ + border-radius: 50%; + width: 30px; + height: 30px; + animation: spin 2s linear infinite; + margin-right: auto; + margin-left: auto; +} +@keyframes spin +{ + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} +.alert > .btn +{ + padding: 0 6px; +} +/*** Bootstrap popover ***/ +#popover-target label +{ + margin: 0 5px; + display: block; +} +#popover-target input +{ + margin-right: 5px; +} +#popover-target .disabled +{ + color: #ddd; +} +.glyphicon-remove +{ + font-size: 150%; + margin: -5px 0; + top: 4px; +} +.ui-autocomplete-loading +{ + background: white url("../../../skin/images/spinner.gif") right 5px center no-repeat; +} + +#paramstbl +{ + margin-bottom: 0; +} + +#rtwaehlen +{ + white-space: nowrap; + padding: 10px; +} + +.rtchkbox +{ + float: left; +} + +.rtchkboxlabel:hover +{ + color: white; + background-color: #337ab7; + cursor: pointer; +} + +/*.rtchkbox:hover,.rtchkbox input:hover,.rtchkbox label:hover +{ + cursor: pointer; +}*/ + +.rtchkbox label +{ + font-weight: normal; +} + +#rtcheckboxes +{ + height: 100%; + width: 500px; + left: 155px; + position: absolute; + z-index: 9999999; + overflow-y: auto; + border: 1px solid; + padding: 8px; + background-color: white; + display: none +} + +#auswertencell +{ + vertical-align: middle; + padding: 0 5px; + border-right: 1px solid #ddd; + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; +} + +#addpers,#toggleDelete,#checkAllResButton,#showUebertragenOptionsButton,#punkteUebertragenButton +{ + margin-left: 10px; +} + +.loaderIcon +{ + display: none; + margin-top: 10px; +} + +.hiddenEl +{ + display: none; +} + +.textcentered +{ + text-align: center; +} + +th.smallcol +{ + width: 20px; +} + +th.toggletblchkboxcol +{ + width: 30px; +} + +.rightaligned +{ + text-align: right; + padding-right: 3px; +} + +.redcolor +{ + color: red; +} + +.darkredcolor +{ + color: #c82333; +} + +.darkyellowcolor +{ + color: #e0a800; +} + +.zerovalcolor +{ + color: #C10000; +} diff --git a/vilesci/stammdaten/auswertung_fhtw.php b/vilesci/stammdaten/auswertung_fhtw.php index 88e7ef4d8..7bcb33323 100644 --- a/vilesci/stammdaten/auswertung_fhtw.php +++ b/vilesci/stammdaten/auswertung_fhtw.php @@ -102,7 +102,7 @@ if (isset($_REQUEST['autocomplete']) && $_REQUEST['autocomplete'] == 'prestudent if (isset($_REQUEST['autocomplete']) && $_REQUEST['autocomplete'] == 'prestudentAdd') { $search = trim((isset($_REQUEST['term']) ? $_REQUEST['term'] : '')); - $studiensemester_kurzbz = trim((isset($_REQUEST['studiensemester_kurzbz']) ? $_REQUEST['studiensemester_kurzbz'] : '')); + $studiensemester_kurzbz = (isset($_REQUEST['studiensemester_kurzbz']) ? $_REQUEST['studiensemester_kurzbz'] : ''); if (is_null($search) || $search == '') { exit(); @@ -120,11 +120,21 @@ if (isset($_REQUEST['autocomplete']) && $_REQUEST['autocomplete'] == 'prestudent lower(vorname) like '%" . $db->db_escape(mb_strtolower($search)) . "%' OR lower(nachname || ' ' || vorname) like '%" . $db->db_escape(mb_strtolower($search)) . "%' OR lower(vorname || ' ' || nachname) like '%" . $db->db_escape(mb_strtolower($search)) . "%' OR - prestudent_id::text like '%" . $db->db_escape(mb_strtolower($search)) . "%') - AND get_rolle_prestudent(prestudent_id, " . $db->db_add_param($studiensemester_kurzbz) . ") IN ('Interessent') - ORDER BY nachname,vorname,stg - LIMIT 10 - "; + prestudent_id::text like '%" . $db->db_escape(mb_strtolower($search)) . "%')"; + $first = true; + if (is_array($studiensemester_kurzbz)) + $qry .= " AND ("; + foreach ($studiensemester_kurzbz as $stsem) { + $stsem = trim($stsem); + if (!$first) + $qry .= 'OR '; + $qry .= "get_rolle_prestudent(prestudent_id, " . $db->db_add_param($stsem) . ") IN ('Interessent')"; + } + if (is_array($studiensemester_kurzbz)) + $qry .= ")"; + $qry .= + " ORDER BY nachname,vorname,stg + LIMIT 10"; if ($result = $db->db_query($qry)) { @@ -471,63 +481,80 @@ if ($rtFreischalten) $testende = filter_input(INPUT_POST, 'testende', FILTER_VALIDATE_BOOLEAN); if ($testende) { - if (isset($_POST['reihungstest_id']) && is_numeric($_POST['reihungstest_id'])) + /*if (isset($_POST['reihungstest_ids']) && is_array($_POST['reihungstest_ids'])) { - $reihungstest = new reihungstest($_POST['reihungstest_id']); - // Alle Bachelor-Studiengänge holen, bei denen der Bewerber Interessent ist, die Bewerbung abgeschickt hat und bestätigt wurde - // Mail an alle diese Studiengänge senden + $reihungstest = new reihungstest($_POST['reihungstest_id']);*/ + // Alle Bachelor-Studiengänge holen, bei denen der Bewerber Interessent ist, die Bewerbung abgeschickt hat und bestätigt wurde + // Mail an alle diese Studiengänge senden - if (isset($_POST['prestudent_ids'])) + if (isset($_POST['prestudents'])) + { + // Array mit allen Prestudenten aufbauen + $prestudentsrt = $_POST['prestudents']; + $prestudentArray = array(); + foreach ($prestudentsrt AS $prestrt) { - // Array mit allen Prestudenten aufbauen - $prestudentArray = array(); - foreach ($_POST['prestudent_ids'] AS $prest) + $prestudent_id = $prestrt['prestudent_id']; + $reihungstest_id = $prestrt['reihungstest_id']; + $prestudentrolle = new prestudent($prestudent_id); + $reihungstest = new reihungstest($reihungstest_id); + // Wenn der letzte Status Abgewiesener ist, wird der Bewerber ignoriert + $prestudentrolle->getLastStatus($prestudent_id, $reihungstest->studiensemester_kurzbz); + if ($prestudentrolle->status_kurzbz == 'Abgewiesener') { - $prestudentrolle = new prestudent($prest); - // Wenn der letzte Status Abgewiesener ist, wird der Bewerber ignoriert - $prestudentrolle->getLastStatus($prest, $reihungstest->studiensemester_kurzbz); - if ($prestudentrolle->status_kurzbz == 'Abgewiesener') - { - continue; - } - // Letzten Interessentenstatus laden - $prestudentrolle->getLastStatus($prest, $reihungstest->studiensemester_kurzbz, 'Interessent'); - $stg = new studiengang($prestudentrolle->studiengang_kz); + continue; + } + // Letzten Interessentenstatus laden + $prestudentrolle->getLastStatus($prestudent_id, $reihungstest->studiensemester_kurzbz, 'Interessent'); + $stg = new studiengang($prestudentrolle->studiengang_kz); - if ($prestudentrolle->bewerbung_abgeschicktamum != '' - && $prestudentrolle->bestaetigtam != '' - && $prestudentrolle->bestaetigtvon != '' - && $stg->typ == 'b') - { - $prestudentArray[$prestudentrolle->studiengang_kz][$prestudentrolle->orgform_kurzbz][] = $prest; - } + if ($prestudentrolle->bewerbung_abgeschicktamum != '' + && $prestudentrolle->bestaetigtam != '' + && $prestudentrolle->bestaetigtvon != '' + && $stg->typ == 'b') + { + $prestudentArray[$reihungstest_id][$prestudentrolle->studiengang_kz][$prestudentrolle->orgform_kurzbz][] = $prestudent_id; + } - // Setzt "teilgenommen" (Zum Reihungstest angetreten) auf TRUE - $teilgenommen = new reihungstest(); - $teilgenommen->getPersonReihungstest($prestudentrolle->person_id, $_POST['reihungstest_id'], $prestudentrolle->studienplan_id); + // Setzt "teilgenommen" (Zum Reihungstest angetreten) auf TRUE + $teilgenommen = new reihungstest(); + $teilgenommen->getPersonReihungstest($prestudentrolle->person_id, $reihungstest_id, $prestudentrolle->studienplan_id); - $teilgenommen->new = false; - $teilgenommen->teilgenommen = true; - $teilgenommen->updateamum = date('Y-m-d H:i:s'); - $teilgenommen->updatevon = $user; + $teilgenommen->new = false; + $teilgenommen->teilgenommen = true; + $teilgenommen->updateamum = date('Y-m-d H:i:s'); + $teilgenommen->updatevon = $user; - if (!$teilgenommen->savePersonReihungstest()) - { - echo json_encode(array( - 'status' => 'fehler', - 'msg' => 'Fehler beim speichern der Reihungstestteilnahme: '.$teilgenommen->errormsg - )); - exit(); - } + if (!$teilgenommen->savePersonReihungstest()) + { + echo json_encode(array( + 'status' => 'fehler', + 'msg' => 'Fehler beim Speichern der Reihungstestteilnahme: '.$teilgenommen->errormsg + )); + exit(); } } + } - $sendError = false; - $empfaengerArray = array(); - foreach ($prestudentArray AS $studiengang_kz => $OrgFormPrestudent) + $sendError = false; + $empfaengerArray = array(); + $rtidArray = array(); + + foreach ($prestudentsrt as $psrt) + { + if (!in_array($psrt['reihungstest_id'], $rtidArray)) + $rtidArray[] = $psrt['reihungstest_id']; + } + + $rtidparams = http_build_query(array('reihungstest' => $rtidArray)); + + foreach ($prestudentArray AS $reihungstest_id => $studiengang) + { + foreach ($studiengang AS $studiengang_kz => $OrgFormPrestudent) { foreach ($OrgFormPrestudent AS $orgForm => $prestudent_id) { + $rtest = new reihungstest($reihungstest_id); $empfaenger = getMailEmpfaenger($studiengang_kz, null, $orgForm); //Pfuschloesung fur BIF Dual if (CAMPUS_NAME == 'FH Technikum Wien' && $studiengang_kz == 257 && $orgForm == 'DUA') @@ -561,12 +588,12 @@ if ($testende) '; - $mailtext .= 'Der Reihungstest vom ' . $datum_obj->convertISODate($reihungstest->datum) . ' um ' . $datum_obj->formatDatum($reihungstest->uhrzeit, 'H:i') . ' Uhr ist beendet.'; - $mailtext .= '
Es haben '.$anzahl.' Person(en) aus dem Studiengang '.$stg->kuerzel.'-'.$orgForm.' teilgenommen.'; - $mailtext .= '

Link zur Auswertung'; - $mailtext .= '

Link zur Pivot-Tabelle für die Priorisierung'; - $mailtext .= '

Reihung der BewerberInnen: Prio 1 innerhalb von 2 Werktagen, Prio 2 am 3. Werktag und Prio 3 am 4. Werktag'; - $mailtext .= ' + $mailtext .= 'Der Reihungstest vom '.$datum_obj->convertISODate($rtest->datum).' um '.$datum_obj->formatDatum($rtest->uhrzeit, 'H:i').' Uhr ist beendet.'; + $mailtext .= '
Es haben '.$anzahl.' Person(en) aus dem Studiengang '.$stg->kuerzel.'-'.$orgForm.' teilgenommen.'; + $mailtext .= '

Link zur Auswertung'; + $mailtext .= '

Link zur Pivot-Tabelle für die Priorisierung'; + $mailtext .= '

Reihung der BewerberInnen: Prio 1 innerhalb von 2 Werktagen, Prio 2 am 3. Werktag und Prio 3 am 4. Werktag'; + $mailtext .= ' @@ -587,8 +614,8 @@ if ($testende) $mail = new mail($empfaenger, 'no-reply', 'Reihungstest vom '.$datum_obj->convertISODate($reihungstest->datum).' um '.$datum_obj->formatDatum($reihungstest->uhrzeit, 'H:i').' beendet', 'Bitte sehen Sie sich die Nachricht in HTML Sicht an, um den Link vollständig darzustellen.'); $mail->setHTMLContent($mailtext); - $mail->addEmbeddedImage(APP_ROOT . 'skin/images/sancho/sancho_header_min_bw.jpg', 'image/jpg', 'header_image', 'sancho_header'); - $mail->addEmbeddedImage(APP_ROOT . 'skin/images/sancho/sancho_footer_min_bw.jpg', 'image/jpg', 'footer_image', 'sancho_footer'); + $mail->addEmbeddedImage(APP_ROOT.'skin/images/sancho/sancho_header_min_bw.jpg', 'image/jpg', 'header_image', 'sancho_header'); + $mail->addEmbeddedImage(APP_ROOT.'skin/images/sancho/sancho_footer_min_bw.jpg', 'image/jpg', 'footer_image', 'sancho_footer'); $mail->setBCCRecievers('kindlm@technikum-wien.at'); if (!$mail->send()) @@ -610,7 +637,8 @@ if ($testende) $empfaengerArray = array_unique($empfaengerArray); echo json_encode(array( 'status' => 'ok', - 'msg' => 'Nachricht erfolgreich verschickt an: ' . implode(',',$empfaengerArray))); + 'msg' => 'Nachricht erfolgreich verschickt an: '.implode(',', $empfaengerArray) + )); exit(); } } @@ -718,9 +746,9 @@ if (isset($_POST['method']) && $_POST['method'] == 'addPerson') $punkteUebertragen = filter_input(INPUT_POST, 'punkteUebertragen', FILTER_VALIDATE_BOOLEAN); if ($punkteUebertragen) { - if (isset($_POST['reihungstest_id']) && is_numeric($_POST['reihungstest_id'])) - { - $reihungstest = new reihungstest($_POST['reihungstest_id']); +/* if (isset($_POST['reihungstest_id']) && is_numeric($_POST['reihungstest_id'])) + {*/ + //$reihungstest = new reihungstest(/*$_POST['reihungstest_id']*/); $msg_warning = ''; $msg_error = ''; $count_success_punkte = 0; @@ -731,6 +759,7 @@ if ($punkteUebertragen) { foreach ($_POST['prestudentPunkteArr'] AS $key => $array) { + $reihungstest = new reihungstest($array['reihungstest_id']); $rtpunkte = number_format(floatval(str_replace(',', '.', $array['ergebnis'])), 4); $prestudentrolle = new prestudent($array['prestudent_id']); $prestudentrolle->getLastStatus($array['prestudent_id'], null, 'Interessent'); @@ -742,10 +771,10 @@ if ($punkteUebertragen) } // Checken, ob Person-Reihungstest-Studienplan zuteilung existiert - if ($reihungstest->checkPersonRtStudienplanExists($prestudentrolle->person_id, $_POST['reihungstest_id'], $prestudentrolle->studienplan_id)) + if ($reihungstest->checkPersonRtStudienplanExists($prestudentrolle->person_id, $array['reihungstest_id'], $prestudentrolle->studienplan_id)) { $setRTPunkte = new reihungstest(); - $setRTPunkte->getPersonReihungstest($prestudentrolle->person_id, $_POST['reihungstest_id'], $prestudentrolle->studienplan_id); + $setRTPunkte->getPersonReihungstest($prestudentrolle->person_id, $array['reihungstest_id'], $prestudentrolle->studienplan_id); // Check, ob Punkte schon befüllt sind if ($setRTPunkte->punkte == '') @@ -774,20 +803,20 @@ if ($punkteUebertragen) $setRTPunkte = new reihungstest(); $ort_kurzbz = ''; // Checken, ob schon irgendeine Raumzuteilung existiert (Check ohne Studienplan) und diese ggf. übernehmen - $setRTPunkte->getPersonReihungstest($prestudentrolle->person_id, $_POST['reihungstest_id']); + $setRTPunkte->getPersonReihungstest($prestudentrolle->person_id, $array['reihungstest_id']); if ($setRTPunkte->ort_kurzbz != '') { $ort_kurzbz = $setRTPunkte->ort_kurzbz; } $setRTPunkte = new reihungstest(); - $setRTPunkte->getPersonReihungstest($prestudentrolle->person_id, $_POST['reihungstest_id'], $prestudentrolle->studienplan_id); + $setRTPunkte->getPersonReihungstest($prestudentrolle->person_id, $array['reihungstest_id'], $prestudentrolle->studienplan_id); // Check, ob Punkte schon befüllt sind if ($setRTPunkte->punkte == '') { $setRTPunkte->new = true; $setRTPunkte->person_id = $prestudentrolle->person_id; - $setRTPunkte->reihungstest_id = $_POST['reihungstest_id']; + $setRTPunkte->reihungstest_id = $array['reihungstest_id']; $setRTPunkte->anmeldedatum = ''; $setRTPunkte->teilgenommen = true; $setRTPunkte->ort_kurzbz = $ort_kurzbz; @@ -934,7 +963,6 @@ if ($punkteUebertragen) 'msg_warning' => $msg_warning, 'msg_error' => $msg_error)); exit(); - } } function sortByField($multArray, $sortField, $desc = true) @@ -1055,14 +1083,23 @@ $orgform_kurzbz = isset($_REQUEST['orgform_kurzbz']) ? $_REQUEST['orgform_kurzbz $format = (isset($_REQUEST['format']) ? $_REQUEST['format'] : ''); $rtStudiensemester = ''; -if ($reihungstest != '' && is_numeric($reihungstest)) +if ($reihungstest != '' && (is_array($reihungstest) || is_numeric($reihungstest))) { - $reihungstestObj = new reihungstest($reihungstest); - $rtStudiensemester = $reihungstestObj->studiensemester_kurzbz; + $rtStudiensemester = array(); + + if (is_numeric($reihungstest)) + $reihungstest = array($reihungstest); + + foreach ($reihungstest as $rt_id) + { + $reihungstestObj = new reihungstest($rt_id); + if (!in_array($reihungstestObj->studiensemester_kurzbz, $rtStudiensemester)) + $rtStudiensemester[] = $reihungstestObj->studiensemester_kurzbz; + } } -elseif ($reihungstest != '' && !is_numeric($reihungstest)) +elseif ($reihungstest != '' && !is_array($reihungstest) && !is_numeric($reihungstest)) { - die('ReihungstestID ist ungueltig'); + die('ReihungstestIDs sind ungueltig'); } if ($studiengang != '' && is_numeric($studiengang)) { @@ -1116,7 +1153,7 @@ $sql_query = "SELECT * FROM public.tbl_reihungstest WHERE date_part('year',datum // Wenn Reihungstest ID gesetzt ist, diesen Test zusaetzlich laden, um auch jene außerhalbs des Datumszeitraums zu erwischen if ($reihungstest != '') { - $sql_query .= "UNION SELECT * FROM public.tbl_reihungstest WHERE reihungstest_id=" . $db->db_add_param($reihungstest, FHC_INTEGER); + $sql_query .= "UNION SELECT * FROM public.tbl_reihungstest WHERE reihungstest_id IN (" . $db->implode4SQL($reihungstest) . ")"; } $sql_query .= " ORDER BY datum,uhrzeit"; @@ -1171,7 +1208,7 @@ if (isset($_REQUEST['reihungstest'])) AND NOT (testtool.tbl_ablauf.gebiet_id IN ( SELECT testtool.tbl_kategorie.gebiet_id FROM testtool.tbl_kategorie))"; if ($reihungstest != '') { - $query .= " AND rt_id = " . $db->db_add_param($reihungstest, FHC_INTEGER); + $query .= " AND rt_id IN (" . $db->implode4SQL($reihungstest) . ")"; } if ($studiengang != '') { @@ -1343,7 +1380,8 @@ if (isset($_REQUEST['reihungstest'])) AND testtool.tbl_frage.gebiet_id = tbl_gebiet.gebiet_id ) END AS punkte, - tbl_gebiet.gebiet_id, + rt.reihungstest_id, + tbl_gebiet.gebiet_id, tbl_gebiet.bezeichnung AS gebiet, tbl_pruefling.idnachweis, tbl_pruefling.registriert, @@ -1399,7 +1437,7 @@ if (isset($_REQUEST['reihungstest'])) "; if ($reihungstest != '') { - $query .= " AND rt_id = " . $db->db_add_param($reihungstest, FHC_INTEGER); + $query .= " AND rt_id IN (" . $db->implode4SQL($reihungstest) . ")"; } if ($studiengang != '') { @@ -1451,6 +1489,7 @@ if (isset($_REQUEST['reihungstest'])) $ergebnis[$row->prestudent_id]->prestudent_id = $row->prestudent_id; $ergebnis[$row->prestudent_id]->person_id = $row->person_id; + $ergebnis[$row->prestudent_id]->reihungstest_id = $row->reihungstest_id; //$ergebnis[$row->prestudent_id]->pruefling_id = $row->pruefling_id; $ergebnis[$row->prestudent_id]->nachname = $row->nachname; $ergebnis[$row->prestudent_id]->vorname = $row->vorname; @@ -1598,7 +1637,32 @@ if (isset($_REQUEST['format']) && $_REQUEST['format'] == 'xls') $workbook = new Spreadsheet_Excel_Writer(); // sending HTTP headers - $workbook->send("Auswertung " . ((isset ($_REQUEST['reihungstest']) && $_REQUEST['reihungstest'] != '') ? $stg_arr[$rtest[$reihungstest]->studiengang_kz] . " " . $datum_obj->formatDatum($rtest[$reihungstest]->datum, 'd.m.Y') : 'aller Reihungstests') . ".xls"); + $stgstr = ''; + if ((isset ($_REQUEST['reihungstest']) && $_REQUEST['reihungstest'] != '')) + { + $rtdates = array(); + foreach ($reihungstest as $index => $rt_id) + { + $rtdate = $datum_obj->formatDatum($rtest[$rt_id]->datum, 'd.m.Y'); + if (!isset($rtdates[$rtdate])) + $rtdates[$rtdate] = array(); + + $rtdates[$rtdate][] = $stg_arr[$rtest[$rt_id]->studiengang_kz]; + /*$stgstr .= " " . $stg_arr[$rtest[$rt_id]->studiengang_kz]; + if (isset($reihungstest[$index + 1]) && $reihungstest[$index + 1] !== ) + $stgstr .= ' ' . $rtdate; + *//*if (!in_array($rtdate, $rtdates)) + $rtdates[] = $rtdate;*//*. " " . $datum_obj->formatDatum($rtest[$rt_id]->datum, 'd.m.Y');*/ + } + foreach ($rtdates as $rtdate => $stgs) + { + $stgstr .= " " . implode("_", $stgs) . "_" . $rtdate; + } + } + else + $stgstr = "aller Reihungstests"; + + $workbook->send("Auswertung" . $stgstr . ".xls"); $workbook->setVersion(8); $workbook->setCustomColor(15, 192, 192, 192); //Setzen der HG-Farbe Hellgrau $workbook->setCustomColor(22, 193, 0, 0); //Setzen der HG-Farbe Dunkelrot @@ -1929,6 +1993,7 @@ else + @@ -1951,11 +2016,36 @@ else - @@ -2528,12 +2592,66 @@ else
- +
- + echo '';*/ + echo ''; echo ' -
- Reihungstest wählen: - + Reihungstest wählen: '; + $selectedrtstr = ''; + $checkbxstr = ''; + $first = true; + //$maxeachline = 1; + foreach ($rtest as $rt) + { + $rtstr = $rt->datum . ' ' . $datum_obj->formatDatum($rt->uhrzeit,'H:i') . ' ' . (isset($stg_arr[$rt->studiengang_kz]) ? $stg_arr[$rt->studiengang_kz] : '') . ' ' . $rt->ort_kurzbz . ' ' . $rt->anmerkung; + + $checked = ''; + if (isset($reihungstest) && is_array($reihungstest)) + { + foreach ($reihungstest as $rttest) + { + if ($rttest === $rt->reihungstest_id) + { + $checked = ' checked'; + + if (!$first) + $selectedrtstr .= '
'; + + $selectedrtstr .= $rtstr; + $first = false; + break; + } + } + } +/* if ($rt->reihungstest_id == $reihungstest && !$select) + { + //$selected = 'selected'; + $select = true; + } + elseif ($prestudent_id == '' && $reihungstest == '' && $rt->datum == date('Y-m-d') && $datum_von == '' && $datum_bis == '' && $studiengang == '' && $semester == '' && !$select) + { + //$selected = 'selected'; + $select = true; + } + else + { + $selected = ''; + }*/ + +/* $checkbxstr .= ''; + $checkbxstr .= '

';*/ + $checkbxstr .= '
'; + $checkbxstr .= '
' . ' ' . $rtstr . '
'; + //echo '\n"; + } + + //var_dump($selectedrtstr); + $btntxt = $selectedrtstr === '' ? '-- keine Auswahl --' : $selectedrtstr; + echo ' +
'; + echo $checkbxstr; + + /*echo '
Studiengang: '; - echo 'von Datum:  '; + echo ' von Datum:  '; echo 'bis Datum: '; echo '
'; echo 'PrestudentIn: '; echo '
'; +
'; echo '

'; echo ' -
'; + &' . http_build_query(array('reihungstest' => $reihungstest)) . '"> +
'; echo '
'; + $disabledZuteilen = true; + $disabledTestende = true; + $rt_id_val = ''; if ($reihungstest != '') { - $disabled = false; - } - else - { - $disabled = true; + $disabledTestende = false; + if (count($reihungstest) == 1) + { + $rt_id_val = $reihungstest[0]; + $disabledZuteilen = false; + } } // Button um Assistenz über Testende zu informieren // Nur aktiv, wenn Reihungstest ausgewählt if ($rechte->isBerechtigtMultipleOe('lehre/reihungstestAufsicht', $berechtigteOes, 'su')) { - echo ''; + echo ''; } // Input um Personen hinzuzufügen @@ -2696,13 +2819,13 @@ else if ($rechte->isBerechtigt('lehre/reihungstestAufsicht', null, 'sui')) { echo ' -
- +
+ - + - @@ -2711,15 +2834,15 @@ else } if ($rechte->isBerechtigt('lehre/reihungstestAufsicht', null, 'suid')) { - echo ''; + echo ''; } echo '

'; echo ''; - echo ''; - echo ''; + echo ''; + echo ''; echo '
'; echo '
-