Commit 1d593744cace6fa44757c77b06803b5738707889
- Diff rendering mode:
- inline
- side by side
mouchak/server.py
(41 / 3)
  | |||
34 | 34 | ||
35 | 35 | PLUGIN_UPLOAD_FOLDER = os.path.join(os.path.dirname(os.path.abspath(__file__)) | |
36 | 36 | + '/static/user_plugins') | |
37 | PLUGIN_ALLOWED_EXTENSIONS = set(['js', 'css']) | ||
38 | 37 | ||
38 | ALLOWED_EXTENSIONS = set(['js', 'css', 'jpg', 'JPG', 'png', 'gif', 'PNG', | ||
39 | 'svg', 'pdf']) | ||
40 | #ALLOWED_EXTENSIONS = set(['js', 'css']) | ||
41 | |||
39 | 42 | FILE_UPLOAD_FOLDER = os.path.join(os.path.dirname(os.path.abspath(__file__)) + | |
40 | 43 | '/static/uploads') | |
41 | 44 | ||
… | … | ||
95 | 95 | ||
96 | 96 | def allowed_file(filename): | |
97 | 97 | return '.' in filename and \ | |
98 | filename.rsplit('.', 1)[1] in PLUGIN_ALLOWED_EXTENSIONS | ||
98 | filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS | ||
99 | 99 | ||
100 | 100 | ||
101 | 101 | @app.errorhandler(404) | |
… | … | ||
302 | 302 | #return flask.redirect(flask.url_for('uploaded_file', | |
303 | 303 | # filename=filename)) | |
304 | 304 | return flask.jsonify(uploaded = True, | |
305 | path=flask.url_for('static', filename = | ||
305 | path=flask.url_for('static', filename =\ | ||
306 | 306 | 'user_plugins/'+ filename)) | |
307 | 307 | ||
308 | @app.route('/upload', methods=['GET', 'POST']) | ||
309 | def upload(): | ||
310 | if flask.request.method == 'POST': | ||
311 | print flask.request.files | ||
312 | file = flask.request.files['upload-file'] | ||
313 | if file and allowed_file(file.filename): | ||
314 | print 'file ok' | ||
315 | filename = secure_filename(file.filename) | ||
316 | file.save(os.path.join(app.config['FILE_UPLOAD_FOLDER'], filename)) | ||
317 | |||
318 | return flask.jsonify(uploaded = True, path =\ | ||
319 | flask.url_for('static', filename =\ | ||
320 | 'uploads/' + filename)) | ||
321 | |||
322 | else: | ||
323 | resp = flask.make_response() | ||
324 | print 'file not ok' | ||
325 | resp.status_code = 400 | ||
326 | return resp | ||
327 | |||
328 | if flask.request.method == 'GET': | ||
329 | uploaded_files = os.listdir(app.config['FILE_UPLOAD_FOLDER']) | ||
330 | print uploaded_files | ||
331 | return flask.jsonify({'uploaded_files': uploaded_files}) | ||
332 | |||
333 | @app.route('/upload/<filename>', methods=['DELETE']) | ||
334 | def removeFile(filename): | ||
335 | filepath = os.path.join(app.config['FILE_UPLOAD_FOLDER'], filename) | ||
336 | print filepath | ||
337 | res = os.remove(filepath) | ||
338 | print res | ||
339 | return '200 OK' | ||
340 | |||
341 | |||
308 | 342 | @app.route('/robots.txt') | |
309 | 343 | @app.route('/crossdomain.xml') | |
310 | 344 | def static_from_root(): | |
… | … | ||
347 | 347 | ||
348 | 348 | app.config.from_object(conf) | |
349 | 349 | app.config['PLUGIN_UPLOAD_FOLDER'] = PLUGIN_UPLOAD_FOLDER | |
350 | app.config['FILE_UPLOAD_FOLDER'] = FILE_UPLOAD_FOLDER | ||
350 | 351 | ||
351 | 352 | import logging,os | |
352 | 353 | from logging import FileHandler |
mouchak/static/js/editor.js
(99 / 1)
  | |||
11 | 11 | 'click .pagename .remove': 'removePage', | |
12 | 12 | 'click #menu-config': 'showMenu', | |
13 | 13 | 'click #footer-config': 'showFooterConfig', | |
14 | 'click #header-config': 'showHeaderConfig' | ||
14 | 'click #header-config': 'showHeaderConfig', | ||
15 | 'click #uploads': 'uploads' | ||
15 | 16 | }, | |
16 | 17 | initialize: function() { | |
17 | 18 | _.bindAll.apply(_, [this].concat(_.functions(this))); | |
… | … | ||
31 | 31 | this.footerconfigview = new FooterConfigView({model: this.footerconfig}); | |
32 | 32 | this.headerconfig = new M.types.model.header(M.site_content.header); | |
33 | 33 | this.headerconfigview = new HeaderConfigView({model: this.headerconfig}); | |
34 | this.uploadview = new UploadView(); | ||
34 | 35 | }, | |
35 | 36 | render: function() { | |
36 | 37 | // append the page list | |
… | … | ||
104 | 104 | this.headerconfigview.render(); | |
105 | 105 | return false; | |
106 | 106 | }, | |
107 | uploads: function(event) { | ||
108 | event.preventDefault(); | ||
109 | this.uploadview.render(); | ||
110 | return false; | ||
111 | }, | ||
107 | 112 | // validate the page list with menu order list | |
108 | 113 | validate: function() { | |
109 | 114 | //TODO: validate if the menu order list matches with the list of pages | |
… | … | ||
676 | 676 | ' will be rendered'+ | |
677 | 677 | '\n@delay: (optional) a delay time, after which the notification'+ | |
678 | 678 | ' will be hidden'; | |
679 | } | ||
680 | }); | ||
681 | |||
682 | /* Upload View */ | ||
683 | var UploadView = Backbone.View.extend({ | ||
684 | tagName: 'div', | ||
685 | className: 'prettybox-lg', | ||
686 | id: 'page', | ||
687 | events: { | ||
688 | 'click #upload-new-file': 'uploadFile', | ||
689 | 'click .uploaded-item .remove': 'removeFile' | ||
690 | }, | ||
691 | initialize: function() { | ||
692 | _.bindAll.apply(_, [this].concat(_.functions(this))); | ||
693 | this.template = _.template($('#uploads-template').html()); | ||
694 | }, | ||
695 | render: function() { | ||
696 | $('#page').remove(); | ||
697 | $('#content-container').append(this.$el); | ||
698 | //console.log('rendering..', this.$el); | ||
699 | var uploaded_files, self = this; | ||
700 | M.editor.showOverlay(); | ||
701 | $.ajax({ | ||
702 | url: '/upload', | ||
703 | type: 'GET', | ||
704 | success: function(data) { | ||
705 | M.editor.hideOverlay(); | ||
706 | self.$el.html(self.template({ | ||
707 | })); | ||
708 | self.appendFileListTemplate(data.uploaded_files); | ||
709 | self.delegateEvents(); | ||
710 | } | ||
711 | }); | ||
712 | }, | ||
713 | appendFileListTemplate: function(files) { | ||
714 | var template = _.template($('#uploaded-item-template').html()); | ||
715 | if(files.length) { | ||
716 | _.each(files, function(file) { | ||
717 | $('#uploads-list').append(template({ | ||
718 | filename: file | ||
719 | })); | ||
720 | }); | ||
721 | } | ||
722 | else { | ||
723 | $('#uploads-list').html('<b> No files uploaded yet </b>'); | ||
724 | } | ||
725 | }, | ||
726 | uploadFile: function() { | ||
727 | //console.log('upload file'); | ||
728 | var self = this; | ||
729 | M.editor.showOverlay(); | ||
730 | var $form = $('#file-upload-form')[0]; | ||
731 | var formdata = new FormData($form); | ||
732 | $.ajax({ | ||
733 | type: 'POST', | ||
734 | url: '/upload', | ||
735 | data: formdata, | ||
736 | processData: false, | ||
737 | contentType: false, | ||
738 | success: function(response) { | ||
739 | M.editor.hideOverlay(); | ||
740 | M.editor.notifs.show('success', 'Success', 'File uploaded'); | ||
741 | self.render(); | ||
742 | }, | ||
743 | error: function(jqxhr, status, error) { | ||
744 | M.editor.hideOverlay(); | ||
745 | if(error === 'BAD REQUEST') { | ||
746 | var msg = 'File format not allowed. Please contact your administrator to allow this kind of file.' | ||
747 | } else { | ||
748 | var msg = 'Something went wrong. Please try again!'; | ||
749 | } | ||
750 | M.editor.notifs.show('fail', 'Error!', msg); | ||
751 | } | ||
752 | }); | ||
753 | }, | ||
754 | removeFile: function(event) { | ||
755 | M.editor.showOverlay(); | ||
756 | //console.log('remove file'); | ||
757 | var self = this; | ||
758 | var filename = $(event.currentTarget).attr('for'); | ||
759 | $.ajax({ | ||
760 | type: 'DELETE', | ||
761 | url: '/upload/' + filename, | ||
762 | success: function(data) { | ||
763 | M.editor.hideOverlay(); | ||
764 | self.render(); | ||
765 | }, | ||
766 | error: function(jqxhr, status, error) { | ||
767 | console.log(arguments); | ||
768 | } | ||
769 | }); | ||
679 | 770 | } | |
680 | 771 | }); | |
681 | 772 |
mouchak/templates/editor.html
(40 / 3)
  | |||
