예제 #1
0
def attach_project_pictures(project, api):
    """Utility function that queries for file objects referenced in picture
    header and square. In eve we currently can't embed objects in nested
    properties, this is the reason why this exists.
    This function should be moved in the API, attached to a new Project object.
    """
    if project.properties.picture_square:
        # Collect the picture square file object
        project.properties.picture_square = File.find(
            project.properties.picture_square, api=api)
    if project.properties.picture_header:
        # Collect the picture header file object
        project.properties.picture_header = File.find(
            project.properties.picture_header, api=api)
예제 #2
0
def attach_project_pictures(project, api):
    """Utility function that queries for file objects referenced in picture
    header and square. In eve we currently can't embed objects in nested
    properties, this is the reason why this exists.
    This function should be moved in the API, attached to a new Project object.
    """
    if project.properties.picture_square:
        # Collect the picture square file object
        project.properties.picture_square = File.find(
            project.properties.picture_square, api=api)
    if project.properties.picture_header:
        # Collect the picture header file object
        project.properties.picture_header = File.find(
            project.properties.picture_header, api=api)
예제 #3
0
def item_delete(item_id):
    """We run this when updating a preview picture (after succesfully uploading
    a new one).
    """
    api = system_util.pillar_api()
    try:
        file_item = File.find(item_id, api=api)
        file_item.delete(api=api)
        message = 'File deleted'
    except ResourceNotFound:
        message = 'File not found'
    return jsonify(status='success', data=dict(message=message))
예제 #4
0
def item_delete(item_id):
    """We run this when updating a preview picture (after succesfully uploading
    a new one).
    """
    api = system_util.pillar_api()
    try:
        file_item = File.find(item_id, api=api)
        file_item.delete(api=api)
        message = 'File deleted'
    except ResourceNotFound:
        message = 'File not found'
    return jsonify(status='success', data=dict(message=message))
예제 #5
0
def get_file(file_id, api=None):
    # TODO: remove this function and just use the Pillar SDK directly.
    if file_id is None:
        return None

    if api is None:
        api = system_util.pillar_api()

    try:
        return File.find(file_id, api=api)
    except ResourceNotFound:
        f = sys.exc_info()[2].tb_frame.f_back
        tb = traceback.format_stack(f=f, limit=2)
        log.warning('File %s not found, but requested from %s\n%s', file_id,
                    request.url, ''.join(tb))
        return None
예제 #6
0
def create():
    """Endpoint hit by the automatic upload of a picture, currently used in the
    edit node form. Some sanity checks are already done in the fronted, but
    additional checks can be implemented here.
    """
    name = request.form['name']
    size = request.form['size']
    content_type = request.form['type']
    field_name = request.form['field_name']
    project_id = request.form['project_id']
    file_item = process_and_create_file(project_id, name, size, content_type)
    api = system_util.pillar_api()
    f = File.find(file_item['_id'], api=api)
    thumbnail_link = f.thumbnail('s', api=api)

    return jsonify(status='success', data=dict(id=file_item._id,
        link=thumbnail_link, field_name=field_name))
예제 #7
0
def create():
    """Endpoint hit by the automatic upload of a picture, currently used in the
    edit node form. Some sanity checks are already done in the fronted, but
    additional checks can be implemented here.
    """
    name = request.form['name']
    size = request.form['size']
    content_type = request.form['type']
    field_name = request.form['field_name']
    project_id = request.form['project_id']
    file_item = process_and_create_file(project_id, name, size, content_type)
    api = system_util.pillar_api()
    f = File.find(file_item['_id'], api=api)
    thumbnail_link = f.thumbnail('s', api=api)

    return jsonify(status='success',
                   data=dict(id=file_item._id,
                             link=thumbnail_link,
                             field_name=field_name))
