Example #1
0
def shared_image_nodes(home_project_id, api):
    """Returns a list of pillarsdk.Node objects."""

    parent_group = Node.find_first({
        'where': {'project': home_project_id,
                  'node_type': 'group',
                  'parent': None,
                  'name': IMAGE_SHARING_GROUP_NODE_NAME},
        'projection': {'_id': 1}},
        api=api)

    if not parent_group:
        log.debug('No image sharing parent node found.')
        return []

    nodes = Node.all({
        'where': {'project': home_project_id,
                  'node_type': 'asset',
                  'properties.content_type': 'image',
                  'parent': parent_group['_id']},
        'sort': '-_created',
        'projection': {
            '_created': 1,
            'name': 1,
            'picture': 1,
            'short_code': 1,
        }},
        api=api)

    nodes = nodes._items or []
    for node in nodes:
        node.picture = utils.get_file(node.picture)

    return nodes
Example #2
0
def post_rate(post_id, operation):
    """Comment rating function

    :param post_id: the post aid
    :type post_id: str
    :param operation: the rating 'revoke', 'upvote', 'downvote'
    :type operation: string

    """

    if operation not in {'revoke', 'upvote', 'downvote'}:
        raise wz_exceptions.BadRequest('Invalid operation')

    api = system_util.pillar_api()

    # PATCH the node and return the result.
    comment = Node({'_id': post_id})
    result = comment.patch({'op': operation}, api=api)
    assert result['_status'] == 'OK'

    return jsonify({
        'status': 'success',
        'data': {
            'op': operation,
            'rating_positive': result.properties.rating_positive,
            'rating_negative': result.properties.rating_negative,
        }})
Example #3
0
def comments_index():
    parent_id = request.args.get('parent_id')
    # Get data only if we format it
    api = system_util.pillar_api()
    if request.args.get('format'):
        nodes = Node.all({
            'where': '{"node_type" : "comment", "parent": "%s"}' % (parent_id),
            'embedded': '{"user":1}'}, api=api)

        comments = []
        for comment in nodes._items:
            # Query for first level children (comment replies)
            replies = Node.all({
                'where': '{"node_type" : "comment", "parent": "%s"}' % (comment._id),
                'embedded': '{"user":1}'}, api=api)
            replies = replies._items if replies._items else None
            if replies:
                replies = [format_comment(reply, is_reply=True) for reply in replies]

            comments.append(
                format_comment(comment, is_reply=False, replies=replies))

        if request.args.get('format') == 'json':
            return_content = jsonify(items=[c for c in comments if c is not None])
    else:
        parent_node = Node.find(parent_id, api=api)
        project = Project.find(parent_node.project, api=api)
        has_method_POST = project.node_type_has_method('comment', 'POST', api=api)
        # Data will be requested via javascript
        return_content = render_template('nodes/custom/_comments.html',
            parent_id=parent_id,
            has_method_POST=has_method_POST)
    return return_content
Example #4
0
def task_add():
    api = system_util.pillar_api()
    shot_id = request.form['shot_id']
    task_name = request.form['task_name']

    node_type_list = NodeType.all({
        'where': "name=='task'",
        }, api=api)
    node_type = node_type_list['_items'][0]

    node_type_id = node_type._id
    import datetime

    RFC1123_DATE_FORMAT = '%a, %d %b %Y %H:%M:%S GMT'
    node = Node()
    prop = {}
    prop['node_type'] = node_type_id
    prop['name'] = task_name
    prop['description'] = ''
    prop['user'] = current_user.objectid
    prop['parent'] = shot_id
    prop['properties'] = {
        'status': 'todo',
        'owners': {
            'users': [],
            'groups': []},
        'time': {
            'duration': 10,
            'start': datetime.datetime.strftime(datetime.datetime.now(), '%a, %d %b %Y %H:%M:%S GMT')}
        }
    post = node.post(prop, api=api)
    return jsonify(node.to_dict())
Example #5
0
def task_add():
    api = SystemUtility.attract_api()
    shot_id = request.form["shot_id"]
    task_name = request.form["task_name"]

    node_type_list = NodeType.all({"where": "name=='task'"}, api=api)
    node_type = node_type_list["_items"][0]

    node_type_id = node_type._id
    import datetime

    RFC1123_DATE_FORMAT = "%a, %d %b %Y %H:%M:%S GMT"
    node = Node()
    prop = {}
    prop["node_type"] = node_type_id
    prop["name"] = task_name
    prop["description"] = ""
    prop["user"] = current_user.objectid
    prop["parent"] = shot_id
    prop["properties"] = {
        "status": "todo",
        "owners": {"users": [], "groups": []},
        "time": {
            "duration": 10,
            "start": datetime.datetime.strftime(datetime.datetime.now(), "%a, %d %b %Y %H:%M:%S GMT"),
        },
    }
    post = node.post(prop, api=api)
    return jsonify(node.to_dict())
Example #6
0
def comments_for_node(node_id):
    """Shows the comments attached to the given node."""

    api = system_util.pillar_api()

    node = Node.find(node_id, api=api)
    project = Project({'_id': node.project})
    can_post_comments = project.node_type_has_method('comment',
                                                     'POST',
                                                     api=api)
    can_comment_override = request.args.get('can_comment', 'True') == 'True'
    can_post_comments = can_post_comments and can_comment_override

    # Query for all children, i.e. comments on the node.
    comments = Node.all(
        {
            'where': {
                'node_type': 'comment',
                'parent': node_id
            },
        }, api=api)

    def enrich(some_comment):
        some_comment['_user'] = subquery.get_user_info(some_comment['user'])
        some_comment['_is_own'] = some_comment['user'] == current_user.objectid
        some_comment['_current_user_rating'] = None  # tri-state boolean
        some_comment[
            '_rating'] = some_comment.properties.rating_positive - some_comment.properties.rating_negative

        if current_user.is_authenticated:
            for rating in some_comment.properties.ratings or ():
                if rating.user != current_user.objectid:
                    continue

                some_comment['_current_user_rating'] = rating.is_positive

    for comment in comments['_items']:
        # Query for all grandchildren, i.e. replies to comments on the node.
        comment['_replies'] = Node.all(
            {
                'where': {
                    'node_type': 'comment',
                    'parent': comment['_id']
                },
            },
            api=api)

        enrich(comment)
        for reply in comment['_replies']['_items']:
            enrich(reply)

    nr_of_comments = sum(1 + comment['_replies']['_meta']['total']
                         for comment in comments['_items'])

    return render_template('nodes/custom/comment/list_embed.html',
                           node_id=node_id,
                           comments=comments,
                           nr_of_comments=nr_of_comments,
                           show_comments=True,
                           can_post_comments=can_post_comments)
