From 4c6fb8d7aba8998b06e825f575ea1e9dc600647d Mon Sep 17 00:00:00 2001 From: Erik Amaru Ortiz Date: Fri, 8 Jul 2011 19:06:32 -0400 Subject: [PATCH] BUG 0000 Report tables ver2, improvements and unification with PMTables (first commit) --- gulliver/system/class.controller.php | 12 +- gulliver/system/class.httpProxyController.php | 1 + gulliver/templates/controller.exception.tpl | 58 + workflow/engine/classes/class.spool.php | 2 +- .../engine/classes/model/AdditionalTables.php | 133 +- workflow/engine/controllers/pmTables.php | 243 ++++ workflow/engine/controllers/pmTablesProxy.php | 512 ++++++++ workflow/engine/menus/setup.php | 2 + .../additionalTables/additionalTablesData.php | 2 +- .../additionalTables/additionalTablesData.js | 2 +- .../additionalTables/map/TableMapBuilder.tpl | 4 +- .../additionalTables/om/BaseTablePeer.tpl | 2 +- workflow/engine/templates/pmTables/data.js | 287 ++++ workflow/engine/templates/pmTables/edit.js | 866 ++++++++++++ .../engine/templates/pmTables/editReport.js | 1161 +++++++++++++++++ workflow/engine/templates/pmTables/list.html | 3 + workflow/engine/templates/pmTables/list.js | 422 ++++++ .../engine/templates/reportTables/edit.js | 6 +- workflow/public_html/images/addcolumn.jpg | Bin 0 -> 1596 bytes .../public_html/images/database-start.png | Bin 0 -> 625 bytes 20 files changed, 3691 insertions(+), 27 deletions(-) create mode 100644 gulliver/templates/controller.exception.tpl create mode 100644 workflow/engine/controllers/pmTables.php create mode 100644 workflow/engine/controllers/pmTablesProxy.php create mode 100644 workflow/engine/templates/pmTables/data.js create mode 100644 workflow/engine/templates/pmTables/edit.js create mode 100644 workflow/engine/templates/pmTables/editReport.js create mode 100644 workflow/engine/templates/pmTables/list.html create mode 100644 workflow/engine/templates/pmTables/list.js create mode 100644 workflow/public_html/images/addcolumn.jpg create mode 100644 workflow/public_html/images/database-start.png diff --git a/gulliver/system/class.controller.php b/gulliver/system/class.controller.php index b0dd1ec06..703d5e252 100644 --- a/gulliver/system/class.controller.php +++ b/gulliver/system/class.controller.php @@ -21,6 +21,8 @@ class Controller private $headPublisher; public $ExtVar = Array(); + + public $controllerClass = ''; public function __construct() { @@ -97,7 +99,15 @@ class Controller $this->$name($this->__request__); } catch (Exception $e) { - new PMException($e->getMessage(), 1); + $template = new TemplatePower(PATH_TEMPLATE . 'controller.exception.tpl'); + $template->prepare(); + $template->assign('controller', get_called_class()); + $template->assign('message', $e->getMessage()); + $template->assign('file', $e->getFile()); + $template->assign('line', $e->getLine()); + $template->assign('trace', $e->getTraceAsString()); + + echo $template->getOutputContent(); } } diff --git a/gulliver/system/class.httpProxyController.php b/gulliver/system/class.httpProxyController.php index 2dddcbff9..a3f6f9757 100755 --- a/gulliver/system/class.httpProxyController.php +++ b/gulliver/system/class.httpProxyController.php @@ -97,6 +97,7 @@ class HttpProxyController { $result->exception->class = get_class($e); $result->exception->code = $e->getCode(); + $result->exception->trace = $e->getTraceAsString(); } print G::json_encode($result); } diff --git a/gulliver/templates/controller.exception.tpl b/gulliver/templates/controller.exception.tpl new file mode 100644 index 000000000..204cf3544 --- /dev/null +++ b/gulliver/templates/controller.exception.tpl @@ -0,0 +1,58 @@ + + + + +Server Error :: + + + + + +
+ +
+
+ + + + +
+ CONTROLLER EXCEPTION
+
+ {message}

