Mercurial > wikked
changeset 17:8a4e0fe2c689
Added "Special Pages" section:
- Only "orphaned" pages for now.
- Made base view/model classes more extensible.
Better way to export views and models from their module.
author | Ludovic Chabant <ludovic@chabant.com> |
---|---|
date | Tue, 01 Jan 2013 00:49:54 -0800 |
parents | 8d6c2a5ed08d |
children | 67c150d5ed53 |
files | wikked/static/css/wikked.less wikked/static/js/wikked/app.js wikked/static/js/wikked/models.js wikked/static/js/wikked/views.js wikked/static/tpl/special-nav.html wikked/static/tpl/special-orphans.html wikked/static/tpl/special-pages.html wikked/views.py |
diffstat | 8 files changed, 175 insertions(+), 59 deletions(-) [+] |
line wrap: on
line diff
--- a/wikked/static/css/wikked.less Mon Dec 31 22:02:39 2012 -0800 +++ b/wikked/static/css/wikked.less Tue Jan 01 00:49:54 2013 -0800 @@ -13,16 +13,21 @@ @colorNavLinkHover: rgb(96, 96, 96); @colorBlueDark: #48577D; -@colorBlueLight: #7690CF; +@colorBlueMedium: #7690CF; +@colorBlueLight: #D9E3FF; + @colorGrayBlueLight: #D3DCF2; @colorGrayBlueMedium: #9197A6; @colorGrayBlueDark: #43464C; + @colorGrayLight: #EEE; @colorGrayMedium: #AAA; @colorGrayDark: #666; + @colorCode: #523C37; @backgroundPage: white; +@backgroundPageSpecial: #E5D19E; // Macros .box-shadow(@style, @c) { @@ -136,6 +141,9 @@ padding: @baseLineHeight; background: @backgroundPage; } + .page.special { + background: @backgroundPageSpecial; + } .page>pre { margin-top: @baseLineHeight; @@ -192,7 +200,7 @@ } .preview-wiki-meta { .meta-name { - background: @colorBlueLight; + background: @colorBlueMedium; color: #fff; padding: 0.2em 0.4em 0.2em 0.6em; border-radius: 0.5em 0 0 0.5em;
--- a/wikked/static/js/wikked/app.js Mon Dec 31 22:02:39 2012 -0800 +++ b/wikked/static/js/wikked/app.js Tue Jan 01 00:49:54 2013 -0800 @@ -25,7 +25,9 @@ 'diff/r/*path/:rev1/:rev2':"showDiff", 'search/:query': "showSearchResults", 'login': "showLogin", - 'logout': "doLogout" + 'logout': "doLogout", + 'special': "showSpecialPages", + 'special/:page': "showSpecialPage" }, readPage: function(path) { var view = new Views.PageReadView({ @@ -127,6 +129,23 @@ alert("Error logging out!"); }); }, + showSpecialPages: function() { + var view = new Views.SpecialPagesView({ + el: $('#app'), + model: new Models.SpecialPagesModel() + }); + view.model.setApp(this); + this.navigate('/special'); + }, + showSpecialPage: function(page) { + var view = new Views.GenericSpecialPageView({ + el: $('#app'), + model: new Models.GenericSpecialPageModel({ page: page }) + }); + view.model.setApp(this); + view.model.fetch(); + this.navigate('/special/' + page); + }, getQueryVariable: function(variable) { var query = window.location.search.substring(1); var vars = query.split("&");
--- a/wikked/static/js/wikked/models.js Mon Dec 31 22:02:39 2012 -0800 +++ b/wikked/static/js/wikked/models.js Tue Jan 01 00:49:54 2013 -0800 @@ -10,7 +10,9 @@ ], function(require, $, _, Backbone, Handlebars) { - var NavigationModel = Backbone.Model.extend({ + var exports = {}; + + var NavigationModel = exports.NavigationModel = Backbone.Model.extend({ idAttribute: 'path', defaults: function() { return { @@ -69,12 +71,18 @@ } }); - var FooterModel = Backbone.Model.extend({ + var FooterModel = exports.FooterModel = Backbone.Model.extend({ defaults: function() { return { - url_extras: [ { name: 'Home', url: '/' } ] + url_extras: [ + { name: 'Home', url: '/' }, + { name: 'Special Pages', url: '/#/special' } + ] }; }, + clearExtraUrls: function() { + this.get('url_extras').length = 0; + }, addExtraUrl: function(name, url, index) { if (index === undefined) { this.get('url_extras').push({ name: name, url: url }); @@ -84,7 +92,7 @@ } }); - var LoginModel = Backbone.Model.extend({ + var LoginModel = exports.LoginModel = Backbone.Model.extend({ setApp: function(app) { this.app = app; }, @@ -100,7 +108,7 @@ } }); - var PageModel = Backbone.Model.extend({ + var PageModel = exports.PageModel = Backbone.Model.extend({ idAttribute: 'path', defaults: function() { return { @@ -146,11 +154,11 @@ } }); - var PageStateModel = PageModel.extend({ + var PageStateModel = exports.PageStateModel = PageModel.extend({ urlRoot: '/api/state/' }); - var MasterPageModel = PageModel.extend({ + var MasterPageModel = exports.MasterPageModel = PageModel.extend({ initialize: function() { this.nav = new NavigationModel({ id: this.id }); this.footer = new FooterModel(); @@ -177,7 +185,7 @@ } }); - var PageReadModel = MasterPageModel.extend({ + var PageReadModel = exports.PageReadModel = MasterPageModel.extend({ urlRoot: '/api/read/', action: 'read', _onChangePath: function(path) { @@ -187,12 +195,12 @@ } }); - var PageSourceModel = MasterPageModel.extend({ + var PageSourceModel = exports.PageSourceModel = MasterPageModel.extend({ urlRoot: '/api/raw/', action: 'source' }); - var PageEditModel = MasterPageModel.extend({ + var PageEditModel = exports.PageEditModel = MasterPageModel.extend({ urlRoot: '/api/edit/', action: 'edit', doEdit: function(form) { @@ -208,7 +216,7 @@ } }); - var PageHistoryModel = MasterPageModel.extend({ + var PageHistoryModel = exports.PageHistoryModel = MasterPageModel.extend({ urlRoot: '/api/history/', action: 'history', doDiff: function(form) { @@ -224,7 +232,7 @@ } }); - var PageRevisionModel = MasterPageModel.extend({ + var PageRevisionModel = exports.PageRevisionModel = MasterPageModel.extend({ urlRoot: '/api/revision/', idAttribute: 'path_and_rev', action: 'revision', @@ -254,7 +262,7 @@ } }); - var PageDiffModel = MasterPageModel.extend({ + var PageDiffModel = exports.PageDiffModel = MasterPageModel.extend({ urlRoot: '/api/diff/', idAttribute: 'path_and_revs', action: 'diff', @@ -295,12 +303,12 @@ } }); - var IncomingLinksModel = MasterPageModel.extend({ + var IncomingLinksModel = exports.IncomingLinksModel = MasterPageModel.extend({ urlRoot: '/api/inlinks/', action: 'inlinks' }); - var WikiSearchModel = MasterPageModel.extend({ + var WikiSearchModel = exports.WikiSearchModel = MasterPageModel.extend({ urlRoot: '/api/search/', action: 'search', title: function() { @@ -318,18 +326,27 @@ } }); - return { - NavigationModel: NavigationModel, - FooterModel: FooterModel, - PageReadModel: PageReadModel, - PageEditModel: PageEditModel, - PageHistoryModel: PageHistoryModel, - IncomingLinksModel: IncomingLinksModel, - PageRevisionModel: PageRevisionModel, - PageDiffModel: PageDiffModel, - WikiSearchModel: WikiSearchModel, - LoginModel: LoginModel, - PageStateModel: PageStateModel - }; + var SpecialPagesModel = exports.SpecialPagesModel = MasterPageModel.extend({ + action: 'special', + title: function() { + return 'Special Pages'; + }, + initialize: function() { + SpecialPagesModel.__super__.initialize.apply(this, arguments); + this.footer.clearExtraUrls(); + } + }); + + var GenericSpecialPageModel = exports.GenericSpecialPageModel = MasterPageModel.extend({ + action: 'special', + urlRoot: '/api/special', + idAttribute: 'page', + initialize: function() { + GenericSpecialPageModel.__super__.initialize.apply(this, arguments); + this.footer.clearExtraUrls(); + } + }); + + return exports; });
--- a/wikked/static/js/wikked/views.js Mon Dec 31 22:02:39 2012 -0800 +++ b/wikked/static/js/wikked/views.js Tue Jan 01 00:49:54 2013 -0800 @@ -11,18 +11,22 @@ ], function($, _, Backbone, Handlebars, Models, Util) { - var PageView = Backbone.View.extend({ + var exports = {}; + + var PageView = exports.PageView = Backbone.View.extend({ tagName: 'div', className: 'wrapper', initialize: function() { PageView.__super__.initialize.apply(this, arguments); - var $view = this; - this.model.on("change", function() { $view.render(); }); + if (this.model !== undefined) { + var $view = this; + this.model.on("change", function() { $view.render(); }); + } return this; }, render: function(view) { if (this.templateName !== undefined) { - this.renderTemplate(this.templateName, this.renderCallback); + this.renderTemplate(_.result(this, 'templateName'), this.renderCallback); } this.renderTitle(this.titleFormat); return this; @@ -47,7 +51,7 @@ }); _.extend(PageView, Backbone.Events); - var NavigationView = PageView.extend({ + var NavigationView = exports.NavigationView = PageView.extend({ templateName: 'nav', initialize: function() { NavigationView.__super__.initialize.apply(this, arguments); @@ -55,7 +59,7 @@ return this; }, render: function() { - this.renderTemplate('nav'); + this.renderTemplate(this.templateName); }, postRender: function() { var model = this.model; @@ -106,7 +110,7 @@ } }); - var FooterView = PageView.extend({ + var FooterView = exports.FooterView = PageView.extend({ templateName: 'footer', initialize: function() { FooterView.__super__.initialize.apply(this, arguments); @@ -120,7 +124,7 @@ } }); - var LoginView = PageView.extend({ + var LoginView = exports.LoginView = PageView.extend({ templateName: 'login', initialize: function() { LoginView.__super__.initialize.apply(this, arguments); @@ -139,11 +143,11 @@ } }); - var MasterPageView = PageView.extend({ + var MasterPageView = exports.MasterPageView = PageView.extend({ initialize: function() { MasterPageView.__super__.initialize.apply(this, arguments); - this.nav = new NavigationView({ model: this.model.nav }); - this.footer = new FooterView({ model: this.model.footer }); + this.nav = this._createNavigation(this.model.nav); + this.footer = this._createFooter(this.model.footer); this.render(); return this; }, @@ -152,10 +156,16 @@ this.nav.postRender(); this.footer.$el.appendTo(this.$el); this.footer.postRender(); + }, + _createNavigation: function(model) { + return new NavigationView({ model: model }); + }, + _createFooter: function(model) { + return new FooterView({ model: model }); } }); - var PageReadView = MasterPageView.extend({ + var PageReadView = exports.PageReadView = MasterPageView.extend({ templateName: 'read-page', initialize: function() { PageReadView.__super__.initialize.apply(this, arguments); @@ -195,7 +205,7 @@ } }); - var PageEditView = MasterPageView.extend({ + var PageEditView = exports.PageEditView = MasterPageView.extend({ templateName: 'edit-page', renderCallback: function(view, model) { PageEditView.__super__.renderCallback.apply(this, arguments); @@ -210,7 +220,7 @@ } }); - var PageHistoryView = MasterPageView.extend({ + var PageHistoryView = exports.PageHistoryView = MasterPageView.extend({ templateName: 'history-page', renderCallback: function(view, model) { PageHistoryView.__super__.renderCallback.apply(this, arguments); @@ -225,40 +235,53 @@ } }); - var PageRevisionView = MasterPageView.extend({ + var PageRevisionView = exports.PageRevisionView = MasterPageView.extend({ templateName: 'revision-page', titleFormat: function(title) { return title + ' [' + this.model.get('rev') + ']'; } }); - var PageDiffView = MasterPageView.extend({ + var PageDiffView = exports.PageDiffView = MasterPageView.extend({ templateName: 'diff-page', titleFormat: function(title) { return title + ' [' + this.model.get('rev1') + '-' + this.model.get('rev2') + ']'; } }); - var IncomingLinksView = MasterPageView.extend({ + var IncomingLinksView = exports.IncomingLinksView = MasterPageView.extend({ templateName: 'inlinks-page', titleFormat: function(title) { return 'Incoming Links: ' + title; } }); - var WikiSearchView = MasterPageView.extend({ + var WikiSearchView = exports.WikiSearchView = MasterPageView.extend({ templateName: 'search-results' }); - return { - PageReadView: PageReadView, - PageEditView: PageEditView, - PageHistoryView: PageHistoryView, - IncomingLinksView: IncomingLinksView, - PageRevisionView: PageRevisionView, - PageDiffView: PageDiffView, - WikiSearchView: WikiSearchView, - LoginView: LoginView - }; + var SpecialNavigationView = exports.SpecialNavigationView = NavigationView.extend({ + templateName: 'special-nav' + }); + + var SpecialPagesView = exports.SpecialPagesView = MasterPageView.extend({ + templateName: 'special-pages', + _createNavigation: function(model) { + model.set('show_root_link', false); + return new SpecialNavigationView({ model: model }); + } + }); + + var GenericSpecialPageView = exports.GenericSpecialPageView = MasterPageView.extend({ + templateName: function() { + return 'special-' + this.model.get('page'); + }, + _createNavigation: function(model) { + model.set('show_root_link', true); + return new SpecialNavigationView({ model: model }); + } + }); + + return exports; });
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wikked/static/tpl/special-nav.html Tue Jan 01 00:49:54 2013 -0800 @@ -0,0 +1,18 @@ +<nav class="row"> + <div class="span12"> + <a href="/">Home</a> + {{#if show_root_link}} + <a href="/#/special">Special Pages</a> + {{/if}} + <form id="search" class="search"> + <input type="text" name="q" class="input-medium search-query" placeholder="Search..."> + <button type="submit" class="btn">Search</button> + </form> + {{#if username}} + <a href="{{url_profile}}">{{username}}</a> + <a href="{{url_logout}}">Logout</a> + {{else}} + <a href="{{url_login}}">Login</a> + {{/if}} + </div> +</nav>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wikked/static/tpl/special-orphans.html Tue Jan 01 00:49:54 2013 -0800 @@ -0,0 +1,14 @@ +<article class="row"> + <div class="page special span12"> + <h1>Orphaned Pages</h1> + <p>The following pages are not linked to by any other page in the wiki.</p> + <p><span class="label label-info">Note</span> The main page can occasionally show up here but that's OK since it's the page visitors will see first anyway.</p> + {{#if orphans}} + {{#each orphans}} + <h3><a href="/#/read/{{meta.url}}">{{meta.title}}</a></h3> + {{/each}} + {{else}} + <p>No orphaned pages!</p> + {{/if}} + </div> +</article>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wikked/static/tpl/special-pages.html Tue Jan 01 00:49:54 2013 -0800 @@ -0,0 +1,7 @@ +<article class="row"> + <div class="page special span12"> + <h1>Special Pages</h1> + <h3><a href="/#/special/orphans">Orphaned Pages</a></h3> + <p>Lists pages in the wiki that have no links to them.</p> + </div> +</article>
--- a/wikked/views.py Mon Dec 31 22:02:39 2012 -0800 +++ b/wikked/views.py Tue Jan 01 00:49:54 2013 -0800 @@ -209,6 +209,16 @@ pass +@app.route('/api/special/orphans') +def api_special_orphans(): + orphans = [] + for page in wiki.getPages(): + if len(page.in_links) == 0: + orphans.append({ 'path': page.url, 'meta': page.all_meta }) + result = { 'orphans': orphans } + return make_auth_response(result) + + @app.route('/api/history/<path:url>') def api_page_history(url): page = get_page_or_404(url)