Example #7
0
def comments_create():
    content = request.form['content']
    parent_id = request.form.get('parent_id')

    api = SystemUtility.attract_api()
    node_type = NodeType.find_first({
        'where': '{"name" : "comment"}',
        }, api=api)

    node_asset_props = dict(
        name='Comment',
        #description=a.description,
        #picture=picture,
        user=current_user.objectid,
        node_type=node_type._id,
        #parent=node_parent,
        properties=dict(
            content=content,
            status='published',
            confidence=0,
            rating_positive=0,
            rating_negative=0))

    if parent_id:
        node_asset_props['parent'] = parent_id
    node_asset = Node(node_asset_props)
    node_asset.create(api=api)

    return jsonify(
        asset_id=node_asset._id,
        content=node_asset.properties.content)
Example #8
0
def posts_view(project_id, url=None):
    """View individual blogpost"""
    api = SystemUtility.attract_api()
    node_type = NodeType.find_first({
        'where': '{"name" : "blog"}',
        'projection': '{"name": 1}'
        }, api=api)
    blog = Node.find_one({
        'where': '{"node_type" : "%s", \
            "parent": "%s"}' % (node_type._id, project_id),
        }, api=api)
    if url:
        try:
            post = Node.find_one({
                'where': '{"parent": "%s", "properties.url": "%s"}' % (blog._id, url),
                'embedded': '{"picture":1, "node_type": 1}',
                }, api=api)
        except ResourceNotFound:
            return abort(404)

        return render_template(
            'nodes/custom/post/view.html',
            blog=blog,
            node=post)
    else:
        # Render all posts
        posts = Node.all({
            'where': '{"parent": "%s"}' % (blog._id),
            'embedded': '{"picture":1}',
            'sort': '-_created'
            }, api=api)
        return render_template(
            'nodes/custom/blog/index.html',
            blog=blog,
            posts=posts._items)
Example #9
0
def synced_blender_versions(home_project_id, api):
    """Returns a list of Blender versions with synced settings.

    Returns a list of {'version': '2.77', 'date': datetime.datetime()} dicts.
    Returns an empty list if no Blender versions were synced.
    """

    sync_group = Node.find_first({
        'where': {'project': home_project_id,
                  'node_type': 'group',
                  'parent': None,
                  'name': SYNC_GROUP_NODE_NAME},
        'projection': {'_id': 1}},
        api=api)

    if not sync_group:
        return []

    sync_nodes = Node.all({
        'where': {'project': home_project_id,
                  'node_type': 'group',
                  'parent': sync_group['_id']},
        'projection': {
            'name': 1,
            '_updated': 1,
        }},
        api=api)

    sync_nodes = sync_nodes._items
    if not sync_nodes:
        return []

    return [{'version': node.name, 'date': node._updated}
            for node in sync_nodes]
Example #10
0
def create(community_url: str, post_type: str):
    api = system_util.pillar_api()

    project = Project.find_first({'where': {'url': community_url}}, api=api)
    if project is None:
        return abort(404)

    log.info('Creating post for user {}'.format(current_user.objectid))

    dillo_post_node_type = project.get_node_type('dillo_post')
    dillo_post_tags_default = dillo_post_node_type['dyn_schema']['tags']['schema']['default']

    post_props = dict(
        project=project['_id'],
        name='Awesome Post Title',
        user=current_user.objectid,
        node_type='dillo_post',
        properties=dict(
            tags=[dillo_post_tags_default, ],
            post_type=post_type)
    )

    post = Node(post_props)
    post.create(api=api)
    embed = request.args.get('embed')
    return redirect(url_for(
        'nodes.edit', node_id=post._id, embed=embed, _external=True,
        _scheme=current_app.config['SCHEME']))
Example #11
0
def comments_rate(comment_id, operation):
    """Comment rating function

    :param comment_id: the comment id
    :type comment_id: str
    :param rating: the rating (is cast from 0 to False and from 1 to True)
    :type rating: int

    """

    if operation not in {'revoke', 'upvote', 'downvote'}:
        raise wz_exceptions.BadRequest('Invalid operation')

    api = system_util.pillar_api()

    # PATCH the node and return the result.
    comment = Node({'_id': comment_id})
    result = comment.patch({'op': operation}, api=api)
    assert result['_status'] == 'OK'

    return jsonify({
        'status': 'success',
        'data': {
            'op': operation,
            'rating_positive': result.properties.rating_positive,
            'rating_negative': result.properties.rating_negative,
        }
    })
Example #12
0
def groups_create():
    # Use current_project_id from the session instead of the cookie
    name = request.form['name']
    project_id = request.form['project_id']
    parent_id = request.form.get('parent_id')

    api = system_util.pillar_api()
    # We will create the Node object later on, after creating the file object
    node_asset_props = dict(
        name=name,
        user=current_user.objectid,
        node_type='group',
        project=project_id,
        properties=dict(
            status='published'))
    # Add parent_id only if provided (we do not provide it when creating groups
    # at the Project root)
    if parent_id:
        node_asset_props['parent'] = parent_id
    print parent_id

    node_asset = Node(node_asset_props)
    node_asset.create(api=api)
    return jsonify(status='success',
        data=dict(name=name, asset_id=node_asset._id))
Example #13
0
def comments_create():
    content = request.form['content']
    parent_id = request.form.get('parent_id')
    api = system_util.pillar_api()
    parent_node = Node.find(parent_id, api=api)

    node_asset_props = dict(
        project=parent_node.project,
        name='Comment',
        user=current_user.objectid,
        node_type='comment',
        properties=dict(
            content=content,
            status='published',
            confidence=0,
            rating_positive=0,
            rating_negative=0))

    if parent_id:
        node_asset_props['parent'] = parent_id

    # Get the parent node and check if it's a comment. In which case we flag
    # the current comment as a reply.
    parent_node = Node.find(parent_id, api=api)
    if parent_node.node_type == 'comment':
        node_asset_props['properties']['is_reply'] = True

    node_asset = Node(node_asset_props)
    node_asset.create(api=api)

    return jsonify(
        asset_id=node_asset._id,
        content=node_asset.properties.content)
