Attachment rendering for posts & node descriptions.

This commit is contained in:
2016-10-26 12:07:01 +02:00
parent d50d206e77
commit aef7754537
7 changed files with 104 additions and 2 deletions

View File

@@ -7,12 +7,14 @@ _file_embedded_schema = {
} }
} }
ATTACHMENT_SLUG_REGEX = '[a-zA-Z0-9_ ]+'
_attachments_embedded_schema = { _attachments_embedded_schema = {
'type': 'dict', 'type': 'dict',
# TODO: will be renamed to 'keyschema' in Cerberus 1.0 # TODO: will be renamed to 'keyschema' in Cerberus 1.0
'propertyschema': { 'propertyschema': {
'type': 'string', 'type': 'string',
'regex': '^[a-zA-Z0-9_ ]+$', 'regex': '^%s$' % ATTACHMENT_SLUG_REGEX,
}, },
'valueschema': { 'valueschema': {
'type': 'dict', 'type': 'dict',

View File

@@ -691,7 +691,7 @@ def upgrade_attachment_schema(proj_url=None, all_projects=False):
nodes = nodes_coll.find({ nodes = nodes_coll.find({
'project': project['_id'], 'project': project['_id'],
'node_type': {'$in': list(node_type_names)}, 'node_type': {'$in': list(node_type_names)},
'properties.attachments.0': {'$exists': True}, 'properties.attachments': {'$exists': True},
}) })
for node in nodes: for node in nodes:
log.info(' - Updating schema on node %s (%s)', node['_id'], node.get('name')) log.info(' - Updating schema on node %s (%s)', node['_id'], node.get('name'))

View File

@@ -0,0 +1,88 @@
import logging
import re
from bson import ObjectId
import flask
import pillarsdk
from pillar.api.node_types import ATTACHMENT_SLUG_REGEX
from pillar.web.utils import system_util
shortcode_re = re.compile(r'@\[(%s)\]' % ATTACHMENT_SLUG_REGEX)
log = logging.getLogger(__name__)
def render_attachments(node, field_value):
"""Renders attachments referenced in the field value.
Returns the rendered field.
"""
# TODO: cache this based on the node's etag and attachment links expiry.
node_attachments = node[u'properties'][u'attachments']
if isinstance(node_attachments, list):
log.warning('Old-style attachments property found on node %s. Ignoring them, '
'will result in attachments not being found.', node[u'_id'])
return field_value
if not node_attachments:
return field_value
def replace(match):
slug = match.group(1)
try:
att = node_attachments[slug]
except KeyError:
return u'[attachment "%s" not found]' % slug
return render_attachment(att)
return shortcode_re.sub(replace, field_value)
def render_attachment(attachment):
"""Renders an attachment as HTML"""
oid = ObjectId(attachment[u'oid'])
collection = attachment.collection or u'files'
renderers = {
'files': render_attachment_file
}
try:
renderer = renderers[collection]
except KeyError:
log.error(u'Unable to render attachment from collection %s', collection)
return u'Unable to render attachment'
return renderer(oid)
def render_attachment_file(oid):
"""Renders a file attachment."""
api = system_util.pillar_api()
sdk_file = pillarsdk.File.find(oid, api=api)
file_renderers = {
'image': render_attachment_file_image
}
mime_type_cat, _ = sdk_file.content_type.split('/', 1)
try:
renderer = file_renderers[mime_type_cat]
except KeyError:
return flask.render_template('nodes/attachments/file_generic.html', file=sdk_file)
return renderer(sdk_file)
def render_attachment_file_image(sdk_file):
"""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)

View File

@@ -14,6 +14,7 @@ from pillar.web.nodes.routes import blueprint
from pillar.web.nodes.routes import url_for_node from pillar.web.nodes.routes import url_for_node
from pillar.web.nodes.forms import get_node_form from pillar.web.nodes.forms import get_node_form
from pillar.web.nodes.forms import process_node_form from pillar.web.nodes.forms import process_node_form
import pillar.web.nodes.attachments
from pillar.web.projects.routes import project_update_nodes_list from pillar.web.projects.routes import project_update_nodes_list
@@ -53,6 +54,9 @@ def posts_view(project_id=None, project_url=None, url=None):
if not (current_user.is_authenticated and post.has_method('PUT')): if not (current_user.is_authenticated and post.has_method('PUT')):
abort(403) abort(403)
post['properties']['content'] = pillar.web.nodes.attachments.render_attachments(
post, post['properties']['content'])
return render_template( return render_template(
'nodes/custom/post/view.html', 'nodes/custom/post/view.html',
blog=blog, blog=blog,
@@ -72,6 +76,9 @@ def posts_view(project_id=None, project_url=None, url=None):
for post in posts._items: for post in posts._items:
post.picture = get_file(post.picture, api=api) post.picture = get_file(post.picture, api=api)
post['properties']['content'] = pillar.web.nodes.attachments.render_attachments(
post, post['properties']['content'])
return render_template( return render_template(
'nodes/custom/blog/index.html', 'nodes/custom/blog/index.html',
node_type_post=node_type_post, node_type_post=node_type_post,

View File

@@ -22,6 +22,7 @@ from wtforms import SelectMultipleField
from flask_login import login_required from flask_login import login_required
from jinja2.exceptions import TemplateNotFound from jinja2.exceptions import TemplateNotFound
import pillar.web.nodes.attachments
from pillar.web.utils import caching from pillar.web.utils import caching
from pillar.web.nodes.forms import get_node_form from pillar.web.nodes.forms import get_node_form
from pillar.web.nodes.forms import process_node_form from pillar.web.nodes.forms import process_node_form
@@ -260,6 +261,8 @@ def _view_handler_asset(node, template_path, template_action, link_allowed):
# Treat it as normal file (zip, blend, application, etc) # Treat it as normal file (zip, blend, application, etc)
asset_type = 'file' asset_type = 'file'
node['description'] = pillar.web.nodes.attachments.render_attachments(node, node['description'])
template_path = os.path.join(template_path, asset_type) template_path = os.path.join(template_path, asset_type)
return template_path, template_action return template_path, template_action

View File

@@ -0,0 +1 @@
a.attachment(href="{{ file.link }}") {{ file.filename }}

View File

@@ -0,0 +1 @@
img(src="{{ vars['l'].link }}",alt="{{ file.filename }}")