Added project settings allowing setup + editing task types.
- Attract added to Project Settings screen - setting up project for Attract - editing shot/asset task types To do: add checks that the user is allowed to use Attract in the first place.
This commit is contained in:
@@ -1,18 +1,21 @@
|
||||
import functools
|
||||
import logging
|
||||
|
||||
from flask import Blueprint, render_template, redirect, url_for
|
||||
from flask import Blueprint, render_template, redirect, url_for, request, jsonify
|
||||
import flask_login
|
||||
import werkzeug.exceptions as wz_exceptions
|
||||
|
||||
from pillar.auth import current_web_user as current_user
|
||||
from pillar.web.utils import attach_project_pictures
|
||||
import pillar.web.subquery
|
||||
from pillar.web.system_util import pillar_api
|
||||
from pillar.web.projects.routes import project_view
|
||||
import pillarsdk
|
||||
|
||||
from attract import current_attract
|
||||
from attract.node_types.task import node_type_task
|
||||
from attract.node_types.shot import node_type_shot
|
||||
from attract.node_types.asset import node_type_asset
|
||||
|
||||
blueprint = Blueprint('attract', __name__)
|
||||
log = logging.getLogger(__name__)
|
||||
@@ -38,7 +41,7 @@ def index():
|
||||
projs_with_summaries = [
|
||||
(proj, current_attract.shot_manager.shot_status_summary(proj['_id']))
|
||||
for proj in projects['_items']
|
||||
]
|
||||
]
|
||||
|
||||
# Fetch all activities for all Attract projects.
|
||||
id_to_proj = {p['_id']: p for p in projects['_items']}
|
||||
@@ -137,8 +140,8 @@ def attract_project_view(extra_project_projections=None, extension_props=False):
|
||||
|
||||
|
||||
@blueprint.route('/<project_url>')
|
||||
@attract_project_view(extension_props=True)
|
||||
def project_index(project, attract_props):
|
||||
@attract_project_view(extension_props=False)
|
||||
def project_index(project):
|
||||
return redirect(url_for('attract.shots.perproject.index', project_url=project.url))
|
||||
|
||||
|
||||
@@ -152,3 +155,88 @@ def help(project):
|
||||
nt_shot['dyn_schema']['status']['allowed'])
|
||||
|
||||
return render_template('attract/help.html', statuses=statuses)
|
||||
|
||||
|
||||
def project_settings(project: pillarsdk.Project, **template_args: dict):
|
||||
"""Renders the project settings page for Attract projects."""
|
||||
|
||||
from . import EXTENSION_NAME
|
||||
|
||||
# Based on the project state, we can render a different template.
|
||||
if not current_attract.is_attract_project(project):
|
||||
return render_template('attract/project_settings/offer_setup.html',
|
||||
project=project, **template_args)
|
||||
|
||||
ntn_shot = node_type_shot['name']
|
||||
ntn_asset = node_type_asset['name']
|
||||
|
||||
try:
|
||||
attract_props = project['extension_props'][EXTENSION_NAME]
|
||||
except KeyError:
|
||||
# Not set up for attract, can happen.
|
||||
shot_task_types = []
|
||||
asset_task_types = []
|
||||
else:
|
||||
shot_task_types = attract_props['task_types'][ntn_shot]
|
||||
asset_task_types = attract_props['task_types'][ntn_asset]
|
||||
|
||||
return render_template('attract/project_settings/settings.html',
|
||||
project=project,
|
||||
asset_node_type_name=ntn_asset,
|
||||
shot_node_type_name=ntn_shot,
|
||||
shot_task_types=shot_task_types,
|
||||
asset_task_types=asset_task_types,
|
||||
**template_args)
|
||||
|
||||
|
||||
@blueprint.route('/<project_url>/<node_type_name>/set-task-types', methods=['POST'])
|
||||
@attract_project_view(extension_props=True)
|
||||
def save_task_types(project, attract_props, node_type_name: str):
|
||||
from . import EXTENSION_NAME
|
||||
from . import setup
|
||||
import re
|
||||
from collections import OrderedDict
|
||||
|
||||
valid_name_re = re.compile(r'^[0-9a-zA-Z &+\-.,_]+$')
|
||||
|
||||
if (not node_type_name.startswith('%s_' % EXTENSION_NAME)
|
||||
or node_type_name not in attract_props['task_types']
|
||||
or not valid_name_re.match(node_type_name)):
|
||||
log.info('%s: received invalid node type name %r', request.endpoint, node_type_name)
|
||||
raise wz_exceptions.BadRequest('Invalid node type name')
|
||||
|
||||
task_types_field = request.form.get('task_types')
|
||||
if not task_types_field:
|
||||
raise wz_exceptions.BadRequest('No task types given')
|
||||
|
||||
task_types = [
|
||||
tt for tt in (tt.strip()
|
||||
for tt in task_types_field.split('\n'))
|
||||
if tt
|
||||
]
|
||||
task_types = list(OrderedDict.fromkeys(task_types)) # removes duplicates, maintains order.
|
||||
if not all(valid_name_re.match(tt) for tt in task_types):
|
||||
raise wz_exceptions.BadRequest('Invalid task type given')
|
||||
|
||||
setup.set_task_types(project.to_dict(), node_type_name, task_types)
|
||||
|
||||
return jsonify(task_types=task_types)
|
||||
|
||||
|
||||
@blueprint.route('/<project_url>/setup-for-attract', methods=['POST'])
|
||||
@flask_login.login_required
|
||||
@project_view()
|
||||
def setup_for_attract(project: pillarsdk.Project):
|
||||
import attract.setup
|
||||
|
||||
project_id = project._id
|
||||
|
||||
if not project.has_method('PUT'):
|
||||
log.warning('User %s tries to set up project %s for Attract, but has no PUT rights.',
|
||||
current_user, project_id)
|
||||
raise wz_exceptions.Forbidden()
|
||||
|
||||
log.info('User %s sets up project %s for Attract', current_user, project_id)
|
||||
attract.setup.setup_for_attract(project.url)
|
||||
|
||||
return '', 204
|
||||
|
Reference in New Issue
Block a user