Example #14
0
def homepage():
    """Homepage"""

    if not current_user.is_authenticated():
        return render_template(
            'join.html',
            title="join")

    # Get latest blog posts
    api = system_util.pillar_api()
    latest_posts = Node.all({
        'projection': {'name': 1, 'project': 1, 'user': 1, 'node_type': 1,
                       'picture': 1, 'properties.status': 1, 'properties.url': 1},
        'where': {'node_type': 'post', 'properties.status': 'published'},
        'embedded': {'user': 1, 'project': 1},
        'sort': '-_created',
        'max_results': '3'
        }, api=api)

    # Append picture Files to last_posts
    for post in latest_posts._items:
        if post.picture:
            post.picture = get_file(post.picture, api=api)

    # Get latest assets added to any project
    latest_assets = Node.latest('assets', api=api)

    # Append picture Files to latest_assets
    for asset in latest_assets._items:
        if asset.picture:
            asset.picture = get_file(asset.picture, api=api)

    # Get latest comments to any node
    latest_comments = Node.latest('comments', api=api)

    # Parse results for replies
    for comment in latest_comments._items:
        if comment.properties.is_reply:
            comment.parent = Node.find(comment.parent.parent, api=api)
        else:
            comment.parent = comment.parent

    main_project = Project.find(app.config['MAIN_PROJECT_ID'], api=api)
    main_project.picture_square = get_file(main_project.picture_square, api=api)
    main_project.picture_header = get_file(main_project.picture_header, api=api)

    return render_template(
        'homepage.html',
        main_project=main_project,
        latest_posts=latest_posts._items,
        latest_assets=latest_assets._items,
        latest_comments=latest_comments._items,
        api=api)
Example #15
0
def comments_index():
    parent_id = request.args.get('parent_id')
    # Get data only if we format it
    api = system_util.pillar_api()
    if request.args.get('format'):
        nodes = Node.all(
            {
                'where': '{"node_type" : "comment", "parent": "%s"}' %
                (parent_id),
                'embedded': '{"user":1}'
            },
            api=api)

        comments = []
        for comment in nodes._items:
            # Query for first level children (comment replies)
            replies = Node.all(
                {
                    'where':
                    '{"node_type" : "comment", "parent": "%s"}' %
                    (comment._id),
                    'embedded':
                    '{"user":1}'
                },
                api=api)
            replies = replies._items if replies._items else None
            if replies:
                replies = [
                    format_comment(reply, is_reply=True) for reply in replies
                ]

            comments.append(
                format_comment(comment, is_reply=False, replies=replies))

        if request.args.get('format') == 'json':
            return_content = jsonify(
                items=[c for c in comments if c is not None])
    else:
        parent_node = Node.find(parent_id, api=api)
        project = Project.find(parent_node.project, api=api)
        has_method_POST = project.node_type_has_method('comment',
                                                       'POST',
                                                       api=api)
        # Data will be requested via javascript
        return_content = render_template('nodes/custom/_comments.html',
                                         parent_id=parent_id,
                                         has_method_POST=has_method_POST)
    return return_content
Example #16
0
    def test_jstree_parse_blog_node(self):
        from pillar.web.utils.jstree import jstree_parse_node

        node_doc = {'_id': ObjectId('55f338f92beb3300c4ff99fe'),
                    '_created': parse('2015-09-11T22:26:33.000+0200'),
                    '_updated': parse('2015-10-30T22:44:27.000+0100'),
                    '_etag': '5248485b4ea7e55e858ff84b1bd4aae88917a37c',
                    'picture': ObjectId('55f338f92beb3300c4ff99de'),
                    'description': 'Play the full movie and see how it was cobbled together.',
                    'parent': ObjectId('55f338f92beb3300c4ff99f9'),
                    'project': self.project_id,
                    'node_type': 'blog',
                    'user': ObjectId('552b066b41acdf5dec4436f2'),
                    'properties': {'status': 'published',
                                   'file': ObjectId('55f338f92beb3300c4ff99c2'),
                                   'content_type': 'file'},
                    'name': 'Live <strong>Edit</strong>'}

        with self.app.test_request_context():
            parsed = jstree_parse_node(Node(node_doc))

        self.assertEqual(parsed, {
            'id': 'n_55f338f92beb3300c4ff99fe',
            'a_attr': {'href': '/blog/'},
            'li_attr': {'data-node-type': 'blog'},
            'text': Markup('Live &lt;strong&gt;Edit&lt;/strong&gt;'),
            'type': 'blog',
            'children': False,
            'custom_view': True,
        })
Example #17
0
def jstree(node_id):
    """JsTree view.

    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>/jstree (construct the whole
      expanded tree starting from the node_id. Use only once)
    - https://pillar/<node_id>/jstree&children=1 (deliver the
      children of a node - use in the navigation of the tree)
    """

    # Get node with basic embedded data
    api = system_util.pillar_api()
    node = Node.find(node_id, api=api)

    if request.args.get('children') != '1':
        return jsonify(items=jstree_build_from_node(node))

    if node.node_type == '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)

    return jsonify(jstree_build_children(node))
Example #18
0
def comment_edit(comment_id):
    """Allows a user to edit their comment."""
    from pillar.web import jinja

    api = system_util.pillar_api()

    comment = Node({'_id': comment_id})
    result = comment.patch({'op': 'edit', 'content': request.form['content']}, api=api)
    assert result['_status'] == 'OK'

    return jsonify({
        'status': 'success',
        'data': {
            'content': result.properties.content or '',
            'content_html': jinja.do_markdowned(result.properties, 'content'),
        }})
Example #19
0
def feeds_blogs():
    """Global feed generator for latest blogposts across all projects"""
    feed = AtomFeed('Blender Cloud - Latest updates',
                    feed_url=request.url, url=request.url_root)
    # Get latest blog posts
    api = system_util.pillar_api()
    latest_posts = Node.all({
        'where': {'node_type': 'post', 'properties.status': 'published'},
        'embedded': {'user': 1},
        'sort': '-_created',
        'max_results': '15'
        }, api=api)

    # Populate the feed
    for post in latest_posts._items:
        author = post.user.fullname
        updated = post._updated if post._updated else post._created
        url = url_for_node(node=post)
        content = post.properties.content[:500]
        content = u'<p>{0}... <a href="{1}">Read more</a></p>'.format(content, url)
        feed.add(post.name, unicode(content),
                 content_type='html',
                 author=author,
                 url=url,
                 updated=updated,
                 published=post._created)
    return feed.get_response()
Example #20
0
    def projects(self):
        """Get list of project for the user"""
        # Find node_type project id (this could become static)
        node_type = NodeType.find_first({
            'where': '{"name" : "project"}',
        },
                                        api=self.api)
        if not node_type: return abort(404)

        # Define key for querying for the project
        if self.is_organization:
            user_path = 'properties.organization'
        else:
            user_path = 'user'

        # Query for the project
        # TODO currently, this system is weak since we rely on the user property
        # of a node when searching for a project using the user it. This allows
        # us to find a project that belongs to an organization also by requesting
        # the user that originally created the node. This can be fixed by
        # introducing a 'user' property in the project node type.

        projects = Node.all({
            'where': '{"node_type" : "%s", "%s": "%s"}'\
                % (node_type._id, user_path, self._id),
            }, api=self.api)

        for project in projects._items:
            attach_project_pictures(project, self.api)

        return projects
