Commits

Anonymous committed 172bfab

working version of history and diff.

  • Participants
  • Parent commits 7968564

Comments (0)

Files changed (13)

File couchit/api.py

     r1 = page.revision(db, a)
     r2 = page.revision(db, b)
     
-    return diff_blocks(r1.content.splitlines(), r2.content.splitlines(), 3)
+    return diff_blocks(r1.content.splitlines(), r2.content.splitlines(), 3), r1, r2
     
     
     

File couchit/template.py

     return value.strftime("%a %b %d %Y at %H:%M")
 template_env.filters['formatdatetime'] = format_datetime
 
-def tabular(value): 
+def tabular(value, r1, r2): 
     """
     display diff as block
     """
-    rst ='<tr class="tabularh"><th class="linenos">a</th><th class="linenos">b</th><td colspan="2"></td></tr>'
+    rst ="""<tr class="tabularh"><th class="linenos">
+    <a href="%(r1_url)s" title="revision %(r1_nb)s">%(r1_nb)s</a></th>
+    <th class="linenos"><a href="%(r2_url)s" title="revision %(r2_nb)s">%(r2_nb)s</a></th>
+    <td colspan="2"></td></tr>""" % {
+        'r1_url': url_for('revision_page', cname=local.request.site.cname, pagename=r1.title.replace(" ", "_"), nb_revision=r1.nb_revision),
+        'r1_nb':  r1.nb_revision,
+        'r2_url': url_for('revision_page', cname=local.request.site.cname, pagename=r2.title.replace(" ", "_"), nb_revision=r2.nb_revision),
+        'r2_nb': str(r2.nb_revision)
+         
+    }
+    
     for row in value:
         for change in row:
             
                 l = change['base']['offset']
                 for line in change['base']['lines']:
                     rst = rst + "<tr class=\"unmod\"><th class=\"linenos\">%s</th>\
-                    <th class=\"linenos\">%s</th><td></td><td>%s</td>" % (
+                    <th class=\"linenos\">%s</th><td></td><td>%s</td></tr>" % (
                         l,
                         l,
                         line
                 pos = 1
                 for line in change['base']['lines']:       
                     rst = rst + '<tr class="%s"><th class=\"linenos\">%s</th>\
-                    <th class=\"linenos\"></th><th class="diffm">-</th><td class="c wrap %s">%s</td>' % (
+                    <th class=\"linenos\"></th><th class="diffm">-</th><td class="c wrap %s">%s</td></tr>' % (
                         class_,
                         change['base']['offset'],
                         class_start,
                 pos = 1
                 for line in change['changed']['lines']:
                     rst = rst + "<tr class=\"%s\"><th class=\"linenos\"></th><th class=\"linenos\">%s</th>\
-                    <th class=\"diffp\">+</th><td class=\"c wrap %s\">%s</td>" % (
+                    <th class=\"diffp\">+</th><td class=\"c wrap %s\">%s</td></tr" % (
                         class_,
                         change['base']['offset'],
                         class_end,
                     pos = pos + 1
                     if pos == nb_lines:
                         class_end = "last"
-            rst = rst + "<tr><th class=\"linenos\">...<th><td colspan=\"3\"></td></tr>"
-    rst = "<table class=\"difftabular\">%s</table>" % rst
+            rst = rst + "<tr><th class=\"linenos\">...</th><td colspan=\"3\"></td></tr>"
+    rst = "<table id=\"tableDiff\" class=\"difftabular\">%s</table>" % rst
     return rst
 template_env.filters['tabular'] = tabular
 

File couchit/views.py

 from couchit.models import Site, Page
 from couchit.api import *
 from couchit.http import BCResponse
-from couchit.template import render_response, url_for
+from couchit.template import render_response, url_for, render_template, send_json
 from couchit.utils import local, make_hash
 
 
         redirect_url = url_for('show_page', cname=cname, pagename=pagename)
         return redirect(redirect_url)
     
-    return render_response('page/edit.html', page=page, site=request.site)
+    return render_response('page/edit.html', page=page)
   
 @site_required  
 def history_page(request, cname=None, pagename=None):
     
     # get all pages
     pages = all_pages(local.db, request.site.id)
-    return render_response('page/history.html', page=page, pages=pages, site=request.site, revisions=revisions)
+    return render_response('page/history.html', page=page, pages=pages, revisions=revisions)
     
 @site_required
 def revision_page(request, cname=None, pagename=None, nb_revision=None):
     if pagename is None:
         pagename ='Home'
     page = get_page(local.db, request.site.id, pagename)
-    if not Page:
+    if not page:
         return NotFound
         
     if nb_revision is None:
             nb_revision = int(nb_revision)
         except ValueError:
             return NotFound
-    
-    # get all pages
-    pages = all_pages(local.db, request.site.id)
-        
+
     revision = page.revision(local.db, nb_revision)
     if revision is None:
         return render_response('page/revision_notfound.html', page=page, pages=pages, site=request.site)
+        
+    # revert page
+    if request.method == "POST" and "srevert" in request.form:
+        page.content = revision.content
+        page.store(local.db)
+        return redirect(url_for("show_page", cname=request.site.cname, pagename=pagename))
+        
+    # get all pages
+    pages = all_pages(local.db, request.site.id)
+    
 
-    return render_response('page/show.html', page=revision, pages=pages, site=request.site)
+    return render_response('page/show.html', page=revision, pages=pages)
  
 @site_required   
 def diff_page(request, cname=None, pagename=None):
         pagename ='Home'
     page = get_page(local.db, request.site.id, pagename)
     if not Page:
+        if request.is_xhr:
+            return send_json({'ok': False, 'reason': 'not found'})
         return NotFound
     
     revisions = request.values.getlist('r')
+    diff, rev1, rev2 = get_diff(local.db, page, revisions[0], revisions[1])
     
+    if request.is_xhr:
+         return send_json({
+            'ok': True,
+            'diff': render_template('page/diff_inc.html', diff=diff, rev1=rev1, rev2=rev2)
+         })
+     
+    all_revisions = [page] + page.revisions(local.db)
+
     # get all pages
     pages = all_pages(local.db, request.site.id)
-    
-    diff = get_diff(local.db, page, revisions[0], revisions[1])
-    
-    return render_response('page/diff.html', page=page, pages=pages, site=request.site, diff=diff)
+
+    return render_response('page/diff.html', page=page, pages=pages, diff=diff, rev1=rev1, 
+    rev2=rev2, revisions=all_revisions)
     
 @site_required
 def site_claim(request, cname):
 @site_required
 def site_design(request, cname):
     return render_response('site/design.html', site=request.site)
+    
+    
+
         
 def proxy(request):
     """ simple proxy to manage remote connexion via ajax"""

File static/css/layout.css

     min-height: 350px;
 }
 
+#phistory, #pdiff {
+    display: block;
+    background: #fff;
+    padding: 10px;
+    border: 4px solid #d4d4d4;
+    background: #fff url("../images/roundedcorners.svg");
+    -moz-border-radius: 5px;
+    -khtml-border-radius: 5px;
+    -webkit-radius: 5px;
+    border-radius: 5px;
+    min-height: 350px;
+}
+
+#prevert p {
+    font-weight: bold;
+}
+
+#pdiff h4 {
+    border-bottom: 1px solid #ccc;
+}
+
 /* tabs */
 ul.subsection_tabs {
 	list-style:none;
 
 ul.page_infos  { 
     list-style: none;
-    border-top: 1px solid #ccc;;
+    border-top: 1px solid #ccc;
 }
 ul.page_infos li {
     display: inline;
     color: #000;
 }
 
-
 tr.rselected {
     background: #E1F1B9;
 }
     margin-bottom: 10px;
     
     
-}
+}
+
+input#srevert,
+input#scompare {
+    /*font-weight: bold;*/
+    background: #cec6b5;
+    border: 1px solid #7a7261;
+    margin-left: 10px;
+}
+
+
+
+/* diff */
+#fdiff {
+    padding-top: 10px;
+    border-top: 1px solid #ccc;
+    border-bottom: 1px solid #ccc;
+    margin-bottom: 15px;
+}
+
+th.linenos {
+    background: #f4f4f4;
+    color: #666;
+    font-weight: bold;
+    width: 15px;
+}
+td.linenos { 
+    padding: 0 5px; 
+}
+ 
+.linenos .special { 
+    font-weight: bold; color: #000;
+    }
+ 
+td.code {
+
+    padding: 0 8px;
+
+}
+table.difftabular {
+    width: 100%;
+    background: #fff;
+    color: #000;
+}
+
+table.difftabular th {
+    background: #f7f7f0;
+    width: 2em;
+    text-align: center;
+}
+
+table.difftabular th.linenos {
+    border: 0;
+    text-align: center;
+}
+tr.tabularh th.linenos {
+    color: #000;
+    padding-bottom: 5px;
+}
+
+tbody.hidenos td.linenos,
+tbody.hidenos th.linenos {
+    display: none;
+}
+tr.base {
+    background: #ffd8d8;
+}
+tr.base td.c,
+th.diffm {
+    border-right: 1px solid #aa3333;
+}
+
+th.diffp,
+tr.changed td.c {
+    border-right: 1px solid #33aa33;
+}
+
+tr.changed {
+    background: #ddf8cc;
+}
+
+tr.changed td.first {
+    border-top: 1px solid #33aa33;
+}
+tr.changed .last {
+    border-bottom: 1px solid #33aa33;
+}
+
+tr.base td.first {
+    border-top: 1px solid #aa3333;
+}
+tr.base .last {
+    border-bottom: 1px solid #aa3333;
+}

