changeset 281:163ba52e7b84

Add simple pagination to the wiki history page and API endpoint.
author Ludovic Chabant <ludovic@chabant.com>
date Fri, 26 Sep 2014 21:14:11 -0700
parents ca5a466412c1
children 7b9f0eed8ced
files wikked/assets/css/wikked/page.less wikked/assets/js/wikked/app.js wikked/assets/js/wikked/models.js wikked/assets/tpl/special-changes.html wikked/scm/base.py wikked/scm/mercurial.py wikked/views/history.py wikked/wiki.py
diffstat 8 files changed, 63 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/wikked/assets/css/wikked/page.less	Fri Sep 26 16:33:10 2014 -0700
+++ b/wikked/assets/css/wikked/page.less	Fri Sep 26 21:14:11 2014 -0700
@@ -85,3 +85,15 @@
     }
 }
 
+// Wiki history
+.wiki-history-entry-collapser {
+    font-size: 90%;
+}
+
+.wiki-history-pagination {
+    padding: 1em;
+}
+.wiki-history-pagination div:last-child {
+    text-align: right;
+}
+
--- a/wikked/assets/js/wikked/app.js	Fri Sep 26 16:33:10 2014 -0700
+++ b/wikked/assets/js/wikked/app.js	Fri Sep 26 21:14:11 2014 -0700
@@ -76,6 +76,7 @@
             'logout':                "doLogout",
             'special':               "showSpecialPages",
             'special/changes':       "showSiteChanges",
+            'special/changes/:rev':  "showSiteChangesAfterRev",
             'special/orphans':       "showOrphans"
         },
         readPage: function(path) {
@@ -187,6 +188,13 @@
             this.viewManager.switchView(view);
             this.navigate('/special/changes');
         },