Example #21
0
def view_embed(node_id):
    api = system_util.pillar_api()

    # Get node, we'll embed linked objects later.
    try:
        node = Node.find(node_id, api=api)
    except ResourceNotFound:
        return render_template('errors/404_embed.html')
    except ForbiddenAccess:
        return render_template('errors/403_embed.html')

    project_projection = {'project': {'url': 1, 'name': 1}}
    project = Project.find(node.project, project_projection, api=api)

    node.picture = get_file(node.picture, api=api)
    node.user = node.user and User.find(node.user, api=api)

    write_access = 'PUT' in (node.allowed_methods or set())

    extra_template_args = {'project': project}

    return render_template(
        'nodes/custom/dillo_post/view_embed.html',
        node_id=node._id,
        node=node,
        write_access=write_access,
        api=api,
        **extra_template_args)
Example #22
0
def posts_create(project_id):
    api = SystemUtility.attract_api()
    node_type = NodeType.find_first(
        {
            'where': '{"name" : "blog"}',
            'projection': '{"name": 1}'
        }, api=api)
    blog = Node.find_first(
        {
            'where':
            '{"node_type" : "%s", \
            "parent": "%s"}' % (node_type._id, project_id),
        },
        api=api)
    node_type = NodeType.find_first({
        'where': '{"name" : "post"}',
    }, api=api)
    form = get_node_form(node_type)
    if form.validate_on_submit():
        user_id = current_user.objectid
        if process_node_form(form, node_type=node_type, user=user_id):
            return redirect(url_for('main_blog'))
    form.parent.data = blog._id
    return render_template('nodes/custom/post/create.html',
                           node_type=node_type,
                           form=form,
                           project_id=project_id)
Example #23
0
    def test_jstree_parse_just_created_node(self):
        from pillar.web.utils.jstree import jstree_parse_node

        node_doc = {
            '_id': ObjectId('55f338f92beb3300c4ff99fe'),
            '_created': parse('2015-09-11T22:26:33.000+0200'),
            '_updated': parse('2015-10-30T22:44:27.000+0100'),
            '_etag': '5248485b4ea7e55e858ff84b1bd4aae88917a37c',
            'project': self.project_id,
            'node_type': 'asset',
            'user': ObjectId('552b066b41acdf5dec4436f2'),
            'name': 'Live <strong>Edit</strong>'
        }

        with self.app.test_request_context():
            parsed = jstree_parse_node(Node(node_doc))

        self.assertEqual(
            parsed, {
                'id': 'n_55f338f92beb3300c4ff99fe',
                'a_attr': {
                    'href':
                    f"/p/{self.project['url']}/55f338f92beb3300c4ff99fe"
                },
                'li_attr': {
                    'data-node-type': 'asset'
                },
                'text': Markup('Live &lt;strong&gt;Edit&lt;/strong&gt;'),
                'type': 'asset',
                'children': False,
                'custom_view': False,
            })
Example #24
0
def jstree(node_id):
    """JsTree view.

    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>/jstree (construct the whole
      expanded tree starting from the node_id. Use only once)
    - https://pillar/<node_id>/jstree&children=1 (deliver the
      children of a node - use in the navigation of the tree)
    """

    # Get node with basic embedded data
    api = system_util.pillar_api()
    node = Node.find(node_id, api=api)

    if request.args.get('children') != '1':
        return jsonify(items=jstree_build_from_node(node))

    if node.node_type == '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)

    return jsonify(jstree_build_children(node))
Example #25
0
    def load_latest(list_of_ids, node_type=None):
        """Loads a list of IDs in reversed order."""

        if not list_of_ids:
            return []

        # Construct query parameters outside the loop.
        projection = {'name': 1, 'user': 1, 'node_type': 1, 'project': 1,
                      'properties.url': 1, 'properties.content_type': 1,
                      'picture': 1}
        params = {'projection': projection, 'embedded': {'user': 1}}

        if node_type == 'post':
            projection['properties.content'] = 1
        elif node_type == 'asset':
            projection['description'] = 1

        list_latest = []
        for node_id in reversed(list_of_ids or ()):
            try:
                node_item = Node.find(node_id, params, api=api)

                node_item.picture = utils.get_file(node_item.picture, api=api)
                list_latest.append(node_item)
            except ForbiddenAccess:
                pass
            except ResourceNotFound:
                log.warning('Project %s refers to removed node %s!',
                            project._id, node_id)

        return list_latest
Example #26
0
    def projects(self):
        """Get list of project for the user"""
        # Find node_type project id (this could become static)
        node_type = NodeType.find_first({
            'where': '{"name" : "project"}',
            }, api=self.api)
        if not node_type: return abort(404)

        # Define key for querying for the project
        if self.is_organization:
            user_path = 'properties.organization'
        else:
            user_path = 'user'

        # Query for the project
        # TODO currently, this system is weak since we rely on the user property
        # of a node when searching for a project using the user it. This allows
        # us to find a project that belongs to an organization also by requesting
        # the user that originally created the node. This can be fixed by
        # introducing a 'user' property in the project node type.

        projects = Node.all({
            'where': '{"node_type" : "%s", "%s": "%s"}'\
                % (node_type._id, user_path, self._id),
            }, api=self.api)

        for project in projects._items:
            attach_project_pictures(project, self.api)

        return projects
Example #27
0
def find_for_comment(project, node):
    """Returns the URL for a comment."""

    api = system_util.pillar_api()

    parent = node
    while parent.node_type == 'comment':
        if isinstance(parent.parent, pillarsdk.Resource):
            parent = parent.parent
            continue

        try:
            parent = Node.find(parent.parent, api=api)
        except ResourceNotFound:
            log.warning(
                'url_for_node(node_id=%r): Unable to find parent node %r',
                node['_id'], parent.parent)
            raise ValueError('Unable to find parent node %r' % parent.parent)

    # Find the redirection URL for the parent node.
    parent_url = find_url_for_node(parent)
    if '#' in parent_url:
        # We can't attach yet another fragment, so just don't link to
        # the comment for now.
        return parent_url
    return parent_url + '#{}'.format(node['_id'])
Example #28
0
def add_featured_node():
    """Feature a node in a project. This method belongs here, because it affects
    the project node itself, not the asset.
    """
    api = system_util.pillar_api()
    node = Node.find(request.form['node_id'], api=api)
    action = project_update_nodes_list(node, project_id=node.project, list_name='featured')
    return jsonify(status='success', data=dict(action=action))
Example #29
0
def add_featured_node():
    """Feature a node in a project. This method belongs here, because it affects
    the project node itself, not the asset.
    """
    api = system_util.pillar_api()
    node = Node.find(request.form['node_id'], api=api)
    action = project_update_nodes_list(node, list_name='featured')
    return jsonify(status='success', data=dict(action=action))