예제 #8
0
    def __call__(self, field, **kwargs):
        html = super(CustomFileSelectWidget, self).__call__(field, **kwargs)

        file_format = self.file_format
        file_format_regex = ''
        if file_format and file_format == 'image':
            file_format_regex = '^image\/(gif|jpe?g|png|tif?f|tga)$'

        button = [u'<div class="form-upload-file">']

        if field.data:
            api = system_util.pillar_api()
            try:
                # Load the existing file attached to the field
                file_item = File.find(field.data, api=api)
            except ResourceNotFound:
                pass
            else:
                filename = Markup.escape(file_item.filename)
                if file_item.content_type.split('/')[0] == 'image':
                    # If a file of type image is available, display the preview
                    button.append(u'<img class="preview-thumbnail" src="{0}" />'.format(
                        file_item.thumbnail('s', api=api)))
                else:
                    button.append(u'<p>{}</p>'.format(filename))

                button.append(u'<ul class="form-upload-file-meta">')
                # File name
                button.append(u'<li class="name">{0}</li>'.format(filename))
                # File size
                button.append(u'<li class="size">({0} MB)</li>'.format(
                    round((file_item.length / 1024) * 0.001, 2)))
                # Image resolution (if image)
                button.append(u'<li class="dimensions">{0}x{1}</li>'.format(
                    file_item.width, file_item.height))
                # Delete button
                button.append(u'<li class="delete">'
                              u'<a href="#" class="file_delete" '
                              u'data-field-name="{field_name}" '
                              u'data-file_id="{file_id}"> '
                              u'<i class="pi-trash"></i> Delete</a></li>'.format(
                    field_name=field.name, file_id=field.data))
                # Download button for original file
                button.append(u'<li class="original">'
                              u'<a href="{}" class="file_original"> '
                              u'<i class="pi-download"></i>Original</a></li>'
                              .format(file_item.link))
                button.append(u'</ul>')

        upload_url = u'%s/storage/stream/{project_id}' % current_app.config[
            'PILLAR_SERVER_ENDPOINT']

        button.append(u'<input class="fileupload" type="file" name="file" '
                      u'data-url="{url}" '
                      u'data-field-name="{name}" '
                      u'data-token="{token}" '
                      u'data-file-format="{file_format}">'
                      u'<div class="form-upload-progress"> '
                      u'<div class="form-upload-progress-bar" role="progressbar" '
                      u'aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" '
                      u'style="width: 0%;"> '
                      u'</div> '
                      u'</div>'.format(url=upload_url,
                                       name=field.name,
                                       token=Markup.escape(current_user.id),
                                       file_format=Markup.escape(file_format_regex)))

        button.append(u'</div>')

        return HTMLString(html + u''.join(button))
