changeset 278:83827f24563e

UI fixes for the menu, getting rid of the Markdown-only editor. * Extra URLs are now in the menu, except for obscure stuff like JSON. * Nicer footer. * No more Markdown editor, only the full preview with a round-trip to the server.
author Ludovic Chabant <ludovic@chabant.com>
date Fri, 26 Sep 2014 07:58:39 -0700
parents 4d84736d125a
children b9c591b3a2c5
files wikked/assets/css/wikked/main.less wikked/assets/css/wikked/nav.less wikked/assets/css/wikked/page.less wikked/assets/js/wikked/models.js wikked/assets/js/wikked/views.js wikked/assets/tpl/edit-page.html wikked/assets/tpl/footer.html wikked/assets/tpl/nav.html wikked/assets/tpl/read-page.html
diffstat 9 files changed, 134 insertions(+), 182 deletions(-) [+]
line wrap: on
line diff
--- a/wikked/assets/css/wikked/main.less	Fri Sep 26 07:53:23 2014 -0700
+++ b/wikked/assets/css/wikked/main.less	Fri Sep 26 07:58:39 2014 -0700
@@ -76,6 +76,10 @@
     position: relative;
 }
 
+.pure-menu .pure-menu-divider {
+    border-top: 1px solid @color-gray-medium;
+}
+
 @media (min-width: 48em) {
     // Place right-aligned menu items to, well, to the right.
     .pure-menu .pure-menu-horizontal-right {
@@ -85,3 +89,8 @@
         clear: both;
     }
 }
+
+.wiki-icon {
+    font-weight: bolder;
+}
+
--- a/wikked/assets/css/wikked/nav.less	Fri Sep 26 07:53:23 2014 -0700
+++ b/wikked/assets/css/wikked/nav.less	Fri Sep 26 07:58:39 2014 -0700
@@ -38,7 +38,7 @@
                 width 200ms ease-in-out 0s,
                 !important;
     a {
-        padding: 1em;
+        padding: 0.5em 1em;
         .wiki-menu-a();
     }
     a:link, a:visited, a:active {
@@ -52,6 +52,7 @@
         border-top: 1px solid @color-gray-medium;
     }
 }
+
 #wiki-menu.wiki-menu-active {
     left: 0 !important;
 }
@@ -156,6 +157,7 @@
     color: @color-gray-dark;
     border-top: 1px solid @color-gray-light;
     padding: 1.5em 0;
+    font-size: 75%;
     font-weight: 300;
     letter-spacing: -0.03em;
     text-align: center;
@@ -176,13 +178,14 @@
         margin: 0;
         padding: 0 0.5em;
     }
-    /*li:before {
-        content: '•';
+    li:before {
+        content: '\2014';
         font-weight: 700;
-        margin: 0 0.5em;
+        font-size: 100%;
+        margin-right: 1em;
     }
     li:first-child:before {
         content: none;
-    }*/
+    }
 }
 
--- a/wikked/assets/css/wikked/page.less	Fri Sep 26 07:53:23 2014 -0700
+++ b/wikked/assets/css/wikked/page.less	Fri Sep 26 07:58:39 2014 -0700
@@ -8,23 +8,23 @@
 }
 
 // Page title decorators
-.decorator-sub {
-    font-size: 0.8em;
-    margin-top: -0.75em;
-    margin-bottom: 1.25em;
-    color: @color-gray-dark;
-}
-.decorator, .decorator-sm {
+.decorator {
     text-transform: uppercase;
     font-family: @font-family-sans-serif;
     font-weight: 200;
-    font-size: 0.8em;
-    margin-top: -0.25em;
-    margin-bottom: 0.75em;
+    font-size: 150%;
+    margin-top: -0.5em;
+    margin-bottom: 1.5em;
     letter-spacing: 0.1em;
     color: @color-gray-dark;
+
+    small {
+        font-size: 60%;
+        text-transform: none;
+    }
+
     .rev_id {
-        //font-family: @font-family-monospace;
+        font-family: @font-family-monospace;
     }
 }
 .decorator-sm {
@@ -45,68 +45,39 @@
 }
 
 // Page editing
-#wmd-preview-button span {
-    background: url(../img/markdown-32x20.png);
-    width: 32px;
-    height: 20px;
+form#page-edit {
+    margin-top: 2em;
 }
-#wmd-input-wrapper {
-    margin: 0.5em 0;
+
+.editing-input, .editing-preview {
+    margin-bottom: 0.5em;
 }
-#wmd-input {
-    height: 10em;
+
+#editing-input-area {
+    min-height: 10em;
     width: 100%;