Example #30
0
def posts_create(project_id):
    api = system_util.pillar_api()
    try:
        project = Project.find(project_id, api=api)
    except ResourceNotFound:
        return abort(404)
    attach_project_pictures(project, api)

    blog = Node.find_one(
        {'where': {
            'node_type': 'blog',
            'project': project_id
        }}, api=api)
    node_type = project.get_node_type('post')
    # Check if user is allowed to create a post in the blog
    if not project.node_type_has_method('post', 'POST', api=api):
        return abort(403)
    form = get_node_form(node_type)
    if form.validate_on_submit():
        # Create new post object from scratch
        post_props = dict(node_type='post',
                          name=form.name.data,
                          picture=form.picture.data,
                          user=current_user.objectid,
                          parent=blog._id,
                          project=project._id,
                          properties=dict(content=form.content.data,
                                          status=form.status.data,
                                          url=form.url.data))
        if form.picture.data == '':
            post_props['picture'] = None
        post = Node(post_props)
        post.create(api=api)
        # Only if the node is set as published, push it to the list
        if post.properties.status == 'published':
            project_update_nodes_list(post,
                                      project_id=project._id,
                                      list_name='blog')
        return redirect(url_for_node(node=post))
    form.parent.data = blog._id
    return render_template('nodes/custom/post/create.html',
                           node_type=node_type,
                           form=form,
                           project=project,
                           api=api)
Example #31
0
def posts_view(project_id, url=None):
    """View individual blogpost"""
    api = SystemUtility.attract_api()
    node_type = NodeType.find_first(
        {
            'where': '{"name" : "blog"}',
            'projection': '{"name": 1}'
        }, api=api)
    blog = Node.find_one(
        {
            'where':
            '{"node_type" : "%s", \
            "parent": "%s"}' % (node_type._id, project_id),
        },
        api=api)
    if url:
        try:
            post = Node.find_one(
                {
                    'where':
                    '{"parent": "%s", "properties.url": "%s"}' %
                    (blog._id, url),
                    'embedded':
                    '{"picture":1, "node_type": 1}',
                },
                api=api)
        except ResourceNotFound:
            return abort(404)

        return render_template('nodes/custom/post/view.html',
                               blog=blog,
                               node=post)
    else:
        # Render all posts
        posts = Node.all(
            {
                'where': '{"parent": "%s"}' % (blog._id),
                'embedded': '{"picture":1}',
                'sort': '-_created'
            },
            api=api)
        return render_template('nodes/custom/blog/index.html',
                               blog=blog,
                               posts=posts._items)
Example #32
0
def assets_create():
    project_id = request.form['project_id']
    name = request.form['name']
    parent_id = request.form.get('parent_id')
    # Detect filetype by extension (improve by detectin real file type)
    root, ext = os.path.splitext(name)
    if ext in ['.jpg', '.jpeg', '.png', '.tif', '.tiff']:
        filetype = 'image'
    elif ext in ['.blend', '.txt', '.zip']:
        filetype = 'file'
    elif ext in ['.mov', '.avi', '.mp4', '.m4v']:
        filetype = 'video'
    else:
        filetype = 'file'

    api = system_util.pillar_api()
    # We will create the Node object later on, after creating the file object
    node_asset_props = dict(
        name=name,
        project=project_id,
        user=current_user.objectid,
        node_type='asset',
        properties=dict(
            content_type=filetype,
            status='processing'))

    if filetype == 'file':
        mime_type_base = 'application'
    else:
        mime_type_base = filetype
    mime_type = "{0}/{1}".format(mime_type_base, ext.replace(".", ""))
    node_file = process_and_create_file(project_id, name, 0, mime_type)

    node_asset_props['properties']['file'] = node_file._id
    if parent_id:
        node_asset_props['parent'] = parent_id
    node_asset = Node(node_asset_props)
    node_asset.create(api=api)

    return jsonify(
        #link=link,
        name=name,
        filetype=filetype,
        asset_id=node_asset._id)
Example #33
0
def delete_node():
    """Delete a node"""
    api = system_util.pillar_api()
    node = Node.find(request.form['node_id'], api=api)
    if not node.has_method('DELETE'):
        return abort(403)

    node.delete(api=api)

    return jsonify(status='success', data=dict(message='Node deleted'))
Example #34
0
def delete_node():
    """Delete a node"""
    api = system_util.pillar_api()
    node = Node.find(request.form['node_id'], api=api)
    if not node.has_method('DELETE'):
        return abort(403)

    node.delete(api=api)

    return jsonify(status='success', data=dict(message='Node deleted'))
Example #35
0
def projects_move_node():
    # Process the move action
    node_id = request.form['node_id']
    dest_parent_node_id = request.form['dest_parent_node_id']

    api = SystemUtility.attract_api()
    node = Node.find(node_id, api=api)
    node.parent = dest_parent_node_id
    node.update(api=api)
    return jsonify(status='success', data=dict(message='node moved'))
Example #36
0
def _homepage_context() -> dict:
    """Returns homepage template context variables."""

    # Get latest blog posts
    api = system_util.pillar_api()

    # Get latest comments to any node
    latest_comments = Node.latest('comments', api=api)

    # Get a list of random featured assets
    random_featured = get_random_featured_nodes()

    # Parse results for replies
    to_remove = []

    @functools.lru_cache()
    def _find_parent(parent_node_id) -> Node:
        return Node.find(parent_node_id, {
            'projection': {
                '_id': 1,
                'name': 1,
                'node_type': 1,
                'project': 1,
                'parent': 1,
                'properties.url': 1,
            }
        },
                         api=api)

    for idx, comment in enumerate(latest_comments._items):
        if comment.properties.is_reply:
            try:
                comment.attached_to = _find_parent(comment.parent.parent)
            except ResourceNotFound:
                # Remove this comment
                to_remove.append(idx)
        else:
            comment.attached_to = comment.parent

    for idx in reversed(to_remove):
        del latest_comments._items[idx]

    for comment in latest_comments._items:
        if not comment.attached_to:
            continue
        comment.attached_to.url = url_for_node(node=comment.attached_to)
        comment.url = url_for_node(node=comment)

    main_project = Project.find(current_app.config['MAIN_PROJECT_ID'], api=api)
    main_project.picture_header = get_file(main_project.picture_header,
                                           api=api)

    return dict(main_project=main_project,
                latest_comments=latest_comments._items,
                random_featured=random_featured)