예제 #9
0
def view(node_id):
    #import time
    #start = time.time()
    api = SystemUtility.attract_api()
    # Get node with embedded picture data
    try:
        node = Node.find(node_id + '/?embedded={"picture":1, "node_type":1}', api=api)
    except ResourceNotFound:
        return abort(404)
    except ForbiddenAccess:
        return abort(403)

    node_type_name = node.node_type.name

    # JsTree functionality.
    # This return a lightweight version of the node, to be used by JsTree in the
    # frontend. We have two possible cases:
    # - https://pillar/<node_id>/view?format=jstree (construct the whole expanded
    #   tree starting from the node_id. Use only once)
    # - https://pillar/<node_id>/view?format=jstree&children=1 (deliver the
    #   children of a node - use in the navigation of the tree)

    if request.args.get('format') and request.args.get('format') == 'jstree':
        if request.args.get('children') == '1':
            if node_type_name == 'storage':
                storage = StorageNode(node)
                # Check if we specify a path within the storage
                path = request.args.get('path')
                # Generate the storage listing
                listing = storage.browse(path)
                # Inject the current node id in the response, so that JsTree can
                # expose the storage_node property and use it for further queries
                listing['storage_node'] = node._id
                if 'children' in listing:
                    for child in listing['children']:
                        child['storage_node'] = node._id
                return jsonify(listing)
            else:
                return jsonify(jstree_build_children(node))
        else:
            return jsonify(items=jstree_build_from_node(node))
    # Continue to process the node (for HTML, HTML embeded and JSON responses)

    # Set the default name of the template path based on the node name
    template_path = os.path.join('nodes', 'custom', node_type_name)
    # Set the default action for a template. By default is view and we override
    # it only if we are working storage nodes, where an 'index' is also possible
    template_action = 'view'

    # XXX Code to detect a node of type asset, and aggregate file data
    if node_type_name == 'asset':
        node_file = File.find(node.properties.file, api=api)
        node_file_children = node_file.children(api=api)
        # Attach the file node to the asset node
        setattr(node, 'file', node_file)

        try:
            asset_type = node_file.content_type.split('/')[0]
        except AttributeError:
            asset_type = None

        if asset_type == 'video':
            # Process video type and select video template
            sources = []
            if node_file_children:
                for f in node_file_children._items:
                    sources.append(dict(
                        type=f.content_type,
                        src=f.link))

            setattr(node, 'video_sources', json.dumps(sources))
            setattr(node, 'file_children', node_file_children)
            template_path = os.path.join(template_path, asset_type)
        elif asset_type == 'image':
            # Process image type and select image template
            #setattr(node, 'file_children', node_file_children)
            template_path = os.path.join(template_path, asset_type)
        else:
            # Treat it as normal file (zip, blend, application, etc)
            template_path = os.path.join(template_path, 'file')
    # XXX The node is of type project
    elif node_type_name == 'project':
        if node.properties.picture_square:
            picture_square = File.find(node.properties.picture_square, api=api)
            node.properties.picture_square = picture_square
        if node.properties.picture_header:
            picture_header = File.find(node.properties.picture_header, api=api)
            node.properties.picture_header = picture_header
        if node.properties.nodes_latest:
            list_latest = []
            for node_id in node.properties.nodes_latest:
                try:
                    node_item = Node.find(node_id, {
                        'projection': '{"name":1, "user":1, "node_type":1}',
                        'embedded': '{"user":1}',
                        }, api=api)
                    list_latest.append(node_item)
                except ForbiddenAccess:
                    list_latest.append(FakeNodeAsset())
            node.properties.nodes_latest = list(reversed(list_latest))
        if node.properties.nodes_featured:
            list_featured = []
            for node_id in node.properties.nodes_featured:
                try:
                    node_item = Node.find(node_id, {
                        'projection': '{"name":1, "user":1, "picture":1, "node_type":1}',
                        'embedded': '{"user":1}',
                        }, api=api)
                    picture = File.find(node_item.picture, api=api)
                    node_item.picture = picture
                    list_featured.append(node_item)
                except ForbiddenAccess:
                    list_featured.append(FakeNodeAsset())
            node.properties.nodes_featured = list(reversed(list_featured))

    elif node_type_name == 'storage':
        storage = StorageNode(node)
        path = request.args.get('path')
        listing = storage.browse(path)
        node.name = listing['name']
        listing['storage_node'] = node._id
        # If the item has children we are working with a group
        if 'children' in listing:
            for child in listing['children']:
                child['storage_node'] = node._id
                child['name'] = child['text']
                child['content_type'] = os.path.dirname(child['type'])
            node.children = listing['children']
            template_action = 'index'
        else:
            node.status = 'published'
            node.length = listing['size']
            node.download_link = listing['signed_url']

    # Get previews
    if node.picture:
        node.picture = File.find(node.picture._id, api=api)
    # Get Parent
    try:
        parent = Node.find(node['parent'], api=api)
    except KeyError:
        parent = None
    except ResourceNotFound:
        parent = None
    # Get children
    try:
        children = Node.all({
            'where': '{"parent": "%s"}' % node._id,
            'embedded': '{"picture": 1, "node_type": 1}'}, api=api)
        children = children._items
    except ForbiddenAccess:
        return abort(403)

    for child in children:
        if child.picture:
            child.picture = File.find(child.picture._id, api=api)

    if request.args.get('format'):
        if request.args.get('format') == 'json':
            node = node.to_dict()
            node['url_edit'] = url_for('nodes.edit', node_id=node['_id']),
            if parent:
                parent = parent.to_dict()
            return_content = jsonify({
                'node': node,
                'children': children.to_dict(),
                'parent': parent
            })
    else:
        embed_string = ''
        # Check if we want to embed the content via an AJAX call
        if request.args.get('embed'):
            if request.args.get('embed') == '1':
                # Define the prefix for the embedded template
                embed_string = '_embed'

        # Check if template exists on the filesystem
        template_path = '{0}/{1}{2}.html'.format(template_path,
                                                template_action, embed_string)
        template_path_full = os.path.join(app.config['TEMPLATES_PATH'],
                                        template_path)
        if not os.path.exists(template_path_full):
            return "Missing template"

        return_content = render_template(template_path,
            node=node,
            type_names=type_names(),
            parent=parent,
            children=children,
            config=app.config)

    #print(time.time() - start)
    return return_content
