* Improved history view (still not there).
authorŁukasz Rekucki <lrekucki@gmail.com>
Sun, 14 Mar 2010 17:22:35 +0000 (18:22 +0100)
committerŁukasz Rekucki <lrekucki@gmail.com>
Sun, 14 Mar 2010 17:22:35 +0000 (18:22 +0100)
* Added debug toolbar, to apps.
* Fewer queries for toolbar (which should be cached).

* Store "last visited" in user's session. Closes #354.

15 files changed:
apps/compress/templates/compress/.tmp_css.html.32854~ [deleted file]
apps/compress/templates/compress/.tmp_js.html.60841~ [deleted file]
apps/toolbar/templates/toolbar/button.html
apps/toolbar/templatetags/toolbar_tags.py
apps/wiki/nice_diff.py [new file with mode: 0755]
apps/wiki/templates/wiki/diff_table.html [new file with mode: 0644]
apps/wiki/templates/wiki/document_list.html
apps/wiki/views.py
platforma/settings.py
platforma/static/css/filelist.css
platforma/static/css/master.css
platforma/static/js/main.js
platforma/templates/base.html
requirements.txt
scripts/nice_diff.py [deleted file]

diff --git a/apps/compress/templates/compress/.tmp_css.html.32854~ b/apps/compress/templates/compress/.tmp_css.html.32854~
deleted file mode 100644 (file)
index 3751a4a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<link href="{{ url }}" rel="stylesheet" type="text/css"{% if media %} media="{{ media }}"{% endif %}{% if title %} title="{{ title|default:"all" }}"{% endif %}{% if charset %} charset="{{ charset }}"{% endif %} />
\ No newline at end of file
diff --git a/apps/compress/templates/compress/.tmp_js.html.60841~ b/apps/compress/templates/compress/.tmp_js.html.60841~
deleted file mode 100644 (file)
index 8419c20..0000000
+++ /dev/null
@@ -1 +0,0 @@
-<script type="text/javascript" src="{{ url }}" charset="utf-8"></script>
\ No newline at end of file
index 25a7c42..8335918 100644 (file)
@@ -2,7 +2,7 @@
 <a href="{{button.link}}" target="_new">\r
 {% endif %}\r
 <button type="button"\r
 <a href="{{button.link}}" target="_new">\r
 {% endif %}\r
 <button type="button"\r
-        ui:action="{{ button.scriptlet.name }}"\r
+        ui:action="{{ button.scriptlet_id }}"\r
         ui:action-params="{{ button.params|escape }}"\r
         {% if button.key %}ui:hotkey="{{ button.hotkey_code }}"{% endif %}\r
         {% if button.tooltip %}title="{{ button.full_tooltip }}"{% endif %} >\r
         ui:action-params="{{ button.params|escape }}"\r
         {% if button.key %}ui:hotkey="{{ button.hotkey_code }}"{% endif %}\r
         {% if button.tooltip %}title="{{ button.full_tooltip }}"{% endif %} >\r
index 14d3679..ac7ebbb 100644 (file)
@@ -5,7 +5,7 @@ register = template.Library()
 
 @register.inclusion_tag('toolbar/toolbar.html')
 def toolbar():
 
 @register.inclusion_tag('toolbar/toolbar.html')
 def toolbar():
-    return {'toolbar_groups': models.ButtonGroup.objects.all()}
+    return {'toolbar_groups': models.ButtonGroup.objects.all().select_related() }
 
 @register.inclusion_tag('toolbar/button.html')
 def toolbar_button(b):
 
 @register.inclusion_tag('toolbar/button.html')
 def toolbar_button(b):
