示例#1
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)
示例#2
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())
示例#3
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)
示例#4
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)
示例#5
0
    def __init__(self, name):
        self.api = SystemUtility.attract_api()
        # Check if organization exists
        user = Organization.find_first({
            'where': '{"url" : "%s"}' % (name),
        },
                                       api=self.api)

        if user:
            self.is_organization = True
            self.name = user.name
            self.url = user.url
            self.description = user.description
            self.gravatar = gravatar(user.email)
        else:
            # Check if user exists
            user = User.find_first({
                'where': '{"username" : "%s"}' % (name),
            },
                                   api=self.api)
            if user:
                self.is_organization = False
                self.name = user.first_name
                self.url = user.username
            else:
                return abort(404)
        self._id = user._id
示例#6
0
def type_names():
    api = SystemUtility.attract_api()

    types = NodeType.all(api=api)['_items']
    type_names = []
    for names in types:
        type_names.append(str(names['name']))
    return type_names
示例#7
0
def type_names():
    api = SystemUtility.attract_api()

    types = NodeType.all(api=api)["_items"]
    type_names = []
    for names in types:
        type_names.append(str(names['name']))
    return type_names
示例#8
0
def tasks():
    """User-assigned tasks"""
    # Pagination index
    page = request.args.get("page", 1)
    max_results = 50

    api = SystemUtility.attract_api()
    node_type_list = NodeType.all({"where": "name=='task'"}, api=api)

    if len(node_type_list["_items"]) == 0:
        return "Empty NodeType list", 200

    node_type = node_type_list._items[0]

    tasks = Node.all(
        {
            "where": '{"node_type" : "%s", "properties.owners.users": {"$in": ["%s"]}}'
            % (node_type["_id"], current_user.objectid),
            "max_results": max_results,
            "page": page,
            "embedded": '{"parent":1, "picture":1}',
            "sort": "order",
        },
        api=api,
    )

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

    tasks_datatable = []
    for task in tasks._items:
        cut_in = 0
        cut_out = 0
        if task.parent.properties.cut_in:
            cut_in = task.parent.properties.cut_in
        if task.parent.properties.cut_out:
            cut_out = task.parent.properties.cut_out
        data = {
            "DT_RowId": "row_{0}".format(task._id),
            "_id": task._id,
            "order": task.order,
            "picture": None,
            "name": task.name,
            "timing": {"cut_in": task.parent.properties.cut_in, "cut_out": task.parent.properties.cut_out},
            "parent": task.parent.to_dict(),
            "description": task.description,
            "url_view": url_for("nodes.view", node_id=task._id),
            "url_edit": url_for("nodes.edit", node_id=task._id, embed=1),
            "status": task.properties.status,
        }

        tasks_datatable.append(data)

    return render_template(
        "users/tasks.html", title="task", tasks_data=json.dumps(tasks_datatable), node_type=node_type
    )
示例#9
0
def tasks():
    """User-assigned tasks"""
    # Pagination index
    page = request.args.get('page', 1)
    max_results = 50

    api = SystemUtility.attract_api()
    node_type_list = NodeType.all({'where': "name=='task'"}, api=api)

    if len(node_type_list['_items']) == 0:
        return "Empty NodeType list", 200

    node_type = node_type_list._items[0]

    tasks = Node.all({
        'where': '{"node_type" : "%s", "properties.owners.users": {"$in": ["%s"]}}'\
                % (node_type['_id'], current_user.objectid),
        'max_results': max_results,
        'page': page,
        'embedded': '{"parent":1, "picture":1}',
        'sort' : "order"}, api=api)

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

    tasks_datatable = []
    for task in tasks._items:
        cut_in = 0
        cut_out = 0
        if task.parent.properties.cut_in:
            cut_in = task.parent.properties.cut_in
        if task.parent.properties.cut_out:
            cut_out = task.parent.properties.cut_out
        data = {
            'DT_RowId': "row_{0}".format(task._id),
            '_id': task._id,
            'order': task.order,
            'picture': None,
            'name': task.name,
            'timing': {
                'cut_in': task.parent.properties.cut_in,
                'cut_out': task.parent.properties.cut_out,
            },
            'parent': task.parent.to_dict(),
            'description': task.description,
            'url_view': url_for('nodes.view', node_id=task._id),
            'url_edit': url_for('nodes.edit', node_id=task._id, embed=1),
            'status': task.properties.status,
        }

        tasks_datatable.append(data)

    return render_template('users/tasks.html',
                           title="task",
                           tasks_data=json.dumps(tasks_datatable),
                           node_type=node_type)
示例#10
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'))
示例#11
0
def assigned_users_to(node, node_type):
    api = SystemUtility.attract_api()

    if node_type['name'] != "task":
        return []
    users = node['properties']['owners']['users']
    owners = []
    for user in users:
        user_node = User.find(user, api=api)
        owners.append(user_node)
    return owners
示例#12
0
def assigned_users_to(node, node_type):
    api = SystemUtility.attract_api()

    if node_type['name'] != "task":
        return []
    users = node['properties']['owners']['users']
    owners = []
    for user in users:
        user_node = User.find(user, api=api)
        owners.append(user_node)
    return owners
示例#13
0
def profile():
    """Profile view and edit page. This is a temporary implementation.
    """
    api = SystemUtility.attract_api()
    user = User.find(current_user.objectid, api=api)

    form = UserProfileForm(first_name=user.first_name, last_name=user.last_name)

    if form.validate_on_submit():
        user.first_name = form.first_name.data
        user.last_name = form.last_name.data
        user.update(api=api)
        flash("Profile updated")

    return render_template("users/profile.html", form=form)
示例#14
0
def authenticate(username, password):
    import requests
    import socket

    payload = dict(username=username, password=password, hostname=socket.gethostname())
    try:
        r = requests.post("{0}/u/identify".format(SystemUtility.blender_id_endpoint()), data=payload)
    except requests.exceptions.ConnectionError as e:
        raise e

    if r.status_code == 200:
        response = r.json()
    else:
        response = None
    return response