예제 #10
0
def shots_index():
    max_results = 100

    api = system_util.pillar_api()
    node_type_name = "shot"
    node_type_list = NodeType.all({
        'where': '{"name" : "%s"}' % node_type_name,
        }, api=api)

    node_type = node_type_list._items[0]

    nodes = Node.all({
        'where': '{"node_type" : "%s"}' % node_type._id,
        'max_results': max_results,
        'embedded': '{"picture":1}',
        'sort' : "order"}, api=api)

    # Get the task node type object id
    node_type_list = NodeType.all({
        'where': '{"name" : "task"}',
        }, api=api)
    node_type_task = node_type_list._items[0]

    nodes_datatables = []
    for node in nodes._items:
        tasks = Node.all({
            'where': '{"node_type" : "%s", "parent" : "%s"}'\
                    % (node_type_task._id, node._id),
            'sort' : "order"}, api=api)

        shot_status = None

        try:
            shot_status = node.properties.status
        except:
            # Notify about missing status property. This should be prominent.
            pass

        data = {
            'DT_RowId': "row_{0}".format(node._id),
            'DT_RowAttr': {'data-shot-status':shot_status},
            '_id': node._id,
            'order': node.order,
            'picture': None,
            'name': node.name,
            #'description': node.description,
            'notes': node.properties.notes,
            'timing': {
                'cut_in': node.properties.cut_in,
                'cut_out': node.properties.cut_out
                },
            'url_view': url_for('nodes.view', node_id=node._id),
            'url_edit': url_for('nodes.edit', node_id=node._id, embed=1),
            'tasks': {
                'animation': None,
                'lighting': None,
                'fx_hair': None,
                'fx_grass': None,
                'fx_smoke': None
                },
            }

        if node.picture:
            # This is an address on the Attract server, so it should be built
            # entirely here
            data['picture'] = "{0}/file_server/file/{1}".format(
                app.config['PILLAR_SERVER_ENDPOINT'], node.picture.path)
            # Get previews
            picture_node = File.find(node.picture['_id'] + \
                                    '/?embedded={"previews":1}', api=api)

            if picture_node.previews:
                for preview in picture_node.previews:
                    if preview.size == 'm':
                        data['picture_thumbnail'] = app.config['PILLAR_SERVER_ENDPOINT'] + "/file_server/file/" + preview.path
                        break
            else:
                data['picture_thumbnail'] = data['picture']


        if node.order is None:
            data['order'] = 0

        for task in tasks._items:
            # If there are tasks assigned to the shot we loop through them and
            # match them with the existing data indexes.
            if task.name in data['tasks']:
                data['tasks'][task.name] = {
                'name': task.name,
                'status': task.properties.status,
                'url_view': url_for('nodes.view', node_id=task._id, embed=1),
                'url_edit': url_for('nodes.edit', node_id=task._id, embed=1),
                'is_conflicting': task.properties.is_conflicting,
                'is_processing': task.properties.is_rendering,
                'is_open': task.properties.is_open
                }


        nodes_datatables.append(data)

    return jsonify(data=nodes_datatables)
