From 6765276519ce5d2c6f93cd82db91bcdcf281cef2 Mon Sep 17 00:00:00 2001 From: Francesco Siddi Date: Wed, 8 Feb 2017 18:10:05 +0100 Subject: [PATCH] Introducing attachments fixes for blog posts and assets. Requires migration of attachments schema using python manage.py maintenance upgrade_attachment_schema --all --- pillar/api/node_types/__init__.py | 8 + pillar/web/main/routes.py | 1 - pillar/web/nodes/attachments.py | 28 ++- pillar/web/nodes/custom/posts.py | 47 ----- pillar/web/nodes/routes.py | 25 +-- pillar/web/utils/forms.py | 6 - src/templates/layout.jade | 3 + .../nodes/attachments/file_image.jade | 12 +- .../nodes/custom/comment/list_embed.jade | 1 - src/templates/nodes/custom/post/edit.jade | 168 ------------------ src/templates/nodes/custom/post/view.jade | 79 ++------ .../nodes/custom/post/view_embed.jade | 134 ++++---------- .../nodes/custom/post/view_main_project.jade | 35 +++- src/templates/nodes/edit.jade | 16 +- src/templates/nodes/edit_embed.jade | 34 ++-- src/templates/projects/view.jade | 62 ++++--- 16 files changed, 204 insertions(+), 455 deletions(-) delete mode 100644 src/templates/nodes/custom/post/edit.jade diff --git a/pillar/api/node_types/__init__.py b/pillar/api/node_types/__init__.py index d75d7d9c..2aa26bc0 100644 --- a/pillar/api/node_types/__init__.py +++ b/pillar/api/node_types/__init__.py @@ -23,6 +23,14 @@ _attachments_embedded_schema = { 'type': 'objectid', 'required': True, }, + 'link': { + 'type': 'string', + 'allowed': ['self', 'none', 'custom'], + 'default': 'self', + }, + 'link_custom': { + 'type': 'string', + }, 'collection': { 'type': 'string', 'allowed': ['files'], diff --git a/pillar/web/main/routes.py b/pillar/web/main/routes.py index 0256b085..4947be8e 100644 --- a/pillar/web/main/routes.py +++ b/pillar/web/main/routes.py @@ -148,7 +148,6 @@ def main_posts_create(): @blueprint.route('/p//blog/') def project_blog(project_url, url=None): """View project blog""" - return posts_view(project_url=project_url, url=url) diff --git a/pillar/web/nodes/attachments.py b/pillar/web/nodes/attachments.py index 24a7d09a..b336b85f 100644 --- a/pillar/web/nodes/attachments.py +++ b/pillar/web/nodes/attachments.py @@ -38,7 +38,6 @@ def render_attachments(node, field_value): att = node_attachments[slug] except KeyError: return u'[attachment "%s" not found]' % slug - return render_attachment(att) return shortcode_re.sub(replace, field_value) @@ -60,14 +59,14 @@ def render_attachment(attachment): log.error(u'Unable to render attachment from collection %s', collection) return u'Unable to render attachment' - return renderer(oid) + return renderer(attachment) -def render_attachment_file(oid): +def render_attachment_file(attachment): """Renders a file attachment.""" api = system_util.pillar_api() - sdk_file = pillarsdk.File.find(oid, api=api) + sdk_file = pillarsdk.File.find(attachment[u'oid'], api=api) file_renderers = { 'image': render_attachment_file_image @@ -79,15 +78,15 @@ def render_attachment_file(oid): except KeyError: return flask.render_template('nodes/attachments/file_generic.html', file=sdk_file) - return renderer(sdk_file) + return renderer(sdk_file, attachment) -def render_attachment_file_image(sdk_file): +def render_attachment_file_image(sdk_file, attachment): """Renders an image file.""" variations = {var.size: var for var in sdk_file.variations} return flask.render_template('nodes/attachments/file_image.html', - file=sdk_file, vars=variations) + file=sdk_file, vars=variations, attachment=attachment) def attachment_form_group_create(schema_prop): @@ -104,6 +103,8 @@ def _attachment_build_single_field(schema_prop): fake_schema = { 'slug': schema_prop['propertyschema'], 'oid': schema_prop['valueschema']['schema']['oid'], + 'link': schema_prop['valueschema']['schema']['link'], + 'link_custom': schema_prop['valueschema']['schema']['link_custom'], } file_select_form_group = build_file_select_form(fake_schema) return file_select_form_group @@ -125,7 +126,12 @@ def attachment_form_group_set_data(db_prop_value, schema_prop, field_list): # Even uglier hard-coded subform.slug = slug subform.oid = att_data['oid'] - + subform.link = 'self' + subform.link_custom = None + if 'link' in att_data: + subform.link = att_data['link'] + if 'link_custom' in att_data: + subform.link_custom = att_data['link_custom'] field_list.append_entry(subform) @@ -138,6 +144,8 @@ def attachment_form_parse_post_data(data): for allprops in data: oid = allprops['oid'] slug = allprops['slug'] + link = allprops['link'] + link_custom = allprops['link_custom'] if not allprops['slug'] and not oid: continue @@ -145,5 +153,9 @@ def attachment_form_parse_post_data(data): if slug in attachments: raise ValueError('Slug "%s" is used more than once' % slug) attachments[slug] = {'oid': oid} + attachments[slug]['link'] = link + + if link == 'custom': + attachments[slug]['link_custom'] = link_custom return attachments diff --git a/pillar/web/nodes/custom/posts.py b/pillar/web/nodes/custom/posts.py index 4b909ccd..8f6000bd 100644 --- a/pillar/web/nodes/custom/posts.py +++ b/pillar/web/nodes/custom/posts.py @@ -73,7 +73,6 @@ def posts_view(project_id=None, project_url=None, url=None): post['properties']['content'] = pillar.web.nodes.attachments.render_attachments( post, post['properties']['content']) - return render_template( 'nodes/custom/post/view{0}.html'.format(main_project_template), blog=blog, @@ -141,52 +140,6 @@ def posts_create(project_id): api=api) -@blueprint.route("/posts//edit", methods=['GET', 'POST']) -@login_required -def posts_edit(post_id): - api = system_util.pillar_api() - - try: - post = Node.find(post_id, { - 'embedded': '{"user": 1}'}, api=api) - except ResourceNotFound: - return abort(404) - # Check if user is allowed to edit the post - if not post.has_method('PUT'): - return abort(403) - - project = Project.find(post.project, api=api) - attach_project_pictures(project, api) - - node_type = project.get_node_type(post.node_type) - form = get_node_form(node_type) - if form.validate_on_submit(): - if process_node_form(form, node_id=post_id, node_type=node_type, - user=current_user.objectid): - # The the post is published, add it to the list - if form.status.data == 'published': - project_update_nodes_list(post, project_id=project._id, list_name='blog') - return redirect(url_for_node(node=post)) - form.parent.data = post.parent - form.name.data = post.name - form.content.data = post.properties.content - form.status.data = post.properties.status - form.url.data = post.properties.url - if post.picture: - form.picture.data = post.picture - # Embed picture file - post.picture = get_file(post.picture, api=api) - if post.properties.picture_square: - form.picture_square.data = post.properties.picture_square - return render_template('nodes/custom/post/edit.html', - node_type=node_type, - post=post, - form=form, - project=project, - api=api) - - - def setup_app(app): global posts_view diff --git a/pillar/web/nodes/routes.py b/pillar/web/nodes/routes.py index 5c796a2d..c5b2e65e 100644 --- a/pillar/web/nodes/routes.py +++ b/pillar/web/nodes/routes.py @@ -28,9 +28,9 @@ from pillar.web.nodes.forms import process_node_form from pillar.web.nodes.custom.storage import StorageNode from pillar.web.projects.routes import project_update_nodes_list from pillar.web.utils import get_file +from pillar.web.utils import attach_project_pictures from pillar.web.utils.jstree import jstree_build_children from pillar.web.utils.jstree import jstree_build_from_node -from pillar.web.utils.forms import ProceduralFileSelectForm from pillar.web.utils.forms import build_file_select_form from pillar.web import system_util @@ -120,8 +120,9 @@ def view(node_id): node_type_name = node.node_type - if node_type_name == 'post': - # Posts shouldn't be shown at this route, redirect to the correct one. + if node_type_name == 'post' and not request.args.get('embed'): + # Posts shouldn't be shown at this route (unless viewed embedded, tipically + # after an edit. Redirect to the correct one. return redirect(url_for_node(node=node)) # Set the default name of the template path based on the node name @@ -353,12 +354,14 @@ def edit(node_id): if not form[prop_name].choices: form[prop_name].choices = [(d, d) for d in db_prop_value] # Choices should be a tuple with value and name - if not set_data: continue # Assign data to the field if prop_name == 'attachments': + # If attachments is an empty list, do not append data + if not db_prop_value: + continue attachments.attachment_form_group_set_data(db_prop_value, schema_prop, form[prop_name]) elif prop_name == 'files': @@ -391,7 +394,6 @@ def edit(node_id): dyn_schema = node_type['dyn_schema'].to_dict() form_schema = node_type['form_schema'].to_dict() error = "" - node_properties = node.properties.to_dict() ensure_lists_exist_as_empty(node.to_dict(), node_type) @@ -405,8 +407,6 @@ def edit(node_id): project_update_nodes_list(node, project_id=project._id, list_name='blog') else: project_update_nodes_list(node, project_id=project._id) - # Emergency hardcore cache flush - # cache.clear() return redirect(url_for('nodes.view', node_id=node_id, embed=1, _external=True, _scheme=current_app.config['SCHEME'])) @@ -416,7 +416,6 @@ def edit(node_id): else: if form.errors: log.debug('Form errors: %s', form.errors) - # Populate Form form.name.data = node.name form.description.data = node.description @@ -424,7 +423,6 @@ def edit(node_id): form.picture.data = node.picture if node.parent: form.parent.data = node.parent - set_properties(dyn_schema, form_schema, node_properties, form, set_data=True) # Get previews @@ -443,9 +441,10 @@ def edit(node_id): if request.args.get('embed') == '1': # Define the prefix for the embedded template embed_string = '_embed' + else: + attach_project_pictures(project, api) template = '{0}/edit{1}.html'.format(node_type['name'], embed_string) - # We should more simply check if the template file actually exsists on # the filesystem level try: @@ -459,6 +458,7 @@ def edit(node_id): api=api) except TemplateNotFound: template = 'nodes/edit{1}.html'.format(node_type['name'], embed_string) + is_embedded_edit = True if embed_string else False return render_template( template, node=node, @@ -466,7 +466,10 @@ def edit(node_id): form=form, errors=form.errors, error=error, - api=api) + api=api, + project=project, + is_embedded_edit=is_embedded_edit, + ) def ensure_lists_exist_as_empty(node_doc, node_type): diff --git a/pillar/web/utils/forms.py b/pillar/web/utils/forms.py index 2b27ee0a..cbbc2fba 100644 --- a/pillar/web/utils/forms.py +++ b/pillar/web/utils/forms.py @@ -108,12 +108,6 @@ class FileSelectField(StringField): self.widget = CustomFileSelectWidget(file_format=file_format) -class ProceduralFileSelectForm(Form): - file = FileSelectField('file') - size = StringField() - slug = StringField() - - def build_file_select_form(schema): class FileSelectForm(Form): pass diff --git a/src/templates/layout.jade b/src/templates/layout.jade index 9011f2cf..af2b1321 100644 --- a/src/templates/layout.jade +++ b/src/templates/layout.jade @@ -427,8 +427,11 @@ html(lang="en") $('[data-toggle="popover"]').popover(); } + | {% block footer_scripts_pre %}{% endblock %} | {% block footer_scripts %}{% endblock %} + + script. (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), diff --git a/src/templates/nodes/attachments/file_image.jade b/src/templates/nodes/attachments/file_image.jade index aa64479f..c513c556 100644 --- a/src/templates/nodes/attachments/file_image.jade +++ b/src/templates/nodes/attachments/file_image.jade @@ -1 +1,11 @@ -img(src="{{ vars['l'].link }}",alt="{{ file.filename }}") +| {% if 'link' in attachment and attachment['link'] != 'none' %} +| {% if attachment['link'] == 'self' %} +a(href="{{ vars['l'].link }}") + img(src="{{ vars['l'].link }}", alt="{{ file.filename }}") +| {% elif attachment['link'] == 'custom' %} +a(href="{{ attachment['link_custom'] }}") + img(src="{{ vars['l'].link }}", alt="{{ file.filename }}") +| {% endif %} +| {% else %} +img(src="{{ vars['l'].link }}", alt="{{ file.filename }}") +| {% endif %} diff --git a/src/templates/nodes/custom/comment/list_embed.jade b/src/templates/nodes/custom/comment/list_embed.jade index 1d00609b..61288a6f 100644 --- a/src/templates/nodes/custom/comment/list_embed.jade +++ b/src/templates/nodes/custom/comment/list_embed.jade @@ -77,7 +77,6 @@ | {% endif %} | {% block comment_scripts %} -script(src="{{ url_for('static_pillar', filename='assets/js/markdown.min.js', v=171020161) }}") script. // Markdown initialization diff --git a/src/templates/nodes/custom/post/edit.jade b/src/templates/nodes/custom/post/edit.jade deleted file mode 100644 index 1be280f8..00000000 --- a/src/templates/nodes/custom/post/edit.jade +++ /dev/null @@ -1,168 +0,0 @@ -| {% extends 'layout.html' %} - -| {% set title = 'blog' %} - -| {% block page_title %}New {{ node_type.name }}{% endblock %} - -| {% block body %} - -.container - form( - method='POST', - action="{{url_for('nodes.posts_edit', post_id=post._id)}}") - - #blog_container.post-create - - | {% with errors = errors %} - | {% if errors %} - | {% for field in errors %} - .alert.alert-danger(role='alert') - strong {{field}} - | {% for message in errors[field] %} - | {{message}}| - | {% endfor %} - | {% endfor %} - | {% endif %} - | {% endwith %} - - #blog_index-sidebar - | {% if project._id != config.MAIN_PROJECT_ID %} - .blog_project-card - a.item-header( - href="{{ url_for('projects.view', project_url=project.url) }}") - - .overlay - | {% if project.picture_header %} - img.background(src="{{ project.picture_header.thumbnail('m', api=api) }}") - | {% endif %} - - a.card-thumbnail( - href="{{ url_for('projects.view', project_url=project.url) }}") - | {% if project.picture_square %} - img.thumb(src="{{ project.picture_square.thumbnail('m', api=api) }}") - | {% endif %} - - .item-info - - a.item-title( - href="{{ url_for('projects.view', project_url=project.url) }}") - | {{ project.name }} - - | {% endif %} - - .blog_project-sidebar - #blog_post-edit-form - | {% for field in form %} - | {% if field.name in ['picture', 'status'] %} - - .form-group(class="{{field.name}}{% if field.errors %} error{% endif %}") - | {{ field.label }} - | {{ field(class='form-control') }} - - | {% if field.errors %} - ul.error - | {% for error in field.errors %} - li {{ error }} - | {% endfor %} - | {% endif %} - - | {% endif %} - | {% endfor %} - - button.btn.btn-default.button-create(type='submit') - i.pi-check - | Update {{ node_type.name }} - - a.btn.btn-default.button-back(href="{{ url_for_node(node=post) }}") - i.pi-angle-left - | Back to Post - - a.btn.btn-default.button-back(href="{{ url_for('projects.view', project_url=project.url) }}blog") - | Go to Blog - - #blog_post-edit-container - #blog_post-edit-title - | Edit {{ node_type.name }} - - #blog_post-edit-form - | {% for field in form %} - | {% if field.name == 'csrf_token' %} - | {{ field }} - | {% else %} - | {% if field.type == 'HiddenField' %} - | {{ field }} - | {% else %} - - | {% if field.name not in ['description', 'picture', 'category', 'status'] %} - - .form-group(class="{{field.name}}{% if field.errors %} error{% endif %}") - | {{ field.label }} - | {{ field(class='form-control') }} - - | {% if field.errors %} - ul.error - | {% for error in field.errors %} - li {{ error }} - | {% endfor %} - | {% endif %} - - | {% endif %} - | {% endif %} - | {% endif %} - | {% endfor %} - - - -| {% endblock %} - -| {% block footer_scripts %} -script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.ui.widget.min.js') }}") -script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.iframe-transport.min.js') }}") -script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.fileupload.min.js') }}") -script(src="{{ url_for('static_pillar', filename='assets/js/file_upload.min.js') }}") - -script(type="text/javascript"). - var convert = new Markdown.getSanitizingConverter().makeHtml; - ProjectUtils.setProjectAttributes({projectId: "{{project._id}}"}); - - /* Build the markdown preview when typing in textarea */ - $(function() { - - var $textarea = $('.form-group.content textarea'), - $loader = $('
').insertAfter($textarea), - $preview = $('
').insertAfter($loader); - - $loader.hide(); - - // Delay function to not start converting heavy posts immediately - var delay = (function(){ - var timer = 0; - return function(callback, ms){ - clearTimeout (timer); - timer = setTimeout(callback, ms); - }; - })(); - - $textarea.keyup(function() { - /* If there's an iframe (YouTube embed), delay markdown convert 1.5s */ - if (/iframe/i.test($textarea.val())) { - $loader.show(); - - delay(function(){ - // Convert markdown - $preview.html(convert($textarea.val())); - $loader.hide(); - }, 1500 ); - } else { - // Convert markdown - $preview.html(convert($textarea.val())); - }; - }).trigger('keyup'); - }); - -| {% endblock %} - -| {% block footer_navigation %} -| {% endblock %} -| {% block footer %} -| {% endblock %} diff --git a/src/templates/nodes/custom/post/view.jade b/src/templates/nodes/custom/post/view.jade index f302fd5b..a4ef18c2 100644 --- a/src/templates/nodes/custom/post/view.jade +++ b/src/templates/nodes/custom/post/view.jade @@ -1,55 +1,15 @@ | {% extends 'projects/view.html' %} | {% set title = 'blog' %} + | {% block page_title %}{{node.name}} - Blog{% endblock%} | {% block css %} -link(href="{{ url_for('static_pillar', filename='assets/css/font-pillar.css', v=6220171) }}", rel="stylesheet") -link(href="{{ url_for('static_pillar', filename='assets/css/base.css', v=6220171) }}", rel="stylesheet") -link(href="{{ url_for('static_pillar', filename='assets/css/project-main.css', v=6220171) }}", rel="stylesheet") +| {{ super() }} link(href="{{ url_for('static_pillar', filename='assets/css/blog.css', v=6220171) }}", rel="stylesheet") | {% endblock %} | {% block project_context %} -#blog_container(class="{% if project._id == config.MAIN_PROJECT_ID %}cloud-blog{% endif %}") - - #blog_post-container - | {% if project._id == config.MAIN_PROJECT_ID %} - a.btn.btn-default.button-back(href="{{ url_for('projects.view', project_url=project.url) }}blog") - | Back to Blog - - | {% if node.has_method('PUT') %} - a.btn.btn-default.button-edit(href="{{url_for('nodes.posts_edit', post_id=node._id)}}") - i.pi-edit - | Edit Post - | {% endif %} - - .clearfix - | {% endif %} - - | {% if node.picture %} - .blog_index-header - img(src="{{ node.picture.thumbnail('l', api=api) }}") - | {% endif %} - .blog_index-item - - .item-title - | {{node.name}} - - .item-info. - {{node._created | pretty_date }} - {% if node._created != node._updated %} - (updated {{node._updated | pretty_date }}) - {% endif %} - {% if node.properties.category %}| {{node.properties.category}}{% endif %} - | by {{node.user.full_name}} - - .item-content - | {{ node.properties.content }} - - - #comments-embed - #comments-list-items-loading - i.pi-spin +| {% include 'nodes/custom/post/view_embed.html' %} | {% endblock %} | {% block project_tree %} @@ -57,18 +17,18 @@ link(href="{{ url_for('static_pillar', filename='assets/css/blog.css', v=6220171 ul.jstree-container-ul.jstree-children li.jstree-node(data-node-type="page") a.jstree-anchor( - href="{{ url_for('projects.view', project_url=project.url) }}") + href="{{ url_for('projects.view', project_url=project.url) }}") | Browse Project li.jstree-node.jstree-leaf(data-node-type="page") a.jstree-anchor( - href="{{ url_for('main.project_blog', project_url=project.url) }}") Blog + href="{{ url_for('main.project_blog', project_url=project.url) }}") Blog | {% for post in posts %} li.jstree-node a.jstree-anchor( - href="{{ url_for_node(node=post) }}", - class="{% if post._id == node._id %}jstree-clicked{% endif %}") + href="{{ url_for_node(node=post) }}", + class="{% if post._id == node._id %}jstree-clicked{% endif %}") .tree-item-thumbnail | {% if post.picture %} img(src="{{ post.picture.thumbnail('s', api=api) }}") @@ -83,32 +43,25 @@ link(href="{{ url_for('static_pillar', filename='assets/css/blog.css', v=6220171 | {% block footer_scripts %} -include ../_scripts script. - {% if project.has_method('PUT') %} - /* Edit Button */ - $('#item_edit').click(function(e){ - e.preventDefault(); - $('.button-edit-icon').addClass('pi-spin spin').removeClass('pi-edit'); - window.location.replace("{{url_for('nodes.posts_edit', post_id=node._id)}}"); - }); - {% endif %} - + ProjectUtils.setProjectAttributes({projectId: "{{project._id}}", isProject: false, nodeId: '{{node._id}}'}); /* Expand images when their link points to a jpg/png/gif */ /* TODO: De-duplicate code from blog index */ - $('.blog_index-item .item-content a img').on('click', function(e){ + var page_overlay = document.getElementById('page-overlay'); + $('.blog_index-item .item-content a img').on('click', function (e) { e.preventDefault(); - var href = $(this).parent().attr('href'); + var href = $(this).parent().attr('href').split("?")[0]; var src = $(this).attr('src'); if (href.match("jpg$") || href.match("png$") || href.match("gif$")) { - var page_overlay = document.getElementById('page-overlay'); + $(page_overlay) - .addClass('active') - .html(''); + .addClass('active') + .html(''); } else { window.location.href = href; } }); -| {% endblock %} + +| {% endblock footer_scripts %} diff --git a/src/templates/nodes/custom/post/view_embed.jade b/src/templates/nodes/custom/post/view_embed.jade index 2897dd43..5b6df358 100644 --- a/src/templates/nodes/custom/post/view_embed.jade +++ b/src/templates/nodes/custom/post/view_embed.jade @@ -1,111 +1,43 @@ -| {% set title = 'blog' %} -| {% block body %} +#blog_container(class="{% if project and project._id == config.MAIN_PROJECT_ID %}cloud-blog{% endif %}") -.container - #blog_container(class="{% if project._id == config.MAIN_PROJECT_ID %}cloud-blog{% endif %}") + #blog_post-container + | {% if project and project._id == config.MAIN_PROJECT_ID %} + a.btn.btn-default.button-back(href="{{ url_for('projects.view', project_url=project.url) }}blog") + | Back to Blog - #blog_post-container - | {% if project._id == config.MAIN_PROJECT_ID %} - a.btn.btn-default.button-back(href="{{ url_for('projects.view', project_url=project.url) }}blog") - | Back to Blog - - | {% if node.has_method('PUT') %} - a.btn.btn-default.button-edit(href="{{url_for('nodes.posts_edit', post_id=node._id)}}") - i.pi-edit - | Edit Post - | {% endif %} - - .clearfix - | {% endif %} - - | {% if node.picture %} - .blog_index-header - img(src="{{ node.picture.thumbnail('l', api=api) }}") - | {% endif %} - .blog_index-item - - .item-title - | {{node.name}} - - .item-info. - {{node._created | pretty_date }} - {% if node._created != node._updated %} - (updated {{node._updated | pretty_date }}) - {% endif %} - {% if node.properties.category %}| {{node.properties.category}}{% endif %} - | by {{node.user.full_name}} - - .item-content - | {{ node.properties.content }} - - - #comments-embed - #comments-list-items-loading - i.pi-spin - - | {% if project._id != config.MAIN_PROJECT_ID %} - #blog_index-sidebar - .blog_project-card - a.item-header( - href="{{ url_for('projects.view', project_url=project.url) }}") - - .overlay - | {% if project.picture_header %} - img.background(src="{{ project.picture_header.thumbnail('m', api=api) }}") - | {% endif %} - - a.card-thumbnail( - href="{{ url_for('projects.view', project_url=project.url) }}") - | {% if project.picture_square %} - img.thumb(src="{{ project.picture_square.thumbnail('m', api=api) }}") - | {% endif %} - - .item-info - - a.item-title( - href="{{ url_for('projects.view', project_url=project.url) }}") - | {{ project.name }} - - | {% if project.summary %} - p.item-description - | {{project.summary|safe}} - | {% endif %} - .blog_project-sidebar - | {% if node.has_method('PUT') %} - a.btn.btn-default.button-create(href="{{url_for('nodes.posts_edit', post_id=node._id)}}") - | Edit Post - | {% endif %} - - a.btn.btn-default.button-back(href="{{ url_for('projects.view', project_url=project.url) }}blog") - | Back to Blog + | {% if node.has_method('PUT') %} + a.btn.btn-default.button-edit(href="{{url_for('nodes.edit', node_id=node._id)}}") + i.pi-edit + | Edit Post | {% endif %} + .clearfix + | {% endif %} -| {% endblock %} + | {% if node.picture %} + .blog_index-header + img(src="{{ node.picture.thumbnail('l', api=api) }}") + | {% endif %} + .blog_index-item + + .item-title + | {{node.name}} + + .item-info. + {{node._created | pretty_date }} + {% if node._created != node._updated %} + (updated {{node._updated | pretty_date }}) + {% endif %} + {% if node.properties.category %}| {{node.properties.category}}{% endif %} + | by {{node.user.full_name}} + + .item-content + | {{ node.properties.content }} -| {% block footer_scripts %} + #comments-embed + #comments-list-items-loading + i.pi-spin include ../_scripts -script. - hopToTop(); // Display jump to top button - - /* Expand images when their link points to a jpg/png/gif */ - /* TODO: De-duplicate code from view post */ - var page_overlay = document.getElementById('page-overlay'); - $('.blog_index-item .item-content a img').on('click', function(e){ - e.preventDefault(); - - var href = $(this).parent().attr('href'); - var src = $(this).attr('src'); - - if (href.match("jpg$") || href.match("png$") || href.match("gif$")) { - $(page_overlay) - .addClass('active') - .html(''); - } else { - window.location.href = href; - } - }); -| {% endblock %} diff --git a/src/templates/nodes/custom/post/view_main_project.jade b/src/templates/nodes/custom/post/view_main_project.jade index b77c8871..9dca9c07 100644 --- a/src/templates/nodes/custom/post/view_main_project.jade +++ b/src/templates/nodes/custom/post/view_main_project.jade @@ -1,4 +1,37 @@ | {% extends 'layout.html' %} | {% block page_title %}{{node.name}} - Blog{% endblock%} -include view_embed +| {% set title = 'blog' %} + +| {% block body %} + +.container + | {% include 'nodes/custom/post/view_embed.html' %} + +| {% endblock %} + + +| {% block footer_scripts %} + +script. + hopToTop(); // Display jump to top button + + /* Expand images when their link points to a jpg/png/gif */ + /* TODO: De-duplicate code from view post */ + var page_overlay = document.getElementById('page-overlay'); + $('.blog_index-item .item-content a img').on('click', function (e) { + e.preventDefault(); + + var href = $(this).parent().attr('href').split("?")[0]; + var src = $(this).attr('src'); + + + if (href.match("jpg$") || href.match("png$") || href.match("gif$")) { + $(page_overlay) + .addClass('active') + .html(''); + } else { + window.location.href = href; + } + }); +| {% endblock %} diff --git a/src/templates/nodes/edit.jade b/src/templates/nodes/edit.jade index c1aa39cc..e8b6d525 100644 --- a/src/templates/nodes/edit.jade +++ b/src/templates/nodes/edit.jade @@ -1,11 +1,17 @@ -| {% extends 'layout.html' %} +| {% extends 'projects/view.html' %} | {% block body %} -div.container +#project-container.container div.page-content | {% include 'nodes/edit_embed.html' %} -| {% endblock %} +| {% endblock body %} | {% block footer_scripts %} -| {% include '_macros/_file_uploader_javascript.html' %} -| {% endblock %} +| {{ super() }} +script. + $(function () { + updateUi('', 'edit'); + }); + +| {% endblock footer_scripts %} + diff --git a/src/templates/nodes/edit_embed.jade b/src/templates/nodes/edit_embed.jade index 5e917a17..bb430eba 100644 --- a/src/templates/nodes/edit_embed.jade +++ b/src/templates/nodes/edit_embed.jade @@ -148,10 +148,19 @@ script(type="text/javascript"). /* Submit changes */ - $("#node-edit-form").unbind( "submit" ) - .submit(function(e) { + $("#node-edit-form").unbind("submit").submit(function(e) { e.preventDefault(); + // Assets always need a file + var $file = $('.form-group.file #file'); + if ($file.val() == '') { + $file.addClass('error'); + statusBarSet('error', 'No File Selected', 'pi-warning', 5000); + return jQuery.Deferred().reject("nofile"); + } + + $file.removeClass('error'); + /* Let us know started saving */ $("li.button-save").addClass('saving'); $("li.button-save a#item_save").html(' Saving...'); @@ -181,7 +190,10 @@ script(type="text/javascript"). }) .done(function(dataHtml){ /* Success! */ + // Disable beforeunolad when submitting a form + $(window).off('beforeunload'); + {% if is_embedded_edit %} /* Load content*/ $('#project_context').html(dataHtml); statusBarSet('success', 'Saved Successfully', 'pi-check'); @@ -194,24 +206,18 @@ script(type="text/javascript"). //- $('#project_tree').jstree("refresh"); updateUi(ProjectUtils.nodeId(), 'view'); + {% else %} + // This code runs only if we are in direct node editing mode, and since we do a redirect, + // nothing of what follows is executed, because of the redirect. + location.href = "{{ url_for('nodes.view', node_id=node._id)}}"; + {% endif %} }); }); $('#item_save, .item-save').click(function(e){ e.preventDefault(); - - // Assets always need a file - if ($('.form-group.file #file').val() == ''){ - $('.form-group.file').addClass('error'); - statusBarSet('error', 'No File Selected', 'pi-warning', 5000); - } else { - $('.form-group.file').removeClass('error'); - $("#node-edit-form").submit(); - - // Disable beforeunolad when submitting a form - $(window).off('beforeunload'); - } + $("#node-edit-form").submit(); }); $('#item_cancel, .item-cancel').click(function(e){ diff --git a/src/templates/projects/view.jade b/src/templates/projects/view.jade index 88e527c2..00ad474f 100644 --- a/src/templates/projects/view.jade +++ b/src/templates/projects/view.jade @@ -137,7 +137,7 @@ link(href="{{ url_for('static_pillar', filename='assets/css/project-main.css', v | {% block project_tree %} #project_tree - | {% endblock %} + | {% endblock project_tree %} | {% endif %} .project_split(title="Toggle Navigation [T]") @@ -246,7 +246,7 @@ link(href="{{ url_for('static_pillar', filename='assets/css/project-main.css', v | {% if show_project %} | {% include "projects/view_embed.html" %} | {% endif %} - | {% endblock %} + | {% endblock project_context %} #overlay-mode-move-container .overlay-container @@ -265,8 +265,8 @@ link(href="{{ url_for('static_pillar', filename='assets/css/project-main.css', v | {% block footer_navigation %}{% endblock %} | {% block footer %}{% endblock %} -| {% block footer_scripts %} -script(src="//cdnjs.cloudflare.com/ajax/libs/jstree/3.3.1/jstree.min.js") + +| {% block footer_scripts_pre %} | {% if project.has_method('PUT') %} | {# JS containing the Edit, Add, Featured, and Move functions #} @@ -274,24 +274,6 @@ script(type="text/javascript", src="{{ url_for('static_pillar', filename='assets | {% endif %} script. - {% if show_project %} - ProjectUtils.setProjectAttributes({projectId: "{{project._id}}", isProject: true, nodeId: ''}); - {% else %} - {% if node %} - ProjectUtils.setProjectAttributes({projectId: "{{project._id}}", isProject: false, nodeId: '{{node._id}}'}); - {% endif %} - {% endif %} - - var projectTree = document.getElementById('project_tree'); - - var urlNodeMove = "{{url_for('projects.move_node')}}"; - var urlNodeFeature = "{{url_for('projects.add_featured_node')}}"; - var urlNodeDelete = "{{url_for('projects.delete_node')}}"; - var urlNodeTogglePublic = "{{url_for('projects.toggle_node_public')}}"; - var urlNodeToggleProjHeader = "{{url_for('projects.toggle_node_project_header')}}"; - var urlProjectDelete = "{{url_for('projects.delete')}}"; - var urlProjectEdit = "{{url_for('projects.edit', project_url=project.url)}}"; - function updateToggleProjHeaderMenuItem() { var $toggle_projheader = $('#item_toggle_projheader'); @@ -308,15 +290,15 @@ script. $(updateToggleProjHeaderMenuItem); // Function to update the interface on loadNodeContent, and edit/saving assets - function updateUi(nodeId, mode){ + function updateUi(nodeId, mode) { if (mode === 'view') { $('.project-mode-view').show(); $('.project-mode-edit').hide(); - $("#node-edit-form").unbind( "submit" ); - $("#item_save").unbind( "click" ); - $("#item_cancel").unbind( "click" ); + $("#node-edit-form").unbind("submit"); + $("#item_save").unbind("click"); + $("#item_cancel").unbind("click"); } else if (mode === 'edit') { $('.project-mode-view').hide(); $('.project-mode-edit').show(); @@ -352,11 +334,33 @@ script. // it's done like that in all users of updateUi(). $('#project-loading').removeAttr('class'); } +| {% endblock %} + +| {% block footer_scripts %} +script(src="//cdnjs.cloudflare.com/ajax/libs/jstree/3.3.1/jstree.min.js") + +script. + {% if show_project %} + ProjectUtils.setProjectAttributes({projectId: "{{project._id}}", isProject: true, nodeId: ''}); + {% else %} + {% if node %} + ProjectUtils.setProjectAttributes({projectId: "{{project._id}}", isProject: false, nodeId: '{{node._id}}'}); + {% endif %} + {% endif %} + + var projectTree = document.getElementById('project_tree'); + + var urlNodeMove = "{{url_for('projects.move_node')}}"; + var urlNodeFeature = "{{url_for('projects.add_featured_node')}}"; + var urlNodeDelete = "{{url_for('projects.delete_node')}}"; + var urlNodeTogglePublic = "{{url_for('projects.toggle_node_public')}}"; + var urlNodeToggleProjHeader = "{{url_for('projects.toggle_node_project_header')}}"; + var urlProjectDelete = "{{url_for('projects.delete')}}"; + var urlProjectEdit = "{{url_for('projects.edit', project_url=project.url)}}"; function loadNodeContent(url, nodeId) { $('#project-loading').addClass('active'); - $.get(url, function(dataHtml) { // Update the DOM injecting the generate HTML into the page $('#project_context').html(dataHtml); @@ -608,8 +612,10 @@ script. }); }; - // Initialize the page + {% if is_embedded_edit is not defined or is_embedded_edit %} + // Initialize the page if we are not directly editing a node (most of the time) loadContent(); + {% endif %} var project_container = document.getElementById('project-container');