Check-in [c4755c01bd]
Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Using diff now for /admin pages and /rc |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
c4755c01bdc43df63a36ef5c716e9311 |
User & Date: | mario 2014-08-08 17:37:53 |
Context
2014-08-08
| ||
17:38 | Make `$version` replacement work on complete text input (RegExp/g) check-in: 6afb9901a5 user: mario tags: trunk | |
17:37 | Using diff now for /admin pages and /rc check-in: c4755c01bd user: mario tags: trunk | |
2014-08-06
| ||
11:01 | Reordered gallery, added Fossies.org check-in: 92ebd481e3 user: mario tags: trunk | |
Changes
Changes to freshcode.css.
1 2 3 4 5 | /** * api: css * type: stylesheet * title: freshcode.club layout+style * description: Simulates the late freecode.com layout and looks; well mostly. | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 | /** * api: css * type: stylesheet * title: freshcode.club layout+style * description: Simulates the late freecode.com layout and looks; well mostly. * version: 0.6.4.1 * * Centered two-pane layout. The #main section is usually 33% of the screen width, * while the #sidebar floats at the right. They're repositioned only using padding: * to the outer html,body{}. * */ |
︙ | ︙ | |||
96 97 98 99 100 101 102 | /** * Main action link box, hovering halfway over header box. * */ #tools { margin: 0 150pt; | | | > | 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | /** * Main action link box, hovering halfway over header box. * */ #tools { margin: 0 150pt; padding: 3pt 5pt 2pt 5pt; border: 1.75pt solid #bbb; border-top: 1pt solid #ccc; border-radius: 5pt; background: #e5e7e9; background: linear-gradient(to bottom, #ffffff, #fdfefe, #f5f7f9, #eaecee, #e5e7e9, #e1e3e5, #d0d1d2); position: relative; top: -14pt; font-size: 95%; } .absolute { position: absolute; } #tools a { color: #777; margin: 0 1pt; |
︙ | ︙ | |||
568 569 570 571 572 573 574 | font-weight: 900; display: block; } #trove_tags span > span.option:hover, #trove_tags span.optgroup > b:hover { background: #ccf; } #trove_tags .option.selected, #tag_cloud a.selected { | | | 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 | font-weight: 900; display: block; } #trove_tags span > span.option:hover, #trove_tags span.optgroup > b:hover { background: #ccf; } #trove_tags .option.selected, #tag_cloud a.selected { background: #fba !important; } #trove_tags .optgroup[data-tag='topic'] { background: #f3f4f7; } #trove_tags .optgroup[data-tag='topic'] * { background: #f7f7f9; } #trove_tags .optgroup[data-tag='programming-language'] { background: #d7dcf0; } #trove_tags .optgroup[data-tag='programming-language'] * { background: #ecf0fa; } #trove_tags .optgroup[data-tag='environment'] { background: #f3f0e0; } |
︙ | ︙ | |||
626 627 628 629 630 631 632 633 634 635 636 637 638 639 | border-bottom: 1px dashed green; background: #efe; } .rc del { color: #521; background: #fee; } .rc .funcs { float: right; } .rc .funcs a { font-size: 60%; color: #99b; background: #e3e3e3; | > > > > > > > > > | 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 | border-bottom: 1px dashed green; background: #efe; } .rc del { color: #521; background: #fee; } .rc.admin ins { border: none; background: #f1fff3; } .rc.admin del { color: #210; background: #fff5f3; text-decoration: none; } .rc .funcs { float: right; } .rc .funcs a { font-size: 60%; color: #99b; background: #e3e3e3; |
︙ | ︙ |
Added lib/diff.php.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | <?php /* Paul's Simple Diff Algorithm v 0.1 (C) Paul Butler 2007 <http://www.paulbutler.org/> May be used and distributed under the zlib/libpng license. This code is intended for learning purposes; it was written with short code taking priority over performance. It could be used in a practical application, but there are a few ways it could be optimized. Given two arrays, the function diff will return an array of the changes. I won't describe the format of the array, but it will be obvious if you use print_r() on the result of a diff on some test data. htmlDiff is a wrapper for the diff command, it takes two strings and returns the differences in HTML. The tags used are <ins> and <del>, which can easily be styled with CSS. */ class pdiff { // static function diff($old, $new){ $matrix = array(); $maxlen = 0; foreach($old as $oindex => $ovalue){ $nkeys = array_keys($new, $ovalue); foreach($nkeys as $nindex){ $matrix[$oindex][$nindex] = isset($matrix[$oindex - 1][$nindex - 1]) ? $matrix[$oindex - 1][$nindex - 1] + 1 : 1; if($matrix[$oindex][$nindex] > $maxlen){ $maxlen = $matrix[$oindex][$nindex]; $omax = $oindex + 1 - $maxlen; $nmax = $nindex + 1 - $maxlen; } } } if($maxlen == 0) return array(array('d'=>$old, 'i'=>$new)); return array_merge( pdiff::diff(array_slice($old, 0, $omax), array_slice($new, 0, $nmax)), array_slice($new, $nmax, $maxlen), pdiff::diff(array_slice($old, $omax + $maxlen), array_slice($new, $nmax + $maxlen))); } // markup <ins> and <del> between old and new text blob static function htmlDiff($old, $new){ $ret = ''; $diff = pdiff::diff(preg_split("/[\s]+/", $old), preg_split("/[\s]+/", $new)); foreach($diff as $k){ if(is_array($k)) $ret .= (!empty($k['d']) ? "<del>" . input::html(implode(' ',$k['d'])) . "</del> " : ''). (!empty($k['i']) ? "<ins>" . input::html(implode(' ',$k['i'])) . "</ins> " : ''); else $ret .= $k . ' '; } return $ret; } // Just compare word-wise without between three revisions, without honoring order static function triDiff($prev, $curr, $next){ $ret = ''; $prev = preg_split("/[\s]+/", $prev); $curr = preg_split("/[\s]+/", $curr); $next = preg_split("/[\s]+/", $next); foreach($curr as $word){ if (!in_array($word, $prev)) { $ret .= "<ins>$word</ins> "; } elseif (!in_array($word, $next)) { $ret .= "<del>$word</del> "; } else { $ret .= "$word "; } } return $ret; } } ?> |
Added page_admin.php.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | <?php /** * api: freshcode * type: page * title: admin interface * description: Showcase user flags and allow to delete or hide project entries/revisions. * version: 0.1 * depends: db * * User flags are collected in a separate `flags` table. Yet each project * entry contains a `flags` counter column as well (this is used by front-end * code to automatically hide too frequently flagged submissions).. * * CREATE TABLE flags * (name TEXT, reason TEXT, note TEXT, submitter_openid TEXT, submitter_ip TEXT); * * The admin page lists from the flags table. Then allows to "delete" certain * revisions, or just mark them as hidden. * */ // Moderator authorization already handled by dispatcher (index.php) include("template/header.php"); ?> <section id=main> <?php $name = $_REQUEST->proj_name["name"]; // Just list flags+projects if (empty($name)) { print "<h3>Flagged entries</h3> <dl>"; // query flags table, but associate data from last release $flags = db("SELECT * FROM flags LEFT JOIN release_versions ON flags.name=release_versions.name"); // just output admin/PROJID links while ($row = $flags->fetch()) { $row = array_map("input::html", $row); print <<<HTML <dt><a href="admin/$row[name]">$row[name]</a> (<em>$row[flag]</em> flags on #$row[t_published])</dt> <dd><b>$row[reason]</b> $row[note] </dd> HTML; } } // Show entry + respond to actions else { /** * Apply actions * * โ Actions in `action[field][]=name and action[value][]=value` * โ Revisions are lists of `select[t_published][] = t_changed` * */ if ($_POST->has("action")) { // Merge action keys and values $action = $_POST->raw["action"]; $action = array_combine( array_intersect_key($action["field"], $action["value"]), array_intersect_key($action["value"], $action["field"]) ); var_dump($action); // Run trough actions foreach ($action as $field=>$value) if (strlen($field)) { // Update DB for each revision in select[][] foreach ($_POST->raw["select"] as $t_published => $t_changed) { db("UPDATE release SET :? = ? WHERE name=? AND t_published=? AND t_changed IN (??)", array($field), $value, $name, $t_published, $t_changed ); } } // Manually empty `flags` table if ($action["flag"] === 0) { db("DELETE FROM flags WHERE name=?", $name); } } /** * Get all revisions and flags for project name * * */ $entries = db("SELECT * FROM release WHERE name=? ORDER BY t_published ASC, t_changed ASC", $name)->fetchAll(); $flags = db("SELECT * FROM flags WHERE name=?", $name)->fetchAll(); // Start <form> print "<h3>Edit '$name' revisions</h3> Oldest to newest. <form action='admin/$name' method=POST> "; // Show all flagging notes foreach ($flags as $row) { $row = array_map("input::html", $row); print "<li>Flag: <b>$row[reason]</b><br>Note: <em>$row[note]</em><br>By: <u>$row[submitter_openid]</u></li><br>"; } // Print each revision; foreach ($entries as $rev=>$row) { // current, last, and next row $row = array_map("input::html", $row); $last = isset($entries[$rev-1]) ? array_map("input::html", $entries[$rev-1]) : $row; $next = isset($entries[$rev+1]) ? array_map("input::html", $entries[$rev+1]) : $row; // Version header $date = strftime("%Y-%m-%d %T", $row["t_changed"]); print " <br> <table class='rc admin'> <tr> <th> <input type=checkbox name='select[$row[t_published]][]' value='$row[t_changed]'> rev=$rev </th> <th> pub=$row[t_published] chg=$row[t_changed] <small>($date)</small> </th> </tr>"; // Fields foreach ($row as $f=>$v) { $v = pdiff::tridiff($last[$f], $v, $next[$f]); if (in_array($f, ["t_published", "t_changed"])) { $v .= " <small>(" . strftime("%Y-%m-%d %T", $row[$f]) . ")</small>"; } if (in_array($f, ["hidden","flag","deleted","name","t_changed","version"])) { $f = "<em>$f</em>"; } print "<tr><td>$f</td><td>$v</td>"; } print "</table>"; } /** * Print `action` form fields * * โ Assocciatively as `action[field][] = dbfield` * and `action[value][] = vakue` * โ Applying depends an the field being non-empty * (for unchecked checkboxes they are). * */ print <<<HTML <h4>Actions</h4> <table class=rc> <tr> <td><label> <input type=checkbox name="action[field][0]" value="hidden"> <input type=hidden name="action[value][0]" value="1"> <b>Set hidden</b> </label></td> <td>so the revision will no longer show up on the frontpage. </td> </tr> <tr> <td><label> <input type=checkbox name="action[field][1]" value="deleted"> <input type=hidden name="action[value][1]" value="1"> <b>Mark deleted</b> </label></td> <td> to terminate a project revision line </td> </tr> <tr> <td><label> <input type=checkbox name="action[field][2]" value="flag" checked> <input type=hidden name="action[value][2]" value="0"> <b>Unset flags</b> </label></td> <td> to clear flagging history when finished. </td> </tr> <tr><th>Update field</th><th>with value</th></tr> <tr> <td> <input type=text name="action[field][3]" value=""> </td> <td> <input type=text name="action[value][3]" value="" size=40> </td> </tr> <tr> <td> <input type=text name="action[field][4]" value=""> </td> <td> <input type=text name="action[value][4]" value="" size=40> </td> </tr> </table> <br> <input type=submit value=Apply> <br> <br> HTML; } ?> |
Changes to page_rc.php.
︙ | ︙ | |||
87 88 89 90 91 92 93 | #-- Table print "\n\n<table class=rc><tr><th><a href=/projects/$name>$name</a></th><th>$date <small>ยค$time_diff</small> <span class=funcs><a href=/submit/$name>edit</a> <a href=/admin/$name>admin</a></span></th></tr>\n"; foreach ($fields as $fn ) { // Diff only if there are differences, obviously if ($entry["prev_$fn"] !== $entry["crnt_$fn"]) { | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | #-- Table print "\n\n<table class=rc><tr><th><a href=/projects/$name>$name</a></th><th>$date <small>ยค$time_diff</small> <span class=funcs><a href=/submit/$name>edit</a> <a href=/admin/$name>admin</a></span></th></tr>\n"; foreach ($fields as $fn ) { // Diff only if there are differences, obviously if ($entry["prev_$fn"] !== $entry["crnt_$fn"]) { $diff = pdiff::htmlDiff($entry["prev_$fn"], $entry["crnt_$fn"]); print "<tr><td>$fn</td><td class=trimmed>$diff</td></tr>\n"; } } print "</table>\n"; } // page footer include("template/bottom.php"); ?> |