예제 #11
0
def shots_index():
    max_results = 100

    api = system_util.pillar_api()
    node_type_name = "shot"
    node_type_list = NodeType.all(
        {
            'where': '{"name" : "%s"}' % node_type_name,
        }, api=api)

    node_type = node_type_list._items[0]

    nodes = Node.all(
        {
            'where': '{"node_type" : "%s"}' % node_type._id,
            'max_results': max_results,
            'embedded': '{"picture":1}',
            'sort': "order"
        },
        api=api)

    # Get the task node type object id
    node_type_list = NodeType.all({
        'where': '{"name" : "task"}',
    }, api=api)
    node_type_task = node_type_list._items[0]

    nodes_datatables = []
    for node in nodes._items:
        tasks = Node.all({
            'where': '{"node_type" : "%s", "parent" : "%s"}'\
                    % (node_type_task._id, node._id),
            'sort' : "order"}, api=api)

        shot_status = None

        try:
            shot_status = node.properties.status
        except:
            # Notify about missing status property. This should be prominent.
            pass

        data = {
            'DT_RowId': "row_{0}".format(node._id),
            'DT_RowAttr': {
                'data-shot-status': shot_status
            },
            '_id': node._id,
            'order': node.order,
            'picture': None,
            'name': node.name,
            #'description': node.description,
            'notes': node.properties.notes,
            'timing': {
                'cut_in': node.properties.cut_in,
                'cut_out': node.properties.cut_out
            },
            'url_view': url_for('nodes.view', node_id=node._id),
            'url_edit': url_for('nodes.edit', node_id=node._id, embed=1),
            'tasks': {
                'animation': None,
                'lighting': None,
                'fx_hair': None,
                'fx_grass': None,
                'fx_smoke': None
            },
        }

        if node.picture:
            # This is an address on the Attract server, so it should be built
            # entirely here
            data['picture'] = "{0}/file_server/file/{1}".format(
                app.config['PILLAR_SERVER_ENDPOINT'], node.picture.path)
            # Get previews
            picture_node = File.find(node.picture['_id'] + \
                                    '/?embedded={"previews":1}', api=api)

            if picture_node.previews:
                for preview in picture_node.previews:
                    if preview.size == 'm':
                        data['picture_thumbnail'] = app.config[
                            'PILLAR_SERVER_ENDPOINT'] + "/file_server/file/" + preview.path
                        break
            else:
                data['picture_thumbnail'] = data['picture']

        if node.order is None:
            data['order'] = 0

        for task in tasks._items:
            # If there are tasks assigned to the shot we loop through them and
            # match them with the existing data indexes.
            if task.name in data['tasks']:
                data['tasks'][task.name] = {
                    'name': task.name,
                    'status': task.properties.status,
                    'url_view': url_for('nodes.view',
                                        node_id=task._id,
                                        embed=1),
                    'url_edit': url_for('nodes.edit',
                                        node_id=task._id,
                                        embed=1),
                    'is_conflicting': task.properties.is_conflicting,
                    'is_processing': task.properties.is_rendering,
                    'is_open': task.properties.is_open
                }

        nodes_datatables.append(data)

    return jsonify(data=nodes_datatables)
