Navigation: Unified cloud navigation
* Removed main drop down menu * Added "My cloud" to user menu * Attract/Flamenco is found under Production Tools menu * Attract/Flamenco has the same navigation as its project
This commit is contained in:
@@ -10,7 +10,7 @@ from pillar.api.utils import str2id
|
||||
from pillar.web.utils import mass_attach_project_pictures
|
||||
import pillar.web.subquery
|
||||
from pillar.web.system_util import pillar_api
|
||||
from pillar.web.projects.routes import project_view
|
||||
from pillar.web.projects.routes import project_view, project_navigation_links
|
||||
import pillarsdk
|
||||
|
||||
from attract import current_attract
|
||||
@@ -64,10 +64,12 @@ def index():
|
||||
except (ValueError, wz_exceptions.NotFound):
|
||||
act.link = None
|
||||
|
||||
project = session.get('attract_last_project')
|
||||
return render_template('attract/index.html',
|
||||
tasks=tasks,
|
||||
projs_with_summaries=projs_with_summaries,
|
||||
activities=activities)
|
||||
activities=activities,
|
||||
project=project)
|
||||
|
||||
|
||||
def error_project_not_setup_for_attract():
|
||||
@@ -92,8 +94,6 @@ def attract_project_view(extra_project_projections: dict=None, extension_props=F
|
||||
:param full_project: skip projections altogether, fetching the whole project.
|
||||
"""
|
||||
|
||||
from . import EXTENSION_NAME
|
||||
|
||||
if callable(extra_project_projections):
|
||||
raise TypeError('Use with @attract_project_view() <-- note the parentheses')
|
||||
|
||||
@@ -101,14 +101,14 @@ def attract_project_view(extra_project_projections: dict=None, extension_props=F
|
||||
'_id': 1,
|
||||
'name': 1,
|
||||
'node_types': 1,
|
||||
'nodes_featured': 1,
|
||||
'extension_props': 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)
|
||||
if extension_props:
|
||||
projections['extension_props.%s' % EXTENSION_NAME] = 1
|
||||
|
||||
def decorator(wrapped):
|
||||
@functools.wraps(wrapped)
|
||||
|
@@ -5,6 +5,8 @@ import flask
|
||||
|
||||
import pillarsdk
|
||||
import pillar.api.utils
|
||||
from pillar import current_app
|
||||
from pillar.web.projects.routes import project_navigation_links
|
||||
from pillar.web.system_util import pillar_api
|
||||
|
||||
from attract.routes import attract_project_view
|
||||
@@ -30,6 +32,8 @@ def for_project(project, attract_props, task_id=None, asset_id=None):
|
||||
project, attract_props, task_id, asset_id)
|
||||
|
||||
can_create = current_attract.auth.current_user_may(current_attract.auth.Actions.USE)
|
||||
navigation_links = project_navigation_links(project, pillar_api())
|
||||
extension_sidebar_links = current_app.extension_sidebar_links(project)
|
||||
|
||||
return render_template('attract/assets/for_project.html',
|
||||
assets=assets,
|
||||
@@ -40,7 +44,10 @@ def for_project(project, attract_props, task_id=None, asset_id=None):
|
||||
project=project,
|
||||
attract_props=attract_props,
|
||||
can_create_task=can_create,
|
||||
can_create_asset=can_create)
|
||||
can_create_asset=can_create,
|
||||
navigation_links=navigation_links,
|
||||
extension_sidebar_links=extension_sidebar_links,
|
||||
)
|
||||
|
||||
|
||||
@perproject_blueprint.route('/<asset_id>')
|
||||
|
@@ -6,6 +6,8 @@ import werkzeug.exceptions as wz_exceptions
|
||||
|
||||
import pillarsdk
|
||||
import pillar.api.utils
|
||||
from pillar import current_app
|
||||
from pillar.web.projects.routes import project_navigation_links
|
||||
from pillar.web.system_util import pillar_api
|
||||
|
||||
from attract.routes import attract_project_view
|
||||
@@ -38,6 +40,8 @@ def for_project(project, attract_props, task_id=None, shot_id=None):
|
||||
if shot.properties.used_in_edit),
|
||||
}
|
||||
can_create_task = current_attract.auth.current_user_may(current_attract.auth.Actions.USE)
|
||||
navigation_links = project_navigation_links(project, pillar_api())
|
||||
extension_sidebar_links = current_app.extension_sidebar_links(project)
|
||||
|
||||
return render_template('attract/shots/for_project.html',
|
||||
shots=shots,
|
||||
@@ -48,7 +52,9 @@ def for_project(project, attract_props, task_id=None, shot_id=None):
|
||||
project=project,
|
||||
attract_props=attract_props,
|
||||
stats=stats,
|
||||
can_create_task=can_create_task)
|
||||
can_create_task=can_create_task,
|
||||
navigation_links=navigation_links,
|
||||
extension_sidebar_links=extension_sidebar_links)
|
||||
|
||||
|
||||
@perproject_blueprint.route('/<shot_id>')
|
||||
|
@@ -7,6 +7,7 @@ import flask_login
|
||||
import werkzeug.exceptions as wz_exceptions
|
||||
|
||||
import pillarsdk
|
||||
from pillar.web.projects.routes import project_navigation_links
|
||||
from pillar.web.system_util import pillar_api
|
||||
import pillar.api.utils
|
||||
import pillar.web.subquery
|
||||
@@ -47,16 +48,20 @@ def delete(task_id):
|
||||
|
||||
|
||||
@perproject_blueprint.route('/', endpoint='index')
|
||||
@attract_project_view()
|
||||
@attract_project_view(extension_props=False)
|
||||
def for_project(project, task_id=None):
|
||||
tasks = current_attract.task_manager.tasks_for_project(project['_id'])
|
||||
can_create_task = current_attract.auth.current_user_may(current_attract.auth.Actions.USE)
|
||||
navigation_links = project_navigation_links(project, pillar_api())
|
||||
extension_sidebar_links = current_app.extension_sidebar_links(project)
|
||||
|
||||
return render_template('attract/tasks/for_project.html',
|
||||
tasks=tasks['_items'],
|
||||
open_task_id=task_id,
|
||||
project=project,
|
||||
can_create_task=can_create_task)
|
||||
can_create_task=can_create_task,
|
||||
navigation_links=navigation_links,
|
||||
extension_sidebar_links=extension_sidebar_links)
|
||||
|
||||
|
||||
@perproject_blueprint.route('/<task_id>')
|
||||
|
@@ -78,7 +78,7 @@ nav.sidebar
|
||||
.table-head
|
||||
&.is-fixed
|
||||
position: fixed
|
||||
top: 42px
|
||||
top: 84px
|
||||
z-index: 1
|
||||
pointer-events: none
|
||||
background-color: white
|
||||
|
@@ -1,7 +1,7 @@
|
||||
| {% extends 'attract/layout.html' %}
|
||||
| {% block bodyattrs %}{{ super() }} data-context='asset'{% endblock %}
|
||||
| {% block page_title %}Assets - {{ project.name }}{% endblock %}
|
||||
| {% block body %}
|
||||
| {% block attractbody %}
|
||||
#col_main
|
||||
.col_header.item-list-header
|
||||
a.item-project(href="{{url_for('projects.view', project_url=project.url)}}") {{ project.name }}
|
||||
|
@@ -2,7 +2,7 @@
|
||||
| {% block bodyattrs %}{{ super() }} data-context='dashboard'{% endblock %}
|
||||
| {% block page_title %}Dashboard{% endblock %}
|
||||
|
||||
| {% block body %}
|
||||
| {% block attractbody %}
|
||||
#col_main
|
||||
.dashboard
|
||||
.d-stats.pt-2.px-2
|
||||
|
@@ -1,121 +1,67 @@
|
||||
doctype html
|
||||
html(lang="en")
|
||||
head
|
||||
meta(charset="utf-8")
|
||||
title {% if self.page_title() %}{% block page_title %}{% endblock %} — {% endif %}Attract
|
||||
meta(name="viewport", content="width=device-width, initial-scale=1.0")
|
||||
| {% extends 'projects/view.html' %}
|
||||
include ../../../../pillar/src/templates/mixins/components
|
||||
|
||||
| {% block head %}{% endblock %}
|
||||
| {% set title = 'production-tools' %}
|
||||
|
||||
link(href='//fonts.googleapis.com/css?family=Roboto:300,400', rel='stylesheet', type='text/css')
|
||||
| {% block css %}
|
||||
| {{ super() }}
|
||||
link(href="{{ url_for('static_attract', filename='assets/css/main.css') }}", rel="stylesheet")
|
||||
link(href="{{ url_for('static_attract', filename='assets/css/plugins/js_select2.css') }}", rel="stylesheet")
|
||||
link(href="{{ url_for('static_attract', filename='assets/img/favicon.png') }}", rel="shortcut icon")
|
||||
link(href="{{ url_for('static_attract', filename='assets/img/apple-touch-icon-precomposed.png') }}", rel="icon apple-touch-icon-precomposed", sizes="192x192")
|
||||
| {% endblock css %}
|
||||
|
||||
link(href="{{ url_for('static_pillar', filename='assets/css/font-pillar.css') }}", rel="stylesheet")
|
||||
link(href="{{ url_for('static_attract', filename='assets/css/main.css') }}", rel="stylesheet")
|
||||
link(href="{{ url_for('static_attract', filename='assets/css/plugins/js_select2.css') }}", rel="stylesheet")
|
||||
script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery-3.1.0.min.js')}}")
|
||||
script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.bootstrap-3.3.7.min.js') }}")
|
||||
script(src="{{ url_for('static_pillar', filename='assets/js/tutti.min.js') }}")
|
||||
script.
|
||||
pillar.utils.initCurrentUser({{ current_user | json | safe }});
|
||||
script(src="{{ url_for('static_attract', filename='assets/js/generated/tutti.min.js') }}")
|
||||
| {% block head %}
|
||||
script(src="{{ url_for('static_attract', filename='assets/js/generated/tutti.min.js') }}")
|
||||
| {% endblock head %}
|
||||
|
||||
link(href="{{ url_for('static_attract', filename='assets/img/favicon.png') }}", rel="shortcut icon")
|
||||
link(href="{{ url_for('static_attract', filename='assets/img/apple-touch-icon-precomposed.png') }}", rel="icon apple-touch-icon-precomposed", sizes="192x192")
|
||||
| {% block body %}
|
||||
#app-main
|
||||
#col_sidebar
|
||||
nav.sidebar(role='navigation')
|
||||
ul
|
||||
li
|
||||
a.navbar-item.attract(href="{{ url_for('attract.index') }}",
|
||||
title='Attract')
|
||||
i.pi-attract
|
||||
| {% if session.get('attract_last_project') %}
|
||||
| {% set attract_last_project = session.get('attract_last_project') %}
|
||||
li
|
||||
a.navbar-item.tasks(href="{{ url_for('attract.tasks.perproject.index', project_url=attract_last_project.url) }}",
|
||||
title='Tasks for project {{ attract_last_project.name }}') Tasks
|
||||
li
|
||||
a.navbar-item.shots(href="{{ url_for('attract.shots.perproject.index', project_url=attract_last_project.url) }}",
|
||||
title='Shots for project {{ attract_last_project.name }}') Shots
|
||||
li
|
||||
a.navbar-item.assets(href="{{ url_for('attract.assets.perproject.index', project_url=attract_last_project.url) }}",
|
||||
title='Assets for project {{ attract_last_project.name }}') Assets
|
||||
| {% else %}
|
||||
| {% if current_user.is_authenticated %}
|
||||
li
|
||||
a.navbar-item.tasks(href="{{ url_for('attract.tasks.index') }}",
|
||||
title='Your tasks') Tasks
|
||||
| {% endif %}
|
||||
| {% endif %}
|
||||
|
||||
| {% block style %}{% endblock %}
|
||||
ul.bottom
|
||||
| {% if project %}
|
||||
li
|
||||
button.js-help(
|
||||
type="button",
|
||||
title="Help",
|
||||
data-url="{{ url_for('attract.help', project_url=project.url) }}")
|
||||
i.pi-question
|
||||
| {% endif %}
|
||||
| {% block attractbody %}
|
||||
| {% endblock attractbody %}
|
||||
| {% endblock body %}
|
||||
|
||||
body("{% block bodyattrs %}{% if project %}data-project-url='{{ project.url }}'{% endif %}{% endblock %}")
|
||||
#app-main
|
||||
#col_sidebar
|
||||
nav.sidebar(role='navigation')
|
||||
a.navbar-brand(
|
||||
href="{{ url_for('main.homepage') }}",
|
||||
title="Blender Cloud")
|
||||
span.app-logo
|
||||
i.pi-blender-cloud
|
||||
ul
|
||||
li
|
||||
a.navbar-item.attract(href="{{ url_for('attract.index') }}",
|
||||
title='Attract')
|
||||
i.pi-attract
|
||||
| {% if session.get('attract_last_project') %}
|
||||
| {% set attract_last_project = session.get('attract_last_project') %}
|
||||
li
|
||||
a.navbar-item.tasks(href="{{ url_for('attract.tasks.perproject.index', project_url=attract_last_project.url) }}",
|
||||
title='Tasks for project {{ attract_last_project.name }}') Tasks
|
||||
li
|
||||
a.navbar-item.shots(href="{{ url_for('attract.shots.perproject.index', project_url=attract_last_project.url) }}",
|
||||
title='Shots for project {{ attract_last_project.name }}') Shots
|
||||
li
|
||||
a.navbar-item.assets(href="{{ url_for('attract.assets.perproject.index', project_url=attract_last_project.url) }}",
|
||||
title='Assets for project {{ attract_last_project.name }}') Assets
|
||||
| {% else %}
|
||||
| {% if current_user.is_authenticated %}
|
||||
li
|
||||
a.navbar-item.tasks(href="{{ url_for('attract.tasks.index') }}",
|
||||
title='Your tasks') Tasks
|
||||
| {% endif %}
|
||||
| {% endif %}
|
||||
|
||||
ul.bottom
|
||||
| {% if project %}
|
||||
li
|
||||
button.js-help(
|
||||
type="button",
|
||||
title="Help",
|
||||
data-url="{{ url_for('attract.help', project_url=project.url) }}")
|
||||
i.pi-question
|
||||
| {% endif %}
|
||||
|
||||
| {% include 'menus/notifications.html' %}
|
||||
| {% include 'menus/user.html' %}
|
||||
|
||||
| {% block body %}
|
||||
#col_left
|
||||
#col_main
|
||||
h1 Main
|
||||
#col_right
|
||||
h1 Right
|
||||
| {% endblock %}
|
||||
|
||||
.modal#modal(role="dialog", tabindex="-1")
|
||||
.modal-dialog(role="document")
|
||||
.modal-content
|
||||
.modal-header
|
||||
span.modal-title.title
|
||||
button.close(type="button", data-dismiss="modal", aria-label="Close")
|
||||
i.pi-cancel
|
||||
.modal-body
|
||||
|
||||
script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.select2.min.js') }}", async=true)
|
||||
script(src="{{ url_for('static_attract', filename='assets/js/vendor/moment-2.15.2.min.js') }}")
|
||||
script(src="{{ url_for('static_attract', filename='assets/js/vendor/pikaday.js') }}")
|
||||
| {% if current_user.is_authenticated %}
|
||||
script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.typewatch-3.0.0.min.js') }}")
|
||||
script.
|
||||
// When sending an AJAX request, always add the X-CSRFToken header to it.
|
||||
var csrf_token = "{{ csrf_token() }}";
|
||||
$.ajaxSetup({
|
||||
beforeSend: function (xhr, settings) {
|
||||
if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
|
||||
xhr.setRequestHeader("X-CSRFToken", csrf_token);
|
||||
}
|
||||
}
|
||||
});
|
||||
| {% endif %}
|
||||
|
||||
script.
|
||||
{% if project %}
|
||||
$('.js-help').openModalUrl('Help', "{{ url_for('attract.help', project_url=project.url) }}");
|
||||
{% endif %}
|
||||
|
||||
$(document).ready(function() {
|
||||
{% if current_user.is_authenticated %}
|
||||
getNotificationsLoop(); // Check for new notifications in the background
|
||||
|
||||
// Resize #notifications and change overflow for scrollbars
|
||||
$(window).on("resize", function() { notificationsResize(); });
|
||||
{% endif %}
|
||||
});
|
||||
|
||||
| {% block footer_scripts %}{% endblock %}
|
||||
| {% block footer_scripts_pre %}
|
||||
script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.select2.min.js') }}", async=true)
|
||||
script(src="{{ url_for('static_attract', filename='assets/js/vendor/moment-2.15.2.min.js') }}")
|
||||
script(src="{{ url_for('static_attract', filename='assets/js/vendor/pikaday.js') }}")
|
||||
| {% if project %}
|
||||
script.
|
||||
ProjectUtils.setProjectAttributes({projectId: "{{project._id}}", projectUrl: "{{project.url}}"});
|
||||
| {% endif %}
|
||||
| {% endblock footer_scripts_pre %}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
| {% extends 'attract/layout.html' %}
|
||||
| {% block page_title %}{{ project.name }} - Attract{% endblock %}
|
||||
| {% block body %}
|
||||
| {% block attractbody %}
|
||||
#page-container
|
||||
#page-content
|
||||
.project
|
||||
|
@@ -1,7 +1,7 @@
|
||||
| {% extends 'attract/layout.html' %}
|
||||
| {% block bodyattrs %}{{ super() }} data-context='shot'{% endblock %}
|
||||
| {% block page_title %}Shots - {{ project.name }}{% endblock %}
|
||||
| {% block body %}
|
||||
| {% block attractbody %}
|
||||
#col_main
|
||||
.col_header.item-list-header
|
||||
a.item-project(href="{{url_for('projects.view', project_url=project.url)}}") {{ project.name }}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
| {% extends 'attract/layout.html' %}
|
||||
| {% block page_title %}Shots{% endblock %}
|
||||
| {% block body %}
|
||||
| {% block attractbody %}
|
||||
#col_main
|
||||
h1 Attract projects
|
||||
ul
|
||||
|
@@ -1,8 +1,6 @@
|
||||
li.tabs-attract(
|
||||
title="Attract",
|
||||
data-toggle="tooltip",
|
||||
data-placement="right")
|
||||
| {% if project %}
|
||||
a(href="{{url_for('attract.project_index', project_url=project.url, _external=True)}}")
|
||||
li
|
||||
a.navbar-item(
|
||||
href="{{ url_for('attract.project_index', project_url=project.url) }}"
|
||||
title="Attract Production Tracking")
|
||||
i.pi-attract
|
||||
| {% endif %}
|
||||
span Production Tracking
|
||||
|
@@ -1,7 +1,8 @@
|
||||
| {% extends 'attract/layout.html' %}
|
||||
| {% block bodyattrs %}{{ super() }} data-context='task'{% endblock %}
|
||||
| {% block page_title %}Tasks - {{ project.name }} {% endblock %}
|
||||
| {% block body %}
|
||||
| {% block attractbody %}
|
||||
|
||||
#col_main
|
||||
.col_header.item-list-header
|
||||
a.item-project(href="{{url_for('projects.view', project_url=project.url)}}") {{ project.name }}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
| {% extends 'attract/layout.html' %}
|
||||
| {% block bodyattrs %}{{ super() }} data-context='task'{% endblock %}
|
||||
| {% block page_title %}Tasks for You{% endblock %}
|
||||
| {% block body %}
|
||||
| {% block attractbody %}
|
||||
#col_main
|
||||
| {% from "attract/tasks/task_list_for_user.html" import task_list_for_user %}
|
||||
| {{ task_list_for_user(task_count, tasks) }}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
| {% extends 'attract/layout.html' %}
|
||||
| {% block page_title %}Tasks{% endblock %}
|
||||
| {% block body %}
|
||||
| {% block attractbody %}
|
||||
#col_main
|
||||
.col_header Tasks
|
||||
|
||||
|
Reference in New Issue
Block a user