Added task creation per project and non-functional tasks-for-project view
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import logging
|
||||
|
||||
from pillar.extension import PillarExtension
|
||||
|
||||
from . import task_manager
|
||||
@@ -5,6 +7,7 @@ from . import task_manager
|
||||
|
||||
class AttractExtension(PillarExtension):
|
||||
def __init__(self):
|
||||
self._log = logging.getLogger('%s.AttractExtension' % __name__)
|
||||
self.task_manager = task_manager.TaskManager()
|
||||
|
||||
@property
|
||||
|
@@ -1,7 +1,11 @@
|
||||
import functools
|
||||
import logging
|
||||
|
||||
from flask import Blueprint, render_template
|
||||
|
||||
from pillar.api.utils import jsonify
|
||||
from pillar.web.system_util import pillar_api
|
||||
import pillarsdk
|
||||
|
||||
blueprint = Blueprint('attract', __name__)
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -30,3 +34,59 @@ def subversion_kick():
|
||||
'previous_last_seen_revision': last_seen_revision,
|
||||
'last_seen_revision': observer.last_seen_revision,
|
||||
})
|
||||
|
||||
|
||||
def error_project_not_setup_for_attract():
|
||||
return render_template('attract/errors/project_not_setup.html')
|
||||
|
||||
|
||||
def attract_project_view(extra_project_projections=None):
|
||||
"""Decorator, replaces the first parameter project_url with the actual project.
|
||||
|
||||
Assumes the first parameter to the decorated function is 'project_url'. It then
|
||||
looks up that project, checks that it's set up for Attract, and passes it to the
|
||||
decorated function.
|
||||
|
||||
If not set up for attract, uses error_project_not_setup_for_attract() to render
|
||||
the response.
|
||||
|
||||
:param extra_project_projections: extra projections to use on top of the ones already
|
||||
used by this decorator.
|
||||
:type extra_project_projections: dict
|
||||
"""
|
||||
|
||||
if callable(extra_project_projections):
|
||||
raise TypeError('Use with @attract_project_view() <-- note the parentheses')
|
||||
|
||||
projections = {
|
||||
'_id': 1,
|
||||
'name': 1,
|
||||
'node_types': 1,
|
||||
# We don't need this here, but this way the wrapped function has access
|
||||
# to the orignal URL passed to it.
|
||||
'url': 1,
|
||||
}
|
||||
if extra_project_projections:
|
||||
projections.update(extra_project_projections)
|
||||
|
||||
def decorator(wrapped):
|
||||
@functools.wraps(wrapped)
|
||||
def wrapper(project_url, *args, **kwargs):
|
||||
api = pillar_api()
|
||||
|
||||
project = pillarsdk.Project.find_by_url(
|
||||
project_url,
|
||||
{'projection': projections},
|
||||
api=api)
|
||||
|
||||
node_type = project.get_node_type('attract.task')
|
||||
if not node_type:
|
||||
log.warning('createProject url=%s does not have node type attract.task',
|
||||
project_url)
|
||||
return error_project_not_setup_for_attract()
|
||||
|
||||
return wrapped(project, *args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
return decorator
|
||||
|
@@ -5,6 +5,7 @@ node_type_task = {
|
||||
'status': {
|
||||
'type': 'string',
|
||||
'allowed': [
|
||||
'invalid',
|
||||
'todo',
|
||||
'in_progress',
|
||||
'on_hold',
|
||||
@@ -13,19 +14,10 @@ node_type_task = {
|
||||
'final',
|
||||
'review'
|
||||
],
|
||||
'default': 'todo',
|
||||
'required': True,
|
||||
},
|
||||
|
||||
# Links to external systems (filenames, SVN repository URLs, SVN revisions, etc.)
|
||||
'external_links': {
|
||||
'svn_revisions': {
|
||||
'type': 'list',
|
||||
'schema': {
|
||||
'type': 'dict',
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
'assigned_to': {
|
||||
'type': 'dict',
|
||||
'schema': {
|
||||
@@ -71,6 +63,5 @@ node_type_task = {
|
||||
'time': {'visible': False},
|
||||
},
|
||||
|
||||
# TODO: is this None really needed? Check.
|
||||
'parent': [None, 'task', 'shot']
|
||||
'parent': ['task', 'shot'],
|
||||
}
|
||||
|
@@ -1,6 +1,13 @@
|
||||
import logging
|
||||
|
||||
from flask import Blueprint, render_template
|
||||
import flask
|
||||
import flask_login
|
||||
|
||||
import pillarsdk
|
||||
from pillar.web.system_util import pillar_api
|
||||
|
||||
from .modules import attract_project_view
|
||||
|
||||
blueprint = Blueprint('attract.tasks', __name__, url_prefix='/tasks')
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -9,3 +16,51 @@ log = logging.getLogger(__name__)
|
||||
@blueprint.route('/')
|
||||
def index():
|
||||
return render_template('attract/tasks/index.html')
|
||||
|
||||
|
||||
@blueprint.route('/<project_url>/')
|
||||
@attract_project_view()
|
||||
def for_project(project):
|
||||
api = pillar_api()
|
||||
|
||||
tasks = pillarsdk.Node.all({
|
||||
'project': project['_id'],
|
||||
'node_type': 'attract.task',
|
||||
}, api=api)
|
||||
|
||||
return render_template('attract/tasks/for_project.html',
|
||||
tasks=tasks,
|
||||
project=project)
|
||||
|
||||
|
||||
@blueprint.route('/<project_url>/<task_id>')
|
||||
@attract_project_view()
|
||||
def view_embed_task(project, task_id):
|
||||
api = pillar_api()
|
||||
|
||||
return 'Not done, come back later.'
|
||||
|
||||
|
||||
@blueprint.route('/<project_url>/create')
|
||||
@attract_project_view()
|
||||
def create_task(project):
|
||||
api = pillar_api()
|
||||
|
||||
node_type = project.get_node_type('attract.task')
|
||||
|
||||
node_props = dict(
|
||||
name='New task',
|
||||
project=project['_id'],
|
||||
user=flask_login.current_user.objectid,
|
||||
node_type=node_type['name'],
|
||||
properties={
|
||||
'status': node_type['dyn_schema']['status']['default'],
|
||||
},
|
||||
)
|
||||
|
||||
task = pillarsdk.Node(node_props)
|
||||
task.create(api=api)
|
||||
|
||||
return flask.redirect(flask.url_for('attract.tasks.view_embed_task',
|
||||
project_url=project['url'],
|
||||
task_id=task['_id']))
|
||||
|
Reference in New Issue
Block a user