示例#15
0
def profile():
    """Profile view and edit page. This is a temporary implementation.
    """
    api = SystemUtility.attract_api()
    user = User.find(current_user.objectid, api=api)

    form = UserProfileForm(first_name=user.first_name,
                           last_name=user.last_name)

    if form.validate_on_submit():
        user.first_name = form.first_name.data
        user.last_name = form.last_name.data
        user.update(api=api)
        flash("Profile updated")

    return render_template('users/profile.html', form=form)
示例#16
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)
示例#17
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
示例#18
0
def index():
    """Generic function to list all nodes
    """
    # Pagination index
    page = request.args.get("page", 1)
    max_results = 50

    api = SystemUtility.attract_api()

    organizations = Organization.all({"max_results": max_results, "page": page}, api=api)

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

    template = "organizations/index.html"

    return render_template(template, title="organizations", organizations=organizations, pagination=pagination)
示例#19
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)
示例#20
0
def add(node_type_id):
    """Generic function to add a node of any type
    """
    api = SystemUtility.attract_api()
    ntype = NodeType.find(node_type_id, api=api)
    form = get_node_form(ntype)
    user_id = current_user.objectid
    if form.validate_on_submit():
        if process_node_form(form, node_type=ntype, user=user_id):
            return redirect(url_for('nodes.index', node_type_name=ntype['name']))
    else:
        print form.errors
    return render_template('nodes/add.html',
        node_type=ntype,
        form=form,
        errors=form.errors,
        type_names=type_names())
示例#21
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)
示例#22
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))
示例#23
0
def add(node_type_id):
    """Generic function to add a node of any type
    """
    api = SystemUtility.attract_api()
    ntype = NodeType.find(node_type_id, api=api)
    form = get_node_form(ntype)
    user_id = current_user.objectid
    if form.validate_on_submit():
        if process_node_form(form, node_type=ntype, user=user_id):
            return redirect(
                url_for('nodes.index', node_type_name=ntype['name']))
    else:
        print form.errors
    return render_template('nodes/add.html',
                           node_type=ntype,
                           form=form,
                           errors=form.errors,
                           type_names=type_names())
示例#24
0
def authenticate(username, password):
    import requests
    import socket
    payload = dict(username=username,
                   password=password,
                   hostname=socket.gethostname())
    try:
        r = requests.post("{0}/u/identify".format(
            SystemUtility.blender_id_endpoint()),
                          data=payload)
    except requests.exceptions.ConnectionError as e:
        raise e

    if r.status_code == 200:
        response = r.json()
    else:
        response = None
    return response
示例#25
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)
示例#26
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
示例#27
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))
示例#28
0
def shot_edit():
    """We want to be able to edit the following properties:
    - notes
    - status
    - cut in
    - cut out
    - picture (optional)
    """
    api = SystemUtility.attract_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())
示例#29
0
def shot_edit():
    """We want to be able to edit the following properties:
    - notes
    - status
    - cut in
    - cut out
    - picture (optional)
    """
    api = SystemUtility.attract_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())
示例#30
0
def create():
    name = request.form['name']
    size = request.form['size']
    content_type = request.form['type']
    root, ext = os.path.splitext(name)
    # Hash name based on file name, user id and current timestamp
    hash_name = name + str(current_user.objectid) + str(round(time.time()))
    link = hashlib.sha1(hash_name).hexdigest()
    link = os.path.join(link[:2], link + ext)

    src_dir_path = os.path.join(app.config['UPLOAD_DIR'],
                                str(current_user.objectid))

    # Move the file in designated location
    destination_dir = os.path.join(app.config['SHARED_DIR'], link[:2])
    if not os.path.isdir(destination_dir):
        os.makedirs(destination_dir)
    # (TODO) Check if filename already exsits
    src_file_path = os.path.join(src_dir_path, name)
    dst_file_path = os.path.join(destination_dir, link[3:])
    # (TODO) Thread this operation

    shutil.copy(src_file_path, dst_file_path)

    api = SystemUtility.attract_api()
    node_file = File({
        'name': link,
        'filename': name,
        'user': current_user.objectid,
        'backend': 'cdnsun',
        'md5': '',
        'content_type': content_type,
        'length': size
    })
    node_file.create(api=api)
    thumbnail = node_file.thumbnail_file('s', api=api)

    return jsonify(status='success',
                   data=dict(id=node_file._id, link=thumbnail.link))
示例#31
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)
示例#32
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"
示例#33
0
def create():
    name = request.form['name']
    size = request.form['size']
    content_type = request.form['type']
    root, ext = os.path.splitext(name)
     # Hash name based on file name, user id and current timestamp
    hash_name = name + str(current_user.objectid) + str(round(time.time()))
    link = hashlib.sha1(hash_name).hexdigest()
    link = os.path.join(link[:2], link + ext)

    src_dir_path = os.path.join(app.config['UPLOAD_DIR'], str(current_user.objectid))

    # Move the file in designated location
    destination_dir = os.path.join(app.config['SHARED_DIR'], link[:2])
    if not os.path.isdir(destination_dir):
        os.makedirs(destination_dir)
    # (TODO) Check if filename already exsits
    src_file_path = os.path.join(src_dir_path, name)
    dst_file_path = os.path.join(destination_dir, link[3:])
    # (TODO) Thread this operation

    shutil.copy(src_file_path, dst_file_path)

    api = SystemUtility.attract_api()
    node_file = File({
        'name': link,
        'filename': name,
        'user': current_user.objectid,
        'backend': 'cdnsun',
        'md5': '',
        'content_type': content_type,
        'length': size
        })
    node_file.create(api=api)
    thumbnail = node_file.thumbnail_file('s', api=api)

    return jsonify(status='success', data=dict(id=node_file._id,
                                                link=thumbnail.link))
