Comment: | Déplacement des méthodes de recherche dans une classe à part, et les rendre un peu plus génériques pour permettre d'utiliser avec la recherche en compta, début de la gestion de sauvegarde de recherche |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | dev |
Files: | files | file ages | folders |
SHA1: |
d3efd06ccbed5f5fa16c766d8b43298f |
User & Date: | bohwaz on 2018-09-20 18:37:36 |
Other Links: | branch diff | manifest | tags |
2018-09-27
| ||
11:33 | Liste des recherches check-in: 632ec9b28f user: bohwaz tags: dev | |
2018-09-20
| ||
18:37 | Déplacement des méthodes de recherche dans une classe à part, et les rendre un peu plus génériques pour permettre d'utiliser avec la recherche en compta, début de la gestion de sauvegarde de recherche check-in: d3efd06ccb user: bohwaz tags: dev | |
2018-09-19
| ||
13:54 | Lien sur le premier champ de la liste check-in: 4d805fc2bf user: bohwaz tags: dev | |
Modified src/include/lib/Garradin/Membres.php from [9cbfc1c785] to [e8bc40a4a8].
︙ | ︙ | |||
290 291 292 293 294 295 296 | } public function getIDWithNumero($numero) { return DB::getInstance()->firstColumn('SELECT id FROM membres WHERE numero = ?;', (int) $numero); } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 290 291 292 293 294 295 296 297 298 299 300 301 302 303 | } public function getIDWithNumero($numero) { return DB::getInstance()->firstColumn('SELECT id FROM membres WHERE numero = ?;', (int) $numero); } public function getSearchHeaderFields(array $result) { if (!count($result)) { return false; } |
︙ | ︙ | |||
445 446 447 448 449 450 451 | $fields[$field] = $config; } } return $fields; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 311 312 313 314 315 316 317 318 319 320 321 322 323 324 | $fields[$field] = $config; } } return $fields; } public function listByCategory($cat, $fields, $page = 1, $order = null, $desc = false) { $begin = ($page - 1) * self::ITEMS_PER_PAGE; $db = DB::getInstance(); $config = Config::getInstance(); |
︙ | ︙ |
Added src/include/lib/Garradin/Recherche.php version [5a3bd60873].
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 | <?php namespace Garradin; class Recherche { const TYPE_JSON = 'json'; const TYPE_SQL = 'sql'; const TARGETS = [ 'membres', 'compta_journal', ]; protected function _checkFields($intitule, $id_membre, $type, $cible, &$query) { $db = DB::getInstance(); if (trim($intitule) === '') { throw new UserException('Le champ intitulé ne peut être vide.'); } if (null !== $id_membre) { $id_membre = (int)$id_membre; } if (null !== $id_membre && !$db->test('membres', 'id = ?', $id_membre)) { throw new \InvalidArgumentException('Numéro d\'utilisateur inconnu.'); } if ($type !== self::TYPE_SQL && $type !== self::TYPE_JSON) { throw new \InvalidArgumentException('Type de recherche inconnu.'); } if (!in_array($cible, self::TARGETS, true)) { throw new \InvalidArgumentException('Cible de recherche invalide.'); } if ($type == self::TYPE_SQL && !is_string($query)) { throw new \InvalidArgumentException('Recherche invalide pour le type SQL'); } if ($type == self::TYPE_JSON) { if (!is_array($query)) { throw new \InvalidArgumentException('Recherche invalide pour le type JSON'); } $query = json_encode($query); if (!json_decode($query)) { throw new \InvalidArgumentException('JSON invalide pour le type JSON'); } } return true; } public function edit($id, $intitule, $id_membre, $type, $cible, $contenu) { $this->_checkFields($intitule, $id_membre, $type, $cible, $contenu); return DB::getInstance()->update('recherches', compact('intitule', 'id_membre', 'type', 'cible', 'contenu'), 'id = ' . (int)$id); } public function add($intitule, $id_membre, $type, $cible, $contenu) { $this->_checkFields($intitule, $id_membre, $type, $cible, $contenu); $db = DB::getInstance(); $db->insert('recherches', compact('intitule', 'id_membre', 'type', 'cible', 'contenu')); return $db->lastInsertRowId(); } public function remove($id) { return DB::getInstance()->delete('recherches', 'id = ?', (int) $id); } public function get($id) { return DB::getInstance()->first('SELECT * FROM recherches WHERE id = ?;', (int) $id); } public function getList($id_membre) { return DB::getInstance()->get('SELECT id, type, intitule, type, id_membre FROM recherches WHERE id_membre IS NULL OR id_membre = ? ORDER BY intitule;', (int)$id_membre); } /** * Lancer une recherche enregistrée */ public function search($id) { $search = $this->get($id); if (!$search) { return false; } if ($search->type == self::TYPE_JSON) { $search->contenu = $this->buildQuery($search->target, json_decode($search->contenu)); } return $this->searchSQL($search->target, $query); } /** * Renvoie la liste des colonnes d'une cible */ public function getColumns($target) { $columns = []; if ($target == 'membres') { $champs = Config::getInstance()->get('champs_membres'); foreach ($champs->getList() as $champ => $config) { $column = (object) [ 'realType' => $config->type, 'textMatch'=> $champs->isText($champ), 'label' => $config->title, 'type' => 'text', 'null' => true, ]; if ($config->type == 'checkbox') { $column->type = 'boolean'; } elseif ($config->type == 'select') { $column->type = 'enum'; $column->values = $config->options; } elseif ($config->type == 'multiple') { $column->type = 'bitwise'; $column->values = $config->options; } elseif ($config->type == 'date' || $config->type == 'datetime') { $column->type = $config->type; } elseif ($config->type == 'number' || $champ == 'numero') { $column->type = 'integer'; } $columns[$champ] = $column; } } return $columns; } /** * Construire une recherche SQL à partir d'un objet généré par QueryBuilder * @param string $target Cible de la requête : membres, compta_journal, etc. * @param array $groups Groupes de critères * @param string $order Ordre de tri * @param boolean $desc Inverser le tri * @param integer $limit Limite * @return string Chaîne SQL */ public function buildQuery($target, array $groups, $order, $desc = false, $limit = 100) { if (!in_array($target, self::TARGETS, true)) { throw new \InvalidArgumentException('Cible inconnue : ' . $target); } if ($target == 'membres') { $config = Config::getInstance(); $champs = $config->get('champs_membres'); } $db = DB::getInstance(); $target_columns = $this->getColumns($target); $query_columns = []; $query_groups = []; foreach ($groups as $group) { if (!isset($group['conditions'], $group['operator']) || !is_array($group['conditions']) || ($group['operator'] != 'AND' && $group['operator'] != 'OR')) { // Ignorer les groupes de conditions invalides continue; } $query_group_conditions = []; foreach ($group['conditions'] as $condition) { if (!isset($condition['column'], $condition['operator']) || (isset($condition['values']) && !is_array($condition['values']))) { // Ignorer les conditions invalides continue; } if (!array_key_exists($condition['column'], $target_columns)) { // Ignorer une condition qui se rapporte à une colonne // qui n'existe pas, cas possible si on reprend une recherche // après avoir modifié les fiches de membres continue; } $query_columns[] = $condition['column']; $column = $target_columns[$condition['column']]; if ($column->textMatch == 'text') { $query = sprintf('transliterate_to_ascii(%s) COLLATE NOCASE %s', $db->quoteIdentifier($condition['column']), $condition['operator']); } else { $query = sprintf('%s %s', $db->quoteIdentifier($condition['column']), $condition['operator']); } $values = isset($condition['values']) ? $condition['values'] : []; $values = array_map(['Garradin\Utils', 'transliterateToAscii'], $values); if ($column->type == 'tel') { // Normaliser le numéro de téléphone $values = array_map(['Garradin\Utils', 'normalizePhoneNumber'], $values); } // L'opérateur binaire est un peu spécial if ($condition['operator'] == '&') { $new_query = []; foreach ($values as $value) { $new_query[] = sprintf('%s (1 << %d)', $query, (int) $value); } $query = '(' . implode(' AND ', $new_query) . ')'; } // Remplacement de liste elseif (strpos($query, '??') !== false) { $values = array_map([$db, 'quote'], $values); $query = str_replace('??', implode(', ', $values), $query); } // Remplacement de recherche LIKE elseif (preg_match('/%\?%|%\?|\?%/', $query, $match)) { $value = str_replace(['%_'], ['\\%', '\\_'], reset($values)); $value = str_replace('?', $value, $match[0]); $query = str_replace($match[0], sprintf('%s ESCAPE \'\\\'', $db->quote($value)), $query); } // Remplacement de paramètre elseif (strpos($query, '?') !== false) { $expected = substr_count($query, '?'); $found = count($values); if ($expected != $found) { throw new \RuntimeException(sprintf('Operator %s expects at least %d parameters, only %d supplied', $condition['operator'], $expected, $found)); } for ($i = 0; $i < $expected; $i++) { $pos = strpos($query, '?'); $query = substr_replace($query, $db->quote(array_shift($values)), $pos, 1); } } $query_group_conditions[] = $query; } if ($query_group_conditions) { $query_groups[] = implode(' ' . $group['operator'] . ' ', $query_group_conditions); } } $query_columns = array_unique($query_columns); // Ajout du champ identité si pas présent if ($target == 'membres' && !in_array($config->get('champ_identite'), $query_columns)) { array_unshift($query_columns, $config->get('champ_identite')); } if ($target_columns[$order]->textMatch) { $order = sprintf('transliterate_to_ascii(%s) COLLATE NOCASE', $db->quoteIdentifier($order)); } else { $order = $db->quoteIdentifier($order); } $query_columns = array_map([$db, 'quoteIdentifier'], $query_columns); $sql_query = sprintf('SELECT id, %s FROM %s WHERE %s ORDER BY %s %s LIMIT %d;', implode(', ', $query_columns), $target, '(' . implode(') AND (', $query_groups) . ')', $order, $desc ? 'DESC' : 'ASC', (int) $limit); return $sql_query; } /** * Lancer une recherche SQL */ public function searchSQL($target, $query) { if (!in_array($target, self::TARGETS, true)) { throw new \InvalidArgumentException('Cible inconnue : ' . $target); } $db = DB::getInstance(); if (!preg_match('/LIMIT\s+/i', $query)) { $query = preg_replace('/;?\s*$/', '', $query); $query .= ' LIMIT 100'; } if (preg_match('/;\s*(.+?)$/', $query)) { throw new UserException('Une seule requête peut être envoyée en même temps.'); } $st = $db->prepare($query); if (!$st->readOnly()) { throw new UserException('Seules les requêtes en lecture sont autorisées.'); } $res = $st->execute(); $out = []; while ($row = $res->fetchArray(SQLITE3_ASSOC)) { $out[] = (object) $row; } return $out; } public function schema($target) { $db = DB::getInstance(); if ($target == 'membres') { $tables = [ 'membres' => $db->firstColumn('SELECT sql FROM sqlite_master WHERE type = \'table\' AND name = \'membres\';'), 'categories'=> $db->firstColumn('SELECT sql FROM sqlite_master WHERE type = \'table\' AND name = \'membres_categories\';'), ]; } return $tables; } } |
Modified src/templates/admin/membres/import.tpl from [f967ae9cb7] to [f774ddb844].
1 2 | {include file="admin/_head.tpl" title="Import & export des membres" current="membres" js=1} | > > | | 1 2 3 4 5 6 7 8 9 10 11 12 | {include file="admin/_head.tpl" title="Import & export des membres" current="membres" js=1} {include file="admin/membres/_nav.tpl" current="import"} <ul class="actions sub"> <li class="current"><a href="{$admin_url}membres/import.php">Importer</a></li> <li><a href="{$admin_url}membres/import.php?export=csv">Exporter en CSV</a></li> <li><a href="{$admin_url}membres/import.php?export=ods">Exporter en classeur Office</a></li> </ul> {form_errors} |
︙ | ︙ |
Modified src/templates/admin/membres/index.tpl from [bdf20a85ce] to [2bdeff033c].
1 2 | {include file="admin/_head.tpl" title="Liste des membres" current="membres" js=1} | | < < < < < < < | 1 2 3 4 5 6 7 8 9 10 | {include file="admin/_head.tpl" title="Liste des membres" current="membres" js=1} {include file="admin/membres/_nav.tpl" current="index"} {if $sent} <p class="confirm">Votre message a été envoyé.</p> {/if} {if !empty($membres_cats)} <form method="get" action="{$self_url}" class="shortFormRight"> |
︙ | ︙ |
Modified src/templates/admin/membres/recherche.tpl from [babb84d9bc] to [469ac19c52].
|
| | | < < < < < < > < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | {include file="admin/_head.tpl" title="Recherche de membre" current="membres" js=1 custom_js=['sql_query_builder.min.js']} {include file="admin/membres/_nav.tpl" current="recherche"} <form method="post" action="{$admin_url}membres/recherche.php" id="queryBuilderForm"> <fieldset> <legend>Rechercher un membre</legend> <div class="queryBuilder" id="queryBuilder"></div> <p class="actions"> <label>Trier par <select name="order"> {foreach from=$colonnes key="colonne" item="config"} <option value="{$colonne}"{form_field name="order" selected=$colonne}>{$config.label}</option> {/foreach} </select> </label> <label><input type="checkbox" name="desc" value="1" {form_field name="desc" checked=1 default=$desc} /> Tri inversé</label> <label>Limiter à <input type="number" value="{$limit}" name="limit" size="5" /> résultats</label> </p> <p class="submit"> <input type="submit" value="Chercher →" id="send" /> <input type="hidden" name="q" id="jsonQuery" /> <input type="submit" value="Enregistrer cette recherche" class="minor" /> </p> </fieldset> </form> <script type="text/javascript"> var colonnes = {$colonnes|escape:'json'}; {literal} var traductions = { |
︙ | ︙ | |||
147 148 149 150 151 152 153 | </td> </tr> {/foreach} </tbody> </table> {if $session->canAccess('membres', Garradin\Membres::DROIT_ADMIN)} | < < < | 141 142 143 144 145 146 147 148 149 150 151 152 153 154 | </td> </tr> {/foreach} </tbody> </table> {if $session->canAccess('membres', Garradin\Membres::DROIT_ADMIN)} <p class="actions"> <em>Pour les membres cochés :</em> <input type="submit" name="move" value="Changer de catégorie" /> <input type="submit" name="delete" value="Supprimer" /> {csrf_field key="membres_action"} </p> {/if} |
︙ | ︙ |
Modified src/templates/admin/membres/recherche_sql.tpl from [b00b9336aa] to [b838ae91f5].
1 2 3 4 5 6 7 8 9 | {include file="admin/_head.tpl" title="Recherche par requête SQL" current="membres" js=1} <form method="get" action="{$admin_url}membres/recherche_sql.php"> <fieldset> <legend>Schéma des tables SQL</legend> <pre class="sql_schema">{$schema.membres}</pre> <dl> <dt><label for="f_query">Requête SQL</label></dt> <dd class="help">Si aucune limite n'est précisée, une limite de 100 résultats sera appliquée.</dd> | > > | | > | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | {include file="admin/_head.tpl" title="Recherche par requête SQL" current="membres" js=1} {include file="admin/membres/_nav.tpl" current="sql"} <form method="get" action="{$admin_url}membres/recherche_sql.php"> <fieldset> <legend>Schéma des tables SQL</legend> <pre class="sql_schema">{$schema.membres}</pre> <dl> <dt><label for="f_query">Requête SQL</label></dt> <dd class="help">Si aucune limite n'est précisée, une limite de 100 résultats sera appliquée.</dd> <dd><textarea name="query" id="f_query" cols="70" rows="7" required="required">{$query}</textarea></dd> </dl> <p class="submit"> <input type="submit" name="run" value="Exécuter →" /> {if $query}<input type="submit" name="save" value="Enregistrer la requête" class="minor" />{/if} </p> </fieldset> </form> {if !empty($error)} <p class="error"> <strong>Erreur dans la requête SQL :</strong><br /> {$error} </p> {/if} <form method="post" action="{$admin_url}membres/action.php" class="memberList"> {if !empty($result)} <p class="alert">{$result|count} résultats retournés.</p> <table class="list search"> <thead> {if array_key_exists('id', $result[0])} <td class="check"><input type="checkbox" value="Tout cocher / décocher" onclick="g.checkUncheck();" /></td> {/if} {foreach from=$result[0] key="col" item="ignore"} <td>{$col}</td> |
︙ | ︙ | |||
56 57 58 59 60 61 62 | </td> {/if} </tr> {/foreach} </tbody> </table> | < < < | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | </td> {/if} </tr> {/foreach} </tbody> </table> <p class="actions"> <em>Pour les membres cochés :</em> <input type="submit" name="move" value="Changer de catégorie" /> <input type="submit" name="delete" value="Supprimer" /> {csrf_field key="membres_action"} </p> |
︙ | ︙ |
Added src/templates/admin/membres/recherches.tpl version [dd2a8a7e3a].
> > > > > > > > > | 1 2 3 4 5 6 7 8 9 | {include file="admin/_head.tpl" title="Recherches enregistrées" current="membres"} {include file="admin/membres/_nav.tpl" current="recherches"} {if count($liste) == 0} <p class="alert">Aucune recherche enregistrée. <a href="{$admin_url}membres/recherche.php">Faire une nouvelle recherche</a></p> {/if} {include file="admin/_foot.tpl"} |
Modified src/www/admin/membres/recherche.php from [218ac5f508] to [0e8c0cdaf4].
1 2 3 4 5 6 7 8 9 10 11 | <?php namespace Garradin; require_once __DIR__ . '/_inc.php'; $champs = $config->get('champs_membres'); $text_query = trim(qg('qt')); $query = null; $limit = f('limit') ?: 100; $order = f('order'); $desc = (bool) f('desc'); | > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 | <?php namespace Garradin; require_once __DIR__ . '/_inc.php'; $recherche = new Recherche; $champs = $config->get('champs_membres'); $text_query = trim(qg('qt')); $query = null; $limit = f('limit') ?: 100; $order = f('order'); $desc = (bool) f('desc'); |
︙ | ︙ | |||
44 45 46 47 48 49 50 | elseif (f('q') !== null) { $query = json_decode(f('q'), true); } if ($query) { | | | | 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | elseif (f('q') !== null) { $query = json_decode(f('q'), true); } if ($query) { $sql_query = $recherche->buildQuery('membres', $query, $order, $desc, $limit); $result = $recherche->searchSQL('membres', $sql_query); if (count($result) == 1 && $text_query !== '') { Utils::redirect(ADMIN_URL . 'membres/fiche.php?id=' . (int)$result[0]->id); } $tpl->assign('result_header', $membres->getSearchHeaderFields($result)); |
︙ | ︙ | |||
75 76 77 78 79 80 81 | $tpl->assign('query', $query); $tpl->assign('sql_query', $sql_query); $tpl->assign('result', $result); $tpl->assign('order', $order); $tpl->assign('desc', $desc); $tpl->assign('limit', $limit); | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | 77 78 79 80 81 82 83 84 85 86 | $tpl->assign('query', $query); $tpl->assign('sql_query', $sql_query); $tpl->assign('result', $result); $tpl->assign('order', $order); $tpl->assign('desc', $desc); $tpl->assign('limit', $limit); $tpl->assign('colonnes', $recherche->getColumns('membres')); $tpl->display('admin/membres/recherche.tpl'); |
Modified src/www/admin/membres/recherche_sql.php from [d0f26422b0] to [64a09b2404].
1 2 3 4 5 6 7 8 9 | <?php namespace Garradin; require_once __DIR__ . '/_inc.php'; $session->requireAccess('membres', Membres::DROIT_ADMIN); $query = trim(qg('query')); | > > > > | | | | | | < | | | < > | > | | | > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <?php namespace Garradin; require_once __DIR__ . '/_inc.php'; $session->requireAccess('membres', Membres::DROIT_ADMIN); $recherche = new Recherche; $query = trim(qg('query')); $error = null; $result = null; $tpl->assign('schema', $recherche->schema('membres')); $tpl->assign('query', $query); if ($query != '') { try { $result = $recherche->searchSQL('membres', $query); } catch (\Exception $e) { $error = $e->getMessage(); } if (!$error && qg('save')) { $id = $recherche->add('Recherche SQL du ' . date('d/m/Y H:i:s'), $user->id, $recherche::TYPE_SQL, 'membres', $query); Utils::redirect('/admin/recherches.php?id=' . $id); } } $tpl->assign('result', $result); $tpl->display('admin/membres/recherche_sql.tpl'); |
Added src/www/admin/membres/recherches.php version [5d489fac1a].
> > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 | <?php namespace Garradin; require_once __DIR__ . '/_inc.php'; $recherche = new Recherche; $tpl->assign('liste', $recherche->getList($user->id)); $tpl->display('admin/membres/recherches.tpl'); |
Modified src/www/admin/static/admin.css from [78c40bcd12] to [c451b4a60c].
︙ | ︙ | |||
619 620 621 622 623 624 625 | } table.list .disabled { background: #eee; color: #999; } | | > > > > > > > > > > > > > | 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 | } table.list .disabled { background: #eee; color: #999; } #queryBuilder .column select, #queryBuilderForm .actions select { max-width: 15em; } #queryBuilder table td { vertical-align: top; padding: .1em .2em; } #queryBuilder input[type=button], #queryBuilder .values input { margin: .1em; } #queryBuilderForm .actions label { margin: 0 .5em; } #queryBuilderForm input[type=number] { width: 4em; } .userOrder .cur { background: rgb(217, 134, 40); background: rgba(var(--gSecondColor), 1.0); color: #fff; color: rgb(var(--gBgColor)); |
︙ | ︙ |