From 9fa0b565383754d62fd01d080312f65326fa96a5 Mon Sep 17 00:00:00 2001 From: Anon Ray Date: Thu, 16 Jan 2014 14:00:09 +0530 Subject: [PATCH] Add Header and Footer config in the editor Now header and footer can be added from the Mouchak editor directly (via HTML) --- mouchak/server.py | 61 ++++++++++++++++++++++++--- mouchak/static/css/editor.css | 2 +- mouchak/static/js/editor.js | 92 ++++++++++++++++++++++++++++++++++++++++- mouchak/static/js/models.js | 26 ++++++++++++ mouchak/static/js/mouchak.js | 16 ++++--- mouchak/templates/editor.html | 31 +++++++++++++- mouchak/templates/index.html | 5 ++- setup.py | 4 +- 8 files changed, 219 insertions(+), 18 deletions(-) diff --git a/mouchak/server.py b/mouchak/server.py index 57c233b..22b65f3 100644 --- a/mouchak/server.py +++ b/mouchak/server.py @@ -50,6 +50,14 @@ siteMenu = db['menu'] if siteMenu.find_one() == None: siteMenu.insert({'customMenu': False, 'menuOrder': [], 'html': ''}) +siteFooter = db['footer'] +if siteFooter.find_one() == None: + siteFooter.insert({'html': ''}) + +siteHeader = db['header'] +if siteHeader.find_one() == None: + siteHeader.insert({'html': ''}) + # handy reference to otherwise long name bson.ObjId = bson.objectid.ObjectId @@ -68,7 +76,18 @@ def getContent(): del(menu['_id']) menu['id'] = str(objId) - return {'content': content, 'menu': menu} + footer = siteFooter.find_one() + objId = bson.ObjId(footer['_id']) + del(footer['_id']) + footer['id'] = str(objId) + + header = siteHeader.find_one() + objId = bson.ObjId(header['_id']) + del(header['_id']) + header['id'] = str(objId) + + return {'content': content, 'menu': menu, 'footer': footer, 'header': + header} def allowed_file(filename): @@ -84,13 +103,14 @@ def pageNotFound(e): @app.route('/', methods=['GET']) def index(): return flask.render_template('index.html', content=getContent(), - title=conf.SITE_TITLE, footer=conf.SITE_FOOTER) + title=conf.SITE_TITLE) @app.route('/edit', methods=['GET']) def edit(): if "logged_in" in flask.session: flask.session['key'] = conf.SECRET_KEY + #print getContent() return flask.render_template('editor.html', content=getContent(), title=conf.SITE_TITLE) else: @@ -111,7 +131,7 @@ def listPages(): for page in siteContent.find().sort('_id', 1)[offset:offset+limit]: del(page['_id']) content.append(page) - print len(content) + #print len(content) return flask.make_response(json.dumps(content), '200 OK', {'Content-Type': 'application/json'}) else: @@ -124,7 +144,7 @@ def listPage(_id): try: page = siteContent.find_one({'_id': bson.ObjId(_id)}) del(page['_id']) - print page + #print page return flask.jsonify(page) except: return flask.abort(404) @@ -133,12 +153,12 @@ def listPage(_id): @app.route('/page', methods=['POST']) def insertPage(): newpage = flask.request.json - print newpage + #print newpage res = siteContent.insert(newpage) _id = bson.ObjId(res) newpage['id'] = str(_id) del(newpage['_id']) - print newpage + #print newpage # FIXME: handle errors #return flask.jsonify(status='ok', page=newpage) return flask.jsonify(newpage) @@ -170,6 +190,35 @@ def updatePage(_id): return flask.jsonify(error=res['err'], status='error') +@app.route('/footer', methods=['POST']) +def insertFooter(): + return '200 OK' + +@app.route('/footer/<_id>', methods=['PUT']) +def updateFooter(_id): + if flask.request.method == 'PUT': + changedFooter = flask.request.json + print "changed footer:" + print changedFooter + res = siteFooter.update({'_id': bson.ObjId(_id)}, changedFooter) + print res + return flask.jsonify(changedFooter) + +@app.route('/header', methods=['POST']) +def insertHeader(): + return '200 OK' + +@app.route('/header/<_id>', methods=['PUT']) +def updateHeader(_id): + if flask.request.method == 'PUT': + changedHeader = flask.request.json + print "changed header:" + print changedHeader + res = siteHeader.update({'_id': bson.ObjId(_id)}, changedHeader) + print res + return flask.jsonify(changedHeader) + + @app.route('/menu', methods=['POST']) def insertMenu(): #newmenu = flask.request.json diff --git a/mouchak/static/css/editor.css b/mouchak/static/css/editor.css index 1bcc1b4..e06e2a5 100644 --- a/mouchak/static/css/editor.css +++ b/mouchak/static/css/editor.css @@ -83,7 +83,7 @@ body { width: 100%; height: 300px; } -#updateMenu { +.update-btn { margin-top: 10px; } #editor-overlay { diff --git a/mouchak/static/js/editor.js b/mouchak/static/js/editor.js index 3876cf1..ca6ab8c 100644 --- a/mouchak/static/js/editor.js +++ b/mouchak/static/js/editor.js @@ -10,7 +10,8 @@ 'click #addPage': 'addPage', 'click .pagename .remove': 'removePage', 'click #menu-config': 'showMenu', - 'click #footer-config': 'showFooterConfig' + 'click #footer-config': 'showFooterConfig', + 'click #header-config': 'showHeaderConfig' }, initialize: function() { _.bindAll.apply(_, [this].concat(_.functions(this))); @@ -25,6 +26,10 @@ //console.log(menu); this.menuconfig = new M.types.model.menu(menu); this.menuconfigview = new MenuConfigView({model: this.menuconfig}); + this.footerconfig = new M.types.model.footer(M.site_content.footer); + this.footerconfigview = new FooterConfigView({model: this.footerconfig}); + this.headerconfig = new M.types.model.header(M.site_content.header); + this.headerconfigview = new HeaderConfigView({model: this.headerconfig}); }, render: function() { // append the page list @@ -89,7 +94,12 @@ }, showFooterConfig: function(event) { event.preventDefault(); - //this.footerconfigview.render(); + this.footerconfigview.render(); + return false; + }, + showHeaderConfig: function(event) { + event.preventDefault(); + this.headerconfigview.render(); return false; }, // validate the page list with menu order list @@ -551,6 +561,84 @@ /* Footer Config View */ var FooterConfigView = Backbone.View.extend({ + tagName: 'div', + className: 'prettybox-lg', + id: 'page', + events: { + 'click #updateFooter': 'saveFooter' + }, + initialize: function() { + _.bindAll.apply(_, [this].concat(_.functions(this))); + this.template = _.template($('#footer-config-template').html()); + }, + render: function() { + $('#page').remove(); + $('#content-container').append(this.$el); + //console.log('rendering..', this.$el); + this.$el.html(this.template({ + footer: this.model.get('html') + })); + M.editor.code.init('footer-input', 'html'); + }, + saveFooter: function() { + var html = M.editor.code.save('footer-input'); + this.model.set({html: html}); + this.model.save({}, { + success: function(model, response) { + //console.log(model, response); + M.editor.hideOverlay(); + M.editor.notifs.show('success', 'Saved', ''); + + }, + error: function(xhr, response) { + M.editor.hideOverlay(); + var msg = 'Something went wrong, and the page could not be updated'; + M.editor.notifs.show('fail', 'Error!', msg); + } + }); + M.editor.showOverlay(); + } + }); + + /* Header Config View */ + var HeaderConfigView = Backbone.View.extend({ + tagName: 'div', + className: 'prettybox-lg', + id: 'page', + events: { + 'click #updateHeader': 'saveHeader' + }, + initialize: function() { + _.bindAll.apply(_, [this].concat(_.functions(this))); + this.template = _.template($('#header-config-template').html()); + }, + render: function() { + $('#page').remove(); + $('#content-container').append(this.$el); + //console.log('rendering..', this.$el); + this.$el.html(this.template({ + header: this.model.get('html') + })); + M.editor.code.init('header-input', 'html'); + }, + saveHeader: function() { + var html = M.editor.code.save('header-input'); + this.model.set({html: html}); + this.model.save({}, { + success: function(model, response) { + //console.log(model, response); + M.editor.hideOverlay(); + M.editor.notifs.show('success', 'Saved', ''); + + }, + error: function(xhr, response) { + M.editor.hideOverlay(); + var msg = 'Something went wrong, and the page could not be updated'; + M.editor.notifs.show('fail', 'Error!', msg); + } + }); + M.editor.showOverlay(); + } }); /* Notification view */ diff --git a/mouchak/static/js/models.js b/mouchak/static/js/models.js index b1f26cf..8984920 100644 --- a/mouchak/static/js/models.js +++ b/mouchak/static/js/models.js @@ -169,6 +169,30 @@ }, }); + var Footer = Backbone.Model.extend({ + defaults: { + html: '' + }, + url: function() { + return M.FooterURL() + '/' + this.id; + }, + initialize: function() { + this.id = this.get('id'); + } + }); + + var Header = Backbone.Model.extend({ + defaults: { + html: '' + }, + url: function() { + return M.HeaderURL() + '/' + this.id; + }, + initialize: function() { + this.id = this.get('id'); + } + }); + //export types to the typemap M.types = M.types || {}; M.types.model = { @@ -177,6 +201,8 @@ 'image': Image, 'video': Video, 'menu': Menu, + 'footer': Footer, + 'header': Header, 'rss': RSS, 'table': Table, 'plugin': Plugin, diff --git a/mouchak/static/js/mouchak.js b/mouchak/static/js/mouchak.js index 10164ca..16c7b29 100644 --- a/mouchak/static/js/mouchak.js +++ b/mouchak/static/js/mouchak.js @@ -38,9 +38,9 @@ var NavigationView = Backbone.View.extend({ }, render: function() { // if custom menu is not defined, render a default menu - console.log(this.model.toJSON()); + //console.log(this.model.toJSON()); if(this.model.get('customMenu') === false) { - console.log('generating default menu..'); + //console.log('generating default menu..'); var startpage = M.site_content.menu.menuOrder[0]; this.$el.append(this.template({ brand: document.title,//brand name, @@ -51,7 +51,7 @@ var NavigationView = Backbone.View.extend({ } // else render the custom menu else { - console.log('rendering custom menu..'); + //console.log('rendering custom menu..'); this.$el.append(this.model.get('html')); } this.$links = $('.nav li'); @@ -86,13 +86,16 @@ var NavigationView = Backbone.View.extend({ if(!event) { var fragment = location.hash.split('/')[1]; //var pos = _.indexOf(M.pages.models, M.pages.where({'name': fragment})[0]); + //console.log(fragment); var pos = _.indexOf(this.model.get('menuOrder'), fragment); + //console.log(pos); if(!fragment) { pos = 0; } $(this.$links[pos]).addClass('active'); } else { + //console.log(); $(event.currentTarget).parent().addClass('active'); } } @@ -122,7 +125,8 @@ var AppRouter = Backbone.Router.extend({ else { $('#navigation').show(); } - M.appView.navView.trigger('navclicked'); + //console.log('navclicked'); + M.appView.navView.trigger('navclicked'); }, render404: function() { $('.pageview').hide(); @@ -180,9 +184,11 @@ M.init = function() { Backbone.history.start(); if(!window.location.hash) { - var startpage = M.site_content.menu.menuOrder[0]; + var startpage = '#/' + M.site_content.menu.menuOrder[0]; + //console.log(startpage); app_router.navigate(startpage, {trigger: true}); } + M.app_router = app_router; //M.simHeir(); }; diff --git a/mouchak/templates/editor.html b/mouchak/templates/editor.html index f1fea45..f6c0385 100644 --- a/mouchak/templates/editor.html +++ b/mouchak/templates/editor.html @@ -22,6 +22,8 @@ // initialize editor window.M = window.M || {}; M.MenuURL = function() { return "{{ url_for('insertMenu') }}"; }; + M.FooterURL = function() { return "{{ url_for('insertFooter') }}"; }; + M.HeaderURL = function() { return "{{ url_for('insertHeader') }}"; }; M.PageURL = function() { return "{{ url_for('insertPage') }}"; }; M.PluginUploadURL = function() { return "{{ url_for('uploadPlugin') }}"; }; M.site_content = {{ content|tojson|safe }}; @@ -100,7 +102,33 @@
- + +
+
+ + + + + +