changeset 276:24d5464274bb

Handle redirects in the backend instead of the UI.
author Ludovic Chabant <ludovic@chabant.com>
date Thu, 25 Sep 2014 16:37:32 -0700
parents bde155a0335b
children 4d84736d125a
files wikked/assets/css/wikked/page.less wikked/assets/js/wikked/models.js wikked/assets/tpl/read-page.html wikked/views/read.py
diffstat 4 files changed, 44 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/wikked/assets/css/wikked/page.less	Thu Sep 25 11:35:54 2014 -0700
+++ b/wikked/assets/css/wikked/page.less	Thu Sep 25 16:37:32 2014 -0700
@@ -7,7 +7,13 @@
     padding: 0 1em;
 }
 
-// Page title decorator
+// Page title decorators
+.decorator-sub {
+    font-size: 0.8em;
+    margin-top: -0.75em;
+    margin-bottom: 1.25em;
+    color: @color-gray-dark;
+}
 .decorator, .decorator-sm {
     text-transform: uppercase;
     font-family: @font-family-sans-serif;
--- a/wikked/assets/js/wikked/models.js	Thu Sep 25 11:35:54 2014 -0700
+++ b/wikked/assets/js/wikked/models.js	Thu Sep 25 16:37:32 2014 -0700
@@ -260,9 +260,13 @@
         },
         url: function() {
             var url = PageReadModel.__super__.url.apply(this, arguments);
-            if (!this.nav.get('user')) {
-                url += '?user';
-            }
+            var qs = {};
+            if (!this.nav.get('user'))
+                qs.user = 1;
+            if (this.get('no_redirect'))
+                qs.no_redirect = 1;
+            if (_.size(qs) > 0)
+                url += '?' + $.param(qs);
             return url;
         },
         checkStatePath: function() {
@@ -273,23 +277,6 @@
                 // Forward user info to the navigation model.
                 this.nav.set('user', this.get('user'));
             }
-            if (this.getMeta('redirect')) {
-                // Handle redirects.
-                var newPath = this.getMeta('redirect')[0].replace(/^\//, "");
-                if (this.get('no_redirect')) {
-                    this.set({ 'redirects_to': newPath }, { 'silent': true });
-                } else {
-                    var oldPath = this.get('path');
-                    this.set({
-                        'path': newPath,
-                        'redirected_from': oldPath
-                    }, {
-                        'silent': true
-                    });
-                    this.fetch();
-                    this.navigate('/read/' + newPath, { replace: true, trigger: false });
-                }
-            }
         }
     });
 
--- a/wikked/assets/tpl/read-page.html	Thu Sep 25 11:35:54 2014 -0700
+++ b/wikked/assets/tpl/read-page.html	Thu Sep 25 16:37:32 2014 -0700
@@ -6,7 +6,12 @@
         <div class="decorator">{{meta_query}}</div>
         {{/if}}
         {{#if redirected_from}}
-        <small>Redirected from <a href="{{get_read_url redirected_from}}?no_redirect">{{redirected_from}}</a></small>
+        <div class="decorator-sub">Redirected from 
+            {{#each redirected_from}}
+            {{#ifeq @index to=0}} {{else}} | {{/ifeq}}
+            <a href="{{get_read_url this}}?no_redirect">{{this}}</a>
+            {{/each}}
+        </div>
         {{/if}}
         {{#if meta.redirect}}
         <small>Redirects to <a href="{{get_read_url redirects_to}}">{{redirects_to}}</a></small>
--- a/wikked/views/read.py	Thu Sep 25 11:35:54 2014 -0700
+++ b/wikked/views/read.py	Thu Sep 25 16:37:32 2014 -0700
@@ -6,6 +6,7 @@
         is_page_readable,
         url_from_viewarg, split_url_from_viewarg,
         CHECK_FOR_READ)
+from wikked.utils import get_absolute_url
 from wikked.web import app
 from wikked.scm.base import STATE_NAMES
 
@@ -66,16 +67,33 @@
             additional_info['user'] = False
 
     force_resolve = ('force_resolve' in request.args)
+    no_redirect = ('no_redirect' in request.args)
 
     endpoint, value, path = split_url_from_viewarg(url)
     if endpoint is None:
         # Normal page.
-        page = get_page_or_404(
-                path,
-                fields=['url', 'title', 'text', 'meta'],
-                convert_url=False,
-                check_perms=CHECK_FOR_READ,
-                force_resolve=force_resolve)
+        visited_paths = []
+        while True:
+            page = get_page_or_404(
+                    path,
+                    fields=['url', 'title', 'text', 'meta'],
+                    convert_url=False,
+                    check_perms=CHECK_FOR_READ,
+                    force_resolve=force_resolve)
+            visited_paths.append(path)
+            redirect_meta = page.getMeta('redirect')
+            if redirect_meta is None:
+                break
+            path = get_absolute_url(path, redirect_meta)
+            if no_redirect:
+                additional_info['redirects_to'] = path
+                break
+            if path in visited_paths:
+                app.logger.error("Circular redirect detected: " + url)
+                abort(409)
+
+        if len(visited_paths) > 1:
+            additional_info['redirected_from'] = visited_paths[:-1]
 
         result = {'meta': get_page_meta(page), 'text': page.text}
         result.update(additional_info)