diff --git a/apps/wiki/nice_diff.py b/apps/wiki/nice_diff.py
new file mode 100755 (executable)
index 0000000..612fa22
--- /dev/null
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+
+import difflib
+import re
+
+from django.template.loader import render_to_string
+from django.utils.html import escape as html_escape
+
+DIFF_RE = re.compile(r"""\x00([+^-])""" ,re.UNICODE)
+NAMES = { '+': 'added', '-': 'removed', '^': 'changed' }
+
+def diff_replace(match):
+       return """<span class="diff_mark diff_mark_%s">""" %  NAMES[match.group(1)]
+
+def filter_line(line):
+       return  DIFF_RE.sub(diff_replace, html_escape(line)).replace('\x01', '</span>')
+
+def html_diff_table(la, lb):
+       return render_to_string("wiki/diff_table.html", {
+               "changes": [(a[0],filter_line(a[1]),
+                                        b[0],filter_line(b[1]),
+                                        change) for a, b, change in difflib._mdiff(la, lb)]
+       }); 
+                                                                               
+       
+__all__ = ['html_diff_table']
\ No newline at end of file
diff --git a/apps/wiki/templates/wiki/diff_table.html b/apps/wiki/templates/wiki/diff_table.html
new file mode 100644 (file)
index 0000000..91ac55c
--- /dev/null
@@ -0,0 +1,20 @@
+<table class="diff_table">
+       <thead>
+               <tr>
+                       <th colspan="2">Stara wersja</th>
+                       <th colspan="2">Nowa wersja</th>
+               </tr>
+       </thead>
+<tbody>
+{% for an, a, bn, b, has_change in changes %}
+
+<tr class="{% if has_change %}change{% endif %}">
+<td>{{an}}</td>
+<td class="left">{{ a|safe }}&nbsp;</td>
+<td>{{bn}}</td>
+<td class="right">{{ b|safe }}&nbsp;</td>
+</tr>
+
+{% endfor %}
+</tbody>
+</table>
\ No newline at end of file
index 183d612..1b0662b 100644 (file)
@@ -29,19 +29,28 @@ $(function() {
 {% block maincontent %}
 <h1><img src="{{STATIC_URL}}/img/logo.png">Platforma Redakcyjna</h1>
 
 {% block maincontent %}
 <h1><img src="{{STATIC_URL}}/img/logo.png">Platforma Redakcyjna</h1>
 
-<div class="document-list">
-    <form action="#" method="GET">
-    <p>Filtr: <input autocomplete="off" name="filter" id="file-list-filter" type="text" size="60" />
-        <input type="submit" value="Znajdź" id="file-list-find-button"/>
-        <input type="reset" value="Wyczyść" id="file-list-reset-button"/>
-    </p>
-    </form>
-        
+<div id="document-list">        
     <div id="file-list">
     <div id="file-list">
-    {% for file in document_list %}
-        <p><a href="{% url wiki.views.document_detail file|urlencode %}">{{ file }}</a></p>
-    {% endfor %}
+       <form action="#" method="GET">
+       <p>Filtr: <input autocomplete="off" name="filter" id="file-list-filter" type="text" size="60" />
+               <input type="submit" value="Znajdź" id="file-list-find-button"/>
+               <input type="reset" value="Wyczyść" id="file-list-reset-button"/>
+       </p>
+       </form>
+       {% for file in document_list %}
+               <p><a target="_blank" href="{% url wiki.views.document_detail file|urlencode %}">{{ file }}</a></p>
+       {% endfor %}
     </div>
     </div>
+       
+       <div id="last-edited-list">
+               <h2>Twoje ostatnio otwierane dokumenty:</h2>
+               <ol>
+                       {% for   name, date in last_docs %}
+                       <li><a href="{% url wiki.views.document_detail name|urlencode %}"
+                               target="_blank">{{ name }}</a><br/><span class="date">({{ date|date:"H:i:s, d/m/Y" }})</span></li>
+                       {% endfor %}                    
+               </ol>
+       </div>
 </div>
 
 </div>
 </div>
 
 </div>
index ea6fa8b..dd3991f 100644 (file)
@@ -10,8 +10,11 @@ from wiki.forms import DocumentForm
 from datetime import datetime
 
 # import google_diff
 from datetime import datetime
 
 # import google_diff
-import difflib
+# import difflib
+import nice_diff
+import operator
 
 
+MAX_LAST_DOCS = 10
 
 class DateTimeEncoder(json.JSONEncoder):
      def default(self, obj):
 
 class DateTimeEncoder(json.JSONEncoder):
      def default(self, obj):
@@ -20,9 +23,12 @@ class DateTimeEncoder(json.JSONEncoder):
          return json.JSONEncoder.default(self, obj)
 
 def document_list(request, template_name = 'wiki/document_list.html'):
          return json.JSONEncoder.default(self, obj)
 
 def document_list(request, template_name = 'wiki/document_list.html'):
+    # TODO: find a way to cache "Storage All"
     return direct_to_template(request, template_name, extra_context = {
         'document_list': storage.all(),
     return direct_to_template(request, template_name, extra_context = {
         'document_list': storage.all(),
-    })
+        'last_docs': sorted(request.session.get("wiki_last_docs", {}).items(), 
+                        key=operator.itemgetter(1), reverse = True)
+    })  
 
 
 def document_detail(request, name, template_name = 'wiki/document_details.html'):
 
 
 def document_detail(request, name, template_name = 'wiki/document_details.html'):
@@ -31,12 +37,15 @@ def document_detail(request, name, template_name = 'wiki/document_details.html')
     except DocumentNotFound:        
         raise Http404
     
     except DocumentNotFound:        
         raise Http404
     
-#    access_time = datetime.ctime();
-#    last_documents = request.session.get("wiki_last_docs", [])
-#        
-#    if name not in last_documents:
-#        last_documents.insert(0, (name, access_time))        
-
+    access_time = datetime.now()
+    last_documents = request.session.get("wiki_last_docs", {})      
+    last_documents[name] = access_time
+    
+    if len(last_documents) > MAX_LAST_DOCS:
+        oldest_key = min(last_documents, key = last_documents.__getitem__)
+        del last_documents[oldest_key]        
+    request.session['wiki_last_docs'] = last_documents   
+                
     if request.method == 'POST':
         
         form = DocumentForm(request.POST, instance = document)
     if request.method == 'POST':
         
         form = DocumentForm(request.POST, instance = document)
@@ -66,15 +75,13 @@ def document_gallery(request, directory):
 
         raise Http404
     
 
         raise Http404
     
-def document_diff(request, name, revA, revB):
-    differ = difflib.HtmlDiff(wrapcolumn=60)
-     
+def document_diff(request, name, revA, revB):     
     docA = storage.get(name, int(revA))
     docA = storage.get(name, int(revA))
-    docB = storage.get(name, int(revB))
-     
-    return HttpResponse(differ.make_table(
-                                docA.plain_text.splitlines(),
-                                docB.plain_text.splitlines() ) )                                           
+    docB = storage.get(name, int(revB)) 
+    
+    
+    return HttpResponse(nice_diff.html_diff_table(docA.plain_text.splitlines(), 
+                                         docB.plain_text.splitlines()) )                                           
     
     
 def document_history(reuqest, name):
     
     
 def document_history(reuqest, name):
index 5d0479a..628b4ef 100644 (file)
@@ -84,8 +84,9 @@ MIDDLEWARE_CLASSES = (
     'django.contrib.auth.middleware.AuthenticationMiddleware',
     'django_cas.middleware.CASMiddleware',
 
     'django.contrib.auth.middleware.AuthenticationMiddleware',
     'django_cas.middleware.CASMiddleware',
 
-    'django.middleware.doc.XViewMiddleware',
+    'django.middleware.doc.XViewMiddleware',    
     'maintenancemode.middleware.MaintenanceModeMiddleware',
     'maintenancemode.middleware.MaintenanceModeMiddleware',
+    'debug_toolbar.middleware.DebugToolbarMiddleware'
 )
 
 AUTHENTICATION_BACKENDS = (
 )
 
 AUTHENTICATION_BACKENDS = (
@@ -127,10 +128,10 @@ COMPRESS_CSS = {
 }
  
 COMPRESS_JS = {
 }
  
 COMPRESS_JS = {
-    # everything except codemirror
+    # everything except codemirror and jquery (which we take from google)
     'detail': {
         'source_filenames': (
     'detail': {
         'source_filenames': (
-                'js/jquery-1.4.2.min.js', 
+                #'js/jquery-1.4.2.min.js', 
                 'js/jquery.autocomplete.js', 
                 'js/jquery.blockui.js',
                 'js/jquery.elastic.js',
                 'js/jquery.autocomplete.js', 
                 'js/jquery.blockui.js',
                 'js/jquery.elastic.js',
@@ -143,13 +144,14 @@ COMPRESS_JS = {
      },
     'listing': {
         'source_filenames': (
      },
     'listing': {
         'source_filenames': (
-                'js/jquery-1.4.2.min.js', 
+                'js/jquery-1.4.2.min.js', 
                 'js/slugify.js',                
         ),             
         'output_filename': 'compressed/listing_scripts_?.js',
      }
 }
  
                 'js/slugify.js',                
         ),             
         'output_filename': 'compressed/listing_scripts_?.js',
      }
 }
  
+COMPRESS = True
 COMPRESS_CSS_FILTERS = None
 COMPRESS_JS_FILTERS = None
 COMPRESS_AUTO = False
 COMPRESS_CSS_FILTERS = None
 COMPRESS_JS_FILTERS = None
 COMPRESS_AUTO = False
@@ -166,6 +168,8 @@ INSTALLED_APPS = (
     'django.contrib.admindocs',
 
     'django_nose',
     'django.contrib.admindocs',
 
     'django_nose',
+    'debug_toolbar',
+    
     'compress',
 
     'wiki',
     'compress',
 
     'wiki',
index 732ebd9..0afc954 100644 (file)
@@ -29,26 +29,40 @@ body {
        font-family: sans-serif;
 }
 
        font-family: sans-serif;
 }
 
-.document-list {
+#file-list {
        overflow: visible;
        float: left;
        overflow: visible;
        float: left;
-       max-width: 60%;
+       max-width: 50%;
+       padding-right: 2%;
+       border-right: 1px dashed black; 
+       
 }
 
 }
 
-.document-list .page-nav-wrap button {
-    width: 2.5em;
+#last-edited-list {
+       float: left;
+       max-width: 35%;
+       margin-left: 5%;
 }
 
 }
 
-ul.file-tree-part {    
-    margin: 0.5em 1em;
-    padding: 0em;
+#last-edited-list ul {
+       margin: 0px;
+}      
+
+#last-edited-list li {
+       margin-bottom: 1em;
 }
 
 }
 
-ul.file-tree-part li {
-    list-style: square;    
-    padding: 0em;    
+#last-edited-list .date {
+       font-size: 70%;
+       color: grey;
 }
 
 }
 