示例#34
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"
示例#35
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
示例#36
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
示例#37
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())
示例#38
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
示例#39
0
    def __init__(self, name):
        self.api = SystemUtility.attract_api()
        # Check if organization exists
        user = Organization.find_first({
            'where': '{"url" : "%s"}' % (name),
            }, api=self.api)

        if user:
            self.is_organization = True
            self.name = user.name
            self.url = user.url
            self.description = user.description
            self.gravatar = gravatar(user.email)
        else:
            # Check if user exists
            user = User.find_first({
                'where': '{"username" : "%s"}' % (name),
                }, api=self.api)
            if user:
                self.is_organization = False
                self.name = user.first_name
                self.url = user.username
            else: return abort(404)
        self._id = user._id
示例#40
0
def index():
    """Generic function to list all nodes
    """
    # Pagination index
    page = request.args.get('page', 1)
    max_results = 50

    api = SystemUtility.attract_api()

    organizations = Organization.all({
        'max_results': max_results,
        'page': page
    },
                                     api=api)

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

    template = 'organizations/index.html'

    return render_template(template,
                           title='organizations',
                           organizations=organizations,
                           pagination=pagination)
示例#41
0
def comments_rate(comment_id):
    """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

    """
    rating_is_positive = False if request.form['is_positive'] == 'false' else True

    api = SystemUtility.attract_api()
    comment = Node.find(comment_id, api=api)

    # Check if comment has been rated
    user_comment_rating = None
    if comment.properties.ratings:
        for rating in comment.properties.ratings:
            if rating['user'] == current_user.objectid:
                user_comment_rating = rating
    #r = next((r for r in comment.ratings if r['user'] == current_user.objectid), None)

    if user_comment_rating:
        # Update or remove rating
        if user_comment_rating['is_positive'] == rating_is_positive:
            # If the rating matches, remove the it
            comment.properties.ratings.remove(user_comment_rating)
            # Update global rating values
            if rating_is_positive:
                comment.properties.rating_positive -= 1
            else:
                comment.properties.rating_negative -= 1
            comment.update(api=api)
            return_data = dict(is_rated=False,
                                rating_up=comment.properties.rating_positive)
        else:
            # If the rating differs from the current, update its value. In this
            # case we make sure we update the existing global rating values as well
            user_comment_rating['is_positive'] = rating_is_positive
            if rating_is_positive:
                comment.properties.rating_positive += 1
                comment.properties.rating_negative -= 1
            else:
                comment.properties.rating_negative += 1
                comment.properties.rating_positive -= 1
            comment.update(api=api)
            return_data = dict(is_positive=rating_is_positive, is_rated=True,
                                rating_up=comment.properties.rating_positive)
    else:
        # Create rating for current user
        user_comment_rating = dict(user=current_user.objectid,
                                    is_positive=rating_is_positive,
                                    # Hardcoded to default (auto valid)
                                    weight=3)
        if not comment.properties.ratings:
            comment.properties.ratings = []
        comment.properties.ratings.append(user_comment_rating)
        if rating_is_positive:
            comment.properties.rating_positive += 1
        else:
            comment.properties.rating_negative += 1
        comment.update(api=api)
        return_data = dict(is_positive=rating_is_positive, is_rated=True,
                            rating_up=comment.properties.rating_positive)

    return jsonify(status='success', data=return_data)
示例#42
0
def task_edit():
    """We want to be able to edit the following properties:
    - status
    - owners
    - description
    - picture (optional)
    """
    api = SystemUtility.attract_api()
    task_id = request.form["task_id"]

    task = Node.find(task_id, api=api)
    task.description = request.form["task_description"]
    if request.form["task_revision"]:
        task.properties.revision = int(request.form["task_revision"])
    task.properties.status = request.form["task_status"]
    task.properties.filepath = request.form["task_filepath"]
    task.properties.owners.users = request.form.getlist("task_owners_users[]")

    siblings = Node.all(
        {"where": 'parent==ObjectId("%s")' % task.parent, "embedded": '{"picture":1, "user":1}'}, api=api
    )

    def check_conflict(task_current, task_sibling):
        return revsion_conflict[task_current.name](task_current, task_sibling)

    def task_animation(task_current, task_sibling):
        if task_sibling.name in ["fx_hair", "fx_smoke", "fx_grass", "lighting"]:
            if task_current.properties.revision > task_sibling.properties.revision:
                return True
        return False

    def task_lighting(task_current, task_sibling):
        if task_sibling.name in ["fx_hair", "fx_smoke", "fx_grass", "animation"]:
            if task_current.properties.revision < task_sibling.properties.revision:
                return True
        return False

    def task_fx_hair(task_current, task_sibling):
        if task_sibling.name in ["animation"]:
            if task_current.properties.revision < task_sibling.properties.revision:
                return True
        if task_sibling.name in ["lighting"]:
            if task_current.properties.revision > task_sibling.properties.revision:
                return True
        return False

    def task_fx_grass(task_current, task_sibling):
        pass

    def task_fx_smoke(task_current, task_sibling):
        pass

    revsion_conflict = {
        "animation": task_animation,
        "lighting": task_lighting,
        "fx_hair": task_fx_hair,
        "fx_grass": task_fx_grass,
        "fx_smoke": task_fx_smoke,
    }

    if task.properties.revision:
        for sibling in siblings._items:
            if sibling.properties.revision and sibling._id != task_id:
                if check_conflict(task, sibling) == True:
                    task.properties.is_conflicting = True
                    break
                else:
                    task.properties.is_conflicting = False

    task.update(api=api)

    return jsonify(task.to_dict())