+        showSiteChangesAfterRev: function(rev) {
+            var view = new Views.SpecialChangesView({
+                model: new Models.SpecialChangesModel({ after_rev: rev })
+            });
+            this.viewManager.switchView(view);
+            this.navigate('/special/changes/' + rev);
+        },
         showOrphans: function() {
             var view = new Views.SpecialOrphansView({
                 model: new Models.SpecialOrphansModel()
--- a/wikked/assets/js/wikked/models.js	Fri Sep 26 16:33:10 2014 -0700
+++ b/wikked/assets/js/wikked/models.js	Fri Sep 26 21:14:11 2014 -0700
@@ -480,11 +480,16 @@
 
     var SpecialChangesModel = exports.SpecialChangesModel = SpecialPageModel.extend({
         title: "Wiki History",
-        url: '/api/history',
         initialize: function() {
             SpecialChangesModel.__super__.initialize.apply(this, arguments);
             this.on('change:history', this._onHistoryChanged);
         },
+        url: function() {
+            var url = '/api/history';
+            if (this.get('after_rev'))
+                url += '?rev=' + this.get('after_rev');
+            return url;
+        },
         _onHistoryChanged: function(model, history) {
             for (var i = 0; i < history.length; ++i) {
                 var rev = history[i];
@@ -504,6 +509,11 @@
                     }
                 }
             }
+            model.set('first_page', '/#/special/changes');
+            if (history.length > 0) {
+                var last_rev = history[0].rev_name;
+                model.set('next_page', '/#/special/changes/' + last_rev);
+            }
         }
     });
 
--- a/wikked/assets/tpl/special-changes.html	Fri Sep 26 16:33:10 2014 -0700
+++ b/wikked/assets/tpl/special-changes.html	Fri Sep 26 21:14:11 2014 -0700
@@ -51,6 +51,14 @@
                     {{/eachr}}
                 </tbody>
             </table>
+            <div class="wiki-history-pagination pure-g">
+                <div class="pure-u-1-2">
+                    <a href="{{first_page}}">First page</a>
+                </div>
+                <div class="pure-u-1-2">
+                    <a href="{{next_page}}">Next page</a>
+                </div>
+            </div>
         </form>
     </section>
 </article>
--- a/wikked/scm/base.py	Fri Sep 26 16:33:10 2014 -0700
+++ b/wikked/scm/base.py	Fri Sep 26 21:14:11 2014 -0700
@@ -28,7 +28,7 @@
     def getSpecialFilenames(self):
         raise NotImplementedError()
 
-    def getHistory(self, path=None, limit=10):
+    def getHistory(self, path=None, limit=10, after_rev=None):
         raise NotImplementedError()
 
     def getState(self, path):
--- a/wikked/scm/mercurial.py	Fri Sep 26 16:33:10 2014 -0700
+++ b/wikked/scm/mercurial.py	Fri Sep 26 21:14:11 2014 -0700
@@ -17,6 +17,9 @@
 logger = logging.getLogger(__name__)
 
 
+re_rev = re.compile(r'^[0-9a-f]+$')
+
+
 class MercurialBaseSourceControl(SourceControl):
     def __init__(self, root):
         SourceControl.__init__(self)
@@ -60,7 +63,7 @@
         self.hg = 'hg'
         self.log_style = os.path.join(os.path.dirname(__file__), 'resources', 'hg_log.style')
 
-    def getHistory(self, path=None, limit=10):
+    def getHistory(self, path=None, limit=10, after_rev=None):
         if path is not None:
             st_out = self._run('status', path)
             if len(st_out) > 0 and st_out[0] == '?':
@@ -71,6 +74,10 @@
             log_args.append(path)
         log_args += ['--style', self.log_style]
         log_args += ['-l', limit]
+        if after_rev:
+            if not re_rev.match(after_rev):
+                raise ValueError("Invalid revision ID: %s" % after_rev)
+            log_args += ['-r', 'reverse(:%s^)' % after_rev]
         log_out = self._run('log', *log_args)
 
         revisions = []
@@ -229,21 +236,29 @@
             # go through.
             pass
 
-    def getHistory(self, path=None, limit=10):
+    def getHistory(self, path=None, limit=10, after_rev=None):
         if path is not None:
             with cl_lock:
                 status = self.client.status(include=[path])
             if len(status) > 0 and status[0] == '?':
                 return []
 
+        rev = None
+        if after_rev:
+            if not re_rev.match(after_rev):
+                raise ValueError("Invalid revision ID: %s" % after_rev)
+            rev = 'reverse(:%s^)' % after_rev
+
         needs_files = False
         if path is not None:
             with cl_lock:
-                repo_revs = self.client.log(files=[path], follow=True, limit=limit)
+                repo_revs = self.client.log(files=[path], follow=True,
+                                            limit=limit, revrange=rev)
         else:
             needs_files = True
             with cl_lock:
-                repo_revs = self.client.log(follow=True, limit=limit)
+                repo_revs = self.client.log(follow=True, limit=limit,
+                                            revrange=rev)
         revisions = []
         for rev in repo_revs:
             r = Revision(rev.node)
--- a/wikked/views/history.py	Fri Sep 26 16:33:10 2014 -0700
+++ b/wikked/views/history.py	Fri Sep 26 21:14:11 2014 -0700
@@ -54,13 +54,8 @@
 
 @app.route('/api/history')
 def api_site_history():
-    limit = request.args.get('l')
-    if not limit:
-        limit = 10
-    else:
-        limit = int(limit)
-
-    history = g.wiki.getHistory(limit=limit)
+    after_rev = request.args.get('rev')
+    history = g.wiki.getHistory(limit=10, after_rev=after_rev)
     hist_data = get_history_data(history, needs_files=True)
     result = {'history': hist_data}
     return jsonify(result)
--- a/wikked/wiki.py	Fri Sep 26 16:33:10 2014 -0700
+++ b/wikked/wiki.py	Fri Sep 26 21:14:11 2014 -0700
@@ -389,10 +389,10 @@
         """
         return self.db.pageExists(url)
 
-    def getHistory(self, limit=10):
+    def getHistory(self, limit=10, after_rev=None):
         """ Shorthand method to get the history from the source-control.
         """
-        return self.scm.getHistory(limit=limit)
+        return self.scm.getHistory(limit=limit, after_rev=after_rev)
 
     def getSpecialFilenames(self):
         return self.special_filenames