Example #37
0
def view_node(project_url, node_id):
    """Entry point to view a node in the context of a project"""
    # Some browsers mangle URLs and URL-encode /p/{p-url}/#node-id
    if node_id.startswith('#'):
        return redirect(url_for('projects.view_node',
                                project_url=project_url,
                                node_id=node_id[1:]),
                        code=301)  # permanent redirect

    theatre_mode = 't' in request.args
    api = system_util.pillar_api()
    # First we check if it's a simple string, in which case we are looking for
    # a static page. Maybe we could use bson.objectid.ObjectId.is_valid(node_id)
    if not utils.is_valid_id(node_id):
        # raise wz_exceptions.NotFound('No such node')
        project, node = render_node_page(project_url, node_id, api)
    else:
        # Fetch the node before the project. If this user has access to the
        # node, we should be able to get the project URL too.
        try:
            node = Node.find(node_id, api=api)
        except ForbiddenAccess:
            return render_template('errors/403.html'), 403
        except ResourceNotFound:
            raise wz_exceptions.NotFound('No such node')

        try:
            project = Project.find_one({'where': {"url": project_url, '_id': node.project}},
                                       api=api)
        except ResourceNotFound:
            # In theatre mode, we don't need access to the project at all.
            if theatre_mode:
                project = None
            else:
                raise wz_exceptions.NotFound('No such project')

    og_picture = node.picture = utils.get_file(node.picture, api=api)
    if project:
        if not node.picture:
            og_picture = utils.get_file(project.picture_header, api=api)
        project.picture_square = utils.get_file(project.picture_square, api=api)

    # Append _theatre to load the proper template
    theatre = '_theatre' if theatre_mode else ''

    extension_sidebar_links = current_app.extension_sidebar_links(project)

    return render_template('projects/view{}.html'.format(theatre),
                           api=api,
                           project=project,
                           node=node,
                           show_node=True,
                           show_project=False,
                           og_picture=og_picture,
                           extension_sidebar_links=extension_sidebar_links)
Example #38
0
def assets_create():
    project_id = request.form['project_id']
    name = request.form['name']
    parent_id = request.form.get('parent_id')
    # Detect filetype by extension (improve by detectin real file type)
    root, ext = os.path.splitext(name)
    if ext in ['.jpg', '.jpeg', '.png', '.tif', '.tiff']:
        filetype = 'image'
    elif ext in ['.blend', '.txt', '.zip']:
        filetype = 'file'
    elif ext in ['.mov', '.avi', '.mp4', '.m4v']:
        filetype = 'video'
    else:
        filetype = 'file'

    api = system_util.pillar_api()
    # We will create the Node object later on, after creating the file object
    node_asset_props = dict(name=name,
                            project=project_id,
                            user=current_user.objectid,
                            node_type='asset',
                            properties=dict(content_type=filetype,
                                            status='processing'))

    if filetype == 'file':
        mime_type_base = 'application'
    else:
        mime_type_base = filetype
    mime_type = "{0}/{1}".format(mime_type_base, ext.replace(".", ""))
    node_file = process_and_create_file(project_id, name, 0, mime_type)

    node_asset_props['properties']['file'] = node_file._id
    if parent_id:
        node_asset_props['parent'] = parent_id
    node_asset = Node(node_asset_props)
    node_asset.create(api=api)

    return jsonify(
        #link=link,
        name=name,
        filetype=filetype,
        asset_id=node_asset._id)
Example #39
0
def create():
    """Create a node. Requires a number of params:

    - project id
    - node_type
    - parent node (optional)
    """
    if request.method != 'POST':
        return abort(403)

    project_id = request.form['project_id']
    parent_id = request.form.get('parent_id')
    node_type_name = request.form['node_type_name']

    api = system_util.pillar_api()
    # Fetch the Project or 404
    try:
        project = Project.find(project_id, api=api)
    except ResourceNotFound:
        return abort(404)

    node_type = project.get_node_type(node_type_name)
    node_type_name = 'folder' if node_type['name'] == 'group' else \
        node_type['name']

    node_props = dict(
        name='New {}'.format(node_type_name),
        project=project['_id'],
        user=current_user.objectid,
        node_type=node_type['name'],
        properties={}
    )

    if parent_id:
        node_props['parent'] = parent_id

    ensure_lists_exist_as_empty(node_props, node_type)

    node = Node(node_props)
    node.create(api=api)

    return jsonify(status='success', data=dict(asset_id=node['_id']))
Example #40
0
 def _find_parent(parent_node_id) -> Node:
     return Node.find(parent_node_id, {
         'projection': {
             '_id': 1,
             'name': 1,
             'node_type': 1,
             'project': 1,
             'parent': 1,
             'properties.url': 1,
         }
     },
                      api=api)
Example #41
0
def create():
    """Create a node. Requires a number of params:

    - project id
    - node_type
    - parent node (optional)
    """
    if request.method != 'POST':
        return abort(403)

    project_id = request.form['project_id']
    parent_id = request.form.get('parent_id')
    node_type_name = request.form['node_type_name']

    api = system_util.pillar_api()
    # Fetch the Project or 404
    try:
        project = Project.find(project_id, api=api)
    except ResourceNotFound:
        return abort(404)

    node_type = project.get_node_type(node_type_name)
    node_type_name = 'folder' if node_type['name'] == 'group' else \
        node_type['name']

    node_props = dict(name='New {}'.format(node_type_name),
                      project=project['_id'],
                      user=current_user.objectid,
                      node_type=node_type['name'],
                      properties={})

    if parent_id:
        node_props['parent'] = parent_id

    ensure_lists_exist_as_empty(node_props, node_type)

    node = Node(node_props)
    node.create(api=api)

    return jsonify(status='success', data=dict(asset_id=node['_id']))
Example #42
0
def render_comments_for_node(node_id: str, *, can_post_comments: bool):
    """Render the list of comments for a node."""
    api = system_util.pillar_api()

    # Query for all children, i.e. comments on the node.
    comments = Node.all({
        'where': {'node_type': 'comment', 'parent': node_id},
    }, api=api)

    def enrich(some_comment):
        some_comment['_user'] = subquery.get_user_info(some_comment['user'])
        some_comment['_is_own'] = some_comment['user'] == current_user.objectid
        some_comment['_current_user_rating'] = None  # tri-state boolean
        some_comment[
            '_rating'] = some_comment.properties.rating_positive - some_comment.properties.rating_negative

        if current_user.is_authenticated:
            for rating in some_comment.properties.ratings or ():
                if rating.user != current_user.objectid:
                    continue

                some_comment['_current_user_rating'] = rating.is_positive

    for comment in comments['_items']:
        # Query for all grandchildren, i.e. replies to comments on the node.
        comment['_replies'] = Node.all({
            'where': {'node_type': 'comment', 'parent': comment['_id']},
        }, api=api)

        enrich(comment)
        for reply in comment['_replies']['_items']:
            enrich(reply)
    nr_of_comments = sum(1 + comment['_replies']['_meta']['total']
                         for comment in comments['_items'])
    return render_template('nodes/custom/comment/list_embed.html',
                           node_id=node_id,
                           comments=comments,
                           nr_of_comments=nr_of_comments,
                           show_comments=True,
                           can_post_comments=can_post_comments)