示例#43
0
def process_node_form(form, node_id=None, node_type=None, user=None):
    """Generic function used to process new nodes, as well as edits
    """
    if not user:
        print ("User is None")
        return False
    api = SystemUtility.attract_api()
    node_schema = node_type['dyn_schema'].to_dict()
    form_schema = node_type['form_schema'].to_dict()

    if node_id:
        # Update existing node
        node = pillarsdk.Node.find(node_id, api=api)
        node.name = form.name.data
        node.description = form.description.data
        if 'picture' in form:
            node.picture = form.picture.data
            if node.picture == "None":
                node.picture = None
        if 'parent' in form:
            node.parent = form.parent.data
        def update_data(node_schema, form_schema, prefix=""):
            for pr in node_schema:
                schema_prop = node_schema[pr]
                form_prop = form_schema[pr]
                if pr == 'items':
                    continue
                if 'visible' in form_prop and not form_prop['visible']:
                    continue
                prop_name = "{0}{1}".format(prefix, pr)
                if schema_prop['type'] == 'dict':
                    update_data(
                        schema_prop['schema'],
                        form_prop['schema'],
                        "{0}__".format(prop_name))
                    continue
                data = form[prop_name].data
                if schema_prop['type'] == 'dict':
                    if data == 'None':
                        continue
                if schema_prop['type'] == 'integer':
                    if data == '':
                        data = 0
                    else:
                        data = int(form[prop_name].data)
                if schema_prop['type'] == 'datetime':
                    data = datetime.strftime(data, RFC1123_DATE_FORMAT)
                else:
                    if pr in form:
                        data = form[prop_name].data
                path = prop_name.split('__')
                if len(path) > 1:
                    recursive_prop = recursive(
                        path, node.properties.to_dict(), data)
                    node.properties = recursive_prop
                else:
                    node.properties[prop_name] = data
        update_data(node_schema, form_schema)
        # send_file(form, node, user)
        update = node.update(api=api)
        # if form.picture.data:
        #     image_data = request.files[form.picture.name].read()
        #     post = node.replace_picture(image_data, api=api)
        return update
    else:
        # Create a new node
        node = pillarsdk.Node()
        prop = {}
        files = {}
        prop['name'] = form.name.data
        prop['description'] = form.description.data
        prop['user'] = user
        if 'picture' in form:
            prop['picture'] = form.picture.data
            if prop['picture'] == 'None':
                prop['picture'] = None
        if 'parent' in form:
            prop['parent'] = form.parent.data
        prop['properties'] = {}

        def get_data(node_schema, form_schema, prefix=""):
            for pr in node_schema:
                schema_prop = node_schema[pr]
                form_prop = form_schema[pr]
                if pr == 'items':
                    continue
                if 'visible' in form_prop and not form_prop['visible']:
                    continue
                prop_name = "{0}{1}".format(prefix, pr)
                if schema_prop['type'] == 'dict':
                    get_data(
                        schema_prop['schema'],
                        form_prop['schema'],
                        "{0}__".format(prop_name))
                    continue
                data = form[prop_name].data
                if schema_prop['type'] == 'media':
                    tmpfile = '/tmp/binary_data'
                    data.save(tmpfile)
                    binfile = open(tmpfile, 'rb')
                    files[pr] = binfile
                    continue
                if schema_prop['type'] == 'integer':
                    if data == '':
                        data = 0
                if schema_prop['type'] == 'list':
                    if data == '':
                        data = []
                if schema_prop['type'] == 'datetime':
                    data = datetime.strftime(data, RFC1123_DATE_FORMAT)
                if schema_prop['type'] == 'objectid':
                    if data == '':
                        data = None
                path = prop_name.split('__')
                if len(path) > 1:
                    prop['properties'] = recursive(path, prop['properties'], data)
                else:
                    prop['properties'][prop_name] = data

        get_data(node_schema, form_schema)

        prop['node_type'] = form.node_type_id.data
        post = node.post(prop, api=api)

        return post
示例#44
0
def index():
    """Custom files entry point
    """
    rfiles = []
    backend = app.config['STORAGE_BACKEND']
    api = SystemUtility.attract_api()
    user = current_user.objectid
    node_picture = File()

    for file_ in request.files:
        filestorage = request.files[file_]

        # Save file on AttractWeb Storage
        picture_path = os.path.join(
            app.config['UPLOAD_DIR'], filestorage.filename)
        filestorage.save(picture_path)

        picture_file_file = open(picture_path, 'rb')
        if backend == 'pillar':
            hash_ = hashfile(picture_file_file, hashlib.md5())
            name = "{0}{1}".format(hash_,
                                   os.path.splitext(picture_path)[1])
        picture_file_file.close()

        file_check = node_picture.all(
            {"where": "path=='{0}'".format(name)}, api=api)
        file_check = file_check['_items']

        if len(file_check) == 0:
            prop = {}
            prop['name'] = filestorage.filename
            prop['description'] = "File {0}".format(filestorage.filename)
            prop['user'] = user
            prop['content_type'] = filestorage.content_type
            # TODO Fix length value
            prop['length'] = filestorage.content_length
            prop['md5'] = hash_
            prop['filename'] = filestorage.filename
            prop['backend'] = backend
            if backend in ["pillar"]:
                prop['path'] = name
            node_picture.post(prop, api=api)
            prop['_id'] = node_picture['_id']
            if backend == 'pillar':
                node_picture.post_file(picture_path, name, api=api)
                node_picture.build_previews(name, api=api)

            url = "{0}/file_storage/file/{1}".format(
                app.config['PILLAR_SERVER_ENDPOINT'], prop['path'])
            rfiles.append( {
                "id": prop['_id'],
                "name": prop['filename'],
                "size": prop['length'],
                "url": url,
                "thumbnailUrl": url,
                "deleteUrl": url,
                "deleteType": "DELETE"
            })
        else:
            url = "{0}/file_storage/file/{1}".format(
                app.config['PILLAR_SERVER_ENDPOINT'], file_check[0]['path'])
            rfiles.append( {
                "id": file_check[0]['_id'],
                "name": file_check[0]['filename'],
                "size": file_check[0]['length'],
                "url": url,
                "thumbnailUrl": url,
                "deleteUrl": url,
                "deleteType": "DELETE"
            })

    return jsonify(dict(files=rfiles))