File static/img/icon_create.png

Added
New image

File static/js/application.js

                 title = date.toLocaleString();
             }
             el.setAttribute('title', title);
-            el.textContent = "Posted " + text;
+            el.textContent = "posted " + text;
         }
     });
 
     
     submit: function() { 
         var title = $("title");
-        if (!title.value.match(/^[ \w]+$/) || FORBIDDEN_PAGES.indexOf(title.value) >= 0) {
+        //a-zA-Z0-9_\\u00A1-\\uFFFF
+        if (!title.value.match(/^[ \w\u00A1-\uFFFF]+$/i) || FORBIDDEN_PAGES.indexOf(title.value) >= 0) {
             alert("Page title invalid");
             return false;
         }
         
         var slug = title.value.replace(/ /g, "_");
-        document.location.href = Site.url + "/" + slug + "#pedit";
+        document.location.href = Site.url + "/" +  slug + "#pedit";
     },
 });
 
     }
 });
 
-
-var claim = Class.create({
-    email: false,
-    password: false,
+var Diff = Class.create({
+    initialize: function() {
+        var self = this;
+        this.rev_from = $('rev_from');
+        this.rev_to = $('rev_to');
+        
+        $('scompare').observe('click', function(e) {
+            Event.stop(e);
+            self.get_diff();
+            return false;
+        })
+    },
     
-    initialize: function() {
-        var email = $('email');
+    get_diff: function() {
+        var from = this.rev_from.getValue();
+        var to = this.rev_to.getValue();
+        if (from == to) {
+            alert("Why would you want compare same version ...");
+            return
+        }
+        url = $('fdiff').action + "?r="+from+"&r="+to;
+        new Ajax.Request(url, {
+          method: 'get',
+          contentType: 'application/json', 
+          requestHeaders: {Accept: 'application/json'},
+          onSuccess: function(response) {   
+             data = response.responseText.evalJSON(true);
+             if (data['ok']) {
+                Element.remove($('tableDiff'));
+                $('pdiff').insert(data['diff'])
+             }
+         }
+        });
     }
 })
 

File static/js/page.js

         this.Page = $('page');
         this.tabs = new Control.Tabs('tabs_wiki');
         
-        this.tabs.observe('beforeChange', function(old_container, new_container) {
-            if (!Page.created) {
-                 self.update_tabs(new_container);
-            } else {
-                var y = window.confirm("Are you sure you want to navigate away from this page?\n\n"+
-                "You have unsaved changes. Continue and discard those changes?\n\n" +
-                "Click OK to continue, or click Cancel to stay on this page.");
-               
-                if (!y) {
-                    throw $break;
-                } else {
-                    history.go(-1);
-                }
-            }
-           
-        });
-        
-        new Resizable('content');
         this.textarea = new Control.TextArea('content');  
         this.toolbar = new Control.TextArea.ToolBar(this.textarea);  
         this.toolbar.container.id = 'markdown_toolbar';
         
         this.build_toolbar();
         this.init();
+        
+        this.tabs.observe('beforeChange', function(old_container, new_container) {
+            if (!Page.created) {
+                 self.update_tabs(new_container);
+            } else {
+                var y = window.confirm("Are you sure you want to navigate away from this page?\n\n"+
+                "You have unsaved changes. Continue and discard those changes?\n\n" +
+                "Click OK to continue, or click Cancel to stay on this page.");
+               
+                if (!y) {
+                    throw $break;
+                } else {
+                    history.go(-1);
+                }
+            }
+        });
+        
 
         Event.observe(window, 'resize', function(e) {
             var new_height = document.viewport.getHeight() - 150;
     
     init: function() {
         var active_container = this.tabs.activeContainer;  
-        this.update_tabs(active_container)
+        if (active_container)
+            this.update_tabs(active_container);
         
         /* init size of textarea */
         var new_height = document.viewport.getHeight() -150;
                     });
                 }
                 
-                
-                
                 return false;
             }
             

File static/js/tabs.js

 			? $(tab_list_container).select(this.options.linkSelector)
 			: this.options.linkSelector($(tab_list_container))
 		).findAll(function(link){
-			return (/^#/).exec(link.href.replace(window.location.href.split('#')[0],''));
+		    if (Prototype.Browser.WebKit)
+		        var href = decodeURIComponent(link.href);
+		    else
+		        var href = link.href;
+		 	return (/^#/).exec(href.replace(window.location.href.split('#')[0],''));
 		}).each(function(link){
 			this.addTab(link);
 		}.bind(this));
 			this.setActiveTab(this.options.defaultTab);
 		var targets = this.options.targetRegExp.exec(window.location);
 		if(targets && targets[1]){
+		    
 			targets[1].split(',').each(function(target){
 				this.setActiveTab(this.links.find(function(link){
 					return link.key == target;

File templates/base.html

 <!DOCTYPE html>
 
-<html lang="en">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
 
 <head>
     <meta charset="utf-8" />

File templates/page/diff.html

 {% extends "base.html" %}
-
-{% block content %}
-    {{ diff|tabular }}
+{% block title %}
+    Compare
 {% endblock %}
 
-{% block aside %}
+
+{% block page %}
+<section id="pdiff">
+    <h3>Compare revisions of <a href="{{ url_for('show_page', cname=site.cname, pagename=page.title|replace(" ", "_")) }}">{{ page.title }}</a></h3>
+    <form id="fdiff" name="fdiff" action="{{ url_for('diff_page', cname=site.cname, pagename=page.title|replace(" ", "_")) }}" method="post">
+        <p>From <select name="rev_from" id="rev_from">
+            {% for rev in revisions %}
+                {% if rev.nb_revision == rev1.nb_revision %}
+                <option value="{{ rev.nb_revision }}" selected="selected">{{ rev.nb_revision }} ({{ rev.updated|formatdatetime }})</option>
+                {% else %}
+                <option value="{{ rev.nb_revision }}">{{ rev.nb_revision }} ({{ rev.updated|formatdatetime }})</option>
+                {% endif %}{% endfor %}</select> to <select name="rev_to" id="rev_to">
+                    {% for rev in revisions %}
+                        {% if rev.nb_revision == rev2.nb_revision %}
+                        <option value="{{ rev.nb_revision }}" selected="selected">{{ rev.nb_revision }} ({{ rev.updated|formatdatetime }})</option>
+                        {% else %}
+                        <option value="{{ rev.nb_revision }}">{{ rev.nb_revision }} ({{ rev.updated|formatdatetime }})</option>
+                        {% endif %}
+                    {% endfor %}</select><input type="submit" name="scompare" id="scompare" value="Compare" /></p>
+    </form>
+    {{ diff|tabular(rev1,rev2) }}
+</section>
+{% endblock %}
+
+{% block sidebar %}
 {% include "sidebar.html" %}
+{% endblock %}
+
+{% block footer %}
+<script type="text/javascript">
+    Site.name = "{{ site.cname }}";
+    Site.url = "/" + "{{ site.cname }}";
+    new Create();
+    new Diff();
+</script>
 {% endblock %}

File templates/page/diff_inc.html

+{{ diff|tabular(rev1,rev2) }}

File templates/page/history.html

 {% extends "base.html" %}
 {% block title %}Revision history of {{ page.title }}{% endblock %}
 {% block page %}
-<h2>Revision history of <a href="{{ url_for('show_page', cname=site.cname, pagename=page.title|replace(" ", "_")) }}">{{ page.title }}</a></h2>
+<section id="phistory">
+    <h2>Revision history of <a href="{{ url_for('show_page', cname=site.cname, pagename=page.title|replace(" ", "_")) }}">{{ page.title }}</a></h2>
 
-<form id="fhistory" name="fhistory" method="get" action="{{ url_for('diff_page', cname=site.cname, pagename=page.title|replace(" ", "_")) }}">
-    <p><input type="submit" class="fhistory" name"fhistory" value="Compare selected version" /></p>
-    <table class="historyTable">
-        <tr>
-            <td><input type="checkbox" class="c" name="r" value="{{ page.nb_revision }}"></td>
-            <td class="nbrev"><a href="{{ url_for('revision_page', cname=site.cname, pagename=page.title|replace(" ", "_"), nb_revision=page.nb_revision ) }}">{{ page.nb_revision }}</a></td>
-            <td><time title="GMT" datetime="{{ page.updated|rfc3339 }}">{{ page.updated|formatdatetime }}</time></td>
-            <td class="changes">
-                {% if page.changes %}
-                <ol>
-                    {% for change in page.changes %}
-                    {% if change['type'] != 'unmod' %}
-                    <li>{{ change['type']|pretty_type }} "<span class="lineChange">{{ change['changed']['lines']|join('\n')|trim|striptags|truncate(40) }}"</li> 
-                    {% endif %}  
-                    {% endfor %}
-                </ol>
-                {% else %}
-                    {% if page.previous %}
-                Edited.
+    <form id="fhistory" name="fhistory" method="get" action="{{ url_for('diff_page', cname=site.cname, pagename=page.title|replace(" ", "_")) }}">
+        <p><input type="submit" class="fhistory" name"fhistory" value="Compare selected version" /></p>
+        <table class="historyTable">
+            <tr>
+                <td><input type="checkbox" class="c" name="r" value="{{ page.nb_revision }}"></td>
+                <td class="nbrev"><a href="{{ url_for('revision_page', cname=site.cname, pagename=page.title|replace(" ", "_"), nb_revision=page.nb_revision ) }}">{{ page.nb_revision }}</a></td>
+                <td><time title="GMT" datetime="{{ page.updated|rfc3339 }}">{{ page.updated|formatdatetime }}</time></td>
+                <td class="changes">
+                    {% if page.changes %}
+                    <ol>
+                        {% for change in page.changes %}
+                        {% if change['type'] != 'unmod' %}
+                        <li>{{ change['type']|pretty_type }} "<span class="lineChange">{{ change['changed']['lines']|join('\n')|trim|striptags|truncate(40) }}"</li> 
+                        {% endif %}  
+                        {% endfor %}
+                    </ol>
                     {% else %}
-                Created page.
+                        {% if page.previous %}
+                    Edited.
+                        {% else %}
+                    Created page.
+                        {% endif %}
+                
                     {% endif %}
-                
-                {% endif %}
 
 
-            </td>
-        </tr>
-        {% for rev in revisions %}
-        <tr>
-            <td><input type="checkbox"  class="c" name="r" value="{{ rev.nb_revision }}"></td>
-            <td class="nbrev"><a href="{{ url_for('revision_page', cname=site.cname, pagename=rev.title|replace(" ", "_"), nb_revision=rev.nb_revision ) }}">{{ rev.nb_revision }}</a></td>
-            <td><time title="GMT" datetime="{{ rev.updated|rfc3339 }}">{{ rev.updated|formatdatetime }}</time></td>
-            <td class="changes">
-                {% if rev.changes %}
-                <ol>
-                    {% for change in rev.changes %}
-                        {% if change['type'] != 'unmod' %}
-                    <li>{{ change['type']|pretty_type }} "<span class="lineChange">{{ change['changed']['lines']|join('\n')|trim|striptags|truncate(40) }}"</li> 
-                        {% endif %}  
-                    {% endfor %}
-                </ol>
-                {% else %}
-                    {% if rev.previous %}
-                Edited.
+                </td>
+            </tr>
+            {% for rev in revisions %}
+            <tr>
+                <td><input type="checkbox"  class="c" name="r" value="{{ rev.nb_revision }}"></td>
+                <td class="nbrev"><a href="{{ url_for('revision_page', cname=site.cname, pagename=rev.title|replace(" ", "_"), nb_revision=rev.nb_revision ) }}">{{ rev.nb_revision }}</a></td>
+                <td><time title="GMT" datetime="{{ rev.updated|rfc3339 }}">{{ rev.updated|formatdatetime }}</time></td>
+                <td class="changes">
+                    {% if rev.changes %}
+                    <ol>
+                        {% for change in rev.changes %}
+                            {% if change['type'] != 'unmod' %}
+                        <li>{{ change['type']|pretty_type }} "<span class="lineChange">{{ change['changed']['lines']|join('\n')|trim|striptags|truncate(40) }}"</li> 
+                            {% endif %}  
+                        {% endfor %}
+                    </ol>
                     {% else %}
-                <span class="created">Created page.</span>
+                        {% if rev.previous %}
+                    Edited.
+                        {% else %}
+                    <span class="created">Created page.</span>
+                        {% endif %}
                     {% endif %}
-                {% endif %}
 
 
-            </td>
-        </tr>
+                </td>
+            </tr>
 
-        {% endfor %}    
-    </table>
-    <p><input type="submit" class="fhistory" name"fhistory" value="Compare selected version" /></p>
-</form>
+            {% endfor %}    
+        </table>
+        <p><input type="submit" class="fhistory" name"fhistory" value="Compare selected version" /></p>
+    </form>
+</section>
 {% endblock %}
 
 {% block footer %}
 <script type="text/javascript" charset="utf-8">
-    site.name = "{{ site.cname }}";
-    site.url = "/" + "{{ site.cname }}"
+    Site.name = "{{ site.cname }}";
+    Site.url = "/" + "{{ site.cname }}"
     new Create();
     new Compare();
 </script>

File templates/page/show.html

 <script src="/static/js/textarea.js" type="text/javascript"></script>
 <script src="/static/js/window.js" type="text/javascript"></script>
 <script src="/static/js/showdown.js" type="text/javascript"></script>
-<script src="/static/js/page.js" type="text/javascript"></script>
+<script src="/static/js/page.js" type="text/javascript" charset="utf-8"></script>
 {% endblock %}
 
 
 
 {% block page %}
 {% if page.parent %}
-<form name="frevert" id="frevert" action="" method="POST">
-    <p>This is the version of <a href="{{ url_for('show_page', cname=site.cname, pagename=page.title|replace(" ", "_")) }}">{{ page.title }}</a> <time title="GMT" datetime="{{ page.updated|rfc3339 }}">{{ page.updated|formatdatetime }}</time></p>
-    <input type="submit" name="srevert" id="srevert" value="revert to this" />
-</form>
+<section id="prevert">
+    <form name="frevert" id="frevert" action="{{ url_for('revision_page', cname=site.cname, pagename=page.title|replace(" ", "_"), nb_revision=page.nb_revision ) }}" method="POST">
+        <p>This is the version of <a href="{{ url_for('show_page', cname=site.cname, pagename=page.title|replace(" ", "_")) }}">{{ page.title }}</a> <time title="GMT" datetime="{{ page.updated|rfc3339 }}">{{ page.updated|formatdatetime }}</time> <input type="submit" name="srevert" id="srevert" value="revert to this" /></p>
+    </form>
+</section>
 {% endif %}
 
 <ul id="tabs_wiki" class="subsection_tabs">  
 
 
 {% block footer %}
-    <script type="text/javascript">
+    <script type="text/javascript" charset="utf-8">
         Site.name = "{{ site.cname }}";
         Site.url = "/" + "{{ site.cname }}"
         {% if not page.id %}
         Page.created = true;
         {% endif %}
-        
         new Create();
         new PageUI();
     </script>
-    
 {% endblock %}