Example #43
0
def comments_create():
    content = request.form['content']
    parent_id = request.form.get('parent_id')
    api = system_util.pillar_api()
    parent_node = Node.find(parent_id, api=api)

    node_asset_props = dict(project=parent_node.project,
                            name='Comment',
                            user=current_user.objectid,
                            node_type='comment',
                            properties=dict(content=content,
                                            status='published',
                                            confidence=0,
                                            rating_positive=0,
                                            rating_negative=0))

    if parent_id:
        node_asset_props['parent'] = parent_id

    # Get the parent node and check if it's a comment. In which case we flag
    # the current comment as a reply.
    parent_node = Node.find(parent_id, api=api)
    if parent_node.node_type == 'comment':
        node_asset_props['properties']['is_reply'] = True

    node_asset = Node(node_asset_props)
    node_asset.create(api=api)

    return jsonify(asset_id=node_asset._id,
                   content=node_asset.properties.content)
Example #44
0
def jstree_get_children(node_id, project_id=None):
    api = system_util.pillar_api()
    children_list = []
    lookup = {
        'projection': {
            'name': 1,
            'parent': 1,
            'node_type': 1,
            'properties.order': 1,
            'properties.status': 1,
            'properties.content_type': 1,
            'user': 1,
            'project': 1
        },
        'sort': [('properties.order', 1), ('_created', 1)],
        'where': {
            '$and': [
                {
                    'node_type': {
                        '$regex': '^(?!attract_)'
                    }
                },
                {
                    'node_type': {
                        '$not': {
                            '$in': ['comment', 'post']
                        }
                    }
                },
            ],
        }
    }
    if node_id:
        if node_id.startswith('n_'):
            node_id = node_id.split('_')[1]
        lookup['where']['parent'] = node_id
    elif project_id:
        lookup['where']['project'] = project_id
        lookup['where']['parent'] = {'$exists': False}

    try:
        children = Node.all(lookup, api=api)
        for child in children['_items']:
            # TODO: allow nodes that don't have a status property to be visible
            # in the node tree (for example blog)
            is_pub = child.properties.status == 'published'
            if is_pub or (current_user.is_authenticated
                          and child.user == current_user.objectid):
                children_list.append(jstree_parse_node(child))
    except ForbiddenAccess:
        pass
    return children_list
Example #45
0
def get_node_children(node_id, node_type_name, user_id):
    """This function is currently unused since it does not give significant
    performance improvements.
    """
    api = system_util.pillar_api()
    if node_type_name == 'group':
        published_status = ',"properties.status": "published"'
    else:
        published_status = ''

    children = Node.all({
        'where': '{"parent": "%s" %s}' % (node_id, published_status),
        'embedded': '{"node_type": 1}'}, api=api)
    return children.to_dict()
Example #46
0
def comments_index():
    parent_id = request.args.get('parent_id')

    if request.args.get('format'):

        # Get data only if we format it
        api = SystemUtility.attract_api()
        node_type = NodeType.find_first({
            'where': '{"name" : "comment"}',
            }, api=api)

        nodes = Node.all({
            'where': '{"node_type" : "%s", "parent": "%s"}' % (node_type._id, parent_id),
            'embedded': '{"user":1}'}, api=api)

        comments = []
        for comment in nodes._items:

            # Query for first level children (comment replies)
            replies = Node.all({
                'where': '{"node_type" : "%s", "parent": "%s"}' % (node_type._id, comment._id),
                'embedded': '{"user":1}'}, api=api)
            replies = replies._items if replies._items else None

            if replies:
                replies = [format_comment(reply, is_reply=True) for reply in replies]

            comments.append(
                format_comment(comment, is_reply=False, replies=replies))

        if request.args.get('format') == 'json':
            return_content = jsonify(items=comments)
    else:
        # Data will be requested via javascript
        return_content = render_template('nodes/custom/_comments.html',
            parent_id=parent_id)
    return return_content
Example #47
0
def index():
    """Custom production stats entry point
    """
    api = SystemUtility.attract_api()
    node_type_list = NodeType.all(
        {'where': '{"name": "%s"}' % ('shot')}, api=api)

    node_type = node_type_list['_items'][0]
    nodes = Node.all({
        'where': '{"node_type": "%s"}' % (node_type['_id']),
        'max_results': 100,
        'sort' : "order"}, api=api)

    node_statuses = {}

    node_totals = {
        'count': 0,
        'frames': 0
    }

    for shot in nodes._items:
        status = shot.properties.status
        if status not in node_statuses:
            # If they key does not exist, initialize with defaults
            node_statuses[status] = {
                'count': 0,
                'frames': 0}

        # Calculate shot duration and increase status count
        frames = shot.properties.cut_out - shot.properties.cut_in
        node_statuses[status]['count'] += 1
        node_statuses[status]['frames'] += frames
        # Update the global stats
        node_totals['count'] += 1
        node_totals['frames'] += frames

    for node_status in node_statuses:
        # Calculate completion percentage based on total duration
        print node_statuses[node_status]['frames']
        print node_totals['frames']
        node_statuses[node_status]['completion'] = percentage(
            node_statuses[node_status]['frames'], node_totals['frames'])

    return render_template(
        'stats/index.html',
        node_statuses=node_statuses)
Example #48
0
def get_projects(category):
    """Utility to get projects based on category. Should be moved on the API
    and improved with more extensive filtering capabilities.
    """
    api = SystemUtility.attract_api()
    node_type = NodeType.find_first({
        'where': '{"name" : "project"}',
        'projection': '{"name": 1}'
        }, api=api)
    projects = Node.all({
        'where': '{"node_type" : "%s", \
            "properties.category": "%s"}' % (node_type._id, category),
        'embedded': '{"picture":1}',
        }, api=api)
    for project in projects._items:
        attach_project_pictures(project, api)
    return projects
Example #49
0
def index(node_type_name=""):
    """Generic function to list all nodes
    """
    # Pagination index
    page = request.args.get('page', 1)
    max_results = 50

    api = SystemUtility.attract_api()
    if node_type_name == "":
        node_type_name = "shot"

    node_type = NodeType.find_first({
        'where': '{"name" : "%s"}' % node_type_name,
        }, api=api)

    if not node_type:
        return "Empty NodeType list", 200

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

    # Build the pagination object
    pagination = Pagination(int(page), max_results, nodes._meta.total)

    template = '{0}/index.html'.format(node_type_name)
    try:
        return render_template(
            template,
            title=node_type_name,
            nodes=nodes,
            node_type=node_type,
            type_names=type_names(),
            pagination=pagination)
    except TemplateNotFound:
        return render_template(
            'nodes/index.html',
            title=node_type_name,
            nodes=nodes,
            node_type=node_type,
            type_names=type_names(),
            pagination=pagination)