예제 #12
0
파일: forms.py 프로젝트: babbysross/pillar
    def __call__(self, field, **kwargs):
        html = super(CustomFileSelectWidget, self).__call__(field, **kwargs)

        file_format = self.file_format
        file_format_regex = ''
        if file_format and file_format == 'image':
            file_format_regex = '^image\/(gif|jpe?g|png|tif?f|tga)$'

        button = ['<div class="form-upload-file">']

        if field.data:
            api = system_util.pillar_api()
            try:
                # Load the existing file attached to the field
                file_item = File.find(field.data, api=api)
            except ResourceNotFound:
                pass
            else:
                button.append('<div class="form-upload-file-meta-container">')

                filename = Markup.escape(file_item.filename)
                if file_item.content_type.split('/')[0] == 'image':
                    # If a file of type image is available, display the preview
                    button.append(
                        '<img class="preview-thumbnail" src="{0}" />'.format(
                            file_item.thumbnail('s', api=api)))

                button.append('<ul class="form-upload-file-meta">')
                # File name
                button.append('<li class="name">{0}</li>'.format(filename))
                # File size
                button.append('<li class="size">({0} MB)</li>'.format(
                    round((file_item.length / 1024) * 0.001, 2)))
                # Image resolution (if image)
                if file_item.content_type.split('/')[0] == 'image':
                    button.append('<li class="dimensions">{0}x{1}</li>'.format(
                        file_item.width, file_item.height))
                button.append('</ul>')
                button.append('<ul class="form-upload-file-actions">')
                # Download button for original file
                button.append(
                    '<li class="original">'
                    '<a href="{}" class="file_original"> '
                    '<i class="pi-download"></i>Original</a></li>'.format(
                        file_item.link))
                # Delete button
                button.append(
                    '<li class="delete">'
                    '<a href="#" class="file_delete" '
                    'data-field-name="{field_name}" '
                    'data-file_id="{file_id}"> '
                    '<i class="pi-trash"></i> Delete</a></li>'.format(
                        field_name=field.name, file_id=field.data))
                button.append('</ul>')
                button.append('</div>')

        upload_url = '%sstorage/stream/{project_id}' % current_app.config[
            'PILLAR_SERVER_ENDPOINT']

        button.append(
            '<input class="fileupload" type="file" name="file" '
            'data-url="{url}" '
            'data-field-name="{name}" '
            'data-field-slug="{slug}" '
            'data-token="{token}" '
            'data-file-format="{file_format}">'
            '<div class="form-upload-progress"> '
            '<div class="form-upload-progress-bar" role="progressbar" '
            'aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" '
            'style="width: 0%;"> '
            '</div> '
            '</div>'.format(url=upload_url,
                            name=field.name,
                            slug=field.name.replace('oid', 'slug'),
                            token=Markup.escape(current_user.id),
                            file_format=Markup.escape(file_format_regex)))

        button.append('</div>')

        return HTMLString(html + ''.join(button))