示例#45
0
 def entrypoint(self):
     return os.path.join(SystemUtility.attract_server_endpoint(), self.path,
                         self.storage_node.properties.backend,
                         self.storage_node.properties.project,
                         self.storage_node.properties.subdir)
示例#46
0
def edit(node_id):
    """Generic node editing form
    """
    def set_properties(
            dyn_schema, form_schema, node_properties, form, prefix="", set_data=True):
        """Initialize custom properties for the form. We run this function once
        before validating the function with set_data=False, so that we can set
        any multiselect field that was originally specified empty and fill it
        with the current choices.
        """
        for prop in dyn_schema:
            if not prop in node_properties:
                continue
            schema_prop = dyn_schema[prop]
            form_prop = form_schema[prop]
            prop_name = "{0}{1}".format(prefix, prop)
            if schema_prop['type'] == 'dict':
                set_properties(
                    schema_prop['schema'],
                    form_prop['schema'],
                    node_properties[prop_name],
                    form,
                    "{0}__".format(prop_name))
            else:
                try:
                    data = node_properties[prop]
                except KeyError:
                    print ("{0} not found in form".format(prop_name))
                if schema_prop['type'] == 'datetime':
                    data = datetime.strptime(data, RFC1123_DATE_FORMAT)
                if prop_name in form:
                    # Other field types
                    if isinstance(form[prop_name], SelectMultipleField):
                        # If we are dealing with a multiselect field, check if
                        # it's empty (usually because we can't query the whole
                        # database to pick all the choices). If it's empty we
                        # populate the choices with the actual data.
                        if not form[prop_name].choices:
                            form[prop_name].choices = [(d,d) for d in data]
                            # Choices should be a tuple with value and name
                    # Assign data to the field
                    if set_data:
                        form[prop_name].data = data

    api = SystemUtility.attract_api()
    node = Node.find(node_id, api=api)
    # TODO: simply embed node_type
    node_type = NodeType.find(node.node_type, api=api)
    form = get_node_form(node_type)
    user_id = current_user.objectid
    dyn_schema = node_type['dyn_schema'].to_dict()
    form_schema = node_type['form_schema'].to_dict()
    error = ""
    node_type_name = node_type.name

    node_properties = node.properties.to_dict()

    set_properties(dyn_schema, form_schema, node_properties, form, set_data=False)

    if form.validate_on_submit():
        if process_node_form(
                form, node_id=node_id, node_type=node_type, user=user_id):
            project_update_nodes_list(node_id)
            return redirect(url_for('nodes.view', node_id=node_id, embed=1))
        else:
            error = "Server error"
            print ("Error sending data")
    else:
        print form.errors

    # Populate Form
    form.name.data = node.name
    form.description.data = node.description
    if 'picture' in form:
        form.picture.data = node.picture
    if node.parent:
        form.parent.data = node.parent

    set_properties(dyn_schema, form_schema, node_properties, form)

    # Get Parent
    try:
        parent = Node.find(node['parent'], api=api)
    except KeyError:
        parent = None
    except ResourceNotFound:
        parent = None

    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'

    template = '{0}/edit{1}.html'.format(node_type['name'], embed_string)

    # We should more simply check if the template file actually exsists on
    # the filesystem level
    try:
        return render_template(
                template,
                node=node,
                parent=parent,
                form=form,
                errors=form.errors,
                error=error)
    except TemplateNotFound:
        template = 'nodes/edit{1}.html'.format(node_type['name'], embed_string)
        return render_template(
                template,
                node=node,
                parent=parent,
                form=form,
                errors=form.errors,
                error=error)
示例#47
0
def assets_create():
    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'
    # Hash name based on file name, user id and current timestamp
    hash_name = name + str(current_user.objectid) + str(round(time.time()))
    link = hashlib.sha1(hash_name).hexdigest()
    link = os.path.join(link[:2], link + ext)

    api = SystemUtility.attract_api()
    node_type = NodeType.find_first({
        'where': '{"name" : "asset"}',
        }, api=api)
    # We will create the Node object later on, after creating the file object
    node_asset_props = dict(
        name=name,
        #description=a.description,
        #picture=picture,
        user=current_user.objectid,
        node_type=node_type._id,
        #parent=node_parent,
        properties=dict(
            content_type=filetype,
            #file=a.link[4:],
            status='processing'))

    src_dir_path = os.path.join(app.config['UPLOAD_DIR'], str(current_user.objectid))

    # Move the file in designated location
    destination_dir = os.path.join(app.config['SHARED_DIR'], link[:2])
    if not os.path.isdir(destination_dir):
        os.makedirs(destination_dir)
    # (TODO) Check if filename already exsits
    src_file_path = os.path.join(src_dir_path, name)
    dst_file_path = os.path.join(destination_dir, link[3:])
    # (TODO) Thread this operation

    shutil.copy(src_file_path, dst_file_path)

    if filetype == 'file':
        mime_type = 'application'
    else:
        mime_type = filetype
    content_type = "{0}/{1}".format(mime_type, ext.replace(".", ""))

    node_file = File({
        'name': link,
        'filename': name,
        'user': current_user.objectid,
        'backend': 'cdnsun',
        'md5': '',
        'content_type': content_type,
        'length': 0
        })

    node_file.create(api=api)

    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)