-    //font-size: @font-size-base;
     font-family: @font-family-monospace;
     margin-bottom: 0;
-    border: 1px solid @color-gray-light;
+    border: 1px solid @color-gray-medium;
     border-radius: 0;
     border-width: 1px 1px 0 1px;
 }
-#wmd-input-grip {
-    //background: @gray-lighter;
+
+#editing-input-grip {
     height: 12px;
-    border: 1px solid @color-gray-light;
+    border: 1px solid @color-gray-medium;
     border-width: 0 1px 1px 1px;
     cursor: ns-resize;
 }
-#wmd-full-preview-button {
-    display: inline-block;
-}
-#wmd-preview-wrapper {
+
+/*#wmd-preview-wrapper {
     border: 1px solid @color-gray-light;
 
     #wmd-preview {
         margin: 1em;
         background: none;
     }
-}
-#wmd-preview {
-    overflow: scroll;
-}
-.preview>h3 {
-    margin: 0;
-    padding: 0;
-}
-.preview-wiki-meta {
-    .meta-name {
-        background: @color-blue-dark;
-        color: #fff;
-        padding: 0.2em 0.4em 0.2em 0.6em;
-        border-radius: 0.5em 0 0 0.5em;
-        letter-spacing: 0.03em;
-    }
-    .meta-value {
-        background: @color-gray-light;
-        color: black;
-        padding: 0.2em 0.6em 0.2em 0.4em;
-        border-radius:  0 0.5em 0.5em 0;
-    }
-}
-.commit-meta {
-    margin-top: 1em;
-    margin-bottom: 1em;
-}
+}*/
 
 @media screen and (min-width: 48em) {
     article {
--- a/wikked/assets/js/wikked/models.js	Fri Sep 26 07:53:23 2014 -0700
+++ b/wikked/assets/js/wikked/models.js	Fri Sep 26 07:58:39 2014 -0700
@@ -17,7 +17,10 @@
             return {
                 path: "",
                 action: "read",
-                username: false
+                username: false,
+                url_extras: [
+                    { name: 'Special Pages', url: '/#/special', icon: 'dashboard' }
+                ]
             };
         },
         initialize: function() {
@@ -34,6 +37,17 @@
         url: function() {
             return '/api/user/info';
         },
+        clearExtraUrls: function() {
+            this.get('url_extras').length = 0;
+        },
+        addExtraUrl: function(name, url, index, icon) {
+            extra = { name: name, url: url, icon: icon };
+            if (index === undefined || index < 0) {
+                this.get('url_extras').push(extra);
+            } else {
+                this.get('url_extras').splice(index, 0, extra);
+            }
+        },
         doPreviewSearch: function(query, callback) {
             if (this._isSearching) {
                 this._pendingQuery = query;
@@ -103,9 +117,7 @@
     var FooterModel = exports.FooterModel = Backbone.Model.extend({
         defaults: function() {
             return {
-                url_extras: [
-                    { name: 'Special Pages', url: '/#/special', icon: 'dashboard' }
-                ]
+                url_extras: []
             };
         },
         clearExtraUrls: function() {
@@ -247,7 +259,7 @@
 
             // Add extra links to the footer.
             var model = this;
-            this.footer.addExtraUrl(
+            this.nav.addExtraUrl(
                 'Pages Linking Here',
                 function() { return '/#/inlinks/' + model.id; },
                 1,
@@ -303,15 +315,15 @@
                     $model.set('error', err.error);
                 });
         },
-        _onChangePath: function(path) {
-            PageEditModel.__super__._onChangePath.apply(this, arguments);
-            this.set('url_read', this._getReadPath(path));
+        doCancel: function() {
+            this._goToReadPage();
         },
         _onEditSuccess: function() {
-            this.navigate('/read/' + this.get('path'), { trigger: true });
+            this._goToReadPage();
         },
-        _getReadPath: function(path) {
-            return '/#/read/' + path;
+        _goToReadPage: function() {
+            this.navigate('/read/' + this.get('path') + '?no_redirect=1',
+                    { trigger: true });
         }
     });
 
@@ -321,7 +333,7 @@
         initialize: function() {
             PageHistoryModel.__super__.initialize.apply(this, arguments);
             var model = this;
-            this.footer.addExtraUrl(
+            this.nav.addExtraUrl(
                 'JSON',
                 function() { return '/api/history/' + model.id; },
                 -1,
@@ -454,7 +466,7 @@
         },
         initialize: function() {
             SpecialPagesModel.__super__.initialize.apply(this, arguments);
-            this.footer.clearExtraUrls();
+            this.nav.clearExtraUrls();
         }
     });
 
@@ -462,7 +474,7 @@
         action: 'special',
         initialize: function() {
             SpecialPageModel.__super__.initialize.apply(this, arguments);
-            this.footer.clearExtraUrls();
+            this.nav.clearExtraUrls();
         }
     });
 
--- a/wikked/assets/js/wikked/views.js	Fri Sep 26 07:53:23 2014 -0700
+++ b/wikked/assets/js/wikked/views.js	Fri Sep 26 07:58:39 2014 -0700
@@ -449,35 +449,14 @@
                 return;
             }
 
-            // Cache some stuff.
-            this._ctrlInput = $('#wmd-input');
-            this._ctrlInputWrapper = $('#wmd-input-wrapper');
-            this._ctrlPreview = $('#wmd-preview');
-            this._ctrlPreviewWrapper = $('#wmd-preview-wrapper');
-
-            // Create the Markdown editor.
-            var m = this.model.get('path').match(/(.*)\/?/);
-            var baseUrl = m[1];
-            var lastSlash = baseUrl.lastIndexOf('/');
-            if (lastSlash >= 0)
-                baseUrl = baseUrl.substr(0, lastSlash);
-            else
-                baseUrl = '';
-            var formatter = new Client.PageFormatter(baseUrl);
-            var converter = new Markdown.Converter();
-            converter.hooks.chain("preConversion", function(text) {
-                return formatter.formatText(text);
-            });
-            var $view = this;
-            var editor = new PageDownConverter.Editor(converter); //TODO: pass options
-            editor.hooks.chain("onPreviewRefresh", function() {
-                $view._updateInputFromPreview();
-            });
-            editor.run();
-
-            // Setup UI.
-            $('.preview').hide();
-            this._isPreviewVisible = false;
+            // Initialize the preview.
+            this.inputSection = $('.editing-input');
+            this.inputCtrl = $('#editing-input-area');
+            this.previewSection = $('.editing-preview');
+            this.previewSection.hide();
+            this.previewButtonLabel = $('.editing-preview-button-label');
+            this.errorSection = $('.editing-error');
+            this.errorSection.hide();
 
             // Start validation on the form.
             $('#page-edit').validate({
@@ -493,9 +472,9 @@
             });
         },
         events: {
-            "mousedown #wmd-input-grip": "_inputGripMouseDown",
-            "click #wmd-preview-button": "_togglePreview",
-            "click #wmd-full-preview-button": "_toggleFullPreview",
+            "mousedown #editing-input-grip": "_inputGripMouseDown",
+            "click #editing-preview-button": "_togglePreview",
+            "click #editing-cancel-button": "_cancelEdit",
             "submit #page-edit": "_submitEditedPage"
         },
         _inputGripMouseDown: function(e) {
@@ -504,9 +483,8 @@
             var last_pageY = e.pageY;
             $('body')
                 .on('mousemove.wikked.editor_resize', function(e) {
-                    var editor_control = $view._ctrlInput;
-                    editor_control.height(editor_control.height() + e.pageY - last_pageY);
-                    $view._ctrlPreview.height(editor_control.height());
+                    var ctrl = $view.inputCtrl;
+                    ctrl.height(ctrl.height() + e.pageY - last_pageY);
                     last_pageY = e.pageY;
                 })
                 .on('mouseup.wikked.editor_resize mouseleave.wikked.editor_resize', function(e) {
@@ -514,62 +492,50 @@
                 });
         },
         _togglePreview: function(e) {
-            // Show/hide live preview.
-            var w = $('body').width() - 40;
-            if (this._isPreviewVisible) {
-                this._removePreview();
-            } else {
-                this._addPreview();
+            e.preventDefault();
+
+            if (this.previewSection.is(':visible')) {
+                // Hide the preview, restore the textbox.
+                this.inputSection.show();
+                this.previewSection.hide();
+                this.previewButtonLabel.html("Preview");
+                return;
             }
-            this._isPreviewVisible = !this._isPreviewVisible;
-            e.preventDefault();
-            return false;
-        },
-        _addPreview: function() {
-            $('article').addClass('pure-g');
-            $('.header-wrapper>header').addClass('pure-u-1');
-            $('.editing-wrapper>.editing').addClass('pure-u-1 pure-u-md-1-2');
-            $('.editing-wrapper>.preview').addClass('pure-u-1 pure-u-md-1-2').show();
-        },
-        _removePreview: function() {
-            $('article').removeClass('pure-g');
-            $('.header-wrapper>header').removeClass('pure-u-1');
-            $('.editing-wrapper>.editing').removeClass('pure-u-1 pure-u-md-1-2');
-            $('.editing-wrapper>.preview').removeClass('pure-u-1 pure-u-md-1-2').hide();
-        },
-        _toggleFullPreview: function(e) {
+
+            // Get the server to compute the preview text, hide the textbox,
+            // show the rendered text.
             var $view = this;
             var previewData = {
                 url: this.model.get('path'),
-                text: $('#wmd-input').val()
+                text: this.inputCtrl.val()
             };
             $.post('/api/preview', previewData)
                 .success(function(data) {
-                    var previewEl = $('#wmd-preview');
-                    previewEl.html(data.text);
-                    processWikiLinks(previewEl);
-                    $view._updateInputFromPreview();
+                    var el = $view.previewSection;
+                    el.html(data.text);
+                    processWikiLinks(el);
+                    el.show();
+                    $view.inputSection.hide();
+                    $view.previewButtonLabel.html("Edit");
+                    $view.errorSection.hide();
                 })
                 .error(function() {
-                    $('#wmd-preview').html("Error running preview.");
+                    $('.editing-error-message').html("Error running preview.");
+                    $view.errorSection.show();
                 });
-            e.preventDefault();
             return false;
         },
-        _updateInputFromPreview: function() {
-            if (this._isPreviewVisible)
-                this._ctrlInput.height(this._ctrlPreview.height());
-        },
-        _updatePreviewFromInput: function() {
-            if (this._isPreviewVisible)
-                this._ctrlPreview.height(this._ctrlInput.height());
-        },
         _submitEditedPage: function(e) {
             // Make the model submit the form.
             e.preventDefault();
             this.model.doEdit(e.currentTarget);
             return false;
         },
+        _cancelEdit: function(e) {
+            e.preventDefault();
+            this.model.doCancel();
+            return false;
+        },
         titleFormat: function(title) {
             return 'Editing: ' + title;
         }
--- a/wikked/assets/tpl/edit-page.html	Fri Sep 26 07:53:23 2014 -0700
+++ b/wikked/assets/tpl/edit-page.html	Fri Sep 26 07:58:39 2014 -0700
@@ -12,31 +12,23 @@
                         <span for="title">You can put this page in a folder by entering a title like <code>Folder/Page Title</code>.</span>
                     </div>
                     {{else}}
-                    <h1>{{meta.title}}<h1>
+                    <h1>{{meta.title}}</h1>
                     <div class="decorator">Editing</div>
                     {{/if}}
                 </header>
             </div>
             <div class="editing-wrapper">
                 <div class="editing">
-                    <section id="wmd-button-bar-wrapper" class="pure-g">
-                        <div id="wmd-button-bar" class="pure-u-4-5"></div>
-                        <div id="wmd-extra-bar" class="pure-u-1-5">
-                            <ul class="wmd-button-row">
-                                <li class="wmd-button" id="wmd-preview-button" title="Toggle Preview"><span></span></li>
-                            </ul>
-                        </div>
+                    <section class="editing-error alert alert-danger">
+                        <p><strong>Error:</strong> <span class="editing-error-message"></span></p>
                     </section>
-                    {{#if error}}
-                    <section class="alert alert-danger">
-                        <p><strong>Error:</strong> {{error.message}}</p>
+                    <section class="editing-input">
+                        <textarea id="editing-input-area" name="text" placeholder="Your page's contents go here...">{{content}}</textarea>
+                        <div id="editing-input-grip"></div>
                     </section>
-                    {{/if}}
-                    <section id="wmd-input-wrapper">
-                        <textarea id="wmd-input" name="text" placeholder="Your page's contents go here...">{{content}}</textarea>
-                        <div id="wmd-input-grip"></div>
+                    <section class="editing-preview">
                     </section>
-                    <section id="wmd-meta-wrapper">
+                    <section class="editing-meta">
                         <div class="pure-control-group pure-control-addon">
                             <label for="author">Author</label>
                             <input type="text" name="author" class="form-control" placeholder="{{commit_meta.author}}"></input>
@@ -46,23 +38,14 @@
                             <input type="text" name="message" class="form-control" placeholder="{{commit_meta.desc}}" minlength="3"></input>
                         </div>
                     </section>
-                    <section id="wmd-commit-wrapper">
-                        <div class="pure-control-group" id="wmd-commit">
-                            <button type="submit" class="pure-button pure-button-primary"><i class="icon-ok icon-white"></i> Save</button>
-                            <a href="{{url_read}}?no_redirect" class="pure-button">Cancel</a>
+                    <section class="editing-submit">
+                        <div class="pure-control-group">
+                            <button type="submit" class="pure-button pure-button-primary"><span class="glyphicon glyphicon-ok"></span> Save</button>
+                            <button id="editing-preview-button" type="submit" class="pure-button"><span class="glyphicon glyphicon-eye-open"></span> <span class="editing-preview-button-label">Preview</span></button>
+                            <button id="editing-cancel-button" type="submit" class="pure-button"><span class="glyphicon glyphicon-remove"></span> Cancel</button>
                         </div>
                     </section>
                 </div>
-                <div class="preview">
-                    <section id="wmd-preview-button-bar-wrapper">
-                        <div class="pure-control-group">
-                            <button id="wmd-full-preview-button" class="pure-button" title="Run a full preview on the text, with queries and includes">Full Preview</button>
-                        </div>
-                    </section>
-                    <section id="wmd-preview-wrapper">
-                        <div id="wmd-preview"></div>
-                    </section>
-                </div>
             </div>
         </fieldset>
     </form>
--- a/wikked/assets/tpl/footer.html	Fri Sep 26 07:53:23 2014 -0700
+++ b/wikked/assets/tpl/footer.html	Fri Sep 26 07:58:39 2014 -0700
@@ -1,5 +1,6 @@
 <footer role="navigation">
     <ul>
+        <li><span class="wiki-icon"></span> Powered by <a href="http://bolt80.com/wikked/">Wikked</a></li>
         {{#each url_extras}}
         <li>{{#if icon}}<span class="glyphicon glyphicon-{{icon}}"></span> {{/if}}<a href="{{url}}">{{name}}</a></li>
         {{/each}}
--- a/wikked/assets/tpl/nav.html	Fri Sep 26 07:53:23 2014 -0700
+++ b/wikked/assets/tpl/nav.html	Fri Sep 26 07:58:39 2014 -0700
@@ -9,14 +9,21 @@
         {{#ifneq action to='edit'}}<li><a href="{{url_edit}}"><span class="glyphicon glyphicon-edit"></span> Edit</a></li>{{/ifneq}}
         {{#ifneq action to='history'}}<li><a href="{{url_hist}}"><span class="glyphicon glyphicon-road"></span> History</a></li>{{/ifneq}}
     </ul>
-    <form role="search" id="search" class="pure-form pure-menu-form">
+    <form role="search" id="search" class="pure-form pure-menu-form pure-menu-divider">
         <fieldset>
-            <button type="submit" class="pure-button"><span class="glyphicon glyphicon-search"></span></button>
+            <!--button type="submit" class="pure-button"><span class="glyphicon glyphicon-search"></span></button-->
             <input type="text" name="q" id="search-query" class="pure-input-1" placeholder="Search..." autocomplete="off"></input>
             <ul id="search-preview"></ul>
         </fieldset>
     </form>
-    <ul class="">
+    {{#if url_extras}}
+    <ul class="pure-menu-divider">
+    {{#each url_extras}}
+        <li><a href="{{url}}">{{#if icon}}<span class="glyphicon glyphicon-{{icon}}"></span> {{/if}}{{name}}</a></li>
+    {{/each}}
+    </ul>
+    {{/if}}
+    <ul class="pure-menu-divider">
         {{#if user}}
         <li><a href="{{url_profile}}"><span class="glyphicon glyphicon-cog"></span> {{user.username}}</a></li>
         <li><a href="{{url_logout}}"><span class="glyphicon glyphicon-log-out"></span> Logout</a></li>
--- a/wikked/assets/tpl/read-page.html	Fri Sep 26 07:53:23 2014 -0700
+++ b/wikked/assets/tpl/read-page.html	Fri Sep 26 07:58:39 2014 -0700
@@ -6,12 +6,12 @@
         <div class="decorator">{{meta_query}}</div>
         {{/if}}
         {{#if redirected_from}}
-        <div class="decorator-sub">Redirected from 
+        <div class="decorator"><small>Redirected from 
             {{#each redirected_from}}
             {{#ifeq @index to=0}} {{else}} | {{/ifeq}}
             <a href="{{get_read_url this}}?no_redirect">{{this}}</a>
             {{/each}}
-        </div>
+        </small></div>
         {{/if}}
         {{#if meta.redirect}}
         <small>Redirects to <a href="{{get_read_url redirects_to}}">{{redirects_to}}</a></small>