Introducing Pillar Framework
Refactor of pillar-server and pillar-web into a single python package. This simplifies the overall architecture of pillar applications. Special thanks @sybren and @venomgfx
This commit is contained in:
22
src/templates/projects/_scripts.jade
Normal file
22
src/templates/projects/_scripts.jade
Normal file
@@ -0,0 +1,22 @@
|
||||
script(type="text/javascript").
|
||||
|
||||
/* Convert Markdown */
|
||||
var convert = new Markdown.getSanitizingConverter().makeHtml;
|
||||
var convert_fields = '.node-details-description, .blog_index-item .item-content';
|
||||
|
||||
/* Parse description/content fields to convert markdown */
|
||||
$(convert_fields).each(function(i){
|
||||
$(convert_fields).eq(i).html(convert($(convert_fields).eq(i).text()));
|
||||
});
|
||||
|
||||
ProjectUtils.setProjectAttributes({isProject: true, nodeId: '', parentNodeId: ''});
|
||||
var movingMode = Cookies.getJSON('bcloud_moving_node');
|
||||
|
||||
if (movingMode){
|
||||
$('#item_move_accept').removeClass('disabled').html('<i class="pi-check"></i> Move to Root');
|
||||
|
||||
if (movingMode.node_type === 'texture'){
|
||||
$('#item_move_accept').addClass('disabled').html('Select a Texture Folder');
|
||||
}
|
||||
|
||||
};
|
250
src/templates/projects/edit.jade
Normal file
250
src/templates/projects/edit.jade
Normal file
@@ -0,0 +1,250 @@
|
||||
| {% extends 'layout.html' %}
|
||||
|
||||
| {% set title = 'edit' %}
|
||||
|
||||
| {% block page_title %}Edit {{ project.name }}{% endblock %}
|
||||
|
||||
| {% block body %}
|
||||
#project-container
|
||||
#project-side-container
|
||||
#project_sidebar
|
||||
ul.project-tabs
|
||||
li.tabs-thumbnail(
|
||||
title="About",
|
||||
data-toggle="tooltip",
|
||||
data-placement="left",
|
||||
class="{% if title == 'about' %}active {% endif %}{% if project.picture_square %}image{% endif %}")
|
||||
a(href="{{url_for('projects.about', project_url=project.url, _external=True)}}")
|
||||
#project-loading
|
||||
i.pi-spin
|
||||
| {% if project.picture_square %}
|
||||
img(src="{{ project.picture_square.thumbnail('b', api=api) }}")
|
||||
| {% else %}
|
||||
i.pi-home
|
||||
| {% endif %}
|
||||
li.tabs-browse(
|
||||
title="Browse",
|
||||
data-toggle="tooltip",
|
||||
data-placement="left")
|
||||
a(href="{{url_for('projects.view', project_url=project.url, _external=True)}}")
|
||||
i.pi-tree-flow
|
||||
| {% if not project.is_private %}
|
||||
li.tabs-search(
|
||||
title="Search",
|
||||
data-toggle="tooltip",
|
||||
data-placement="left")
|
||||
a(href="{{url_for('projects.search', project_url=project.url, _external=True)}}")
|
||||
i.pi-search
|
||||
| {% endif %}
|
||||
|
||||
.project_nav-toggle-btn(
|
||||
title="Expand Navigation [T]",
|
||||
data-toggle="tooltip",
|
||||
data-placement="right")
|
||||
i.pi-angle-double-left
|
||||
|
||||
#project_nav
|
||||
#project_nav-container
|
||||
#project_nav-header
|
||||
.project-title
|
||||
a(href="{{url_for('projects.view', project_url=project.url, _external=True)}}")
|
||||
| {{ project.name }}
|
||||
|
||||
// TODO - make list a macro
|
||||
#project_tree
|
||||
ul.project_nav-edit-list
|
||||
li(class="{% if title == 'edit' %}active{% endif %}")
|
||||
a(href="{{ url_for('projects.edit', project_url=project.url) }}")
|
||||
i.pi-list
|
||||
| Overview
|
||||
li(class="{% if title == 'sharing' %}active{% endif %}")
|
||||
a(href="{{ url_for('projects.sharing', project_url=project.url) }}")
|
||||
i.pi-share
|
||||
| Sharing
|
||||
li(class="{% if title == 'edit_node_types' %}active{% endif %}")
|
||||
a(href="{{ url_for('projects.edit_node_types', project_url=project.url) }}")
|
||||
i.pi-puzzle
|
||||
| Node Types
|
||||
|
||||
.project_split(title="Toggle Navigation [T]")
|
||||
|
||||
#project_context-container
|
||||
#project_context-header
|
||||
span#project-statusbar
|
||||
|
||||
span#project-edit-title
|
||||
| Edit Project
|
||||
|
||||
ul.project-edit-tools
|
||||
|
||||
// Edit Mode
|
||||
li.button-cancel
|
||||
a#item_cancel.project-mode-edit(
|
||||
href="{{url_for('projects.view', project_url=project.url, _external=True)}}",
|
||||
title="Cancel changes")
|
||||
i.button-cancel-icon.pi-back
|
||||
| Go to Project
|
||||
|
||||
li.button-save
|
||||
a#item_save.project-mode-edit(
|
||||
href="#",
|
||||
title="Save changes")
|
||||
i.button-save-icon.pi-check
|
||||
| Save Changes
|
||||
#project_context
|
||||
#node-edit-container
|
||||
form(
|
||||
id="node-edit-form"
|
||||
method='POST',
|
||||
action="{{url_for('projects.edit', project_url=project.url)}}")
|
||||
|
||||
| {% with errors = errors %}
|
||||
| {% if errors %}
|
||||
| {% for field in errors %}
|
||||
.alert.alert-danger(role='alert')
|
||||
strong {{field}}
|
||||
| {% for message in errors[field] %}
|
||||
| {{message}}|
|
||||
| {% endfor %}
|
||||
| {% endfor %}
|
||||
| {% endif %}
|
||||
| {% endwith %}
|
||||
|
||||
| {% for field in form %}
|
||||
|
||||
| {% if field.name == 'csrf_token' %}
|
||||
| {{ field }}
|
||||
| {% else %}
|
||||
| {% if field.type == 'HiddenField' %}
|
||||
| {{ field }}
|
||||
| {% else %}
|
||||
|
||||
| {% if field.name not in hidden_fields %}
|
||||
|
||||
.form-group(class="{{field.name}}{% if field.errors %} error{% endif %}")
|
||||
| {{ field.label }}
|
||||
| {% if field.name == 'picture' %}
|
||||
| {% if post.picture %}
|
||||
img.node-preview-thumbnail(src="{{ post.picture.thumbnail('m', api=api) }}")
|
||||
a(href="#", class="file_delete", data-field-name="picture", data-file_id="{{post.picture._id}}") Delete
|
||||
| {% endif %}
|
||||
| {% endif %}
|
||||
| {{ field(class='form-control') }}
|
||||
|
||||
| {% if field.errors %}
|
||||
ul.error
|
||||
| {% for error in field.errors %}
|
||||
li {{ error }}
|
||||
| {% endfor %}
|
||||
| {% endif %}
|
||||
|
||||
| {% else %}
|
||||
| {{ field(class='hidden') }}
|
||||
| {% endif %}
|
||||
|
||||
| {% endif %}
|
||||
| {% endif %}
|
||||
|
||||
| {% endfor %}
|
||||
|
||||
|
||||
ul.project-edit-tools.bottom
|
||||
li.button-cancel
|
||||
a#item_cancel.project-mode-edit(
|
||||
href="{{url_for('projects.view', project_url=project.url, _external=True)}}",
|
||||
title="Cancel changes")
|
||||
i.button-cancel-icon.pi-back
|
||||
| Go to Project
|
||||
|
||||
li.button-save
|
||||
a#item_save.project-mode-edit(
|
||||
href="#",
|
||||
title="Save changes")
|
||||
i.button-save-icon.pi-check
|
||||
| Save Changes
|
||||
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_scripts %}
|
||||
script(type='text/javascript', src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.ui.widget.min.js') }}")
|
||||
script(type='text/javascript', src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.iframe-transport.min.js') }}")
|
||||
script(type='text/javascript', src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.fileupload.min.js') }}")
|
||||
script(type='text/javascript', src="{{ url_for('static_pillar', filename='assets/js/file_upload.min.js') }}")
|
||||
|
||||
script(type="text/javascript").
|
||||
|
||||
/* UI Stuff */
|
||||
$(window).on("load resize",function(){
|
||||
containerResizeY($(window).height());
|
||||
});
|
||||
|
||||
/* Initialize scrollbars */
|
||||
if ((typeof Ps !== 'undefined') && window.innerWidth > 768){
|
||||
Ps.initialize(document.getElementById('project_tree'), {suppressScrollX: true});
|
||||
}
|
||||
|
||||
$('.project-mode-edit').show();
|
||||
|
||||
ProjectUtils.setProjectAttributes({projectId: "{{project._id}}", isProject: true, nodeId: ''});
|
||||
var convert = new Markdown.getSanitizingConverter().makeHtml;
|
||||
|
||||
$('.button-save').on('click', function(e){
|
||||
e.preventDefault();
|
||||
// Disable beforeunolad when submitting a form
|
||||
$(window).off('beforeunload');
|
||||
|
||||
$(this).children('a').html('<i class="pi-spin spin"></i> Saving');
|
||||
$('#node-edit-form').submit();
|
||||
});
|
||||
|
||||
/* Build the markdown preview when typing in textarea */
|
||||
$(function() {
|
||||
|
||||
var $textarea = $('.form-group.description textarea'),
|
||||
$loader = $('<div class="md-preview-loading"><i class="pi-spin spin"></i></div>').insertAfter($textarea),
|
||||
$preview = $('<div class="node-edit-form-md-preview" />').insertAfter($loader);
|
||||
|
||||
$loader.hide();
|
||||
|
||||
// Delay function to not start converting heavy posts immediately
|
||||
var delay = (function(){
|
||||
var timer = 0;
|
||||
return function(callback, ms){
|
||||
clearTimeout (timer);
|
||||
timer = setTimeout(callback, ms);
|
||||
};
|
||||
})();
|
||||
|
||||
$textarea.keyup(function() {
|
||||
/* If there's an iframe (YouTube embed), delay markdown convert 1.5s */
|
||||
if (/iframe/i.test($textarea.val())) {
|
||||
$loader.show();
|
||||
|
||||
delay(function(){
|
||||
// Convert markdown
|
||||
$preview.html(convert($textarea.val()));
|
||||
$loader.hide();
|
||||
}, 1500 );
|
||||
} else {
|
||||
// Convert markdown
|
||||
$preview.html(convert($textarea.val()));
|
||||
};
|
||||
}).trigger('keyup');
|
||||
|
||||
$('input, textarea').keypress(function () {
|
||||
// Unused: save status of the page as 'edited'
|
||||
ProjectUtils.setProjectAttributes({isModified: true});
|
||||
// Set the beforeunload to warn the user of unsaved changes
|
||||
$(window).on('beforeunload', function () {
|
||||
return 'You have unsaved changes in your project.';
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_navigation %}
|
||||
| {% endblock %}
|
||||
| {% block footer %}
|
||||
| {% endblock %}
|
88
src/templates/projects/edit_node_type.jade
Normal file
88
src/templates/projects/edit_node_type.jade
Normal file
@@ -0,0 +1,88 @@
|
||||
| {% extends 'layout.html' %}
|
||||
|
||||
| {% set title = 'edit_node_types' %}
|
||||
|
||||
| {% block page_title %}Project {{ project.name }}{% endblock %}
|
||||
|
||||
| {% block body %}
|
||||
.container.box
|
||||
form(
|
||||
method='POST',
|
||||
action="{{url_for('projects.edit_node_type', project_url=project.url, node_type_name=node_type['name'])}}")
|
||||
|
||||
#blog_container.post-create
|
||||
|
||||
| {% with errors = errors %}
|
||||
| {% if errors %}
|
||||
| {% for field in errors %}
|
||||
.alert.alert-danger(role='alert')
|
||||
strong {{field}}
|
||||
| {% for message in errors[field] %}
|
||||
| {{message}}|
|
||||
| {% endfor %}
|
||||
| {% endfor %}
|
||||
| {% endif %}
|
||||
| {% endwith %}
|
||||
|
||||
#blog_index-sidebar
|
||||
.blog_project-sidebar
|
||||
input.btn.btn-default.button-create(type='submit', value="Update {{ node_type['name'] }}")
|
||||
a.btn.btn-default.button-back(href="{{ url_for('projects.view', project_url=project.url) }}")
|
||||
| Back to Project
|
||||
|
||||
#blog_post-edit-container
|
||||
#blog_post-edit-title
|
||||
| Edit {{ node_type['name'] }}
|
||||
|
||||
#blog_post-edit-form
|
||||
| {% for field in form %}
|
||||
| {% if field.name == 'csrf_token' %}
|
||||
| {{ field }}
|
||||
| {% else %}
|
||||
| {% if field.type == 'HiddenField' %}
|
||||
| {{ field }}
|
||||
| {% else %}
|
||||
.form-group(class="{{field.name}}{% if field.errors %} error{% endif %}")
|
||||
| {{ field.label }}
|
||||
| {{ field(class='form-control') }}
|
||||
|
||||
| {% if field.errors %}
|
||||
ul.error
|
||||
| {% for error in field.errors %}
|
||||
li {{ error }}
|
||||
| {% endfor %}
|
||||
| {% endif %}
|
||||
|
||||
| {% endif %}
|
||||
| {% endif %}
|
||||
| {% endfor %}
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_scripts%}
|
||||
script(src="https://cdn.jsdelivr.net/g/ace@1.2.3(noconflict/ace.js+noconflict/mode-json.js)")
|
||||
|
||||
script.
|
||||
var dynSchemaEditorContainer = $("<div>", {id: "dyn_schema_editor"});
|
||||
$(".form-group.dyn_schema").before(dynSchemaEditorContainer);
|
||||
var dynSchemaEditor = ace.edit("dyn_schema_editor");
|
||||
dynSchemaEditor.getSession().setValue($("#dyn_schema").val());
|
||||
|
||||
var formSchemaEditorContainer = $("<div>", {id: "form_schema_editor"});
|
||||
$(".form-group.form_schema").before(formSchemaEditorContainer);
|
||||
var formSchemaEditor = ace.edit("form_schema_editor");
|
||||
formSchemaEditor.getSession().setValue($("#form_schema").val());
|
||||
|
||||
var permissionsEditorContainer = $("<div>", {id: "permissions_editor"});
|
||||
$(".form-group.permissions").before(permissionsEditorContainer);
|
||||
var permissionsEditor = ace.edit("permissions_editor");
|
||||
permissionsEditor.getSession().setValue($("#permissions").val());
|
||||
|
||||
$("form").submit(function(e) {
|
||||
$("#dyn_schema").val(dynSchemaEditor.getSession().getValue());
|
||||
$("#form_schema").val(formSchemaEditor.getSession().getValue());
|
||||
$("#permissions").val(permissionsEditor.getSession().getValue());
|
||||
});
|
||||
| {% endblock %}
|
||||
|
||||
|
110
src/templates/projects/edit_node_types.jade
Normal file
110
src/templates/projects/edit_node_types.jade
Normal file
@@ -0,0 +1,110 @@
|
||||
| {% extends 'layout.html' %}
|
||||
|
||||
| {% set title = 'edit_node_types' %}
|
||||
|
||||
| {% block page_title %}Node Types: {{ project.name }}{% endblock %}
|
||||
|
||||
| {% block body %}
|
||||
#project-container
|
||||
#project-side-container
|
||||
#project_sidebar
|
||||
ul.project-tabs
|
||||
li.tabs-thumbnail(
|
||||
title="About",
|
||||
data-toggle="tooltip",
|
||||
data-placement="left",
|
||||
class="{% if title == 'about' %}active {% endif %}{% if project.picture_square %}image{% endif %}")
|
||||
a(href="{{url_for('projects.about', project_url=project.url, _external=True)}}")
|
||||
#project-loading
|
||||
i.pi-spin
|
||||
| {% if project.picture_square %}
|
||||
img(src="{{ project.picture_square.thumbnail('b', api=api) }}")
|
||||
| {% else %}
|
||||
i.pi-home
|
||||
| {% endif %}
|
||||
li.tabs-browse(
|
||||
title="Browse",
|
||||
data-toggle="tooltip",
|
||||
data-placement="left")
|
||||
a(href="{{url_for('projects.view', project_url=project.url, _external=True)}}")
|
||||
i.pi-tree-flow
|
||||
| {% if not project.is_private %}
|
||||
li.tabs-search(
|
||||
title="Search",
|
||||
data-toggle="tooltip",
|
||||
data-placement="left")
|
||||
a(href="{{url_for('projects.search', project_url=project.url, _external=True)}}")
|
||||
i.pi-search
|
||||
| {% endif %}
|
||||
|
||||
.project_nav-toggle-btn(
|
||||
title="Expand Navigation [T]",
|
||||
data-toggle="tooltip",
|
||||
data-placement="right")
|
||||
i.pi-angle-double-left
|
||||
|
||||
#project_nav
|
||||
#project_nav-container
|
||||
#project_nav-header
|
||||
.project-title
|
||||
a(href="{{url_for('projects.view', project_url=project.url, _external=True)}}")
|
||||
| {{ project.name }}
|
||||
|
||||
// TODO - make list a macro
|
||||
#project_tree
|
||||
ul.project_nav-edit-list
|
||||
li(class="{% if title == 'edit' %}active{% endif %}")
|
||||
a(href="{{ url_for('projects.edit', project_url=project.url) }}")
|
||||
i.pi-list
|
||||
| Overview
|
||||
li(class="{% if title == 'sharing' %}active{% endif %}")
|
||||
a(href="{{ url_for('projects.sharing', project_url=project.url) }}")
|
||||
i.pi-share
|
||||
| Sharing
|
||||
li(class="{% if title == 'edit_node_types' %}active{% endif %}")
|
||||
a(href="{{ url_for('projects.edit_node_types', project_url=project.url) }}")
|
||||
i.pi-puzzle
|
||||
| Node Types
|
||||
|
||||
.project_split(title="Toggle Navigation [T]")
|
||||
|
||||
|
||||
#project_context-container
|
||||
#project_context-header
|
||||
span#project-statusbar
|
||||
|
||||
span#project-edit-title
|
||||
| Edit Project
|
||||
|
||||
#project_context
|
||||
#node-edit-container
|
||||
div(id="node-edit-form")
|
||||
h3 Node Types (coming soon)
|
||||
p.
|
||||
Nodes are all the items that can be found in a project.
|
||||
Everything is a node: a file, a folder, a comment. They are
|
||||
defined with custom properties and properly presented to you.
|
||||
When we add support for new node types in the future, it means we
|
||||
allow the creation of new items (such as textures).
|
||||
|
||||
| {% if current_user.has_role('admin') %}
|
||||
ul
|
||||
| {% for node_type in project.node_types %}
|
||||
li
|
||||
a(href="{{ url_for('projects.edit_node_type', project_url=project.url, node_type_name=node_type.name) }}")
|
||||
| {{node_type.name}}
|
||||
| {% endfor %}
|
||||
| {% endif %}
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_scripts %}
|
||||
script(type="text/javascript").
|
||||
$(window).on("load resize",function(){
|
||||
containerResizeY($(window).height());
|
||||
});
|
||||
| {% endblock %}
|
||||
| {% block footer_navigation %}
|
||||
| {% endblock %}
|
||||
| {% block footer %}
|
||||
| {% endblock %}
|
139
src/templates/projects/home_images.jade
Normal file
139
src/templates/projects/home_images.jade
Normal file
@@ -0,0 +1,139 @@
|
||||
| {% extends 'projects/home_layout.html' %}
|
||||
| {% set subtab = 'images' %}
|
||||
| {% set learn_more_btn_url = '/blog/introducing-image-sharing' %}
|
||||
| {% block currenttab %}
|
||||
section.nav-tabs__tab.active#tab-images
|
||||
.tab_header-container
|
||||
| {% if not shared_images %}
|
||||
.tab_header-intro(
|
||||
style="background-image: url({{ url_for('static', filename='assets/img/backgrounds/pattern_01.jpg')}})")
|
||||
.tab_header-intro_text
|
||||
h2 Share what you see.
|
||||
p.
|
||||
Got a nice render, a Blender oddity, or a cool screenshot?
|
||||
<br/>
|
||||
Share it instantly from within Blender to the world!
|
||||
.tab_header-intro_icons
|
||||
i.pi-blender
|
||||
i.pi-heart-filled
|
||||
i.pi-picture-album
|
||||
| {% endif %}
|
||||
|
||||
| {% if shared_images %}
|
||||
div#home-images__list
|
||||
| {% for node in shared_images %}
|
||||
div.home-images__list-item
|
||||
.home-images__list-details
|
||||
a.title(href="{{ url_for_node(node=node) }}?t")
|
||||
| {{ node.name }}
|
||||
| {% if node.picture %}
|
||||
a.home-images__list-thumbnail(
|
||||
href="{{ url_for_node(node=node) }}?t")
|
||||
img(src="{{ node.picture.thumbnail('l', api=api) }}")
|
||||
| {% endif %}
|
||||
.home-images__list-details
|
||||
ul.meta
|
||||
li.when(title="{{ node._created }}") {{ node._created | pretty_date_time }}
|
||||
li.delete-image
|
||||
a.delete-prompt(href='javascript:void(0);')
|
||||
| Delete
|
||||
span.delete-confirm
|
||||
| Are you sure?
|
||||
a.delete-confirm(href='javascript:void(0);',
|
||||
data-image-id="{{ node._id }}")
|
||||
i.pi-check
|
||||
| Yes, delete
|
||||
a.delete-cancel(href='javascript:void(0);')
|
||||
i.pi-cancel
|
||||
| No, cancel
|
||||
| {% if node.short_link %}
|
||||
li
|
||||
a(href="{{ node.short_link }}") {{ node.short_link }}
|
||||
| {% endif %}
|
||||
| {% endfor %}
|
||||
| {% else %}
|
||||
.blender_sync-main.empty
|
||||
.blender_sync-main-header
|
||||
span.blender_sync-main-title
|
||||
| Share some images using the
|
||||
a(
|
||||
href="https://cloud.blender.org/r/downloads/blender_cloud-latest-bundle.zip")
|
||||
| Blender Cloud add-on.
|
||||
|
||||
| {% endif %}
|
||||
| {% endblock %}
|
||||
|
||||
| {% block side_announcement %}
|
||||
.title
|
||||
a(href="https://cloud.blender.org/blog/introducing-image-sharing") Image Sharing
|
||||
|
||||
.lead
|
||||
p.
|
||||
Share your renders, painted textures, and other images, straight from Blender
|
||||
to the cloud.
|
||||
hr
|
||||
| {% if show_addon_download_buttons %}
|
||||
p.
|
||||
Image Sharing requires a Blender Cloud subscription, which you have!
|
||||
| {% else %}
|
||||
p.
|
||||
Image Sharing requires a Blender Cloud subscription.
|
||||
|
||||
.buttons
|
||||
a.btn.btn-default.btn-outline.green(href="https://store.blender.org/product/membership/")
|
||||
| Join Now
|
||||
| {% endif %}
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_scripts %}
|
||||
| {{ super() }}
|
||||
script.
|
||||
var urlNodeDelete = "{{url_for('projects.delete_node')}}";
|
||||
|
||||
$(document).ready(function() {
|
||||
// 'Delete' link on images
|
||||
var $home_image_list = $('#home-images__list');
|
||||
$home_image_list.find('a.delete-prompt').on('click', function(e){
|
||||
$(this)
|
||||
.hide()
|
||||
.next().show();
|
||||
});
|
||||
|
||||
// 'Cancel delete' link on images
|
||||
$home_image_list.find('a.delete-cancel').on('click', function(e){
|
||||
$(this).parent()
|
||||
.hide()
|
||||
.prev().show();
|
||||
});
|
||||
|
||||
// 'Confirm delete' link on images
|
||||
$home_image_list.find('a.delete-confirm').on('click', function (e) {
|
||||
var image_id = this.dataset.imageId;
|
||||
|
||||
var $this = $(this);
|
||||
var parent = $this.closest('.home-images__list-item');
|
||||
console.log('My parent is', parent);
|
||||
var error_elt = $this.parent();
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: urlNodeDelete,
|
||||
data: {node_id: image_id},
|
||||
success: function () {
|
||||
if (parent.siblings().length == 0) {
|
||||
// This was the last shared image. Reload the page,
|
||||
// so that we can show the correct "no images shared"
|
||||
// content with Jinja2.
|
||||
window.location = window.location;
|
||||
}
|
||||
parent.hide('slow', function() { parent.remove(); });
|
||||
},
|
||||
error: function (jqxhr, textStatus, errorThrown) {
|
||||
error_elt.text('Unable to delete image; ' + textStatus + ': ' + errorThrown);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
hopToTop(); // Display jump to top button
|
||||
});
|
||||
| {% endblock %}
|
43
src/templates/projects/home_index.jade
Normal file
43
src/templates/projects/home_index.jade
Normal file
@@ -0,0 +1,43 @@
|
||||
| {% extends 'projects/home_layout.html' %}
|
||||
| {% set subtab = 'blender_sync' %}
|
||||
| {% set learn_more_btn_url = '/blog/introducing-blender-sync' %}
|
||||
| {% block currenttab %}
|
||||
section.nav-tabs__tab.active#tab-blender_sync
|
||||
.tab_header-container
|
||||
.tab_header-intro(
|
||||
style="background-image: url({{ url_for('static', filename='assets/img/backgrounds/pattern_01.jpg')}})")
|
||||
.tab_header-intro_text
|
||||
h2 Connect Blender with the Cloud
|
||||
p
|
||||
| Save your Blender preferences once, load them anywhere.
|
||||
<br/>
|
||||
| Use the
|
||||
=' '
|
||||
a(href='https://cloud.blender.org/r/downloads/blender_cloud-latest-bundle.zip') Blender Cloud add-on
|
||||
=' '
|
||||
| to synchronise your settings from within Blender.
|
||||
.tab_header-intro_icons
|
||||
i.pi-blender
|
||||
i.pi-heart-filled
|
||||
i.pi-blender-cloud
|
||||
|
||||
| {% for version in synced_versions %}
|
||||
.blender_sync-main
|
||||
.blender_sync-main-header
|
||||
h2.blender_sync-main-title
|
||||
i.pi-blender
|
||||
| Blender {{ version.version }}
|
||||
.blender_sync-main-last
|
||||
| Last synced on: {{ version.date|pretty_date }}
|
||||
| {% else %}
|
||||
.blender_sync-main.empty
|
||||
.blender_sync-main-header
|
||||
span.blender_sync-main-title
|
||||
| No settings synced yet
|
||||
<hr/>
|
||||
a.download(
|
||||
href='https://cloud.blender.org/r/downloads/blender_cloud-latest-bundle.zip')
|
||||
| Download add-on
|
||||
| {% endfor %}
|
||||
| {% endblock %}
|
||||
|
79
src/templates/projects/home_layout.jade
Normal file
79
src/templates/projects/home_layout.jade
Normal file
@@ -0,0 +1,79 @@
|
||||
| {% extends 'layout.html' %}
|
||||
| {% from '_macros/_navigation.html' import navigation_tabs %}
|
||||
|
||||
| {% set title = 'home' %}
|
||||
|
||||
| {% block og %}
|
||||
meta(property="og:title", content="Blender Cloud - Home")
|
||||
meta(property="og:url", content="https://cloud.blender.org{{ request.path }}")
|
||||
meta(property="og:type", content="website")
|
||||
| {% endblock %}
|
||||
|
||||
| {% block tw %}
|
||||
meta(name="twitter:card", content="summary_large_image")
|
||||
meta(name="twitter:site", content="@Blender_Cloud")
|
||||
meta(name="twitter:title", content="Blender Cloud")
|
||||
meta(name="twitter:image", content="{{ url_for('static', filename='assets/img/backgrounds/cloud_services_oti.jpg')}}")
|
||||
| {% endblock %}
|
||||
|
||||
| {% block page_title %}
|
||||
| {{current_user.full_name}}
|
||||
| {% endblock %}
|
||||
|
||||
| {% block body %}
|
||||
.dashboard-container
|
||||
section#main
|
||||
| {{ navigation_tabs(title) }}
|
||||
|
||||
section#projects
|
||||
|
||||
section#sub-nav-tabs.home
|
||||
ul#sub-nav-tabs__list
|
||||
li.nav-tabs__list-tab#subtab-blender_sync(data-tab-url='.')
|
||||
i.pi-blender
|
||||
| Blender Sync
|
||||
|
||||
li.nav-tabs__list-tab#subtab-images(data-tab-url='images')
|
||||
i.pi-picture
|
||||
| Images
|
||||
| {% block currenttab %}{% endblock %}
|
||||
|
||||
section#side
|
||||
section#announcement
|
||||
img.header(
|
||||
src="{{ url_for('static', filename='assets/img/blender_sync_header.jpg') }}")
|
||||
.text
|
||||
| {% block side_announcement %}
|
||||
.title
|
||||
a(href="https://cloud.blender.org/blog/introducing-blender-sync") Blender Sync
|
||||
|
||||
.lead
|
||||
span.
|
||||
Save your settings once. Use them anywhere.
|
||||
Carry your Blender configuration with you, use our free add-on to sync your keymaps and preferences.
|
||||
<hr/>
|
||||
Syncing is free for everyone. No subscription required.
|
||||
| {% endblock %}
|
||||
| {% if show_addon_download_buttons %}
|
||||
.buttons
|
||||
a.btn.btn-default.btn-outline.orange(
|
||||
href="https://cloud.blender.org/r/downloads/blender_cloud-latest-bundle.zip")
|
||||
i.pi-download
|
||||
| Download <small>v</small>{{ config.BLENDER_CLOUD_ADDON_VERSION }}
|
||||
a.btn.btn-default.btn-outline.blue(
|
||||
href="{{ learn_more_btn_url }}")
|
||||
| Learn More
|
||||
| {% endif %}
|
||||
| {% endblock %}
|
||||
|
||||
|
||||
| {% block footer_scripts %}
|
||||
script.
|
||||
$(document).ready(function () {
|
||||
$('#subtab-{{ subtab }}').addClass('active');
|
||||
var $nav_tabs = $('#sub-nav-tabs__list').find('li.nav-tabs__list-tab');
|
||||
$nav_tabs.on('click', function (e) {
|
||||
window.location = $(this).attr('data-tab-url');
|
||||
});
|
||||
});
|
||||
| {% endblock %}
|
87
src/templates/projects/index_collection.jade
Normal file
87
src/templates/projects/index_collection.jade
Normal file
@@ -0,0 +1,87 @@
|
||||
| {% extends 'layout.html' %}
|
||||
|
||||
| {% block og %}
|
||||
meta(property="og:title", content="{% if title == 'open-projects' %}Open Projects{% elif title == 'training' %}Training{% endif %}")
|
||||
// XXX - Replace with actual url
|
||||
meta(property="og:url", content="https://cloud.blender.org")
|
||||
meta(property="og:type", content="website")
|
||||
| {% endblock %}
|
||||
|
||||
| {% block tw %}
|
||||
meta(name="twitter:card", content="summary_large_image")
|
||||
meta(name="twitter:site", content="@Blender_Cloud")
|
||||
meta(name="twitter:title", content="{% if title == 'open-projects' %}Open Projects{% elif title == 'training' %}Training{% endif %} on Blender Cloud")
|
||||
meta(name="twitter:description", content="{% if title == 'open-projects' %}Full production data and tutorials from all open movies, for you to use freely{% elif title == 'training' %}Production quality training by 3D professionals{% endif %}")
|
||||
meta(name="twitter:image", content="{% if title == 'training' %}{{ url_for('static', filename='assets/img/backgrounds/background_caminandes_3_03.jpg')}}{% else %}{{ url_for('static', filename='assets/img/backgrounds/background_agent327_01.jpg')}}{% endif %}")
|
||||
| {% endblock %}
|
||||
|
||||
| {% block page_title %}
|
||||
| {% if title == 'open-projects' %}Open Projects{% elif title == 'training' %}Training{% else %}Projects{% endif %}
|
||||
| {% endblock %}
|
||||
|
||||
| {% block body %}
|
||||
|
||||
#project-container
|
||||
|
||||
#node_index-container
|
||||
#node_index-header.collection
|
||||
img.background-header(src="{% if title == 'training' %}{{ url_for('static', filename='assets/img/backgrounds/background_caminandes_3_03.jpg')}}{% else %}{{ url_for('static', filename='assets/img/backgrounds/background_agent327_01.jpg')}}{% endif %}")
|
||||
#node_index-collection-info
|
||||
| {% if title == 'open-projects' %}
|
||||
.node_index-collection-name
|
||||
span Open Projects
|
||||
.node_index-collection-description
|
||||
span.
|
||||
The iconic Blender Institute Open Movies.
|
||||
Featuring all the production files, assets, artwork, and never-seen-before content.
|
||||
| {% elif title == 'training' %}
|
||||
.node_index-collection-name
|
||||
span Training
|
||||
.node_index-collection-description
|
||||
span.
|
||||
Character modeling, 3D printing, VFX, rigging and more.
|
||||
| {% endif %}
|
||||
|
||||
.node_index-collection
|
||||
|
||||
| {% for project in projects %}
|
||||
| {% if (project.status == 'published') or (project.status == 'pending' and current_user.is_authenticated) and project._id != config.MAIN_PROJECT_ID %}
|
||||
|
||||
.node_index-collection-card.project(
|
||||
data-url="{{ url_for('projects.view', project_url=project.url) }}",
|
||||
tabindex="{{ loop.index }}")
|
||||
| {% if project.picture_header %}
|
||||
a.item-header(
|
||||
href="{{ url_for('projects.view', project_url=project.url) }}")
|
||||
img(src="{{ project.picture_header.thumbnail('m', api=api) }}")
|
||||
| {% endif %}
|
||||
|
||||
.item-info
|
||||
a.item-title(
|
||||
href="{{ url_for('projects.view', project_url=project.url) }}")
|
||||
| {{project.name}}
|
||||
| {% if project.status == 'pending' and current_user.is_authenticated and current_user.has_role('admin') %}
|
||||
small (pending)
|
||||
| {% endif %}
|
||||
|
||||
| {% if project.summary %}
|
||||
p.item-description
|
||||
| {{project.summary|safe}}
|
||||
| {% endif %}
|
||||
|
||||
a.learn-more LEARN MORE
|
||||
|
||||
| {% endif %}
|
||||
| {% endfor %}
|
||||
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
|
||||
| {% block footer_scripts %}
|
||||
script.
|
||||
$('.node_index-collection-card.project').on('click', function(e){
|
||||
e.preventDefault();
|
||||
window.location.href = $(this).data('url');
|
||||
});
|
||||
| {% endblock %}
|
232
src/templates/projects/index_dashboard.jade
Normal file
232
src/templates/projects/index_dashboard.jade
Normal file
@@ -0,0 +1,232 @@
|
||||
| {% extends 'layout.html' %}
|
||||
| {% from '_macros/_navigation.html' import navigation_tabs %}
|
||||
|
||||
| {% set title = 'dashboard' %}
|
||||
|
||||
| {% block og %}
|
||||
meta(property="og:title", content="Dashboard")
|
||||
meta(property="og:url", content="https://cloud.blender.org/{{ request.path }}")
|
||||
meta(property="og:type", content="website")
|
||||
| {% endblock %}
|
||||
|
||||
| {% block tw %}
|
||||
meta(name="twitter:card", content="summary_large_image")
|
||||
meta(name="twitter:site", content="@Blender_Cloud")
|
||||
meta(name="twitter:title", content="Blender Cloud")
|
||||
meta(name="twitter:image", content="{{ url_for('static', filename='assets/img/backgrounds/cloud_services_oti.jpg')}}")
|
||||
| {% endblock %}
|
||||
|
||||
| {% block page_title %}
|
||||
| {{current_user.full_name}}
|
||||
| {% endblock %}
|
||||
|
||||
| {% block body %}
|
||||
.dashboard-container
|
||||
section#main
|
||||
| {{ navigation_tabs(title) }}
|
||||
|
||||
section#projects
|
||||
|
||||
section#sub-nav-tabs.projects
|
||||
ul#sub-nav-tabs__list
|
||||
li.nav-tabs__list-tab.active(data-tab-toggle='own_projects')
|
||||
| Own Projects
|
||||
| {% if projects_user|length != 0 %}
|
||||
span ({{ projects_user|length }})
|
||||
| {% endif %}
|
||||
|
||||
li.nav-tabs__list-tab(data-tab-toggle='shared')
|
||||
| Shared with me
|
||||
| {% if projects_shared|length != 0 %}
|
||||
span ({{ projects_shared|length }})
|
||||
| {% endif %}
|
||||
|
||||
| {% if (current_user.has_role('subscriber') or current_user.has_role('admin')) %}
|
||||
li.create(
|
||||
data-url="{{ url_for('projects.create') }}")
|
||||
a#project-create(
|
||||
href="{{ url_for('projects.create') }}")
|
||||
i.pi-plus
|
||||
| Create Project
|
||||
| {% endif %}
|
||||
|
||||
section.nav-tabs__tab.active#own_projects
|
||||
ul.projects__list
|
||||
| {% if projects_user %}
|
||||
| {% for project in projects_user %}
|
||||
li.projects__list-item(
|
||||
data-url="{{ url_for('projects.view', project_url=project.url) }}")
|
||||
a.projects__list-thumbnail(
|
||||
href="{{ url_for('projects.view', project_url=project.url) }}")
|
||||
| {% if project.picture_square %}
|
||||
img(src="{{ project.picture_square.thumbnail('s', api=api) }}")
|
||||
| {% else %}
|
||||
i.pi-blender-cloud
|
||||
| {% endif %}
|
||||
.projects__list-details
|
||||
a.title(href="{{ url_for('projects.view', project_url=project.url) }}")
|
||||
| {{ project.name }}
|
||||
|
||||
ul.meta
|
||||
li.when(title="{{ project._created }}") {{ project._created | pretty_date }}
|
||||
li.edit
|
||||
a(href="{{ url_for('projects.edit', project_url=project.url) }}") Edit
|
||||
| {% if project.status == 'pending' and current_user.is_authenticated and current_user.has_role('admin') %}
|
||||
li.pending Not Published
|
||||
| {% endif %}
|
||||
|
||||
| {% endfor %}
|
||||
| {% else %}
|
||||
li.projects__list-item
|
||||
a.projects__list-thumbnail
|
||||
i.pi-plus
|
||||
.projects__list-details
|
||||
a.title(href="{{ url_for('projects.create') }}")
|
||||
| Create a project to get started!
|
||||
| {% endif %}
|
||||
|
||||
section.nav-tabs__tab#shared
|
||||
ul.projects__list
|
||||
| {% if projects_shared %}
|
||||
| {% for project in projects_shared %}
|
||||
li.projects__list-item(
|
||||
data-url="{{ url_for('projects.view', project_url=project.url) }}")
|
||||
a.projects__list-thumbnail(
|
||||
href="{{ url_for('projects.view', project_url=project.url) }}")
|
||||
| {% if project.picture_square %}
|
||||
img(src="{{ project.picture_square.thumbnail('s', api=api) }}")
|
||||
| {% else %}
|
||||
i.pi-blender-cloud
|
||||
| {% endif %}
|
||||
.projects__list-details
|
||||
a.title(href="{{ url_for('projects.view', project_url=project.url) }}")
|
||||
| {{ project.name }}
|
||||
|
||||
ul.meta
|
||||
li.when {{ project._created | pretty_date }}
|
||||
li.who by {{ project.user.full_name }}
|
||||
li.edit
|
||||
a(href="{{ url_for('projects.edit', project_url=project.url) }}") Edit
|
||||
| {% if project.status == 'pending' and current_user.is_authenticated and current_user.has_role('admin') %}
|
||||
li.pending Not Published
|
||||
| {% endif %}
|
||||
|
||||
li.leave
|
||||
span.user-remove-prompt
|
||||
| Leave Project
|
||||
|
||||
span.user-remove
|
||||
| Are you sure?
|
||||
span.user-remove-confirm(
|
||||
user-id="{{ current_user.objectid }}",
|
||||
project-url="{{url_for('projects.sharing', project_url=project.url)}}")
|
||||
i.pi-check
|
||||
| Yes, leave
|
||||
span.user-remove-cancel
|
||||
i.pi-cancel
|
||||
| No, cancel
|
||||
|
||||
| {% endfor %}
|
||||
| {% else %}
|
||||
li.projects__list-item
|
||||
a.projects__list-thumbnail
|
||||
i.pi-heart
|
||||
.projects__list-details
|
||||
.title
|
||||
| No projects shared with you... yet!
|
||||
| {% endif %}
|
||||
|
||||
section#side
|
||||
section#announcement
|
||||
img.header(
|
||||
src="{{ url_for('static', filename='assets/img/backgrounds/services_projects.jpg')}}")
|
||||
.text
|
||||
.title Projects
|
||||
.lead
|
||||
span.
|
||||
Create and manage your own personal projects.
|
||||
Upload assets and collaborate with other Blender Cloud members.
|
||||
.buttons
|
||||
a.btn.btn-default.btn-outline.blue(
|
||||
href="https://cloud.blender.org/blog/introducing-private-projects")
|
||||
| Learn More
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
|
||||
| {% block footer_scripts %}
|
||||
script.
|
||||
$(document).ready(function() {
|
||||
|
||||
$('li.projects__list-item').click(function(e){
|
||||
url = $(this).data('url');
|
||||
if (typeof url === 'undefined') return;
|
||||
|
||||
window.location.href = url;
|
||||
if (console) console.log(url);
|
||||
|
||||
$(this).addClass('active');
|
||||
$(this).find('.projects__list-thumbnail i')
|
||||
.removeAttr('class')
|
||||
.addClass('pi-spin spin');
|
||||
});
|
||||
|
||||
// Tabs behavior
|
||||
var $nav_tabs_list = $('#sub-nav-tabs__list');
|
||||
var $nav_tabs = $nav_tabs_list.find('li.nav-tabs__list-tab');
|
||||
$nav_tabs.on('click', function(e){
|
||||
e.preventDefault();
|
||||
|
||||
$nav_tabs.removeClass('active');
|
||||
$(this).addClass('active');
|
||||
|
||||
$('.nav-tabs__tab').hide();
|
||||
$('#' + $(this).attr('data-tab-toggle')).show();
|
||||
});
|
||||
|
||||
// Create project
|
||||
$nav_tabs_list.find('li.create').on('click', function(e){
|
||||
e.preventDefault();
|
||||
|
||||
$(this).addClass('disabled');
|
||||
$('a', this).html('<i class="pi-spin spin"></i> Creating project...');
|
||||
|
||||
window.location.href = $(this).data('url');
|
||||
});
|
||||
|
||||
// Leave project
|
||||
var $projects_list = $('ul.projects__list');
|
||||
$projects_list.find('span.user-remove-prompt').on('click', function(e){
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
$(this).next().show();
|
||||
$(this).hide();
|
||||
});
|
||||
|
||||
$projects_list.find('span.user-remove-cancel').on('click', function(e){
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
$(this).parent().prev().show();
|
||||
$(this).parent().hide();
|
||||
});
|
||||
|
||||
$projects_list.find('span.user-remove-confirm').on('click', function(e){
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
var parent = $(this).closest('projects__list-item');
|
||||
|
||||
function removeUser(userId, projectUrl){
|
||||
$.post(projectUrl, {user_id: userId, action: 'remove'})
|
||||
.done(function (data) {
|
||||
parent.remove();
|
||||
});
|
||||
}
|
||||
|
||||
removeUser($(this).attr('user-id'), $(this).attr('project-url'));
|
||||
});
|
||||
|
||||
hopToTop(); // Display jump to top button
|
||||
});
|
||||
| {% endblock %}
|
266
src/templates/projects/sharing.jade
Normal file
266
src/templates/projects/sharing.jade
Normal file
@@ -0,0 +1,266 @@
|
||||
| {% extends 'layout.html' %}
|
||||
|
||||
| {% set title = 'sharing' %}
|
||||
|
||||
| {% block page_title %}Sharing: {{ project.name }}{% endblock %}
|
||||
|
||||
| {% block body %}
|
||||
#project-container
|
||||
#project-side-container
|
||||
#project_sidebar
|
||||
ul.project-tabs
|
||||
li.tabs-thumbnail(
|
||||
title="About",
|
||||
data-toggle="tooltip",
|
||||
data-placement="left",
|
||||
class="{% if title == 'about' %}active {% endif %}{% if project.picture_square %}image{% endif %}")
|
||||
a(href="{{url_for('projects.about', project_url=project.url, _external=True)}}")
|
||||
#project-loading
|
||||
i.pi-spin
|
||||
| {% if project.picture_square %}
|
||||
img(src="{{ project.picture_square.thumbnail('b', api=api) }}")
|
||||
| {% else %}
|
||||
i.pi-home
|
||||
| {% endif %}
|
||||
li.tabs-browse(
|
||||
title="Browse",
|
||||
data-toggle="tooltip",
|
||||
data-placement="left")
|
||||
a(href="{{url_for('projects.view', project_url=project.url, _external=True)}}")
|
||||
i.pi-tree-flow
|
||||
| {% if not project.is_private %}
|
||||
li.tabs-search(
|
||||
title="Search",
|
||||
data-toggle="tooltip",
|
||||
data-placement="left")
|
||||
a(href="{{url_for('projects.search', project_url=project.url, _external=True)}}")
|
||||
i.pi-search
|
||||
| {% endif %}
|
||||
|
||||
.project_nav-toggle-btn(
|
||||
title="Expand Navigation [T]",
|
||||
data-toggle="tooltip",
|
||||
data-placement="right")
|
||||
i.pi-angle-double-left
|
||||
|
||||
#project_nav
|
||||
#project_nav-container
|
||||
#project_nav-header
|
||||
.project-title
|
||||
a(href="{{url_for('projects.view', project_url=project.url, _external=True)}}")
|
||||
| {{ project.name }}
|
||||
|
||||
// TODO - make list a macro
|
||||
#project_tree
|
||||
ul.project_nav-edit-list
|
||||
li(class="{% if title == 'edit' %}active{% endif %}")
|
||||
a(href="{{ url_for('projects.edit', project_url=project.url) }}")
|
||||
i.pi-list
|
||||
| Overview
|
||||
li(class="{% if title == 'sharing' %}active{% endif %}")
|
||||
a(href="{{ url_for('projects.sharing', project_url=project.url) }}")
|
||||
i.pi-share
|
||||
| Sharing
|
||||
li(class="{% if title == 'edit_node_types' %}active{% endif %}")
|
||||
a(href="{{ url_for('projects.edit_node_types', project_url=project.url) }}")
|
||||
i.pi-puzzle
|
||||
| Node Types
|
||||
|
||||
.project_split(title="Toggle Navigation [T]")
|
||||
|
||||
#project_context-container
|
||||
#project_context-header
|
||||
span#project-statusbar
|
||||
|
||||
span#project-edit-title
|
||||
| Manage users for this project
|
||||
|
||||
#project_context
|
||||
#node-edit-container
|
||||
#node-edit-form
|
||||
.col-md-6
|
||||
| {% if (project.user == current_user.objectid or current_user.has_role('admin')) %}
|
||||
.sharing-users-search
|
||||
.form-group
|
||||
input#user-select.form-control(
|
||||
name='contacts',
|
||||
type='text',
|
||||
placeholder='Add users by name')
|
||||
| {% else %}
|
||||
.sharing-users-search
|
||||
.disabled Only project owners can manage users
|
||||
| {% endif %}
|
||||
|
||||
|
||||
ul.sharing-users-list
|
||||
| {% for user in users %}
|
||||
li.sharing-users-item(
|
||||
user-id="{{ user['_id'] }}",
|
||||
class="{% if current_user.objectid == user['_id'] %}self{% endif %}")
|
||||
.sharing-users-avatar
|
||||
img(src="{{ user['avatar'] }}")
|
||||
.sharing-users-details
|
||||
span.sharing-users-name
|
||||
| {{user['full_name']}}
|
||||
| {% if project.user == user['_id'] and current_user.objectid == user['_id'] %}
|
||||
small (You, owner)
|
||||
| {% elif project.user == user['_id'] %}
|
||||
small (Owner)
|
||||
| {% elif current_user.objectid == user['_id'] %}
|
||||
small (You)
|
||||
| {% endif %}
|
||||
span.sharing-users-extra {{user['username']}}
|
||||
.sharing-users-action
|
||||
| {# Only allow deletion if we are: admin, project owners, or current_user in the team #}
|
||||
| {% if current_user.has_role('admin') or (project.user == current_user.objectid) or (current_user.objectid == user['_id']) %}
|
||||
|
||||
| {% if project.user == user['_id'] %}
|
||||
span
|
||||
i.pi-happy(title="Hi boss!")
|
||||
| {% elif current_user.objectid == user['_id'] %}
|
||||
button.user-remove(title="Leave this project") Leave
|
||||
| {% else %}
|
||||
button.user-remove(title="Remove this user from your project")
|
||||
i.pi-trash
|
||||
| {% endif %}
|
||||
|
||||
| {% endif %}
|
||||
| {% endfor %}
|
||||
|
||||
.col-md-6
|
||||
.sharing-users-info
|
||||
h4 What can team members do?
|
||||
p.
|
||||
Team members are able to upload new content to the
|
||||
project; as well as view, edit, and comment on the content previously created.
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_navigation %}
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_scripts %}
|
||||
script(type="text/javascript").
|
||||
$(window).on("load resize",function(){
|
||||
containerResizeY($(window).height());
|
||||
});
|
||||
| {% if (project.user == current_user.objectid or current_user.has_role('admin')) %}
|
||||
script(src='//cdn.jsdelivr.net/autocomplete.js/0/autocomplete.jquery.min.js')
|
||||
script.
|
||||
$(document).ready(function() {
|
||||
var APPLICATION_ID = '{{config.ALGOLIA_USER}}'
|
||||
var SEARCH_ONLY_API_KEY = '{{config.ALGOLIA_PUBLIC_KEY}}';
|
||||
var INDEX_NAME = '{{config.ALGOLIA_INDEX_USERS}}';
|
||||
var client = algoliasearch(APPLICATION_ID, SEARCH_ONLY_API_KEY);
|
||||
var index = client.initIndex(INDEX_NAME);
|
||||
|
||||
$('#user-select').autocomplete({hint: false}, [
|
||||
{
|
||||
source: function (q, cb) {
|
||||
index.search(q, {hitsPerPage: 5}, function (error, content) {
|
||||
if (error) {
|
||||
cb([]);
|
||||
return;
|
||||
}
|
||||
cb(content.hits, content);
|
||||
});
|
||||
},
|
||||
displayKey: 'full_name',
|
||||
minLength: 2,
|
||||
limit: 10,
|
||||
templates: {
|
||||
suggestion: function (hit) {
|
||||
return hit._highlightResult.full_name.value + ' (' + hit._highlightResult.username.value + ')';
|
||||
}
|
||||
}
|
||||
}
|
||||
]).on('autocomplete:selected', function (event, hit, dataset) {
|
||||
|
||||
var lis = document.getElementsByClassName('sharing-users-item');
|
||||
var has_match = false;
|
||||
|
||||
for (var i = 0; i < lis.length; ++i) {
|
||||
|
||||
// Check if the user already is in the list
|
||||
if ($(lis[i]).attr('user-id') == hit.objectID){
|
||||
|
||||
$(lis[i]).addClass('active');
|
||||
setTimeout(function(){ $('.sharing-users-item').removeClass('active');}, 350);
|
||||
statusBarSet('info', 'User is already part of the project', 'pi-info');
|
||||
|
||||
has_match = false;
|
||||
break;
|
||||
} else {
|
||||
has_match = true;
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
if (has_match){
|
||||
addUser(hit.objectID);
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
function addUser(userId){
|
||||
if (userId && userId.length > 0) {
|
||||
$.post("{{url_for('projects.sharing', project_url=project.url)}}",
|
||||
{user_id: userId, action: 'add'})
|
||||
.done(function (data) {
|
||||
|
||||
$("ul.sharing-users-list").prepend('' +
|
||||
'<li class="sharing-users-item" user-id="' + data._id + '">' +
|
||||
'<div class="sharing-users-avatar">' +
|
||||
'<img src="' + data.avatar + '">'+
|
||||
'</div>' +
|
||||
'<div class="sharing-users-details">' +
|
||||
'<span class="sharing-users-name">' + data.full_name + '</span>' +
|
||||
'<span class="sharing-users-extra">' + data.username + '</span>' +
|
||||
'</div>' +
|
||||
'<div class="sharing-users-action">' +
|
||||
'<button title="Remove this user from your project" class="user-remove">'+
|
||||
'<i class="pi-trash"></i>'+
|
||||
'</button>'+
|
||||
'</div>'+
|
||||
'</li>');
|
||||
|
||||
$("ul.sharing-users-list").find("[user-id='" + userId + "']").addClass('added');
|
||||
setTimeout(function(){ $('.sharing-users-item').removeClass('added');}, 350);
|
||||
statusBarSet('success', 'User added to this project!', 'pi-grin');
|
||||
})
|
||||
.fail(function (jsxhr){
|
||||
data = jsxhr.responseJSON;
|
||||
statusBarSet('error', 'Could not add user (' + data.message + ')', 'pi-warning');
|
||||
});
|
||||
} else {
|
||||
statusBarSet('error', 'Please select a user from the list', 'pi-warning');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
| {% endif %}
|
||||
script.
|
||||
$(document).ready(function() {
|
||||
$('body').on('click', '.user-remove', function(e) {
|
||||
var userId = $(this).parent().parent().attr('user-id');
|
||||
removeUser(userId);
|
||||
});
|
||||
|
||||
function removeUser(userId){
|
||||
$.post("{{url_for('projects.sharing', project_url=project.url)}}",
|
||||
{user_id: userId, action: 'remove'})
|
||||
.done(function (data) {
|
||||
$("ul.sharing-users-list").find("[user-id='" + userId + "']").remove();
|
||||
statusBarSet('success', 'User removed from this project', 'pi-trash');
|
||||
})
|
||||
.fail(function (data){
|
||||
statusBarSet('error', 'Could not remove user (' + data._status + ')', 'pi-warning');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
| {% endblock %}
|
586
src/templates/projects/view.jade
Normal file
586
src/templates/projects/view.jade
Normal file
@@ -0,0 +1,586 @@
|
||||
| {% extends 'layout.html' %}
|
||||
| {% from '_macros/_add_new_menu.html' import add_new_menu %}
|
||||
|
||||
| {% block page_title %}{{project.name}}{% endblock%}
|
||||
|
||||
| {% block og %}
|
||||
meta(property="og:type", content="website")
|
||||
| {% if og_picture %}
|
||||
meta(property="og:image", content="{{ og_picture.thumbnail('l', api=api) }}")
|
||||
| {% endif %}
|
||||
| {% if show_project %}
|
||||
meta(property="og:title", content="{{project.name}} - Blender Cloud")
|
||||
meta(property="og:url", content="{{url_for('projects.view', project_url=project.url, _external=True)}}")
|
||||
meta(property="og:description", content="{{project.summary}}")
|
||||
| {% else %}
|
||||
meta(property="og:title", content="{{node.name}} - Blender Cloud")
|
||||
meta(property="og:url", content="{{url_for('projects.view_node', project_url=project.url, node_id=node._id)}}")
|
||||
meta(property="og:description", content="{{node.description}}")
|
||||
| {% endif %}
|
||||
| {% endblock %}
|
||||
|
||||
| {% block tw %}
|
||||
| {% if og_picture %}
|
||||
meta(property="twitter:image", content="{{ og_picture.thumbnail('l', api=api) }}")
|
||||
| {% endif %}
|
||||
| {% if show_project %}
|
||||
meta(name="twitter:title", content="{{project.name}} on Blender Cloud")
|
||||
meta(name="twitter:description", content="{{project.summary}}")
|
||||
| {% else %}
|
||||
meta(name="twitter:title", content="{{node.name}} on Blender Cloud")
|
||||
meta(name="twitter:description", content="{{node.description}}")
|
||||
| {% endif %}
|
||||
| {% endblock %}
|
||||
|
||||
| {% block head %}
|
||||
link(href="//cdnjs.cloudflare.com/ajax/libs/jstree/3.3.1/themes/default/style.min.css", rel="stylesheet")
|
||||
| {% endblock %}
|
||||
|
||||
| {% block css %}
|
||||
link(href="{{ url_for('static_pillar', filename='assets/css/project-main.css', v=040820161) }}", rel="stylesheet")
|
||||
| {% endblock %}
|
||||
|
||||
| {% block body %}
|
||||
#project-container
|
||||
#project-side-container
|
||||
#project_sidebar
|
||||
ul.project-tabs
|
||||
li.tabs-thumbnail(
|
||||
title="About",
|
||||
data-toggle="tooltip",
|
||||
data-placement="left",
|
||||
class="{% if title == 'about' %}active {% endif %}{% if project.picture_square %}image{% endif %}")
|
||||
a(href="{{url_for('projects.about', project_url=project.url, _external=True)}}")
|
||||
#project-loading
|
||||
i.pi-spin
|
||||
| {% if project.picture_square %}
|
||||
img(src="{{ project.picture_square.thumbnail('b', api=api) }}")
|
||||
| {% else %}
|
||||
i.pi-home
|
||||
| {% endif %}
|
||||
li.tabs-browse(
|
||||
title="Browse",
|
||||
data-toggle="tooltip",
|
||||
data-placement="left",
|
||||
class="{% if title != 'about' %}active{% endif %}")
|
||||
a(href="{{url_for('projects.view', project_url=project.url, _external=True)}}")
|
||||
i.pi-tree-flow
|
||||
| {% if not project.is_private %}
|
||||
li.tabs-search(
|
||||
title="Search",
|
||||
data-toggle="tooltip",
|
||||
data-placement="left")
|
||||
a(href="{{url_for('projects.search', project_url=project.url, _external=True)}}")
|
||||
i.pi-search
|
||||
| {% endif %}
|
||||
|
||||
.project_nav-toggle-btn(
|
||||
title="Expand Navigation [T]",
|
||||
data-toggle="tooltip",
|
||||
data-placement="right")
|
||||
i.pi-angle-double-left
|
||||
|
||||
#project_nav(class="{{ title }}")
|
||||
#project_nav-container
|
||||
| {% if title != 'about' %}
|
||||
#project_nav-header
|
||||
.project-title
|
||||
a(href="{{url_for('projects.view', project_url=project.url, _external=True)}}")
|
||||
| {{ project.name }}
|
||||
|
||||
#project_tree
|
||||
| {% endif %}
|
||||
|
||||
.project_split(title="Toggle Navigation [T]")
|
||||
|
||||
|
||||
#project_context-container
|
||||
| {% if project.has_method('PUT') %}
|
||||
#project_context-header
|
||||
span#project-statusbar
|
||||
|
||||
ul.project-edit-tools.disabled
|
||||
li.button-dropdown
|
||||
a#item_add.dropdown-toggle.project-mode-view(
|
||||
type="button",
|
||||
data-toggle="dropdown",
|
||||
aria-haspopup="true",
|
||||
aria-expanded="false")
|
||||
i.button-add-icon.pi-collection-plus
|
||||
| New...
|
||||
|
||||
ul.dropdown-menu.add_new-menu
|
||||
| {{ add_new_menu(project.node_types) }}
|
||||
|
||||
li.button-edit
|
||||
a#item_edit.project-mode-view(
|
||||
href="javascript:void(0);",
|
||||
title="Edit",
|
||||
data-project_id="{{project._id}}")
|
||||
i.button-edit-icon.pi-edit
|
||||
| Edit Project
|
||||
|
||||
li.button-dropdown
|
||||
a.dropdown-toggle.project-mode-view(
|
||||
type="button",
|
||||
data-toggle="dropdown",
|
||||
aria-haspopup="true",
|
||||
aria-expanded="false")
|
||||
i.pi-more-vertical
|
||||
|
||||
ul.dropdown-menu
|
||||
| {% if current_user.has_role('admin') %}
|
||||
li.button-featured
|
||||
a#item_featured(
|
||||
href="javascript:void(0);",
|
||||
title="Feature on project's homepage",
|
||||
data-toggle="tooltip",
|
||||
data-placement="left")
|
||||
i.button-featured-icon.pi-star
|
||||
| Toggle Featured
|
||||
|
||||
li.button-toggle-public
|
||||
a#item_toggle_public(
|
||||
href="javascript:void(0);",
|
||||
title="Toggle public",
|
||||
data-toggle="tooltip",
|
||||
data-placement="left")
|
||||
i.pi-lock-open
|
||||
| Toggle public
|
||||
| {% endif %}
|
||||
|
||||
li.button-toggle-projheader
|
||||
a#item_toggle_projheader(
|
||||
href="javascript:void(0);",
|
||||
title="Feature as project's header",
|
||||
data-toggle="tooltip",
|
||||
data-placement="left")
|
||||
i.button-featured-icon.pi-star
|
||||
| Toggle Project Header video
|
||||
|
||||
li.button-move
|
||||
a#item_move(
|
||||
href="javascript:void(0);",
|
||||
title="Move into a folder...",
|
||||
data-toggle="tooltip",
|
||||
data-placement="left")
|
||||
i.button-move-icon.pi-move
|
||||
| Move
|
||||
|
||||
li.button-delete
|
||||
a#item_delete(
|
||||
href="javascript:void(0);",
|
||||
title="Delete",
|
||||
data-toggle="tooltip",
|
||||
data-placement="left")
|
||||
i.pi-trash
|
||||
| Delete Project
|
||||
|
||||
// Edit Mode
|
||||
li.button-cancel
|
||||
a#item_cancel.project-mode-edit(
|
||||
href="javascript:void(0);",
|
||||
title="Cancel changes")
|
||||
i.button-cancel-icon.pi-cancel
|
||||
| Cancel
|
||||
|
||||
li.button-save
|
||||
a#item_save.project-mode-edit(
|
||||
href="javascript:void(0);",
|
||||
title="Save changes")
|
||||
i.button-save-icon.pi-check
|
||||
| Save Changes
|
||||
|
||||
| {% endif %}
|
||||
|
||||
#project_context
|
||||
| {% if show_project %}
|
||||
| {% include "projects/view_embed.html" %}
|
||||
| {% endif %}
|
||||
|
||||
#overlay-mode-move-container
|
||||
.overlay-container
|
||||
.title
|
||||
i.pi-angle-left
|
||||
| Select the <strong>folder</strong> where you want to move it
|
||||
.buttons
|
||||
button#item_move_accept.move.disabled
|
||||
| Select a Folder
|
||||
button#item_move_cancel.cancel
|
||||
i.pi-cancel
|
||||
| Cancel
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_navigation %}{% endblock %}
|
||||
| {% block footer %}{% endblock %}
|
||||
|
||||
| {% block footer_scripts %}
|
||||
script(src="//cdnjs.cloudflare.com/ajax/libs/jstree/3.3.1/jstree.min.js")
|
||||
script(src="//releases.flowplayer.org/6.0.5/flowplayer.min.js")
|
||||
|
||||
| {% if project.has_method('PUT') %}
|
||||
| {# JS containing the Edit, Add, Featured, and Move functions #}
|
||||
script(type="text/javascript", src="{{ url_for('static_pillar', filename='assets/js/project-edit.min.js', v=190520161) }}")
|
||||
| {% endif %}
|
||||
|
||||
script.
|
||||
{% if show_project %}
|
||||
ProjectUtils.setProjectAttributes({projectId: "{{project._id}}", isProject: true, nodeId: ''});
|
||||
{% else %}
|
||||
ProjectUtils.setProjectAttributes({projectId: "{{project._id}}", isProject: false, nodeId: '{{node._id}}'});
|
||||
{% endif %}
|
||||
|
||||
var projectTree = document.getElementById('project_tree');
|
||||
|
||||
/* Initialize project_tree scrollbar */
|
||||
if ((typeof Ps !== 'undefined') && projectTree && window.innerWidth > 768){
|
||||
Ps.initialize(projectTree, {suppressScrollX: true});
|
||||
}
|
||||
|
||||
var urlNodeMove = "{{url_for('projects.move_node')}}";
|
||||
var urlNodeFeature = "{{url_for('projects.add_featured_node')}}";
|
||||
var urlNodeDelete = "{{url_for('projects.delete_node')}}";
|
||||
var urlNodeTogglePublic = "{{url_for('projects.toggle_node_public')}}";
|
||||
var urlNodeToggleProjHeader = "{{url_for('projects.toggle_node_project_header')}}";
|
||||
var urlProjectDelete = "{{url_for('projects.delete')}}";
|
||||
var urlProjectEdit = "{{url_for('projects.edit', project_url=project.url)}}";
|
||||
|
||||
function updateToggleProjHeaderMenuItem() {
|
||||
var $toggle_projheader = $('#item_toggle_projheader');
|
||||
|
||||
if (ProjectUtils.isProject()) {
|
||||
$toggle_projheader.hide();
|
||||
return;
|
||||
}
|
||||
if (ProjectUtils.nodeType() == 'asset') {
|
||||
$toggle_projheader.show();
|
||||
} else {
|
||||
$toggle_projheader.hide();
|
||||
}
|
||||
}
|
||||
$(updateToggleProjHeaderMenuItem);
|
||||
|
||||
// Function to update the interface on loadNodeContent, and edit/saving assets
|
||||
function updateUi(nodeId, mode){
|
||||
|
||||
if (mode === 'view') {
|
||||
$('.project-mode-view').show();
|
||||
$('.project-mode-edit').hide();
|
||||
|
||||
$("#node-edit-form").unbind( "submit" );
|
||||
$("#item_save").unbind( "click" );
|
||||
$("#item_cancel").unbind( "click" );
|
||||
} else if (mode === 'edit') {
|
||||
$('.project-mode-view').hide();
|
||||
$('.project-mode-edit').show();
|
||||
} else {
|
||||
if (console) console.log('Invalid mode:', mode);
|
||||
}
|
||||
|
||||
// Prevent flicker by scrolling to top
|
||||
$("#project_context-container").scrollTop(0);
|
||||
|
||||
// Enable specific items under the Add New dropdown
|
||||
if (ProjectUtils.nodeType() === 'group') {
|
||||
addMenuEnable(['asset', 'group']);
|
||||
|
||||
} else if (ProjectUtils.nodeType() === 'group_texture') {
|
||||
addMenuEnable(['group_texture', 'texture']);
|
||||
|
||||
} else if (ProjectUtils.nodeType() === 'group_hdri') {
|
||||
addMenuEnable(['group_hdri', 'hdri']);
|
||||
|
||||
} else if (!ProjectUtils.isProject()) {
|
||||
addMenuEnable(false);
|
||||
}
|
||||
|
||||
updateToggleProjHeaderMenuItem();
|
||||
|
||||
var nodeTitle = document.getElementById('node-title');
|
||||
var nodeTitleText = $(nodeTitle).text() + " - {{project.name}} - Blender Cloud";
|
||||
|
||||
document.title = nodeTitleText;
|
||||
|
||||
// TODO: Maybe remove this, now it's also in loadNodeContent(), but double-check
|
||||
// it's done like that in all users of updateUi().
|
||||
$('#project-loading').removeAttr('class');
|
||||
}
|
||||
|
||||
|
||||
function loadNodeContent(url, nodeId) {
|
||||
$('#project-loading').addClass('active');
|
||||
|
||||
$.get(url, function(dataHtml) {
|
||||
// Update the DOM injecting the generate HTML into the page
|
||||
$('#project_context').html(dataHtml);
|
||||
})
|
||||
.done(function(){
|
||||
updateUi(nodeId, 'view');
|
||||
})
|
||||
.fail(function(dataResponse) {
|
||||
$('#project_context').html($('<iframe id="server_error"/>'));
|
||||
$('#server_error').attr('src', url);
|
||||
})
|
||||
.always(function(){
|
||||
$('#project-loading').removeAttr('class');
|
||||
$('.button-edit-icon').addClass('pi-edit').removeClass('pi-spin spin');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function loadProjectContent(url) {
|
||||
$('#project-loading').addClass('active');
|
||||
|
||||
$.get(url, function(dataHtml) {
|
||||
// Update the DOM injecting the generated HTML into the page
|
||||
$('#project_context').html(dataHtml);
|
||||
})
|
||||
.done(function() {
|
||||
updateUi('', 'view');
|
||||
addMenuEnable();
|
||||
addMenuDisable(['texture']);
|
||||
})
|
||||
.fail(function(dataResponse) {
|
||||
$('#project_context').html($('<iframe id="server_error"/>'));
|
||||
$('#server_error').attr('src', url);
|
||||
})
|
||||
.always(function(){
|
||||
$('#project-loading').removeAttr('class');
|
||||
$('.button-edit-icon').addClass('pi-edit').removeClass('pi-spin spin');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function displayStorage(storageNodeId, path) {
|
||||
var url = '/nodes/' + storageNodeId + '/view?path=' + path;
|
||||
loadNodeContent(url);
|
||||
}
|
||||
|
||||
|
||||
function displayNode(nodeId, pushState) {
|
||||
// Remove the 'n_' suffix from the id
|
||||
if (nodeId.substring(0, 2) == 'n_') {
|
||||
nodeId = nodeId.substr(2);
|
||||
}
|
||||
var url = '/nodes/' + nodeId + '/view';
|
||||
loadNodeContent(url, nodeId);
|
||||
|
||||
// Determine whether we should push the new state or not.
|
||||
pushState = (typeof pushState !== 'undefined') ? pushState : true;
|
||||
if (!pushState) return;
|
||||
|
||||
// Push the correct URL onto the history.
|
||||
var push_state = {nodeId: nodeId, url: url};
|
||||
var push_url = '{{url_for("projects.view", project_url=project.url)}}' + nodeId;
|
||||
// console.log('Pushing state ', push_state, ' with URL ', push_url);
|
||||
window.history.pushState(
|
||||
push_state,
|
||||
'Node ' + nodeId, // TODO: use sensible title
|
||||
push_url
|
||||
);
|
||||
}
|
||||
|
||||
function redirectToNode(nodeId) {
|
||||
var generic_url = '{{ url_for("projects.view_node", project_url=project.url, node_id="theNodeId") }}';
|
||||
var node_url = generic_url.replace('theNodeId', nodeId);
|
||||
|
||||
// This makes the user skip the current page when using the 'back' button,
|
||||
// i.e. it works as a proper redirect.
|
||||
location.replace(node_url);
|
||||
}
|
||||
|
||||
window.onpopstate = function(event) {
|
||||
var state = event.state;
|
||||
// console.log('State popped. location:', document.location, 'state:', state);
|
||||
|
||||
// Deselect any selected node. We'll select the visited node (if any) later on.
|
||||
var jstreeAPI = $(projectTree).jstree(true);
|
||||
jstreeAPI.deselect_all(true);
|
||||
|
||||
if (state == null) {
|
||||
// Went back to the project.
|
||||
displayProject();
|
||||
return;
|
||||
}
|
||||
|
||||
// Went back to a node.
|
||||
loadNodeContent(state.url, state.nodeId);
|
||||
|
||||
// Annoying hack because jstreeAPI.select_node() can only suppress the
|
||||
// changed.jstree event, and NOT the selected_node.jstree event.
|
||||
projectTree.dataset.ignoreSelectNode = true;
|
||||
jstreeAPI.select_node('n_' + state.nodeId, true);
|
||||
delete projectTree.dataset.ignoreSelectNode;
|
||||
};
|
||||
|
||||
function displayProject() {
|
||||
var url = "{{url_for('projects.view', project_url=project.url, embed=1)}}";
|
||||
loadProjectContent(url);
|
||||
}
|
||||
|
||||
|
||||
function getHashId() {
|
||||
if (console)
|
||||
console.log('getHashId() should not be used any more!');
|
||||
}
|
||||
|
||||
/* Loaded once, on page load */
|
||||
function loadContent() {
|
||||
|
||||
var nodeId = ProjectUtils.nodeId();
|
||||
var isProject = ProjectUtils.isProject();
|
||||
if (isProject) {
|
||||
// No need to asynchronously load the project, as it's embedded by Jinja.
|
||||
// displayProject() is still needed, though, when people use 'back' to go there.
|
||||
if (location.hash) {
|
||||
// Handle old-style /p/{url}/#node-ID links, and redirect them to the correct spot.
|
||||
redirectToNode(location.hash.substr(1));
|
||||
}
|
||||
$('.project-mode-view').show();
|
||||
$('.project-mode-edit').hide();
|
||||
} else {
|
||||
displayNode(nodeId, false);
|
||||
}
|
||||
|
||||
$(projectTree).jstree({
|
||||
'core': {
|
||||
'data': function (obj, callback) {
|
||||
if(obj.id === '#') { //tree root
|
||||
if (isProject) {
|
||||
$.getJSON("{{url_for('projects.jstree', project_url=project.url)}}", function (jsonObject) {
|
||||
callback.call(this, jsonObject['items']);
|
||||
});
|
||||
} else {
|
||||
$.getJSON('/nodes/' + nodeId + '/jstree', function(jsonObject) {
|
||||
callback.call(this, jsonObject['items']);
|
||||
});
|
||||
}
|
||||
} else { //normal node
|
||||
var childNodeId;
|
||||
if (obj.original.type == 'group_storage') {
|
||||
childNodeId = obj.original.storage_node;
|
||||
$.getJSON('/nodes/' + childNodeId + '/jstree?children=1&path=' + obj.original.path, function(jsonObject) {
|
||||
callback.call(this, jsonObject.children);
|
||||
});
|
||||
} else {
|
||||
// Remove the 'n_' suffix from the id
|
||||
childNodeId = obj.id.substring(2);
|
||||
$.getJSON('/nodes/' + childNodeId + '/jstree?children=1', function(jsonObject) {
|
||||
callback.call(this, jsonObject.children);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"types" : {
|
||||
"#": {"valid_children": ["collection"]},
|
||||
"chapter" : {"icon": "pi-folder"},
|
||||
"group" : {"icon": "pi-folder"},
|
||||
"group_texture" : {"icon": "pi-folder-texture"},
|
||||
"group_hdri" : {"icon": "pi-folder-texture", "max_children": 0},
|
||||
"group_storage" : {"icon": "pi-folder"},
|
||||
"filesystem_node" : {"icon": "pi-folder"},
|
||||
"file" : {"icon": "pi-file-archive", "max_children": 0},
|
||||
"filesystem_file" : {"icon": "pi-document", "max_children": 0},
|
||||
"image" : {"icon": "pi-image", "max_children": 0},
|
||||
"hdri" : {"icon": "pi-globe", "max_children": 0},
|
||||
"texture" : {"icon": "pi-texture", "max_children": 0},
|
||||
"video" : {"icon": "pi-film-thick", "max_children": 0},
|
||||
"blog" : {"icon": "pi-newspaper", "max_children": 0},
|
||||
"default" : {"icon": "pi-document"}
|
||||
},
|
||||
"plugins": ["types",] //, "state", "sort"
|
||||
});
|
||||
|
||||
|
||||
var jstreeAPI = $(projectTree).jstree(true);
|
||||
|
||||
$(projectTree).on("select_node.jstree", function (e, data) {
|
||||
var selectedNodeId = data.node.id.substr(2);
|
||||
|
||||
// Ignore events that can't be suppressed otherwise.
|
||||
// This can be removed if jstreeAPI.select_node() allows suppressing
|
||||
// the select_node.jstree event.
|
||||
if (e.target.dataset.ignoreSelectNode === 'true') return;
|
||||
|
||||
if (typeof(data.node.original.path) === 'undefined') {
|
||||
var movingMode = Cookies.getJSON('bcloud_moving_node');
|
||||
|
||||
// Check if we are in the process of moving a node
|
||||
if (movingMode) {
|
||||
// Allow moving nodes only inside of node_type group
|
||||
if (data.node.original.type != 'group' || movingMode.node_id === selectedNodeId || movingMode.node_id === ProjectUtils.parentNodeId()) {
|
||||
|
||||
if (movingMode.node_type === 'texture') {
|
||||
|
||||
if (data.node.original.type === 'group_texture') {
|
||||
$('#item_move_accept').html('<i class="pi-check"></i>Move Here').removeClass('disabled');
|
||||
} else {
|
||||
$('#item_move_accept').html('Select a Texture Folder').addClass('disabled');
|
||||
}
|
||||
|
||||
} else if (movingMode.node_type === 'hdri') {
|
||||
|
||||
if (data.node.original.type === 'group_hdri') {
|
||||
$('#item_move_accept').html('<i class="pi-check"></i>Move Here').removeClass('disabled');
|
||||
} else {
|
||||
$('#item_move_accept').html('Select an HDRi Folder').addClass('disabled');
|
||||
}
|
||||
|
||||
} else {
|
||||
$('#item_move_accept').html('Select a Folder').addClass('disabled');
|
||||
}
|
||||
|
||||
} else {
|
||||
$('#item_move_accept').html('<i class="pi-check"></i>Move Here').removeClass('disabled');
|
||||
}
|
||||
}
|
||||
|
||||
// Check the type of node and act accordingly
|
||||
if (data.node.original.type == 'blog') {
|
||||
window.location.replace('blog');
|
||||
} else {
|
||||
var currentNodeId = ProjectUtils.nodeId();
|
||||
if (currentNodeId != selectedNodeId) {
|
||||
displayNode(selectedNodeId);
|
||||
}
|
||||
|
||||
jstreeAPI.open_node(data.node);
|
||||
}
|
||||
} else {
|
||||
displayStorage(data.node.original.storage_node, data.node.original.path);
|
||||
jstreeAPI.toggle_node(data.node);
|
||||
}
|
||||
|
||||
/* Update scrollbar */
|
||||
Ps.update(projectTree);
|
||||
});
|
||||
|
||||
$(projectTree).on("open_node.jstree", function () {
|
||||
/* Update scrollbar */
|
||||
Ps.update(projectTree);
|
||||
});
|
||||
$(projectTree).on("close_node.jstree", function () {
|
||||
/* Update scrollbar */
|
||||
Ps.update(projectTree);
|
||||
});
|
||||
};
|
||||
|
||||
// Initialize the page
|
||||
loadContent();
|
||||
|
||||
/* UI Stuff */
|
||||
$(window).on("load resize",function(){
|
||||
containerResizeY($(window).height());
|
||||
});
|
||||
|
||||
if (projectTree){
|
||||
$(projectTree).hover(function(){
|
||||
Ps.update(projectTree);
|
||||
});
|
||||
}
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
| {% block comment_scripts %} {% endblock%}
|
188
src/templates/projects/view_embed.jade
Normal file
188
src/templates/projects/view_embed.jade
Normal file
@@ -0,0 +1,188 @@
|
||||
| {% block head %}
|
||||
| {% if header_video_file %}
|
||||
script(src="//releases.flowplayer.org/6.0.5/flowplayer.min.js")
|
||||
script.
|
||||
$(function() {
|
||||
$('#flowplayer_container').flowplayer({
|
||||
key: "{{config.FLOWPLAYER_KEY}}",
|
||||
embed: false,
|
||||
splash: true,
|
||||
clip: { sources: [
|
||||
{% for var in header_video_file.variations %}
|
||||
{type: "{{ var.content_type }}", src: "{{ var.link|safe }}"},
|
||||
{% endfor %}
|
||||
]}
|
||||
});
|
||||
});
|
||||
| {% endif %}
|
||||
| {% endblock %}
|
||||
|
||||
| {% block body %}
|
||||
|
||||
#node-container
|
||||
section.node-preview.project
|
||||
| {% if project.url == 'caminandes-3' %}
|
||||
iframe(
|
||||
style="height: 490px",
|
||||
src="https://www.youtube.com/embed/SkVqJ1SGeL0?rel=0&controls=0&showinfo=0",
|
||||
frameborder="0",
|
||||
allowfullscreen)
|
||||
| {% elif header_video_file %}
|
||||
#flowplayer_container.is-splash.play-button(
|
||||
style="{% if header_video_node.picture %}background-image:url({{header_video_node.picture.thumbnail('l', api=api)}}); background-repeat:no-repeat; {% endif %}")
|
||||
.fp-startscreen.fp-toggle
|
||||
a.big-play-button
|
||||
i.pi-play
|
||||
.fp-endscreen
|
||||
a.watch-again.fp-toggle
|
||||
i.pi-replay
|
||||
| Watch again
|
||||
.fp-waiting
|
||||
i.pi-spin.spin
|
||||
| {% elif project.picture_header %}
|
||||
a(href="{{ url_for( 'projects.about', project_url=project.url) }}")
|
||||
img.header(src="{{ project.picture_header.thumbnail('l', api=api) }}")
|
||||
| {% endif %}
|
||||
|
||||
section.node-details-container.project
|
||||
|
||||
| {# Hide for now
|
||||
.node-details-header
|
||||
.node-title-details
|
||||
.date(title="Last updated {{ project._updated | pretty_date }}") {{ project._created | pretty_date }}
|
||||
|
||||
| {% if project.status %}
|
||||
.status {{project.status}}
|
||||
| {% endif %}
|
||||
| #}
|
||||
|
||||
.node-details-title
|
||||
h1
|
||||
a(href="{{ url_for( 'projects.about', project_url=project.url) }}") {{ project.name }}
|
||||
|
||||
| {% if title != 'about' or not project.description %}
|
||||
| {% set description = project.summary %}
|
||||
| {% else %}
|
||||
| {% set description = project.description %}
|
||||
| {% endif %}
|
||||
|
||||
.node-details-description
|
||||
| {{ description }}
|
||||
|
||||
| {% if title != 'about' %}
|
||||
.node-extra
|
||||
a.learn-more(href="{{ url_for( 'projects.about', project_url=project.url) }}") LEARN MORE
|
||||
| {% endif %}
|
||||
|
||||
| {% if project.nodes_featured %}
|
||||
.project-featured-container
|
||||
h3 Featured Content
|
||||
.featured-list#featured-list
|
||||
| {% for n in project.nodes_featured %}
|
||||
| {% if n.picture %}
|
||||
a.featured-item.hidden(href="{{ url_for_node(node=n) }}")
|
||||
.featured-item-info
|
||||
span.type {{ n.properties.content_type }} - {{ n.user.full_name }}
|
||||
span.title {{ n.name }}
|
||||
img(src="{{ n.picture.thumbnail('l', api=api) }}")
|
||||
| {% endif %}
|
||||
| {% endfor %}
|
||||
| {% endif %}
|
||||
|
||||
.node-extra
|
||||
| {% if project.nodes_blog %}
|
||||
.node-blog
|
||||
h3 Blog
|
||||
ul.node-blog-list
|
||||
| {% for n in project.nodes_blog %}
|
||||
li.node-blog-list-item(data-node_id="{{ n._id }}")
|
||||
a.image(href="{{ url_for_node(node=n) }}")
|
||||
| {% if n.picture %}
|
||||
img(src="{{ n.picture.thumbnail('s', api=api) }}")
|
||||
| {% else %}
|
||||
i.pi-chatbubble-working
|
||||
| {% endif %}
|
||||
.info
|
||||
a.title(href="{{ url_for_node(node=n) }}") {{ n.name }}
|
||||
span.details
|
||||
span.when {{ n._updated | pretty_date }} by
|
||||
span.who {{ n.user.full_name }}
|
||||
| {% endfor %}
|
||||
| {% endif %}
|
||||
|
||||
| {% if project.nodes_latest %}
|
||||
.node-updates
|
||||
h3 Latest Updates
|
||||
ul.node-updates-list
|
||||
| {% for n in project.nodes_latest %}
|
||||
| {% if n.node_type not in ['comment'] %}
|
||||
li.node-updates-list-item(data-node_id="{{ n._id }}")
|
||||
a.image(href="{{ url_for_node(node=n) }}")
|
||||
| {% if n.picture %}
|
||||
img(src="{{ n.picture.thumbnail('s', api=api) }}")
|
||||
| {% else %}
|
||||
| {% if n.properties.content_type == 'video' %}
|
||||
i.pi-film-thick
|
||||
| {% elif n.properties.content_type == 'image' %}
|
||||
i.pi-picture
|
||||
| {% elif n.properties.content_type == 'file' %}
|
||||
i.pi-file-archive
|
||||
| {% else %}
|
||||
i.pi-folder
|
||||
| {% endif %}
|
||||
| {% endif %}
|
||||
.info
|
||||
a.title(href="{{ url_for_node(node=n) }}") {{ n.name }}
|
||||
span.details
|
||||
span.what {% if n.properties.content_type %}{{ n.properties.content_type }}{% else %}folder{% endif %} ·
|
||||
span.when {{ n._updated | pretty_date }} by
|
||||
span.who {{ n.user.full_name }}
|
||||
| {% endif %}
|
||||
| {% endfor %}
|
||||
| {% endif %}
|
||||
|
||||
|
||||
include _scripts
|
||||
|
||||
script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.montage.min.js') }}")
|
||||
script.
|
||||
function montage(){
|
||||
var $container = $('#featured-list'),
|
||||
$imgs = $container.find('img').hide(),
|
||||
totalImgs = $imgs.length,
|
||||
cnt = 0;
|
||||
|
||||
$imgs.each(function(i) {
|
||||
var $img = $(this);
|
||||
$('<img/>').load(function() {
|
||||
++cnt;
|
||||
if( cnt === totalImgs ) {
|
||||
$imgs.show();
|
||||
$container.montage({
|
||||
fillLastRow : true,
|
||||
alternateHeight : true,
|
||||
alternateHeightRange : {
|
||||
min : 180,
|
||||
max : 240
|
||||
},
|
||||
margin : 3
|
||||
});
|
||||
}
|
||||
}).attr('src',$img.attr('src'));
|
||||
$img.parent().removeClass('hidden');
|
||||
});
|
||||
}
|
||||
|
||||
$(function() {
|
||||
montage();
|
||||
|
||||
$(".node-updates-list-item, .node-blog-list-item")
|
||||
.unbind('click')
|
||||
.click(function(e) {
|
||||
e.preventDefault();
|
||||
displayNode($(this).data('node_id'));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
| {% endblock %}
|
57
src/templates/projects/view_theatre.jade
Normal file
57
src/templates/projects/view_theatre.jade
Normal file
@@ -0,0 +1,57 @@
|
||||
| {% extends 'layout.html' %}
|
||||
|
||||
| {% set title = 'theatre' %}
|
||||
|
||||
| {% block og %}
|
||||
meta(property="og:title", content="{{ node.name }}")
|
||||
meta(property="og:url", content="{{ url_for('projects.view_node', project_url=project.url, node_id=node._id, t=1, _external=True) }}")
|
||||
meta(property="og:type", content="website")
|
||||
meta(property="og:description", content="Created on {{ node._created.strftime('%d %b %Y') }}")
|
||||
| {% if og_picture %}
|
||||
meta(property="og:image", content="{{ og_picture.thumbnail('l', api=api) }}")
|
||||
meta(property="og:image:secure_url", content="{{ og_picture.thumbnail('l', api=api) }}")
|
||||
meta(property="og:image:type", content="{{ og_picture.content_type }}")
|
||||
meta(property="og:image:witdh", content="{{ og_picture.width }}")
|
||||
meta(property="og:image:height", content="{{ og_picture.height }}")
|
||||
| {% endif %}
|
||||
| {% endblock %}
|
||||
|
||||
| {% block tw %}
|
||||
| {% if og_picture %}
|
||||
meta(property="twitter:image", content="{{ og_picture.thumbnail('l', api=api) }}")
|
||||
| {% endif %}
|
||||
meta(name="twitter:title", content="{{node.name}}")
|
||||
meta(name="twitter:description", content="Created on {{ node._created.strftime('%d %b %Y') }}")
|
||||
| {% endblock %}
|
||||
|
||||
| {% block header_backdrop %}{% endblock %}
|
||||
| {% block navigation_search %}{% endblock %}
|
||||
| {% block navigation_sections %}
|
||||
li
|
||||
a.navbar-item.info(
|
||||
href="",
|
||||
title="Toggle info & sidebar")
|
||||
i.pi-info
|
||||
| {% endblock %}
|
||||
|
||||
| {% block css %}
|
||||
link(href="{{ url_for('static_pillar', filename='assets/css/theatre.css', v=2016) }}", rel="stylesheet")
|
||||
| {% endblock %}
|
||||
|
||||
| {% block body %}
|
||||
#theatre-container(class="{% if current_user.is_authenticated %}with-info{% endif %}")
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_scripts %}
|
||||
script.
|
||||
|
||||
$(function(){
|
||||
$.get("{{url_for('nodes.view', node_id=node._id, t=True)}}", function(dataHtml) {
|
||||
$("#theatre-container").html(dataHtml);
|
||||
});
|
||||
});
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer %}{% endblock %}
|
||||
| {% block footer_navigation %}{% endblock %}
|
Reference in New Issue
Block a user