示例#48
0
def edit(node_id):
    """Generic node editing form
    """
    def set_properties(dyn_schema,
                       form_schema,
                       node_properties,
                       form,
                       prefix="",
                       set_data=True):
        """Initialize custom properties for the form. We run this function once
        before validating the function with set_data=False, so that we can set
        any multiselect field that was originally specified empty and fill it
        with the current choices.
        """
        for prop in dyn_schema:
            if not prop in node_properties:
                continue
            schema_prop = dyn_schema[prop]
            form_prop = form_schema[prop]
            prop_name = "{0}{1}".format(prefix, prop)
            if schema_prop['type'] == 'dict':
                set_properties(schema_prop['schema'], form_prop['schema'],
                               node_properties[prop_name], form,
                               "{0}__".format(prop_name))
            else:
                try:
                    data = node_properties[prop]
                except KeyError:
                    print("{0} not found in form".format(prop_name))
                if schema_prop['type'] == 'datetime':
                    data = datetime.strptime(data, RFC1123_DATE_FORMAT)
                if prop_name in form:
                    # Other field types
                    if isinstance(form[prop_name], SelectMultipleField):
                        # If we are dealing with a multiselect field, check if
                        # it's empty (usually because we can't query the whole
                        # database to pick all the choices). If it's empty we
                        # populate the choices with the actual data.
                        if not form[prop_name].choices:
                            form[prop_name].choices = [(d, d) for d in data]
                            # Choices should be a tuple with value and name
                    # Assign data to the field
                    if set_data:
                        form[prop_name].data = data

    api = SystemUtility.attract_api()
    node = Node.find(node_id, api=api)
    # TODO: simply embed node_type
    node_type = NodeType.find(node.node_type, api=api)
    form = get_node_form(node_type)
    user_id = current_user.objectid
    dyn_schema = node_type['dyn_schema'].to_dict()
    form_schema = node_type['form_schema'].to_dict()
    error = ""
    node_type_name = node_type.name

    node_properties = node.properties.to_dict()

    set_properties(dyn_schema,
                   form_schema,
                   node_properties,
                   form,
                   set_data=False)

    if form.validate_on_submit():
        if process_node_form(form,
                             node_id=node_id,
                             node_type=node_type,
                             user=user_id):
            project_update_nodes_list(node_id)
            return redirect(url_for('nodes.view', node_id=node_id, embed=1))
        else:
            error = "Server error"
            print("Error sending data")
    else:
        print form.errors

    # Populate Form
    form.name.data = node.name
    form.description.data = node.description
    if 'picture' in form:
        form.picture.data = node.picture
    if node.parent:
        form.parent.data = node.parent

    set_properties(dyn_schema, form_schema, node_properties, form)

    # Get Parent
    try:
        parent = Node.find(node['parent'], api=api)
    except KeyError:
        parent = None
    except ResourceNotFound:
        parent = None

    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'

    template = '{0}/edit{1}.html'.format(node_type['name'], embed_string)

    # We should more simply check if the template file actually exsists on
    # the filesystem level
    try:
        return render_template(template,
                               node=node,
                               parent=parent,
                               form=form,
                               errors=form.errors,
                               error=error)
    except TemplateNotFound:
        template = 'nodes/edit{1}.html'.format(node_type['name'], embed_string)
        return render_template(template,
                               node=node,
                               parent=parent,
                               form=form,
                               errors=form.errors,
                               error=error)
示例#49
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
示例#50
0
def shots_index():
    max_results = 100

    api = SystemUtility.attract_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)
示例#51
0
def get_node_form(node_type):
    class ProceduralForm(Form):
        pass

    api = SystemUtility.attract_api()
    node_schema = node_type['dyn_schema'].to_dict()
    form_prop = node_type['form_schema'].to_dict()
    parent_prop = node_type['parent'].to_dict()

    setattr(ProceduralForm, 'name',
            TextField('Name', validators=[DataRequired()]))
    # Parenting
    if 'node_types' in parent_prop and len(parent_prop['node_types']) > 0:
        # select = []
        # for parent_type in parent_prop['node_types']:
        #     parent_node_type = pillarsdk.NodeType.all(
        #         {'where': '{"name" : "%s"}' % parent_type}, api=api)
        #     nodes = Node.all({
        #         'where': '{"node_type" : "%s"}' % str(
        #             parent_node_type._items[0]['_id']),
        #         'max_results': 999,
        #         'sort': "order"},
        #         api=api)
        #     for option in nodes._items:
        #         select.append((str(option._id), str(option.name)))

        parent_names = ""
        for parent_type in parent_prop['node_types']:
            parent_names = "{0} {1},".format(parent_names, parent_type)

        # setattr(ProceduralForm,
        #         'parent',
        #         SelectField('Parent ({0})'.format(parent_names),
        #                     choices=select))
        setattr(ProceduralForm, 'parent',
                HiddenField('Parent ({0})'.format(parent_names)))

    setattr(ProceduralForm, 'description', TextAreaField('Description'))
    setattr(ProceduralForm, 'picture', FileSelectField('Picture'))
    setattr(ProceduralForm, 'node_type_id', HiddenField(default=node_type._id))

    def build_form(node_schema, form_schema, prefix=""):
        for prop in node_schema:
            schema_prop = node_schema[prop]
            form_prop = form_schema[prop]
            if prop == 'items':
                continue
            if 'visible' in form_prop and not form_prop['visible']:
                continue
            prop_name = "{0}{1}".format(prefix, prop)

            # Recursive call if detects a dict
            if schema_prop['type'] == 'dict':
                # This works if the dictionary schema is hardcoded.
                # I we define it useing propertyschema dna valueschema, this
                # validation pattern does not work and crahses.
                build_form(schema_prop['schema'], form_prop['schema'],
                           "{0}__".format(prop_name))
                continue
            if schema_prop['type'] == 'list' and 'items' in form_prop:
                # Attempt at populating the content of a select menu. If this
                # is a large collection this will not work because of pagination.
                # This whole section should just be removed in the future. See
                # the next statement for an improved approach to this.
                for item in form_prop['items']:
                    items = eval("pillarsdk.{0}".format(item[0]))
                    items_to_select = items.all(api=api)
                    if items_to_select:
                        items_to_select = items_to_select["_items"]
                    else:
                        items_to_select = []
                    select = []
                    for select_item in items_to_select:
                        select.append(
                            (select_item['_id'], select_item[item[1]]))
                    if item[0] == 'File':
                        setattr(ProceduralForm, prop_name,
                                FileSelectMultipleField(choices=select))
                    else:
                        setattr(
                            ProceduralForm, prop_name,
                            SelectMultipleField(choices=select, coerce=str))
            elif schema_prop['type'] == 'list':
                # Create and empty multiselect field, which will be populated
                # with choices from the data it's being initialized with.
                setattr(ProceduralForm, prop_name,
                        SelectMultipleField(choices=[]))

            elif 'allowed' in schema_prop:
                select = []
                for option in schema_prop['allowed']:
                    select.append((str(option), str(option)))
                setattr(ProceduralForm, prop_name, SelectField(choices=select))
            elif schema_prop['type'] == 'datetime':
                if 'dateonly' in form_prop and form_prop['dateonly']:
                    setattr(ProceduralForm, prop_name,
                            DateField(prop_name, default=date.today()))
                else:
                    setattr(ProceduralForm, prop_name,
                            DateTimeField(prop_name, default=datetime.now()))
            elif schema_prop['type'] == 'integer':
                setattr(ProceduralForm, prop_name, IntegerField(prop_name))
            elif schema_prop['type'] == 'boolean':
                setattr(ProceduralForm, prop_name, BooleanField(prop_name))
            elif schema_prop['type'] == 'media':
                setattr(ProceduralForm, prop_name, FileField(prop_name))
            elif 'maxlength' in schema_prop and schema_prop['maxlength'] > 64:
                setattr(ProceduralForm, prop_name, TextAreaField(prop_name))
            else:
                setattr(ProceduralForm, prop_name, TextField(prop_name))

    build_form(node_schema, form_prop)

    return ProceduralForm()