-ul.file-tree-part a {
-    padding: 0em;
+a, a:visited, a:active {
+       color: blue;
+       text-decoration: none;  
+}
+
+a:hover {
+       text-decoration: underline;
+}
 }
 }
index 5fc28d0..619d3fd 100644 (file)
@@ -1,3 +1,8 @@
+a, a:visited, a:active {
+       color: gold;
+       text-decoration: none;  
+}
+
 body {
     margin: 0;
     overflow: hidden;
 body {
     margin: 0;
     overflow: hidden;
@@ -321,43 +326,71 @@ p { margin: 0;}
     line-height: 18px;
        padding-right: 5px;
 }
     line-height: 18px;
        padding-right: 5px;
 }
+
+#history-view table {
+       width: 80%;
+       margin: 1em auto;       
+}
+
+#history-view .diff_table {
+       width: 90%;
+}
  
 /* DIFFS */
  
 /* DIFFS */
- #history-view table {
-       width: 75%;
-       margin: 1em auto;
-       max-height: 400px;
-       overflow-y: auto;
- }
- #diff-view {
-       border: 2px solid black;
-       background: #fafafa;
-       margin: 1em auto;
-       width: 90%;     
- }
- td.diff_header {
-       display: none;
- }
- td.diff_next {
-       display: none;
- }
+ .diff_table { 
+       border-width: 1px;
+       border-style: solid;
+       border-color: black;
+       empty-cells: show;
+       border-spacing: 0px;            
+}
+
+.diff_table td {
+       border-width: 0px 1px 1px 0px;
+       border-style: dotted;
+       border-color: grey;
+       
+       font-size: 10px;
+       line-height: 20px;
+       font-family: monospace;
+       padding: 0px;
+       white-space:pre-line;
+       /*word-wrap:break-word;
+       word-break:break-all; */
+}
 
 
- .diff_sub {
-       background-color: #ef4040;
- }
- .diff_chg {
-       background-color: #efef40;
- }
+.diff_table th {
+       border-width: 0px 1px 1px 0px;
+       border-style: solid;
+       border-color: black;
+       background: #e5ffe5;            
+}
  
  
- .diff_add {
-       background-color: #40ef40;
- }
+/* .diff_table td.left, .diff_table td.right {
+       width: 50%;
+}*/
+
+.diff_table tr.change {
+       background-color: #dcdcdc;
+       
+}
 
 
+.diff_mark {
+       display: inline-block;
+       padding: 2px;
+}
+
+.diff_mark_removed {
+       background-color: #ff9c94;
+}
 
 
+.diff_mark_added {
+       background-color: #90ee90;
+}
+
+.diff_mark_changed {
+       background-color: yellow;
+}
 /*
  * HTML Editor view
  */ 
 /*
  * HTML Editor view
  */ 