+ Controller: {controller}
+ File: {file}
+ Line: {line} +
+
+ + + +
{trace}
+
+ +
+ + + diff --git a/workflow/engine/classes/class.spool.php b/workflow/engine/classes/class.spool.php index 7d5367240..eee4399e8 100755 --- a/workflow/engine/classes/class.spool.php +++ b/workflow/engine/classes/class.spool.php @@ -363,7 +363,7 @@ class spoolRun { /** * Posible Options for SMTPSecure are: "", "ssl" or "tls" */ - if (preg_match('/^(ssl|tls)$/', $this->config['SMTPSecure'])) { + if (isset($this->config['SMTPSecure']) && preg_match('/^(ssl|tls)$/', $this->config['SMTPSecure'])) { $oPHPMailer->SMTPSecure = $this->config['SMTPSecure']; } diff --git a/workflow/engine/classes/model/AdditionalTables.php b/workflow/engine/classes/model/AdditionalTables.php index 9301ade4d..29b60df26 100644 --- a/workflow/engine/classes/model/AdditionalTables.php +++ b/workflow/engine/classes/model/AdditionalTables.php @@ -253,7 +253,7 @@ class AdditionalTables extends BaseAdditionalTables { } function createTable($sTableName, $sConnection = '', $aFields = array()) { - $sTableName = $sTableName; + if ($sConnection == '' || $sConnection == 'wf') { $sConnection = 'workflow'; } @@ -425,6 +425,8 @@ class AdditionalTables extends BaseAdditionalTables { } function updateTable($sTableName, $sConnection = 'wf', $aNewFields = array(), $aOldFields = array()) { + $debug=false; + if ($sConnection == '' || $sConnection == 'wf') { $sConnection = 'workflow'; } @@ -455,11 +457,25 @@ class AdditionalTables extends BaseAdditionalTables { $aFieldsToDelete[] = $aOldField; } } - + if ($debug) { + echo 'new'; + print_r($aNewFields); + echo 'old'; + print_r($aOldFields); + echo 'to add'; + print_r($aFieldsToAdd); + echo 'keys'; + print_r($aKeys); + echo 'to delete'; + print_r($aFieldsToDelete); + } + foreach ($aNewFields as $aNewField) { if (isset($aOldFields[$aNewField['FLD_UID']])) { + $aOldField = $aOldFields[$aNewField['FLD_UID']]; $bEqual = true; + if (trim($aNewField['FLD_NAME']) != trim($aOldField['FLD_NAME'])) { $bEqual = false; } @@ -483,7 +499,12 @@ class AdditionalTables extends BaseAdditionalTables { $aFieldsToAlter[] = $aNewField; } } - } + + } + + if ($debug) { + echo 'to alter'; print_r($aFieldsToAlter); + } G::LoadSystem('database_' . strtolower(DB_ADAPTER)); $oDataBase = new database(DB_ADAPTER, DB_HOST, DB_USER, DB_PASS, DB_NAME); @@ -492,12 +513,28 @@ class AdditionalTables extends BaseAdditionalTables { //$oDataBase->executeQuery($oDataBase->generateDropPrimaryKeysSQL($sTableName)); $con = Propel::getConnection($sConnection); $stmt = $con->createStatement(); + $sQuery = $oDataBase->generateDropPrimaryKeysSQL($sTableName); + if ($debug) { + echo 'sql drop pk'; + var_dump($sQuery); + } try { $rs = $stmt->executeQuery($sQuery); } catch(PDOException $oException ) { throw $oException; } + + foreach ($aFieldsToDelete as $aFieldToDelete) { + //$oDataBase->executeQuery($oDataBase->generateDropColumnSQL($sTableName, strtoupper($aFieldToDelete['FLD_NAME']))); + $sQuery = $oDataBase->generateDropColumnSQL($sTableName, strtoupper($aFieldToDelete['FLD_NAME'])); + if ($debug) { + echo 'sql drop field'; + var_dump($sQuery); + } + $rs = $stmt->executeQuery($sQuery); + } + foreach ($aFieldsToAdd as $aFieldToAdd) { switch ($aFieldToAdd['FLD_TYPE']) { case 'VARCHAR': @@ -540,17 +577,19 @@ class AdditionalTables extends BaseAdditionalTables { //$oDataBase->executeQuery($oDataBase->generateAddColumnSQL($sTableName, strtoupper($aFieldToAdd['FLD_NAME']), $aData)); $sQuery = $oDataBase->generateAddColumnSQL($sTableName, strtoupper($aFieldToAdd['FLD_NAME']), $aData); - $rs = $stmt->executeQuery($sQuery); - - } - foreach ($aFieldsToDelete as $aFieldToDelete) { - //$oDataBase->executeQuery($oDataBase->generateDropColumnSQL($sTableName, strtoupper($aFieldToDelete['FLD_NAME']))); - $sQuery = $oDataBase->generateDropColumnSQL($sTableName, strtoupper($aFieldToDelete['FLD_NAME'])); + if ($debug) { + echo 'sql add'; + var_dump($sQuery); + } $rs = $stmt->executeQuery($sQuery); } //$oDataBase->executeQuery($oDataBase->generateAddPrimaryKeysSQL($sTableName, $aKeys)); $sQuery = $oDataBase->generateAddPrimaryKeysSQL($sTableName, $aKeys); + if ($debug) { + echo 'sql gen pk'; + var_dump($sQuery); + } $rs = $stmt->executeQuery($sQuery); foreach ($aFieldsToAlter as $aFieldToAlter) { @@ -595,6 +634,10 @@ class AdditionalTables extends BaseAdditionalTables { //$oDataBase->executeQuery($oDataBase->generateChangeColumnSQL($sTableName, strtoupper($aFieldToAlter['FLD_NAME']), $aData, strtoupper($aFieldToAlter['FLD_NAME_OLD']))); $sQuery = $oDataBase->generateChangeColumnSQL($sTableName, strtoupper($aFieldToAlter['FLD_NAME']), $aData, strtoupper($aFieldToAlter['FLD_NAME_OLD'])); + if ($debug) { + echo 'sql alter'; + var_dump($sQuery); + } $rs = $stmt->executeQuery($sQuery); } } @@ -603,7 +646,7 @@ class AdditionalTables extends BaseAdditionalTables { } } - function createPropelClasses($sTableName, $sClassName, $aFields, $sAddTabUid) { + function createPropelClasses($sTableName, $sClassName, $aFields, $sAddTabUid, $connection='workflow') { try { /*$aUID = array('FLD_NAME' => 'PM_UNIQUE_ID', 'FLD_TYPE' => 'INT', @@ -632,14 +675,19 @@ class AdditionalTables extends BaseAdditionalTables { $sPath = PATH_DB . SYS_SYS . PATH_SEP . 'classes' . PATH_SEP; if (!file_exists($sPath)) { - G::mk_dir($sPath); + G::mk_dir($sPath); + } + if (!file_exists($sPath . 'map')) { G::mk_dir($sPath . 'map'); - G::mk_dir($sPath . 'om'); + } + if (!file_exists($sPath . 'om')) { + G::mk_dir($sPath . 'om'); } $aData = array(); $aData['pathClasses'] = substr(PATH_DB, 0, -1); $aData['tableName'] = $sTableName; $aData['className'] = $sClassName; + $aData['connection'] = $connection; $aData['GUID'] = $sAddTabUid; $aData['firstColumn'] = strtoupper($aFields[1]['FLD_NAME']); $aData['totalColumns'] = count($aFields); @@ -770,13 +818,13 @@ class AdditionalTables extends BaseAdditionalTables { break; } $aColumns[] = $aColumn; - if ($aField['FLD_KEY'] == 'on') { + if ($aField['FLD_KEY'] == 1 || $aField['FLD_KEY'] === 'on') { $aPKs[] = $aColumn; } else { $aNotPKs[] = $aColumn; } - if ($aField['FLD_AUTO_INCREMENT'] == 'on') { + if ($aField['FLD_AUTO_INCREMENT'] == 1 || $aField['FLD_AUTO_INCREMENT'] === 'on') { $aData['useIdGenerator'] = 'true'; } $i++; @@ -1027,11 +1075,12 @@ class AdditionalTables extends BaseAdditionalTables { //deleting clases $sClassName = $this->getPHPName($aData['ADD_TAB_CLASS_NAME'] != '' ? $aData['ADD_TAB_CLASS_NAME'] : $aData['ADD_TAB_NAME']); $sPath = PATH_DB . SYS_SYS . PATH_SEP . 'classes' . PATH_SEP; + @unlink($sPath . $sClassName . '.php'); @unlink($sPath . $sClassName . 'Peer.php'); - @unlink($sPath . PATH_SEP . 'map' . PATH_SEP . $sClassName . 'MapBuilder.php'); - @unlink($sPath . PATH_SEP . 'om' . PATH_SEP . 'Base' . $sClassName . '.php'); - @unlink($sPath . PATH_SEP . 'om' . PATH_SEP . 'Base' . $sClassName . 'Peer.php'); + @unlink($sPath . 'map' . PATH_SEP . $sClassName . 'MapBuilder.php'); + @unlink($sPath . 'om' . PATH_SEP . 'Base' . $sClassName . '.php'); + @unlink($sPath . 'om' . PATH_SEP . 'Base' . $sClassName . 'Peer.php'); } catch (Exception $oError) { throw($oError); @@ -1119,7 +1168,10 @@ var additionalTablesDataDelete = function(sUID, sKeys) { } $sClassPeerName = $sClassName . 'Peer'; - $oCriteria = new Criteria('workflow'); + $con = Propel::getConnection($aData['DBS_UID']); + $oCriteria = new Criteria($aData['DBS_UID']); + var_dump($aData['DBS_UID']); + print_r($oCriteria); //eval('$oCriteria->addSelectColumn(' . $sClassPeerName . '::PM_UNIQUE_ID);'); eval('$oCriteria->addSelectColumn("\'1\' AS DUMMY");'); foreach ($aData['FIELDS'] as $aField) { @@ -1147,6 +1199,47 @@ var additionalTablesDataDelete = function(sUID, sKeys) { } } + function getAllData($sUID, $start=NULL, $limit=NULL) + { + $aData = $this->load($sUID, true); + $sPath = PATH_DB . SYS_SYS . PATH_SEP . 'classes' . PATH_SEP; + $sClassName = ($aData['ADD_TAB_CLASS_NAME'] != '' ? $aData['ADD_TAB_CLASS_NAME'] : $this->getPHPName($aData['ADD_TAB_NAME'])); + + if (file_exists ($sPath . $sClassName . '.php') ) { + require_once $sPath . $sClassName . '.php'; + } else { + return null; + } + + $sClassPeerName = $sClassName . 'Peer'; + $con = Propel::getConnection($aData['DBS_UID']); + $oCriteria = new Criteria($aData['DBS_UID']); + + eval('$oCriteria->addSelectColumn("\'1\' AS DUMMY");'); + foreach ($aData['FIELDS'] as $aField) { + eval('$oCriteria->addSelectColumn(' . $sClassPeerName . '::' . $aField['FLD_NAME'] . ');'); + } + + $oCriteriaCount = clone $oCriteria; + $count = $sClassPeerName::doCount($oCriteria); + + if (isset($limit)) { + $oCriteria->setLimit($limit); + } + if (isset($start)) { + $oCriteria->setOffset($start); + } + $rs = $sClassPeerName::doSelectRS($oCriteria); + $rs->setFetchmode (ResultSet::FETCHMODE_ASSOC); + + $rows = Array(); + while ($rs->next()) { + $rows[] = $rs->getRow(); + } + + return array('rows' => $rows, 'count' => $count); + } + function checkClassNotExist($sUID) { try { $aData = $this->load($sUID, true); @@ -1366,6 +1459,8 @@ var additionalTablesDataDelete = function(sUID, sKeys) { public function populateReportTable($sTableName, $sConnection = 'rp', $sType = 'NORMAL', $aFields = array(), $sProcessUid = '', $sGrid = '') { + require_once "classes/model/Application.php"; + $con = Propel::getConnection($sConnection); $stmt = $con->createStatement(); if ($sType == 'GRID') { @@ -1862,6 +1957,8 @@ var additionalTablesDataDelete = function(sUID, sKeys) { $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); $addTables = Array(); + $proUids = Array(); + while( $oDataset->next() ) { $row = $oDataset->getRow(); $row['PRO_TITLE'] = $row['PRO_DESCRIPTION'] = ''; diff --git a/workflow/engine/controllers/pmTables.php b/workflow/engine/controllers/pmTables.php new file mode 100644 index 000000000..ffd7d0f6f --- /dev/null +++ b/workflow/engine/controllers/pmTables.php @@ -0,0 +1,243 @@ +requirePermissions('PM_SETUP_ADVANCE'); + + G::LoadClass('configuration'); + $c = new Configurations(); + $configPage = $c->getConfiguration('additionalTablesList', 'pageSize','',$_SESSION['USER_LOGGED']); + $Config['pageSize'] = isset($configPage['pageSize']) ? $configPage['pageSize'] : 20; + + $this->includeExtJS('pmTables/list', $this->debug); + $this->setView('pmTables/list'); + + //assigning js variables + $this->setJSVar('FORMATS',$c->getFormats()); + $this->setJSVar('CONFIG', $Config); + $this->setJSVar('PRO_UID', isset($_GET['PRO_UID'])? $_GET['PRO_UID'] : false); + + //render content + G::RenderPage('publish', 'extJs'); + } + + public function edit($httpData) + { + $addTabUid = isset($_GET['id']) ? $_GET['id'] : false; + $table = false; + $repTabPluginPermissions = false; + + if ($addTabUid !== false) { // if is a edit request + require_once 'classes/model/AdditionalTables.php'; + require_once 'classes/model/Fields.php'; + $tableFields = array(); + $fieldsList = array(); + + $additionalTables = new AdditionalTables(); + $table = $additionalTables->load($addTabUid, true); + + // list the case fields + foreach ($table['FIELDS'] as $i=>$field) { + $table['FIELDS'][$i]['FLD_KEY'] = $field['FLD_KEY'] == '1' ? TRUE: FALSE; + $table['FIELDS'][$i]['FLD_NULL'] = $field['FLD_NULL'] == '1' ? TRUE: FALSE; + $table['FIELDS'][$i]['FLD_FILTER'] = $field['FLD_FILTER'] == '1' ? TRUE: FALSE; + array_push($tableFields, $field['FLD_DYN_NAME']); + } + + //list dynaform fields + switch ($table['ADD_TAB_TYPE']) { + case 'NORMAL': + $fields = $this->_getDynafields($table['PRO_UID']); + + foreach ($fields as $field) { + //select to not assigned fields for available grid + if (!in_array($field['name'], $tableFields)) { + $fieldsList[] = array( + 'FIELD_UID' => $field['name'] . '-' . $field['type'], + 'FIELD_NAME' => $field['name'] + ); + } + } + $this->setJSVar('avFieldsList', $fieldsList); + $repTabPluginPermissions = $this->_getSimpleReportPluginDef(); + $this->setJSVar('_plugin_permissions', $repTabPluginPermissions); + break; + + case 'GRID': + list($gridName, $gridId) = explode('-', $table['ADD_TAB_GRID']); + // $G_FORM = new Form($table['PRO_UID'] . '/' . $gridId, PATH_DYNAFORM, SYS_LANG, false); + // $gridFields = $G_FORM->getVars(false); + $fieldsList = array(); + $gridFields = $this->_getGridDynafields($table['PRO_UID'], $gridId); + foreach ($gridFields as $gfield) { + if (!in_array($gfield['name'], $tableFields)) { + $fieldsList[] = array( + 'FIELD_UID' => $gfield['name'] . '-' . $gfield['type'], + 'FIELD_NAME' => $gfield['name'] + ); + } + } + + $this->setJSVar('avFieldsList', $fieldsList); + $repTabPluginPermissions = $this->_getSimpleReportPluginDef(); + break; + + default: + + break; + } + } + + $jsFile = isset($httpData->tableType) && $httpData->tableType == 'report' ? 'editReport' : 'edit'; + + $this->includeExtJS('pmTables/' . $jsFile, $this->debug); + + $this->setJSVar('ADD_TAB_UID', $addTabUid); + $this->setJSVar('PRO_UID', isset($_GET['PRO_UID'])? $_GET['PRO_UID'] : false); + $this->setJSVar('TABLE', $table); + $this->setJSVar('_plugin_permissions', $repTabPluginPermissions); + + G::RenderPage('publish', 'extJs'); + } + + function data($httpData) + { + require_once 'classes/model/AdditionalTables.php'; + $additionalTables = new AdditionalTables(); + $tableDef = $additionalTables->load($httpData->id, true); + + $this->includeExtJS('pmTables/data', $this->debug); + $this->setJSVar('tableDef', $tableDef); + //g::pr($tableDef['FIELDS']); + G::RenderPage('publish', 'extJs'); + } + + + /** + * protected functions + */ + protected function _getSimpleReportPluginDef() + { + global $G_TMP_MENU; + $oMenu = new Menu(); + $oMenu->load('setup'); + $repTabPluginPermissions = false; + + foreach( $oMenu->Options as $i=>$option) { + if ($oMenu->Types[$i] == 'private' && $oMenu->Id[$i] == 'PLUGIN_REPTAB_PERMISSIONS') { + $repTabPluginPermissions = array(); + $repTabPluginPermissions['label'] = $oMenu->Labels[$i]; + $repTabPluginPermissions['fn'] = $oMenu->Options[$i]; + break; + } + } + + return $repTabPluginPermissions; + } + + protected function _getDynafields($proUid, $type = 'xmlform') + { + require_once 'classes/model/Dynaform.php'; + $fields = array(); + $fieldsNames = array(); + + $oCriteria = new Criteria('workflow'); + $oCriteria->addSelectColumn(DynaformPeer::DYN_FILENAME); + $oCriteria->add(DynaformPeer::PRO_UID, $proUid); + $oCriteria->add(DynaformPeer::DYN_TYPE, $type); + $oDataset = DynaformPeer::doSelectRS($oCriteria); + $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); + $oDataset->next(); + + $excludeFieldsList = array('title', 'subtitle', 'link', 'file', 'button', 'reset', 'submit', + 'listbox', 'checkgroup', 'grid', 'javascript'); + + $labelFieldsTypeList = array('dropdown', 'checkbox', 'radiogroup', 'yesno'); + + while ($aRow = $oDataset->getRow()) { + if (file_exists(PATH_DYNAFORM . PATH_SEP . $aRow['DYN_FILENAME'] . '.xml')) { + $G_FORM = new Form($aRow['DYN_FILENAME'], PATH_DYNAFORM, SYS_LANG); + + if ($G_FORM->type == 'xmlform' || $G_FORM->type == '') { + foreach($G_FORM->fields as $fieldName => $fieldNode) { + if (!in_array($fieldNode->type, $excludeFieldsList) && !in_array($fieldName, $fieldsNames)) { + $fields[] = array('name' => $fieldName, 'type' => $fieldNode->type, 'label'=> $fieldNode->label); + $fieldsNames[] = $fieldName; + + if (in_array($fieldNode->type, $labelFieldsTypeList) && !in_array($fieldName.'_label', $fieldsNames)) { + $fields[] = array('name' => $fieldName . '_label', 'type' => $fieldNode->type, 'label'=>$fieldNode->label . '_label'); + $fieldsNames[] = $fieldName; + } + } + } + } + } + $oDataset->next(); + } + + return $fields; + } + + protected function _getGridDynafields($proUid, $gridId) + { + $fields = array(); + $fieldsNames = array(); + $excludeFieldsList = array('title', 'subtitle', 'link', 'file', 'button', 'reset', 'submit', + 'listbox', 'checkgroup', 'grid', 'javascript'); + + $labelFieldsTypeList = array('dropdown', 'checkbox', 'radiogroup', 'yesno'); + + $G_FORM = new Form($proUid . '/' . $gridId, PATH_DYNAFORM, SYS_LANG, false); + + if ($G_FORM->type == 'grid') { + foreach($G_FORM->fields as $fieldName => $fieldNode) { + if (!in_array($fieldNode->type, $excludeFieldsList) && !in_array($fieldName, $fieldsNames)) { + $fields[] = array('name' => $fieldName, 'type' => $fieldNode->type, 'label'=> $fieldNode->label); + $fieldsNames[] = $fieldName; + + if (in_array($fieldNode->type, $labelFieldsTypeList) && !in_array($fieldName.'_label', $fieldsNames)) { + $fields[] = array('name' => $fieldName . '_label', 'type' => $fieldNode->type, 'label'=>$fieldNode->label . '_label'); + $fieldsNames[] = $fieldName; + } + } + } + } + + return $fields; + } + + protected function _getGridFields($proUid) + { + $aFields = array(); + $aFieldsNames = array(); + require_once 'classes/model/Dynaform.php'; + $oCriteria = new Criteria('workflow'); + $oCriteria->addSelectColumn(DynaformPeer::DYN_FILENAME); + $oCriteria->add(DynaformPeer::PRO_UID, $proUid); + $oDataset = DynaformPeer::doSelectRS($oCriteria); + $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); + $oDataset->next(); + while ($aRow = $oDataset->getRow()) { + $G_FORM = new Form($aRow['DYN_FILENAME'], PATH_DYNAFORM, SYS_LANG); + if ($G_FORM->type == 'xmlform') { + foreach($G_FORM->fields as $k => $v) { + if ($v->type == 'grid') { + if (!in_array($k, $aFieldsNames)) { + $aFields[] = array('name' => $k, 'xmlform' => str_replace($proUid . '/', '', $v->xmlGrid)); + $aFieldsNames[] = $k; + } + } + } + } + $oDataset->next(); + } + return $aFields; + } + +} + diff --git a/workflow/engine/controllers/pmTablesProxy.php b/workflow/engine/controllers/pmTablesProxy.php new file mode 100644 index 000000000..d4386705d --- /dev/null +++ b/workflow/engine/controllers/pmTablesProxy.php @@ -0,0 +1,512 @@ +getConfiguration('additionalTablesList', 'pageSize','',$_SESSION['USER_LOGGED']); + $env = $configurations->getConfiguration('ENVIRONMENT_SETTINGS', ''); + $limit_size = isset($config->pageSize) ? $config['pageSize'] : 20; + $start = isset($params->start) ? $params->start : 0; + $limit = isset($params->limit) ? $params->limit : $limit_size; + $filter = isset($params->textFilter) ? $params->textFilter : ''; + $pro_uid = isset($params->pro_uid) ? $params->pro_uid : null; + + //$process = $pro_uid == '' ? array('not_equal'=>$pro_uid) : array('equal'=>$pro_uid); + $process = null; + $addTables = AdditionalTables::getAll($start, $limit, $filter, $process); + + return $addTables; + } + + public function getProcessList() + { + require_once 'classes/model/Process.php'; + + $process = new Process(); + return $process->getAll(); + } + + public function getDbConnectionsList() + { + G::LoadClass ( 'dbConnections'); + $proUid = $_POST['PRO_UID']; + $dbConn = new DbConnections(); + $dbConnections = $dbConn->getConnectionsProUid($proUid); + $defaultConnections = array ( + array('DBS_UID'=>'workflow', 'DBS_NAME'=>'Workflow'), + array('DBS_UID'=>'rp', 'DBS_NAME'=>'REPORT') + ); + + $dbConnections = array_merge($defaultConnections, $dbConnections); + + return $dbConnections; + } + + public function availableFieldsReportTables($params) + { + G::LoadClass('reportTables'); + //G::LoadClass('xmlfield_InputPM'); + + $aFields['FIELDS'] = array(); + $aFields['PRO_UID'] = $_POST['PRO_UID']; + + if(isset($_POST['TYPE']) && $_POST['TYPE'] == 'GRID') { + $aProcessGridFields = Array(); + if (isset($_POST['GRID_UID'])) { + global $G_FORM; + list($gridName, $gridId) = explode('-', $_POST['GRID_UID']); + + // $G_FORM = new Form($_POST['PRO_UID'] . '/' . $gridId, PATH_DYNAFORM, SYS_LANG, false); + //$gridFields = $G_FORM->getVars(false); + $gridFields = getGridDynafields($_POST['PRO_UID'], $gridId); + + foreach ($gridFields as $gfield) { + $aProcessGridFields[] = array( + 'FIELD_UID' => $gfield['name'] . '-' . $gfield['type'], + 'FIELD_NAME' => $gfield['name'] + ); + } + } else { + $gridFields = getGridFields($aFields['PRO_UID']); + + foreach ($gridFields as $gfield) { + $aProcessGridFields[] = array( + 'FIELD_UID' => $gfield['name'] . '-' . $gfield['xmlform'], + 'FIELD_NAME' => $gfield['name'] + ); + } + } + $resultList['processFields'] = $aProcessGridFields; + + } else { + $aProcessFields = Array(); + //$dynFields = getDynaformsVars($aFields['PRO_UID'], false); + $dynFields = getDynafields($aFields['PRO_UID']); + + foreach ($dynFields as $dfield) { + $aProcessFields[] = array( + 'FIELD_UID' => $dfield['name'] . '-' . $dfield['type'], + 'FIELD_NAME' => $dfield['name'] + ); + } + $resultList['processFields'] = $aProcessFields; + } + + return $resultList; + } + + public function save() + { + require_once 'classes/model/AdditionalTables.php'; + require_once 'classes/model/Fields.php'; + try { + $data = $_POST; + $data['PRO_UID'] = trim($data['PRO_UID']); + $data['columns'] = G::json_decode($_POST['columns']); //decofing data columns + $isReportTable = $data['PRO_UID'] != '' ? true : false; + + // Reserved Words + $aReservedWords = array( + 'ALTER', 'CLOSE', 'COMMIT', 'CREATE', 'DECLARE', + 'DELETE', 'DROP', 'FETCH', 'FUNCTION', 'GRANT', + 'INDEX', 'INSERT', 'OPEN', 'REVOKE', 'ROLLBACK', + 'SELECT', 'SYNONYM', 'TABLE', 'UPDATE', 'VIEW', + 'APP_UID', 'ROW' + ); + + $oAdditionalTables = new AdditionalTables(); + $oFields = new Fields(); + + // verify if exists. + $aNameTable = $oAdditionalTables->loadByName($data['REP_TAB_NAME']); + + $repTabClassName = $oAdditionalTables->getPHPName($data['REP_TAB_NAME']); + + $repTabData = array( + 'ADD_TAB_UID' => $data['REP_TAB_UID'], + 'ADD_TAB_NAME' => $data['REP_TAB_NAME'], + 'ADD_TAB_CLASS_NAME' => $repTabClassName, + 'ADD_TAB_DESCRIPTION' => $data['REP_TAB_DSC'], + 'ADD_TAB_PLG_UID' => '', + 'DBS_UID' => $data['REP_TAB_CONNECTION'], + 'PRO_UID' => $data['PRO_UID'], + 'ADD_TAB_TYPE' => $data['REP_TAB_TYPE'], + 'ADD_TAB_GRID' => $data['REP_TAB_GRID'] + ); + + $columns = $data['columns']; + + if ($data['REP_TAB_UID'] == '') { //new report table + + if ($isReportTable) { //setting default columns + $defaultColumns = $this->_getReportTableDefaultColumns($data['REP_TAB_TYPE']); + $columns = array_merge($defaultColumns, $columns); + } + + /** validations **/ + if(is_array($aNameTable)) { + throw new Exception('The table "' . $data['REP_TAB_NAME'] . '" already exits.'); + } + + if (in_array(strtoupper($data['REP_TAB_NAME']), $aReservedWords) ) { + throw new Exception('Could not create the table with the name "' . $data['REP_TAB_NAME'] . '" because it is a reserved word.'); + } + //create record + $addTabUid = $oAdditionalTables->create($repTabData); + + } else { //editing report table + $addTabUid = $data['REP_TAB_UID']; + //loading old data before update + $addTabBeforeData = $oAdditionalTables->load($addTabUid, true); + //updating record + $oAdditionalTables->update($repTabData); + + //removing old data fields references + $oCriteria = new Criteria('workflow'); + $oCriteria->add(FieldsPeer::ADD_TAB_UID, $data['REP_TAB_UID']); + //$oCriteria->add(FieldsPeer::FLD_NAME, 'APP_UID', Criteria::NOT_EQUAL); + //$oCriteria->add(FieldsPeer::FLD_NAME, 'ROW', Criteria::NOT_EQUAL); + FieldsPeer::doDelete($oCriteria); + + //getting old fieldnames + $oldFields = array(); + foreach ($addTabBeforeData['FIELDS'] as $field) { + $oldFields[$field['FLD_UID']] = $field; + } + } + + $aFields = array(); + $fieldsList = array(); + $editFieldsList = array(); + + foreach ($columns as $i => $column) { + //new feature, to reorder the columns + if (isset($oldFields[$column->uid])) { // the the field alreaday exists + if ($oldFields[$column->uid]['FLD_INDEX'] != $i) { // if its index has changed + $column->uid = ''; //set as new field, + } + } + + $field = array( + 'FLD_UID' => $column->uid, + 'FLD_INDEX' => $i, + 'ADD_TAB_UID' => $addTabUid, + 'FLD_NAME' => $column->field_name, + 'FLD_DESCRIPTION' => $column->field_label, + 'FLD_TYPE' => $column->field_type, + 'FLD_SIZE' => $column->field_size, + 'FLD_NULL' => (isset($column->field_null) && $column->field_null ? 1 : 0), + 'FLD_AUTO_INCREMENT' => 0, + 'FLD_KEY' => (isset($column->field_key) && $column->field_key ? 1 : 0), + 'FLD_FOREIGN_KEY' => 0, + 'FLD_FOREIGN_KEY_TABLE' => '', + 'FLD_DYN_NAME' => $column->field_dyn, + 'FLD_DYN_UID' => $column->field_uid, + 'FLD_FILTER' => (isset($column->field_filter) && $column->field_filter ? 1 : 0) + ); + + $fieldUid = $oFields->create($field); + $fieldsList[] = $field; + + if($data['REP_TAB_UID'] == '') { //new + $aFields[] = array( + 'sType' => $column->field_type, + 'iSize' => $column->field_size, + 'sFieldName' => $column->field_name, + 'bNull' => (isset($column->field_null) ? $column->field_null : 1), + 'bAI' => 0, + 'bPrimaryKey' => (isset($column->field_key) ? $column->field_key : 0) + ); + } else { //editing + $field['FLD_UID'] = $fieldUid; + $aFields[$fieldUid] = $field; + } + } + if ($data['REP_TAB_UID'] == '') { //create a new report table + $oAdditionalTables->createTable($data['REP_TAB_NAME'], $data['REP_TAB_CONNECTION'], $aFields); + } else { //editing + //print_R($aFields); + $oAdditionalTables->updateTable($data['REP_TAB_NAME'], $data['REP_TAB_CONNECTION'], $aFields, $oldFields); + } + + $oAdditionalTables->createPropelClasses($data['REP_TAB_NAME'], '', $fieldsList, $addTabUid, $data['REP_TAB_CONNECTION']); + + if ($isReportTable) { + $oAdditionalTables->populateReportTable($data['REP_TAB_NAME'], $data['REP_TAB_CONNECTION'], $data['REP_TAB_TYPE'], $fieldsList, $data['PRO_UID'], $data['REP_TAB_GRID']); + } + + $result->success = true; + } catch (Exception $e) { + $result->success = false; + $result->msg = $e->getMessage(); + $result->trace = $e->getTraceAsString(); + } + + return $result; + } + + public function delete($httpData) + { + G::LoadClass('reportTables'); + $rows = G::json_decode($_REQUEST['rows']); + $rp = new reportTables(); + $at = new AdditionalTables(); + + try { + foreach ($rows as $row ) { + if($row->type == 'CLASSIC') { + $rp->deleteReportTable($row->id); + } else { + $at->deleteAll($row->id); + } + } + $result->success = true; + } catch(Exception $e) { + $result->success = false; + $result->msg = $e->getMessage(); + } + + return $result; + } + + public function getData($httpData) + { + require_once 'classes/model/AdditionalTables.php'; + + G::LoadClass('configuration'); + $co = new Configurations(); + $config = $co->getConfiguration('additionalTablesData', 'pageSize','',$_SESSION['USER_LOGGED']); + $limit_size = isset($config['pageSize']) ? $config['pageSize'] : 20; + $start = isset($_REQUEST['start']) ? $_REQUEST['start'] : 0; + $limit = isset($_REQUEST['limit']) ? $_REQUEST['limit'] : $limit_size; + + $oAdditionalTables = new AdditionalTables(); + $result = $oAdditionalTables->getAllData($httpData->id, $start, $limit); + + return $result; + } + + + // protected functions + protected function _getReportTableDefaultColumns($type='NORMAL') + { + $defaultColumns = array(); + $application = new stdClass(); //APPLICATION KEY + $application->uid = ''; + $application->field_dyn = ''; + $application->field_uid = ''; + $application->field_name = 'APP_UID'; + $application->field_label = 'APP_UID'; + $application->field_type = 'VARCHAR'; + $application->field_size = 32; + $application->field_dyn = ''; + $application->field_key = 1; + $application->field_null = 0; + $application->field_filter = false; + array_push($defaultColumns, $application); + + $application = new stdClass(); //APP_NUMBER + $application->uid = ''; + $application->field_dyn = ''; + $application->field_uid = ''; + $application->field_name = 'APP_NUMBER'; + $application->field_label = 'APP_NUMBER'; + $application->field_type = 'INT'; + $application->field_size = 11; + $application->field_dyn = ''; + $application->field_key = 0; + $application->field_null = 0; + $application->field_filter = false; + array_push($defaultColumns, $application); + + //if it is a grid report table + if ($type == 'GRID') { //GRID INDEX + $gridIndex = new stdClass(); + $gridIndex->uid = ''; + $gridIndex->field_dyn = ''; + $gridIndex->field_uid = ''; + $gridIndex->field_name = 'ROW'; + $gridIndex->field_label = 'ROW'; + $gridIndex->field_type = 'INT'; + $gridIndex->field_size = '11'; + $gridIndex->field_dyn = ''; + $gridIndex->field_key = 1; + $gridIndex->field_null = 0; + $gridIndex->field_filter = false; + array_push($defaultColumns, $gridIndex); + } + + return $defaultColumns; + } +} + + +/// +/** + * Translates a string with underscores into camel case (e.g. first_name -> firstName) + * @param string $str String in underscore format + * @param bool $capitalise_first_char If true, capitalise the first char in $str + * @return string $str translated into camel caps + */ + function to_camel_case($str, $capitalise_first_char = true) { + if($capitalise_first_char) { + $str[0] = strtoupper($str[0]); + } + $func = create_function('$c', 'return strtoupper($c[1]);'); + return preg_replace_callback('/_([a-z])/', $func, $str); + } + + + + function getDynafields($proUid, $type = 'xmlform') + { + require_once 'classes/model/Dynaform.php'; + $fields = array(); + $fieldsNames = array(); + + $oCriteria = new Criteria('workflow'); + $oCriteria->addSelectColumn(DynaformPeer::DYN_FILENAME); + $oCriteria->add(DynaformPeer::PRO_UID, $proUid); + $oCriteria->add(DynaformPeer::DYN_TYPE, $type); + $oDataset = DynaformPeer::doSelectRS($oCriteria); + $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); + $oDataset->next(); + + $excludeFieldsList = array('title', 'subtitle', 'link', 'file', 'button', 'reset', 'submit', + 'listbox', 'checkgroup', 'grid', 'javascript'); + + $labelFieldsTypeList = array('dropdown', 'checkbox', 'radiogroup', 'yesno'); + + while ($aRow = $oDataset->getRow()) { + if (file_exists(PATH_DYNAFORM . PATH_SEP . $aRow['DYN_FILENAME'] . '.xml')) { + $G_FORM = new Form($aRow['DYN_FILENAME'], PATH_DYNAFORM, SYS_LANG); + + if ($G_FORM->type == 'xmlform' || $G_FORM->type == '') { + foreach($G_FORM->fields as $fieldName => $fieldNode) { + if (!in_array($fieldNode->type, $excludeFieldsList) && !in_array($fieldName, $fieldsNames)) { + $fields[] = array('name' => $fieldName, 'type' => $fieldNode->type, 'label'=> $fieldNode->label); + $fieldsNames[] = $fieldName; + + if (in_array($fieldNode->type, $labelFieldsTypeList) && !in_array($fieldName.'_label', $fieldsNames)) { + $fields[] = array('name' => $fieldName . '_label', 'type' => $fieldNode->type, 'label'=>$fieldNode->label . '_label'); + $fieldsNames[] = $fieldName; + } + } + } + } + } + $oDataset->next(); + } + + return $fields; + } + + function getGridDynafields($proUid, $gridId) + { + $fields = array(); + $fieldsNames = array(); + $excludeFieldsList = array('title', 'subtitle', 'link', 'file', 'button', 'reset', 'submit', + 'listbox', 'checkgroup', 'grid', 'javascript'); + + $labelFieldsTypeList = array('dropdown', 'checkbox', 'radiogroup', 'yesno'); + + $G_FORM = new Form($proUid . '/' . $gridId, PATH_DYNAFORM, SYS_LANG, false); + + if ($G_FORM->type == 'grid') { + foreach($G_FORM->fields as $fieldName => $fieldNode) { + if (!in_array($fieldNode->type, $excludeFieldsList) && !in_array($fieldName, $fieldsNames)) { + $fields[] = array('name' => $fieldName, 'type' => $fieldNode->type, 'label'=> $fieldNode->label); + $fieldsNames[] = $fieldName; + + if (in_array($fieldNode->type, $labelFieldsTypeList) && !in_array($fieldName.'_label', $fieldsNames)) { + $fields[] = array('name' => $fieldName . '_label', 'type' => $fieldNode->type, 'label'=>$fieldNode->label . '_label'); + $fieldsNames[] = $fieldName; + } + } + } + } + + return $fields; + } + + function getGridFields($proUid) + { + $aFields = array(); + $aFieldsNames = array(); + require_once 'classes/model/Dynaform.php'; + $oCriteria = new Criteria('workflow'); + $oCriteria->addSelectColumn(DynaformPeer::DYN_FILENAME); + $oCriteria->add(DynaformPeer::PRO_UID, $proUid); + $oDataset = DynaformPeer::doSelectRS($oCriteria); + $oDataset->setFetchmode(ResultSet::FETCHMODE_ASSOC); + $oDataset->next(); + while ($aRow = $oDataset->getRow()) { + $G_FORM = new Form($aRow['DYN_FILENAME'], PATH_DYNAFORM, SYS_LANG); + if ($G_FORM->type == 'xmlform') { + foreach($G_FORM->fields as $k => $v) { + if ($v->type == 'grid') { + if (!in_array($k, $aFieldsNames)) { + $aFields[] = array('name' => $k, 'xmlform' => str_replace($proUid . '/', '', $v->xmlGrid)); + $aFieldsNames[] = $k; + } + } + } + } + $oDataset->next(); + } + return $aFields; + } + + function getAllFields($filepath, $includeTypes=array(), $excludeTypes=array()) + { + $G_FORM = new Form($filepath, PATH_DYNAFORM, SYS_LANG); + $fields = array(); + $fieldsNames = array(); + $labelFieldsTypeList = array('dropdown', 'checkbox', 'radiogroup', 'yesno'); + + if ($G_FORM->type == 'xmlform' || $G_FORM->type == '') { + + foreach($G_FORM->fields as $fieldName => $fieldNode) { + if (!in_array($fieldNode->type, $excludeTypes)) { + continue; + } + + if (count($includeTypes) > 0) { + if (in_array($fieldNode->type, $includeTypes) && !in_array($fieldName, $fieldsNames)) { + $fields[] = array('name' => $fieldName, 'type' => $fieldNode->type, 'label'=> $fieldNode->label); + $fieldsNames[] = $fieldName; + + if (in_array($fieldNode->type, $labelFieldsTypeList) && !in_array($fieldName.'_label', $fieldsNames)) { + $fields[] = array('name' => $fieldName . '_label', 'type' => $fieldNode->type, 'label'=>$fieldNode->label . '_label'); + $fieldsNames[] = $fieldName; + } + } + continue; + } + + if (!in_array($fieldName, $fieldsNames)) { + + $fields[] = array('name' => $fieldName, 'type' => $fieldNode->type, 'label'=> $fieldNode->label); + $fieldsNames[] = $fieldName; + + if (in_array($fieldNode->type, $labelFieldsTypeList) && !in_array($fieldName.'_label', $fieldsNames)) { + $fields[] = array('name' => $fieldName . '_label', 'type' => $fieldNode->type, 'label'=>$fieldNode->label . '_label'); + $fieldsNames[] = $fieldName; + } + } + } + } + + return $fields; + } + + + \ No newline at end of file diff --git a/workflow/engine/menus/setup.php b/workflow/engine/menus/setup.php index 67a5b0e82..b1ca42772 100644 --- a/workflow/engine/menus/setup.php +++ b/workflow/engine/menus/setup.php @@ -44,6 +44,8 @@ $G_TMP_MENU->AddIdRawOption('CLEAR_CACHE', 'clearCompiled', G::LoadTranslation(' if ($RBAC->userCanAccess('PM_SETUP') == 1) { $G_TMP_MENU->AddIdRawOption('ADDITIONAL_TABLES', '../additionalTables/additionalTablesList', G::LoadTranslation('ID_ADDITIONAL_TABLES'), 'icon-tables.png','', 'settings'); $G_TMP_MENU->AddIdRawOption('REPORT_TABLES', '../reportTables/main', 'Report Tables', 'icon-tables.png','', 'settings'); + + $G_TMP_MENU->AddIdRawOption('PM_TABLES', '../pmTables', 'PM Tables 2', 'icon-tables.png','', 'settings'); } $G_TMP_MENU->AddIdRawOption('WEBSERVICES', 'webServices', G::LoadTranslation('ID_WEB_SERVICES'), 'icon-webservices.png', '', 'settings'); diff --git a/workflow/engine/methods/additionalTables/additionalTablesData.php b/workflow/engine/methods/additionalTables/additionalTablesData.php index d63f152d4..82599cd29 100644 --- a/workflow/engine/methods/additionalTables/additionalTablesData.php +++ b/workflow/engine/methods/additionalTables/additionalTablesData.php @@ -72,4 +72,4 @@ $oHeadPublisher->assign('NAMES', $arrNames); $oHeadPublisher->assign('VALUES', $arrDescrip); $oHeadPublisher->assign('CONFIG', $Config); -G::RenderPage('publish', 'extJs'); \ No newline at end of file +G::RenderPage('publish', 'extJs'); diff --git a/workflow/engine/templates/additionalTables/additionalTablesData.js b/workflow/engine/templates/additionalTables/additionalTablesData.js index 98e57de05..4658c0e8a 100644 --- a/workflow/engine/templates/additionalTables/additionalTablesData.js +++ b/workflow/engine/templates/additionalTables/additionalTablesData.js @@ -78,7 +78,7 @@ Ext.onReady(function(){ contextMenu = new Ext.menu.Menu({ items: [editButton, deleteButton] - }); + }); //This loop loads columns and fields to store and column model for (var c=0; cdbMap = Propel::getDatabaseMap('workflow'); + $this->dbMap = Propel::getDatabaseMap('{connection}'); $tMap = $this->dbMap->addTable('{tableName}'); diff --git a/workflow/engine/templates/additionalTables/om/BaseTablePeer.tpl b/workflow/engine/templates/additionalTables/om/BaseTablePeer.tpl index dedf3615f..bcbbb9446 100644 --- a/workflow/engine/templates/additionalTables/om/BaseTablePeer.tpl +++ b/workflow/engine/templates/additionalTables/om/BaseTablePeer.tpl @@ -15,7 +15,7 @@ include_once '{pathClasses}/' . SYS_SYS . '/classes/{className}.php'; abstract class Base{className}Peer { /** the default database name for this class */ - const DATABASE_NAME = 'workflow'; + const DATABASE_NAME = '{connection}'; /** the table name for this class */ const TABLE_NAME = '{tableName}'; diff --git a/workflow/engine/templates/pmTables/data.js b/workflow/engine/templates/pmTables/data.js new file mode 100644 index 000000000..8131c057d --- /dev/null +++ b/workflow/engine/templates/pmTables/data.js @@ -0,0 +1,287 @@ + +var newButton; +var editButton; +var deleteButton; +var importButton; +var backButton; + +var store; +var cmodel; +var smodel; +var infoGrid; + +Ext.onReady(function(){ + + pageSize = 20; //parseInt(CONFIG.pageSize); + + newButton = new Ext.Action({ + text: _('ID_ADD_ROW'), + iconCls: 'button_menu_ext ss_sprite ss_add', + handler: NewPMTableRow + }); + + editButton = new Ext.Action({ + text: _('ID_EDIT'), + iconCls: 'button_menu_ext ss_sprite ss_pencil', + handler: EditPMTableRow, + disabled: true + }); + + deleteButton = new Ext.Action({ + text: _('ID_DELETE'), + iconCls: 'button_menu_ext ss_sprite ss_delete', + handler: DeletePMTableRow, + disabled: true + }); + + importButton = new Ext.Action({ + text: _('ID_IMPORT'), + iconCls: 'silk-add', + icon: '/images/import.gif', + handler: ImportPMTableCSV + }); + + backButton = new Ext.Action({ + text: _('ID_BACK'), + iconCls: 'button_menu_ext ss_sprite ss_arrow_redo', + handler: BackPMList + }); + + contextMenu = new Ext.menu.Menu({ + items: [editButton, deleteButton] + }); + + //This loop loads columns and fields to store and column model + _columns = new Array(); + _fields = new Array(); + + if (tableDef.FIELDS.length !== 0) { + for (i in tableDef.FIELDS) { + _columns.push({ + id: tableDef.FIELDS[i].FLD_NAME, + header: tableDef.FIELDS[i].FLD_DESCRIPTION, + dataIndex: tableDef.FIELDS[i].FLD_NAME, + width: 40 + }); + + _fields.push({name: tableDef.FIELDS[i].FLD_NAME}); + } + } + +// smodel = new Ext.grid.CheckboxSelectionModel({ +// listeners:{ +// selectionchange: function(sm){ +// var count_rows = sm.getCount(); +// switch(count_rows){ +// case 0: +// editButton.disable(); +// deleteButton.disable(); +// break; +// case 1: +// editButton.enable(); +// deleteButton.enable(); +// break; +// default: +// editButton.disable(); +// deleteButton.disable(); +// break; +// } +// } +// } +// }); + + store = new Ext.data.GroupingStore({ + proxy : new Ext.data.HttpProxy({ + url: '../pmTablesProxy/getData?id=' + tableDef.ADD_TAB_UID + }), + reader : new Ext.data.JsonReader({ + root: 'rows', + totalProperty: 'count', + fields : _fields + }) + }); + + cmodel = new Ext.grid.ColumnModel({ + defaults: { + width: 50, + sortable: true + }, + columns: _columns + }); + + storePageSize = new Ext.data.SimpleStore({ + fields: ['size'], + data: [['20'],['30'],['40'],['50'],['100']], + autoLoad: true + }); + + comboPageSize = new Ext.form.ComboBox({ + typeAhead : false, + mode : 'local', + triggerAction : 'all', + store: storePageSize, + valueField: 'size', + displayField: 'size', + width: 50, + editable: false, + listeners:{ + select: function(c,d,i){ + UpdatePageConfig(d.data['size']); + bbarpaging.pageSize = parseInt(d.data['size']); + bbarpaging.moveFirst(); + } + } + }); + + comboPageSize.setValue(pageSize); + + bbarpaging = new Ext.PagingToolbar({ + pageSize: pageSize, + store: store, + displayInfo: true, + displayMsg: _('ID_GRID_PAGE_DISPLAYING_ROWS_MESSAGE') + '    ', + emptyMsg: _('ID_GRID_PAGE_NO_ROWS_MESSAGE'), + items: ['-',_('ID_PAGE_SIZE')+':',comboPageSize] + }); + + + infoGrid = new Ext.grid.GridPanel({ + region: 'center', + layout: 'fit', + id: 'infoGrid', + height:1000, + autoWidth : true, + title : _('ID_PM_TABLE') + " : " + tableDef.ADD_TAB_NAME, + stateful : true, + stateId : 'grid', + enableColumnResize: true, + enableHdMenu: true, + frame:false, + columnLines: false, + viewConfig: { + forceFit:true + }, + store: store, + cm: cmodel, + //sm: smodel, + tbar:[newButton,'-',editButton, deleteButton,'-',importButton,{xtype: 'tbfill' }, backButton], + bbar: bbarpaging, + listeners: { + rowdblclick: EditPMTableRow, + render: function(){ + this.loadMask = new Ext.LoadMask(this.body, {msg:_('ID_LOADING_GRID')}); + } + }, + view: new Ext.grid.GroupingView({ + forceFit:true, + groupTextTpl: '{text}' + }) + }); + + infoGrid.on('rowcontextmenu', + function (grid, rowIndex, evt) { + var sm = grid.getSelectionModel(); + sm.selectRow(rowIndex, sm.isSelected(rowIndex)); + }, + this + ); + + infoGrid.on('contextmenu', function(evt){evt.preventDefault();}, this); + infoGrid.addListener('rowcontextmenu',onMessageContextMenu, this); + + infoGrid.store.load(); + + viewport = new Ext.Viewport({ + layout: 'fit', + autoScroll: false, + items: [infoGrid] + }); +}); + +//Funtion Handles Context Menu Opening +onMessageContextMenu = function (grid, rowIndex, e) { + e.stopEvent(); + var coords = e.getXY(); + contextMenu.showAt([coords[0], coords[1]]); +}; + + + +/////JS FUNCTIONS + +//Capitalize String Function +capitalize = function(s){ + s = s.toLowerCase(); + return s.replace( /(^|\s)([a-z])/g , function(m,p1,p2){ return p1+p2.toUpperCase(); } ); +}; + +//Do Nothing Function +DoNothing = function(){}; + +//Load New PM Table Row Forms +NewPMTableRow = function(){ + location.href = 'additionalTablesDataNew?sUID=' + TABLES.UID; +}; + +//Load PM Table Edition Row Form +EditPMTableRow = function(){ + iGrid = Ext.getCmp('infoGrid'); + rowsSelected = iGrid.getSelectionModel().getSelections(); + var aRowsSeleted = (RetrieveRowsID(rowsSelected)).split(",") ; + var aTablesPKF = (TABLES.PKF).split(","); ; + var sParam = ''; + for(var i=0;i0){ + var c = 0; + for(var i=0; i + */ + +var store; +var storeP; +var storeA; +var cmodelP; +var smodelA; +var smodelP; +var availableGrid; +var assignButton; +var assignAllButton; +var removeButton; +var removeAllButton; + +var store; +var editor; + +Ext.onReady(function(){ + + var fm = Ext.form; + var fieldsCount = 0; + // store for available fields grid + storeA = new Ext.data.GroupingStore( { + proxy : new Ext.data.HttpProxy({ + url: '../pmTablesProxy/availableFieldsReportTables' + }), + reader : new Ext.data.JsonReader( { + root: 'processFields', + fields : [{name : 'FIELD_UID'}, {name : 'FIELD_NAME'}] + }), + listeners: { + load: function() { + + } + } + }); + //column model for available fields grid + cmodelA = new Ext.grid.ColumnModel({ + defaults: { + width: 55, + sortable: true + }, + columns: [ + { + id:'FIELD_UID', + dataIndex: 'FIELD_UID', + hidden:true, + hideable:false + }, { + header : _("ID_DYNAFORM_FIELDS"), + dataIndex : 'FIELD_NAME', + sortable : true, + align:'left' + } + ] + }); + //selection model for available fields grid + smodelA = new Ext.grid.RowSelectionModel({ + selectSingle: false, + listeners:{ + selectionchange: function(sm){ + switch(sm.getCount()){ + case 0: Ext.getCmp('assignButton').disable(); break; + default: Ext.getCmp('assignButton').enable(); break; + } + } + } + }); + //grid for table columns grid + availableGrid = new Ext.grid.GridPanel({ + layout: 'fit', + region: 'center', + id: 'availableGrid', + ddGroup : 'assignedGridDDGroup', + enableDragDrop : true, + stripeRows : true, + autoWidth : true, + stripeRows : true, + height : 100, + width : 200, + stateful : true, + stateId : 'grid', + enableColumnResize : true, + enableHdMenu : true, + frame : false, + columnLines : false, + viewConfig : {forceFit:true}, + cm: cmodelA, + sm: smodelA, + store: storeA, + listeners: {rowdblclick: AssignFieldsAction} + }); + + //selecion model for table columns grid + sm = new Ext.grid.RowSelectionModel({ + selectSingle: false, + listeners:{ + selectionchange: function(sm){ + switch(sm.getCount()){ + case 0: Ext.getCmp('removeButton').disable(); break; + default: Ext.getCmp('removeButton').enable(); break; + } + } + } + }); + //check column for table columns grid + var checkColumn = new Ext.grid.CheckColumn({ + header: 'Filter', + dataIndex: 'FIELD_FILTER', + id: 'FIELD_FILTER', + width: 55 + }); + //columns for table columns grid + var cmColumns = [ + { + id: 'uid', + dataIndex: 'uid', + hidden: true + }, + { + id: 'field_uid', + dataIndex: 'field_uid', + hidden: true + }, + { + id: 'field_key', + dataIndex: 'field_key', + hidden: true + }, + { + id: 'field_null', + dataIndex: 'field_null', + hidden: true + }, + { + id: 'field_dyn', + header: _("ID_DYNAFORM_FIELD"), + dataIndex: 'field_dyn', + hidden: true + }, { + id: 'field_name', + header: _("ID_FIELD_NAME"), + dataIndex: 'field_name', + width: 220, + editor: { + xtype: 'textfield', + allowBlank: true, + style:'text-transform: uppercase', + listeners:{ + change: function(f,e){ + this.setValue(this.getValue().toUpperCase()); + } + } + } + }, { + id: 'field_label', + header: _("ID_FIELD_LABEL"), + dataIndex: 'field_label', + width: 220, + editor:{ + xtype: 'textfield', + allowBlank: true + } + }, { + id: 'field_type', + header: _("ID_TYPE"), + dataIndex: 'field_type', + width: 75, + editor: new fm.ComboBox({ + typeAhead: true, + editable:true, + lazyRender: true, + mode: 'local', + displayField:'type', + valueField:'type_id', + autocomplete: true, + triggerAction: 'all', + forceSelection: true, + store: new Ext.data.SimpleStore({ + fields: ['type_id', 'type'], + data : [['VARCHAR',_("ID_VARCHAR")],['TEXT',_("ID_TEXT")],['DATE',_("ID_DATE")],['INT',_("ID_INT")],['FLOAT',_("ID_FLOAT")]], + sortInfo: {field:'type_id', direction:'ASC'} + }) + }) + }, { + id: 'field_size', + header: _("ID_SIZE"), + dataIndex: 'field_size', + width: 50, + align: 'right', + editor: new fm.NumberField({ + allowBlank: true + }) + }, { + xtype: 'booleancolumn', + header: 'Null', + dataIndex: 'field_null', + align: 'center', + width: 50, + trueText: 'Yes', + falseText: 'No', + editor: { + xtype: 'checkbox' + } + }, { + xtype: 'booleancolumn', + header: 'Primary Key', + dataIndex: 'field_key', + align: 'center', + width: 50, + trueText: 'Yes', + falseText: 'No', + editor: { + xtype: 'checkbox' + } + } + ]; + + //if permissions plugin is enabled + if (TABLE !== false && TABLE.ADD_TAB_TAG == 'plugin@simplereport') { + cmColumns.push({ + xtype: 'booleancolumn', + header: 'Filter', + dataIndex: 'field_filter', + align: 'center', + width: 50, + trueText: 'Yes', + falseText: 'No', + editor: { + xtype: 'checkbox' + } + }) + } + + //column model for table columns grid + var cm = new Ext.grid.ColumnModel({ + // specify any defaults for each column + defaults: { + sortable: true // columns are not sortable by default + }, + columns:cmColumns + }); + //store for table columns grid + store = new Ext.data.ArrayStore({ + fields: [ + {name: 'uid', type: 'string'}, + {name: 'field_uid', type: 'string'}, + {name: 'field_key', type: 'string'}, + {name: 'field_name', type: 'string'}, + {name: 'field_label', type: 'string'}, + {name: 'field_type'}, + {name: 'field_size', type: 'float'}, + {name: 'field_null', type: 'float'}, + {name: 'field_filter', type: 'string'} + ] + }); + //row editor for table columns grid + editor = new Ext.ux.grid.RowEditor({ + saveText: _("ID_UPDATE") + }); + + editor.on({ + afteredit: function(roweditor, changes, record, rowIndex) { + // + }, + afteredit: function(roweditor, rowIndex) { + row = assignedGrid.getSelectionModel().getSelected(); + if (row.get('field_key') == true) { + row.data.field_null = false; + row.commit(); + } + } + }); + + //table columns grid + assignedGrid = new Ext.grid.GridPanel({ + //title: 'Columns', + region: 'center', + id: 'assignedGrid', + ddGroup : 'availableGridDDGroup', + enableDragDrop : true, + enableColumnResize : true, + viewConfig : {forceFit:true}, + cm: cm, + sm: sm, + store: store, + plugins: [editor, checkColumn], + tbar: [ + { + icon: '/images/addcolumn.jpg', + text: _("ID_ADD_COLUMN"), + handler: addColumn + } + ], + listeners: { + render: function(grid) { + var ddrow = new Ext.dd.DropTarget(grid.getView().mainBody, { + ddGroup: 'availableGridDDGroup', + copy: false, + notifyDrop: function(dd, e, data) { + var ds = grid.store; + var sm = grid.getSelectionModel(); + var rows = sm.getSelections(); + if (dd.getDragData(e)) { + var cindex = dd.getDragData(e).rowIndex; + //skipping primary keys, we can't reorder + if (store.data.items[cindex].data.field_key) + return; + + if (typeof(cindex) != "undefined") { + for(var i = 0; i < rows.length; i++) { + //skipping primary keys, we can't reorder + if (rows[i].data.field_key ) + continue; + + var srcIndex = ds.indexOfId(rows[i].id); + ds.remove(ds.getById(rows[i].id)); + if (i > 0 && cindex < srcIndex) { + cindex++; + } + ds.insert(cindex, rows[i]); + } + sm.selectRecords(rows); + } + } + } + }); + } + } + }); + + assignedGrid.getSelectionModel().on('selectionchange', function(sm){ + //alert('s'); + }); + + // (vertical) selection buttons + buttonsPanel = new Ext.Panel({ + width : 40, + layout : { + type:'vbox', + padding:'0', + pack:'center', + align:'center' + }, + defaults:{margins:'0 0 35 0'}, + items:[ + { xtype:'button',text: '>', + handler: AssignFieldsAction, + id: 'assignButton', disabled: true + }, + { xtype:'button',text: '<', + handler: RemoveFieldsAction, + id: 'removeButton', disabled: true + }, + { xtype:'button',text: '>>', + handler: AssignAllFieldsAction, + id: 'assignButtonAll', disabled: false}, + { xtype:'button',text: '<<', + handler: RemoveAllFieldsAction, + id: 'removeButtonAll', disabled: false + } + ] + + }); + + + FieldsPanel = new Ext.Panel({ + //title: _('ID_FIELDS'), + region : 'center', + //autoWidth : true, + width: 150, + layout : 'hbox', + defaults : { flex : 1 }, //auto stretch + layoutConfig : { align : 'stretch' }, + items : [assignedGrid], + viewConfig : {forceFit:true} + + }); + + searchTextA = new Ext.form.TextField ({ + id: 'searchTextA', + ctCls:'pm_search_text_field', + allowBlank: true, + width: 110, + emptyText: _('ID_ENTER_SEARCH_TERM'), + listeners: { + specialkey: function(f,e){ + if (e.getKey() == e.ENTER) { + DoSearchA(); + } + } + } + }); + + searchTextP = new Ext.form.TextField ({ + id: 'searchTextP', + ctCls:'pm_search_text_field', + allowBlank: true, + width: 110, + emptyText: _('ID_ENTER_SEARCH_TERM'), + listeners: { + specialkey: function(f,e){ + if (e.getKey() == e.ENTER) { + DoSearchP(); + } + } + } + }); + + var types = new Ext.data.SimpleStore({ + fields: ['REP_TAB_TYPE', 'type'], + data : [['NORMAL',_("ID_GLOBAL")],['GRID',_("ID_GRID")]] + }); + + comboReport = new Ext.form.ComboBox({ + id : 'REP_TAB_TYPE', + name: 'type', + fieldLabel: 'Type', + hiddenName : 'REP_TAB_TYPE', + mode: 'local', + store: types, + displayField:'type', + valueField:'REP_TAB_TYPE', + width: 120, + typeAhead: true, + triggerAction: 'all', + editable:false, + lazyRender: true, + value: typeof TABLE.ADD_TAB_TYPE != 'undefined'? TABLE.ADD_TAB_TYPE : 'NORMAL', + listeners: { + select: function(combo,record,index){ + if (this.getValue()=='NORMAL') { + Ext.getCmp('REP_TAB_GRID').setVisible(false); + loadFieldNormal(); + } else { + Ext.getCmp('availableGrid').store.removeAll(); + Ext.getCmp('REP_TAB_GRID').setVisible(true); + Ext.getCmp('REP_TAB_GRID').setValue(''); + gridsListStore.reload({params:{PRO_UID : PRO_UID !== false ? PRO_UID : Ext.getCmp('PROCESS').getValue()}}); + } + } + } + }); + + dbConnectionsStore = new Ext.data.Store({ + autoLoad: false, + proxy : new Ext.data.HttpProxy({ + url: '../pmTablesProxy/getDbConnectionsList', + method : 'POST' + }), + baseParams : { + PRO_UID : '' + }, + reader : new Ext.data.JsonReader( { + fields : [{name : 'DBS_UID'}, {name : 'DBS_NAME'}] + }), + listeners: { + load: function() { + if (TABLE !== false) { // is editing + // set current editing process combobox + var i = this.findExact('DBS_UID', TABLE.DBS_UID, 0); + if (i > -1){ + comboDbConnections.setValue(this.getAt(i).data.DBS_UID); + comboDbConnections.setRawValue(this.getAt(i).data.DBS_NAME); + comboDbConnections.setDisabled(true); + } else { + // DB COnnection deleted + Ext.Msg.alert( _('ID_ERROR'), 'DB Connection doesn\'t exist!'); + } + } else { + comboDbConnections.setValue('rp'); + } + } + } + }); + + comboDbConnections = new Ext.form.ComboBox({ + id: 'REP_TAB_CONNECTION', + fieldLabel : _("ID_DB_CONNECTION"), + hiddenName : 'DBS_UID', + store : dbConnectionsStore, + //value: 'rp', + valueField : 'DBS_UID', + displayField : 'DBS_NAME', + triggerAction : 'all', + editable : false, + mode:'local' + }); + + var tbar = new Array(); + var items = new Array(); + + items.push({ + id: 'REP_TAB_NAME', + fieldLabel: _("ID_TABLE_NAME"), + xtype:'textfield', + emptyText: _("ID_SET_A_TABLE_NAME"), + width: 250, + stripCharsRe: /(\W+)/g, + style:'text-transform: uppercase', + listeners:{ + change: function(){ + this.setValue(this.getValue().toUpperCase()) + } + } + }); + items.push({ + id: 'REP_TAB_DSC', + fieldLabel: _("ID_DESCRIPTION"), + xtype:'textarea', + emptyText: _("ID_SET_TABLE_DESCRIPTION"), + width: 250, + height: 40, + allowBlank: true + }); + + //items.push(comboDbConnections); + + var frmDetails = new Ext.FormPanel({ + id :'frmDetails', + region : 'north', + labelWidth : 120, + labelAlign :'right', + title : 'New Report Table', + bodyStyle :'padding:10px', + frame : true, + height : 120, + items : items, + //tbar : tbar, + waitMsgTarget : true, + defaults: { + allowBlank : false, + msgTarget : 'side', + align :'center' + } + }); + + + southPanel = new Ext.FormPanel({ + region: 'south', + buttons:[ { + text: TABLE === false ? _("ID_CREATE") : _("ID_UPDATE"), + handler: createReportTable + }, { + text:_("ID_CANCEL"), + handler: function() { + proParam = PRO_UID !== false ? '?PRO_UID='+PRO_UID : ''; + //location.href = '../pmTables' + proParam; //history.back(); + } + }] + }); + + var viewport = new Ext.Viewport({ + layout: 'border', + autoScroll: false, + items:[frmDetails, FieldsPanel, southPanel] + }); + + /*** Editing routines ***/ + if (TABLE !== false) { + Ext.getCmp('REP_TAB_NAME').setValue(TABLE.ADD_TAB_NAME); + Ext.getCmp('REP_TAB_NAME').setDisabled(true); + Ext.getCmp('REP_TAB_DSC').setValue(TABLE.ADD_TAB_DESCRIPTION); + + loadTableRowsFromArray(TABLE.FIELDS); + } + //DDLoadFields(); + +}); + +// actions + +function createReportTable() +{ + //validate table name + if(Ext.getCmp('REP_TAB_NAME').getValue().trim() == '') { + Ext.getCmp('REP_TAB_NAME').focus(); + PMExt.error(_('ID_ERROR'), 'Table Name is required.', function(){ + Ext.getCmp('REP_TAB_NAME').focus(); + }); + return false; + } + + var allRows = assignedGrid.getStore(); + var columns = new Array(); + var hasSomePrimaryKey = false; + + //validate columns count + if(allRows.getCount() == 0) { + PMExt.error(_('ID_ERROR'), 'Set columns for this Report Table please.'); + return false; + } + + for (var r=0; r < allRows.getCount(); r++) { + row = allRows.getAt(r); + + // validate that fieldname is not empty + if(row.data['field_name'].trim() == '') { + PMExt.error(_('ID_ERROR'), 'Field Name for all columns is required.'); + return false; + } + + if(row.data['field_label'].trim() == '') { + PMExt.error(_('ID_ERROR'), 'Field Label for all columns is required.'); + return false; + } + + // validate field size for varchar & int column types + if(row.data['field_type'] == 'VARCHAR' || row.data['field_type'] == 'INT') { + PMExt.error(_('ID_ERROR'), 'Set a field size for '+row.data['field_name']+' ('+row.data['field_type']+') please.'); + return false; + } + + if (row.data['field_key']) { + hasSomePrimaryKey = true; + } + + columns.push(row.data); + } + + if (!hasSomePrimaryKey) { + PMExt.error(_('ID_ERROR'), 'You need set one column at least as Primary Key.'); + return; + } + + Ext.Ajax.request({ + url: '../pmTablesProxy/save', + params: { + REP_TAB_UID : TABLE !== false ? TABLE.ADD_TAB_UID : '', + PRO_UID : '', + REP_TAB_NAME : Ext.getCmp('REP_TAB_NAME').getValue(), + REP_TAB_DSC : Ext.getCmp('REP_TAB_DSC').getValue(), + REP_TAB_CONNECTION : 'workflow', + REP_TAB_TYPE : '', + REP_TAB_GRID : '', + columns : Ext.util.JSON.encode(columns) + }, + success: function(resp){ + result = Ext.util.JSON.decode(resp.responseText); + + if (result.success) { + proParam = PRO_UID !== false ? '?PRO_UID='+PRO_UID : ''; + location.href = '../pmTables' + proParam; //history.back(); + } else { + Ext.Msg.alert( _('ID_ERROR'), result.msg); + } + }, + failure: function(obj, resp){ + Ext.Msg.alert( _('ID_ERROR'), resp.result.msg); + } + }); +} +//end createReportTable + +function addColumn() { + var PMRow = assignedGrid.getStore().recordType; + //var meta = mapPMFieldType(records[i].data['FIELD_UID']); + var row = new PMRow({ + uid : '', + field_uid : '', + field_dyn : '', + field_name : '', + field_label : '', + field_type : '', + field_size : '', + field_key : 0, + field_null : 1 + }); + length = assignedGrid.getStore().data.length; + + editor.stopEditing(); + store.insert(length, row); + assignedGrid.getView().refresh(); + assignedGrid.getSelectionModel().selectRow(length); + editor.startEditing(length); +} + + +////ASSIGNBUTON FUNCTIONALITY +AssignFieldsAction = function(){ + records = Ext.getCmp('availableGrid').getSelectionModel().getSelections(); + + for(i=0; i < records.length; i++){ + var PMRow = assignedGrid.getStore().recordType; + var meta = mapPMFieldType(records[i].data['FIELD_UID']); + var row = new PMRow({ + uid : '', + field_uid : records[i].data['FIELD_UID'], + field_dyn : records[i].data['FIELD_NAME'], + field_name : records[i].data['FIELD_NAME'].toUpperCase(), + field_label : records[i].data['FIELD_NAME'].toUpperCase(), + field_type : meta.type, + field_size : meta.size, + field_key : 0, + field_null : 1 + }); + + store.add(row); + } + + //remove from source grid + Ext.each(records, Ext.getCmp('availableGrid').store.remove, Ext.getCmp('availableGrid').store); +}; +//RemoveButton Functionality +RemoveFieldsAction = function(){ + + records = Ext.getCmp('assignedGrid').getSelectionModel().getSelections(); + var PMRow = availableGrid.getStore().recordType; + for(i=0; i < records.length; i++){ + if (records[i].data['field_dyn'] != '' && records[i].data['field_name'] != 'APP_UID' && records[i].data['field_name'] != 'APP_NUMBER' && records[i].data['field_name'] != 'ROW') { + var row = new PMRow({ + FIELD_UID : records[i].data['field_uid'], + FIELD_NAME : records[i].data['field_dyn'] + }); + availableGrid.getStore().add(row); + } else { + records[i] = null; + } + } + //remove from source grid + Ext.each(records, Ext.getCmp('assignedGrid').store.remove, Ext.getCmp('assignedGrid').store); +}; + +//AssignALLButton Functionality +AssignAllFieldsAction = function(){ + var available = Ext.getCmp('availableGrid'); + var allRows = available.getStore(); + var arrAux = new Array(); + records = new Array() + + if (allRows.getCount() > 0){ + var PMRow = assignedGrid.getStore().recordType; + for (i=0; i < allRows.getCount(); i++){ + records[i] = allRows.getAt(i); + var meta = mapPMFieldType(records[i].data['FIELD_UID']); + var row = new PMRow({ + uid : '', + field_uid : records[i].data['FIELD_UID'], + field_dyn : records[i].data['FIELD_NAME'], + field_name : records[i].data['FIELD_NAME'].toUpperCase(), + field_label : records[i].data['FIELD_NAME'].toUpperCase(), + field_type : meta.type, + field_size : meta.size, + field_key : 0, + field_null : 1 + }); + + store.add(row); + } + //remove from source grid + Ext.each(records, Ext.getCmp('availableGrid').store.remove, Ext.getCmp('availableGrid').store); + } + +}; + +//RevomeALLButton Functionality +RemoveAllFieldsAction = function(){ + var allRows = Ext.getCmp('assignedGrid').getStore(); + var records = new Array(); + if (allRows.getCount() > 0) { + var PMRow = availableGrid.getStore().recordType; + for (var i=0; i < allRows.getCount(); i++){ + records[i] = allRows.getAt(i); + if (records[i].data['field_dyn'] != '' && records[i].data['field_name'] != 'APP_UID' && records[i].data['field_name'] != 'APP_NUMBER' && records[i].data['field_name'] != 'ROW') { + var row = new PMRow({ + FIELD_UID : records[i].data['field_uid'], + FIELD_NAME : records[i].data['field_dyn'] + }); + availableGrid.getStore().add(row); + } else { + records[i] = null; + } + } + //remove from source grid + Ext.each(records, Ext.getCmp('assignedGrid').store.remove, Ext.getCmp('assignedGrid').store); + } +}; + +// drag & drop handler +var DDLoadFields = function(){ + var availableGridDropTargetEl = availableGrid.getView().scroller.dom; + var availableGridDropTarget = new Ext.dd.DropTarget(availableGridDropTargetEl, { + ddGroup : 'availableGridDDGroup', + notifyDrop : function(ddSource, e, data){ + + var records = ddSource.dragData.selections; + var PMRow = availableGrid.getStore().recordType; + + for (i=0; i < records.length; i++){ + if (records[i].data['field_dyn'] != '' && records[i].data['field_name'] != 'APP_UID' && records[i].data['field_name'] != 'APP_NUMBER' && records[i].data['field_name'] != 'ROW') { + var row = new PMRow({ + FIELD_UID: records[i].data['field_uid'], + FIELD_NAME: records[i].data['field_dyn'] + }); + availableGrid.getStore().add(row); + } else if (records[i].data['field_dyn'] != '') { + records[i] = null; + } + } + + Ext.each(records, ddSource.grid.store.remove, ddSource.grid.store); + return true; + } + }); + + //droptarget on grid forassignment + var assignedGridDropTargetEl = assignedGrid.getView().scroller.dom; + var assignedGridDropTarget = new Ext.dd.DropTarget(assignedGridDropTargetEl, { + ddGroup : 'assignedGridDDGroup', + notifyDrop : function(ddSource, e, data){ + + var records = ddSource.dragData.selections; + var PMRow = assignedGrid.getStore().recordType; + + //add on target grid + for (i=0; i < records.length; i++){ + //arrAux[r] = records[r].data['FIELD_UID']; + var meta = mapPMFieldType(records[i].data['FIELD_UID']); + var row = new PMRow({ + uid : '', + field_uid : records[i].data['FIELD_UID'], + field_dyn : records[i].data['FIELD_NAME'], + field_name : records[i].data['FIELD_NAME'].toUpperCase(), + field_label : records[i].data['FIELD_NAME'].toUpperCase(), + field_type : meta.type, + field_size : meta.size, + field_key : 0, + field_null : 1 + }); + + store.add(row); + } + //remove from source grid + Ext.each(records, availableGrid.store.remove, availableGrid.store); + + return true; + } + }); + //sw_func_groups = true; +}; + +function loadTableRowsFromArray(records) +{ + var PMRow = assignedGrid.getStore().recordType; + if (records.length == 0) return; + + for(i in records) { + var row = new PMRow({ + uid : records[i].FLD_UID, + field_uid : records[i].FLD_DYN_UID, + field_dyn : records[i].FLD_DYN_NAME, + field_name : records[i].FLD_NAME, + field_label: records[i].FLD_DESCRIPTION, + field_type : records[i].FLD_TYPE, + field_size : records[i].FLD_SIZE, + field_key : records[i].FLD_KEY, + field_null : records[i].FLD_NULL, + field_filter: records[i].FLD_FILTER == '1' ? true : false + }); + + store.add(row); + } +} diff --git a/workflow/engine/templates/pmTables/editReport.js b/workflow/engine/templates/pmTables/editReport.js new file mode 100644 index 000000000..d51b98c36 --- /dev/null +++ b/workflow/engine/templates/pmTables/editReport.js @@ -0,0 +1,1161 @@ +/** + * Report tables New/Edit + * @author Erik A. O. + */ + +//grids define +var availableGrid; + +var assignedGrid; +var editor; // row editor for assignedGrid +var store; // store for assignedGrid + +//buttons define +var assignButton; +var assignAllButton; +var removeButton; +var removeAllButton; +var tmp1 = new Array(); +//main +Ext.onReady(function(){ + + var fm = Ext.form; + var fieldsCount = 0; + + // store for available fields grid + storeA = new Ext.data.GroupingStore( { + proxy : new Ext.data.HttpProxy({ + url: '../pmTablesProxy/availableFieldsReportTables' + }), + reader : new Ext.data.JsonReader( { + root: 'processFields', + fields : [{name : 'FIELD_UID'}, {name : 'FIELD_NAME'}] + }), + listeners: { + load: function() { + + } + } + }); + //column model for available fields grid + cmodelA = new Ext.grid.ColumnModel({ + defaults: { + width: 55, + sortable: true + }, + columns: [ + { + id:'FIELD_UID', + dataIndex: 'FIELD_UID', + hidden:true, + hideable:false + }, { + header : _("ID_DYNAFORM_FIELDS"), + dataIndex : 'FIELD_NAME', + sortable : true, + align:'left' + } + ] + }); + //selection model for available fields grid + smodelA = new Ext.grid.RowSelectionModel({ + selectSingle: false, + listeners:{ + selectionchange: function(sm){ + switch(sm.getCount()){ + case 0: Ext.getCmp('assignButton').disable(); break; + default: Ext.getCmp('assignButton').enable(); break; + } + } + } + }); + //grid for table columns grid + availableGrid = new Ext.grid.GridPanel({ + layout : 'fit', + region : 'center', + id : 'availableGrid', + ddGroup : 'assignedGridDDGroup', + enableDragDrop : true, + stripeRows : true, + autoWidth : true, + stripeRows : true, + height : 100, + width : 200, + stateful : true, + stateId : 'grid', + enableHdMenu : false, + columnLines : false, + viewConfig : {forceFit:true}, + cm : cmodelA, + sm : smodelA, + store : storeA, + listeners : { + rowdblclick: AssignFieldsAction + } + }); + + //selecion model for table columns grid + sm = new Ext.grid.RowSelectionModel({ + selectSingle: false, + listeners:{ + selectionchange: function(sm){ + switch(sm.getCount()){ + case 0: Ext.getCmp('removeButton').disable(); break; + default: Ext.getCmp('removeButton').enable(); break; + } + } + } + }); + //check column for table columns grid + var checkColumn = new Ext.grid.CheckColumn({ + header: 'Filter', + dataIndex: 'FIELD_FILTER', + id: 'FIELD_FILTER', + width: 55 + }); + //columns for table columns grid + var cmColumns = [ + { + id: 'uid', + dataIndex: 'uid', + hidden: true + }, + { + id: 'field_uid', + dataIndex: 'field_uid', + hidden: true + }, + { + id: 'field_key', + dataIndex: 'field_key', + hidden: true + }, + { + id: 'field_null', + dataIndex: 'field_null', + hidden: true + }, + { + id: 'field_dyn', + header: _("ID_DYNAFORM_FIELD"), + dataIndex: 'field_dyn', + width: 220, + // use shorthand alias defined above + editor: { + xtype: 'displayfield', + readOnly: true, + style: 'font-size:11px; font-weight:bold; padding-left:4px' + } + }, { + id: 'field_name', + header: _("ID_FIELD_NAME"), + dataIndex: 'field_name', + width: 220, + editor: { + xtype: 'textfield', + allowBlank: true, + style:'text-transform: uppercase', + listeners:{ + /*specialkey: function(f,e){ + if(e.getKey()==e.ENTER){ + this.setValue(this.getValue().toUpperCase()); + } + }*/ + change: function(f,e){ + this.setValue(this.getValue().toUpperCase()); + } + } + } + }, { + id: 'field_label', + header: _("ID_FIELD_LABEL"), + dataIndex: 'field_label', + width: 220, + editor:{ + xtype: 'textfield', + allowBlank: true + } + }, { + id: 'field_type', + header: _("ID_TYPE"), + dataIndex: 'field_type', + width: 75, + editor: new fm.ComboBox({ + typeAhead: true, + triggerAction: 'all', + editable:false, + lazyRender: true, + mode: 'local', + displayField:'type', + valueField:'type_id', + store: new Ext.data.SimpleStore({ + fields: ['type_id', 'type'], + data : [['VARCHAR',_("ID_VARCHAR")],['TEXT',_("ID_TEXT")],['DATE',_("ID_DATE")],['INT',_("ID_INT")],['FLOAT',_("ID_FLOAT")]], + sortInfo: {field:'type_id', direction:'ASC'} + }) + }) + }, { + id: 'field_size', + header: _("ID_SIZE"), + dataIndex: 'field_size', + width: 70, + align: 'right', + editor: new fm.NumberField({ + allowBlank: true + }) + } + ]; + + //if permissions plugin is enabled + if (TABLE !== false && TABLE.ADD_TAB_TAG == 'plugin@simplereport') { + cmColumns.push({ + xtype: 'booleancolumn', + header: 'Filter', + dataIndex: 'field_filter', + align: 'center', + width: 50, + trueText: 'Yes', + falseText: 'No', + editor: { + xtype: 'checkbox' + } + }) + } + + //column model for table columns grid + var cm = new Ext.grid.ColumnModel({ + // specify any defaults for each column + defaults: { + sortable: true // columns are not sortable by default + }, + columns:cmColumns + }); + //store for table columns grid + store = new Ext.data.ArrayStore({ + fields: [ + {name: 'uid', type: 'string'}, + {name: 'field_uid', type: 'string'}, + {name: 'field_key', type: 'string'}, + {name: 'field_name', type: 'string'}, + {name: 'field_label', type: 'string'}, + {name: 'field_type'}, + {name: 'field_size', type: 'float'}, + {name: 'field_null', type: 'float'}, + {name: 'field_filter', type: 'string'} + ] + }); + //row editor for table columns grid + editor = new Ext.ux.grid.RowEditor({ + saveText: _("ID_UPDATE") + }); + + editor.on({ + afteredit: function(roweditor, changes, record, rowIndex) { + // + }, + beforeedit: function(roweditor, rowIndex) { + row = assignedGrid.getSelectionModel().getSelected(); + if (row.get('field_name') == 'APP_UID' || row.get('field_name') == 'APP_NUMBER' || row.get('field_name') == 'ROW') { + return false; + } + } + }); + + //table columns grid + assignedGrid = new Ext.grid.GridPanel({ + //title: 'Columns', + region : 'center', + id : 'assignedGrid', + ddGroup : 'availableGridDDGroup', + enableDragDrop : true, + viewConfig : {forceFit: true}, + cm : cm, + sm : sm, + store : store, + plugins : [editor, checkColumn], + tbar : [{ + icon: '/images/addcolumn.jpg', + text: _("ID_ADD_CUSTOM_COLUMN"), + handler: addColumn + }], + listeners: { + render: function(grid) { + var ddrow = new Ext.dd.DropTarget(grid.getView().mainBody, { + ddGroup: 'availableGridDDGroup', + copy: false, + notifyDrop: function(dd, e, data) { + var ds = grid.store; + var sm = grid.getSelectionModel(); + var rows = sm.getSelections(); + if (dd.getDragData(e)) { + var cindex = dd.getDragData(e).rowIndex; + //skipping primary keys, we can't reorder + if (store.data.items[cindex].data.field_key) + return; + + if (typeof(cindex) != "undefined") { + for(var i = 0; i < rows.length; i++) { + //skipping primary keys, we can't reorder + if (rows[i].data.field_key ) + continue; + + var srcIndex = ds.indexOfId(rows[i].id); + ds.remove(ds.getById(rows[i].id)); + if (i > 0 && cindex < srcIndex) { + cindex++; + } + ds.insert(cindex, rows[i]); + } + sm.selectRecords(rows); + } + } + } + }); + } + } + }); + + assignedGrid.getSelectionModel().on('selectionchange', function(sm){ + //alert('s'); + }); + + // (vertical) selection buttons + buttonsPanel = new Ext.Panel({ + width : 40, + layout : { + type:'vbox', + padding:'0', + pack:'center', + align:'center' + }, + defaults:{margins:'0 0 35 0'}, + items:[ + { xtype:'button',text: '>', + handler: AssignFieldsAction, + id: 'assignButton', disabled: true + }, + { xtype:'button',text: '<', + handler: RemoveFieldsAction, + id: 'removeButton', disabled: true + }, + { xtype:'button',text: '>>', + handler: AssignAllFieldsAction, + id: 'assignButtonAll', disabled: false}, + { xtype:'button',text: '<<', + handler: RemoveAllFieldsAction, + id: 'removeButtonAll', disabled: false + } + ] + + }); + + + FieldsPanel = new Ext.Panel({ + //title: _('ID_FIELDS'), + region : 'center', + //autoWidth : true, + width: 150, + layout : 'hbox', + defaults : { flex : 1 }, //auto stretch + layoutConfig : { align : 'stretch' }, + items : [availableGrid,buttonsPanel,assignedGrid], + viewConfig : {forceFit:true} + + }); + + searchTextA = new Ext.form.TextField ({ + id: 'searchTextA', + ctCls:'pm_search_text_field', + allowBlank: true, + width: 110, + emptyText: _('ID_ENTER_SEARCH_TERM'), + listeners: { + specialkey: function(f,e){ + if (e.getKey() == e.ENTER) { + DoSearchA(); + } + } + } + }); + + searchTextP = new Ext.form.TextField ({ + id: 'searchTextP', + ctCls:'pm_search_text_field', + allowBlank: true, + width: 110, + emptyText: _('ID_ENTER_SEARCH_TERM'), + listeners: { + specialkey: function(f,e){ + if (e.getKey() == e.ENTER) { + DoSearchP(); + } + } + } + }); + + var types = new Ext.data.SimpleStore({ + fields: ['REP_TAB_TYPE', 'type'], + data : [['NORMAL',_("ID_GLOBAL")],['GRID',_("ID_GRID")]] + }); + + comboReport = new Ext.form.ComboBox({ + id : 'REP_TAB_TYPE', + name: 'type', + fieldLabel: 'Type', + hiddenName : 'REP_TAB_TYPE', + mode: 'local', + store: types, + displayField:'type', + valueField:'REP_TAB_TYPE', + width: 120, + typeAhead: true, + triggerAction: 'all', + editable:false, + lazyRender: true, + value: typeof TABLE.ADD_TAB_TYPE != 'undefined'? TABLE.ADD_TAB_TYPE : 'NORMAL', + listeners: { + select: function(combo,record,index){ + if (this.getValue()=='NORMAL') { + Ext.getCmp('REP_TAB_GRID').setVisible(false); + loadFieldNormal(); + } else { + Ext.getCmp('availableGrid').store.removeAll(); + Ext.getCmp('REP_TAB_GRID').setVisible(true); + Ext.getCmp('REP_TAB_GRID').setValue(''); + gridsListStore.reload({params:{PRO_UID : PRO_UID !== false ? PRO_UID : Ext.getCmp('PROCESS').getValue()}}); + } + } + } + }); + + dbConnectionsStore = new Ext.data.Store({ + //autoLoad: true, + proxy : new Ext.data.HttpProxy({ + url: '../pmTablesProxy/getDbConnectionsList', + method : 'POST' + }), + baseParams : { + PRO_UID : '' + }, + reader : new Ext.data.JsonReader( { + fields : [{name : 'DBS_UID'}, {name : 'DBS_NAME'}] + }), + listeners: { + load: function() { + if (TABLE !== false) { // is editing + // set current editing process combobox + var i = this.findExact('DBS_UID', TABLE.DBS_UID, 0); + if (i > -1){ + comboDbConnections.setValue(this.getAt(i).data.DBS_UID); + comboDbConnections.setRawValue(this.getAt(i).data.DBS_NAME); + comboDbConnections.setDisabled(true); + } else { + // DB COnnection deleted + Ext.Msg.alert( _('ID_ERROR'), 'DB Connection doesn\'t exist!'); + } + } else { + comboDbConnections.setValue('rp'); + } + } + } + }); + + comboDbConnections = new Ext.form.ComboBox({ + id: 'REP_TAB_CONNECTION', + fieldLabel : _("ID_DB_CONNECTION"), + hiddenName : 'DBS_UID', + store : dbConnectionsStore, + //value: 'rp', + valueField : 'DBS_UID', + displayField : 'DBS_NAME', + triggerAction : 'all', + editable : false, + mode:'local' + }); + + gridsListStore = new Ext.data.Store({ + //autoLoad: true, + proxy : new Ext.data.HttpProxy({ + url: '../pmTablesProxy/availableFieldsReportTables', + method : 'POST' + }), + baseParams : { + PRO_UID : '', + TYPE: 'GRID' + }, + reader : new Ext.data.JsonReader( { + root : 'processFields', + fields : [{name : 'FIELD_UID'}, {name : 'FIELD_NAME'}] + }), + listeners: { + load: function(){ + if (TABLE !== false) { + var i = this.findExact('FIELD_UID', TABLE.ADD_TAB_GRID, 0); + if (i > -1){ + comboGridsList.setValue(this.getAt(i).data.FIELD_UID); + comboGridsList.setRawValue(this.getAt(i).data.FIELD_NAME); + comboGridsList.setDisabled(true); + } else { + Ext.Msg.alert( _('ID_ERROR'), 'Grid doesn\'t exist!'); + } + } + } + } + }); + + comboGridsList = new Ext.form.ComboBox({ + id: 'REP_TAB_GRID', + fieldLabel : 'Grid', + hiddenName : 'FIELD_UID', + store : gridsListStore, + emptyText: _("ID_SELECT_GRID"), + //hidden:true, + //hideLabel: true, + //value: 'rp', + valueField : 'FIELD_UID', + displayField : 'FIELD_NAME', + triggerAction : 'all', + width: 120, + editable : false, + mode:'local', + listeners:{ + afterrender: function(){ + //Ext.getCmp('REP_TAB_GRID').setVisible(false); + //loadFieldNormal(); + }, + select: function(combo,record,index){ + + //Ext.getCmp('REP_TAB_TYPE').setVisible(true); + // Ext.getCmp('REP_TAB_GRID').setVisible(true); + loadFieldsGrids(); + + } + } + }); + + + processStore = new Ext.data.Store( { + autoLoad: true, + proxy : new Ext.data.HttpProxy({ + url: '../pmTablesProxy/getProcessList', + method : 'POST' + }), + baseParams : { + action: 'getProcessList' + }, + reader : new Ext.data.JsonReader( { + fields : [{name : 'PRO_UID'}, {name : 'PRO_TITLE'},{name : 'PRO_DESCRIPTION'}] + }), + listeners: { + load: function() { + if (TABLE !== false) { // is editing + // set current editing process combobox + var i = this.findExact('PRO_UID', TABLE.PRO_UID, 0); + if (i > -1){ + processComboBox.setValue(this.getAt(i).data.PRO_UID); + processComboBox.setRawValue(this.getAt(i).data.PRO_TITLE); + processComboBox.setDisabled(true); + } else { + // Process deleted + Ext.Msg.alert( _('ID_ERROR'), 'Process doesn\'t exist!'); + } + // setting table attributes for current editing process + Ext.getCmp('REP_TAB_NAME').setValue(TABLE.ADD_TAB_NAME); + Ext.getCmp('REP_TAB_NAME').setDisabled(true); + Ext.getCmp('REP_TAB_DSC').setValue(TABLE.ADD_TAB_DESCRIPTION); + + // grid + comboReport.setDisabled(true); + if (TABLE.ADD_TAB_TYPE == 'GRID') { + Ext.getCmp('REP_TAB_GRID').setVisible(true); + gridsListStore.reload({params:{PRO_UID : Ext.getCmp('PROCESS').getValue()}}); + } + // db connections + comboDbConnections.getStore().reload({params:{PRO_UID : Ext.getCmp('PROCESS').getValue()}}); + + // loading available fields + //if (TABLE.ADD_TAB_TYPE == 'NORMAL') { + loadAvFieldsFromArray(avFieldsList); + //} + + // loading table fields + loadTableRowsFromArray(TABLE.FIELDS); + } + } + } + }); + + processComboBox = new Ext.form.ComboBox({ + id: 'PROCESS', + fieldLabel : _("ID_CASESLIST_APP_PRO_TITLE"), + hiddenName : 'PRO_UID', + store : processStore, + emptyText: _("ID_EMPTY_PROCESSES"), + valueField : 'PRO_UID', + displayField : 'PRO_TITLE', + + //width: 180, + editable : true, + typeAhead: true, + mode: 'local', + autocomplete: true, + triggerAction: 'all', + forceSelection: true, + + listeners:{ + select: function(){ + comboDbConnections.getStore().reload({params:{PRO_UID : Ext.getCmp('PROCESS').getValue()}}); + if (Ext.getCmp('REP_TAB_TYPE').getValue() == 'GRID') { + gridsListStore.reload({params:{PRO_UID : Ext.getCmp('PROCESS').getValue()}}); + } else { + loadFieldNormal(); + } + } + } + }); + + var tbar = new Array(); + //if (_plugin_permissions !== false) { + if (TABLE !== false && TABLE.ADD_TAB_TAG == 'plugin@simplereport') { + tbar = [ + { + text: _plugin_permissions.label, + handler: function(){ + setTimeout(_plugin_permissions.fn, 0); + } + } + ] + } + + var items = new Array(); + if (PRO_UID === false) + items.push(processComboBox); + + items.push({ + id: 'REP_TAB_NAME', + fieldLabel: _("ID_TABLE_NAME"), + xtype:'textfield', + emptyText: _("ID_SET_A_TABLE_NAME"), + width: 250, + stripCharsRe: /(\W+)/g, + style:'text-transform: uppercase', + listeners:{ + change: function(){ + this.setValue(this.getValue().toUpperCase()) + } + } + }); + items.push({ + id: 'REP_TAB_DSC', + fieldLabel: _("ID_DESCRIPTION"), + xtype:'textarea', + emptyText: _("ID_SET_TABLE_DESCRIPTION"), + width: 250, + height: 40, + allowBlank: true + }); + items.push({ + xtype: 'hidden', + name: 'REP_TAB_GRID', + value: 'GridComments-463650787492db06640c904001904930' + }); + items.push({ + xtype: 'compositefield', + fieldLabel: _("ID_TYPE"), + msgTarget : 'side', + anchor : '-20', + defaults : {flex: 1 }, + items: [comboReport, comboGridsList] + }); + items.push(comboDbConnections); + + + var frmDetails = new Ext.FormPanel({ + id:'frmDetails', + region: 'north', + labelWidth: 120, + labelAlign:'right', + title: 'New Report Table', + bodyStyle:'padding:10px', + waitMsgTarget : true, + frame: true, + height: _plugin_permissions !== false ? 224 : 200, + defaults: { + allowBlank: false, + msgTarget: 'side', + align:'center' + }, + items: items, + tbar: tbar + }); + + + southPanel = new Ext.FormPanel({ + region: 'south', + buttons:[ { + text: TABLE === false ? _("ID_CREATE") : _("ID_UPDATE"), + handler: createReportTable + }, { + text:_("ID_CANCEL"), + handler: function() { + proParam = PRO_UID !== false ? '?PRO_UID='+PRO_UID : ''; + location.href = '../pmTables' + proParam; //history.back(); + } + }] + }); + + var viewport = new Ext.Viewport({ + layout: 'border', + autoScroll: false, + items:[frmDetails, FieldsPanel, southPanel] + }); + + /*** Editing routines ***/ + if (TABLE !== false) { + if(TABLE.ADD_TAB_TYPE != 'GRID') + Ext.getCmp('REP_TAB_GRID').hide(); + } else { + Ext.getCmp('REP_TAB_GRID').hide(); + } + + if (PRO_UID !== false) { + comboDbConnections.getStore().reload({params:{PRO_UID : PRO_UID}}); + if (Ext.getCmp('REP_TAB_TYPE').getValue() == 'GRID') { + gridsListStore.reload({params:{PRO_UID : PRO_UID}}); + } + + if (TABLE === false) { + loadFieldNormal(); + } //else if(typeof avFieldsList != 'undefined') + //loadAvFieldsFromArray(avFieldsList); + + } else { + + } + + DDLoadFields(); + +}); + + + + + +////////////////////////////////////////////////////////////////////////////////////////// + +function createReportTable() +{ + //validate table name + if(Ext.getCmp('REP_TAB_NAME').getValue().trim() == '') { + Ext.getCmp('REP_TAB_NAME').focus(); + PMExt.error(_('ID_ERROR'), 'Table Name is required.', function(){ + Ext.getCmp('REP_TAB_NAME').focus(); + }); + return false; + } + + var allRows = assignedGrid.getStore(); + var columns = new Array(); + + var hasSomePrimaryKey = false; + + //validate columns count + if(allRows.getCount() == 0) { + PMExt.error(_('ID_ERROR'), 'Set columns for this Report Table please.'); + return false; + } + + for (var r=0; r < allRows.getCount(); r++) { + row = allRows.getAt(r); + + // validate that fieldname is not empty + if(row.data['field_name'].trim() == '') { + PMExt.error(_('ID_ERROR'), 'Field Name for "'+row.data['field_dyn']+'" is required.'); + return false; + } + + if(row.data['field_label'].trim() == '') { + PMExt.error(_('ID_ERROR'), 'Field Label for all columns is required.'); + return false; + } + + // validate field size for varchar & int column types + if(row.data['field_type'] == 'VARCHAR' || row.data['field_type'] == 'INT') { + PMExt.error(_('ID_ERROR'), 'Set a field size for '+row.data['field_name']+' ('+row.data['field_type']+') please.'); + return false; + } + + if (row.data['field_key']) { + hasSomePrimaryKey = true; + } + + columns.push(row.data); + } + + if (!hasSomePrimaryKey) { + PMExt.error(_('ID_ERROR'), 'You need set one column at least as Primary Key.'); + return; + } + + Ext.Ajax.request({ + url: '../pmTablesProxy/save', + params: { + REP_TAB_UID : TABLE !== false ? TABLE.ADD_TAB_UID : '', + PRO_UID : PRO_UID !== false? PRO_UID : Ext.getCmp('PROCESS').getValue(), + REP_TAB_NAME : Ext.getCmp('REP_TAB_NAME').getValue(), + REP_TAB_DSC : Ext.getCmp('REP_TAB_DSC').getValue(), + REP_TAB_CONNECTION : Ext.getCmp('REP_TAB_CONNECTION').getValue(), + REP_TAB_TYPE : Ext.getCmp('REP_TAB_TYPE').getValue(), + REP_TAB_GRID : Ext.getCmp('REP_TAB_TYPE').getValue()=='GRID'? Ext.getCmp('REP_TAB_GRID').getValue(): '', + columns : Ext.util.JSON.encode(columns) + }, + success: function(resp){ + result = Ext.util.JSON.decode(resp.responseText); + + if (result.success) { + proParam = PRO_UID !== false ? '?PRO_UID='+PRO_UID : ''; + location.href = '../pmTables' + proParam; //history.back(); + } else { + Ext.Msg.alert( _('ID_ERROR'), result.msg+'\n'+result.trace); + } + }, + failure: function(obj, resp){ + Ext.Msg.alert( _('ID_ERROR'), resp.result.msg); + } + }); +} +//end createReportTable + +//add custon column for assignedGrid +function addColumn() +{ + var PMRow = assignedGrid.getStore().recordType; + var row = new PMRow({ + uid : '', + field_uid : '', + field_dyn : '', + field_name : '', + field_label : '', + field_type : '', + field_size : '', + field_key : 0, + field_null : 1 + }); + length = assignedGrid.getStore().data.length; + + editor.stopEditing(); + store.insert(length, row); + assignedGrid.getView().refresh(); + assignedGrid.getSelectionModel().selectRow(length); + editor.startEditing(length); +} + +////ASSIGNBUTON FUNCTIONALITY +AssignFieldsAction = function(){ + records = Ext.getCmp('availableGrid').getSelectionModel().getSelections(); + + for(i=0; i < records.length; i++){ + var PMRow = assignedGrid.getStore().recordType; + var meta = mapPMFieldType(records[i].data['FIELD_UID']); + var row = new PMRow({ + uid : '', + field_uid : records[i].data['FIELD_UID'], + field_dyn : records[i].data['FIELD_NAME'], + field_name : records[i].data['FIELD_NAME'].toUpperCase(), + field_label : records[i].data['FIELD_NAME'].toUpperCase(), + field_type : meta.type, + field_size : meta.size, + field_key : 0, + field_null : 1 + }); + + store.add(row); + } + + //remove from source grid + Ext.each(records, Ext.getCmp('availableGrid').store.remove, Ext.getCmp('availableGrid').store); +}; +//RemoveButton Functionality +RemoveFieldsAction = function(){ + + records = Ext.getCmp('assignedGrid').getSelectionModel().getSelections(); + var PMRow = availableGrid.getStore().recordType; + for(i=0; i < records.length; i++){ + if (records[i].data['field_dyn'] != '' && records[i].data['field_name'] != 'APP_UID' && records[i].data['field_name'] != 'APP_NUMBER' && records[i].data['field_name'] != 'ROW') { + var row = new PMRow({ + FIELD_UID : records[i].data['field_uid'], + FIELD_NAME : records[i].data['field_dyn'] + }); + availableGrid.getStore().add(row); + } else { + records[i] = null; + } + } + //remove from source grid + Ext.each(records, Ext.getCmp('assignedGrid').store.remove, Ext.getCmp('assignedGrid').store); +}; + +//AssignALLButton Functionality +AssignAllFieldsAction = function(){ + var available = Ext.getCmp('availableGrid'); + var allRows = available.getStore(); + var arrAux = new Array(); + records = new Array() + + if (allRows.getCount() > 0){ + var PMRow = assignedGrid.getStore().recordType; + for (i=0; i < allRows.getCount(); i++){ + records[i] = allRows.getAt(i); + var meta = mapPMFieldType(records[i].data['FIELD_UID']); + var row = new PMRow({ + uid : '', + field_uid : records[i].data['FIELD_UID'], + field_dyn : records[i].data['FIELD_NAME'], + field_name : records[i].data['FIELD_NAME'].toUpperCase(), + field_label : records[i].data['FIELD_NAME'].toUpperCase(), + field_type : meta.type, + field_size : meta.size, + field_key : 0, + field_null : 1 + }); + + store.add(row); + } + //remove from source grid + Ext.each(records, Ext.getCmp('availableGrid').store.remove, Ext.getCmp('availableGrid').store); + } + +}; + +//RevomeALLButton Functionality +RemoveAllFieldsAction = function(){ + var allRows = Ext.getCmp('assignedGrid').getStore(); + var records = new Array(); + if (allRows.getCount() > 0) { + var PMRow = availableGrid.getStore().recordType; + for (var i=0; i < allRows.getCount(); i++){ + records[i] = allRows.getAt(i); + if (records[i].data['field_dyn'] != '' && records[i].data['field_name'] != 'APP_UID' && records[i].data['field_name'] != 'APP_NUMBER' && records[i].data['field_name'] != 'ROW') { + var row = new PMRow({ + FIELD_UID : records[i].data['field_uid'], + FIELD_NAME : records[i].data['field_dyn'] + }); + availableGrid.getStore().add(row); + } else { + records[i] = null; + } + } + //remove from source grid + Ext.each(records, Ext.getCmp('assignedGrid').store.remove, Ext.getCmp('assignedGrid').store); + } +}; + +//INITIAL FIELDS GRIDS +loadFieldNormal = function(){ + Ext.getCmp('availableGrid').store.removeAll(); + Ext.getCmp('availableGrid').store.load({ + params: { + action: "availableFieldsReportTables", + PRO_UID: PRO_UID !== false ? PRO_UID : Ext.getCmp('PROCESS').getValue() + } + }); + Ext.getCmp('assignedGrid').store.removeAll(); +}; + +loadFieldsGrids = function(){ + var available = Ext.getCmp('availableGrid'); + available.store.removeAll(); + + available.store.load({ + params: { + action: "availableFieldsReportTables", + PRO_UID: PRO_UID !== false ? PRO_UID : Ext.getCmp('PROCESS').getValue(), + TYPE: 'GRID', + GRID_UID: Ext.getCmp('REP_TAB_GRID').getValue() + } + }); + + var assigned = Ext.getCmp('assignedGrid'); + assigned.store.removeAll(); + +}; + +//REFRESH FIELDS GRIDS +RefreshFields = function(){ + var available = Ext.getCmp('availableGrid'); + available.store.load({params: {"action":"deleteFieldsReportTables", "PRO_UID":PRO_UID }}); + var assigned = Ext.getCmp('assignedGrid'); + assigned.store.load({params: {"action":"assignedFieldsReportTables", "PRO_UID":PRO_UID }}); +}; + +//FAILURE AJAX FUNCTION +FailureFields = function(){ + Ext.Msg.alert(_('ID_GROUPS'), _('ID_MSG_AJAX_FAILURE')); +}; + +// drag & drop handler +var DDLoadFields = function(){ + var availableGridDropTargetEl = availableGrid.getView().scroller.dom; + var availableGridDropTarget = new Ext.dd.DropTarget(availableGridDropTargetEl, { + ddGroup : 'availableGridDDGroup', + notifyDrop : function(ddSource, e, data){ + + var records = ddSource.dragData.selections; + var PMRow = availableGrid.getStore().recordType; + + for (i=0; i < records.length; i++) { + if (records[i].data['field_dyn'] != '') { + var row = new PMRow({ + FIELD_UID: records[i].data['field_uid'], + FIELD_NAME: records[i].data['field_dyn'] + }); + availableGrid.getStore().add(row); + } else { + if ( records[i].data['field_name'] == 'APP_UID' + || records[i].data['field_name'] == 'APP_NUMBER' + || records[i].data['field_name'] == 'ROW') + { + records[i] = null; + } + } + } + + Ext.each(records, ddSource.grid.store.remove, ddSource.grid.store); + return true; + } + }); + + //droptarget on grid forassignment + var assignedGridDropTargetEl = assignedGrid.getView().scroller.dom; + var assignedGridDropTarget = new Ext.dd.DropTarget(assignedGridDropTargetEl, { + ddGroup : 'assignedGridDDGroup', + notifyDrop : function(ddSource, e, data){ + + var records = ddSource.dragData.selections; + var PMRow = assignedGrid.getStore().recordType; + + //add on target grid + for (i=0; i < records.length; i++){ + //arrAux[r] = records[r].data['FIELD_UID']; + var meta = mapPMFieldType(records[i].data['FIELD_UID']); + var row = new PMRow({ + uid : '', + field_uid : records[i].data['FIELD_UID'], + field_dyn : records[i].data['FIELD_NAME'], + field_name : records[i].data['FIELD_NAME'].toUpperCase(), + field_label : records[i].data['FIELD_NAME'].toUpperCase(), + field_type : meta.type, + field_size : meta.size, + field_key : 0, + field_null : 1 + }); + + store.add(row); + } + //remove from source grid + Ext.each(records, availableGrid.store.remove, availableGrid.store); + + return true; + } + }); + //sw_func_groups = true; +}; + +function loadTableRowsFromArray(records) +{ + var PMRow = assignedGrid.getStore().recordType; + if (records.length == 0) return; + + for(i in records) { + var row = new PMRow({ + uid : records[i].FLD_UID, + field_uid : records[i].FLD_DYN_UID, + field_dyn : records[i].FLD_DYN_NAME, + field_name : records[i].FLD_NAME, + field_label: records[i].FLD_DESCRIPTION, + field_type : records[i].FLD_TYPE, + field_size : records[i].FLD_SIZE, + field_key : records[i].FLD_KEY, + field_null : records[i].FLD_NULL, + field_filter: records[i].FLD_FILTER == '1' ? true : false + }); + + store.add(row); + } +} + +function loadAvFieldsFromArray(records) +{ + var PMRow = availableGrid.getStore().recordType; + + for(i=0; i +
+ diff --git a/workflow/engine/templates/pmTables/list.js b/workflow/engine/templates/pmTables/list.js new file mode 100644 index 000000000..3d6756a10 --- /dev/null +++ b/workflow/engine/templates/pmTables/list.js @@ -0,0 +1,422 @@ +var newButton; +var editButton; +var deleteButton; +var importButton; +var exportButton; +var dataButton; + +var store; +var expander; +var cmodel; +var infoGrid; +var viewport; +var smodel; + +var rowsSelected; + +Ext.onReady(function(){ + ///Keyboard Events + new Ext.KeyMap(document, { + key: Ext.EventObject.F5, + fn: function(keycode, e) { + if (! e.ctrlKey) { + if (Ext.isIE) { + e.browserEvent.keyCode = 8; + } + e.stopEvent(); + document.location = document.location; + } + else{ + Ext.Msg.alert('Refresh', 'You clicked: CTRL-F5'); + } + } + }); + + Ext.QuickTips.init(); + + pageSize = parseInt(CONFIG.pageSize); + + newButton = new Ext.Action({ + text: _('ID_NEW'), + iconCls: 'button_menu_ext ss_sprite ss_add', + + menu: [ + { + text: 'New Table', + handler: newPMTable + }, { + text: 'New Report Table', + handler: NewReportTable + } + ] + }); + + editButton = new Ext.Action({ + text: _('ID_EDIT'), + icon: '/images/icon-edit.png', + handler: EditPMTable, + disabled: true + }); + + deleteButton = new Ext.Action({ + text: _('ID_DELETE'), + iconCls: 'button_menu_ext ss_sprite ss_delete', + handler: DeletePMTable, + disabled: true + }); + + importButton = new Ext.Action({ + text: _('ID_IMPORT'), + iconCls: 'silk-add', + icon: '/images/import.gif', + handler: ImportPMTable + }); + + exportButton = new Ext.Action({ + text: _('ID_EXPORT'), + iconCls: 'silk-add', + icon: '/images/export.png', + handler: ExportPMTable, + disabled: true + }); + + dataButton = new Ext.Action({ + text: ' ' + _('ID_DATA'), + iconCls: 'silk-add', + icon: '/images/database-start.png', + handler: PMTableData, + disabled: true + }); + + searchButton = new Ext.Action({ + text: _('ID_SEARCH'), + handler: DoSearch + }); + + contextMenu = new Ext.menu.Menu({ + items: [editButton, deleteButton,'-',dataButton,'-',exportButton] + }); + + searchText = new Ext.form.TextField ({ + id: 'searchTxt', + ctCls:'pm_search_text_field', + allowBlank: true, + width: 150, + emptyText: _('ID_ENTER_SEARCH_TERM'), + listeners: { + specialkey: function(f,e){ + if (e.getKey() == e.ENTER) { + DoSearch(); + } + }, + focus: function(f,e) { + var row = infoGrid.getSelectionModel().getSelected(); + infoGrid.getSelectionModel().deselectRow(infoGrid.getStore().indexOf(row)); + } + } + }); + + clearTextButton = new Ext.Action({ + text: 'X', + ctCls:'pm_search_x_button', + handler: GridByDefault + }); + + storePageSize = new Ext.data.SimpleStore({ + fields: ['size'], + data: [['20'],['30'],['40'],['50'],['100']], + autoLoad: true + }); + + comboPageSize = new Ext.form.ComboBox({ + typeAhead : false, + mode : 'local', + triggerAction : 'all', + store: storePageSize, + valueField: 'size', + displayField: 'size', + width: 50, + editable: false, + listeners:{ + select: function(c,d,i){ + UpdatePageConfig(d.data['size']); + bbarpaging.pageSize = parseInt(d.data['size']); + bbarpaging.moveFirst(); + } + } + }); + + comboPageSize.setValue(pageSize); + + + store = new Ext.data.GroupingStore( { + proxy : new Ext.data.HttpProxy({ + url: 'pmTablesProxy/getList' + }), + reader : new Ext.data.JsonReader( { + root: 'rows', + totalProperty: 'count', + fields : [ + {name : 'ADD_TAB_UID'}, + {name : 'ADD_TAB_NAME'}, + {name : 'ADD_TAB_DESCRIPTION'}, + {name : 'PRO_TITLE'}, + {name : 'TYPE'}, + {name : 'ADD_TAB_TYPE'}, + {name : 'ADD_TAB_TAG'}, + {name : 'PRO_UID'}, + ] + }) + }); + + smodel = new Ext.grid.CheckboxSelectionModel({ + listeners:{ + selectionchange: function(sm){ + var count_rows = sm.getCount(); + switch(count_rows){ + case 0: + editButton.disable(); + deleteButton.disable(); + exportButton.disable(); + dataButton.disable(); + break; + case 1: + editButton.enable(); + deleteButton.enable(); + exportButton.enable(); + dataButton.enable(); + break; + default: + editButton.disable(); + deleteButton.enable(); + exportButton.enable(); + dataButton.disable(); + break; + } + } + } + }); + + cmodelColumns = new Array(); + cmodelColumns.push({id:'ADD_TAB_UID', dataIndex: 'ADD_TAB_UID', hidden:true, hideable:false}); + cmodelColumns.push({dataIndex: 'ADD_TAB_TAG', hidden:true, hideable:false}); + cmodelColumns.push({header: _('ID_NAME'), dataIndex: 'ADD_TAB_NAME', width: 300, align:'left', renderer: function(v,p,r){ + return r.get('TYPE') == 'CLASSIC'? v + ' (old version)' : v; + }}); + cmodelColumns.push({header: _('ID_DESCRIPTION'), dataIndex: 'ADD_TAB_DESCRIPTION', width: 400, hidden:false, align:'left', renderer: function(v,p,r){ + if (r.get('ADD_TAB_TAG')) { + tag = r.get('ADD_TAB_TAG').replace('plugin@', ''); + tag = tag.charAt(0).toUpperCase() + tag.slice(1); + } + return r.get('ADD_TAB_TAG') ? ''+tag+': '+ v : v; + }}); + + cmodelColumns.push({header: 'Table Type', dataIndex: 'PRO_UID', width: 120, align:'left', renderer: function(v,p,r){ + color = r.get('PRO_UID') == '' ? 'green' : 'blue'; + value = r.get('PRO_UID') == '' ? 'Table' : 'Report'; + return ''+value+' '; + }}); + + if (PRO_UID === false) { + cmodelColumns.push({header: _('ID_PROCESS'), dataIndex: 'PRO_TITLE', width: 180, align:'left'}); + } + + cmodelColumns.push({header: _('ID_TYPE'), dataIndex: 'ADD_TAB_TYPE', width: 400, hidden:true, align:'left'}); + + cmodel = new Ext.grid.ColumnModel({ + defaults: { + width: 50, + sortable: true + }, + columns: cmodelColumns + }); + + bbarpaging = new Ext.PagingToolbar({ + pageSize: pageSize, + store: store, + displayInfo: true, + displayMsg: _('ID_GRID_PAGE_DISPLAYING_PMTABLES_MESSAGE') + '    ', + emptyMsg: _('ID_GRID_PAGE_NO_PMTABLES_MESSAGE'), + items: ['-',_('ID_PAGE_SIZE')+':',comboPageSize] + }); + + infoGrid = new Ext.grid.GridPanel({ + region: 'center', + layout: 'fit', + id: 'infoGrid', + height:100, + autoWidth : true, + title : _('ID_ADDITIONAL_TABLES'), + stateful : true, + stateId : 'grid', + enableColumnResize: true, + enableHdMenu: true, + frame:false, + columnLines: false, + viewConfig: { + forceFit:true + }, + store: store, + cm: cmodel, + sm: smodel, + tbar:[newButton, editButton, deleteButton,'-', dataButton,'-' , importButton, exportButton,{xtype: 'tbfill'},searchText,clearTextButton,searchButton], + bbar: bbarpaging, + listeners: { + rowdblclick: EditPMTable, + render: function(){ + this.loadMask = new Ext.LoadMask(this.body, {msg:_('ID_LOADING_GRID')}); + } + }, + view: new Ext.grid.GroupingView({ + forceFit:true, + groupTextTpl: '{text}' + }) + }); + + infoGrid.on('rowcontextmenu', + function (grid, rowIndex, evt) { + var sm = grid.getSelectionModel(); + sm.selectRow(rowIndex, sm.isSelected(rowIndex)); + }, + this + ); + + infoGrid.on('contextmenu', function(evt){evt.preventDefault();}, this); + infoGrid.addListener('rowcontextmenu',onMessageContextMenu, this); + + infoGrid.store.load(); + + viewport = new Ext.Viewport({ + layout: 'fit', + autoScroll: false, + items: [ + infoGrid + ] + }); +}); + +//Funtion Handles Context Menu Opening +onMessageContextMenu = function (grid, rowIndex, e) { + e.stopEvent(); + var coords = e.getXY(); + contextMenu.showAt([coords[0], coords[1]]); +}; + +/////JS FUNCTIONS + +//Capitalize String Function +capitalize = function(s){ + s = s.toLowerCase(); + return s.replace( /(^|\s)([a-z])/g , function(m,p1,p2){ return p1+p2.toUpperCase(); } ); +}; + +//Do Nothing Function +DoNothing = function(){}; + +//Load New PM Table Forms +NewReportTable = function(){ + //location.href = 'additionalTablesNew'; + + if(PRO_UID !== false) + location.href = 'pmTables/edit?PRO_UID='+PRO_UID+'&tableType=report'; + else + location.href = 'pmTables/edit?tableType=report'; +}; + +newPMTable = function(){ + location.href = 'pmTables/edit?tableType=table'; +}; + +EditPMTable = function(){ + var row = Ext.getCmp('infoGrid').getSelectionModel().getSelected(); + + if (row.data.TYPE != 'CLASSIC') { + tableType = row.data.PRO_UID !== '' ? 'report' : 'table'; + proParam = PRO_UID !== false ? '&PRO_UID='+PRO_UID : ''; + location.href = 'pmTables/edit?id='+row.data.ADD_TAB_UID+'&tableType=' + tableType + proParam; + } + else { //edit old report table + location.href = '../reportTables/reportTables_Edit?REP_TAB_UID='+row.data.ADD_TAB_UID + } +}; + +//Confirm PM Table Deletion Tasks +DeletePMTable = function() { + var rows = Ext.getCmp('infoGrid').getSelectionModel().getSelections(); + var selections = new Array(); + + for(var i=0; i!BF#XVu?N8hH+*b>0E+j(_QQ^LhYUP|Xd#hN;Zbx(5X*oNNi#L@!kU_40mU;Q8GwFMs1_};`gQrb_83y_1{fCmxivJ`<7vu&2KoF1*0{#{R9D&%Pgj8193ISjrJurWC z|7EHHPzZBg<81H_ha8=pT?j;X4^OXS-afvxz@T7y2qTnriX9Uh7yrZg zVixKUbGUU9RsidR?PAP_b-HMiXD?CQRE|F_?J#C`n(gF{cA z4ok*gPE1Zs|2Z=&U0Qy#B73_kf2R&2LpMK9X%iU&jRiMM9gf(6-LlQjO^M3X*lB(a zscD~GQrn@7wxBGc0-{AKTDvSIhSE*y573{-obM3A4ah2aqgF0yKlEeY{BKccy@HC`sc|M zy7XY0YJCP%^+=+=9J)R*OEp&x2$AqwdzDf+#;ItOil-O0-@{DYWn7FO}f;;tHL=N4JHd@k4a0F6)%J&E@qv&%3Y&` z`0W)XO5Eb;68*MC1>ooMRn_Ylxn{6*FIgXj zu_0UYRqc6Icu{9uJSXZpwbmGS*bpfhp&6Z_8sd%al@-nQWSJh7k=*#0N20S6RZT1m zo*Otblc>d|>GN6i(>!N-c)^t^F3tMd&F7p#Ii@bbd9gsQ&-BNpD1dgM52;ahE8t|( ztEj?_>+DH+_t^pZ)K$U0x(>ecuEq@{tC)Z1jQG{-=j**HcXIB_gK;PYz+14jn6S+{ zXc2aLpH5|e;AI7H_otK>4m?+;?9xa=0z^mB%BU)Q<8R`P9t}&cKu{wf=XQ(R>=#Fs z=a(L;%A@8i5**r$V;F&TExE~a8$-M+d-#5$iWv`imJxqW%Dz$FGo4gX9m82&5fj%& z8FELfKej*CS=Zap=JONu7K;U}cy{9c3xg#4rB1io86;_9MuV%($`^POQ{4j#bMxE% zgo3OkO>ub7;a}3c1j6X#EK8#mH$XDnFA=V1pEBx3Ej;wwmqzmX*bmL*!QP^>98rSeG&&>o&_iwnnr| z(m8Tqpo3YnZL(p51Jh0G5WBPE89~h_accyOlRFV-#UNUa75WOa_msKa_utu5Yd+mY zo%P}xr&&t9n-6+S^dD!x7Dq?+l7dFwT1dKkAH;Z2KvwCDEg@x7lIShp~=I$SNeBQSsJfoU7|yjj9L z^P^xx+UwRi3fXRr%q|w0Vio4HC%ifj%qfVEb8g=nwwWPycBVz3m*mY)T>;mR^%u{L zpKxAnO>g4=viLYB!B;lSUtNI?R4s9hC`m3#O)N>(O#u=NMg|5Jx`qb2M#dqAhE}E) xR>o%91{PKZ1}lXl@4+