26 | 26 | M.HeaderURL = function() { return "{{ url_for('insertHeader') }}"; }; | |
27 | 27 | M.PageURL = function() { return "{{ url_for('insertPage') }}"; }; | |
28 | 28 | M.PluginUploadURL = function() { return "{{ url_for('uploadPlugin') }}"; }; | |
29 | M.UploadsURL = function() { return "{{ url_for('static', filename='uploads/') }}"; }; | ||
29 | 30 | M.site_content = {{ content|tojson|safe }}; | |
30 | 31 | window.onload = function() { | |
31 | 32 | M.editor.init(); | |
… | … | ||
144 | 144 | <p> <a href="#" id="header-config"> Header </a> </p> | |
145 | 145 | <p> <a href="#" id="footer-config"> Footer </a> </p> | |
146 | 146 | <p> <a href="#" id="menu-config"> Navigation Menu </a> </p> | |
147 | <p> <a href="#" id="uploads"> Uploads </a> </p> | ||
147 | 148 | <p><a href="{{ url_for('index') }}"> Go to site </a></p> | |
148 | 149 | </div> | |
149 | 150 | </script> | |
… | … | ||
196 | 196 | <small>title of the page</small> | |
197 | 197 | </span> | |
198 | 198 | </div> | |
199 | <div class="form-group"> | ||
199 | <!--div class="form-group"> | ||
200 | 200 | <div class="input-group"> | |
201 | 201 | <span class="input-group-addon"> <strong>Children</strong> </span> | |
202 | 202 | <input class="form-control" id="children" type="text" placeholder="csv of child pages" | |
… | … | ||
205 | 205 | <span class="help-block"> | |
206 | 206 | <small> leave this blank for now</small> | |
207 | 207 | </span> | |
208 | </div> | ||
208 | </div--> | ||
209 | 209 | <div class="form-group"> | |
210 | 210 | <div class="input-group"> | |
211 | 211 | <span class="input-group-addon"> | |
… | … | ||
336 | 336 | <div class="row"> | |
337 | 337 | <div class="form-group col-lg-6"> | |
338 | 338 | <form id="plugin-upload-form" action="" method="post" enctype="multipart/form-data"> | |
339 | <input type="file" name="plugin-file" id="select-plugin"> | ||
339 | <input type="file" name="plugin-file" id="select-plugin"> | ||
340 | 340 | <input type="button" id="upload-plugin" class="btn btn-info" value="Upload Plugin"> | |
341 | 341 | </form> | |
342 | 342 | </div> | |
… | … | ||
404 | 404 | <button type="button" class="close" data-dismiss="alert">×</button> | |
405 | 405 | <h4> <%= title %> </h4> | |
406 | 406 | <%= msg %> | |
407 | </div> | ||
408 | </script> | ||
409 | |||
410 | <script type="text/template" id="uploads-template"> | ||
411 | <div class="page"> | ||
412 | <div><h4> All your uploads </h4></div> | ||
413 | <div id="uploads-list" class="well"> | ||
414 | </div> | ||
415 | <hr> | ||
416 | <div class="row"> | ||
417 | <div> <h4> New Upload </h4> </div> | ||
418 | <form id="file-upload-form" action="" method="post" enctype="multipart/form-data"> | ||
419 | <input type="file" name="upload-file" id="select-file"> | ||
420 | <input type="button" id="upload-new-file" class="btn btn-sm btn-primary update-btn" value="Upload File"> | ||
421 | </form> | ||
422 | </div> | ||
423 | <div class="clearfix"></div> | ||
424 | </div> | ||
425 | </script> | ||
426 | |||
427 | <script type="text/template" id="uploaded-item-template"> | ||
428 | <div class="uploaded-item row"> | ||
429 | <span> <icon here> </span> | ||
430 | <!--span class="uploaded-item-name"> <%= filename %> </span--> | ||
431 | <span class="uploaded-item-path"> | ||
432 | <a href="<%= M.UploadsURL() + filename %>"> | ||
433 | <%= M.UploadsURL() + filename %> | ||
434 | </a> | ||
435 | </span> | ||
436 | <span class="pull-right"> | ||
437 | <a href="javascript:void(0);" class="remove" for="<%= filename %>"> | ||
438 | <span class="glyphicon glyphicon-trash"></span> | ||
439 | </a> | ||
440 | </span> | ||
441 | <span class="clearfix"></span> | ||
407 | 442 | </div> | |
408 | 443 | </script> | |
409 | 444 |