index 3f4d30c..1509958 100644 (file)
@@ -715,7 +715,7 @@ function refreshHistory(callback){
                                        +'<td>'+ this[1]+'</td></tr>')                  
                        });                                                     
                        $.unblockUI();  
                                        +'<td>'+ this[1]+'</td></tr>')                  
                        });                                                     
                        $.unblockUI();  
-                       callback();
+                       if(callback) callback();
                }
        });
 };
                }
        });
 };
@@ -887,11 +887,11 @@ $(function() {
     $('.vsplitbar').click(function() {
         if ($('#sidebar').width() == 0) {
             $('#sidebar').width(480).css({right: 0}).show();
     $('.vsplitbar').click(function() {
         if ($('#sidebar').width() == 0) {
             $('#sidebar').width(480).css({right: 0}).show();
-            $('#source-editor, #simple-editor').css({right: 495});
+            $('#editor .editor').css({right: 495});
             $('.vsplitbar').css({right: 480}).addClass('active');
         } else {
             $('#sidebar').width(0).hide();
             $('.vsplitbar').css({right: 480}).addClass('active');
         } else {
             $('#sidebar').width(0).hide();
-            $('#source-editor, #simple-editor').css({right: 15});
+            $('#editor .editor').css({right: 15});
             $('.vsplitbar').css({right: 0}).removeClass('active');
         }
         $(window).resize();
             $('.vsplitbar').css({right: 0}).removeClass('active');
         }
         $(window).resize();
index 07c9f78..cb518a3 100644 (file)
@@ -11,6 +11,8 @@
        <div id="body-wrap">
         <div id="content">{% block maincontent %} {% endblock %}</div>
         </div>
        <div id="body-wrap">
         <div id="content">{% block maincontent %} {% endblock %}</div>
         </div>
+       <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" 
+               type="text/javascript"></script>
     {% block extrabody %}{% endblock %}
     </body>
 </html>
     {% block extrabody %}{% endblock %}
     </body>
 </html>
index 00c38ac..975ceb7 100644 (file)
@@ -6,4 +6,6 @@ mercurial>=1.3.1
 librarian>=1.3.dev,<1.4
 PyYAML>=3.0
 # MySQL-python>=1.2,<2.0
 librarian>=1.3.dev,<1.4
 PyYAML>=3.0
 # MySQL-python>=1.2,<2.0
+# debug stuff
 django-nose>=0.0.3
 django-nose>=0.0.3
+django-debug-toolbar>=0.8
diff --git a/scripts/nice_diff.py b/scripts/nice_diff.py
deleted file mode 100644 (file)
index 3de9ad4..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-import difflib
-import re
-
-def read_whole(path):
-       with open(path) as f:
-               return f.readlines()
-
-DIFF_RE = re.compile(r"""\x00([+^-])""" ,re.UNICODE)
-NAMES = { '+': 'added', '-': 'removed', '^': 'changed' }
-
-def diff_replace(match):
-       return """<span class="diff_mark diff_mark_%s">""" %  NAMES[match.group(1)]
-
-
-def filter_line(line):
-       return DIFF_RE.sub(diff_replace, line).replace('\x01', '</span>')
-
-def group(diffs):
-       group_a = []
-       group_b = []
-
-       a, b, _ = diffs.next()
-       group_a.append(a[1])
-       group_b.append(b[1])
-
-
-       for _ in range(10):
-               a, b, _ = diffs.next()
-               group_a.append(a[1])
-               group_b.append(b[1])    
-
-               while a[0] == '':
-                       a, b, _ = diffs.next()
-                       group_a.append(a[1])
-                       group_b.append(b[1])
-
-               yield group_a[:-1], group_b[:-1]
-               group_a, group_b = group_a[-1:], group_b[-1:]
-
-def join_to_html(diffs):
-       for group_a, group_b in group(diffs):
-               yield """
-<div class="change_block">
-       <div class="old_block">%s</div>
-       <div class="new_block">%s</div>
-</div>""" % ( 
-       '\n'.join( filter_line(line) for line in group_a ),
-       '\n'.join( filter_line(line) for line in group_b ),
-       )
-
-fa = read_whole("file_a")
-fb = read_whole("file_b")
-
-print '\n'.join( repr(x) for x in  difflib._mdiff(fa, fb)  )
-print "**************************"
-print '\n'.join( join_to_html( difflib._mdiff(fa, fb) ) )
-# print '\n'.join( repr(x) for x in group(difflib._mdiff(fa, fb)) )