예제 #13
0
def view(node_id):
    #import time
    #start = time.time()
    api = SystemUtility.attract_api()
    # Get node with embedded picture data
    try:
        node = Node.find(node_id + '/?embedded={"picture":1, "node_type":1}',
                         api=api)
    except ResourceNotFound:
        return abort(404)
    except ForbiddenAccess:
        return abort(403)

    node_type_name = node.node_type.name

    # JsTree functionality.
    # This return a lightweight version of the node, to be used by JsTree in the
    # frontend. We have two possible cases:
    # - https://pillar/<node_id>/view?format=jstree (construct the whole expanded
    #   tree starting from the node_id. Use only once)
    # - https://pillar/<node_id>/view?format=jstree&children=1 (deliver the
    #   children of a node - use in the navigation of the tree)

    if request.args.get('format') and request.args.get('format') == 'jstree':
        if request.args.get('children') == '1':
            if node_type_name == 'storage':
                storage = StorageNode(node)
                # Check if we specify a path within the storage
                path = request.args.get('path')
                # Generate the storage listing
                listing = storage.browse(path)
                # Inject the current node id in the response, so that JsTree can
                # expose the storage_node property and use it for further queries
                listing['storage_node'] = node._id
                if 'children' in listing:
                    for child in listing['children']:
                        child['storage_node'] = node._id
                return jsonify(listing)
            else:
                return jsonify(jstree_build_children(node))
        else:
            return jsonify(items=jstree_build_from_node(node))
    # Continue to process the node (for HTML, HTML embeded and JSON responses)

    # Set the default name of the template path based on the node name
    template_path = os.path.join('nodes', 'custom', node_type_name)
    # Set the default action for a template. By default is view and we override
    # it only if we are working storage nodes, where an 'index' is also possible
    template_action = 'view'

    # XXX Code to detect a node of type asset, and aggregate file data
    if node_type_name == 'asset':
        node_file = File.find(node.properties.file, api=api)
        node_file_children = node_file.children(api=api)
        # Attach the file node to the asset node
        setattr(node, 'file', node_file)

        try:
            asset_type = node_file.content_type.split('/')[0]
        except AttributeError:
            asset_type = None

        if asset_type == 'video':
            # Process video type and select video template
            sources = []
            if node_file_children:
                for f in node_file_children._items:
                    sources.append(dict(type=f.content_type, src=f.link))

            setattr(node, 'video_sources', json.dumps(sources))
            setattr(node, 'file_children', node_file_children)
            template_path = os.path.join(template_path, asset_type)
        elif asset_type == 'image':
            # Process image type and select image template
            #setattr(node, 'file_children', node_file_children)
            template_path = os.path.join(template_path, asset_type)
        else:
            # Treat it as normal file (zip, blend, application, etc)
            template_path = os.path.join(template_path, 'file')
    # XXX The node is of type project
    elif node_type_name == 'project':
        if node.properties.picture_square:
            picture_square = File.find(node.properties.picture_square, api=api)
            node.properties.picture_square = picture_square
        if node.properties.picture_header:
            picture_header = File.find(node.properties.picture_header, api=api)
            node.properties.picture_header = picture_header
        if node.properties.nodes_latest:
            list_latest = []
            for node_id in node.properties.nodes_latest:
                try:
                    node_item = Node.find(node_id, {
                        'projection': '{"name":1, "user":1, "node_type":1}',
                        'embedded': '{"user":1}',
                    },
                                          api=api)
                    list_latest.append(node_item)
                except ForbiddenAccess:
                    list_latest.append(FakeNodeAsset())
            node.properties.nodes_latest = list(reversed(list_latest))
        if node.properties.nodes_featured:
            list_featured = []
            for node_id in node.properties.nodes_featured:
                try:
                    node_item = Node.find(node_id, {
                        'projection':
                        '{"name":1, "user":1, "picture":1, "node_type":1}',
                        'embedded': '{"user":1}',
                    },
                                          api=api)
                    picture = File.find(node_item.picture, api=api)
                    node_item.picture = picture
                    list_featured.append(node_item)
                except ForbiddenAccess:
                    list_featured.append(FakeNodeAsset())
            node.properties.nodes_featured = list(reversed(list_featured))

    elif node_type_name == 'storage':
        storage = StorageNode(node)
        path = request.args.get('path')
        listing = storage.browse(path)
        node.name = listing['name']
        listing['storage_node'] = node._id
        # If the item has children we are working with a group
        if 'children' in listing:
            for child in listing['children']:
                child['storage_node'] = node._id
                child['name'] = child['text']
                child['content_type'] = os.path.dirname(child['type'])
            node.children = listing['children']
            template_action = 'index'
        else:
            node.status = 'published'
            node.length = listing['size']
            node.download_link = listing['signed_url']

    # Get previews
    if node.picture:
        node.picture = File.find(node.picture._id, api=api)
    # Get Parent
    try:
        parent = Node.find(node['parent'], api=api)
    except KeyError:
        parent = None
    except ResourceNotFound:
        parent = None
    # Get children
    try:
        children = Node.all(
            {
                'where': '{"parent": "%s"}' % node._id,
                'embedded': '{"picture": 1, "node_type": 1}'
            },
            api=api)
        children = children._items
    except ForbiddenAccess:
        return abort(403)

    for child in children:
        if child.picture:
            child.picture = File.find(child.picture._id, api=api)

    if request.args.get('format'):
        if request.args.get('format') == 'json':
            node = node.to_dict()
            node['url_edit'] = url_for('nodes.edit', node_id=node['_id']),
            if parent:
                parent = parent.to_dict()
            return_content = jsonify({
                'node': node,
                'children': children.to_dict(),
                'parent': parent
            })
    else:
        embed_string = ''
        # Check if we want to embed the content via an AJAX call
        if request.args.get('embed'):
            if request.args.get('embed') == '1':
                # Define the prefix for the embedded template
                embed_string = '_embed'

        # Check if template exists on the filesystem
        template_path = '{0}/{1}{2}.html'.format(template_path,
                                                 template_action, embed_string)
        template_path_full = os.path.join(app.config['TEMPLATES_PATH'],
                                          template_path)
        if not os.path.exists(template_path_full):
            return "Missing template"

        return_content = render_template(template_path,
                                         node=node,
                                         type_names=type_names(),
                                         parent=parent,
                                         children=children,
                                         config=app.config)

    #print(time.time() - start)
    return return_content