--- a/mouchak/server.py +++ b/mouchak/server.py @@ -50,7 +50,15 @@ 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,9 +76,20 @@ 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): return '.' in filename and \ filename.rsplit('.', 1)[1] in PLUGIN_ALLOWED_EXTENSIONS @@ -84,13 +103,14 @@ @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 @@ 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 @@ 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 @@ @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) @@ -168,6 +188,35 @@ return flask.jsonify(status='ok') else: 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']) --- a/mouchak/static/css/editor.css +++ b/mouchak/static/css/editor.css @@ -83,7 +83,7 @@ width: 100%; height: 300px; } -#updateMenu { +.update-btn { margin-top: 10px; } #editor-overlay { --- 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,9 +94,14 @@ }, 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 validate: function() { //TODO: validate if the menu order list matches with the list of pages @@ -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 */ --- 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, --- a/mouchak/static/js/mouchak.js +++ b/mouchak/static/js/mouchak.js @@ -38,9 +38,9 @@ }, 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 @@ } // 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 @@ 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 @@ else { $('#navigation').show(); } - M.appView.navView.trigger('navclicked'); + //console.log('navclicked'); + M.appView.navView.trigger('navclicked'); }, render404: function() { $('.pageview').hide(); @@ -180,9 +184,11 @@ 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(); }; --- 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,12 +102,38 @@
- +
+ + + +