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:
2019-02-07 14:45:55 +01:00
parent 763866787d
commit 66212ec5fa
15 changed files with 104 additions and 141 deletions

View File

@@ -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)

View File

@@ -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>')

View File

@@ -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>')

View File

@@ -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>')

View File

@@ -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

View File

@@ -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 }}

View File

@@ -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

View File

@@ -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 %}

View File

@@ -1,6 +1,6 @@
| {% extends 'attract/layout.html' %}
| {% block page_title %}{{ project.name }} - Attract{% endblock %}
| {% block body %}
| {% block attractbody %}
#page-container
#page-content
.project

View File

@@ -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 }}

View File

@@ -1,6 +1,6 @@
| {% extends 'attract/layout.html' %}
| {% block page_title %}Shots{% endblock %}
| {% block body %}
| {% block attractbody %}
#col_main
h1 Attract projects
ul

View File

@@ -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

View File

@@ -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 }}

View File

@@ -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) }}

View File

@@ -1,6 +1,6 @@
| {% extends 'attract/layout.html' %}
| {% block page_title %}Tasks{% endblock %}
| {% block body %}
| {% block attractbody %}
#col_main
.col_header Tasks