Example #50
0
def delete(node_id):
    """Generic node deletion
    """
    api = SystemUtility.attract_api()
    node = Node.find(node_id, api=api)
    name = node.name
    node_type = NodeType.find(node.node_type, api=api)
    try:
        node.delete(api=api)
        forbidden = False
    except ForbiddenAccess:
        forbidden = True

    if not forbidden:
        # print (node_type['name'])
        return redirect(url_for('nodes.index', node_type_name=node_type['name']))
    else:
        return redirect(url_for('nodes.edit', node_id=node._id))
Example #51
0
def jstree_get_children(node_id):
    api = SystemUtility.attract_api()
    children_list = []

    if node_id.startswith('n_'):
        node_id = node_id.split('_')[1]
    try:
        children = Node.all({
            'projection': '{"name": 1, "parent": 1, "node_type": 1, "properties": 1}',
            'embedded': '{"node_type": 1}',
            'where': '{"parent": "%s"}' % node_id}, api=api)
        for child in children._items:
            # Skip nodes of type comment
            if child.node_type.name != 'comment':
                children_list.append(jstree_parse_node(child))
    except ForbiddenAccess:
        pass

    return children_list
Example #52
0
def toggle_node_public():
    """Give a node GET permissions for the world. Later on this can turn into
    a more powerful permission management function.
    """
    api = system_util.pillar_api()
    node = Node.find(request.form['node_id'], api=api)
    if node.has_method('PUT'):
        if node.permissions and 'world' in node.permissions.to_dict():
            node.permissions = {}
            message = "Node is not public anymore."
        else:
            node.permissions = dict(world=['GET'])
            message = "Node is now public!"
        node.update(api=api)
        # Delete cached parent template fragment
        delete_redis_cache_template('group_view', node.parent)
        return jsonify(status='success', data=dict(message=message))
    else:
        return abort(403)
Example #53
0
def shot_edit():
    """We want to be able to edit the following properties:
    - notes
    - status
    - cut in
    - cut out
    - picture (optional)
    """
    api = system_util.pillar_api()
    shot_id = request.form['shot_id']

    shot = Node.find(shot_id, api=api)
    shot.properties.notes = request.form['shot_notes']
    shot.properties.status = request.form['shot_status']
    shot.properties.cut_in = int(request.form['shot_cut_in'])
    shot.properties.cut_out = int(request.form['shot_cut_out'])

    shot.update(api=api)

    return jsonify(shot.to_dict())
Example #54
0
def move_node():
    """Move a node within a project. While this affects the node.parent prop, we
    keep it in the scope of the project."""
    node_id = request.form['node_id']
    dest_parent_node_id = request.form.get('dest_parent_node_id')

    api = system_util.pillar_api()
    node = Node.find(node_id, api=api)
    # Get original parent id for clearing template fragment on success
    previous_parent_id = node.parent
    if dest_parent_node_id:
        node.parent = dest_parent_node_id
    elif node.parent:
        node.parent = None
    node.update(api=api)
    # Delete cached parent template fragment
    if node.parent:
        delete_redis_cache_template('group_view', node.parent)
    if previous_parent_id:
        delete_redis_cache_template('group_view', previous_parent_id)
    return jsonify(status='success', data=dict(message='node moved'))
Example #55
0
    def find_for_comment():
        """Returns the URL for a comment."""

        parent = node
        while parent.node_type == 'comment':
            if isinstance(parent.parent, pillarsdk.Resource):
                parent = parent.parent
                continue

            try:
                parent = Node.find(parent.parent, api=api)
            except ResourceNotFound:
                log.warning('url_for_node(node_id=%r): Unable to find parent node %r',
                            node_id, parent.parent)
                raise ValueError('Unable to find parent node %r' % parent.parent)

        # Find the redirection URL for the parent node.
        parent_url = url_for_node(node=parent)
        if '#' in parent_url:
            # We can't attach yet another fragment, so just don't link to the comment for now.
            return parent_url
        return parent_url + '#{}'.format(node_id)
Example #56
0
def posts_create(project_id):
    api = SystemUtility.attract_api()
    node_type = NodeType.find_first({
        'where': '{"name" : "blog"}',
        'projection': '{"name": 1}'
        }, api=api)
    blog = Node.find_first({
        'where': '{"node_type" : "%s", \
            "parent": "%s"}' % (node_type._id, project_id),
        }, api=api)
    node_type = NodeType.find_first({'where': '{"name" : "post"}',}, api=api)
    form = get_node_form(node_type)
    if form.validate_on_submit():
        user_id = current_user.objectid
        if process_node_form(
                form, node_type=node_type, user=user_id):
            return redirect(url_for('main_blog'))
    form.parent.data = blog._id
    return render_template('nodes/custom/post/create.html',
        node_type=node_type,
        form=form,
        project_id=project_id)
Example #57
0
    def project(self, project_name):
        """Get single project for one user. The project is searched by looking
        up project directly associated with that user or organization."""
        # Find node_type project id (this could become static)
        node_type = NodeType.find_first({
            'where': '{"name" : "project"}',
            }, api=self.api)
        if not node_type: return abort(404)


        # Define key for querying for the project
        if self.is_organization:
            user_path = 'properties.organization'
        else:
            user_path = 'user'

        project_node = Node.find_first({
        'where': '{"node_type" : "%s", "properties.url" : "%s", "%s": "%s"}'\
            % (node_type._id, project_name, user_path, self._id),
        }, api=self.api)
        if not project_node: return abort(404)
        return project_node
Example #58
0
def project_update_nodes_list(node_id, project_id=None, list_name='latest'):
    """Update the project node with the latest edited or favorited node.
    The list value can be 'latest' or 'featured' and it will determined where
    the node reference will be placed in.
    """
    if not project_id and 'current_project_id' in session:
        project_id = session['current_project_id']
    elif not project_id:
        return None
    api = SystemUtility.attract_api()
    project = Node.find(project_id, api=api)
    if list_name == 'latest':
        nodes_list = project.properties.nodes_latest
    else:
        nodes_list = project.properties.nodes_featured

    # Do not allow adding project to lists
    if node_id == project._id:
        return "fail"

    if not nodes_list:
        node_list_name = 'nodes_' + list_name
        project.properties[node_list_name] = []
        nodes_list = project.properties[node_list_name]
    elif len(nodes_list) > 5:
        nodes_list.pop(0)

    if node_id in nodes_list:
        # Pop to put this back on top of the list
        nodes_list.remove(node_id)
        if list_name == 'featured':
            # We treat the action as a toggle and do not att the item back
            project.update(api=api)
            return "removed"

    nodes_list.append(node_id)
    project.update(api=api)
    return "added"