示例#52
0
def index():
    """Custom files entry point
    """
    rfiles = []
    backend = app.config['STORAGE_BACKEND']
    api = SystemUtility.attract_api()
    user = current_user.objectid
    node_picture = File()

    for file_ in request.files:
        filestorage = request.files[file_]

        # Save file on AttractWeb Storage
        picture_path = os.path.join(app.config['UPLOAD_DIR'],
                                    filestorage.filename)
        filestorage.save(picture_path)

        picture_file_file = open(picture_path, 'rb')
        if backend == 'pillar':
            hash_ = hashfile(picture_file_file, hashlib.md5())
            name = "{0}{1}".format(hash_, os.path.splitext(picture_path)[1])
        picture_file_file.close()

        file_check = node_picture.all({"where": "path=='{0}'".format(name)},
                                      api=api)
        file_check = file_check['_items']

        if len(file_check) == 0:
            prop = {}
            prop['name'] = filestorage.filename
            prop['description'] = "File {0}".format(filestorage.filename)
            prop['user'] = user
            prop['content_type'] = filestorage.content_type
            # TODO Fix length value
            prop['length'] = filestorage.content_length
            prop['md5'] = hash_
            prop['filename'] = filestorage.filename
            prop['backend'] = backend
            if backend in ["pillar"]:
                prop['path'] = name
            node_picture.post(prop, api=api)
            prop['_id'] = node_picture['_id']
            if backend == 'pillar':
                node_picture.post_file(picture_path, name, api=api)
                node_picture.build_previews(name, api=api)

            url = "{0}/file_storage/file/{1}".format(
                app.config['PILLAR_SERVER_ENDPOINT'], prop['path'])
            rfiles.append({
                "id": prop['_id'],
                "name": prop['filename'],
                "size": prop['length'],
                "url": url,
                "thumbnailUrl": url,
                "deleteUrl": url,
                "deleteType": "DELETE"
            })
        else:
            url = "{0}/file_storage/file/{1}".format(
                app.config['PILLAR_SERVER_ENDPOINT'], file_check[0]['path'])
            rfiles.append({
                "id": file_check[0]['_id'],
                "name": file_check[0]['filename'],
                "size": file_check[0]['length'],
                "url": url,
                "thumbnailUrl": url,
                "deleteUrl": url,
                "deleteType": "DELETE"
            })

    return jsonify(dict(files=rfiles))
示例#53
0
def jstree_build_from_node(node):
    api = SystemUtility.attract_api()
    open_nodes = [jstree_parse_node(node)]
    # Get the current node again (with parent data)
    try:
        parent = Node.find(node.parent, {
            'projection': '{"name": 1, "parent": 1, "node_type": 1}',
            'embedded': '{"node_type":1}',
            }, api=api)
    except ResourceNotFound:
        parent = None
    except ForbiddenAccess:
        parent = None
    while (parent):
        open_nodes.append(jstree_parse_node(parent))
        # If we have a parent
        if parent.parent:
            try:
                parent = Node.find(parent.parent, {
                    'projection': '{"name":1, "parent":1, "node_type": 1}',
                    'embedded': '{"node_type":1}',
                    }, api=api)
            except ResourceNotFound:
                parent = None
        else:
            parent = None
    open_nodes.reverse()
    #open_nodes.pop(0)

    nodes_list = []

    for node in jstree_get_children(open_nodes[0]['id']):
        # Nodes at the root of the project
        node_dict = {
            'id': node['id'],
            'text': node['text'],
            'type': node['type'],
            'children': True
        }
        if len(open_nodes) > 1:
            # Opening and selecting the tree nodes according to the landing place
            if node['id'] == open_nodes[1]['id']:
                current_dict = node_dict
                current_dict['state'] = {'opened': True}
                current_dict['children'] = jstree_get_children(node['id'])
                # Iterate on open_nodes until the end
                for n in open_nodes[2:]:
                    for c in current_dict['children']:
                        if n['id'] == c['id']:
                            current_dict = c
                            break
                    current_dict['state'] = {'opened': True}
                    current_dict['children'] = jstree_get_children(n['id'])

                # if landing_asset_id:
                #     current_dict['children'] = aux_product_tree_node(open_nodes[-1])
                #     for asset in current_dict['children']:
                #         if int(asset['id'][1:])==landing_asset_id:
                #             asset.update(state=dict(selected=True))

        nodes_list.append(node_dict)
    return nodes_list
