From 017ebe2a20a8f2e2c8e9bdff26ffd8abc4bdc4f2 Mon Sep 17 00:00:00 2001 From: nuxsmin Date: Mon, 28 Oct 2013 02:20:47 +0100 Subject: [PATCH] Fix updates checking. Change fancybox to alertify for non-locking messages. Fix error on removing groups. Set version string in DB and config file. Update translations. Add scroll to search, users, groups and profiles results. Update to 1.0rc3 --- CHANGELOG | 18 ++ ajax/ajax_checkupds.php | 2 +- css/alertify.core.css | 137 ++++++++++++++ css/alertify.default.css | 82 +++++++++ css/styles.css | 16 +- inc/config.class.php | 57 +++--- inc/html.class.php | 3 + inc/init.php | 32 ++++ inc/locales/en_US/LC_MESSAGES/messages.mo | Bin 37137 -> 37382 bytes inc/tpl/search.php | 5 - inc/users.class.php | 18 +- inc/util.class.php | 4 +- js/alertify.min.js | 2 + js/functions.js | 207 +++++++++++----------- js/functions.php | 2 +- 15 files changed, 443 insertions(+), 142 deletions(-) create mode 100644 css/alertify.core.css create mode 100644 css/alertify.default.css create mode 100644 js/alertify.min.js diff --git a/CHANGELOG b/CHANGELOG index 6878922f..f3cf6cdb 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,12 @@ +=== ** v1.0rc3 ** === + +* [BUG] Corregidos fallos en la comprobación de actualizaciones. +* [BUG] Corregido error al borrar grupos. +* [MOD] Cambio de fancybox por alertify para los mensajes que no requieren de bloqueo. +* [MOD] Ecribir versión en BD y archivo de configuración. +* [MOD] Añadir scroll en resultados de cuentas, usuarios, grupos y perfiles. +* [MOD] Actualizadas las traducciones. + === ** v1.0rc2 ** === * [MOD] Mejor manejo de peticiones GET/POST. @@ -109,6 +118,15 @@ --- +=== ** v1.0rc3 ** === + +* [BUG] Fix updates checking. +* [BUG] Fix error on removing groups. +* [MOD] Change fancybox to alertify for non-locking messages. +* [MOD] Set version string in DB and config file +* [MOD] Update translations +* [MOD] Add scroll to search, users, groups and profiles results. + === ** v1.0rc2 ** === * [MOD] Better GET/POST variable handling. diff --git a/ajax/ajax_checkupds.php b/ajax/ajax_checkupds.php index 1d7bbddb..a0637745 100644 --- a/ajax/ajax_checkupds.php +++ b/ajax/ajax_checkupds.php @@ -28,7 +28,7 @@ include_once (APP_ROOT."/inc/init.php"); SP_Util::checkReferer('GET'); -$checkVersion = SP_Common::parseParams('s', 'UPDATED', FALSE); +$checkVersion = SP_Common::parseParams('s', 'UPDATED', FALSE, TRUE); // Una vez por sesión if ( ! $checkVersion ){ diff --git a/css/alertify.core.css b/css/alertify.core.css new file mode 100644 index 00000000..12d82dd2 --- /dev/null +++ b/css/alertify.core.css @@ -0,0 +1,137 @@ +.alertify, +.alertify-show, +.alertify-log { + -webkit-transition: all 500ms cubic-bezier(0.175, 0.885, 0.320, 1.275); + -moz-transition: all 500ms cubic-bezier(0.175, 0.885, 0.320, 1.275); + -ms-transition: all 500ms cubic-bezier(0.175, 0.885, 0.320, 1.275); + -o-transition: all 500ms cubic-bezier(0.175, 0.885, 0.320, 1.275); + transition: all 500ms cubic-bezier(0.175, 0.885, 0.320, 1.275); /* easeOutBack */ +} +.alertify-hide { + -webkit-transition: all 250ms cubic-bezier(0.600, -0.280, 0.735, 0.045); + -moz-transition: all 250ms cubic-bezier(0.600, -0.280, 0.735, 0.045); + -ms-transition: all 250ms cubic-bezier(0.600, -0.280, 0.735, 0.045); + -o-transition: all 250ms cubic-bezier(0.600, -0.280, 0.735, 0.045); + transition: all 250ms cubic-bezier(0.600, -0.280, 0.735, 0.045); /* easeInBack */ +} +.alertify-log-hide { + -webkit-transition: all 500ms cubic-bezier(0.600, -0.280, 0.735, 0.045); + -moz-transition: all 500ms cubic-bezier(0.600, -0.280, 0.735, 0.045); + -ms-transition: all 500ms cubic-bezier(0.600, -0.280, 0.735, 0.045); + -o-transition: all 500ms cubic-bezier(0.600, -0.280, 0.735, 0.045); + transition: all 500ms cubic-bezier(0.600, -0.280, 0.735, 0.045); /* easeInBack */ +} +.alertify-cover { + position: fixed; z-index: 99999; + top: 0; right: 0; bottom: 0; left: 0; + background-color:white; + filter:alpha(opacity=0); + opacity:0; +} + .alertify-cover-hidden { + display: none; + } +.alertify { + position: fixed; z-index: 99999; + top: 50px; left: 50%; + width: 550px; + margin-left: -275px; + opacity: 1; +} + .alertify-hidden { + -webkit-transform: translate(0,-150px); + -moz-transform: translate(0,-150px); + -ms-transform: translate(0,-150px); + -o-transform: translate(0,-150px); + transform: translate(0,-150px); + opacity: 0; + display: none; + } + /* overwrite display: none; for everything except IE6-8 */ + :root *> .alertify-hidden { + display: block; + visibility: hidden; + } +.alertify-logs { + position: fixed; + z-index: 5000; + bottom: 10px; + right: 10px; + width: 300px; +} +.alertify-logs-hidden { + display: none; +} + .alertify-log { + display: block; + margin-top: 10px; + position: relative; + right: -300px; + opacity: 0; + } + .alertify-log-show { + right: 0; + opacity: 1; + } + .alertify-log-hide { + -webkit-transform: translate(300px, 0); + -moz-transform: translate(300px, 0); + -ms-transform: translate(300px, 0); + -o-transform: translate(300px, 0); + transform: translate(300px, 0); + opacity: 0; + } + .alertify-dialog { + padding: 25px; + } + .alertify-resetFocus { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; + } + .alertify-inner { + text-align: center; + } + .alertify-text { + margin-bottom: 15px; + width: 100%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + font-size: 100%; + } + .alertify-buttons { + } + .alertify-button, + .alertify-button:hover, + .alertify-button:active, + .alertify-button:visited { + background: none; + text-decoration: none; + border: none; + /* line-height and font-size for input button */ + line-height: 1.5; + font-size: 100%; + display: inline-block; + cursor: pointer; + margin-left: 5px; + } + +@media only screen and (max-width: 680px) { + .alertify, + .alertify-logs { + width: 90%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; + } + .alertify { + left: 5%; + margin: 0; + } +} diff --git a/css/alertify.default.css b/css/alertify.default.css new file mode 100644 index 00000000..e6e3d89f --- /dev/null +++ b/css/alertify.default.css @@ -0,0 +1,82 @@ +/** + * Default Look and Feel + */ +.alertify, +.alertify-log { + font-family: sans-serif; +} +.alertify { + background: #FFF; + border: 10px solid #333; /* browsers that don't support rgba */ + border: 10px solid rgba(0,0,0,.7); + border-radius: 8px; + box-shadow: 0 3px 3px rgba(0,0,0,.3); + -webkit-background-clip: padding; /* Safari 4? Chrome 6? */ + -moz-background-clip: padding; /* Firefox 3.6 */ + background-clip: padding-box; /* Firefox 4, Safari 5, Opera 10, IE 9 */ +} +.alertify-text { + border: 1px solid #CCC; + padding: 10px; + border-radius: 4px; +} +.alertify-button { + border-radius: 4px; + color: #FFF; + font-weight: bold; + padding: 6px 15px; + text-decoration: none; + text-shadow: 1px 1px 0 rgba(0,0,0,.5); + box-shadow: inset 0 1px 0 0 rgba(255,255,255,.5); + background-image: -webkit-linear-gradient(top, rgba(255,255,255,.3), rgba(255,255,255,0)); + background-image: -moz-linear-gradient(top, rgba(255,255,255,.3), rgba(255,255,255,0)); + background-image: -ms-linear-gradient(top, rgba(255,255,255,.3), rgba(255,255,255,0)); + background-image: -o-linear-gradient(top, rgba(255,255,255,.3), rgba(255,255,255,0)); + background-image: linear-gradient(top, rgba(255,255,255,.3), rgba(255,255,255,0)); +} +.alertify-button:hover, +.alertify-button:focus { + outline: none; + background-image: -webkit-linear-gradient(top, rgba(0,0,0,.1), rgba(0,0,0,0)); + background-image: -moz-linear-gradient(top, rgba(0,0,0,.1), rgba(0,0,0,0)); + background-image: -ms-linear-gradient(top, rgba(0,0,0,.1), rgba(0,0,0,0)); + background-image: -o-linear-gradient(top, rgba(0,0,0,.1), rgba(0,0,0,0)); + background-image: linear-gradient(top, rgba(0,0,0,.1), rgba(0,0,0,0)); +} +.alertify-button:focus { + box-shadow: 0 0 15px #2B72D5; +} +.alertify-button:active { + position: relative; + box-shadow: inset 0 2px 4px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.05); +} +.alertify-button-cancel, +.alertify-button-cancel:hover, +.alertify-button-cancel:focus { + background-color: #FE1A00; + border: 1px solid #D83526; +} +.alertify-button-ok, +.alertify-button-ok:hover, +.alertify-button-ok:focus { + background-color: #5CB811; + border: 1px solid #3B7808; +} + +.alertify-log { + background: #1F1F1F; + background: rgba(0,0,0,.9); + padding: 15px; + border-radius: 4px; + color: #FFF; + font-weight: bold; + text-shadow: -1px -1px 0 rgba(0,0,0,.5); +} +.alertify-log-error { + background: #FE1A00; + background: rgba(254,26,0,.9); +} +.alertify-log-success { + background: #5CB811; + background: rgba(92,184,17,.9); +} \ No newline at end of file diff --git a/css/styles.css b/css/styles.css index b638bb3a..c30cd24d 100644 --- a/css/styles.css +++ b/css/styles.css @@ -244,8 +244,12 @@ A:focus {text-decoration: none; color: #FF0000;} #content #tblTools{width: 100%; height: 5em; padding-left: 15px;padding: 5px;} -#content #resBuscar{ width: 100%; margin-top: 20px; min-height: 500px;} +#content #resBuscar{ width: 100%; margin-top: 20px;} #content #resBuscar IMG {vertical-align:middle;} +#content #resBuscar #data-search, +#content .data-rows, +#content #resEventLog #resSearch +{overflow-y: auto; max-height: 400px} #content #pageNav { float: left; @@ -714,6 +718,16 @@ A:focus {text-decoration: none; color: #FF0000;} #passLevel.good, #passLevel.good:hover { background-color: #FFF2D9 !important; color: orange; font-weight: bold; border: #ffe5b3 1px solid;} #passLevel.weak, #passLevel.weak:hover { background-color: #fee8e6 !important; color: #CC0000; font-weight: bold; border: #fed2ce 1px solid;} +#alert #alert-text{margin: 15px auto; font-size: 14px; font-weight: bold;} +#alert #alert-pass{ + width: 50%; + padding: 10px; + margin: 15px auto; + border: 1px solid #c9c9c9; + color: #555; + font-weight: bold; +} + /*Login Page*/ #boxLogin{ width:450px; diff --git a/inc/config.class.php b/inc/config.class.php index 66f6b2f3..e429b379 100644 --- a/inc/config.class.php +++ b/inc/config.class.php @@ -49,14 +49,14 @@ class SP_Config{ static $arrConfigValue; /** - * @brief Obtener en valor de un parámetro - * @param string $strConfigParam parámetro - * @return string valor + * @brief Obtiene un valor desde la configuración en la BBDD + * @param string $param con el parámetro de configuración + * @return string con el valor * * Obtener el valor de un parámetro almacenado en la BBDD */ - public static function getConfigValue($strConfigParam){ - $query = "SELECT config_value FROM config WHERE config_parameter = '$strConfigParam'"; + public static function getConfigValue($param){ + $query = "SELECT config_value FROM config WHERE config_parameter = '$param'"; $queryRes = DB::getResults($query, __FUNCTION__); if ( $queryRes === FALSE || ! is_array($queryRes) ){ @@ -65,7 +65,7 @@ class SP_Config{ return $queryRes[0]->config_value; } - + /** * @brief Obtener array con la configuración * @@ -122,7 +122,34 @@ class SP_Config{ return TRUE; } - + + /** + * @brief Guardar un parámetro de configuración + * @param string $param con el parámetro a guardar + * @param string $value con el calor a guardar + * @return bool + */ + public static function setConfigValue($param, $value) { + $query = "INSERT INTO config " + . "SET config_parameter = '" . DB::escape($param) . "'," + . "config_value = '" . DB::escape($value) . "'" + . "ON DUPLICATE KEY UPDATE config_value = '" . DB::escape($value) . "' "; + + if (DB::doQuery($query, __FUNCTION__) === FALSE) { + return FALSE; + } + + $message['action'] = _('Configuración'); + $message['text'][] = _('Modificar configuración'); + $message['text'][] = _('Parámetro') . ': ' . $param; + $message['text'][] = _('Valor') . ': ' . $value; + + SP_Common::wrLogInfo($message); + SP_Common::sendEmail($message); + + return TRUE; + } + /** * @brief Cargar la configuración desde la BBDD * @param bool $force reescribir la variable global $CFG? @@ -353,22 +380,6 @@ class SP_Config{ return TRUE; } - /** - * @brief Obtiene un valor desde la configuración en la BBDD - * @param $param string con el parámetro de configuración - * @return array or false - */ - public static function getConfigParameter($param){ - $query = "SELECT config_value FROM config WHERE config_parameter = '$param' "; - $queryRes = DB::getResults($query, __FUNCTION__); - - if ( $queryRes === FALSE || ! is_array($queryRes) ){ - return FALSE; - } - - return $queryRes; - } - /** * @brief Establece los valores de configuración por defecto en config.php * @return none diff --git a/inc/html.class.php b/inc/html.class.php index 064f15b7..1aa09f84 100644 --- a/inc/html.class.php +++ b/inc/html.class.php @@ -303,6 +303,8 @@ class SP_Html { array("href" => "css/jquery.powertip.css", "media" => "screen"), array("href" => "css/jquery.powertip-yellow.min.css", "media" => "screen"), array("href" => "css/chosen.css", "media" => "screen"), + array("href" => "css/alertify.core.css", "media" => "screen"), + array("href" => "css/alertify.default.css", "media" => "screen"), array("href" => "js/fancybox/jquery.fancybox.css", "media" => "screen"), array("href" => "css/styles.css", "media" => "")); @@ -326,6 +328,7 @@ class SP_Html { array("src" => "js/fancybox/jquery.fancybox.pack.js", "params" => ""), array("src" => "js/jquery.powertip.min.js", "params" => ""), array("src" => "js/chosen.jquery.min.js", "params" => ""), + array("src" => "js/alertify.min.js", "params" => ""), array("src" => "js/functions.php", "params" => "&l=" . SP_Init::$LANG . "&r=" . base64_encode(SP_Init::$WEBROOT))); foreach ($jsProp as $js) { diff --git a/inc/init.php b/inc/init.php index 1b38347e..b3ef7fe2 100644 --- a/inc/init.php +++ b/inc/init.php @@ -118,6 +118,8 @@ class SP_Init { // Comprobar si el modo mantenimiento está activado self::checkMaintenanceMode(); + // Comprobar la versión y actualizarla + self::checkVersion(); // Inicializar la sesión self::initSession(); @@ -403,6 +405,36 @@ class SP_Init { textdomain("messages"); bind_textdomain_codeset("messages", 'UTF-8'); } + + /** + * @brief Comrpueba y actualiza la versión de la aplicación + * @returns none + */ + private static function checkVersion(){ + $update = FALSE; + $configVersion = SP_Config::getValue('version'); + $databaseVersion = SP_Config::getConfigValue('version'); + $appVersion = SP_Util::getVersionString(); + + if ( $configVersion != $appVersion ){ + SP_Config::setValue('version', $appVersion); + $update = TRUE; + } + + if ( $databaseVersion != $appVersion ){ + SP_Config::setConfigValue('version', $appVersion); + $update = TRUE; + } + + if ( $update === TRUE ){ + $message['action'] = _('Actualización'); + $message['text'][] = _('Actualización de versión realizada.'); + $message['text'][] = _('Versión') . ': ' . $appVersion; + + SP_Common::wrLogInfo($message); + SP_Common::sendEmail($message); + } + } } // Empezar a calcular el tiempo y memoria utilizados diff --git a/inc/locales/en_US/LC_MESSAGES/messages.mo b/inc/locales/en_US/LC_MESSAGES/messages.mo index 7a143eb457de977a694c95b3e8974cc9c6d3ddfd..fbab3ce16ca4f3a46d078343d14952d9ebdbaec9 100644 GIT binary patch delta 11568 zcmY+~3w)2||Htv$Y-UFrW^>%vVZ&^;Ic;oCb8L*|6giGf=4?(8zQ~~%%1Sv)IfVMj zD9Rz^P$|mk7da(LDhef}-|PLouKgeV@5k@6=jXca>%OnUeckt_$M5B}UUS~^a$hX% z{i?$e;^jD%a7BpY98z9YwT_bz>o~!fh`!ju+8#?&&cxa{2%F&oRQqEXh37EU>r7!}?ePo1zc4#`5&K@M2x?&GQA>Xt)xJW4 zS?UDT3{$ZbrlGFyg6gL)>iS{m){Lf;Xhe%qH(ZDH@i^)k7Ed%6*2eObldv2Ga%(4`9_z0grq*Lwum|eI7Sz&RzzX;?szYB!r5RO0 zJ=3}vg2`9|pTNpE(wcAGgj#{4SQ<~FR^obn)?d%|E*0wVA!@|_4a`VOqt4etT^NtL zFb&mlCaQfFYG%1u2Hoh51*n<7j%vTjmOrw7p@v$*OBjgvQ8V>vXgaEds*gbpAPLK2 zI#$8{wmi+23s3{zhPrMSYQTqW`IIeRK~30wi$onhwkN_GnHy9`%`67>I@QBCOhG;C zT+~2jpgt8#Py^bDF?bexqE`~DhrLmcW|l3lMegf%J}1%AoI)+#HPkcy3pGN&WK)hn zwX0=qjB1~5&-X+2l`|5x``4iM&U)*9)C9i8$>`r$E5q}jO`@eLKz(4=pbPh)Mtl)9 zvq$!P#U|$MNJj4E3`fm)9je_4)Qa4~2nU&{zoQ&mg73#VjsFnB<)sfTG+&>yCQEY}4us6CZl1#8C7NZ96 zA5{Hu)QxXqP4sGJ&c|RZ<#g1HCZal8hHC#Yy6`OOKKD@_mu+qan26dF>CIVx-C!&g zb#Mu4DG%5NzhGs`Q{$y-!tDNkWlypOs;g*0P=wJqv=A9Ud~jKtMg1^3zdi>P-0pjM=6EAt4FQ6H*I zRQ-522_H8n9}{pNvRckHYtjM6b;a)C|0yFiR7KUXAWtU~`z2-DRC@mLdEqP~E+s2fj0ZPF#EO?DU) z@fxOLcn9+qbVGe7@=zV*qb9ZyHL(4t`&_|B7}}BbSA+H>zL#x`3G8HY*tCP8~6~<5= zg1iV$0qVlD=)$|GfrNE7Gmb+|pdAKdXVfO^hg$M%s~hzwmZ9FV&7E2Qh9o~xk%F#F zvs?RMDavC|9nC;3?NZc=6=Db;L$$kL%fFx=HM0I!q^$dTq`aEUYxiFOaM683YupW*=J^Qs7h8t1$ z-HT=LIBLLGF;MS+v7V+uFzUicWMobh>X{{?9#J!FiycwBzW_CW6{wEh#d7!ws-yE* z8gHRi(5siJ4@dP=2mST_Cz6C?Dr#xEp)Tx=>Ubn-22)TSFF;-ZX9;R1*HD|V_|s

U>Uxznn`Pn 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 delta 11358 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 eFs^?^@50_$$<+#1 "category", - @@ -65,16 +64,12 @@ $categoriesSelProp = array("name" => "category", - -