示例#54
0
def assets_create():
    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'
    # Hash name based on file name, user id and current timestamp
    hash_name = name + str(current_user.objectid) + str(round(time.time()))
    link = hashlib.sha1(hash_name).hexdigest()
    link = os.path.join(link[:2], link + ext)

    api = SystemUtility.attract_api()
    node_type = NodeType.find_first({
        'where': '{"name" : "asset"}',
    }, api=api)
    # We will create the Node object later on, after creating the file object
    node_asset_props = dict(
        name=name,
        #description=a.description,
        #picture=picture,
        user=current_user.objectid,
        node_type=node_type._id,
        #parent=node_parent,
        properties=dict(
            content_type=filetype,
            #file=a.link[4:],
            status='processing'))

    src_dir_path = os.path.join(app.config['UPLOAD_DIR'],
                                str(current_user.objectid))

    # Move the file in designated location
    destination_dir = os.path.join(app.config['SHARED_DIR'], link[:2])
    if not os.path.isdir(destination_dir):
        os.makedirs(destination_dir)
    # (TODO) Check if filename already exsits
    src_file_path = os.path.join(src_dir_path, name)
    dst_file_path = os.path.join(destination_dir, link[3:])
    # (TODO) Thread this operation

    shutil.copy(src_file_path, dst_file_path)

    if filetype == 'file':
        mime_type = 'application'
    else:
        mime_type = filetype
    content_type = "{0}/{1}".format(mime_type, ext.replace(".", ""))

    node_file = File({
        'name': link,
        'filename': name,
        'user': current_user.objectid,
        'backend': 'cdnsun',
        'md5': '',
        'content_type': content_type,
        'length': 0
    })

    node_file.create(api=api)

    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)
示例#55
0
def process_node_form(form, node_id=None, node_type=None, user=None):
    """Generic function used to process new nodes, as well as edits
    """
    if not user:
        print("User is None")
        return False
    api = SystemUtility.attract_api()
    node_schema = node_type['dyn_schema'].to_dict()
    form_schema = node_type['form_schema'].to_dict()

    if node_id:
        # Update existing node
        node = pillarsdk.Node.find(node_id, api=api)
        node.name = form.name.data
        node.description = form.description.data
        if 'picture' in form:
            node.picture = form.picture.data
            if node.picture == "None":
                node.picture = None
        if 'parent' in form:
            node.parent = form.parent.data

        def update_data(node_schema, form_schema, prefix=""):
            for pr in node_schema:
                schema_prop = node_schema[pr]
                form_prop = form_schema[pr]
                if pr == 'items':
                    continue
                if 'visible' in form_prop and not form_prop['visible']:
                    continue
                prop_name = "{0}{1}".format(prefix, pr)
                if schema_prop['type'] == 'dict':
                    update_data(schema_prop['schema'], form_prop['schema'],
                                "{0}__".format(prop_name))
                    continue
                data = form[prop_name].data
                if schema_prop['type'] == 'dict':
                    if data == 'None':
                        continue
                if schema_prop['type'] == 'integer':
                    if data == '':
                        data = 0
                    else:
                        data = int(form[prop_name].data)
                if schema_prop['type'] == 'datetime':
                    data = datetime.strftime(data, RFC1123_DATE_FORMAT)
                else:
                    if pr in form:
                        data = form[prop_name].data
                path = prop_name.split('__')
                if len(path) > 1:
                    recursive_prop = recursive(path, node.properties.to_dict(),
                                               data)
                    node.properties = recursive_prop
                else:
                    node.properties[prop_name] = data

        update_data(node_schema, form_schema)
        # send_file(form, node, user)
        update = node.update(api=api)
        # if form.picture.data:
        #     image_data = request.files[form.picture.name].read()
        #     post = node.replace_picture(image_data, api=api)
        return update
    else:
        # Create a new node
        node = pillarsdk.Node()
        prop = {}
        files = {}
        prop['name'] = form.name.data
        prop['description'] = form.description.data
        prop['user'] = user
        if 'picture' in form:
            prop['picture'] = form.picture.data
            if prop['picture'] == 'None':
                prop['picture'] = None
        if 'parent' in form:
            prop['parent'] = form.parent.data
        prop['properties'] = {}

        def get_data(node_schema, form_schema, prefix=""):
            for pr in node_schema:
                schema_prop = node_schema[pr]
                form_prop = form_schema[pr]
                if pr == 'items':
                    continue
                if 'visible' in form_prop and not form_prop['visible']:
                    continue
                prop_name = "{0}{1}".format(prefix, pr)
                if schema_prop['type'] == 'dict':
                    get_data(schema_prop['schema'], form_prop['schema'],
                             "{0}__".format(prop_name))
                    continue
                data = form[prop_name].data
                if schema_prop['type'] == 'media':
                    tmpfile = '/tmp/binary_data'
                    data.save(tmpfile)
                    binfile = open(tmpfile, 'rb')
                    files[pr] = binfile
                    continue
                if schema_prop['type'] == 'integer':
                    if data == '':
                        data = 0
                if schema_prop['type'] == 'list':
                    if data == '':
                        data = []
                if schema_prop['type'] == 'datetime':
                    data = datetime.strftime(data, RFC1123_DATE_FORMAT)
                if schema_prop['type'] == 'objectid':
                    if data == '':
                        data = None
                path = prop_name.split('__')
                if len(path) > 1:
                    prop['properties'] = recursive(path, prop['properties'],
                                                   data)
                else:
                    prop['properties'][prop_name] = data

        get_data(node_schema, form_schema)

        prop['node_type'] = form.node_type_id.data
        post = node.post(prop, api=api)

        return post