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:
27
src/templates/_macros/_add_new_menu.jade
Normal file
27
src/templates/_macros/_add_new_menu.jade
Normal file
@@ -0,0 +1,27 @@
|
||||
| {% macro add_new_menu(node_types) %}
|
||||
|
||||
| {% for node_type in node_types %}
|
||||
| {% if node_type['name'] in ['group', 'group_texture', 'group_hdri', 'asset', 'texture', 'page', 'hdri'] %}
|
||||
| {% set node_type_name = node_type['name'] %}
|
||||
| {% if node_type_name == 'group' %}
|
||||
| {% set node_type_name = 'folder' %}
|
||||
| {% endif %}
|
||||
li(class="button-{{ node_type['name'] }}")
|
||||
a.item_add_node(
|
||||
href="#",
|
||||
title="{{ node_type['description'] }}",
|
||||
data-node-type-name="{{ node_type['name'] }}",
|
||||
data-toggle="tooltip",
|
||||
data-placement="left")
|
||||
i.pi(class="icon-{{ node_type['name'] }}")
|
||||
| {% if node_type_name == 'group_texture' %}
|
||||
| Texture Folder
|
||||
| {% elif node_type_name == 'group_hdri' %}
|
||||
| HDRi Folder
|
||||
| {% else %}
|
||||
| {{ node_type_name }}
|
||||
| {% endif %}
|
||||
| {% endif %}
|
||||
| {% endfor %}
|
||||
|
||||
| {% endmacro %}
|
18
src/templates/_macros/_file_uploader.jade
Normal file
18
src/templates/_macros/_file_uploader.jade
Normal file
@@ -0,0 +1,18 @@
|
||||
| {% macro render_file_uploader() %}
|
||||
|
||||
#fileUploaderModal.modal.fade(
|
||||
tabindex="-1", role="dialog", aria-labelledby="fileUploaderModalLabel", aria-hidden="true")
|
||||
.modal-dialog
|
||||
.modal-content
|
||||
.modal-header
|
||||
button.close(type="button", data-dismiss="modal", aria-label="Close")
|
||||
span(aria-hidden="true") ×
|
||||
h4.modal-title Upload file
|
||||
|
||||
.modal-body
|
||||
| {% include '_macros/include _file_uploader_form.html' %}
|
||||
|
||||
.modal-footer
|
||||
button.btn.btn-default(type="button", data-dismiss="modal") Close
|
||||
|
||||
| {% endmacro %}
|
70
src/templates/_macros/_file_uploader_form.jade
Normal file
70
src/templates/_macros/_file_uploader_form.jade
Normal file
@@ -0,0 +1,70 @@
|
||||
|
||||
#node-add-container
|
||||
#node-add-header
|
||||
.node-add-title Upload Assets
|
||||
|
||||
#node-add-form
|
||||
p.
|
||||
This is the first step in the asset creation process. Once files are uploaded,
|
||||
they are stored in a temp location until further actions are taken.
|
||||
You can upload multiple assets simultaneously, but you can only edit one at a time.
|
||||
|
||||
hr
|
||||
|
||||
// The file upload form used as target for the file upload widget
|
||||
form#fileupload(action="{{url_for('files.upload')}}", method='POST', enctype='multipart/form-data')
|
||||
|
||||
// Redirect browsers with JavaScript disabled to the origin page
|
||||
noscript
|
||||
input(type='hidden', name='redirect', value="{{url_for('files.upload')}}")
|
||||
|
||||
// The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload
|
||||
.row.fileupload-buttonbar
|
||||
.col-lg-7
|
||||
|
||||
// The fileinput-button span is used to style the file input field as button
|
||||
span.btn.btn-success.fileinput-button
|
||||
i.pi-plus
|
||||
span Add files...
|
||||
input(type='file', name='file', multiple='')
|
||||
|
||||
button.btn.btn-primary.start(type='submit')
|
||||
i.pi-upload
|
||||
span Start upload
|
||||
|
||||
button.btn.btn-warning.cancel(type='reset')
|
||||
i.pi-cancel
|
||||
span Cancel upload
|
||||
|
||||
button.btn.btn-danger.delete(type='button')
|
||||
i.pi-trash
|
||||
span Delete
|
||||
|
||||
input.toggle(type='checkbox')
|
||||
// The global file processing state
|
||||
span.fileupload-process
|
||||
// The global progress state
|
||||
.col-lg-5.fileupload-progress.fade
|
||||
// The global progress bar
|
||||
.progress.progress-striped.active(role='progressbar', aria-valuemin='0', aria-valuemax='100')
|
||||
.progress-bar.progress-bar-success(style='width:0%;')
|
||||
// The extended global progress state
|
||||
.progress-extended
|
||||
// The table listing the files available for upload/download
|
||||
table.table(role='presentation')
|
||||
tbody.files
|
||||
br
|
||||
|
||||
h3 Notes
|
||||
ul
|
||||
li
|
||||
| The maximum file size for this interface is
|
||||
strong {{ config.MAX_CONTENT_LENGTH | filesizeformat }}
|
||||
| .
|
||||
li
|
||||
| Only the following formats are allowed:
|
||||
br
|
||||
strong.text-uppercase
|
||||
| {% for f in config.ALLOWED_EXTENSIONS %}
|
||||
| {{f}}
|
||||
| {% endfor %}
|
133
src/templates/_macros/_file_uploader_javascript.jade
Normal file
133
src/templates/_macros/_file_uploader_javascript.jade
Normal file
@@ -0,0 +1,133 @@
|
||||
| {% raw %}
|
||||
|
||||
// The template to display files available for upload
|
||||
script#template-upload(type="text/x-tmpl").
|
||||
| {% for (var i=0, file; file=o.files[i]; i++) { %}
|
||||
<tr class="template-upload fade">
|
||||
<td>
|
||||
<span class="preview"></span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="name">{%=file.name%}</span>
|
||||
<strong class="error text-danger"></strong>
|
||||
</td>
|
||||
<td>
|
||||
<p class="size">Processing...</p>
|
||||
<div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><div class="progress-bar progress-bar-success" style="width:0%;"></div></div>
|
||||
</td>
|
||||
<td>
|
||||
{% if (!i && !o.options.autoUpload) { %}
|
||||
<button class="btn btn-primary start" disabled>
|
||||
<i class="ion-upload"></i>
|
||||
<span>Start</span>
|
||||
</button>
|
||||
{% } %}
|
||||
{% if (!i) { %}
|
||||
<button class="btn btn-warning cancel">
|
||||
<i class="ion-close-round"></i>
|
||||
<span>Cancel</span>
|
||||
</button>
|
||||
{% } %}
|
||||
</td>
|
||||
</tr>
|
||||
| {% } %}
|
||||
|
||||
|
||||
// The template to display files available for download
|
||||
script#template-download(type="text/x-tmpl").
|
||||
| {% for (var i=0, file; file=o.files[i]; i++) { %}
|
||||
<tr class="template-download fade">
|
||||
<td>
|
||||
<span class="preview">
|
||||
{% if (file.thumbnailUrl) { %}
|
||||
<a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" data-gallery><img src="{%=file.thumbnailUrl%}"></a>
|
||||
{% } %}
|
||||
</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="name">
|
||||
{% if (file.url) { %}
|
||||
<a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" {%=file.thumbnailUrl?'data-gallery':''%}>{%=file.name%}</a>
|
||||
{% } else { %}
|
||||
<span>{%=file.name%}</span>
|
||||
{% } %}
|
||||
</span>
|
||||
{% if (file.error) { %}
|
||||
<div><span class="label label-danger">Error</span> {%=file.error%}</div>
|
||||
{% } %}
|
||||
</td>
|
||||
<td>
|
||||
<span class="size">{%=o.formatFileSize(file.size)%}</span>
|
||||
</td>
|
||||
<td>
|
||||
{% if (file.deleteUrl) { %}
|
||||
<button class="btn btn-danger delete" data-type="{%=file.deleteType%}" data-url="{%=file.deleteUrl%}"{% if (file.deleteWithCredentials) { %} data-xhr-fields='{"withCredentials":true}'{% } %}>
|
||||
<i class="ion-trash-b"></i>
|
||||
<span>Delete</span>
|
||||
</button>
|
||||
<input type="checkbox" name="delete" value="1" class="toggle">
|
||||
<div class="btn btn-success create" data-name="{%=file.name%}" data-type="{%=file.type%}">
|
||||
<i class="ion-upload"></i>
|
||||
Create
|
||||
</div>
|
||||
{% } else { %}
|
||||
<button class="btn btn-warning cancel">
|
||||
<i class="ion-close-round"></i>
|
||||
<span>Cancel</span>
|
||||
</button>
|
||||
{% } %}
|
||||
</td>
|
||||
</tr>
|
||||
| {% } %}
|
||||
|
||||
| {% endraw %}
|
||||
|
||||
script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.iframe-transport.min.js') }}")
|
||||
script(src="{{ url_for('static_pillar', filename='javascript-templates/js/tmpl.min.js') }}")
|
||||
script(src="{{ url_for('static_pillar', filename='javascript-load-image/js/load-image.all.min.js') }}")
|
||||
script(src="{{ url_for('static_pillar', filename='javascript-canvas-to-blob/js/canvas-to-blob.min.js') }}")
|
||||
script(src="{{ url_for('static_pillar', filename='gallery/js/jquery.blueimp-gallery.min.js') }}")
|
||||
script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.iframe-transport.min.js') }}")
|
||||
script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.fileupload.min.js') }}")
|
||||
script(src="{{ url_for('static_pillar', filename='jquery-file-upload/js/jquery.fileupload-process.js') }}")
|
||||
script(src="{{ url_for('static_pillar', filename='jquery-file-upload/js/jquery.fileupload-image.js') }}")
|
||||
script(src="{{ url_for('static_pillar', filename='jquery-file-upload/js/jquery.fileupload-audio.js') }}")
|
||||
script(src="{{ url_for('static_pillar', filename='jquery-file-upload/js/jquery.fileupload-video.js') }}")
|
||||
script(src="{{ url_for('static_pillar', filename='jquery-file-upload/js/jquery.fileupload-validate.js') }}")
|
||||
script(src="{{ url_for('static_pillar', filename='jquery-file-upload/js/jquery.fileupload-ui.js') }}")
|
||||
script(src="{{ url_for('static_pillar', filename='jquery-file-upload/js/main.js') }}")
|
||||
|
||||
script().
|
||||
$('body').unbind('click');
|
||||
$('body').on('click', '.create', function(event) {
|
||||
// Start the asset creation process
|
||||
event.preventDefault();
|
||||
var parent_id = ProjectUtils.nodeId();
|
||||
$('#node-add-form').text('Please wait...');
|
||||
$.post('{{url_for('nodes.assets_create')}}', {
|
||||
name: $(this).attr('data-name'),
|
||||
project_id: ProjectUtils.projectId(),
|
||||
type: $(this).attr('data-type'),
|
||||
parent_id: parent_id})
|
||||
.done(function(data) {
|
||||
if (parent_id) {
|
||||
// We are in embedded mode and try to call the editNode function
|
||||
editNode(data.asset_id);
|
||||
} else {
|
||||
window.location.replace("/nodes/" + data.asset_id + "/edit");
|
||||
}
|
||||
//alert( "Data Loaded: " + data.message );
|
||||
});
|
||||
});
|
||||
|
||||
// Temporary list of CSS to style the upload form
|
||||
var cssLinks = ['/static/assets/css/blueimp/blueimp-gallery.min.css',
|
||||
'/static/jquery-file-upload/css/jquery.fileupload.css',
|
||||
'/static/jquery-file-upload/css/jquery.fileupload-ui.css']
|
||||
|
||||
$.each(cssLinks, function(index, value) {
|
||||
// Check if the CSS is needed
|
||||
if (!$("link[href='" + value + "']").length) {
|
||||
$('<link href="' + value + '" rel="stylesheet">').appendTo("head");
|
||||
}
|
||||
});
|
15
src/templates/_macros/_navigation.jade
Normal file
15
src/templates/_macros/_navigation.jade
Normal file
@@ -0,0 +1,15 @@
|
||||
| {% macro navigation_tabs(title) %}
|
||||
|
||||
section#nav-tabs
|
||||
ul#nav-tabs__list
|
||||
li.nav-tabs__list-tab(
|
||||
class="{% if title == 'homepage' %}active{% endif %}")
|
||||
a(href="{{ url_for('main.homepage') }}") Activity
|
||||
li.nav-tabs__list-tab(
|
||||
class="{% if title == 'dashboard' %}active{% endif %}")
|
||||
a(href="{{ url_for('projects.index') }}") My Projects
|
||||
li.nav-tabs__list-tab(
|
||||
class="{% if title == 'home' %}active{% endif %}")
|
||||
a(href="{{ url_for('projects.home_project') }}") Home
|
||||
|
||||
| {% endmacro %}
|
34
src/templates/_macros/_node_edit_form.jade
Normal file
34
src/templates/_macros/_node_edit_form.jade
Normal file
@@ -0,0 +1,34 @@
|
||||
| {% macro render_field(field) %}
|
||||
|
||||
.form-group(class="{{field.name}}{% if field.errors %} error{% endif %}")
|
||||
|
||||
| {% if field.type == 'BooleanField' %}
|
||||
.checkbox
|
||||
label
|
||||
| {{ field(class='checkbox') }}
|
||||
| {{ field.label }}
|
||||
| {% elif field.type == 'FieldList' %}
|
||||
|
||||
ul.fieldlist#files
|
||||
| {% for file in field %}
|
||||
li.fieldlist-item
|
||||
|
||||
| {% for subfield in file %}
|
||||
| {{ render_field(subfield) }}
|
||||
| {% endfor %}
|
||||
|
||||
| {% endfor %}
|
||||
|
||||
| {% else %}
|
||||
| {{ field.label }}
|
||||
| {{ field(class='form-control') }}
|
||||
| {% endif %}
|
||||
|
||||
| {% if field.errors %}
|
||||
ul.error
|
||||
| {% for error in field.errors %}
|
||||
li {{ error }}
|
||||
| {% endfor %}
|
||||
| {% endif %}
|
||||
|
||||
| {% endmacro %}
|
13
src/templates/_modal.jade
Normal file
13
src/templates/_modal.jade
Normal file
@@ -0,0 +1,13 @@
|
||||
// Modal
|
||||
#modal-default.modal.fade(tabindex='-1', role='dialog', aria-labelledby='modal-default-label')
|
||||
.modal-dialog(role='document')
|
||||
.modal-content
|
||||
.modal-header
|
||||
button.close(type='button', data-dismiss='modal', aria-label='Close')
|
||||
span(aria-hidden='true') ×
|
||||
h4#modal-default-label.modal-title Modal title
|
||||
.modal-body
|
||||
| ...
|
||||
.modal-footer
|
||||
button.btn.btn-default(type='button', data-dismiss='modal') Close
|
||||
button.btn.btn-primary(type='button') Save changes
|
4
src/templates/_notifications.jade
Normal file
4
src/templates/_notifications.jade
Normal file
@@ -0,0 +1,4 @@
|
||||
ul#notifications-list
|
||||
li.nc-item
|
||||
#notifications-loader
|
||||
i.pi-spin.spin
|
4
src/templates/errors/403.jade
Normal file
4
src/templates/errors/403.jade
Normal file
@@ -0,0 +1,4 @@
|
||||
| {% extends "errors/layout.html" %}
|
||||
| {% block body %}
|
||||
| {% include "errors/403_embed.html" %}
|
||||
| {% endblock %}
|
25
src/templates/errors/403_embed.jade
Normal file
25
src/templates/errors/403_embed.jade
Normal file
@@ -0,0 +1,25 @@
|
||||
#error_container.403
|
||||
#error_box
|
||||
.error-top-container
|
||||
.error-title Sorry to bother you, but...
|
||||
|
||||
.error-lead.
|
||||
This content is only available to Cloud subscribers.<br/>
|
||||
Get full access to the Blender Cloud for only $9.90 per month.
|
||||
|
||||
.buttons
|
||||
a.sign-up.btn.btn-outline(href="https://store.blender.org/product/membership/")
|
||||
i.pi-check
|
||||
| Subscribe Now
|
||||
|
||||
| {% if not current_user.is_authenticated %}
|
||||
a.sign-in.btn.btn-empty(href="{{ url_for('users.login') }}")
|
||||
i.pi-log-in
|
||||
| Log in
|
||||
| {% endif %}
|
||||
|
||||
hr
|
||||
|
||||
.error-lead.extra.
|
||||
If you have just subscribed, please <a href="{{ url_for('users.logout') }}">log out</a> and in again.<br/>
|
||||
For any other issue get in touch with <a href="mailto:cloudsupport@blender.org">cloudsupport@blender.org</a>
|
17
src/templates/errors/404.jade
Normal file
17
src/templates/errors/404.jade
Normal file
@@ -0,0 +1,17 @@
|
||||
| {% extends "errors/layout.html" %}
|
||||
| {% block body %}
|
||||
#error_container.404.standalone
|
||||
#error_box
|
||||
.error-top-container
|
||||
.error-title Not found.
|
||||
.error-lead
|
||||
p.
|
||||
The error has been logged and we're working on getting it fixed.
|
||||
hr
|
||||
p.
|
||||
Looking for the Open Movies? Check out <a href="https://www.youtube.com/BlenderFoundation">Blender Foundation's YouTube</a> channel. <br/> Were you looking for tutorials instead? <a href="http://www.blender.org/support/tutorials/">blender.org</a> has a good selection.
|
||||
|
||||
|
||||
.error-lead.extra.
|
||||
We'll be back soon, in the meantime follow <a href="https://twitter.com/Blender_Cloud">@Blender_Cloud</a> for updates.
|
||||
| {% endblock %}
|
12
src/templates/errors/404_embed.jade
Normal file
12
src/templates/errors/404_embed.jade
Normal file
@@ -0,0 +1,12 @@
|
||||
#error_container.404
|
||||
#error_box
|
||||
.error-title 404. Not Found.
|
||||
|
||||
.error-lead.
|
||||
Whatever you're looking for, it's not here.
|
||||
|
||||
hr
|
||||
|
||||
.error-lead.extra.
|
||||
Is this content missing? Let us know on <a href="https://twitter.com/Blender_Cloud">Twitter</a>
|
||||
or email <a href="mailto:cloudsupport@blender.org">cloudsupport@blender.org</a>
|
42
src/templates/errors/500.jade
Normal file
42
src/templates/errors/500.jade
Normal file
@@ -0,0 +1,42 @@
|
||||
doctype
|
||||
html(lang="en")
|
||||
head
|
||||
meta(charset="utf-8")
|
||||
title Blender Cloud
|
||||
meta(name="viewport", content="width=device-width, initial-scale=1.0")
|
||||
meta(name="description", content="Blender Cloud is a web based service developed by Blender Institute that allows people to access the training videos and all the data from the past open projects.")
|
||||
meta(name="author", content="Blender Institute")
|
||||
meta(name="theme-color", content="#3e92aa")
|
||||
|
||||
script.
|
||||
!function(e){"use strict";e.loadCSS=function(t,n,o){var r,i=e.document,l=i.createElement("link");if(n)r=n;else{var d=(i.body||i.getElementsByTagName("head")[0]).childNodes;r=d[d.length-1]}var a=i.styleSheets;l.rel="stylesheet",l.href=t,l.media="only x",r.parentNode.insertBefore(l,n?r:r.nextSibling);var f=function(e){for(var t=l.href,n=a.length;n--;)if(a[n].href===t)return e();setTimeout(function(){f(e)})};return l.onloadcssdefined=f,f(function(){l.media=o||"all"}),l},"undefined"!=typeof module&&(module.exports=e.loadCSS)}(this);
|
||||
|
||||
loadCSS( "//fonts.googleapis.com/css?family=Roboto:300,400,500" );
|
||||
loadCSS( "//fonts.googleapis.com/css?family=Lato:300,400" );
|
||||
|
||||
link(href="{{ url_for('static_pillar', filename='assets/ico/favicon.png') }}", rel="shortcut icon")
|
||||
link(href="{{ url_for('static_pillar', filename='assets/ico/apple-touch-icon-precomposed.png') }}", rel="icon apple-touch-icon-precomposed", sizes="192x192")
|
||||
|
||||
link(href="{{ url_for('static_pillar', filename='assets/css/main.css') }}", rel="stylesheet")
|
||||
|
||||
body.error
|
||||
|
||||
#error_container.500.standalone
|
||||
#error_box
|
||||
.error-top-container
|
||||
.error-title Something went wrong.
|
||||
.error-lead
|
||||
p.
|
||||
The error has been logged and we're working on getting it fixed.
|
||||
hr
|
||||
p.
|
||||
Looking for the Open Movies? Check out <a href="https://www.youtube.com/BlenderFoundation">Blender Foundation's YouTube</a> channel. <br/> Were you looking for tutorials instead? <a href="http://www.blender.org/support/tutorials/">blender.org</a> has a good selection.
|
||||
|
||||
|
||||
.error-lead.extra.
|
||||
We'll be back soon, in the meantime follow <a href="https://twitter.com/Blender_Cloud">@Blender_Cloud</a> for updates.
|
||||
|
||||
|
||||
noscript
|
||||
link(href='//fonts.googleapis.com/css?family=Roboto:300,400,500', rel='stylesheet', type='text/css')
|
||||
link(href='//fonts.googleapis.com/css?family=Lato:300,400', rel='stylesheet', type='text/css')
|
27
src/templates/errors/layout.jade
Normal file
27
src/templates/errors/layout.jade
Normal file
@@ -0,0 +1,27 @@
|
||||
doctype
|
||||
html(lang="en")
|
||||
head
|
||||
meta(charset="utf-8")
|
||||
title Blender Cloud
|
||||
meta(name="viewport", content="width=device-width, initial-scale=1.0")
|
||||
meta(name="description", content="Blender Cloud is a web based service developed by Blender Institute that allows people to access the training videos and all the data from the past open projects.")
|
||||
meta(name="author", content="Blender Institute")
|
||||
meta(name="theme-color", content="#3e92aa")
|
||||
|
||||
script.
|
||||
!function(e){"use strict";e.loadCSS=function(t,n,o){var r,i=e.document,l=i.createElement("link");if(n)r=n;else{var d=(i.body||i.getElementsByTagName("head")[0]).childNodes;r=d[d.length-1]}var a=i.styleSheets;l.rel="stylesheet",l.href=t,l.media="only x",r.parentNode.insertBefore(l,n?r:r.nextSibling);var f=function(e){for(var t=l.href,n=a.length;n--;)if(a[n].href===t)return e();setTimeout(function(){f(e)})};return l.onloadcssdefined=f,f(function(){l.media=o||"all"}),l},"undefined"!=typeof module&&(module.exports=e.loadCSS)}(this);
|
||||
|
||||
loadCSS( "//fonts.googleapis.com/css?family=Roboto:300,400,500" );
|
||||
loadCSS( "//fonts.googleapis.com/css?family=Lato:300,400" );
|
||||
|
||||
link(href="{{ url_for('static_pillar', filename='assets/ico/favicon.png') }}", rel="shortcut icon")
|
||||
link(href="{{ url_for('static_pillar', filename='assets/ico/apple-touch-icon-precomposed.png') }}", rel="icon apple-touch-icon-precomposed", sizes="192x192")
|
||||
|
||||
link(href="{{ url_for('static_pillar', filename='assets/css/main.css') }}", rel="stylesheet")
|
||||
|
||||
body.error
|
||||
| {% block body %}{% endblock %}
|
||||
|
||||
noscript
|
||||
link(href='//fonts.googleapis.com/css?family=Roboto:300,400,500', rel='stylesheet', type='text/css')
|
||||
link(href='//fonts.googleapis.com/css?family=Lato:300,400', rel='stylesheet', type='text/css')
|
378
src/templates/homepage.jade
Normal file
378
src/templates/homepage.jade
Normal file
@@ -0,0 +1,378 @@
|
||||
| {% extends 'layout.html' %}
|
||||
| {% from '_macros/_navigation.html' import navigation_tabs %}
|
||||
|
||||
| {% set title = 'homepage' %}
|
||||
|
||||
| {% block og %}
|
||||
meta(property="og:title", content="Blender Cloud")
|
||||
meta(property="og:url", content="https://cloud.blender.org/")
|
||||
meta(property="og:image", content="{% if main_project.picture_header %}{{ main_project.picture_header.thumbnail('l', api=api) }}{% else %}{{ url_for('static', filename='assets/img/backgrounds/background_caminandes_3_02.jpg')}}{% endif %}")
|
||||
| {% endblock %}
|
||||
|
||||
| {% block tw %}
|
||||
meta(name="twitter:title", content="Blender Cloud")
|
||||
meta(name="twitter:description", content="Blender Cloud is a web based service developed by Blender Institute that allows people to access the training videos and all the data from the open projects.")
|
||||
meta(name="twitter:image", content="{% if main_project.picture_header %}{{ main_project.picture_header.thumbnail('l', api=api) }}{% else %}{{ url_for('static', filename='assets/img/backgrounds/background_caminandes_3_02.jpg')}}{% endif %}")
|
||||
| {% endblock %}
|
||||
|
||||
| {% block body %}
|
||||
.dashboard-container
|
||||
section#main
|
||||
| {{ navigation_tabs(title) }}
|
||||
|
||||
section#stream
|
||||
|
||||
h3#activity-stream__title
|
||||
| Activity Stream
|
||||
|
||||
ul#activity-stream__filters
|
||||
li Filter
|
||||
li.filter.active(
|
||||
data-filter='image',
|
||||
title="List images")
|
||||
i.pi-picture
|
||||
li.filter.active(
|
||||
data-filter='video',
|
||||
title="List videos")
|
||||
i.pi-film-thick
|
||||
li.filter.active(
|
||||
data-filter='file',
|
||||
title="List files")
|
||||
i.pi-file-archive
|
||||
li.filter.active(
|
||||
data-filter='post',
|
||||
title="List blog posts")
|
||||
i.pi-newspaper
|
||||
li.filter(
|
||||
data-filter='comment',
|
||||
title="List comments")
|
||||
i.pi-comment
|
||||
|
||||
ul#activity-stream__list
|
||||
| {% for n in activity_stream %}
|
||||
| {% if n.node_type == 'comment' %}
|
||||
li.activity-stream__list-item.hidden(
|
||||
class="{{ n.node_type }}",
|
||||
data-url="{{ url_for_node(node=n) }}")
|
||||
a.activity-stream__list-thumbnail(href="{{ url_for_node(node=n) }}")
|
||||
i.pi-comment
|
||||
.activity-stream__list-details
|
||||
a.title(href="{{ url_for_node(node=n) }}") {{ n.properties.content }}
|
||||
ul.meta
|
||||
li.who {{ n.user.full_name }}
|
||||
li.where-project
|
||||
a.project(href="{{ url_for('projects.view', project_url=n.project.url) }}") {{ n.project.name }}
|
||||
li.where-parent
|
||||
a(href="{{ url_for_node(node_id=n.attached_to._id) }}") {{ n.attached_to.name }}
|
||||
li.when
|
||||
a(href="{{ url_for_node(node=n) }}", title="{{ n._created }}") {{ n._created | pretty_date_time }}
|
||||
| {% elif n.node_type == 'asset' %}
|
||||
li.activity-stream__list-item(
|
||||
class="{{ n.node_type }} {{ n.properties.content_type }}",
|
||||
data-url="{{ url_for_node(node=n) }}")
|
||||
a.activity-stream__list-thumbnail(
|
||||
class="{{ n.properties.content_type }}",
|
||||
href="{{ url_for_node(node=n) }}")
|
||||
| {% 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 %}
|
||||
|
||||
.activity-stream__list-details
|
||||
| {% if n.picture %}
|
||||
a.image(href="{{ url_for_node(node=n) }}")
|
||||
| {% if n.properties.content_type == 'video' %}
|
||||
i.pi-play
|
||||
| {% endif %}
|
||||
img(src="{{ n.picture.thumbnail('l', api=api) }}")
|
||||
| {% endif %}
|
||||
a.date(href="{{ url_for_node(node=n) }}", title="{{ n._created }}") {{ n._created | pretty_date_time }}
|
||||
a.title(href="{{ url_for_node(node=n) }}")
|
||||
| {{ n.name }}
|
||||
| {% if n.permissions.world %}
|
||||
.ribbon
|
||||
span free
|
||||
| {% endif %}
|
||||
ul.meta
|
||||
li.what {{ n.properties.content_type }}
|
||||
li.who {{ n.user.full_name }}
|
||||
li.where-project
|
||||
a.project(href="{{ url_for('projects.view', project_url=n.project.url) }}") {{ n.project.name }}
|
||||
| {% elif n.node_type == 'post' %}
|
||||
li.activity-stream__list-item(
|
||||
class="{{ n.node_type }}",
|
||||
data-url="{{ url_for_node(node=n) }}")
|
||||
a.activity-stream__list-thumbnail(href="{{ url_for_node(node=n) }}")
|
||||
i.pi-newspaper
|
||||
.activity-stream__list-details
|
||||
| {% if n.picture %}
|
||||
a.image(href="{{ url_for_node(node=n) }}")
|
||||
img(src="{{ n.picture.thumbnail('l', api=api) }}")
|
||||
| {% endif %}
|
||||
a.date(href="{{ url_for_node(node=n) }}", title="{{ n._created }}") {{ n._created | pretty_date_time }}
|
||||
a.title(href="{{ url_for_node(node=n) }}") {{ n.name }}
|
||||
ul.meta
|
||||
li.what Blog Post
|
||||
li.where-project
|
||||
a.project(href="{{ url_for('projects.view', project_url=n.project.url) }}")
|
||||
| {{ n.project.name }}
|
||||
| {% endif %}
|
||||
| {% endfor %}
|
||||
li.activity-stream__list-item.empty#activity-stream__empty
|
||||
| No items to list.
|
||||
|
||||
|
||||
section#side
|
||||
section#announcement
|
||||
| {% if main_project.picture_header %}
|
||||
a(href="https://cloud.blender.org/blog/introducing-blender-sync")
|
||||
img.header(
|
||||
src="{{ main_project.picture_header.thumbnail('l', api=api) }}")
|
||||
| {% endif %}
|
||||
.text
|
||||
.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.
|
||||
|
||||
.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="https://cloud.blender.org/blog/introducing-blender-sync")
|
||||
| Learn More
|
||||
|
||||
|
||||
section#random-asset
|
||||
h3
|
||||
a(href="/search") Explore the Cloud
|
||||
span.section-lead Random selection of the best assets & tutorials
|
||||
|
||||
ul.random-asset__list
|
||||
| {% for n in random_featured %}
|
||||
| {% if n.picture and loop.first %}
|
||||
li.random-asset__list-item.featured
|
||||
| {% if n.permissions.world %}
|
||||
.ribbon
|
||||
span free
|
||||
| {% endif %}
|
||||
a.random-asset__thumbnail(
|
||||
href="{{ url_for_node(node=n) }}",
|
||||
class="{{ n.properties.content_type }}")
|
||||
| {% if n.picture %}
|
||||
img(src="{{ n.picture.thumbnail('l', api=api) }}")
|
||||
|
||||
| {% if n.properties.content_type == 'video' %}
|
||||
i.pi-play
|
||||
| {% endif %}
|
||||
|
||||
| {% endif %}
|
||||
|
||||
a.title(href="{{ url_for_node(node=n) }}")
|
||||
| {{ n.name }}
|
||||
ul.meta
|
||||
li.what
|
||||
a(href="{{ url_for_node(node=n) }}")
|
||||
| {% if n.properties.content_type %}{{ n.properties.content_type }}{% else %}Folder{% endif %}
|
||||
li.where
|
||||
a(href="{{ url_for('projects.view', project_url=n.project.url) }}")
|
||||
| {{ n.project.name }}
|
||||
| {% else %}
|
||||
|
||||
li.random-asset__list-item
|
||||
| {% if n.permissions.world %}
|
||||
.ribbon
|
||||
span free
|
||||
| {% endif %}
|
||||
a.random-asset__list-thumbnail(
|
||||
href="{{ url_for_node(node=n) }}",
|
||||
class="{{ n.properties.content_type }}")
|
||||
| {% if n.picture %}
|
||||
img.image(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 %}
|
||||
.random-asset__list-details
|
||||
a.title(href="{{ url_for_node(node=n) }}") {{ n.name }}
|
||||
ul.meta
|
||||
li.what
|
||||
a(href="{{ url_for_node(node=n) }}")
|
||||
| {% if n.properties.content_type %}{{ n.properties.content_type }}{% else %}Folder{% endif %}
|
||||
li.where
|
||||
a(href="{{ url_for('projects.view', project_url=n.project.url) }}") {{ n.project.name }}
|
||||
|
||||
| {% endif %}
|
||||
| {% endfor %}
|
||||
|
||||
section#blog-stream
|
||||
a.feed(
|
||||
href="{{ url_for('main.feeds_blogs') }}",
|
||||
title="Blender Cloud & Projects Blog Feed",
|
||||
data-toggle="tooltip",
|
||||
data-placement="left")
|
||||
i.pi-rss
|
||||
|
||||
h3
|
||||
a(href="{{ url_for('main.main_blog') }}") Blog
|
||||
|
||||
ul#blog-stream__list
|
||||
| {% if latest_posts %}
|
||||
| {% for n in latest_posts %}
|
||||
| {% if n.picture and loop.first %}
|
||||
li.blog-stream__list-item.featured
|
||||
a.blog-stream__thumbnail(
|
||||
href="{{ url_for_node(node=n) }}")
|
||||
img(src="{{ n.picture.thumbnail('l', api=api) }}")
|
||||
a.title(href="{{ url_for_node(node=n) }}")
|
||||
| {{ n.name }}
|
||||
|
||||
ul.meta
|
||||
li.when
|
||||
a(href="{{ url_for_node(node=n) }}",
|
||||
title="Updated {{ n._updated | pretty_date }}")
|
||||
| {{ n._created | pretty_date }}
|
||||
li.where-project
|
||||
a.project(href="{{ url_for('projects.view', project_url=n.project.url) }}") {{ n.project.name }}
|
||||
| {% else %}
|
||||
li.blog-stream__list-item
|
||||
a.blog-stream__list-thumbnail(href="{{ url_for_node(node=n) }}")
|
||||
| {% if n.picture %}
|
||||
img.image(src="{{ n.picture.thumbnail('s', api=api) }}")
|
||||
| {% else %}
|
||||
i.pi-newspaper
|
||||
| {% endif %}
|
||||
.blog-stream__list-details
|
||||
a.title(href="{{ url_for_node(node=n) }}") {{ n.name }}
|
||||
ul.meta
|
||||
li.when
|
||||
a(href="{{ url_for_node(node=n) }}",
|
||||
title="Updated {{ n._updated | pretty_date }}")
|
||||
| {{ n._created | pretty_date }}
|
||||
li.where-project
|
||||
a.project(href="{{ url_for('projects.view', project_url=n.project.url) }}") {{ n.project.name }}
|
||||
| {% endif %}
|
||||
| {% endfor %}
|
||||
| {% else %}
|
||||
li.blog-stream__list-item
|
||||
.blog-stream__list-details
|
||||
ul.meta
|
||||
li.when No updates yet
|
||||
| {% endif %}
|
||||
li.blog-stream__list-item.more
|
||||
a(href="{{ url_for('main.main_blog') }}") See All Blog Posts
|
||||
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_scripts %}
|
||||
script.
|
||||
$(function () {
|
||||
|
||||
/* cleanup mentions in comments */
|
||||
$('.activity-stream__list-details a.title').each(function(){
|
||||
$(this).text($(this).text().replace(/\*|\@|\<(.*?)\>/g, ''));
|
||||
});
|
||||
|
||||
function saveFilters(){
|
||||
var filtersEnabled = [];
|
||||
|
||||
$('ul#activity-stream__filters li.filter.active').each(function(){
|
||||
filtersEnabled.push($(this).attr('data-filter'));
|
||||
});
|
||||
|
||||
setJSONCookie('bcloud_ui', 'homepage_activity_filters', filtersEnabled);
|
||||
}
|
||||
|
||||
function loadFilters(){
|
||||
|
||||
var filters = Cookies.getJSON('bcloud_ui');
|
||||
|
||||
if (filters) {
|
||||
if (filters.homepage_activity_filters && filters.homepage_activity_filters.length){
|
||||
/* Clear style on filters/items */
|
||||
$('ul#activity-stream__filters li.filter').removeClass('active');
|
||||
$('ul#activity-stream__list li.activity-stream__list-item').addClass('hidden');
|
||||
|
||||
for (var f in filters.homepage_activity_filters){
|
||||
|
||||
var savedFilter = filters.homepage_activity_filters[f];
|
||||
|
||||
/* Style each filter type */
|
||||
$('ul#activity-stream__filters li.filter').each(function(){
|
||||
if ($(this).attr('data-filter') == savedFilter){
|
||||
$(this).addClass('active');
|
||||
}
|
||||
});
|
||||
|
||||
/* Show items that are on the cookie */
|
||||
$('ul#activity-stream__list li.activity-stream__list-item').each(function(){
|
||||
if ($(this).hasClass(savedFilter)) {
|
||||
$(this).removeClass('hidden');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Toggle filters */
|
||||
$('ul#activity-stream__filters li.filter').click(function(){
|
||||
|
||||
// Style the filter button
|
||||
$(this).toggleClass('active');
|
||||
|
||||
var filterType = $(this).attr('data-filter');
|
||||
|
||||
saveFilters();
|
||||
|
||||
// Toggle hidden class on list item if it has class matching the filter
|
||||
$('ul#activity-stream__list li.activity-stream__list-item').each(function(){
|
||||
if ($(this).hasClass(filterType)) {
|
||||
$(this).toggleClass('hidden');
|
||||
}
|
||||
});
|
||||
|
||||
var hiddenItems = $('ul#activity-stream__list li.activity-stream__list-item.hidden').length;
|
||||
|
||||
if (hiddenItems == '{{ activity_stream|length }}'){
|
||||
$('#activity-stream__empty').show();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
loadFilters();
|
||||
|
||||
/* Click on the whole asset/comment row to go */
|
||||
$('li.activity-stream__list-item.asset, li.activity-stream__list-item.comment').click(function(e){
|
||||
|
||||
window.location.href = $(this).data('url');
|
||||
|
||||
$(this).addClass('active');
|
||||
$(this).find('.activity-stream__list-thumbnail i')
|
||||
.removeAttr('class')
|
||||
.addClass('pi-spin spin');
|
||||
});
|
||||
|
||||
hopToTop(); // Display jump to top button
|
||||
});
|
||||
| {% endblock %}
|
537
src/templates/join.jade
Normal file
537
src/templates/join.jade
Normal file
@@ -0,0 +1,537 @@
|
||||
| {% extends 'layout.html' %}
|
||||
| {% block page_title %}Welcome{% endblock %}
|
||||
|
||||
| {% set title = 'join' %}
|
||||
|
||||
| {% block og %}
|
||||
meta(property="og:title", content="Join the Blender Cloud")
|
||||
meta(property="og:url", content="https://cloud.blender.org/")
|
||||
meta(property="og:image", content="{{ url_for('static', filename='assets/img/backgrounds/background_services.jpg')}}")
|
||||
| {% endblock %}
|
||||
|
||||
| {% block header_backdrop %}
|
||||
.navbar-backdrop.join(
|
||||
style="background-image: url({{ url_for('static', filename='assets/img/backgrounds/background_andy_hdribot_01.jpg')}})")
|
||||
| {% endblock %}
|
||||
|
||||
| {% block page_overlay %}
|
||||
#page-overlay.video
|
||||
.video-embed
|
||||
| {% endblock %}
|
||||
|
||||
| {% block body %}
|
||||
#page-container.join
|
||||
#page-header
|
||||
.page-title-icons
|
||||
i.pi-blender
|
||||
i.pi-heart-filled
|
||||
i.pi-blender-cloud
|
||||
.page-title
|
||||
| Your Own Production Platform
|
||||
//- .page-title-summary
|
||||
//- | Get inspiration, knowledge, and tools all in one place.
|
||||
|
||||
.page-header-cta-container
|
||||
a.page-header-cta(href="https://store.blender.org/product/membership/")
|
||||
| Join Now
|
||||
|
||||
a.page-header-cta-extra(href="{{ url_for('main.nodes_search_index') }}")
|
||||
| Explore
|
||||
i.pi-angle-right
|
||||
|
||||
|
||||
#page-content
|
||||
.page-triplet-container.homepage
|
||||
.row
|
||||
.col-md-4
|
||||
.triplet-card(data-url="{{ url_for('main.open_projects') }}")
|
||||
.triplet-card-thumbnail
|
||||
img(
|
||||
alt="Open Projects",
|
||||
src="{{ url_for('static', filename='assets/img/features/open_movies_02.jpg')}}")
|
||||
.triplet-card-info
|
||||
h3 Open Projects
|
||||
p.
|
||||
The iconic Blender Institute Open Movies,
|
||||
featuring all the production files, assets, artwork, and never-seen-before content.
|
||||
span.triplet-cta
|
||||
| LEARN MORE
|
||||
|
||||
.col-md-4
|
||||
.triplet-card(data-url="{{ url_for('main.training') }}")
|
||||
.triplet-card-thumbnail
|
||||
img(
|
||||
alt="Training and Tutorials",
|
||||
src="{{ url_for('static', filename='assets/img/features/training_02.jpg')}}")
|
||||
.triplet-card-info
|
||||
h3 Training & Tutorials
|
||||
p.
|
||||
Character modeling, 3D printing, VFX, rigging and more. We offer
|
||||
12 complete training series with +100 hours of training.
|
||||
span.triplet-cta
|
||||
| LEARN MORE
|
||||
|
||||
.col-md-4
|
||||
.triplet-card(data-url="{{ url_for('main.services') }}")
|
||||
.triplet-card-thumbnail
|
||||
img(
|
||||
alt="Services and Tools",
|
||||
src="{{ url_for('static', filename='assets/img/features/services_01.jpg')}}")
|
||||
.triplet-card-info
|
||||
h3 Services
|
||||
p.
|
||||
Crate your personal projects, collaborate with other members, store
|
||||
and sync your Blender settings across multiple workstations.
|
||||
span.triplet-cta
|
||||
| LEARN MORE
|
||||
|
||||
|
||||
section.page-card-header
|
||||
h2 Download 1000s of files and assets
|
||||
|
||||
|
||||
.page-triplet-container.homepage
|
||||
.row
|
||||
.col-md-4
|
||||
.triplet-card(data-url="{{ url_for('main.redir_hdri') }}")
|
||||
.triplet-card-thumbnail
|
||||
img(
|
||||
alt="HDRI",
|
||||
src="{{ url_for('static', filename='assets/img/features/hdri_01.jpg')}}")
|
||||
.triplet-card-info
|
||||
h3 HDRI
|
||||
p.
|
||||
Up to 8K and 18 EVs (extremely high) HDR images to light your renders.
|
||||
span.triplet-cta
|
||||
| LEARN MORE
|
||||
|
||||
.col-md-4
|
||||
.triplet-card(data-url="{{ url_for('main.redir_textures') }}")
|
||||
.triplet-card-thumbnail
|
||||
img(
|
||||
alt="Textures",
|
||||
src="{{ url_for('static', filename='assets/img/features/textures_01.jpg')}}")
|
||||
.triplet-card-info
|
||||
h3 Textures
|
||||
p.
|
||||
More than 1500 texture maps.
|
||||
Browse online or from Blender with our awesome add-on.
|
||||
span.triplet-cta
|
||||
| LEARN MORE
|
||||
|
||||
.col-md-4
|
||||
.triplet-card(data-url="{{ url_for('main.redir_characters') }}")
|
||||
.triplet-card-thumbnail
|
||||
img(
|
||||
alt="Characters",
|
||||
src="{{ url_for('static', filename='assets/img/features/characters_01.jpg')}}")
|
||||
.triplet-card-info
|
||||
h3 Characters
|
||||
p.
|
||||
Production quality, fully rigged and shaded characters ready to animate.
|
||||
span.triplet-cta
|
||||
| LEARN MORE
|
||||
|
||||
|
||||
section.page-card-header
|
||||
h2 Learn by Example
|
||||
|
||||
|
||||
section.page-card.services-projects
|
||||
|
||||
.page-card-side
|
||||
h2.page-card-title Exclusive Production Insights
|
||||
.page-card-summary
|
||||
p.
|
||||
Watch the original authors of shots breaking it down into a detailed
|
||||
explanation and share their insight in the production process. Watch
|
||||
animation reviews, narrated timelapses, shot walk-throughs.
|
||||
|
||||
.page-card-side
|
||||
.page-card-image
|
||||
img(
|
||||
alt="Exclusive Production Insights",
|
||||
src="{{ url_for('static', filename='assets/img/features/animation_review_01.gif')}}")
|
||||
|
||||
|
||||
section.page-card.right.services-projects
|
||||
|
||||
.page-card-side
|
||||
h2.page-card-title Production Quality Files
|
||||
.page-card-summary
|
||||
p.
|
||||
From fully rigged characters ready to animate to an Art Gallery
|
||||
curated by the best Blender artists, access top quality blendfiles to learn
|
||||
new techniques and improve your art.
|
||||
|
||||
.page-card-side
|
||||
.page-card-image
|
||||
img(
|
||||
alt="High Quality Assets",
|
||||
src="{{ url_for('static', filename='assets/img/features/locomotive_01.jpg')}}")
|
||||
|
||||
|
||||
#blender-addon.page-section-container(
|
||||
style="background-image: url({{ url_for('static', filename='assets/img/backgrounds/pattern_bw_01.jpg')}})")
|
||||
section.page-card-header.dark Blender Cloud Add-on
|
||||
span.page-card-header_lead.dark Connect Blender with the Cloud
|
||||
|
||||
a.page-card-cta.download(
|
||||
href="https://cloud.blender.org/r/downloads/blender_cloud-latest-bundle.zip")
|
||||
i.pi-download
|
||||
| Download <small>v</small>{{ config.BLENDER_CLOUD_ADDON_VERSION }}
|
||||
|
||||
section.page-card.dark.right
|
||||
|
||||
.page-card-side
|
||||
h2.page-card-title Blender Sync
|
||||
.page-card-summary.
|
||||
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/>
|
||||
<small>Syncing settings is free for everyone! No subscription required.</small>
|
||||
|
||||
a.page-card-cta(
|
||||
href="https://cloud.blender.org/blog/introducing-blender-sync")
|
||||
| Learn More
|
||||
|
||||
.page-card-side
|
||||
.page-card-icon
|
||||
svg(xmlns="http://www.w3.org/2000/svg",
|
||||
width="64", height="54", viewBox="0 0 64 54")
|
||||
g(fill="none", stroke="#aaa", stroke-width="2", stroke-miterlimit="10")
|
||||
path(d="M29 47H5l-4-4v-2h24l2 2h2M29 3H10C8.344 3 7 4.343 7 6v32M35 51h24l4-4v-2H39l-2 2h-2M35 7h19c1.656 0 3 1.343 3 3v32M32 34v20M32 20v8M32 0v14")
|
||||
g
|
||||
path(d="M32 31c-3.866 0-7-3.134-7-7M32 17c3.866 0 7 3.134 7 7M32 31h8M24 17h8M36 35l4-4-4-4M28 21l-4-4 4-4")
|
||||
path(d="M29 37H11V7h18M35 11h18v30H35")
|
||||
|
||||
|
||||
section.page-card.dark
|
||||
|
||||
.page-card-side
|
||||
h2.page-card-title Texture Browser
|
||||
.page-card-summary
|
||||
p.
|
||||
Access the <a href="https://cloud.blender.org/p/textures/">Blender Cloud Textures and HDRI</a>
|
||||
libraries from within Blender.
|
||||
Create, manage and share <em>your own</em> texture libraries!
|
||||
|
||||
a.page-card-cta.watch-video(
|
||||
href="https://www.youtube.com/watch?v=-srXYv2Osjw",
|
||||
data-youtube-id="-srXYv2Osjw")
|
||||
i.pi-play
|
||||
| Watch Video
|
||||
|
||||
.page-card-side
|
||||
.page-card-icon
|
||||
svg(xmlns="http://www.w3.org/2000/svg",
|
||||
width="64", height="60",
|
||||
viewBox="0 0 64 60")
|
||||
g(fill="#aaa")
|
||||
path(d="M32 60c-.188 0-.377-.053-.542-.16l-31-20C.173 39.656 0 39.34 0 39s.173-.656.458-.84l31-20c.33-.213.754-.213 1.084 0l31 20c.285.184.458.5.458.84s-.173.656-.458.84l-31 20c-.165.107-.354.16-.542.16zM2.845 39L32 57.81 61.155 39 32 20.19 2.845 39z")
|
||||
path(d="M32 51c-.188 0-.377-.053-.542-.16l-31-20C.173 30.656 0 30.34 0 30s.173-.656.458-.84l31-20c.33-.213.754-.213 1.084 0l31 20c.285.184.458.5.458.84s-.173.656-.458.84l-31 20c-.165.107-.354.16-.542.16zM2.845 30L32 48.81 61.155 30 32 11.19 2.845 30z")
|
||||
path(d="M32 42c-.188 0-.377-.053-.542-.16l-31-20C.173 21.656 0 21.34 0 21s.173-.656.458-.84l31-20c.33-.213.754-.213 1.084 0l31 20c.285.184.458.5.458.84s-.173.656-.458.84l-31 20c-.165.107-.354.16-.542.16zM2.845 21L32 39.81 61.155 21 32 2.19 2.845 21z")
|
||||
path(d="M31 27h2v2h-2zm0-4h2v2h-2zm0 8h2v2h-2zm4-4h2v2h-2zm4 2h2v2h-2zm-16 0h2v2h-2zm12 2h2v2h-2zm-8-4h2v2h-2zm0 4h2v2h-2zm4 4h2v2h-2zm31 15h2v2h-2zm0-4h2v2h-2zm0 8h2v2h-2zm0 4h2v2h-2zm0-54h2v2h-2zm0-4h2v2h-2zm0 8h2v2h-2zm0 4h2v2h-2zM0 50h2v2H0zm0-4h2v2H0zm0 8h2v2H0zm0 4h2v2H0zM0 4h2v2H0zm0-4h2v2H0zm4 0h2v2H4zm4 0h2v2H8zm4 0h2v2h-2zm4 0h2v2h-2zm4 0h2v2h-2zm22 0h2v2h-2zm4 0h2v2h-2zm4 0h2v2h-2zm4 0h2v2h-2zm4 0h2v2h-2zM4 58h2v2H4zm4 0h2v2H8zm4 0h2v2h-2zm4 0h2v2h-2zm4 0h2v2h-2zm22 0h2v2h-2zm4 0h2v2h-2zm4 0h2v2h-2zm4 0h2v2h-2zm4 0h2v2h-2zM0 8h2v2H0zm0 4h2v2H0z")
|
||||
|
||||
|
||||
section.page-card.dark.right
|
||||
|
||||
.page-card-side
|
||||
h2.page-card-title
|
||||
| Image Sharing
|
||||
.page-card-summary
|
||||
p.
|
||||
Got a nice render, a Blender oddity, a cool screenshot?
|
||||
Share it instantly from within Blender to the Cloud, to the world!
|
||||
|
||||
a.page-card-cta(
|
||||
href="https://cloud.blender.org/blog/introducing-image-sharing")
|
||||
| Learn More
|
||||
|
||||
.page-card-side
|
||||
.page-card-icon
|
||||
svg(xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64")
|
||||
g(fill="none",
|
||||
stroke="#aaa",
|
||||
stroke-width="2",
|
||||
stroke-linejoin="round",
|
||||
stroke-miterlimit="10")
|
||||
path(d="M1 1h62v62H1zM4 59h2M8 59h2M12 59h2M60 49H48M46 49H27M60 53H40")
|
||||
path(d="M5 5h54v40H5z")
|
||||
path(d="M9 45v-3c0-1.656 1.344-3 3-3h6c1.656 0 3 1.344 3 3v3M29 45v-3c0-1.656 1.344-3 3-3h6c1.656 0 3 1.344 3 3v3M13 45v-3M17 45v-3M33 45v-3M37 45v-3M22 31h-5c-2.762 0-5 2.238-5 5v3M38 39v-3c0-2.762-2.238-5-5-5h-5M31 20c0 3.313-1 9-6 9s-6-5.687-6-9c0-1 0-5 6-5s6 4 6 5z")
|
||||
path(d="M29 27l-2 8h-4l-2-8M18 31c-4-3-5-9-5-9l6-3M32 31c4-3 5-9 5-9l-6-3M59 24L44 9l-8 8M44 9l8 36")
|
||||
circle(cx="12", cy="12", r="3")
|
||||
|
||||
|
||||
section.page-card
|
||||
|
||||
.page-card-side
|
||||
h2.page-card-title Private Projects
|
||||
.page-card-summary.
|
||||
Create and manage your own personal projects.
|
||||
Upload assets and collaborate with other Blender Cloud members.
|
||||
|
||||
a.page-card-cta(
|
||||
href="https://cloud.blender.org/blog/introducing-private-projects")
|
||||
| Learn More
|
||||
|
||||
.page-card-side
|
||||
.page-card-icon
|
||||
svg(xmlns='http://www.w3.org/2000/svg', width='56', height='64', viewbox='0 0 56 64')
|
||||
g(fill='#555')
|
||||
path(d='M42 38H14V26h28v12zm-26-2h24v-8H16v8zm-4-5H8c-1.654 0-3-1.346-3-3V15h2v13c0 .55.45 1 1 1h4v2z')
|
||||
path(d='M9.293 19.707L6 16.414l-3.293 3.293-1.414-1.414 4-4c.39-.39 1.023-.39 1.414 0l4 4-1.414 1.414zM48 31h-4v-2h4c.55 0 1-.45 1-1V15h2v13c0 1.654-1.346 3-3 3z')
|
||||
path(d='M53.293 19.707L50 16.414l-3.293 3.293-1.414-1.414L50 13.586l4.707 4.707M27 15h2v9h-2z')
|
||||
path(d='M31.293 19.707L28 16.414l-3.293 3.293-1.414-1.414L28 13.586l4.707 4.707M7 49H5V36c0-1.654 1.346-3 3-3h4v2H8c-.55 0-1 .45-1 1v13z')
|
||||
path(d='M6 50c-.256 0-.512-.098-.707-.293l-4-4 1.414-1.414L6 47.586l3.293-3.293 1.414 1.414-4 4c-.195.195-.45.293-.707.293zm45-1h-2V36c0-.55-.45-1-1-1h-4v-2h4c1.654 0 3 1.346 3 3v13z')
|
||||
path(d='M50 50.414l-4.707-4.707 1.414-1.414L50 47.586l3.293-3.293 1.414 1.414M27 40h2v9h-2z')
|
||||
path(d='M28 50.414l-4.707-4.707 1.414-1.414L28 47.586l3.293-3.293 1.414 1.414M6 12c-3.31 0-6-2.692-6-6s2.69-6 6-6 6 2.692 6 6-2.69 6-6 6zM6 2C3.794 2 2 3.794 2 6s1.794 4 4 4 4-1.794 4-4-1.794-4-4-4zm22 10c-3.31 0-6-2.692-6-6s2.69-6 6-6 6 2.692 6 6-2.69 6-6 6zm0-10c-2.206 0-4 1.794-4 4s1.794 4 4 4 4-1.794 4-4-1.794-4-4-4zm22 10c-3.31 0-6-2.692-6-6s2.69-6 6-6 6 2.692 6 6-2.69 6-6 6zm0-10c-2.206 0-4 1.794-4 4s1.794 4 4 4 4-1.794 4-4-1.794-4-4-4zM6 64c-3.31 0-6-2.692-6-6s2.69-6 6-6 6 2.692 6 6-2.69 6-6 6zm0-10c-2.206 0-4 1.794-4 4s1.794 4 4 4 4-1.794 4-4-1.794-4-4-4zm22 10c-3.31 0-6-2.692-6-6s2.69-6 6-6 6 2.692 6 6-2.69 6-6 6zm0-10c-2.206 0-4 1.794-4 4s1.794 4 4 4 4-1.794 4-4-1.794-4-4-4zm22 10c-3.31 0-6-2.692-6-6s2.69-6 6-6 6 2.692 6 6-2.69 6-6 6zm0-10c-2.206 0-4 1.794-4 4s1.794 4 4 4 4-1.794 4-4-1.794-4-4-4zM27 31h2v2h-2zm-4 0h2v2h-2zm8 0h2v2h-2z')
|
||||
|
||||
|
||||
section.pricing
|
||||
.container
|
||||
.row
|
||||
.col-md-12
|
||||
h2 Simple Pricing. Any payment method.
|
||||
.row
|
||||
.col-md-4.col-sm-4
|
||||
.box.monthly
|
||||
h3 Monthly
|
||||
.pricing-display
|
||||
span.currency-sign $
|
||||
span.digit-int 9
|
||||
span.digit-dec .90 / month*
|
||||
|
||||
.pricing-caption
|
||||
p * with a 3-months minimum period
|
||||
|
||||
a.sign-up-now(href="https://store.blender.org/product/membership/")
|
||||
| Subscribe Now
|
||||
|
||||
.col-md-4.col-sm-4
|
||||
.box.yearly
|
||||
h3 Yearly
|
||||
.pricing-display
|
||||
span.currency-sign $
|
||||
span.digit-int 109
|
||||
span.digit-dec .00 / year
|
||||
.pricing-caption
|
||||
p 1 month free!
|
||||
p Free copy of the <a href="https://store.blender.org/product/art-of-blender-2/">Art of Blender</a>
|
||||
|
||||
a.sign-up-now(href="https://store.blender.org/product/membership/")
|
||||
| Subscribe Now
|
||||
|
||||
.col-md-4.col-sm-4
|
||||
.box.education
|
||||
h3 Education
|
||||
|
||||
.pricing-caption
|
||||
p.
|
||||
We also provide flexible options for group subscription
|
||||
ideal for schools or teams.
|
||||
p.
|
||||
Get in touch to discuss direct support, custom solutions,
|
||||
team management tools and Single Sign-on.
|
||||
|
||||
a.sign-up-now(href="mailto:cloudsupport@blender.org")
|
||||
i.pi-email
|
||||
| Get in Touch
|
||||
|
||||
section.team(
|
||||
style="background-image: url({{ url_for('static', filename='assets/img/backgrounds/pattern_01.jpg')}})")
|
||||
.container
|
||||
.row
|
||||
.col-md-12
|
||||
h2.
|
||||
A restless team of artists and developers <br/>
|
||||
wants to share their work with you.
|
||||
|
||||
.people-container
|
||||
.people-intro
|
||||
h3 Blender Institute
|
||||
span Amsterdam, The Netherlands
|
||||
|
||||
.people-faces
|
||||
.face(data-blenderhead='ton')
|
||||
img(alt="Ton", src="{{ url_for('static', filename='assets/img/people/ton.jpg')}}")
|
||||
.face(data-blenderhead='francesco')
|
||||
img(alt="Francesco", src="{{ url_for('static', filename='assets/img/people/francesco.jpg')}}")
|
||||
.face(data-blenderhead='pablo')
|
||||
img(alt="Pablo", src="{{ url_for('static', filename='assets/img/people/pablo.jpg')}}")
|
||||
.face(data-blenderhead='andy')
|
||||
img(alt="Andy", src="{{ url_for('static', filename='assets/img/people/andy.jpg')}}")
|
||||
.face(data-blenderhead='hjalti')
|
||||
img(alt="Hjalti", src="{{ url_for('static', filename='assets/img/people/hjalti.jpg')}}")
|
||||
.face(data-blenderhead='sergey')
|
||||
img(alt="Sergey", src="{{ url_for('static', filename='assets/img/people/sergey.jpg')}}")
|
||||
.face(data-blenderhead='sybren')
|
||||
img(alt="Sybren", src="{{ url_for('static', filename='assets/img/people/sybren.jpg')}}")
|
||||
|
||||
.people-bio
|
||||
.bio#ton
|
||||
h3 Ton Roosendaal
|
||||
small CEO Blender Foundation. Producer Blender Institute
|
||||
span The Netherlands
|
||||
|
||||
.bio#francesco
|
||||
h3 Francesco Siddi
|
||||
small Pipeline Tools & Back-end Web Development
|
||||
span Italy
|
||||
|
||||
.bio#pablo
|
||||
h3 Pablo Vázquez
|
||||
small Lighting, Rendering. Front-end Web Development
|
||||
span Argentina
|
||||
|
||||
.bio#andy
|
||||
h3 Andy Goralczyk
|
||||
small Shading, Lighting, Rendering, FX
|
||||
span Germany
|
||||
|
||||
.bio#hjalti
|
||||
h3 Hjalti Hjálmarsson
|
||||
small Animation. Layout Artist.
|
||||
span Iceland
|
||||
|
||||
.bio#sergey
|
||||
h3 Sergey Sharybin
|
||||
small Blender & Cycles Core Developer
|
||||
span Russia
|
||||
|
||||
.bio#sybren
|
||||
h3 Sybren Stüvel
|
||||
small Blender Cloud Developer
|
||||
span The Netherlands
|
||||
|
||||
|
||||
.people-container.online
|
||||
.people-intro
|
||||
h3 Online Collaborators
|
||||
span Contributing to Blender Cloud from all over the globe.
|
||||
|
||||
.people-faces
|
||||
.face(data-blenderhead='gleb')
|
||||
img(alt="Gleb", src="{{ url_for('static', filename='assets/img/people/gleb.jpg')}}")
|
||||
.face(data-blenderhead='david')
|
||||
img(alt="David", src="{{ url_for('static', filename='assets/img/people/david.jpg')}}")
|
||||
.face(data-blenderhead='sebastian')
|
||||
img(alt="Sebastian", src="{{ url_for('static', filename='assets/img/people/sebastian.jpg')}}")
|
||||
.face(data-blenderhead='jpbouza')
|
||||
img(alt="Juan Pablo", src="{{ url_for('static', filename='assets/img/people/jpbouza.jpg')}}")
|
||||
.face(data-blenderhead='bassam')
|
||||
img(alt="Bassam", src="{{ url_for('static', filename='assets/img/people/bassam.jpg')}}")
|
||||
|
||||
.people-bio
|
||||
.bio#gleb
|
||||
h3 Gleb Alexandrov
|
||||
small Lighting & Shading
|
||||
span Belarus
|
||||
|
||||
.bio#david
|
||||
h3 David Revoy
|
||||
small Illustrator & Concept Artist
|
||||
span France
|
||||
|
||||
.bio#jpbouza
|
||||
h3 Juan Pablo Bouza
|
||||
small Rigging
|
||||
span Argentina
|
||||
|
||||
.bio#bassam
|
||||
h3 Bassam Kurdali
|
||||
small Rigging & Pipeline
|
||||
span United States
|
||||
|
||||
.bio#sebastian
|
||||
h3 Sebastian König
|
||||
small VFX
|
||||
span Germany
|
||||
|
||||
|
||||
section.page-card.oneofus.
|
||||
Join <strong>2021</strong> awesome people, <a href="">subscribe to Blender Cloud</a> now.
|
||||
|
||||
section.supported-by
|
||||
h2 Our projects were supported by
|
||||
img.logos(alt="Supported by", src="{{ url_for('static', filename='assets/img/support_logos.png') }}")
|
||||
|
||||
section.page-card.subscribe(
|
||||
style="background-image: url({{ url_for('static', filename='assets/img/backgrounds/background_services.jpg')}});")
|
||||
.page-card-side
|
||||
h2.page-card-title
|
||||
| Get inspiration, knowledge, and tools in one place.
|
||||
.page-card-summary
|
||||
| Join us for only $9.90/month!
|
||||
a.page-card-cta(
|
||||
href="https://store.blender.org/product/membership/")
|
||||
| Subscribe Now
|
||||
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_scripts %}
|
||||
script.
|
||||
|
||||
$('.triplet-card').click(function(){
|
||||
window.location.replace($(this).attr('data-url'));
|
||||
});
|
||||
|
||||
$(window).on('load scroll', function() {
|
||||
var y = $(this).scrollTop();
|
||||
if (y < 100){
|
||||
$('.navbar-backdrop').css('background-position-y', (parseInt(-y / 4) * -1) + 'px');
|
||||
}
|
||||
});
|
||||
|
||||
function getSubscribers(){
|
||||
$.get('https://store.blender.org/product-counter/?prod=cloud', function(data) {
|
||||
}).done(function(data){
|
||||
if (data.total_sold > 0) {
|
||||
$('.page-card.oneofus').addClass('active');
|
||||
$('.page-card.oneofus strong').html(data.total_sold);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getSubscribers();
|
||||
|
||||
$('.people-faces .face').hover(
|
||||
function(){
|
||||
var who = $(this).data('blenderhead');
|
||||
$('#' + who).addClass('active');
|
||||
$(this).parent().prev().addClass('active');
|
||||
},
|
||||
function(){
|
||||
$('.bio, .people-intro').removeClass('active');
|
||||
}
|
||||
);
|
||||
|
||||
// Click anywhere in the page to hide the overlay
|
||||
function hideOverlay() {
|
||||
$('#page-overlay.video').removeClass('active');
|
||||
$('#page-overlay.video .video-embed').html('');
|
||||
}
|
||||
|
||||
$(document).click(function() {
|
||||
hideOverlay();
|
||||
});
|
||||
|
||||
$(document).keyup(function(e) {
|
||||
if (e.keyCode == 27) {
|
||||
hideOverlay();
|
||||
}
|
||||
});
|
||||
|
||||
$('a.watch-video').click(function(e){
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
$('#page-overlay.video').addClass('active');
|
||||
|
||||
var videoId = $(this).attr('data-youtube-id');
|
||||
$('#page-overlay .video-embed').html('<iframe src="https://www.youtube.com/embed/' + videoId +'?rel=0&showinfo=0;autoplay=1" frameborder="0" allowfullscreen></iframe>')
|
||||
});
|
||||
|
||||
| {% endblock %}
|
436
src/templates/layout.jade
Normal file
436
src/templates/layout.jade
Normal file
@@ -0,0 +1,436 @@
|
||||
doctype
|
||||
html(lang="en")
|
||||
head
|
||||
meta(charset="utf-8")
|
||||
title {% if self.page_title() %}{% block page_title %}{% endblock %} — {% endif %}Blender Cloud
|
||||
meta(name="viewport", content="width=device-width, initial-scale=1.0")
|
||||
meta(name="description", content="Blender Cloud is a web based service developed by Blender Institute that allows people to access the training videos and all the data from the open projects.")
|
||||
meta(name="author", content="Blender Institute")
|
||||
meta(name="theme-color", content="#3e92aa")
|
||||
|
||||
meta(property="og:site_name", content="Blender Cloud")
|
||||
| {% block og %}
|
||||
meta(property="og:title", content="Blender Cloud")
|
||||
meta(property="og:url", content="https://cloud.blender.org")
|
||||
meta(property="og:type", content="website")
|
||||
meta(property="og:image", content="{{ url_for('static', filename='assets/img/backgrounds/background_gleb_locomotive.jpg')}}")
|
||||
| {% endblock %}
|
||||
|
||||
meta(name="twitter:card", content="summary_large_image")
|
||||
meta(name="twitter:site", content="@Blender_Cloud")
|
||||
| {% block tw %}
|
||||
meta(name="twitter:title", content="Blender Cloud")
|
||||
meta(name="twitter:description", content="Blender Cloud is a web based service developed by Blender Institute that allows people to access the training videos and all the data from the open projects.")
|
||||
meta(name="twitter:image", content="{{ url_for('static', filename='assets/img/backgrounds/background_gleb_locomotive.jpg')}}")
|
||||
| {% endblock %}
|
||||
|
||||
script(src="//code.jquery.com/jquery-2.2.1.min.js")
|
||||
script(src="//cdn.jsdelivr.net/typeahead.js/0.11.1/typeahead.jquery.min.js")
|
||||
script(src="//cdn.jsdelivr.net/algoliasearch/3/algoliasearch.min.js")
|
||||
script(src="//cdnjs.cloudflare.com/ajax/libs/js-cookie/2.0.3/js.cookie.min.js",)
|
||||
|
||||
script.
|
||||
var algolia = algoliasearch("{{config['ALGOLIA_USER']}}", "{{config['ALGOLIA_PUBLIC_KEY']}}");
|
||||
var index = algolia.initIndex("{{config['ALGOLIA_INDEX_NODES']}}");
|
||||
|
||||
!function(e){"use strict";e.loadCSS=function(t,n,o){var r,i=e.document,l=i.createElement("link");if(n)r=n;else{var d=(i.body||i.getElementsByTagName("head")[0]).childNodes;r=d[d.length-1]}var a=i.styleSheets;l.rel="stylesheet",l.href=t,l.media="only x",r.parentNode.insertBefore(l,n?r:r.nextSibling);var f=function(e){for(var t=l.href,n=a.length;n--;)if(a[n].href===t)return e();setTimeout(function(){f(e)})};return l.onloadcssdefined=f,f(function(){l.media=o||"all"}),l},"undefined"!=typeof module&&(module.exports=e.loadCSS)}(this);
|
||||
|
||||
loadCSS( "//fonts.googleapis.com/css?family=Roboto:300,400,500" );
|
||||
loadCSS( "//fonts.googleapis.com/css?family=Lato:300,400" );
|
||||
|
||||
script(src="{{ url_for('static_pillar', filename='assets/js/markdown.min.js', v=040820161) }}")
|
||||
script(src="{{ url_for('static_pillar', filename='assets/js/tutti.min.js', v=040820161) }}")
|
||||
|
||||
link(href="{{ url_for('static_pillar', filename='assets/ico/favicon.png') }}", rel="shortcut icon")
|
||||
link(href="{{ url_for('static_pillar', filename='assets/ico/apple-touch-icon-precomposed.png') }}", rel="icon apple-touch-icon-precomposed", sizes="192x192")
|
||||
|
||||
link(href="{{ url_for('static_pillar', filename='assets/css/vendor/bootstrap.min.css') }}", rel="stylesheet")
|
||||
|
||||
| {% block head %}{% endblock %}
|
||||
|
||||
| {% block css %}
|
||||
| {% if title == 'blog' %}
|
||||
link(href="{{ url_for('static_pillar', filename='assets/css/blog.css', v=040820161) }}", rel="stylesheet")
|
||||
| {% else %}
|
||||
link(href="{{ url_for('static_pillar', filename='assets/css/main.css', v=040820161) }}", rel="stylesheet")
|
||||
| {% endif %}
|
||||
| {% endblock %}
|
||||
|
||||
|
||||
| {% if not title %}{% set title="default" %}{% endif %}
|
||||
|
||||
body(class="{{ title }}")
|
||||
.container-page
|
||||
header.navbar-backdrop-container
|
||||
| {% block header_backdrop %}
|
||||
img(src="{{ url_for('static', filename='assets/img/backgrounds/pattern_02_blur.jpg')}}")
|
||||
| {% endblock %}
|
||||
|
||||
| {% with messages = get_flashed_messages(with_categories=True) %}
|
||||
| {% if messages %}
|
||||
|
||||
| {% for (category, message) in messages %}
|
||||
.alert(role="alert", class="alert-{{ category }}")
|
||||
i.alert-icon(class="{{ category }}")
|
||||
span {{ message }}
|
||||
button.close(type="button", data-dismiss="alert")
|
||||
i.pi-cancel
|
||||
| {% endfor %}
|
||||
|
||||
| {% endif %}
|
||||
| {% endwith %}
|
||||
|
||||
nav.navbar.navbar-transparent.navbar-fixed-top
|
||||
.navbar-overlay
|
||||
|
||||
.navbar-container
|
||||
header.navbar-header
|
||||
button.navbar-toggle(data-target=".navbar-collapse", data-toggle="collapse", type="button")
|
||||
span.sr-only Toggle navigation
|
||||
i.pi-menu
|
||||
a.navbar-brand(
|
||||
href="/",
|
||||
title="Blender Cloud")
|
||||
span.app-logo
|
||||
i.pi-blender-cloud
|
||||
|
||||
| {% block navigation_search %}
|
||||
.search-input
|
||||
input#cloud-search(
|
||||
type="text",
|
||||
placeholder="Search assets, tutorials...")
|
||||
i.search-icon.pi-search
|
||||
| {% endblock %}
|
||||
|
||||
nav.collapse.navbar-collapse
|
||||
ul.nav.navbar-nav.navbar-right
|
||||
| {% if node and node.properties and node.properties.category %}
|
||||
| {% set category = node.properties.category %}
|
||||
| {% else %}
|
||||
| {% set category = title %}
|
||||
| {% endif %}
|
||||
|
||||
| {% block navigation_sections %}
|
||||
li
|
||||
a.navbar-item(
|
||||
href="{{ url_for('main.main_blog') }}",
|
||||
title="Blender Cloud Blog",
|
||||
data-toggle="tooltip",
|
||||
data-placement="bottom",
|
||||
class="{% if category == 'blog' %}active{% endif %}")
|
||||
span Blog
|
||||
|
||||
li(class="dropdown libraries")
|
||||
a.navbar-item.dropdown-toggle(
|
||||
href="#",
|
||||
data-toggle="dropdown",
|
||||
title="Libraries")
|
||||
span Libraries
|
||||
i.pi-angle-down
|
||||
|
||||
ul.dropdown-menu
|
||||
li
|
||||
a.navbar-item(
|
||||
href="{{ url_for('main.redir_hdri') }}",
|
||||
title="HDRI Library",
|
||||
data-toggle="tooltip",
|
||||
data-placement="left")
|
||||
i.pi-globe
|
||||
| HDRI
|
||||
li
|
||||
a.navbar-item(
|
||||
href="{{ url_for('main.redir_textures') }}",
|
||||
title="Textures Library",
|
||||
data-toggle="tooltip",
|
||||
data-placement="left")
|
||||
i.pi-folder-texture
|
||||
| Textures
|
||||
li
|
||||
a.navbar-item(
|
||||
href="{{ url_for('main.redir_characters') }}",
|
||||
title="Character Library",
|
||||
data-toggle="tooltip",
|
||||
data-placement="left")
|
||||
i.pi-character
|
||||
| Characters
|
||||
li
|
||||
a.navbar-item(
|
||||
href="{{ url_for('main.gallery') }}",
|
||||
title="Curated artwork collection",
|
||||
data-toggle="tooltip",
|
||||
data-placement="left")
|
||||
i.pi-image
|
||||
| Art Gallery
|
||||
|
||||
li
|
||||
a.navbar-item(
|
||||
href="{{ url_for('main.training') }}",
|
||||
title="Training & Tutorials",
|
||||
data-toggle="tooltip",
|
||||
data-placement="bottom",
|
||||
class="{% if category == 'training' %}active{% endif %}")
|
||||
span Training
|
||||
li
|
||||
a.navbar-item(
|
||||
href="{{ url_for('main.open_projects') }}",
|
||||
title="Browse all the Open Projects",
|
||||
data-toggle="tooltip",
|
||||
data-placement="bottom",
|
||||
class="{% if category in ['open-projects', 'film'] %}active{% endif %}")
|
||||
span Open Projects
|
||||
li
|
||||
a.navbar-item(
|
||||
href="{{ url_for('main.services') }}",
|
||||
title="Blender Cloud Services",
|
||||
data-toggle="tooltip",
|
||||
data-placement="bottom",
|
||||
class="{% if category == 'services' %}active{% endif %}")
|
||||
span Services
|
||||
| {% endblock %}
|
||||
|
||||
| {% if current_user.is_anonymous %}
|
||||
li
|
||||
a.navbar-item(
|
||||
href="https://store.blender.org/product/membership/",
|
||||
title="Sign up") Sign up
|
||||
| {% endif %}
|
||||
|
||||
| {% if current_user.is_authenticated %}
|
||||
|
||||
| {% if current_user.has_role('demo') %}
|
||||
| {% set subscription = 'demo' %}
|
||||
| {% elif current_user.has_role('subscriber') %}
|
||||
| {% set subscription = 'subscriber' %}
|
||||
| {% else %}
|
||||
| {% set subscription = 'none' %}
|
||||
| {% endif %}
|
||||
|
||||
li.nav-notifications
|
||||
a.navbar-item#notifications-toggle(
|
||||
title="Notifications",
|
||||
data-toggle="tooltip",
|
||||
data-placement="bottom")
|
||||
i.pi-notifications-none.nav-notifications-icon
|
||||
span#notifications-count
|
||||
span
|
||||
.flyout-hat
|
||||
|
||||
#notifications.flyout.notifications
|
||||
.flyout-content
|
||||
span.flyout-title Notifications
|
||||
a#notifications-markallread(
|
||||
title="Mark All as Read",
|
||||
href="/notifications/read-all")
|
||||
| Mark All as Read
|
||||
|
||||
| {% include '_notifications.html' %}
|
||||
|
||||
|
||||
li(class="dropdown{% if title in ['profile', 'billing-address', 'pledges', 'manage-collection']: %} active{% endif %}")
|
||||
a.navbar-item.dropdown-toggle(href="#", data-toggle="dropdown", title="{{ current_user.email }}")
|
||||
img.gravatar(
|
||||
src="{{ current_user.gravatar }}",
|
||||
class="{{ subscription }}",
|
||||
alt="Avatar")
|
||||
.special(class="{{ subscription }}")
|
||||
| {% if subscription == 'subscriber' %}
|
||||
i.pi-check
|
||||
| {% elif subscription == 'demo' %}
|
||||
i.pi-heart-filled
|
||||
| {% else %}
|
||||
i.pi-attention
|
||||
| {% endif %}
|
||||
|
||||
ul.dropdown-menu
|
||||
| {% if not current_user.has_role('protected') %}
|
||||
li.subscription-status(class="{{ subscription }}")
|
||||
| {% if subscription == 'subscriber' %}
|
||||
a.navbar-item(
|
||||
href="{{url_for('users.settings_billing')}}"
|
||||
title="View subscription info")
|
||||
i.pi-grin
|
||||
span Your subscription is active!
|
||||
| {% elif subscription == 'demo' %}
|
||||
a.navbar-item(
|
||||
href="{{url_for('users.settings_billing')}}"
|
||||
title="View subscription info")
|
||||
i.pi-heart-filled
|
||||
span You have a free account.
|
||||
| {% else %}
|
||||
a.navbar-item(
|
||||
href="https://store.blender.org/product/membership/"
|
||||
title="Renew subscription")
|
||||
i.pi-unhappy
|
||||
span.info Your subscription is not active.
|
||||
span.renew Click here to renew.
|
||||
| {% endif %}
|
||||
|
||||
li
|
||||
a.navbar-item(
|
||||
href="{{ url_for('projects.home_project') }}"
|
||||
title="Home")
|
||||
i.pi-home
|
||||
| Home
|
||||
|
||||
li
|
||||
home_project
|
||||
a.navbar-item(
|
||||
href="{{ url_for('projects.index') }}"
|
||||
title="My Projects")
|
||||
i.pi-star
|
||||
| My Projects
|
||||
|
||||
li
|
||||
a.navbar-item(
|
||||
href="{{ url_for('users.settings_profile') }}"
|
||||
title="Settings")
|
||||
i.pi-cog
|
||||
| Settings
|
||||
li
|
||||
a.navbar-item(
|
||||
href="{{ url_for('users.settings_billing') }}"
|
||||
title="Billing")
|
||||
i.pi-credit-card
|
||||
| Subscription
|
||||
li.divider(role="separator")
|
||||
| {% endif %}
|
||||
li
|
||||
a.navbar-item(
|
||||
href="{{ url_for('users.logout') }}")
|
||||
i.pi-log-out(title="Log Out")
|
||||
| Log out
|
||||
|
||||
| {% else %}
|
||||
|
||||
li.nav-item-sign-in
|
||||
a.navbar-item(href="{{ url_for('users.login') }}")
|
||||
| Log in
|
||||
| {% endif %}
|
||||
|
||||
.page-content
|
||||
#search-overlay
|
||||
| {% block page_overlay %}
|
||||
#page-overlay
|
||||
| {% endblock %}
|
||||
.page-body
|
||||
| {% block body %}{% endblock %}
|
||||
|
||||
| {% block footer_container %}
|
||||
#footer-container
|
||||
| {% block footer_navigation %}
|
||||
#footer-navigation
|
||||
.container
|
||||
.row
|
||||
.col-md-4.col-xs-6
|
||||
.footer-support
|
||||
h4 Support & Feedback
|
||||
p.
|
||||
Let us know what you think or if you have any issues
|
||||
just write to cloudsupport at blender dot org
|
||||
|
||||
.col-md-2.col-xs-6
|
||||
ul.footer-social
|
||||
li
|
||||
a(href="https://twitter.com/Blender_Cloud",
|
||||
title="Follow us on Twitter")
|
||||
i.pi-social-twitter
|
||||
li
|
||||
a(href="mailto:cloudsupport@blender.org"
|
||||
title="Support Email")
|
||||
i.pi-email
|
||||
|
||||
.col-md-2.col-xs-6
|
||||
h4
|
||||
a(href="{{ url_for('main.homepage') }}")
|
||||
| Blender Cloud
|
||||
ul.footer-links
|
||||
li
|
||||
a(href="{{ url_for('main.main_blog') }}",
|
||||
title="Blender Cloud Blog")
|
||||
| Blog
|
||||
|
||||
li
|
||||
a(href="{{ url_for('main.services') }}",
|
||||
title="Blender Cloud Services")
|
||||
| Services
|
||||
|
||||
li
|
||||
a(href="https://cloud.blender.org/blog/blender-cloud-v3",
|
||||
title="About Blender Cloud")
|
||||
| About
|
||||
|
||||
.col-md-2.col-xs-6
|
||||
h4
|
||||
a(href="https://www.blender.org",
|
||||
title="Blender official Website")
|
||||
| Blender
|
||||
ul.footer-links
|
||||
li
|
||||
a(href="https://www.blender.org",
|
||||
title="Blender official Website")
|
||||
| Blender.org
|
||||
li
|
||||
a(href="https://www.blender.org/store",
|
||||
title="The official Blender Store")
|
||||
| Blender Store
|
||||
|
||||
.col-md-2.col-xs-6.special
|
||||
| With the support of the <br/> MEDIA Programme of the European Union<br/><br/>
|
||||
img(alt="MEDIA Programme of the European Union",
|
||||
src="https://gooseberry.blender.org/wp-content/uploads/2014/01/media_programme.png")
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer %}
|
||||
footer.container
|
||||
ul.links
|
||||
li
|
||||
a(href="{{ url_for('main.homepage') }}")
|
||||
| Blender Cloud
|
||||
|
||||
#hop(title="Be awesome in space")
|
||||
i.pi-angle-up
|
||||
|
||||
| {% endblock %}
|
||||
| {% endblock %}
|
||||
|
||||
#notification-pop(data-url="", data-read-toggle="")
|
||||
.nc-progress
|
||||
a#pop-close(href="#", title="Dismiss")
|
||||
i.pi-cancel
|
||||
.nc-item
|
||||
.nc-avatar
|
||||
.nc-text
|
||||
span.nc-date
|
||||
a(href="")
|
||||
|
||||
noscript
|
||||
link(href='//fonts.googleapis.com/css?family=Roboto:300,400,500', rel='stylesheet', type='text/css')
|
||||
link(href='//fonts.googleapis.com/css?family=Lato:300,400', rel='stylesheet', type='text/css')
|
||||
|
||||
script(type="text/javascript", src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js")
|
||||
script(type="text/javascript", src="//cdnjs.cloudflare.com/ajax/libs/jquery.perfect-scrollbar/0.6.10/js/min/perfect-scrollbar.min.js")
|
||||
script(type="text/javascript", src="//cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.min.js")
|
||||
|
||||
script.
|
||||
$(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(); });
|
||||
|
||||
// Load perfectScrollbar
|
||||
Ps.initialize(document.getElementById('notifications'), {suppressScrollX: true});
|
||||
|
||||
{% endif %}
|
||||
});
|
||||
|
||||
| {% block footer_scripts %}{% endblock %}
|
||||
|
||||
script.
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
ga('create', '{{ config.GOOGLE_ANALYTICS_TRACKING_ID }} ', 'auto', {'allowAnchor': true});
|
||||
ga('send', 'pageview');
|
445
src/templates/nodes/custom/_comments.jade
Normal file
445
src/templates/nodes/custom/_comments.jade
Normal file
@@ -0,0 +1,445 @@
|
||||
|
||||
#comments-container
|
||||
a(name="comments")
|
||||
|
||||
section#comments-list
|
||||
.comment-reply-container
|
||||
| {% if current_user.is_authenticated %}
|
||||
|
||||
| {% if has_method_POST %}
|
||||
.comment-reply-avatar
|
||||
img(src="{{ current_user.gravatar }}")
|
||||
|
||||
.comment-reply-form
|
||||
|
||||
.comment-reply-field
|
||||
textarea(
|
||||
id="comment_field",
|
||||
data-parent_id="{{ parent_id }}",
|
||||
placeholder="Join the conversation...",)
|
||||
|
||||
.comment-reply-meta
|
||||
.comment-details
|
||||
.comment-rules
|
||||
a(
|
||||
title="Markdown Supported"
|
||||
href="https://guides.github.com/features/mastering-markdown/")
|
||||
i.pi-markdown
|
||||
|
||||
.comment-author
|
||||
span.commenting-as commenting as
|
||||
span.author-name {{ current_user.full_name }}
|
||||
|
||||
button.comment-action-cancel.btn.btn-outline(
|
||||
type="button",
|
||||
title="Cancel")
|
||||
i.pi-cancel
|
||||
button.comment-action-submit.btn.btn-outline(
|
||||
id="comment_submit",
|
||||
type="button",
|
||||
title="Post Comment")
|
||||
| Post Comment
|
||||
span.hint (Ctrl+Enter)
|
||||
|
||||
.comment-reply-preview
|
||||
|
||||
| {% else %}
|
||||
|
||||
| {# * It's authenticated, but has no 'POST' permission #}
|
||||
.comment-reply-form
|
||||
.comment-reply-field.sign-in
|
||||
textarea(
|
||||
disabled,
|
||||
id="comment_field",
|
||||
data-parent_id="{{ parent_id }}",
|
||||
placeholder="")
|
||||
.sign-in
|
||||
| Join the conversation! <a href="https://store.blender.org/product/membership/">Subscribe to Blender Cloud now.</a>
|
||||
| {% endif %}
|
||||
|
||||
| {% else %}
|
||||
| {# * It's not autenticated #}
|
||||
.comment-reply-form
|
||||
.comment-reply-field.sign-in
|
||||
textarea(
|
||||
disabled,
|
||||
id="comment_field",
|
||||
data-parent_id="{{ parent_id }}",
|
||||
placeholder="")
|
||||
.sign-in
|
||||
a(href="{{ url_for('users.login') }}") Log in
|
||||
| to comment.
|
||||
|
||||
| {% endif %}
|
||||
|
||||
section#comments-list-header
|
||||
#comments-list-title
|
||||
#comments-list-items
|
||||
#comments-list-items-loading
|
||||
i.pi-spin
|
||||
|
||||
script#comment-template(type="text/x-handlebars-template")
|
||||
| {% raw %}
|
||||
|
||||
| {{#list items }}
|
||||
|
||||
.comment-container(
|
||||
id="{{ _id }}",
|
||||
data-node_id="{{ _id }}",
|
||||
class="{{#if is_team}}is-team{{/if}}{{#if is_reply}}is-reply{{else}}is-first{{/if}}")
|
||||
|
||||
.comment-header
|
||||
.comment-avatar
|
||||
img(src="{{ gravatar }}")
|
||||
|
||||
.comment-author(class="{{#if is_own}}own{{/if}}")
|
||||
| {{ author }}
|
||||
span.username ({{ author_username }})
|
||||
|
||||
| {{#if is_team}}
|
||||
.comment-badge.badge-team(title="Project Member") team
|
||||
| {{/if}}
|
||||
|
||||
.comment-time {{ time_published }} {{#if time_edited }} (edited {{ time_edited }}){{/if}}
|
||||
|
||||
.comment-content {{{ content }}}
|
||||
| {{#if is_own}}
|
||||
.comment-content-preview
|
||||
| {{/if}}
|
||||
|
||||
.comment-meta
|
||||
.comment-rating(
|
||||
class="{{#if is_rated}}rated{{/if}}{{#if is_rated_positive}} positive{{/if}}")
|
||||
.comment-rating-value(title="Number of likes") {{ rating }}
|
||||
.comment-action-rating.up(title="Like comment")
|
||||
|
||||
.comment-action-reply(title="Reply to this comment")
|
||||
span reply
|
||||
| {{#if is_own}}
|
||||
.comment-action-edit
|
||||
span.edit_mode(title="Edit comment") edit
|
||||
span.edit_save(title="Save comment")
|
||||
i.pi-check
|
||||
| save changes
|
||||
span.edit_cancel(title="Cancel changes")
|
||||
i.pi-cancel
|
||||
| cancel
|
||||
| {{/if}}
|
||||
|
||||
| {{/list}}
|
||||
| {% endraw %}
|
||||
|
||||
|
||||
| {% block comment_scripts %}
|
||||
|
||||
script.
|
||||
// Markdown initialization
|
||||
var convert = new Markdown.getSanitizingConverter();
|
||||
Markdown.Extra.init(convert);
|
||||
convert = convert.makeHtml;
|
||||
|
||||
// Define the template for handlebars
|
||||
var source = $("#comment-template").html();
|
||||
var template = Handlebars.compile(source);
|
||||
|
||||
|
||||
// Register the helper for generating the comments list
|
||||
Handlebars.registerHelper('list', function(context, options) {
|
||||
var ret = "";
|
||||
var comments_count = 0
|
||||
|
||||
// Loop through all first-level comments
|
||||
for(var i=0, j=context.length; i<j; i++) {
|
||||
|
||||
comments_count++
|
||||
|
||||
// Convert Markdown for each comment
|
||||
context[i]['content'] = convert(context[i]['content']);
|
||||
|
||||
// Append compiled comment to return string
|
||||
ret = ret + options.fn(context[i]);
|
||||
|
||||
// Search for replies to the current comment
|
||||
if (context[i]['replies']) {
|
||||
|
||||
var replies = context[i]['replies'];
|
||||
var compiled_replies = "";
|
||||
|
||||
// Loop through replies
|
||||
for(var r=0, t=replies.length; r<t; r++) {
|
||||
|
||||
// Convert Markdown for each comment
|
||||
replies[r]['content'] = convert(replies[r]['content']);
|
||||
|
||||
// Append compiled replies
|
||||
compiled_replies = compiled_replies + options.fn(replies[r]);
|
||||
comments_count++
|
||||
}
|
||||
|
||||
// Append replies list to the return string
|
||||
ret = ret + compiled_replies;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
$("#comments-list-title").html(((comments_count > 0) ? comments_count : 'No') + ((comments_count == 1) ? ' comment' : ' comments'));
|
||||
|
||||
return ret;
|
||||
});
|
||||
|
||||
// Helper for the if/else statement
|
||||
Handlebars.registerHelper('if', function(conditional, options) {
|
||||
if(conditional) {
|
||||
return options.fn(this);
|
||||
} else {
|
||||
return options.inverse(this);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/* Build the markdown preview when typing in textarea */
|
||||
$(function() {
|
||||
var $textarea = $('.comment-reply-field textarea'),
|
||||
$container = $('.comment-reply-form'),
|
||||
$preview = $('.comment-reply-preview');
|
||||
|
||||
// As we type in the textarea
|
||||
$textarea.keyup(function(e) {
|
||||
|
||||
// Convert markdown
|
||||
$preview.html(convert($textarea.val()));
|
||||
|
||||
// While we are at it, style when empty
|
||||
if ($textarea.val()) {
|
||||
$container.addClass('filled');
|
||||
} else {
|
||||
$container.removeClass('filled');
|
||||
};
|
||||
|
||||
// Send on ctrl+enter
|
||||
if ((e.keyCode == 10 || e.keyCode == 13) && e.ctrlKey){
|
||||
$( ".comment-action-submit" ).trigger( "click" );
|
||||
};
|
||||
|
||||
}).trigger('keyup');
|
||||
});
|
||||
|
||||
|
||||
// Get the comments list in JSON
|
||||
$.getJSON( "{{url_for('nodes.comments_index')}}?parent_id={{ parent_id }}&format=json", function( data ) {
|
||||
// Format using handlebars template
|
||||
var comments = template(data);
|
||||
|
||||
if (comments && comments.trim() !="") {
|
||||
$('#comments-list-items').html(comments);
|
||||
} else {
|
||||
$('#comments-list-items').html('');
|
||||
}
|
||||
})
|
||||
.done(function(){
|
||||
var scrollToId = location.hash;
|
||||
if (scrollToId.length <= 1) return;
|
||||
|
||||
document.getElementById(scrollToId.substr(1)).scrollIntoView(true);
|
||||
$(scrollToId).addClass('comment-linked');
|
||||
});
|
||||
|
||||
/* Submit comment */
|
||||
$('.comment-action-submit').click(function(e){
|
||||
|
||||
var $this = $(this);
|
||||
var $textarea = $('.comment-reply-field textarea');
|
||||
var commentField = document.getElementById('comment_field');
|
||||
var comment = commentField.value;
|
||||
|
||||
function error(msg) {
|
||||
// No content in the textarea
|
||||
$this.addClass('button-field-error');
|
||||
$textarea.addClass('field-error')
|
||||
$this.html(msg);
|
||||
|
||||
setTimeout(function(){
|
||||
$this.html('Post Comment');
|
||||
$this.removeClass('button-field-error');
|
||||
$textarea.removeClass('field-error');
|
||||
}, 2500);
|
||||
}
|
||||
|
||||
if (comment.length < 5) {
|
||||
if (comment.length == 0) error("Say something...");
|
||||
else error("Minimum 5 characters.");
|
||||
return;
|
||||
}
|
||||
|
||||
$this.addClass('submitting');
|
||||
$this.html('<i class="pi-spin spin"></i> Posting...');
|
||||
|
||||
// Collect parent_id
|
||||
parent_id = commentField.getAttribute('data-parent_id');
|
||||
|
||||
$.post("{{url_for('nodes.comments_create')}}",
|
||||
// Submit content and parent_id for comment creation
|
||||
{'content': comment, 'parent_id': parent_id}
|
||||
)
|
||||
.fail(function(){
|
||||
$this.addClass('button-field-error');
|
||||
$textarea.addClass('field-error')
|
||||
$this.html("Houston! Try again?");
|
||||
|
||||
setTimeout(function(){
|
||||
$this.html('Post Comment');
|
||||
$this.removeClass('button-field-error');
|
||||
$textarea.removeClass('field-error');
|
||||
}, 2500);
|
||||
})
|
||||
.done(function(){
|
||||
// Load the comments
|
||||
var url = "{{url_for('nodes.comments_index')}}?parent_id={{ parent_id }}";
|
||||
$.get(url, function(dataHtml) {
|
||||
// Update the DOM injecting the generate HTML into the page
|
||||
$('#comments-container').replaceWith(dataHtml);
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
/* Edit comment */
|
||||
|
||||
// Markdown convert as we type in the textarea
|
||||
$(document).on('keyup','body .comment-content textarea',function(e){
|
||||
|
||||
var $textarea = $(this),
|
||||
$container = $(this).parent(),
|
||||
$preview = $container.next();
|
||||
|
||||
// Convert markdown
|
||||
$preview.html(convert($textarea.val()));
|
||||
|
||||
// While we are at it, style if empty
|
||||
if (!$textarea.val()) {
|
||||
$container.addClass('empty');
|
||||
} else {
|
||||
$container.removeClass('empty');
|
||||
};
|
||||
}).trigger('keyup');
|
||||
|
||||
|
||||
/* Enter edit mode */
|
||||
$(document).on('click','body .comment-action-edit span.edit_mode',function(){
|
||||
|
||||
$(this).hide();
|
||||
$(this).siblings('span.edit_cancel').show();
|
||||
$(this).siblings('span.edit_save').show();
|
||||
|
||||
var comment_content = $(this).parent().parent().siblings('.comment-content');
|
||||
var comment_id = comment_content.parent().attr('data-node_id');
|
||||
var height = comment_content.height();
|
||||
var url = '/nodes/' + comment_id + '/view?format=json';
|
||||
|
||||
$.get(url, function(data) {
|
||||
var comment_raw = data['node']['properties']['content'];
|
||||
comment_content.html('<textarea>' + comment_raw + '</textarea>');
|
||||
|
||||
comment_content.addClass('editing')
|
||||
.find('textarea')
|
||||
.height(height)
|
||||
.focus();
|
||||
comment_content.siblings('.comment-content-preview').show();
|
||||
})
|
||||
.fail(function(data){
|
||||
statusBarSet('error', 'Error entering edit mode.', 'pi-warning');
|
||||
});
|
||||
});
|
||||
|
||||
/* Return UI to normal, when cancelling or saving */
|
||||
function commentEditCancel(comment_container) {
|
||||
var comment_id = comment_container.parent().attr('id');
|
||||
var url = '/nodes/' + comment_id + '/view?format=json';
|
||||
|
||||
$.get(url, function(data) {
|
||||
var comment_raw = data['node']['properties']['content'];
|
||||
|
||||
comment_container.html(convert(comment_raw))
|
||||
.removeClass('editing');
|
||||
comment_container.siblings('.comment-content-preview').html('').hide();
|
||||
})
|
||||
.fail(function(data){
|
||||
statusBarSet('error', 'Error canceling.', 'pi-warning');
|
||||
});
|
||||
}
|
||||
|
||||
$(document).on('click','body .comment-action-edit span.edit_cancel',function(e){
|
||||
|
||||
$(this).hide();
|
||||
$(this).siblings('span.edit_save').hide();
|
||||
$(this).siblings('span.edit_mode').show();
|
||||
|
||||
var commentContainer = $(this).parent().parent().siblings('.comment-content');
|
||||
commentEditCancel(commentContainer);
|
||||
});
|
||||
|
||||
/* Save edited comment */
|
||||
$(document).on('click','body .comment-action-edit span.edit_save',function(e){
|
||||
|
||||
var $this = $(this);
|
||||
var commentContainer = $(this).parent().parent().siblings('.comment-content');
|
||||
var commentField = commentContainer.find('textarea');
|
||||
var comment = commentField.val();
|
||||
var commentId = commentContainer.parent().attr('id');
|
||||
|
||||
function error(msg) {
|
||||
// No content in the textarea
|
||||
$this.addClass('error')
|
||||
.html(msg);
|
||||
commentField.addClass('field-error')
|
||||
|
||||
setTimeout(function(){
|
||||
$this.html('<i class="pi-check"></i> save changes')
|
||||
.removeClass('error');
|
||||
commentField.removeClass('field-error');
|
||||
}, 2500);
|
||||
}
|
||||
|
||||
if (comment.length < 5) {
|
||||
if (comment.length == 0) error("Say something...");
|
||||
else error("Minimum 5 characters.");
|
||||
return;
|
||||
}
|
||||
|
||||
$this.addClass('saving')
|
||||
.html('<i class="pi-spin spin"></i> Saving...');
|
||||
|
||||
$.post('/nodes/comments/' + commentId,
|
||||
{'content': comment}
|
||||
)
|
||||
.fail(function(){
|
||||
$this.addClass('error')
|
||||
.html("Houston! Try again?");
|
||||
commentField.addClass('field-error')
|
||||
|
||||
setTimeout(function(){
|
||||
$this.html('Save changes')
|
||||
.removeClass('error');
|
||||
commentField.removeClass('field-error');
|
||||
}, 2500);
|
||||
})
|
||||
.done(function(){
|
||||
|
||||
commentEditCancel(commentContainer);
|
||||
commentContainer
|
||||
.html(convert(comment));
|
||||
commentContainer.next().text(comment);
|
||||
|
||||
$this.html('<i class="pi-grin"></i> saved!')
|
||||
.removeClass('saving')
|
||||
.siblings('span.edit_cancel').hide();
|
||||
|
||||
setTimeout(function(){
|
||||
$this.html('<i class="pi-check"></i> save changes')
|
||||
.hide()
|
||||
.siblings('span.edit_mode').show();
|
||||
}, 2500);
|
||||
});
|
||||
});
|
||||
|
||||
| {% endblock %}
|
189
src/templates/nodes/custom/_scripts.jade
Normal file
189
src/templates/nodes/custom/_scripts.jade
Normal file
@@ -0,0 +1,189 @@
|
||||
script(type="text/javascript").
|
||||
|
||||
/* Convert Markdown */
|
||||
var convert_fields = '.node-details-description, .blog_index-item .item-content';
|
||||
var convert = new Markdown.getSanitizingConverter();
|
||||
Markdown.Extra.init(convert);
|
||||
convert = convert.makeHtml;
|
||||
|
||||
|
||||
/* 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: false});
|
||||
|
||||
{% if node %}
|
||||
ProjectUtils.setProjectAttributes({
|
||||
nodeId: '{{node._id}}',
|
||||
nodeType: '{{node.node_type}}'});
|
||||
|
||||
var node_type = ProjectUtils.nodeType();
|
||||
var node_type_str = node_type;
|
||||
|
||||
if (node_type === 'group'){
|
||||
node_type_str = 'Folder';
|
||||
} else if (node_type === 'group_texture') {
|
||||
node_type_str = 'Texture Folder';
|
||||
} else if (node_type === 'group_hdri') {
|
||||
node_type_str = 'HDRi Folder';
|
||||
}
|
||||
$('a', '.button-edit').html('<i class="pi-edit button-edit-icon"></i> Edit ' + node_type_str);
|
||||
$('a', '.button-delete').html('<i class="pi-trash button-delete-icon"></i>Delete ' + node_type_str);
|
||||
|
||||
{% if parent %}
|
||||
ProjectUtils.setProjectAttributes({parentNodeId: '{{parent._id}}'});
|
||||
{% endif %}
|
||||
|
||||
|
||||
// If we are im preview mode, update the image source
|
||||
var page_overlay = document.getElementById('page-overlay');
|
||||
|
||||
if (page_overlay.classList.contains('active')) {
|
||||
var node_preview = document.getElementById('node-preview');
|
||||
|
||||
if (node_preview){
|
||||
if ($(node_preview).hasClass('image') || $(node_preview).hasClass('file')){
|
||||
var src = $(node_preview).find('img').attr('src');
|
||||
showOverlayPreviewImage(src);
|
||||
}
|
||||
} else {
|
||||
$(page_overlay).html('<div class="nav-prev"></div><div class="no-preview">No Preview Available</div><div class="nav-next"></div>');
|
||||
}
|
||||
}
|
||||
|
||||
function loadComments(){
|
||||
var commentsUrl = "{{ url_for('nodes.comments_index', parent_id=node._id) }}";
|
||||
|
||||
$.get(commentsUrl, function(dataHtml) {
|
||||
})
|
||||
.done(function(dataHtml){
|
||||
// Update the DOM injecting the generate HTML into the page
|
||||
$('#comments-container').replaceWith(dataHtml);
|
||||
})
|
||||
.fail(function(e, data){
|
||||
statusBarSet('error', 'Couldn\'t load comments. Error: ' + data.errorThrown, 'pi-attention', 5000);
|
||||
$('#comments-container').html('<a id="comments-reload"><i class="pi-refresh"></i> Reload comments</a>');
|
||||
});
|
||||
}
|
||||
|
||||
loadComments();
|
||||
|
||||
$('body').on('click', '#comments-reload', function(){
|
||||
loadComments();
|
||||
});
|
||||
|
||||
{% if node.has_method('PUT') %}
|
||||
$('.project-mode-view').show();
|
||||
{% else %}
|
||||
$('.project-mode-view').hide();
|
||||
{% endif %}
|
||||
|
||||
{% if node.picture %}
|
||||
function showOverlayPreviewImage(src) {
|
||||
$(page_overlay)
|
||||
.addClass('active')
|
||||
.html('<div class="nav-prev"></div><img src="' + src + '"/><div class="nav-next"></div>');
|
||||
}
|
||||
|
||||
$('#node-preview.image, #node-preview.file').click(function(e){
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
showOverlayPreviewImage("{{ node.picture.thumbnail('l', api=api) }}");
|
||||
});
|
||||
|
||||
{% endif %}
|
||||
|
||||
// Click anywhere in the page to hide the overlay
|
||||
function hidePageOverlay() {
|
||||
$(page_overlay)
|
||||
.removeAttr('class')
|
||||
.html('');
|
||||
}
|
||||
|
||||
$(page_overlay).click(function(e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
hidePageOverlay();
|
||||
});
|
||||
|
||||
function navigateTree(prev){
|
||||
var tree = $('#project_tree').jstree(true);
|
||||
var curr = tree.get_selected(false);
|
||||
|
||||
if (prev === undefined){
|
||||
var n = tree.get_next_dom(curr);
|
||||
} else {
|
||||
var n = tree.get_prev_dom(curr);
|
||||
}
|
||||
|
||||
if (n && n.length > 0) {
|
||||
tree.deselect_all();
|
||||
tree.select_node(n);
|
||||
}
|
||||
}
|
||||
|
||||
document.onkeydown = function(e) {
|
||||
var event = document.all ? window.event : e;
|
||||
switch (e.target.tagName.toLowerCase()) {
|
||||
case "input":
|
||||
case "textarea":
|
||||
case "select":
|
||||
case "button":
|
||||
break
|
||||
default:
|
||||
if (event.keyCode==27) hidePageOverlay();
|
||||
if (event.keyCode==37) navigateTree(true);
|
||||
if (event.keyCode==39) navigateTree();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$(page_overlay).find('.nav-prev').click(function(e){
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
navigateTree(true);
|
||||
});
|
||||
|
||||
$(page_overlay).find('.nav-next').click(function(e){
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
|
||||
navigateTree();
|
||||
});
|
||||
|
||||
// Auto-scale the image preview to the right aspect ratio
|
||||
var node_preview = document.getElementById("node-preview-thumbnail");
|
||||
|
||||
if (node_preview) {
|
||||
node_preview.addEventListener('load', function() {
|
||||
var preview_aspect = this.naturalWidth / this.naturalHeight
|
||||
|
||||
if (preview_aspect > 1.0){
|
||||
$('.node-preview, .node-preview-thumbnail').css({'max-height': 'auto', 'width': '100%'});
|
||||
$('.node-preview img').css({'max-height': '100%'});
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
$('#node-overlay').click(function(){
|
||||
$(this).removeClass('active').hide().html();
|
||||
});
|
||||
|
||||
if (typeof $().popover != 'undefined'){
|
||||
$('#asset-license').popover();
|
||||
}
|
||||
|
||||
{% endif %}
|
||||
|
||||
|
||||
if (typeof $().tooltip != 'undefined'){
|
||||
$('[data-toggle="tooltip"]').tooltip({'delay' : {'show': 1250, 'hide': 250}});
|
||||
}
|
||||
|
128
src/templates/nodes/custom/asset/file/view_embed.jade
Normal file
128
src/templates/nodes/custom/asset/file/view_embed.jade
Normal file
@@ -0,0 +1,128 @@
|
||||
| {% block body %}
|
||||
|
||||
#node-container
|
||||
#node-overlay
|
||||
|
||||
| {% if node.picture %}
|
||||
section#node-preview.node-preview.file
|
||||
img.node-preview-thumbnail#node-preview-thumbnail(
|
||||
src="{{ node.picture.thumbnail('l', api=api) }}")
|
||||
| {% endif %}
|
||||
|
||||
|
||||
section.node-details-container.file
|
||||
|
||||
.node-details-header
|
||||
.node-title#node-title
|
||||
| {{node.name}}
|
||||
|
||||
.node-details-meta.header
|
||||
ul.node-details-meta-list
|
||||
| {% if node.permissions.world %}
|
||||
li.node-details-meta-list-item.access.public(
|
||||
data-toggle="tooltip",
|
||||
data-placement="left",
|
||||
title="Anybody can download. Share it!")
|
||||
i.pi-lock-open
|
||||
span Public
|
||||
| {% endif %}
|
||||
|
||||
| {% if node.file %}
|
||||
li.node-details-meta-list-item.type
|
||||
| {{ node.file.content_type }}
|
||||
|
||||
li.node-details-meta-list-item.file.length
|
||||
| {{ node.file.length | filesizeformat }}
|
||||
| {% endif %}
|
||||
|
||||
| {% if node.properties.license_type %}
|
||||
| {% if node.properties.license_notes %}
|
||||
li.node-details-meta-list-item.license(
|
||||
id="asset-license",
|
||||
data-toggle="popover",
|
||||
data-placement="left",
|
||||
data-trigger="hover",
|
||||
data-content="{{ node.properties.license_notes }}",
|
||||
title="{{ node.properties.license_type }}")
|
||||
|
||||
i(class="pi-license-{{ node.properties.license_type }}")
|
||||
| {% else %}
|
||||
li.node-details-meta-list-item.license(
|
||||
id="asset-license",
|
||||
data-toggle="tooltip",
|
||||
data-placement="bottom",
|
||||
title="{{ node.properties.license_type }}")
|
||||
|
||||
i(class="pi-license-{{ node.properties.license_type }}")
|
||||
| {% endif %}
|
||||
| {% endif %}
|
||||
|
||||
| {% if node.file %}
|
||||
li.node-details-meta-list-item.file.download(title="Download File")
|
||||
| {% if node.file.link %}
|
||||
a(href="{{ node.file.link }}",
|
||||
title="Download file",
|
||||
download="{{ node.file.filename }}")
|
||||
button.btn.btn-default(type="button")
|
||||
i.pi-download
|
||||
| {% else %}
|
||||
button.btn.btn-default.disabled.sorry(type="button")
|
||||
i.pi-download
|
||||
| {% endif %}
|
||||
| {% endif %}
|
||||
|
||||
|
||||
| {% if node.description %}
|
||||
.node-details-description#node-description
|
||||
| {{node.description}}
|
||||
| {% endif %}
|
||||
|
||||
| {% if node.properties.license_notes %}
|
||||
.node-details-meta.license
|
||||
| {{ node.properties.license_notes }}
|
||||
| {% endif %}
|
||||
|
||||
.node-details-meta.footer
|
||||
ul.node-details-meta-list
|
||||
li.node-details-meta-list-item.status
|
||||
| {{node.properties.status}}
|
||||
|
||||
li.node-details-meta-list-item.author
|
||||
| {{ node.user.full_name }}
|
||||
|
||||
li.node-details-meta-list-item.date(title="Created {{ node._created }}")
|
||||
| {{ node._created | pretty_date }}
|
||||
| {% if (node._created | pretty_date) != (node._updated | pretty_date) %}
|
||||
span(title="Updated {{ node._updated }}") (updated {{ node._updated | pretty_date }})
|
||||
| {% endif %}
|
||||
|
||||
|
||||
#comments-container
|
||||
#comments-list-items-loading
|
||||
i.pi-spin
|
||||
|
||||
include ../../_scripts
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_scripts %}
|
||||
script.
|
||||
// Generate GA pageview
|
||||
ga('send', 'pageview', location.pathname);
|
||||
|
||||
var content_type = $("li.node-details-meta-list-item.type").text();
|
||||
var type_trimmed = content_type.substring(content_type.indexOf("/") + 1);
|
||||
|
||||
if (type_trimmed == 'x-blender' || type_trimmed == 'blend'){
|
||||
type_trimmed = '<span class="blend"><i class="pi-blender-logo"></i></span>';
|
||||
};
|
||||
|
||||
$("li.node-details-meta-list-item.type").html(type_trimmed);
|
||||
|
||||
$('.sorry').click(function() {
|
||||
$.get('/403', function(data) {
|
||||
$('#node-overlay').html(data).addClass('active');
|
||||
})
|
||||
});
|
||||
|
||||
| {% endblock %}
|
4
src/templates/nodes/custom/asset/image/view.jade
Normal file
4
src/templates/nodes/custom/asset/image/view.jade
Normal file
@@ -0,0 +1,4 @@
|
||||
| {% extends 'layout.html' %}
|
||||
|
||||
| {% block footer_scripts %}
|
||||
| {% endblock %}
|
128
src/templates/nodes/custom/asset/image/view_embed.jade
Normal file
128
src/templates/nodes/custom/asset/image/view_embed.jade
Normal file
@@ -0,0 +1,128 @@
|
||||
| {% block body %}
|
||||
|
||||
#node-container
|
||||
#node-overlay
|
||||
|
||||
| {% if node.picture %}
|
||||
section#node-preview.node-preview.image
|
||||
img.node-preview-thumbnail#node-preview-thumbnail(
|
||||
src="{{ node.picture.thumbnail('l', api=api) }}")
|
||||
| {% endif %}
|
||||
|
||||
|
||||
section.node-details-container.image
|
||||
|
||||
.node-details-header
|
||||
.node-title#node-title
|
||||
| {{node.name}}
|
||||
|
||||
.node-details-meta.header
|
||||
ul.node-details-meta-list
|
||||
| {% if node.permissions.world %}
|
||||
li.node-details-meta-list-item.access.public(
|
||||
data-toggle="tooltip",
|
||||
data-placement="left",
|
||||
title="Anybody can download. Share it!")
|
||||
i.pi-lock-open
|
||||
span Public
|
||||
| {% endif %}
|
||||
| {% if node.short_link %}
|
||||
li.node-details-meta-list-item.access.shared
|
||||
a(href="{{ node.short_link }}")
|
||||
i.pi-share
|
||||
| Shared
|
||||
| {% endif %}
|
||||
|
||||
| {% if node.file %}
|
||||
li.node-details-meta-list-item.type
|
||||
| {{ node.file.content_type }}
|
||||
|
||||
li.node-details-meta-list-item.image.length
|
||||
| {{ node.file.length | filesizeformat }}
|
||||
| {% endif %}
|
||||
|
||||
| {% if node.properties.license_type %}
|
||||
| {% if node.properties.license_notes %}
|
||||
li.node-details-meta-list-item.license(
|
||||
id="asset-license",
|
||||
data-toggle="popover",
|
||||
data-placement="left",
|
||||
data-trigger="hover",
|
||||
data-content="{{ node.properties.license_notes }}",
|
||||
title=" {{ node.properties.license_type }}")
|
||||
|
||||
i(class="pi-license-{{ node.properties.license_type }}")
|
||||
| {% else %}
|
||||
li.node-details-meta-list-item.license(
|
||||
id="asset-license",
|
||||
data-toggle="tooltip",
|
||||
data-placement="bottom",
|
||||
title="{{ node.properties.license_type }}")
|
||||
|
||||
i(class="pi-license-{{ node.properties.license_type }}")
|
||||
| {% endif %}
|
||||
| {% endif %}
|
||||
|
||||
| {% if node.file %}
|
||||
li.node-details-meta-list-item.image.download(title="Download Image")
|
||||
| {% if node.file.link %}
|
||||
a(href="{{ node.file.link }}",
|
||||
title="Download image",
|
||||
download="{{ node.file.filename }}")
|
||||
button.btn.btn-default(type="button")
|
||||
i.pi-download
|
||||
| {% else %}
|
||||
button.btn.btn-default.disabled.sorry(type="button")
|
||||
i.pi-download
|
||||
| {% endif %}
|
||||
| {% endif %}
|
||||
|
||||
| {% if node.description %}
|
||||
.node-details-description#node-description
|
||||
| {{node.description}}
|
||||
| {% endif %}
|
||||
|
||||
| {% if node.properties.license_notes %}
|
||||
.node-details-meta.license
|
||||
| {{ node.properties.license_notes }}
|
||||
| {% endif %}
|
||||
|
||||
.node-details-meta.footer
|
||||
ul.node-details-meta-list
|
||||
| {% if node.has_method('PUT') %}
|
||||
li.node-details-meta-list-item.status
|
||||
| {{node.properties.status}}
|
||||
| {% endif %}
|
||||
|
||||
li.node-details-meta-list-item.author
|
||||
| {{ node.user.full_name }}
|
||||
|
||||
li.node-details-meta-list-item.date(title="Created {{ node._created }}")
|
||||
| {{ node._created | pretty_date }}
|
||||
| {% if (node._created | pretty_date) != (node._updated | pretty_date) %}
|
||||
span(title="Updated {{ node._updated }}") (updated {{ node._updated | pretty_date }})
|
||||
| {% endif %}
|
||||
#comments-container
|
||||
#comments-list-items-loading
|
||||
i.pi-spin
|
||||
|
||||
include ../../_scripts
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_scripts %}
|
||||
script.
|
||||
// Generate GA pageview
|
||||
ga('send', 'pageview', location.pathname);
|
||||
|
||||
var content_type = $("li.node-details-meta-list-item.type").text();
|
||||
$("li.node-details-meta-list-item.type").text(content_type.substring(content_type.indexOf("/") + 1));
|
||||
|
||||
$('.sorry').click(function() {
|
||||
$.get('/403', function(data) {
|
||||
$('#node-overlay').html(data).addClass('active');
|
||||
})
|
||||
});
|
||||
|
||||
| {% endblock %}
|
||||
|
6
src/templates/nodes/custom/asset/video/view.jade
Normal file
6
src/templates/nodes/custom/asset/video/view.jade
Normal file
@@ -0,0 +1,6 @@
|
||||
| {% extends 'layout.html' %}
|
||||
| {% from '_macros/_file_uploader_javascript.html' import render_file_uploader_javascript %}
|
||||
|
||||
| {% block footer_scripts %}
|
||||
| {{render_file_uploader_javascript()}}
|
||||
| {% endblock %}
|
158
src/templates/nodes/custom/asset/video/view_embed.jade
Normal file
158
src/templates/nodes/custom/asset/video/view_embed.jade
Normal file
@@ -0,0 +1,158 @@
|
||||
| {% block body %}
|
||||
|
||||
#node-container
|
||||
#node-overlay
|
||||
|
||||
section.node-preview.video
|
||||
#flowplayer_container.is-splash.play-button(
|
||||
style="{% if node.picture %}background-image:url({{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
|
||||
|
||||
|
||||
section.node-details-container.video
|
||||
|
||||
.node-details-header
|
||||
.node-title#node-title
|
||||
| {{node.name}}
|
||||
|
||||
.node-details-meta.header
|
||||
ul.node-details-meta-list
|
||||
| {% if node.permissions.world %}
|
||||
li.node-details-meta-list-item.access.public(
|
||||
data-toggle="tooltip",
|
||||
data-placement="bottom",
|
||||
title="Anybody can download. Share it!")
|
||||
i.pi-lock-open
|
||||
span Public
|
||||
| {% endif %}
|
||||
|
||||
| {% if node.properties.license_type %}
|
||||
| {% if node.properties.license_notes %}
|
||||
li.node-details-meta-list-item.video.license(
|
||||
id="asset-license",
|
||||
data-toggle="popover",
|
||||
data-placement="left",
|
||||
data-trigger="hover",
|
||||
data-content="{{ node.properties.license_notes }}",
|
||||
title="{{ node.properties.license_type }}")
|
||||
|
||||
i(class="pi-license-{{ node.properties.license_type }}")
|
||||
| {% else %}
|
||||
li.node-details-meta-list-item.video.license(
|
||||
id="asset-license",
|
||||
data-toggle="tooltip",
|
||||
data-placement="bottom",
|
||||
title="{{ node.properties.license_type }}")
|
||||
|
||||
i(class="pi-license-{{ node.properties.license_type }}")
|
||||
| {% endif %}
|
||||
| {% endif %}
|
||||
|
||||
| {% if node.file %}
|
||||
| {% if node.file_variations %}
|
||||
li.btn-group.node-details-meta-list-item.video.download(
|
||||
title="Download Video")
|
||||
button.btn.btn-default.dropdown-toggle(
|
||||
type="button",
|
||||
data-toggle="dropdown",
|
||||
aria-haspopup="true",
|
||||
aria-expanded="false")
|
||||
i.pi-download
|
||||
i.pi-angle-down.icon-dropdown-menu
|
||||
|
||||
ul.dropdown-menu
|
||||
| {% for child in node.file_variations %}
|
||||
li
|
||||
a(href="{{ child.link }}",
|
||||
title="Download this video format",
|
||||
download)
|
||||
span.length {{ child.length | filesizeformat }}
|
||||
|
||||
span.format {{ child.format }}
|
||||
span.size {{ child.size }}
|
||||
|
||||
| {% endfor %}
|
||||
| {% else %}
|
||||
li.btn-group.node-details-meta-list-item.video.download.disabled(
|
||||
title="Download Video")
|
||||
button.btn.btn-default.sorry(type="button")
|
||||
i.pi-download
|
||||
i.pi-angle-down.icon-dropdown-menu
|
||||
| {% endif %}
|
||||
| {% endif %}
|
||||
|
||||
| {% if node.description %}
|
||||
.node-details-description#node-description
|
||||
| {{node.description}}
|
||||
| {% endif %}
|
||||
|
||||
| {% if node.properties.license_notes %}
|
||||
.node-details-meta.license
|
||||
| {{ node.properties.license_notes }}
|
||||
| {% endif %}
|
||||
|
||||
.node-details-meta.footer
|
||||
ul.node-details-meta-list
|
||||
li.node-details-meta-list-item.status
|
||||
| {{node.properties.status}}
|
||||
|
||||
li.node-details-meta-list-item.author
|
||||
| {{ node.user.full_name }}
|
||||
|
||||
li.node-details-meta-list-item.date(title="Created {{ node._created }}")
|
||||
| {{ node._created | pretty_date }}
|
||||
| {% if (node._created | pretty_date) != (node._updated | pretty_date) %}
|
||||
span(title="Updated {{ node._updated }}") (updated {{ node._updated | pretty_date }})
|
||||
| {% endif %}
|
||||
|
||||
|
||||
#comments-container
|
||||
#comments-list-items-loading
|
||||
i.pi-spin
|
||||
|
||||
include ../../_scripts
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_scripts %}
|
||||
script(type="text/javascript").
|
||||
$(function(){
|
||||
// Generate GA pageview
|
||||
ga('send', 'pageview', location.pathname);
|
||||
|
||||
var content_type = $("li.node-details-meta-list-item.type").text();
|
||||
$("li.node-details-meta-list-item.type").text(content_type.substring(content_type.indexOf("/") + 1));
|
||||
|
||||
var container = document.getElementById("flowplayer_container");
|
||||
|
||||
flowplayer(container, {
|
||||
key: "{{config.FLOWPLAYER_KEY}}",
|
||||
embed: false,
|
||||
splash: true,
|
||||
{% if node.video_sources %}
|
||||
clip: {
|
||||
sources: {{ node.video_sources | safe }}
|
||||
}
|
||||
{% else %}
|
||||
disabled: true
|
||||
{% endif %}
|
||||
});
|
||||
|
||||
{% if not node.video_sources %}
|
||||
$('#flowplayer_container, .sorry').click(function() {
|
||||
$.get('/403', function(data) {
|
||||
$('#node-overlay').html(data).addClass('active');
|
||||
})
|
||||
});
|
||||
{% endif %}
|
||||
});
|
||||
|
||||
| {% endblock %}
|
127
src/templates/nodes/custom/asset/view_theatre_embed.jade
Normal file
127
src/templates/nodes/custom/asset/view_theatre_embed.jade
Normal file
@@ -0,0 +1,127 @@
|
||||
#theatre-media
|
||||
img(src="{{ node.picture.thumbnail('h', api=api) }}", onmousedown="return false")
|
||||
|
||||
ul#theatre-tools
|
||||
li.theatre-tool-resize(title="Toggle Normal Size")
|
||||
span
|
||||
i.pi-resize-full
|
||||
| {% if node.file and node.file.link %}
|
||||
li.download
|
||||
a(href="{{ node.file.link }}",
|
||||
title="Download the original file",
|
||||
download="{{ node.file.filename }}")
|
||||
i.pi-download
|
||||
| {% else %}
|
||||
li.download.disabled
|
||||
a(href="{{ url_for('users.login') }}",
|
||||
title="Sign in to download the original file")
|
||||
i.pi-download
|
||||
| {% endif %}
|
||||
|
||||
#theatre-info
|
||||
.theatre-info-header
|
||||
.theatre-info-title {{ node.name }}
|
||||
.theatre-info-user {{ node.user.full_name }}
|
||||
.theatre-info-date {{ node._created | pretty_date_time }}
|
||||
|
||||
ul.theatre-info-details
|
||||
li
|
||||
span Type
|
||||
span {{ node.file.content_type }}
|
||||
li
|
||||
span Dimensions
|
||||
span {{ node.file.width }} <small>x</small> {{ node.file.height }}
|
||||
li
|
||||
span Size
|
||||
span {{ node.file.length | filesizeformat }}
|
||||
| {% if node.short_link %}
|
||||
li
|
||||
span Share link
|
||||
a(href="{{ node.short_link }}") {{ node.short_link }}
|
||||
| {% endif %}
|
||||
|
||||
#comments-container
|
||||
#comments-list-items-loading
|
||||
i.pi-spin
|
||||
|
||||
include ../_scripts
|
||||
|
||||
script.
|
||||
$(function () {
|
||||
|
||||
// Load scrollbar for sidebar
|
||||
Ps.initialize(document.getElementById('theatre-info'), {suppressScrollX: true});
|
||||
|
||||
var file_width = {{ node.file.width }};
|
||||
var file_height = {{ node.file.height }};
|
||||
var theatre_media = document.getElementById('theatre-media');
|
||||
var $theatre_media = $(theatre_media);
|
||||
|
||||
function canZoom() {
|
||||
return theatre_media.scrollWidth < file_width ||
|
||||
theatre_media.scrollHeight < file_height;
|
||||
}
|
||||
|
||||
// TODO: update this whenever the screen resizes.
|
||||
if (canZoom()) $theatre_media.addClass('zoomed-out');
|
||||
|
||||
function theatreZoom() {
|
||||
var started_zoomed_in = $theatre_media.hasClass('zoomed-in');
|
||||
|
||||
// See if we need to zoom in at all. Zooming out is always allowed.
|
||||
if (!started_zoomed_in && !canZoom()) {
|
||||
$theatre_media.removeClass('zoomed-out');
|
||||
return;
|
||||
}
|
||||
|
||||
// Use add/removeClass to ensure there is always exactly one of zoomed-{in,out}.
|
||||
// If we were to use toggleClass() they could both be applied when we started
|
||||
// without zoomed-out class.
|
||||
if (started_zoomed_in) {
|
||||
$theatre_media.removeClass('zoomed-in');
|
||||
$theatre_media.addClass('zoomed-out');
|
||||
Ps.destroy(theatre_media);
|
||||
} else {
|
||||
$theatre_media.addClass('zoomed-in');
|
||||
$theatre_media.removeClass('zoomed-out');
|
||||
Ps.initialize(theatre_media);
|
||||
}
|
||||
|
||||
// Style toolbar button
|
||||
$('ul#theatre-tools li.theatre-tool-resize').toggleClass('active');
|
||||
}
|
||||
|
||||
$('ul#theatre-tools li.theatre-tool-resize').on('click', function (e) {
|
||||
theatreZoom();
|
||||
});
|
||||
|
||||
$('ul.nav.navbar-nav a.navbar-item.info').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
$('#theatre-container').toggleClass('with-info');
|
||||
});
|
||||
|
||||
$("#theatre-media img").on('click', function (e) {
|
||||
var $parent = $(this).parent();
|
||||
var mouse_x = e.pageX;
|
||||
var mouse_y = e.pageY;
|
||||
|
||||
// Compute relative position before zooming in.
|
||||
var pre_width = e.target.clientWidth;
|
||||
var rel_x = e.offsetX / pre_width;
|
||||
var rel_y = e.offsetY / e.target.clientHeight;
|
||||
|
||||
theatreZoom();
|
||||
|
||||
var post_width = e.target.clientWidth;
|
||||
|
||||
if (post_width > pre_width) {
|
||||
// We zoomed in, scroll such that the target position is under the mouse.
|
||||
var target_x = Math.round(rel_x * post_width);
|
||||
var target_y = Math.round(rel_y * e.target.clientHeight);
|
||||
|
||||
$parent
|
||||
.scrollLeft(target_x - mouse_x + e.target.parentElement.parentElement.offsetLeft)
|
||||
.scrollTop(target_y - mouse_y + e.target.parentElement.parentElement.offsetTop);
|
||||
}
|
||||
});
|
||||
});
|
130
src/templates/nodes/custom/blog/index.jade
Normal file
130
src/templates/nodes/custom/blog/index.jade
Normal file
@@ -0,0 +1,130 @@
|
||||
| {% extends 'layout.html' %}
|
||||
|
||||
| {% set title = 'blog' %}
|
||||
|
||||
| {% block page_title %}Blog{% endblock%}
|
||||
|
||||
| {% block body %}
|
||||
|
||||
.container.box
|
||||
#blog_container(class="{% if project._id == config.MAIN_PROJECT_ID %}cloud-blog{% endif %}")
|
||||
|
||||
#blog_index-container
|
||||
|
||||
| {% if project._id == config.MAIN_PROJECT_ID and project.node_type_has_method('post', 'POST', api=api) %}
|
||||
a.btn.btn-default.button-create(href="{{url_for('nodes.posts_create', project_id=project._id)}}")
|
||||
i.pi-plus
|
||||
| Create New Post
|
||||
| {% endif %}
|
||||
|
||||
| {% if posts %}
|
||||
|
||||
| {% for node in posts %}
|
||||
|
||||
| {% if loop.first %}
|
||||
| {% if node.picture %}
|
||||
.blog_index-header
|
||||
img(src="{{ node.picture.thumbnail('l', api=api) }}")
|
||||
| {% endif %}
|
||||
.blog_index-item
|
||||
a.item-title(
|
||||
href="{{ url_for_node(node=node) }}")
|
||||
| {{node.name}}
|
||||
|
||||
.item-info.
|
||||
<span title="{{node._created}}">{{node._created | pretty_date }}</span>
|
||||
{% if node._created != node._updated %}
|
||||
<span title="{{node._updated}}">(updated {{node._updated | pretty_date }})</span>
|
||||
{% endif %}
|
||||
{% if node.properties.category %}| {{node.properties.category}}{% endif %}
|
||||
| by {{node.user.full_name}}
|
||||
| <a href="{{ url_for_node(node=node) }}#comments">Leave a comment</a>
|
||||
{% if node.properties.status != 'published' %} | {{ node.properties.status}} {% endif %}
|
||||
|
||||
.item-content
|
||||
| {{node.properties.content}}
|
||||
|
||||
.item-meta
|
||||
a(href="{{ url_for_node(node=node) }}#comments") Leave a comment
|
||||
|
||||
| {% else %}
|
||||
|
||||
| {% if loop.index == 2 %}
|
||||
h4.blog_index-title Blasts from the past
|
||||
| {% endif %}
|
||||
|
||||
.blog_index-item.list
|
||||
| {% if node.picture %}
|
||||
.item-header
|
||||
img.image(src="{{ node.picture.thumbnail('s', api=api) }}")
|
||||
| {% else %}
|
||||
.item-header.nothumb
|
||||
i.pi-document-text
|
||||
| {% endif %}
|
||||
a.item-title(
|
||||
href="{{ url_for_node(node=node) }}")
|
||||
| {{node.name}}
|
||||
|
||||
.item-info.
|
||||
<span title="{{node._created}}">{{node._created | pretty_date }}</span>
|
||||
{% if node._created != node._updated %}
|
||||
<span title="{{node._updated}}">(updated {{node._updated | pretty_date }})</span>
|
||||
{% endif %}
|
||||
{% if node.properties.category %}| {{node.properties.category}}{% endif %}
|
||||
| by {{node.user.full_name}}
|
||||
{% if node.properties.status != 'published' %} | {{ node.properties.status}} {% endif %}
|
||||
|
||||
| {% endif %} {# loop #}
|
||||
|
||||
| {% endfor %} {# posts #}
|
||||
|
||||
| {% else %}
|
||||
|
||||
.blog_index-item
|
||||
.item-content No posts yet.
|
||||
|
||||
| {% endif %} {# posts #}
|
||||
|
||||
| {% if project._id != config.MAIN_PROJECT_ID %}
|
||||
#blog_index-sidebar
|
||||
.blog_project-card
|
||||
a.item-header(
|
||||
href="{{ url_for('projects.view', project_url=project.url) }}")
|
||||
|
||||
.overlay
|
||||
| {% if project.picture_header %}
|
||||
img.background(src="{{ project.picture_header.thumbnail('m', api=api) }}")
|
||||
| {% endif %}
|
||||
|
||||
a.card-thumbnail(
|
||||
href="{{ url_for('projects.view', project_url=project.url) }}")
|
||||
| {% if project.picture_square %}
|
||||
img.thumb(src="{{ project.picture_square.thumbnail('m', api=api) }}")
|
||||
| {% endif %}
|
||||
|
||||
.item-info
|
||||
|
||||
a.item-title(
|
||||
href="{{ url_for('projects.view', project_url=project.url) }}")
|
||||
| {{ project.name }}
|
||||
|
||||
| {% if project.summary %}
|
||||
p.item-description
|
||||
| {{project.summary|safe}}
|
||||
| {% endif %}
|
||||
|
||||
| {% if project.node_type_has_method('post', 'POST', api=api) %}
|
||||
.blog_project-sidebar
|
||||
a.btn.btn-default.button-create(href="{{url_for('nodes.posts_create', project_id=project._id)}}")
|
||||
| Create New Post
|
||||
| {% endif %}
|
||||
| {% endif %}
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_scripts %}
|
||||
|
||||
include ../_scripts
|
||||
script hopToTop(); // Display jump to top button
|
||||
|
||||
| {% endblock %}
|
254
src/templates/nodes/custom/group/view_embed.jade
Normal file
254
src/templates/nodes/custom/group/view_embed.jade
Normal file
@@ -0,0 +1,254 @@
|
||||
| {% block body %}
|
||||
#node-container
|
||||
|
||||
section.node-preview.group
|
||||
| {% if node.picture %}
|
||||
img.backdrop(src="{{ node.picture.thumbnail('l', api=api) }}")
|
||||
.overlay
|
||||
| {% endif %}
|
||||
.node-title#node-title
|
||||
| {{node.name}}
|
||||
|
||||
section.node-details-container.group
|
||||
.node-details-meta.preview
|
||||
ul.node-details-meta-list
|
||||
li.node-details-meta-list-item.date(title="Created {{ node._created | pretty_date }}")
|
||||
| {{ node._updated | pretty_date }}
|
||||
|
||||
li.node-details-meta-list-item.author
|
||||
| {{ node.user.full_name }}
|
||||
|
||||
| {% if node.properties.status != 'published' %}
|
||||
li.node-details-meta-list-item.status
|
||||
| {{node.properties.status}}
|
||||
| {% endif %}
|
||||
|
||||
.node-details-meta-actions
|
||||
.btn-browsetoggle(
|
||||
title="Toggle between list/grid view",
|
||||
data-toggle="tooltip",
|
||||
data-placement="top")
|
||||
i.pi-list
|
||||
|
||||
|
||||
| {% if node.description %}
|
||||
.node-details-description
|
||||
| {{node.description}}
|
||||
| {% endif %}
|
||||
|
||||
section.node-children.group
|
||||
|
||||
| {% if children %}
|
||||
| {% for child in children %}
|
||||
|
||||
| {# Browse type: List #}
|
||||
a(
|
||||
href="#",
|
||||
data-node_id="{{ child._id }}",
|
||||
class="item_icon list-node-children-item browse-list")
|
||||
.list-node-children-item-thumbnail
|
||||
|
||||
| {% if child.picture %}
|
||||
img(
|
||||
src="{{ child.picture.thumbnail('t', api=api)}} ")
|
||||
| {% endif %}
|
||||
|
||||
.list-node-children-item-thumbnail-icon
|
||||
| {# If there's a type available, otherwise show a folder icon #}
|
||||
| {% if child.properties.content_type %}
|
||||
|
||||
| {# Show an icon if there's no thumbnail #}
|
||||
| {% if not child.picture %}
|
||||
| {% if child.properties.content_type == 'image' %}
|
||||
i.dark.pi-image
|
||||
| {% elif child.properties.content_type == 'video' %}
|
||||
i.dark.pi-film-thick
|
||||
| {% elif child.properties.content_type == 'file' %}
|
||||
i.dark.pi-document
|
||||
| {% endif %}
|
||||
|
||||
| {% else %}
|
||||
| {% if child.properties.content_type == 'video' %}
|
||||
i.pi-play
|
||||
| {% endif %}
|
||||
| {% endif %}
|
||||
|
||||
| {% else %}
|
||||
| {% if not child.picture %}
|
||||
i.dark.pi-folder
|
||||
| {% endif %}
|
||||
| {% endif %}
|
||||
|
||||
| {% if child.permissions.world %}
|
||||
.list-node-children-item-ribbon
|
||||
span free
|
||||
| {% endif %}
|
||||
|
||||
.list-node-children-item-name {{ child.name }}
|
||||
|
||||
.list-node-children-item-meta
|
||||
| {% if child.properties.status != 'published' %}
|
||||
span.status {{ child.properties.status }}
|
||||
| {% endif %}
|
||||
|
||||
| {% if child.properties.content_type == 'video' %}
|
||||
span Video ·
|
||||
| {% elif child.properties.content_type == 'image' %}
|
||||
span Image ·
|
||||
| {% elif child.properties.content_type == 'file' %}
|
||||
span File ·
|
||||
| {% else %}
|
||||
| {% if child.picture %}
|
||||
span Folder ·
|
||||
| {% endif %}
|
||||
| {% endif %}
|
||||
|
||||
| {% if child._updated %}
|
||||
span(title="Updated on {{ child._created }}") {{ child._updated | pretty_date }}
|
||||
span.updated(title="Created on {{ child._updated }}") *
|
||||
| {% else %}
|
||||
span(title="Created on {{ child._created }}") {{ child._created | pretty_date }}
|
||||
| {% endif %}
|
||||
|
||||
|
||||
| {# Browse type: Icon #}
|
||||
a(href="#", data-node_id="{{ child._id }}", title="{{ child.name }}", class="item_icon list-node-children-item browse-icon")
|
||||
.list-node-children-item-thumbnail
|
||||
|
||||
| {% if child.picture %}
|
||||
img(
|
||||
src="{{ child.picture.thumbnail('b', api=api)}} ")
|
||||
| {% endif %}
|
||||
|
||||
.list-node-children-item-thumbnail-icon
|
||||
| {% if child.properties.content_type %}
|
||||
|
||||
| {% if child.properties.content_type == 'video' %}
|
||||
i.pi-play
|
||||
| {% endif %}
|
||||
|
||||
| {% else %}
|
||||
i.pi-folder
|
||||
| {% endif %}
|
||||
|
||||
| {% if child.properties.status != 'published' %}
|
||||
.list-node-children-item-status {{ child.properties.status }}
|
||||
| {% endif %}
|
||||
|
||||
| {% if child.permissions.world %}
|
||||
.list-node-children-item-ribbon
|
||||
span free
|
||||
| {% endif %}
|
||||
|
||||
.list-node-children-item-name
|
||||
|
||||
| {% if child.properties.content_type == 'video' %}
|
||||
i.pi-film-thick
|
||||
| {% elif child.properties.content_type == 'image' %}
|
||||
i.pi-image
|
||||
| {% elif child.properties.content_type == 'file' %}
|
||||
i.pi-document
|
||||
| {% else %}
|
||||
i.pi-folder
|
||||
| {% endif %}
|
||||
|
||||
span {{ child.name }}
|
||||
|
||||
| {% endfor %}
|
||||
| {% else %}
|
||||
.list-node-children-container
|
||||
.list-node-children-empty No items... yet!
|
||||
| {% endif %}
|
||||
|
||||
script.
|
||||
// Generate GA pageview
|
||||
ga('send', 'pageview', location.pathname);
|
||||
|
||||
$('a.item_icon').unbind("click")
|
||||
.click(function(e){
|
||||
e.preventDefault();
|
||||
|
||||
var nodeId = $(this).data('node_id');
|
||||
|
||||
if (ProjectUtils.projectId()) {
|
||||
// When clicking on a node preview, we load its content
|
||||
// displayNode will run asynchronously and set the bcloud_current_node_id
|
||||
// as well, but we set it manually in the next line as well, to make sure
|
||||
// that select_node on jstree works as expected, preventing the node to be
|
||||
// loaded twice.
|
||||
Cookies.set('bcloud_current_node_id', nodeId);
|
||||
displayNode(nodeId);
|
||||
|
||||
// Update tree with current selection
|
||||
var jstree = $('#project_tree').jstree(true);
|
||||
jstree.deselect_all();
|
||||
jstree.open_node('n_' + ProjectUtils.nodeId(), function() {
|
||||
jstree.select_node('n_' + nodeId);
|
||||
});
|
||||
} else {
|
||||
// If there's project_id defined, we use the full link (for search)
|
||||
window.location.replace('/nodes/' + nodeId + '/redir');
|
||||
};
|
||||
});
|
||||
|
||||
// Browse type: icon or list
|
||||
function projectBrowseTypeIcon() {
|
||||
$(".list-node-children-item.browse-list").hide();
|
||||
$(".list-node-children-item.browse-icon").show();
|
||||
$(".btn-browsetoggle").html('<i class="pi-list"></i>');
|
||||
};
|
||||
|
||||
function projectBrowseTypeList() {
|
||||
$(".list-node-children-item.browse-list").show();
|
||||
$(".list-node-children-item.browse-icon").hide();
|
||||
$(".btn-browsetoggle").html('<i class="pi-layout"></i>');
|
||||
};
|
||||
|
||||
function projectBrowseTypeCheck(){
|
||||
/* Only run if we're in a project, or search */
|
||||
if(document.getElementById("project-container") !== null || document.getElementById("search-container") !== null) {
|
||||
|
||||
var browse_type = Cookies.getJSON('bcloud_ui');
|
||||
|
||||
if (browse_type && browse_type.group_browse_type) {
|
||||
if (browse_type.group_browse_type == 'icon') {
|
||||
projectBrowseTypeIcon();
|
||||
|
||||
} else if ( browse_type.group_browse_type == 'list' ) {
|
||||
projectBrowseTypeList();
|
||||
}
|
||||
} else {
|
||||
projectBrowseTypeIcon();
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
function projectBrowseToggle(){
|
||||
|
||||
var browse_type = Cookies.getJSON('bcloud_ui');
|
||||
|
||||
if (browse_type && browse_type.group_browse_type) {
|
||||
if (browse_type.group_browse_type == 'icon') {
|
||||
projectBrowseTypeList();
|
||||
setJSONCookie('bcloud_ui', 'group_browse_type', 'list');
|
||||
} else if ( browse_type.group_browse_type == 'list' ) {
|
||||
projectBrowseTypeIcon();
|
||||
setJSONCookie('bcloud_ui', 'group_browse_type', 'icon');
|
||||
}
|
||||
} else {
|
||||
projectBrowseTypeList();
|
||||
setJSONCookie('bcloud_ui', 'group_browse_type', 'list');
|
||||
}
|
||||
}
|
||||
|
||||
$('.btn-browsetoggle').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
projectBrowseToggle();
|
||||
});
|
||||
|
||||
projectBrowseTypeCheck();
|
||||
|
||||
|
||||
include ../_scripts
|
||||
|
||||
| {% endblock %}
|
159
src/templates/nodes/custom/group_hdri/view_embed.jade
Normal file
159
src/templates/nodes/custom/group_hdri/view_embed.jade
Normal file
@@ -0,0 +1,159 @@
|
||||
| {% block body %}
|
||||
#node-container.texture
|
||||
|
||||
.texture-title#node-title
|
||||
| {{node.name}}
|
||||
|
||||
| {% if node.picture %}
|
||||
.texture-backdrop(
|
||||
style="background-image: url({{ node.picture.thumbnail('m', api=api) }})")
|
||||
| {% endif %}
|
||||
|
||||
| {% if children %}
|
||||
section.node-row.texture-info
|
||||
span.texture-info-files {{ children|length }} item{% if children|length != 1 %}s{% endif %}
|
||||
| {% endif %}
|
||||
|
||||
section.node-children.group.texture
|
||||
|
||||
| {% if children %}
|
||||
| {% for child in children %}
|
||||
| {% if child.properties.status == 'published' %}
|
||||
|
||||
a.list-node-children-container(
|
||||
href="#",
|
||||
data-node_id="{{ child._id }}",
|
||||
class="item_icon {{child.node_type}} {% if child.picture %}thumbnail{% endif %}")
|
||||
.list-node-children-item-preview
|
||||
span.texture-name {{child.name}}
|
||||
| {% if child.picture %}
|
||||
img.texture-preview(
|
||||
src="",
|
||||
data-preview="{{ child.picture.thumbnail('m', api=api)}}",
|
||||
alt='{{child.name}}')
|
||||
| {% endif %}
|
||||
.list-node-children-item(class="{{child.node_type}}")
|
||||
.list-node-children-item-thumbnail
|
||||
| {% if child.picture %}
|
||||
img.texture-thumbnail(src="{{ child.picture.thumbnail('b', api=api)}}")
|
||||
| {% else %}
|
||||
.list-node-children-item-thumbnail-icon
|
||||
| {% if child.node_type == 'group_hdri' %}
|
||||
i.pi-folder-texture
|
||||
| {% else %}
|
||||
i.pi-texture
|
||||
| {% endif %}
|
||||
| {% endif %}
|
||||
|
||||
| {% if child.properties.status != 'published' %}
|
||||
.list-node-children-item-status {{ child.properties.status }}
|
||||
| {% endif %}
|
||||
|
||||
| {% if child.permissions.world %}
|
||||
.list-node-children-item-ribbon
|
||||
span free
|
||||
| {% endif %}
|
||||
|
||||
| {% if child.node_type == 'hdri' %}
|
||||
.list-node-children-item-name
|
||||
span.sizes {{ child.name }}
|
||||
| {% if child.properties.files %}
|
||||
span.variations
|
||||
| {% if child.properties.files|length > 6 %}
|
||||
span {{ child.properties.files|length }} resolutions
|
||||
span from {{ child.properties.files[0].resolution }}
|
||||
span to {{ child.properties.files[-1].resolution }}
|
||||
| {% else %}
|
||||
| {% for f in child.properties.files %}
|
||||
span {{ f.resolution }}
|
||||
| {% endfor %}
|
||||
| {% endif %}
|
||||
| {% endif %}
|
||||
| {% endif %}
|
||||
|
||||
| {% if child.node_type == 'group_hdri' %}
|
||||
.list-node-children-item-name
|
||||
i.pi-folder-texture
|
||||
span {{ child.name }}
|
||||
| {% endif %}
|
||||
|
||||
| {% endif %}
|
||||
| {% endfor %}
|
||||
| {% else %}
|
||||
.list-node-children-container
|
||||
.list-node-children-empty No textures... yet!
|
||||
| {% endif %}
|
||||
|
||||
script.
|
||||
// Generate GA pageview
|
||||
ga('send', 'pageview', location.href);
|
||||
|
||||
// Display texture preview on mouse hover
|
||||
$('a.list-node-children-container.texture.thumbnail').hover(
|
||||
function(){
|
||||
|
||||
var thumbnail = $(this);
|
||||
|
||||
var src = thumbnail.find('.texture-thumbnail').attr('src');
|
||||
var src_xl = thumbnail.find('.texture-preview').data('preview');
|
||||
|
||||
// Load the bigger preview
|
||||
var preview_img = thumbnail.find('.texture-preview');
|
||||
preview_img.attr('src', src_xl);
|
||||
|
||||
|
||||
if (preview_img) {
|
||||
|
||||
preview_img.load(function() {
|
||||
|
||||
var preview = thumbnail.find('.list-node-children-item-preview');
|
||||
|
||||
// Positioning stuff
|
||||
var offset = thumbnail.offset();
|
||||
var offset_min_x = $('.node-children').width() - preview.width();
|
||||
var offset_min_y = $('.node-children').height() - preview.height();
|
||||
|
||||
if (preview && offset.top > 300) {
|
||||
$(preview).css({'top': (preview.height() * (-1))});
|
||||
};
|
||||
|
||||
if (offset.left > offset_min_x) {
|
||||
$(preview).css({'right': 0});
|
||||
};
|
||||
|
||||
$(preview).addClass('active');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
function(){
|
||||
$('.list-node-children-item-preview').removeClass('active');
|
||||
});
|
||||
|
||||
// hide preview on mouse hover itself
|
||||
$('.list-node-children-item-preview').hover(function(){
|
||||
$(this).removeClass('active');
|
||||
});
|
||||
|
||||
|
||||
$('a.item_icon')
|
||||
.unbind("click")
|
||||
.click(function(e){
|
||||
e.preventDefault();
|
||||
// When clicking on a node preview, we load its content
|
||||
var nodeId = $(this).data('node_id');
|
||||
// displayNode will run asynchronously and set the bcloud_current_node_id
|
||||
// as well, but we set it manually in the next line as well, to make sure
|
||||
// that select_node on jstree works as expected, preventing the node to be
|
||||
// loaded twice.
|
||||
Cookies.set('bcloud_current_node_id', nodeId);
|
||||
displayNode(nodeId);
|
||||
// Update tree with current selection
|
||||
$('#project_tree').jstree('select_node', 'n_' + nodeId);
|
||||
});
|
||||
|
||||
include ../_scripts
|
||||
|
||||
| {% endblock %}
|
||||
|
190
src/templates/nodes/custom/group_texture/view_embed.jade
Normal file
190
src/templates/nodes/custom/group_texture/view_embed.jade
Normal file
@@ -0,0 +1,190 @@
|
||||
| {% block body %}
|
||||
#node-container.texture
|
||||
|
||||
.texture-title#node-title
|
||||
| {{node.name}}
|
||||
|
||||
| {% if node.picture %}
|
||||
.texture-backdrop(
|
||||
style="background-image: url({{ node.picture.thumbnail('m', api=api) }})")
|
||||
| {% endif %}
|
||||
|
||||
| {% if children %}
|
||||
section.node-row.texture-info
|
||||
span.texture-info-files {{ children|length }} item{% if children|length != 1 %}s{% endif %}
|
||||
| {% endif %}
|
||||
|
||||
section.node-children.group.texture
|
||||
|
||||
| {% if children %}
|
||||
| {% for child in children %}
|
||||
| {% if child.properties.status == 'published' %}
|
||||
|
||||
a.list-node-children-container(
|
||||
href="#",
|
||||
data-node_id="{{ child._id }}",
|
||||
class="item_icon {{child.node_type}} {% if child.picture %}thumbnail{% endif %}")
|
||||
.list-node-children-item-preview
|
||||
span.texture-name {{child.name}}
|
||||
| {% if child.picture %}
|
||||
img.texture-preview(
|
||||
src="",
|
||||
data-preview="{{ child.picture.thumbnail('m', api=api)}}",
|
||||
alt='{{child.name}}')
|
||||
| {% endif %}
|
||||
.list-node-children-item(class="{{child.node_type}}")
|
||||
.list-node-children-item-thumbnail
|
||||
| {% if child.picture %}
|
||||
img.texture-thumbnail(src="{{ child.picture.thumbnail('b', api=api)}}")
|
||||
| {% else %}
|
||||
.list-node-children-item-thumbnail-icon
|
||||
| {% if child.node_type == 'group_texture' %}
|
||||
i.pi-folder-texture
|
||||
| {% else %}
|
||||
i.pi-texture
|
||||
| {% endif %}
|
||||
| {% endif %}
|
||||
|
||||
| {% if child.properties.status != 'published' %}
|
||||
.list-node-children-item-status {{ child.properties.status }}
|
||||
| {% endif %}
|
||||
|
||||
| {% if child.permissions.world %}
|
||||
.list-node-children-item-ribbon
|
||||
span free
|
||||
| {% endif %}
|
||||
|
||||
| {% if child.node_type == 'texture' %}
|
||||
.list-node-children-item-name
|
||||
| {% if child.picture.width %}
|
||||
span.sizes
|
||||
| {{ child.picture.width }}
|
||||
small x
|
||||
| {{ child.picture.height }}
|
||||
| {% else %}
|
||||
span.sizes {{ child.name }}
|
||||
| {% endif %}
|
||||
span.icons
|
||||
| {% if child.properties.is_tileable %}
|
||||
i.pi-puzzle(title="Tileable", data-toggle="tooltip", data-placement="bottom", data-delay=0)
|
||||
| {% endif %}
|
||||
| {% if child.properties.files %}
|
||||
span.variations
|
||||
| {% for f in child.properties.files %}
|
||||
|
||||
| {% if loop.last and loop.index > 5 %}
|
||||
span.more +{{ loop.length - 5 }} more
|
||||
| {% elif loop.index <= 5 %}
|
||||
|
||||
| {% if f.map_type == 'color' %}
|
||||
span Color
|
||||
| {% elif f.map_type == 'bump' %}
|
||||
span Bump
|
||||
| {% elif f.map_type == 'specular' %}
|
||||
span Specular
|
||||
| {% elif f.map_type == 'normal' %}
|
||||
span Normal Map
|
||||
| {% elif f.map_type == 'translucency' %}
|
||||
span Translucency
|
||||
| {% elif f.map_type == 'emission' %}
|
||||
span Emission
|
||||
| {% elif f.map_type == 'alpha' %}
|
||||
span Alpha
|
||||
| {% elif f.map_type == 'id' %}
|
||||
span ID Map
|
||||
| {% else %}
|
||||
span {{ f.map_type }}
|
||||
| {% endif %}
|
||||
|
||||
| {% endif %}
|
||||
|
||||
| {% endfor %}
|
||||
| {% endif %}
|
||||
| {% endif %}
|
||||
|
||||
| {% if child.node_type == 'group_texture' %}
|
||||
.list-node-children-item-name
|
||||
i.pi-folder-texture
|
||||
span {{ child.name }}
|
||||
| {% endif %}
|
||||
|
||||
| {% endif %}
|
||||
| {% endfor %}
|
||||
| {% else %}
|
||||
.list-node-children-container
|
||||
.list-node-children-empty No textures... yet!
|
||||
| {% endif %}
|
||||
|
||||
script.
|
||||
// Generate GA pageview
|
||||
ga('send', 'pageview', location.href);
|
||||
|
||||
// Display texture preview on mouse hover
|
||||
$('a.list-node-children-container.texture.thumbnail').hover(
|
||||
function(){
|
||||
|
||||
var thumbnail = $(this);
|
||||
|
||||
var src = thumbnail.find('.texture-thumbnail').attr('src');
|
||||
var src_xl = thumbnail.find('.texture-preview').data('preview');
|
||||
|
||||
// Load the bigger preview
|
||||
var preview_img = thumbnail.find('.texture-preview');
|
||||
preview_img.attr('src', src_xl);
|
||||
|
||||
|
||||
if (preview_img) {
|
||||
|
||||
preview_img.load(function() {
|
||||
|
||||
var preview = thumbnail.find('.list-node-children-item-preview');
|
||||
|
||||
// Positioning stuff
|
||||
var offset = thumbnail.offset();
|
||||
var offset_min_x = $('.node-children').width() - preview.width();
|
||||
var offset_min_y = $('.node-children').height() - preview.height();
|
||||
|
||||
if (preview && offset.top > 300) {
|
||||
$(preview).css({'top': (preview.height() * (-1))});
|
||||
};
|
||||
|
||||
if (offset.left > offset_min_x) {
|
||||
$(preview).css({'right': 0});
|
||||
};
|
||||
|
||||
$(preview).addClass('active');
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
function(){
|
||||
$('.list-node-children-item-preview').removeClass('active');
|
||||
});
|
||||
|
||||
// hide preview on mouse hover itself
|
||||
$('.list-node-children-item-preview').hover(function(){
|
||||
$(this).removeClass('active');
|
||||
});
|
||||
|
||||
|
||||
$('a.item_icon')
|
||||
.unbind("click")
|
||||
.click(function(e){
|
||||
e.preventDefault();
|
||||
// When clicking on a node preview, we load its content
|
||||
var nodeId = $(this).data('node_id');
|
||||
// displayNode will run asynchronously and set the bcloud_current_node_id
|
||||
// as well, but we set it manually in the next line as well, to make sure
|
||||
// that select_node on jstree works as expected, preventing the node to be
|
||||
// loaded twice.
|
||||
Cookies.set('bcloud_current_node_id', nodeId);
|
||||
displayNode(nodeId);
|
||||
// Update tree with current selection
|
||||
$('#project_tree').jstree('select_node', 'n_' + nodeId);
|
||||
});
|
||||
|
||||
include ../_scripts
|
||||
|
||||
| {% endblock %}
|
||||
|
133
src/templates/nodes/custom/hdri/view_embed.jade
Normal file
133
src/templates/nodes/custom/hdri/view_embed.jade
Normal file
@@ -0,0 +1,133 @@
|
||||
| {% block body %}
|
||||
|
||||
#node-container.texture
|
||||
#node-overlay
|
||||
section.node-preview
|
||||
| {% if node.picture %}
|
||||
iframe(
|
||||
width='100%',
|
||||
height='450px',
|
||||
scrolling='no',
|
||||
frameborder='0',
|
||||
allowfullscreen='',
|
||||
src="{{url_for('main.vrview', preview=node.picture.thumbnail('l', api=api), image=node.picture.thumbnail('h', api=api), is_stereo='false')}}")
|
||||
| {% endif %}
|
||||
|
||||
section.node-details-container
|
||||
|
||||
.node-details-header
|
||||
.node-title#node-title
|
||||
| {{node.name}}
|
||||
|
||||
.node-details-meta.header
|
||||
ul.node-details-meta-list
|
||||
| {% if node.permissions.world %}
|
||||
li.node-details-meta-list-item.access.public(
|
||||
data-toggle="tooltip",
|
||||
data-placement="bottom",
|
||||
title="Anybody can download. Share it!")
|
||||
i.pi-lock-open
|
||||
span Public
|
||||
| {% endif %}
|
||||
|
||||
| {% if node.properties.license_type %}
|
||||
| {% if node.properties.license_notes %}
|
||||
li.node-details-meta-list-item.video.license(
|
||||
id="asset-license",
|
||||
data-toggle="popover",
|
||||
data-placement="left",
|
||||
data-trigger="hover",
|
||||
data-content="{{ node.properties.license_notes }}",
|
||||
title="{{ node.properties.license_type }}")
|
||||
|
||||
i(class="pi-license-{{ node.properties.license_type }}")
|
||||
| {% else %}
|
||||
li.node-details-meta-list-item.video.license(
|
||||
id="asset-license",
|
||||
data-toggle="tooltip",
|
||||
data-placement="bottom",
|
||||
title="{{ node.properties.license_type }}")
|
||||
|
||||
i(class="pi-license-{{ node.properties.license_type }}")
|
||||
| {% endif %}
|
||||
| {% endif %}
|
||||
|
||||
| {% if node.properties.files %}
|
||||
li.btn-group.node-details-meta-list-item.video.download(
|
||||
title="Download HDRI")
|
||||
button.btn.btn-default.dropdown-toggle(
|
||||
type="button",
|
||||
data-toggle="dropdown",
|
||||
aria-haspopup="true",
|
||||
aria-expanded="false")
|
||||
i.pi-download
|
||||
i.pi-angle-down.icon-dropdown-menu
|
||||
|
||||
ul.dropdown-menu
|
||||
| {% for var in node.properties.files %}
|
||||
li
|
||||
a(href="{{ var.file.link }}",
|
||||
title="Download this HDRi format",
|
||||
download)
|
||||
span.length {{ var.file.length | filesizeformat }}
|
||||
|
||||
span.format {{ var.file.format }}
|
||||
span.size {{ var.resolution }}
|
||||
|
||||
| {% endfor %}
|
||||
| {% else %}
|
||||
li.btn-group.node-details-meta-list-item.video.download.disabled(
|
||||
title="Download HDRi")
|
||||
button.btn.btn-default.sorry(type="button")
|
||||
i.pi-download
|
||||
i.pi-angle-down.icon-dropdown-menu
|
||||
| {% endif %}
|
||||
|
||||
| {% if node.description %}
|
||||
.node-details-description#node-description
|
||||
| {{node.description}}
|
||||
| {% endif %}
|
||||
|
||||
| {% if node.properties.license_notes %}
|
||||
.node-details-meta.license
|
||||
| {{ node.properties.license_notes }}
|
||||
| {% endif %}
|
||||
|
||||
.node-details-meta.footer
|
||||
ul.node-details-meta-list
|
||||
li.node-details-meta-list-item.status
|
||||
| {{node.properties.status}}
|
||||
|
||||
li.node-details-meta-list-item.author
|
||||
| {{ node.user.full_name }}
|
||||
|
||||
li.node-details-meta-list-item.date(title="Created {{ node._created }}")
|
||||
| {{ node._created | pretty_date }}
|
||||
| {% if (node._created | pretty_date) != (node._updated | pretty_date) %}
|
||||
span(title="Updated {{ node._updated }}") (updated {{ node._updated | pretty_date }})
|
||||
| {% endif %}
|
||||
|
||||
|
||||
include ../_scripts
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_scripts %}
|
||||
script.
|
||||
$('#asset-license').popover();
|
||||
// Generate GA pageview
|
||||
ga('send', 'pageview', location.pathname);
|
||||
|
||||
|
||||
$('.sorry').click(function() {
|
||||
$.get('/403', function(data) {
|
||||
$('#node-overlay').html(data).show().addClass('active');
|
||||
})
|
||||
});
|
||||
|
||||
$('#node-overlay').click(function(){
|
||||
$(this).removeClass('active').hide().html();
|
||||
});
|
||||
|
||||
| {% endblock %}
|
||||
|
175
src/templates/nodes/custom/post/create.jade
Normal file
175
src/templates/nodes/custom/post/create.jade
Normal file
@@ -0,0 +1,175 @@
|
||||
| {% extends 'layout.html' %}
|
||||
|
||||
| {% set title = 'blog' %}
|
||||
|
||||
| {% block page_title %}New {{ node_type.name }}{% endblock %}
|
||||
|
||||
| {% block body %}
|
||||
.container.box
|
||||
form(
|
||||
method='POST',
|
||||
action="{{url_for('nodes.posts_create', project_id=project._id)}}")
|
||||
|
||||
#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
|
||||
| {% if project._id != config.MAIN_PROJECT_ID %}
|
||||
.blog_project-card
|
||||
a.item-header(
|
||||
href="{{ url_for('projects.view', project_url=project.url) }}")
|
||||
|
||||
.overlay
|
||||
| {% if project.picture_header %}
|
||||
img.background(src="{{ project.picture_header.thumbnail('m', api=api) }}")
|
||||
| {% endif %}
|
||||
|
||||
a.card-thumbnail(
|
||||
href="{{ url_for('projects.view', project_url=project.url) }}")
|
||||
| {% if project.picture_square %}
|
||||
img.thumb(src="{{ project.picture_square.thumbnail('m', api=api) }}")
|
||||
| {% endif %}
|
||||
|
||||
.item-info
|
||||
|
||||
a.item-title(
|
||||
href="{{ url_for('projects.view', project_url=project.url) }}")
|
||||
| {{ project.name }}
|
||||
|
||||
| {% endif %}
|
||||
|
||||
.blog_project-sidebar
|
||||
#blog_post-edit-form
|
||||
| {% for field in form %}
|
||||
| {% if field.name in ['picture', 'status'] %}
|
||||
|
||||
.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 %}
|
||||
| {% endfor %}
|
||||
|
||||
input.btn.btn-default.button-create(type='submit', value='Create {{ node_type.name }}')
|
||||
|
||||
a.btn.btn-default.button-back(href="{{ url_for('projects.view', project_url=project.url) }}blog")
|
||||
| Back to Blog
|
||||
|
||||
#blog_post-create-container
|
||||
#blog_post-edit-title
|
||||
| Create {{ node_type.name }} on {{ project.name }}
|
||||
|
||||
#blog_post-edit-form
|
||||
| {% for field in form %}
|
||||
| {% if field.name == 'csrf_token' %}
|
||||
| {{ field }}
|
||||
| {% else %}
|
||||
| {% if field.type == 'HiddenField' %}
|
||||
| {{ field }}
|
||||
| {% else %}
|
||||
|
||||
| {% if field.name not in ['description', 'picture', 'category', 'status'] %}
|
||||
|
||||
.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 %}
|
||||
| {% endif %}
|
||||
| {% endfor %}
|
||||
|
||||
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_scripts %}
|
||||
script(type="text/javascript").
|
||||
|
||||
function FormatForUrl(str) {
|
||||
return str.replace(/_/g, '-')
|
||||
.replace(/ /g, '-')
|
||||
.replace(/:/g, '-')
|
||||
.replace(/\\/g, '-')
|
||||
.replace(/\//g, '-')
|
||||
.replace(/[^a-zA-Z0-9\-]+/g, '')
|
||||
.replace(/-{2,}/g, '-')
|
||||
.toLowerCase();
|
||||
};
|
||||
|
||||
var convert = new Markdown.getSanitizingConverter().makeHtml;
|
||||
|
||||
/* Build the markdown preview when typing in textarea */
|
||||
$(function() {
|
||||
|
||||
var $textarea = $('.form-group.content 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');
|
||||
});
|
||||
|
||||
$(function() {
|
||||
var $name_input = $('.form-group.name input');
|
||||
$name_input.keyup(function() {
|
||||
$('#url').val(FormatForUrl($name_input.val()));
|
||||
}).trigger('keyup');
|
||||
});
|
||||
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_navigation %}
|
||||
| {% endblock %}
|
||||
| {% block footer %}
|
||||
| {% endblock %}
|
168
src/templates/nodes/custom/post/edit.jade
Normal file
168
src/templates/nodes/custom/post/edit.jade
Normal file
@@ -0,0 +1,168 @@
|
||||
| {% extends 'layout.html' %}
|
||||
|
||||
| {% set title = 'blog' %}
|
||||
|
||||
| {% block page_title %}New {{ node_type.name }}{% endblock %}
|
||||
|
||||
| {% block body %}
|
||||
|
||||
.container.box
|
||||
form(
|
||||
method='POST',
|
||||
action="{{url_for('nodes.posts_edit', post_id=post._id)}}")
|
||||
|
||||
#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
|
||||
| {% if project._id != config.MAIN_PROJECT_ID %}
|
||||
.blog_project-card
|
||||
a.item-header(
|
||||
href="{{ url_for('projects.view', project_url=project.url) }}")
|
||||
|
||||
.overlay
|
||||
| {% if project.picture_header %}
|
||||
img.background(src="{{ project.picture_header.thumbnail('m', api=api) }}")
|
||||
| {% endif %}
|
||||
|
||||
a.card-thumbnail(
|
||||
href="{{ url_for('projects.view', project_url=project.url) }}")
|
||||
| {% if project.picture_square %}
|
||||
img.thumb(src="{{ project.picture_square.thumbnail('m', api=api) }}")
|
||||
| {% endif %}
|
||||
|
||||
.item-info
|
||||
|
||||
a.item-title(
|
||||
href="{{ url_for('projects.view', project_url=project.url) }}")
|
||||
| {{ project.name }}
|
||||
|
||||
| {% endif %}
|
||||
|
||||
.blog_project-sidebar
|
||||
#blog_post-edit-form
|
||||
| {% for field in form %}
|
||||
| {% if field.name in ['picture', 'status'] %}
|
||||
|
||||
.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 %}
|
||||
| {% endfor %}
|
||||
|
||||
button.btn.btn-default.button-create(type='submit')
|
||||
i.pi-check
|
||||
| Update {{ node_type.name }}
|
||||
|
||||
a.btn.btn-default.button-back(href="{{ url_for_node(node=post) }}")
|
||||
i.pi-angle-left
|
||||
| Back to Post
|
||||
|
||||
a.btn.btn-default.button-back(href="{{ url_for('projects.view', project_url=project.url) }}blog")
|
||||
| Go to Blog
|
||||
|
||||
#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 %}
|
||||
|
||||
| {% if field.name not in ['description', 'picture', 'category', 'status'] %}
|
||||
|
||||
.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 %}
|
||||
| {% endif %}
|
||||
| {% endfor %}
|
||||
|
||||
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_scripts %}
|
||||
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.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").
|
||||
var convert = new Markdown.getSanitizingConverter().makeHtml;
|
||||
ProjectUtils.setProjectAttributes({projectId: "{{project._id}}"});
|
||||
|
||||
/* Build the markdown preview when typing in textarea */
|
||||
$(function() {
|
||||
|
||||
var $textarea = $('.form-group.content 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');
|
||||
});
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_navigation %}
|
||||
| {% endblock %}
|
||||
| {% block footer %}
|
||||
| {% endblock %}
|
4
src/templates/nodes/custom/post/view.jade
Normal file
4
src/templates/nodes/custom/post/view.jade
Normal file
@@ -0,0 +1,4 @@
|
||||
| {% extends 'layout.html' %}
|
||||
| {% block page_title %}{{node.name}} - Blog{% endblock%}
|
||||
|
||||
include view_embed
|
128
src/templates/nodes/custom/post/view_embed.jade
Normal file
128
src/templates/nodes/custom/post/view_embed.jade
Normal file
@@ -0,0 +1,128 @@
|
||||
| {% block og %}
|
||||
|
||||
| {% set title = 'blog' %}
|
||||
|
||||
| {% if project %}
|
||||
meta(property="og:title", content="{{ node.name }}{% if project._id == config.MAIN_PROJECT_ID %} — Blender Cloud Blog{% else%} - {{ project.name }} — Blender Cloud{% endif %}")
|
||||
| {% endif %}
|
||||
| {% if project and project.properties.picture_header %}
|
||||
meta(property="og:image", content="{{ project.properties.picture_header.thumbnail('l', api=api) }}")
|
||||
| {% elif node and node.picture %}
|
||||
meta(property="og:image", content="{{ node.picture.thumbnail('l', api=api) }}")
|
||||
| {% endif %}
|
||||
meta(property="og:description", content="{{ node.properties.content }}")
|
||||
meta(property="og:type", content="article")
|
||||
meta(property="article:type", content="{{node.user.full_name}}")
|
||||
meta(property="article:published_time", content="{{node._created | pretty_date }}")
|
||||
meta(property="og:see_also", content="https://cloud.blender.org/blog")
|
||||
meta(property="og:url", content="https://cloud.blender.org{{ url_for_node(node=node) }}")
|
||||
| {% endblock %}
|
||||
|
||||
| {% block tw %}
|
||||
meta(name="twitter:card", content="summary_large_image")
|
||||
| {% if project._id == config.MAIN_PROJECT_ID %}
|
||||
meta(property="twitter:title", content="{{ node.name }} — Blender Cloud Blog")
|
||||
| {% else %}
|
||||
meta(property="twitter:title", content="{{ node.name }} - {{ project.name }} Blog — Blender Cloud")
|
||||
| {% endif %}
|
||||
| {% if project and project.properties.picture_header %}
|
||||
meta(name="twitter:image", content="{{ project.properties.picture_header.thumbnail('l', api=api) }}")
|
||||
| {% elif node and node.picture %}
|
||||
meta(name="twitter:image", content="{{ node.picture.thumbnail('l', api=api) }}")
|
||||
| {% else %}
|
||||
meta(name="twitter:image", content="{{ url_for('static', filename='assets/img/backgrounds/background_caminandes_3_02.jpg')}}")
|
||||
| {% endif %}
|
||||
meta(name="twitter:description", content="{{ node.properties.content }}")
|
||||
| {% endblock %}
|
||||
|
||||
| {% block body %}
|
||||
|
||||
.container.box
|
||||
#blog_container(class="{% if project._id == config.MAIN_PROJECT_ID %}cloud-blog{% endif %}")
|
||||
|
||||
#blog_post-container
|
||||
| {% if project._id == config.MAIN_PROJECT_ID %}
|
||||
a.btn.btn-default.button-back(href="{{ url_for('projects.view', project_url=project.url) }}blog")
|
||||
| Back to Blog
|
||||
|
||||
| {% if node.has_method('PUT') %}
|
||||
a.btn.btn-default.button-edit(href="{{url_for('nodes.posts_edit', post_id=node._id)}}")
|
||||
i.pi-edit
|
||||
| Edit Post
|
||||
| {% endif %}
|
||||
|
||||
.clearfix
|
||||
| {% endif %}
|
||||
|
||||
| {% if node.picture %}
|
||||
.blog_index-header
|
||||
img(src="{{ node.picture.thumbnail('l', api=api) }}")
|
||||
| {% endif %}
|
||||
.blog_index-item
|
||||
|
||||
.item-title
|
||||
| {{node.name}}
|
||||
|
||||
.item-info.
|
||||
<span title="{{node._created}}">{{node._created | pretty_date }}</span>
|
||||
{% if node._created != node._updated %}
|
||||
<span title="{{node._updated}}">(updated {{node._updated | pretty_date }})</span>
|
||||
{% endif %}
|
||||
{% if node.properties.category %}| {{node.properties.category}}{% endif %}
|
||||
| by {{node.user.full_name}}
|
||||
|
||||
.item-content
|
||||
| {{ node.properties.content }}
|
||||
|
||||
|
||||
#comments-container
|
||||
#comments-list-items-loading
|
||||
i.pi-spin
|
||||
|
||||
| {% if project._id != config.MAIN_PROJECT_ID %}
|
||||
#blog_index-sidebar
|
||||
.blog_project-card
|
||||
a.item-header(
|
||||
href="{{ url_for('projects.view', project_url=project.url) }}")
|
||||
|
||||
.overlay
|
||||
| {% if project.picture_header %}
|
||||
img.background(src="{{ project.picture_header.thumbnail('m', api=api) }}")
|
||||
| {% endif %}
|
||||
|
||||
a.card-thumbnail(
|
||||
href="{{ url_for('projects.view', project_url=project.url) }}")
|
||||
| {% if project.picture_square %}
|
||||
img.thumb(src="{{ project.picture_square.thumbnail('m', api=api) }}")
|
||||
| {% endif %}
|
||||
|
||||
.item-info
|
||||
|
||||
a.item-title(
|
||||
href="{{ url_for('projects.view', project_url=project.url) }}")
|
||||
| {{ project.name }}
|
||||
|
||||
| {% if project.summary %}
|
||||
p.item-description
|
||||
| {{project.summary|safe}}
|
||||
| {% endif %}
|
||||
.blog_project-sidebar
|
||||
| {% if node.has_method('PUT') %}
|
||||
a.btn.btn-default.button-create(href="{{url_for('nodes.posts_edit', post_id=node._id)}}")
|
||||
| Edit Post
|
||||
| {% endif %}
|
||||
|
||||
a.btn.btn-default.button-back(href="{{ url_for('projects.view', project_url=project.url) }}blog")
|
||||
| Back to Blog
|
||||
| {% endif %}
|
||||
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
|
||||
| {% block footer_scripts %}
|
||||
|
||||
include ../_scripts
|
||||
script hopToTop(); // Display jump to top button
|
||||
|
||||
| {% endblock %}
|
53
src/templates/nodes/custom/storage/index_embed.jade
Normal file
53
src/templates/nodes/custom/storage/index_embed.jade
Normal file
@@ -0,0 +1,53 @@
|
||||
| {% block body %}
|
||||
|
||||
#node-container
|
||||
|
||||
section.node-details-container.storage
|
||||
|
||||
.node-details-header
|
||||
.node-title
|
||||
| {{node.name}}
|
||||
|
||||
|
||||
section.node-children.storage
|
||||
|
||||
| {% if node.children %}
|
||||
| {% for child in node.children %}
|
||||
|
||||
a(href="#", data-node_id="{{ node._id }}" data-path="{{ child['path'] }}", title="{{ child['name'] }}", class="item_icon")
|
||||
.list-node-children-item
|
||||
.list-node-children-item-thumbnail
|
||||
|
||||
.list-node-children-item-thumbnail-icon
|
||||
| {% if child['content_type'] == 'video' %}
|
||||
i.pi-film
|
||||
| {% elif child['content_type'] == 'image' %}
|
||||
i.pi-image
|
||||
| {% elif child['content_type'] == 'file' %}
|
||||
i.pi-document
|
||||
| {% elif child['content_type'] == 'binary' %}
|
||||
i.pi-file-archive
|
||||
| {% else %}
|
||||
i.pi-folder
|
||||
| {% endif %}
|
||||
|
||||
.list-node-children-item-name
|
||||
|
||||
span {{ child['name'] }}
|
||||
|
||||
| {% endfor %}
|
||||
| {% endif %}
|
||||
|
||||
script.
|
||||
$('a.item_icon').click(function(e){
|
||||
// When clicking on a node preview, we load its content
|
||||
e.preventDefault;
|
||||
var nodeId = $(this).data('node_id');
|
||||
var path = $(this).data('path');
|
||||
displayStorage(nodeId, path);
|
||||
// Update tree with current selection
|
||||
//$('#project_tree').jstree('select_node', 'n_' + nodeId);
|
||||
});
|
||||
|
||||
| {% endblock %}
|
||||
|
33
src/templates/nodes/custom/storage/view_embed.jade
Normal file
33
src/templates/nodes/custom/storage/view_embed.jade
Normal file
@@ -0,0 +1,33 @@
|
||||
| {% block body %}
|
||||
|
||||
#node-container
|
||||
|
||||
section.node-details-container.storage
|
||||
|
||||
.node-details-header
|
||||
.node-title
|
||||
| {{node.name}}
|
||||
|
||||
//- .node-details-description
|
||||
//- | {{node.description}}
|
||||
|
||||
.node-details-meta
|
||||
|
||||
ul.node-details-meta-list
|
||||
li.node-details-meta-list-item.status
|
||||
| {{node.status}}
|
||||
|
||||
li.node-details-meta-list-item.date(title="Created {{ node._created | pretty_date }}")
|
||||
| {{ node._updated | pretty_date }}
|
||||
|
||||
li.node-details-meta-list-item.file.length
|
||||
| {{ node.length | filesizeformat }}
|
||||
|
||||
li.node-details-meta-list-item.file.download
|
||||
a(href="{% if node.has_method('GET') %}{{ node.download_link }}{% else %}{{ url_for('users.login') }}{% endif %}")
|
||||
button.btn.btn-default(type="button")
|
||||
| Download
|
||||
|
||||
|
||||
| {% endblock %}
|
||||
|
195
src/templates/nodes/custom/texture/view_embed.jade
Normal file
195
src/templates/nodes/custom/texture/view_embed.jade
Normal file
@@ -0,0 +1,195 @@
|
||||
| {% block body %}
|
||||
|
||||
#node-container.texture
|
||||
#node-overlay
|
||||
|
||||
.texture-title#node-title
|
||||
| {{node.name}}
|
||||
|
||||
| {% if node.properties.license_type %}
|
||||
| {% if node.properties.license_notes %}
|
||||
.texture-license(
|
||||
id="asset-license",
|
||||
data-toggle="popover",
|
||||
data-placement="left",
|
||||
data-trigger="hover",
|
||||
data-content="{{ node.properties.license_notes }}",
|
||||
title="{{ node.properties.license_type }}")
|
||||
|
||||
i(class="pi-license-{{ node.properties.license_type }}")
|
||||
| {% else %}
|
||||
.texture-license(
|
||||
id="asset-license",
|
||||
data-toggle="tooltip",
|
||||
data-placement="bottom",
|
||||
title="{{ node.properties.license_type }}")
|
||||
|
||||
i(class="pi-license-{{ node.properties.license_type }}")
|
||||
| {% endif %}
|
||||
| {% endif %}
|
||||
|
||||
|
||||
section.node-row.texture-info
|
||||
| {% if node.properties.files %}
|
||||
span.texture-info-files
|
||||
i.pi-texture
|
||||
| {{ node.properties.files|length }} map{% if node.properties.files|length != 1 %}s{% endif %}
|
||||
| {% endif %}
|
||||
span.texture-info-seamless
|
||||
i.pi-puzzle
|
||||
| {% if not node.properties.is_tileable %}Not {% endif %}Seamless
|
||||
|
||||
| {% if node.properties.files %}
|
||||
| {% for f in node.properties.files %}
|
||||
section.node-row.texture-map
|
||||
section.node-preview.texture
|
||||
img.node-preview-thumbnail(
|
||||
src="{{ f.file.thumbnail('m', api=api) }}",
|
||||
data-preview="{{ f.file.thumbnail('l', api=api) }}",
|
||||
data-aspect_ratio="{{ node.properties.aspect_ratio }}")
|
||||
|
||||
| {% if f.map_type == 'color' %}
|
||||
| {% set map_type = 'Color Map' %}
|
||||
| {% elif f.map_type == 'bump' %}
|
||||
| {% set map_type = 'Bump Map' %}
|
||||
| {% elif f.map_type == 'specular' %}
|
||||
| {% set map_type = 'Specular Map' %}
|
||||
| {% elif f.map_type == 'normal' %}
|
||||
| {% set map_type = 'Normal Map' %}
|
||||
| {% elif f.map_type == 'translucency' %}
|
||||
| {% set map_type = 'Translucency' %}
|
||||
| {% elif f.map_type == 'emission' %}
|
||||
| {% set map_type = 'Emission' %}
|
||||
| {% elif f.map_type == 'alpha' %}
|
||||
| {% set map_type = 'Alpha' %}
|
||||
| {% elif f.map_type == 'id' %}
|
||||
| {% set map_type = 'ID Map' %}
|
||||
| {% else %}
|
||||
| {% set map_type = f.map_type %}
|
||||
| {% endif %}
|
||||
|
||||
section.node-details-container.texture
|
||||
|
||||
.node-details-header
|
||||
.node-title {{map_type}}
|
||||
|
||||
.node-details-attributes
|
||||
span.sizes
|
||||
span.x
|
||||
| Width:
|
||||
strong {{ f.file.width }}
|
||||
span.y
|
||||
| Height:
|
||||
strong {{ f.file.height }}
|
||||
span.length
|
||||
| {{ f.file.length | filesizeformat }}
|
||||
span.content_type
|
||||
| {{ f.file.content_type }}
|
||||
|
||||
.node-details-meta
|
||||
ul.node-details-meta-list
|
||||
li.node-details-meta-list-item.texture.download
|
||||
| {% if f.file.link %}
|
||||
a(href="{{ f.file.link }}",,
|
||||
title="Download texture",
|
||||
download="{{ f.file.filename }}")
|
||||
button.btn.btn-default(type="button")
|
||||
i.pi-download
|
||||
| Download
|
||||
| {% else %}
|
||||
button.btn.btn-default.disabled.sorry(type="button")
|
||||
| Download
|
||||
| {% endif %}
|
||||
| {% endfor %}
|
||||
| {% else %}
|
||||
section.node-row
|
||||
section.node-details-container.texture
|
||||
.node-details-header.nofiles
|
||||
.node-title No texture maps... yet!
|
||||
|
||||
| {% endif %}
|
||||
|
||||
|
||||
include ../_scripts
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_scripts %}
|
||||
script.
|
||||
$('#asset-license').popover();
|
||||
// Generate GA pageview
|
||||
ga('send', 'pageview', location.pathname);
|
||||
|
||||
var str = $('.texture-title').text();
|
||||
var to_replace = /_color|_bump|_specular|_normal|_translucency|_emission|_alpha|_tileable|.jpg|.png/g;
|
||||
$('.texture-title').text(str.replace(to_replace,'').replace(/_/g,' '));
|
||||
|
||||
$('.node-preview-thumbnail').each(function(i){
|
||||
$(this).closest('.node-preview').css({'height' : $(this).width() / $(this).data('aspect_ratio')});
|
||||
|
||||
var thumbnail = $(this);
|
||||
var src = $(this).attr('src');
|
||||
var src_xl = $(thumbnail).data('preview');
|
||||
var src_xl_width, src_xl_height;
|
||||
|
||||
/* Make dummy img in memory otherwise we have css issues */
|
||||
$("<img/>")
|
||||
.attr('src', src_xl)
|
||||
.load(function(){
|
||||
src_xl_width = this.width;
|
||||
src_xl_height = this.height;
|
||||
});
|
||||
|
||||
$(this).on('click', function(e){
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
$(this).hover(
|
||||
function(){
|
||||
var preview = $(this);
|
||||
|
||||
/* Replace image src with larger one */
|
||||
if (src_xl_width > 350 || src_xl_height > 250) {
|
||||
$(thumbnail).attr('src', src_xl);
|
||||
$(preview).css({width: src_xl_width + 'px', height: src_xl_height + 'px'});
|
||||
}
|
||||
|
||||
var parent = $(preview).parent();
|
||||
var parentOffset = parent.offset();
|
||||
|
||||
if (src_xl_width > 600 || src_xl_height > 300) {
|
||||
|
||||
$(document).on('mousemove', function(e){
|
||||
$(preview).css({
|
||||
left: e.pageX - parentOffset.left - (src_xl_width / 2),
|
||||
top: e.pageY - parentOffset.top - (src_xl_height / 2),
|
||||
transform: 'initial',
|
||||
cursor: 'grabbing',
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
},
|
||||
function(){
|
||||
$(document).off('mousemove');
|
||||
$(this).attr('src', src);
|
||||
|
||||
$(this).css({left: '50%', top: "50%", width: '100%', height: 'auto', transform: 'translate(-50%, -50%)'});
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
});
|
||||
|
||||
$('.sorry').click(function() {
|
||||
$.get('/403', function(data) {
|
||||
$('#node-overlay').html(data).show().addClass('active');
|
||||
})
|
||||
});
|
||||
|
||||
$('#node-overlay').click(function(){
|
||||
$(this).removeClass('active').hide().html();
|
||||
});
|
||||
|
||||
| {% endblock %}
|
||||
|
11
src/templates/nodes/edit.jade
Normal file
11
src/templates/nodes/edit.jade
Normal file
@@ -0,0 +1,11 @@
|
||||
| {% extends 'layout.html' %}
|
||||
|
||||
| {% block body %}
|
||||
div.container
|
||||
div.page-content
|
||||
| {% include 'nodes/edit_embed.html' %}
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_scripts %}
|
||||
| {% include '_macros/_file_uploader_javascript.html' %}
|
||||
| {% endblock %}
|
347
src/templates/nodes/edit_embed.jade
Normal file
347
src/templates/nodes/edit_embed.jade
Normal file
@@ -0,0 +1,347 @@
|
||||
| {% from '_macros/_node_edit_form.html' import render_field %}
|
||||
|
||||
| {% block body %}
|
||||
|
||||
| {% 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 %}
|
||||
|
||||
| {% if error!="" %}
|
||||
.alert.alert-danger(role="alert")
|
||||
| {{error}}
|
||||
| {% endif %}
|
||||
|
||||
#node-edit-container
|
||||
|
||||
form(
|
||||
id="node-edit-form",
|
||||
class="{{ node.node_type }}",
|
||||
method="POST",
|
||||
enctype="multipart/form-data",
|
||||
action="{{url_for('nodes.edit', node_id=node._id)}}")
|
||||
|
||||
| {% for field in form %}
|
||||
|
||||
| {% if field.name == 'csrf_token' %}
|
||||
| {{ field }}
|
||||
|
||||
| {% elif field.type == 'HiddenField' %}
|
||||
| {{ field }}
|
||||
|
||||
| {% elif field.name == 'attachments' %}
|
||||
#attachments-actions
|
||||
.btn.btn-info#attachments-action-add
|
||||
i.pi-plus
|
||||
| Add New Attachment
|
||||
|
||||
| {{ render_field(field) }}
|
||||
|
||||
| {% elif field.name == 'files' %}
|
||||
.files-header
|
||||
#files-actions
|
||||
#files-action-add
|
||||
i.pi-plus
|
||||
| Add New File
|
||||
| {{ render_field(field) }}
|
||||
|
||||
| {% else %}
|
||||
| {{ render_field(field) }}
|
||||
|
||||
| {% endif %}
|
||||
|
||||
| {% endfor %}
|
||||
|
||||
ul.project-edit-tools.bottom
|
||||
li.button-cancel
|
||||
a#item_cancel.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.item-save.project-mode-edit(
|
||||
href="javascript:void(0);",
|
||||
title="Save changes")
|
||||
i.button-save-icon.pi-check
|
||||
| Save Changes
|
||||
script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.ui.widget.min.js') }}")
|
||||
script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.iframe-transport.min.js') }}")
|
||||
script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.fileupload.min.js') }}")
|
||||
script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.select2.min.js') }}")
|
||||
script(src="{{ url_for('static_pillar', filename='assets/js/file_upload.min.js') }}")
|
||||
|
||||
script(type="text/javascript").
|
||||
|
||||
$(function () {
|
||||
$('#tags').select2();
|
||||
});
|
||||
|
||||
var convert = new Markdown.getSanitizingConverter();
|
||||
Markdown.Extra.init(convert);
|
||||
convert = convert.makeHtml;
|
||||
|
||||
/* 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');
|
||||
});
|
||||
|
||||
$(function() {
|
||||
$('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 asset.';
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$("#item_save").unbind( "click" );
|
||||
$("#item_cancel").unbind( "click" );
|
||||
$(".file_delete").unbind( "click" );
|
||||
|
||||
/* Reset Save Changes button status */
|
||||
$("li.button-save").removeClass('field-error saving');
|
||||
$("li.button-save a#item_save").html('<i class="pi-check"></i> Save Changes');
|
||||
|
||||
|
||||
/* Submit changes */
|
||||
$("#node-edit-form").unbind( "submit" )
|
||||
.submit(function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
/* Let us know started saving */
|
||||
$("li.button-save").addClass('saving');
|
||||
$("li.button-save a#item_save").html('<i class="pi-spin spin"></i> Saving...');
|
||||
|
||||
$.ajax({
|
||||
url: "{{url_for('nodes.edit', node_id=node._id)}}",
|
||||
data: $(this).serialize(),
|
||||
type: 'POST'
|
||||
})
|
||||
.fail(function(data){
|
||||
/* Something went wrong, print it */
|
||||
if (data.status == 422) {
|
||||
statusBarSet('error', 'The submitted data could not be validated.', 8000);
|
||||
} else {
|
||||
statusBarSet('error', 'Error! We\'ve been notified and are working on it - '
|
||||
+ data.status + ' ' + data.statusText, 8000);
|
||||
}
|
||||
|
||||
$("li.button-save").addClass('field-error');
|
||||
$("li.button-save a#item_save").html('<i class="pi-warning"></i> Houston!');
|
||||
|
||||
/* Back to normal */
|
||||
setTimeout(function(){
|
||||
$("li.button-save").removeClass('saving field-error');
|
||||
$("li.button-save a#item_save").html('<i class="pi-check"></i> Save Changes');
|
||||
}, 8000);
|
||||
})
|
||||
.done(function(dataHtml){
|
||||
/* Success! */
|
||||
|
||||
/* Load content*/
|
||||
$('#project_context').html(dataHtml);
|
||||
statusBarSet('success', 'Saved Successfully', 'pi-check');
|
||||
|
||||
/* Style button */
|
||||
$("li.button-save").removeClass('saving field-error');
|
||||
$("li.button-save a#item_save").html('<i class="pi-check"></i> Save Changes');
|
||||
|
||||
// XXX TODO - Keeps displaying 'loading', needs further investigation
|
||||
//- $('#project_tree').jstree("refresh");
|
||||
|
||||
updateUi(ProjectUtils.nodeId(), 'view');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
$('#item_save, .item-save').click(function(e){
|
||||
e.preventDefault();
|
||||
|
||||
// Assets always need a file
|
||||
if ($('.form-group.file #file').val() == ''){
|
||||
$('.form-group.file').addClass('error');
|
||||
statusBarSet('error', 'No File Selected', 'pi-warning', 5000);
|
||||
} else {
|
||||
$('.form-group.file').removeClass('error');
|
||||
$("#node-edit-form").submit();
|
||||
|
||||
// Disable beforeunolad when submitting a form
|
||||
$(window).off('beforeunload');
|
||||
}
|
||||
});
|
||||
|
||||
$('#item_cancel, .item-cancel').click(function(e){
|
||||
displayNode('{{node._id}}');
|
||||
});
|
||||
|
||||
var attrs = ['for', 'id', 'name', 'data-field-name'];
|
||||
function resetAttributeNames(section) {
|
||||
var tags = section.find('input, select, label, div, a');
|
||||
var idx = section.index();
|
||||
tags.each(function () {
|
||||
var $this = $(this);
|
||||
|
||||
// Renumber certain attributes.
|
||||
$.each(attrs, function (i, attr) {
|
||||
var attr_val = $this.attr(attr);
|
||||
if (attr_val) {
|
||||
$this.attr(attr, attr_val.replace(/-\d+/, '-' + idx))
|
||||
}
|
||||
});
|
||||
|
||||
// Clear input field values
|
||||
var tagname = $this.prop('tagName');
|
||||
if (tagname == 'INPUT') {
|
||||
if ($this.attr('type') == 'checkbox') {
|
||||
$this.prop('checked', false);
|
||||
} else {
|
||||
$this.val('');
|
||||
}
|
||||
} else if (tagname == 'SELECT') {
|
||||
$this.find(':nth-child(1)').prop('selected', true);
|
||||
}
|
||||
});
|
||||
|
||||
// Click on all file delete buttons to clear all file widgets.
|
||||
section.find('a.file_delete').click();
|
||||
section.find('div.form-upload-progress-bar').hide();
|
||||
}
|
||||
|
||||
var initUploadFields = function(selector_string) {
|
||||
// console.log($(selector_string));
|
||||
$(selector_string).fileupload({
|
||||
dataType: 'json',
|
||||
acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
|
||||
replaceFileInput: false,
|
||||
dropZone: $(this),
|
||||
formData: {},
|
||||
progressall: function (e, data) {
|
||||
// Update progressbar during upload
|
||||
var progress = parseInt(data.loaded / data.total * 100, 10);
|
||||
$(this).next().find('.form-upload-progress-bar').css(
|
||||
{'width': progress + '%', 'display': 'block'}
|
||||
).removeClass('progress-error').addClass('progress-active');
|
||||
fieldUpload = $(this);
|
||||
},
|
||||
done: function (e, data) {
|
||||
// Get the first file upload result (we only need one)
|
||||
var fileData = data.result.files[0];
|
||||
// Create a file object on the server and retrieve its id
|
||||
statusBarSet('info', 'Uploading File...', 'pi-upload-cloud');
|
||||
|
||||
$('.button-save').addClass('disabled');
|
||||
$('li.button-save a#item_save').html('<i class="pi-spin spin"></i> Uploading Preview...');
|
||||
|
||||
var payload = {
|
||||
name: fileData.name,
|
||||
size: fileData.size,
|
||||
type: fileData.type,
|
||||
field_name: $(this).data('field-name'),
|
||||
project_id: ProjectUtils.projectId()
|
||||
}
|
||||
$.post("/files/create", payload)
|
||||
.done(function (data) {
|
||||
if (data.status === 'success') {
|
||||
// If successful, add id to the picture hidden field
|
||||
var field_name = '#' + data.data.field_name;
|
||||
if ($(field_name).val()) {
|
||||
$('.node-preview-thumbnail').hide();
|
||||
deleteFile($(field_name), data.data.id);
|
||||
} else {
|
||||
$(field_name).val(data.data.id);
|
||||
}
|
||||
|
||||
var previewThumbnail = fieldUpload.prev().prev();
|
||||
|
||||
$(previewThumbnail).attr('src', data.data.link);
|
||||
$('.node-preview-thumbnail').show();
|
||||
statusBarSet('success', 'File Uploaded Successfully', 'pi-check');
|
||||
|
||||
$('.button-save').removeClass('disabled');
|
||||
$('li.button-save a#item_save').html('<i class="pi-check"></i> Save Changes');
|
||||
$('.progress-active').removeClass('progress-active progress-error');
|
||||
}
|
||||
})
|
||||
.fail(function(data) {
|
||||
$('.button-save').removeClass('disabled');
|
||||
$('li.button-save a#item_save').html('<i class="pi-check"></i> Save Changes');
|
||||
|
||||
statusBarSet(data.textStatus, 'Upload error: ' + data.errorThrown, 'pi-attention', 8000);
|
||||
});
|
||||
},
|
||||
fail: function (e, data) {
|
||||
$('.button-save').removeClass('disabled');
|
||||
$('li.button-save a#item_save').html('<i class="pi-check"></i> Save Changes');
|
||||
|
||||
statusBarSet(data.textStatus, 'Upload error: ' + data.errorThrown, 'pi-attention', 8000);
|
||||
$('.progress-active').addClass('progress-error').removeClass('progress-active');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (document.getElementById("attachments") !== null) {
|
||||
$("#attachments-action-add").on('click', function(){
|
||||
var lastRepeatingGroup = $('#attachments > li').last();
|
||||
var cloned = lastRepeatingGroup.clone(true);
|
||||
cloned.insertAfter(lastRepeatingGroup);
|
||||
resetAttributeNames(cloned);
|
||||
});
|
||||
}
|
||||
|
||||
if (document.getElementById("files") !== null) {
|
||||
$("#files-action-add").on('click', function () {
|
||||
var lastRepeatingGroup = $('#files > li').last();
|
||||
var cloned = lastRepeatingGroup.clone(false);
|
||||
cloned.insertAfter(lastRepeatingGroup);
|
||||
resetAttributeNames(cloned);
|
||||
cloned.find('.fileupload').each(setup_file_uploader)
|
||||
});
|
||||
}
|
||||
//- console.log($._data($(elementSelector)[0], "events"));
|
||||
|
||||
|
||||
| {% endblock %}
|
301
src/templates/nodes/search.jade
Normal file
301
src/templates/nodes/search.jade
Normal file
@@ -0,0 +1,301 @@
|
||||
| {% extends 'layout.html' %}
|
||||
| {% block page_title %}Search{% if project %} {{ project.name }}{% endif %}{% 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 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}}")
|
||||
| {% endif %}
|
||||
| {% endblock %}
|
||||
|
||||
| {% block tw %}
|
||||
| {% if og_picture %}
|
||||
meta(property="twitter:image", content="{{ og_picture.thumbnail('l', api=api) }}")
|
||||
| {% endif %}
|
||||
| {% if project %}
|
||||
meta(name="twitter:title", content="{{project.name}} on Blender Cloud")
|
||||
meta(name="twitter:description", content="{{project.summary}}")
|
||||
| {% endif %}
|
||||
| {% endblock %}
|
||||
|
||||
| {% block body %}
|
||||
|
||||
#search-container
|
||||
|
||||
| {% if project %}
|
||||
#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
|
||||
li.tabs-search.active(
|
||||
title="Search",
|
||||
data-toggle="tooltip",
|
||||
data-placement="left")
|
||||
a(href="{{url_for('projects.search', project_url=project.url, _external=True)}}")
|
||||
i.pi-search
|
||||
| {% endif %}
|
||||
|
||||
#search-sidebar
|
||||
input.search-field(
|
||||
type="text",
|
||||
name="q",
|
||||
id="q",
|
||||
autocomplete="off",
|
||||
spellcheck="false",
|
||||
autocorrect="false",
|
||||
placeholder="Search by Title, Type...")
|
||||
|
||||
.search-list-filters
|
||||
.filter-list
|
||||
| View as:
|
||||
ul.filter-list
|
||||
li.filter-list-type.grid(
|
||||
title="Browse as grid",
|
||||
data-list-type="grid")
|
||||
i.pi-layout
|
||||
li.filter-list-type.list(
|
||||
title="Browse as list",
|
||||
data-list-type="list")
|
||||
i.pi-list
|
||||
|
||||
#accordion.panel-group.accordion(role="tablist", aria-multiselectable="true")
|
||||
#facets
|
||||
|
||||
#pagination
|
||||
|
||||
.search-list-stats
|
||||
#stats
|
||||
|
||||
#search-list
|
||||
#hits
|
||||
|
||||
#search-details
|
||||
#search-error
|
||||
#search-hit-container
|
||||
|
||||
|
||||
| {% raw %}
|
||||
// Facet template
|
||||
script(type="text/template", id="facet-template")
|
||||
.panel.panel-default
|
||||
a(data-toggle='collapse', data-parent='#accordion', href='#filter_{{ facet }}', aria-expanded='true', aria-controls='filter_{{ facet }}')
|
||||
.panel-heading(role='tab')
|
||||
.panel-title {{ title }}
|
||||
.panel-collapse.collapse.in(id='filter_{{ facet }}', role='tabpanel', aria-labelledby='headingOne')
|
||||
.panel-body
|
||||
| {{#values}}
|
||||
a.facet_link.toggleRefine(
|
||||
class='{{#refined}}refined{{/refined}}',
|
||||
data-facet='{{ facet }}',
|
||||
data-value='{{ value }}',
|
||||
href='#')
|
||||
span
|
||||
| {{ label }}
|
||||
small.facet_count.pull-right {{ count }}
|
||||
| {{/values}}
|
||||
|
||||
|
||||
// Hit template
|
||||
script(type="text/template", id="hit-template")
|
||||
.search-hit(data-hit-id='{{ objectID }}')
|
||||
#search-loading.search-loading
|
||||
.spinner
|
||||
span.spin ·
|
||||
.search-hit-thumbnail
|
||||
| {{#picture}}
|
||||
img(src="{{{ picture }}}")
|
||||
| {{/picture}}
|
||||
| {{^picture}}
|
||||
.search-hit-thumbnail-icon
|
||||
| {{#media}}
|
||||
i(class="pi-{{{ media }}}")
|
||||
| {{/media}}
|
||||
| {{^media}}
|
||||
i.dark(class="pi-{{{ node_type }}}")
|
||||
| {{/media}}
|
||||
| {{/picture}}
|
||||
| {{#is_free}}
|
||||
.search-hit-ribbon
|
||||
span free
|
||||
| {{/is_free}}
|
||||
.search-hit-name
|
||||
| {{{ _highlightResult.name.value }}}
|
||||
.search-hit-meta
|
||||
span.project {{{ project.name }}} ·
|
||||
span.node_type {{{ node_type }}}
|
||||
| {{#media}}
|
||||
span.media · {{{ media }}}
|
||||
| {{/media}}
|
||||
span.when {{{ created }}}
|
||||
span.context
|
||||
a(href="/nodes/{{ objectID }}/redir") view in context
|
||||
|
||||
|
||||
// Pagination template
|
||||
script(type="text/template", id="pagination-template")
|
||||
ul.search-pagination.
|
||||
<li {{^prev_page}}class="disabled"{{/prev_page}}><a href="#" {{#prev_page}} class="gotoPage" data-page="{{ prev_page }}" {{/prev_page}}><i class="pi-angle-left"></i></a></li>
|
||||
{{#pages}}
|
||||
<li class="{{#current}}active{{/current}}{{#disabled}}disabled{{/disabled}}"><a href="#" {{^disabled}} class="gotoPage" data-page="{{ number }}" {{/disabled}}>{{ number }}</a></li>
|
||||
{{/pages}}
|
||||
<li {{^next_page}}class="disabled"{{/next_page}}><a href="#" {{#next_page}} class="gotoPage" data-page="{{ next_page }}" {{/next_page}}><i class="pi-angle-right"></i></a></li>
|
||||
|
||||
// Stats template
|
||||
script(type="text/template", id="stats-template")
|
||||
span {{ nbHits }} result{{#nbHits_plural}}s{{/nbHits_plural}}
|
||||
small ({{ processingTimeMS }}ms)
|
||||
| {% endraw %}
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_scripts %}
|
||||
script(src="//releases.flowplayer.org/6.0.5/flowplayer.min.js", async)
|
||||
script().
|
||||
var APPLICATION_ID = '{{config.ALGOLIA_USER}}';
|
||||
var SEARCH_ONLY_API_KEY = '{{config.ALGOLIA_PUBLIC_KEY}}';
|
||||
var INDEX_NAME = '{{config.ALGOLIA_INDEX_NODES}}';
|
||||
var sortByCountDesc = null;
|
||||
var FACET_CONFIG = [
|
||||
{ name: 'node_type', title: 'Type', disjunctive: false, sortFunction: sortByCountDesc },
|
||||
{ name: 'media', title: 'Media', disjunctive: false, sortFunction: sortByCountDesc },
|
||||
{ name: 'tags', title: 'Tags', disjunctive: false, sortFunction: sortByCountDesc },
|
||||
{ name: 'is_free', title: 'Free Access', disjunctive: false, sortFunction: sortByCountDesc },
|
||||
];
|
||||
{% if project %}
|
||||
FACET_CONFIG.push({ name: 'project._id', title: 'Project', disjunctive: false, hidden: true, value: '{{project._id}}' })
|
||||
{% endif %}
|
||||
|
||||
script(src="//cdn.jsdelivr.net/algoliasearch.helper/2/algoliasearch.helper.min.js")
|
||||
script(src="//cdn.jsdelivr.net/hogan.js/3.0.0/hogan.common.js")
|
||||
script(src="{{ url_for('static_pillar', filename='assets/js/algolia_search.min.js') }}")
|
||||
|
||||
script(type="text/javascript").
|
||||
|
||||
function displayUser(userId) {
|
||||
var url = '/nodes/' + userId + '/view';
|
||||
|
||||
$.get(url, function(dataHtml){
|
||||
$('#search-hit-container').html(dataHtml);
|
||||
})
|
||||
.done(function(){
|
||||
$('.search-loading').removeClass('active');
|
||||
$('#search-error').hide();
|
||||
$('#search-hit-container').show();
|
||||
})
|
||||
.fail(function(data){
|
||||
$('.search-loading').removeClass('active');
|
||||
$('#search-hit-container').hide();
|
||||
$('#search-error').show().html('Houston!\n\n' + data.status + ' ' + data.statusText);
|
||||
});
|
||||
}
|
||||
|
||||
$('body').on('click', '.search-hit', function(){
|
||||
if ($('.search-loading').hasClass('active')){
|
||||
$(this).removeClass('active');
|
||||
}
|
||||
$(this).find('#search-loading').addClass('active');
|
||||
|
||||
displayUser($(this).data('hit-id'));
|
||||
$('.search-hit').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
});
|
||||
|
||||
// Remove focus from search input so that the click event bound to .search-hit
|
||||
// can be fired on the first click.
|
||||
$(searchList).hover(function(){
|
||||
$('#q').blur();
|
||||
});
|
||||
$('#search-sidebar').hover(function(){
|
||||
$('#q').focus();
|
||||
});
|
||||
|
||||
/* UI Stuff */
|
||||
|
||||
/* List types, grid or list (default)*/
|
||||
var uiListType = Cookies.getJSON('bcloud_ui');
|
||||
var searchList = document.getElementById('search-list');
|
||||
|
||||
function uiSetListType(type){
|
||||
$('.filter-list-type').removeClass('active');
|
||||
|
||||
if (type == 'grid'){
|
||||
$(searchList).addClass('view-grid');
|
||||
$('.filter-list-type.grid').addClass('active');
|
||||
} else {
|
||||
$(searchList).removeClass('view-grid');
|
||||
$('.filter-list-type.list').addClass('active');
|
||||
}
|
||||
}
|
||||
|
||||
if (uiListType && uiListType.search_browse_type == 'grid'){
|
||||
uiSetListType('grid');
|
||||
} else {
|
||||
uiSetListType('list');
|
||||
}
|
||||
|
||||
$('.filter-list-type').on('click', function(){
|
||||
if ($(this).attr('data-list-type') == 'grid'){
|
||||
uiSetListType('grid');
|
||||
setJSONCookie('bcloud_ui', 'search_browse_type', 'grid');
|
||||
} else {
|
||||
uiSetListType('list');
|
||||
setJSONCookie('bcloud_ui', 'search_browse_type', 'list');
|
||||
}
|
||||
});
|
||||
|
||||
/* Scrollbars */
|
||||
if (typeof Ps !== 'undefined'){
|
||||
Ps.initialize(searchList, {suppressScrollX: true});
|
||||
Ps.initialize(document.getElementById('search-hit-container'), {suppressScrollX: true});
|
||||
}
|
||||
|
||||
/* Hide site-wide search, kinda confusing */
|
||||
$('.search-input').hide();
|
||||
|
||||
/* Resize container so we can have custom scrollbars */
|
||||
container_offset = $('#search-container').offset();
|
||||
|
||||
function containerResizeY(window_height){
|
||||
|
||||
var container_height = window_height - container_offset.top;
|
||||
|
||||
if (container_height > parseInt($('#search-container').css("min-height"))) {
|
||||
$('#search-container').css(
|
||||
{'max-height': container_height + 'px', 'height': container_height + 'px'}
|
||||
);
|
||||
$('#search-list, #search-hit-container').css(
|
||||
{'max-height': container_height + 'px', 'height': container_height + 'px'}
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
$(window).on("load resize",function(){
|
||||
containerResizeY($(window).height());
|
||||
});
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_navigation %}{% endblock %}
|
||||
| {% block footer %}{% endblock %}
|
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 %}
|
218
src/templates/services.jade
Normal file
218
src/templates/services.jade
Normal file
@@ -0,0 +1,218 @@
|
||||
| {% extends 'layout.html' %}
|
||||
| {% block page_title %}Services{% endblock %}
|
||||
|
||||
| {% set title = 'services' %}
|
||||
|
||||
| {% block og %}
|
||||
meta(property="og:title", content="Services - Blender Cloud")
|
||||
meta(property="og:url", content="https://cloud.blender.org/services")
|
||||
meta(property="og:image", content="{{ url_for('static', filename='assets/img/backgrounds/background_services.jpg')}}")
|
||||
| {% endblock %}
|
||||
|
||||
| {% block header_backdrop %}
|
||||
.navbar-backdrop(
|
||||
style="background-image: url({{ url_for('static', filename='assets/img/backgrounds/services_projects.jpg')}})")
|
||||
.navbar-backdrop-overlay.services
|
||||
| {% endblock %}
|
||||
|
||||
| {% block page_overlay %}
|
||||
#page-overlay.video
|
||||
.video-embed
|
||||
| {% endblock %}
|
||||
|
||||
| {% block body %}
|
||||
#page-container
|
||||
#page-header
|
||||
.page-title(style="text-align: left")
|
||||
i.pi-blender-cloud-logo
|
||||
em SERVICES
|
||||
.page-title-summary
|
||||
| Personal Projects · Blender Integration · Texture Browsing · Production Management
|
||||
|
||||
#page-content
|
||||
section.page-card
|
||||
|
||||
.page-card-side
|
||||
h2.page-card-title Private Projects
|
||||
.page-card-summary.
|
||||
Create and manage your own personal projects.
|
||||
Upload assets and collaborate with other Blender Cloud members.
|
||||
|
||||
a.page-card-cta(
|
||||
href="https://cloud.blender.org/blog/introducing-private-projects")
|
||||
| Learn More
|
||||
|
||||
.page-card-side
|
||||
.page-card-icon
|
||||
svg(xmlns='http://www.w3.org/2000/svg', width='56', height='64', viewbox='0 0 56 64')
|
||||
g(fill='#555')
|
||||
path(d='M42 38H14V26h28v12zm-26-2h24v-8H16v8zm-4-5H8c-1.654 0-3-1.346-3-3V15h2v13c0 .55.45 1 1 1h4v2z')
|
||||
path(d='M9.293 19.707L6 16.414l-3.293 3.293-1.414-1.414 4-4c.39-.39 1.023-.39 1.414 0l4 4-1.414 1.414zM48 31h-4v-2h4c.55 0 1-.45 1-1V15h2v13c0 1.654-1.346 3-3 3z')
|
||||
path(d='M53.293 19.707L50 16.414l-3.293 3.293-1.414-1.414L50 13.586l4.707 4.707M27 15h2v9h-2z')
|
||||
path(d='M31.293 19.707L28 16.414l-3.293 3.293-1.414-1.414L28 13.586l4.707 4.707M7 49H5V36c0-1.654 1.346-3 3-3h4v2H8c-.55 0-1 .45-1 1v13z')
|
||||
path(d='M6 50c-.256 0-.512-.098-.707-.293l-4-4 1.414-1.414L6 47.586l3.293-3.293 1.414 1.414-4 4c-.195.195-.45.293-.707.293zm45-1h-2V36c0-.55-.45-1-1-1h-4v-2h4c1.654 0 3 1.346 3 3v13z')
|
||||
path(d='M50 50.414l-4.707-4.707 1.414-1.414L50 47.586l3.293-3.293 1.414 1.414M27 40h2v9h-2z')
|
||||
path(d='M28 50.414l-4.707-4.707 1.414-1.414L28 47.586l3.293-3.293 1.414 1.414M6 12c-3.31 0-6-2.692-6-6s2.69-6 6-6 6 2.692 6 6-2.69 6-6 6zM6 2C3.794 2 2 3.794 2 6s1.794 4 4 4 4-1.794 4-4-1.794-4-4-4zm22 10c-3.31 0-6-2.692-6-6s2.69-6 6-6 6 2.692 6 6-2.69 6-6 6zm0-10c-2.206 0-4 1.794-4 4s1.794 4 4 4 4-1.794 4-4-1.794-4-4-4zm22 10c-3.31 0-6-2.692-6-6s2.69-6 6-6 6 2.692 6 6-2.69 6-6 6zm0-10c-2.206 0-4 1.794-4 4s1.794 4 4 4 4-1.794 4-4-1.794-4-4-4zM6 64c-3.31 0-6-2.692-6-6s2.69-6 6-6 6 2.692 6 6-2.69 6-6 6zm0-10c-2.206 0-4 1.794-4 4s1.794 4 4 4 4-1.794 4-4-1.794-4-4-4zm22 10c-3.31 0-6-2.692-6-6s2.69-6 6-6 6 2.692 6 6-2.69 6-6 6zm0-10c-2.206 0-4 1.794-4 4s1.794 4 4 4 4-1.794 4-4-1.794-4-4-4zm22 10c-3.31 0-6-2.692-6-6s2.69-6 6-6 6 2.692 6 6-2.69 6-6 6zm0-10c-2.206 0-4 1.794-4 4s1.794 4 4 4 4-1.794 4-4-1.794-4-4-4zM27 31h2v2h-2zm-4 0h2v2h-2zm8 0h2v2h-2z')
|
||||
|
||||
#blender-addon.page-section-container(
|
||||
style="background-image: url({{ url_for('static', filename='assets/img/backgrounds/pattern_bw_01.jpg')}})")
|
||||
section.page-card-header.dark Blender Cloud Add-on
|
||||
span.page-card-header_lead.dark Connect Blender with the Cloud
|
||||
|
||||
a.page-card-cta.download(
|
||||
href="https://cloud.blender.org/r/downloads/blender_cloud-latest-bundle.zip")
|
||||
i.pi-download
|
||||
| Download <small>v</small>1.3
|
||||
|
||||
section.page-card.dark.right
|
||||
|
||||
.page-card-side
|
||||
h2.page-card-title Blender Sync
|
||||
.page-card-summary.
|
||||
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/>
|
||||
<small>Syncing settings is free for everyone! No subscription required.</small>
|
||||
|
||||
a.page-card-cta(
|
||||
href="https://cloud.blender.org/blog/introducing-blender-sync")
|
||||
| Learn More
|
||||
|
||||
.page-card-side
|
||||
.page-card-icon
|
||||
svg(xmlns="http://www.w3.org/2000/svg",
|
||||
width="64", height="54", viewBox="0 0 64 54")
|
||||
g(fill="none", stroke="#aaa", stroke-width="2", stroke-miterlimit="10")
|
||||
path(d="M29 47H5l-4-4v-2h24l2 2h2M29 3H10C8.344 3 7 4.343 7 6v32M35 51h24l4-4v-2H39l-2 2h-2M35 7h19c1.656 0 3 1.343 3 3v32M32 34v20M32 20v8M32 0v14")
|
||||
g
|
||||
path(d="M32 31c-3.866 0-7-3.134-7-7M32 17c3.866 0 7 3.134 7 7M32 31h8M24 17h8M36 35l4-4-4-4M28 21l-4-4 4-4")
|
||||
path(d="M29 37H11V7h18M35 11h18v30H35")
|
||||
|
||||
|
||||
section.page-card.dark
|
||||
|
||||
.page-card-side
|
||||
h2.page-card-title Texture Browser
|
||||
.page-card-summary
|
||||
p.
|
||||
Access the <a href="https://cloud.blender.org/p/textures/">Blender Cloud Textures</a>
|
||||
library from within Blender using our exclusive add-on.
|
||||
Create, manage and share <em>your own</em> texture libraries!
|
||||
|
||||
a.page-card-cta.watch-video(
|
||||
href="https://www.youtube.com/watch?v=-srXYv2Osjw",
|
||||
data-youtube-id="-srXYv2Osjw")
|
||||
i.pi-play
|
||||
| Watch Video
|
||||
|
||||
.page-card-side
|
||||
.page-card-icon
|
||||
svg(xmlns="http://www.w3.org/2000/svg",
|
||||
width="64", height="60",
|
||||
viewBox="0 0 64 60")
|
||||
g(fill="#aaa")
|
||||
path(d="M32 60c-.188 0-.377-.053-.542-.16l-31-20C.173 39.656 0 39.34 0 39s.173-.656.458-.84l31-20c.33-.213.754-.213 1.084 0l31 20c.285.184.458.5.458.84s-.173.656-.458.84l-31 20c-.165.107-.354.16-.542.16zM2.845 39L32 57.81 61.155 39 32 20.19 2.845 39z")
|
||||
path(d="M32 51c-.188 0-.377-.053-.542-.16l-31-20C.173 30.656 0 30.34 0 30s.173-.656.458-.84l31-20c.33-.213.754-.213 1.084 0l31 20c.285.184.458.5.458.84s-.173.656-.458.84l-31 20c-.165.107-.354.16-.542.16zM2.845 30L32 48.81 61.155 30 32 11.19 2.845 30z")
|
||||
path(d="M32 42c-.188 0-.377-.053-.542-.16l-31-20C.173 21.656 0 21.34 0 21s.173-.656.458-.84l31-20c.33-.213.754-.213 1.084 0l31 20c.285.184.458.5.458.84s-.173.656-.458.84l-31 20c-.165.107-.354.16-.542.16zM2.845 21L32 39.81 61.155 21 32 2.19 2.845 21z")
|
||||
path(d="M31 27h2v2h-2zm0-4h2v2h-2zm0 8h2v2h-2zm4-4h2v2h-2zm4 2h2v2h-2zm-16 0h2v2h-2zm12 2h2v2h-2zm-8-4h2v2h-2zm0 4h2v2h-2zm4 4h2v2h-2zm31 15h2v2h-2zm0-4h2v2h-2zm0 8h2v2h-2zm0 4h2v2h-2zm0-54h2v2h-2zm0-4h2v2h-2zm0 8h2v2h-2zm0 4h2v2h-2zM0 50h2v2H0zm0-4h2v2H0zm0 8h2v2H0zm0 4h2v2H0zM0 4h2v2H0zm0-4h2v2H0zm4 0h2v2H4zm4 0h2v2H8zm4 0h2v2h-2zm4 0h2v2h-2zm4 0h2v2h-2zm22 0h2v2h-2zm4 0h2v2h-2zm4 0h2v2h-2zm4 0h2v2h-2zm4 0h2v2h-2zM4 58h2v2H4zm4 0h2v2H8zm4 0h2v2h-2zm4 0h2v2h-2zm4 0h2v2h-2zm22 0h2v2h-2zm4 0h2v2h-2zm4 0h2v2h-2zm4 0h2v2h-2zm4 0h2v2h-2zM0 8h2v2H0zm0 4h2v2H0z")
|
||||
|
||||
|
||||
section.page-card.dark.right
|
||||
|
||||
.page-card-side
|
||||
h2.page-card-title Image Sharing
|
||||
.page-card-summary.
|
||||
Got a nice render, a Blender oddity, a cool screenshot?
|
||||
Share it instantly from within Blender to the Cloud, to the world!
|
||||
|
||||
a.page-card-cta(
|
||||
href="https://cloud.blender.org/blog/introducing-image-sharing")
|
||||
| Learn More
|
||||
|
||||
.page-card-side
|
||||
.page-card-icon
|
||||
svg(xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 64 64")
|
||||
g(fill="none",
|
||||
stroke="#aaa",
|
||||
stroke-width="2",
|
||||
stroke-linejoin="round",
|
||||
stroke-miterlimit="10")
|
||||
path(d="M1 1h62v62H1zM4 59h2M8 59h2M12 59h2M60 49H48M46 49H27M60 53H40")
|
||||
path(d="M5 5h54v40H5z")
|
||||
path(d="M9 45v-3c0-1.656 1.344-3 3-3h6c1.656 0 3 1.344 3 3v3M29 45v-3c0-1.656 1.344-3 3-3h6c1.656 0 3 1.344 3 3v3M13 45v-3M17 45v-3M33 45v-3M37 45v-3M22 31h-5c-2.762 0-5 2.238-5 5v3M38 39v-3c0-2.762-2.238-5-5-5h-5M31 20c0 3.313-1 9-6 9s-6-5.687-6-9c0-1 0-5 6-5s6 4 6 5z")
|
||||
path(d="M29 27l-2 8h-4l-2-8M18 31c-4-3-5-9-5-9l6-3M32 31c4-3 5-9 5-9l-6-3M59 24L44 9l-8 8M44 9l8 36")
|
||||
circle(cx="12", cy="12", r="3")
|
||||
|
||||
|
||||
section.page-card.services-attract
|
||||
|
||||
.page-card-side
|
||||
h2.page-card-title
|
||||
| Attract
|
||||
small (soon)
|
||||
.page-card-summary.
|
||||
Production-management software for your film, game, or commercial projects.
|
||||
|
||||
.page-card-side
|
||||
.page-card-icon
|
||||
svg(xmlns='http://www.w3.org/2000/svg', width='56', height='64', viewbox='0 0 56 64')
|
||||
path(fill='#aaa', d='M16 32C7.178 32 0 24.822 0 16S7.178 0 16 0s16 7.178 16 16-7.178 16-16 16zm0-30C8.28 2 2 8.28 2 16s6.28 14 14 14 14-6.28 14-14S23.72 2 16 2z')
|
||||
path(fill='#aaa', d='M16 56c-2.757 0-5-2.243-5-5V31h2v20c0 1.654 1.346 3 3 3s3-1.346 3-3V31h2v20c0 2.757-2.243 5-5 5z')
|
||||
path(fill='#aaa', d='M15 40h2v2h-2zM15 44h2v2h-2zM15 48h2v2h-2zM46.414 64H15v-6h2v4h28.586L54 53.586V8H32V6h24v48.414')
|
||||
path(fill='#aaa', d='M47 63h-2V53h10v2h-8M24 24H8V8h12v2H10v12h12v-6h2')
|
||||
path(fill='#aaa', d='M16 19.414l-3.707-3.707 1.414-1.414L16 16.586l6.293-6.293 1.414 1.414M29 39h-6v-6h6v6zm-4-2h2v-2h-2v2zM29 47h-6v-6h6v6zm-4-2h2v-2h-2v2zM29 55h-6v-6h6v6zm-4-2h2v-2h-2v2zM31 33h19v2H31zM31 37h19v2H31zM31 41h19v2H31zM31 45h19v2H31zM31 53h10v2H31zM31 49h19v2H31z')
|
||||
g
|
||||
path(fill='#aaa', d='M50 29H31v-2h17v-8H34v-2h16')
|
||||
g
|
||||
path(fill='#aaa', d='M48 13h2v2h-2z')
|
||||
g
|
||||
path(fill='#aaa', d='M44 13h2v2h-2z')
|
||||
g
|
||||
path(fill='#aaa', d='M40 13h2v2h-2z')
|
||||
|
||||
|
||||
| {% if not current_user.has_role('subscriber') %}
|
||||
section.page-card.subscribe(
|
||||
style="background-image: url({{ url_for('static', filename='assets/img/backgrounds/background_services.jpg')}});background-size: cover")
|
||||
.page-card-side
|
||||
h2.page-card-title
|
||||
| All of this, plus hours of training and production assets.
|
||||
.page-card-summary
|
||||
| Join us for only $9.90/month!
|
||||
a.page-card-cta(
|
||||
href="https://store.blender.org/product/membership/")
|
||||
| Subscribe Now
|
||||
| {% endif %}
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_scripts %}
|
||||
script.
|
||||
// Click anywhere in the page to hide the overlay
|
||||
function hideOverlay() {
|
||||
$('#page-overlay.video').removeClass('active');
|
||||
$('#page-overlay.video .video-embed').html('');
|
||||
}
|
||||
|
||||
$(document).click(function() {
|
||||
hideOverlay();
|
||||
});
|
||||
|
||||
$(document).keyup(function(e) {
|
||||
if (e.keyCode == 27) {
|
||||
hideOverlay();
|
||||
}
|
||||
});
|
||||
|
||||
$('a.watch-video').click(function(e){
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
$('#page-overlay.video').addClass('active');
|
||||
|
||||
var videoId = $(this).attr('data-youtube-id');
|
||||
$('#page-overlay .video-embed').html('<iframe src="https://www.youtube.com/embed/' + videoId +'?rel=0&showinfo=0;autoplay=1" frameborder="0" allowfullscreen></iframe>')
|
||||
});
|
||||
|
||||
| {% endblock %}
|
120
src/templates/stats.jade
Normal file
120
src/templates/stats.jade
Normal file
@@ -0,0 +1,120 @@
|
||||
| {% extends 'layout.html' %}
|
||||
| {% block page_title %}Stats{% endblock %}
|
||||
|
||||
| {% block body %}
|
||||
.container
|
||||
#stats-container.page-content
|
||||
.row
|
||||
.col-md-6
|
||||
.box
|
||||
span.stats__graph-title.income
|
||||
span.stats__graph-title-amount
|
||||
small $
|
||||
| 20307
|
||||
span.stats__graph-title-label Monthly Income
|
||||
|
||||
#site-stats.stats__graph
|
||||
|
||||
.col-md-6
|
||||
.box
|
||||
span.stats__graph-title subscribers
|
||||
span.stats__graph-title-amount 1807
|
||||
span.stats__graph-title-label Active Subscribers
|
||||
|
||||
#site-stats2.stats__graph
|
||||
|
||||
hr
|
||||
|
||||
.row
|
||||
.col-md-12
|
||||
.box
|
||||
.row
|
||||
.col-md-6.text-left
|
||||
p.
|
||||
The Blender Cloud is our Open Production platform - a hub for creating and sharing open content and training online. The Blender Institute projects - developers and artists who work on compelling technical creative targets - are made possible thanks to the support of subscribers to the Cloud.
|
||||
|
||||
p.
|
||||
We created this page to share with you the numbers that make the Cloud.
|
||||
|
||||
p.
|
||||
Thank you very much for your support.
|
||||
<br/>
|
||||
The Blender Institute team
|
||||
|
||||
.col-md-6 stats__join
|
||||
a(href="https://cloud.blender.org/join")
|
||||
h3.
|
||||
Get a subscription
|
||||
|
||||
h3.
|
||||
Now only $10 per month
|
||||
|
||||
.btn.btn-default
|
||||
| Join the Cloud
|
||||
|
||||
hr
|
||||
|
||||
.row.stats__data
|
||||
.col-md-12
|
||||
|
||||
.row
|
||||
|
||||
.col-md-3 stats__data-type_money
|
||||
.box
|
||||
h2.
|
||||
<small>$</small> 20307
|
||||
|
||||
h3.
|
||||
<small>Monthly Income</small>
|
||||
|
||||
i.fa.fa-money backicon
|
||||
</div>
|
||||
</div>
|
||||
|
||||
.col-md-2 stats__data-type_money
|
||||
.box
|
||||
i.fa.fa-users backicon
|
||||
h2.
|
||||
1807
|
||||
|
||||
h3.
|
||||
<small>Active Subscribers</small>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
.col-md-2 stats__data-type_quantity
|
||||
.box
|
||||
i.fa.fa-film backicon
|
||||
h2.
|
||||
245
|
||||
|
||||
h3.
|
||||
<small>Hours of Video</small>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
.col-md-2 stats__data-type_quantity
|
||||
.box
|
||||
i.fa.fa-database backicon
|
||||
h2.
|
||||
94
|
||||
|
||||
h3.
|
||||
<small>Gigabytes of Data</small>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
.col-md-3 stats__data-type_quantity
|
||||
.box
|
||||
i.fa.fa-cloud-download backicon
|
||||
h2.
|
||||
3641
|
||||
|
||||
h3.
|
||||
<small>Downloadable Assets</small>
|
||||
|
||||
|
||||
| {% endblock %}
|
25
src/templates/upload.jade
Normal file
25
src/templates/upload.jade
Normal file
@@ -0,0 +1,25 @@
|
||||
| {% extends 'layout.html' %}
|
||||
|
||||
| {% block head %}
|
||||
| {{ super() }}
|
||||
|
||||
// blueimp Gallery styles
|
||||
link(rel="stylesheet", href="{{ url_for('static_pillar', filename='assets/css/blueimp/blueimp-gallery.min.css') }}")
|
||||
|
||||
// CSS to style the file input field as button and adjust the Bootstrap progress bars
|
||||
link(rel="stylesheet", href="{{ url_for('static_pillar', filename='jquery-file-upload/css/jquery.fileupload.css') }}")
|
||||
link(rel="stylesheet", href="{{ url_for('static_pillar', filename='jquery-file-upload/css/jquery.fileupload-ui.css') }}")
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
| {% block body %}
|
||||
.container
|
||||
#project-container(style="background-color:white;padding:20px")
|
||||
|
||||
| {% include '_macros/_file_uploader_form.html' %}
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_scripts %}
|
||||
| {% include '_macros/_file_uploader_javascript.html' %}
|
||||
| {% endblock %}
|
4
src/templates/upload_embed.jade
Normal file
4
src/templates/upload_embed.jade
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
#node-add-container
|
||||
| {% include '_macros/_file_uploader_form.html' %}
|
||||
| {% include '_macros/_file_uploader_javascript.html' %}
|
78
src/templates/users/edit_embed.jade
Normal file
78
src/templates/users/edit_embed.jade
Normal file
@@ -0,0 +1,78 @@
|
||||
| {% block body %}
|
||||
|
||||
#user-edit-container
|
||||
|
||||
#user-edit-header
|
||||
.user-edit-name {{user.full_name}}
|
||||
.user-edit-username {{user.username}}
|
||||
.user-edit-email {{user.email}}
|
||||
|
||||
form(
|
||||
id="user-edit-form",
|
||||
method="POST",
|
||||
enctype="multipart/form-data",
|
||||
action="{{url_for('users.users_edit', user_id=user._id)}}")
|
||||
|
||||
| {% 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 %}
|
||||
|
||||
|
||||
a#button-cancel.btn.btn-default(href="#", data-user-id='{{user._id}}') Cancel
|
||||
|
||||
input#submit_edit_user.btn.btn-default(
|
||||
data-user-id="{{user._id}}",
|
||||
type="submit" value="Submit")
|
||||
|
||||
#user-edit-notification
|
||||
|
||||
|
||||
script(type="text/javascript").
|
||||
$('#roles').select2();
|
||||
|
||||
$('#user-edit-form').submit(function(e){
|
||||
e.preventDefault();
|
||||
//- console.log($(this).serialize());
|
||||
$.post($(this).attr('action'), $(this).serialize())
|
||||
.done(function(data){
|
||||
$('#user-edit-notification').addClass('success').html('Success!');
|
||||
})
|
||||
.fail(function(data){
|
||||
$('#user-edit-notification').addClass('fail').html('Houston!');
|
||||
});
|
||||
//- $("#user-edit-form").submit();
|
||||
});
|
||||
|
||||
$('#button-cancel').click(function(e){
|
||||
$('#user-container').html('')
|
||||
});
|
||||
|
||||
|
||||
|
||||
| {% endblock %}
|
120
src/templates/users/index.jade
Normal file
120
src/templates/users/index.jade
Normal file
@@ -0,0 +1,120 @@
|
||||
| {% extends 'layout.html' %}
|
||||
| {% block page_title %}Users{% endblock %}
|
||||
|
||||
| {% block body %}
|
||||
|
||||
#search-container
|
||||
#search-sidebar
|
||||
input.search-field(
|
||||
type="text",
|
||||
name="q",
|
||||
id="q",
|
||||
autocomplete="off",
|
||||
spellcheck="false",
|
||||
autocorrect="false",
|
||||
placeholder="Search by Full Name, Username...")
|
||||
|
||||
.search-list-filters
|
||||
#accordion.panel-group.accordion(role="tablist", aria-multiselectable="true")
|
||||
#facets
|
||||
|
||||
#pagination
|
||||
|
||||
.search-list-stats
|
||||
#stats
|
||||
|
||||
#search-list
|
||||
#hits
|
||||
|
||||
#search-details
|
||||
#search-hit-container
|
||||
|
||||
|
||||
| {% raw %}
|
||||
// Facet template
|
||||
script(type="text/template", id="facet-template")
|
||||
.panel.panel-default
|
||||
a(data-toggle='collapse', data-parent='#accordion', href='#filter_{{ facet }}', aria-expanded='true', aria-controls='filter_{{ facet }}')
|
||||
.panel-heading(role='tab')
|
||||
.panel-title {{ title }}
|
||||
.panel-collapse.collapse.in(id='filter_{{ facet }}', role='tabpanel', aria-labelledby='headingOne')
|
||||
.panel-body
|
||||
| {{#values}}
|
||||
a.facet_link.toggleRefine(
|
||||
class='{{#refined}}refined{{/refined}}',
|
||||
data-facet='{{ facet }}',
|
||||
data-value='{{ value }}',
|
||||
href='#')
|
||||
span
|
||||
| {{ label }}
|
||||
small.facet_count.text-muted.pull-right {{ count }}
|
||||
| {{/values}}
|
||||
|
||||
|
||||
// Hit template
|
||||
script(type="text/template", id="hit-template")
|
||||
.search-hit.users(data-user-id='{{ objectID }}')
|
||||
.search-hit-name
|
||||
| {{{ _highlightResult.full_name.value }}}
|
||||
small ({{{ username }}})
|
||||
.search-hit-roles
|
||||
| {{{ roles }}}
|
||||
|
||||
|
||||
// Pagination template
|
||||
script(type="text/template", id="pagination-template")
|
||||
ul.search-pagination.
|
||||
<li {{^prev_page}}class="disabled"{{/prev_page}}><a href="#" {{#prev_page}} class="gotoPage" data-page="{{ prev_page }}" {{/prev_page}}><i class="pi-angle-left"></i></a></li>
|
||||
{{#pages}}
|
||||
<li class="{{#current}}active{{/current}}{{#disabled}}disabled{{/disabled}}"><a href="#" {{^disabled}} class="gotoPage" data-page="{{ number }}" {{/disabled}}>{{ number }}</a></li>
|
||||
{{/pages}}
|
||||
<li {{^next_page}}class="disabled"{{/next_page}}><a href="#" {{#next_page}} class="gotoPage" data-page="{{ next_page }}" {{/next_page}}><i class="pi-angle-right"></i></a></li>
|
||||
|
||||
// Stats template
|
||||
script(type="text/template", id="stats-template")
|
||||
h5 {{ nbHits }} result{{#nbHits_plural}}s{{/nbHits_plural}}
|
||||
span ({{ processingTimeMS }}ms)
|
||||
| {% endraw %}
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_scripts %}
|
||||
script().
|
||||
var APPLICATION_ID = '{{config.ALGOLIA_USER}}';
|
||||
var SEARCH_ONLY_API_KEY = '{{config.ALGOLIA_PUBLIC_KEY}}';
|
||||
var INDEX_NAME = '{{config.ALGOLIA_INDEX_USERS}}';
|
||||
var sortByCountDesc = null;
|
||||
var FACET_CONFIG = [
|
||||
{ name: 'roles', title: 'Roles', disjunctive: false, sortFunction: sortByCountDesc },
|
||||
];
|
||||
|
||||
script(src="//cdn.jsdelivr.net/algoliasearch/3/algoliasearch.min.js")
|
||||
script(src="//cdn.jsdelivr.net/algoliasearch.helper/2/algoliasearch.helper.min.js")
|
||||
script(src="//cdn.jsdelivr.net/hogan.js/3.0.0/hogan.common.js")
|
||||
script(src="{{ url_for('static_pillar', filename='assets/js/algolia_search.min.js') }}")
|
||||
script(type='text/javascript', src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.select2.min.js') }}")
|
||||
|
||||
script(type="text/javascript").
|
||||
|
||||
if (typeof Ps !== 'undefined'){
|
||||
Ps.initialize(document.getElementById('hits'), {suppressScrollX: true});
|
||||
}
|
||||
|
||||
function displayUser(userId) {
|
||||
var url = '/u/' + userId + '/edit?embed=1';
|
||||
$.get(url, function(dataHtml){
|
||||
$('#search-hit-container').html(dataHtml);
|
||||
});
|
||||
}
|
||||
|
||||
$('body').on('click', '.search-hit', function(){
|
||||
displayUser($(this).data('user-id'));
|
||||
});
|
||||
|
||||
// Remove focus from search input so that the click event bound to .user-hit
|
||||
// can be fired on the first click.
|
||||
$('#search-list').hover(function(){
|
||||
$('#q').blur();
|
||||
});
|
||||
|
||||
| {% endblock %}
|
45
src/templates/users/login.jade
Normal file
45
src/templates/users/login.jade
Normal file
@@ -0,0 +1,45 @@
|
||||
| {% extends 'layout.html' %}
|
||||
|
||||
| {% block body %}
|
||||
.container
|
||||
#login-container
|
||||
.login-title Welcome back!
|
||||
|
||||
.login-info
|
||||
| Log in using your shared username and password.
|
||||
|
||||
.login-form
|
||||
form#login-form(method="POST", action="{{url_for('users.login_local')}}")
|
||||
.form-group
|
||||
| {{ form.username.label }}
|
||||
| {{ form.username(class='form-control') }}
|
||||
|
||||
.form-group
|
||||
| {{ form.password.label }}
|
||||
| {{ form.password(class='form-control') }}
|
||||
|
||||
.buttons
|
||||
.login-button-container
|
||||
//a.forgot(href="https://blender.org/id/reset") forgot your password?
|
||||
button.btn.btn-default.button-login(type="submit")
|
||||
i.pi-log-in
|
||||
| Login
|
||||
|
||||
//a.btn.btn-default.button-register(href="https://blender.org/id/register", target="_blank")
|
||||
// i.pi-star-outline
|
||||
// | Create Account
|
||||
|
||||
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_scripts %}
|
||||
script.
|
||||
$('.button-login').on('click', function(e){
|
||||
e.preventDefault();
|
||||
$(this).html('<i class="pi-spin spin"></i> Hold on...');
|
||||
|
||||
$('#login-form').submit();
|
||||
});
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_container %}{% endblock %}
|
20
src/templates/users/settings/_sidebar.jade
Normal file
20
src/templates/users/settings/_sidebar.jade
Normal file
@@ -0,0 +1,20 @@
|
||||
#settings-sidebar
|
||||
.settings-header
|
||||
.settings-title Settings
|
||||
.settings-content
|
||||
ul
|
||||
a(class="{% if title == 'profile' %}active{% endif %}",
|
||||
href="{{ url_for('users.settings_profile') }}")
|
||||
li
|
||||
i.pi-vcard
|
||||
| Profile
|
||||
a(class="{% if title == 'emails' %}active{% endif %}",
|
||||
href="{{ url_for('users.settings_emails') }}")
|
||||
li
|
||||
i.pi-email
|
||||
| Emails
|
||||
a(class="{% if title == 'billing' %}active{% endif %}",
|
||||
href="{{ url_for('users.settings_billing') }}")
|
||||
li
|
||||
i.pi-credit-card
|
||||
| Subscription
|
55
src/templates/users/settings/billing.jade
Normal file
55
src/templates/users/settings/billing.jade
Normal file
@@ -0,0 +1,55 @@
|
||||
| {% extends 'layout.html' %}
|
||||
| {% block body %}
|
||||
.container
|
||||
#settings
|
||||
include _sidebar
|
||||
#settings-container
|
||||
.settings-header
|
||||
.settings-title Subscription
|
||||
|
||||
.settings-content
|
||||
|
||||
| {% if store_user['cloud_access'] %}
|
||||
h3.subscription-active
|
||||
i.pi-check
|
||||
| Your subscription is active
|
||||
h4 Thank you for supporting us!
|
||||
|
||||
hr
|
||||
|
||||
p Subscription expires on: <strong>{{ store_user['expiration_date'][:10] }}</strong>
|
||||
a(href="https://store.blender.org/my-account/") Manage your subscription on Blender Store
|
||||
|
||||
hr
|
||||
|
||||
| {# This text is confusing (refers to the total payments ever made by the user)
|
||||
.settings-billing-info.
|
||||
Paid balance: {{ store_user['paid_balance'] }} {{ store_user['balance_currency'] }}
|
||||
| #}
|
||||
|
||||
| {% else %}
|
||||
|
||||
| {% if 'demo' in groups %}
|
||||
h3.subscription-demo
|
||||
i.pi-heart-filled
|
||||
| You have a free account
|
||||
|
||||
hr
|
||||
|
||||
p You have full access to the Blender Cloud, provided by the Blender Institute. This account is meant for free evaluation of the service. Get in touch with #[a(href="mailto:cloudsupport@blender.org") cloudsupport@blender.org] if you have any questions.
|
||||
|
||||
| {% else %}
|
||||
h3.subscription-missing
|
||||
i.pi-info
|
||||
| You do not have an active subscription.
|
||||
h3
|
||||
a(href="https://store.blender.org/product/membership/") Get full access to Blender Cloud now!
|
||||
| {% endif %}
|
||||
|
||||
| {% endif %}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
| {% endblock %}
|
27
src/templates/users/settings/emails.jade
Normal file
27
src/templates/users/settings/emails.jade
Normal file
@@ -0,0 +1,27 @@
|
||||
| {% extends 'layout.html' %}
|
||||
| {% block body %}
|
||||
.container
|
||||
#settings
|
||||
include _sidebar
|
||||
#settings-container
|
||||
.settings-header
|
||||
.settings-title Emails
|
||||
|
||||
.settings-content
|
||||
|
||||
.settings-form
|
||||
form#settings-form(method='POST', action="{{url_for('users.settings_emails')}}")
|
||||
| {{ form.csrf_token }}
|
||||
| {% for subfield in form.email_communications %}
|
||||
.form-group.
|
||||
{{ subfield }}
|
||||
{{ subfield.label }}
|
||||
| {% endfor %}
|
||||
|
||||
.buttons
|
||||
button.btn.btn-default.button-submit(type='submit')
|
||||
i.pi-check
|
||||
| Save Changes
|
||||
|
||||
|
||||
| {% endblock %}
|
45
src/templates/users/settings/profile.jade
Normal file
45
src/templates/users/settings/profile.jade
Normal file
@@ -0,0 +1,45 @@
|
||||
| {% extends 'layout.html' %}
|
||||
| {% block body %}
|
||||
.container
|
||||
#settings
|
||||
include _sidebar
|
||||
#settings-container
|
||||
.settings-header
|
||||
.settings-title Profile
|
||||
|
||||
.settings-content
|
||||
.settings-form
|
||||
form#settings-form(method='POST', action="{{url_for('users.settings_profile')}}")
|
||||
.left
|
||||
.form-group
|
||||
| {{ form.full_name.label }}
|
||||
| {{ form.full_name(size=20, class='form-control') }}
|
||||
| {% if form.full_name.errors %}
|
||||
| {% for error in form.full_name.errors %}{{ error|e }}{% endfor %}
|
||||
| {% endif %}
|
||||
|
||||
.form-group
|
||||
| {{ form.username.label }}
|
||||
| {{ form.username(size=20, class='form-control') }}
|
||||
| {% if form.username.errors %}
|
||||
| {% for error in form.username.errors %}{{ error|e }}{% endfor %}
|
||||
| {% endif %}
|
||||
|
||||
|
||||
.form-group.settings-password
|
||||
| Change your password at the
|
||||
a(href="https://blender.org/id/change") Blender ID
|
||||
|
||||
.right
|
||||
.settings-avatar
|
||||
a(href="https://gravatar.com/")
|
||||
img(src="{{ current_user.gravatar }}")
|
||||
span Change Gravatar
|
||||
|
||||
.buttons
|
||||
button.btn.btn-default.button-submit(type='submit')
|
||||
i.pi-check
|
||||
| Save Changes
|
||||
|
||||
|
||||
| {% endblock %}
|
170
src/templates/users/tasks.jade
Normal file
170
src/templates/users/tasks.jade
Normal file
@@ -0,0 +1,170 @@
|
||||
| {% extends 'layout.html' %}
|
||||
|
||||
| {% block header_items %}
|
||||
link(href='//cdn.datatables.net/plug-ins/1.10.7/integration/bootstrap/3/dataTables.bootstrap.css', rel='stylesheet')
|
||||
| {% endblock %}
|
||||
|
||||
| {% block body %}
|
||||
#shots-main.col-md-8
|
||||
table#user_tasks.table.table-striped.table-hover(
|
||||
cellpadding='0', cellspacing='0', border='0')
|
||||
thead
|
||||
tr
|
||||
th {# 0 #}
|
||||
th {# 1 #}
|
||||
th {# 2 #}
|
||||
th {# 3 #}
|
||||
th {# 4 #} Shot
|
||||
th {# 5 #} Name
|
||||
th {# 6 #} Description
|
||||
th {# 7 #} Duration
|
||||
th {# 8 #} Status
|
||||
| {% endblock %}
|
||||
| {% block sidebar %}
|
||||
#shots-sidebar.col-md-4
|
||||
#shot_details_container
|
||||
#task_details_container
|
||||
| {% endblock %}
|
||||
|
||||
| {% block footer_scripts %}
|
||||
script(type='text/javascript', src='//cdn.datatables.net/1.10.7/js/jquery.dataTables.min.js')
|
||||
script().
|
||||
$(document).ready(function(){
|
||||
|
||||
function render_timing(timing) {
|
||||
var timing_text = '';
|
||||
if (timing['cut_in'] && timing['cut_out']) {
|
||||
timing_frames = timing['cut_out'] - timing['cut_in'];
|
||||
|
||||
timing_text += '<span title="';
|
||||
timing_text += timing_frames;
|
||||
timing_text += 'f">';
|
||||
timing_text += Math.round(timing_frames / 24);
|
||||
timing_text += 's</span>';
|
||||
}
|
||||
return timing_text;
|
||||
}
|
||||
|
||||
function render_status_options(status) {
|
||||
var selected = false;
|
||||
var options = []
|
||||
|
||||
statuses = ['todo', 'in_progress', 'on_hold', 'review', 'approved', 'final']
|
||||
$.each(statuses, function(key, value) {
|
||||
selected = false;
|
||||
if (status === value) {
|
||||
selected = true;
|
||||
};
|
||||
option = $("<option />", {
|
||||
value: value,
|
||||
text: value,
|
||||
selected: selected
|
||||
});
|
||||
options.push(option);
|
||||
});
|
||||
return options;
|
||||
}
|
||||
|
||||
function render_status_label(task, task_name) {
|
||||
switch(task.status) {
|
||||
case 'todo':
|
||||
label_text = 'ToDo';
|
||||
break;
|
||||
case 'in_progress':
|
||||
label_text = 'In progress';
|
||||
break;
|
||||
case 'on_hold':
|
||||
label_text = 'On Hold';
|
||||
break;
|
||||
case 'cbb':
|
||||
label_text = 'Could Be Better';
|
||||
break;
|
||||
case 'review':
|
||||
label_text = 'Review';
|
||||
break;
|
||||
case 'approved':
|
||||
label_text = 'Approved';
|
||||
break;
|
||||
case 'final':
|
||||
label_text = 'Final';
|
||||
break;
|
||||
case 'conflict':
|
||||
label_text = 'Conflict';
|
||||
break;
|
||||
default:
|
||||
label_text = task.status;
|
||||
break
|
||||
}
|
||||
|
||||
if (task.is_conflicting) {
|
||||
label_text = 'Conflict';
|
||||
task.status = 'conflict';
|
||||
}
|
||||
|
||||
return tag = '<span task-edit-url="' + task.url_edit + '" class="load-task-view label label-' + task.status + '">' + label_text + '</span>'
|
||||
}
|
||||
|
||||
var shots_table = $('#user_tasks').DataTable({
|
||||
"paging": false,
|
||||
"order": [[ 7, "desc" ]],
|
||||
"data": {{tasks_data | safe}},
|
||||
"columns": [
|
||||
/* */ {"data": "_id"},
|
||||
/* */ {"data": "order"},
|
||||
/* 0 */ {"data": "picture", "width": "80px", "className": "shots-shot_thumbnail"},
|
||||
/* 1 */ {"data": "parent.name"},
|
||||
/* 2 */ {"data": "name", "className": "shots-shot_name"},
|
||||
/* 3 */ {"data": "description", "className": "shots-shot_description"},
|
||||
/* 4 */ {"data": null,},
|
||||
/* 5 */ {"data": "status"},
|
||||
/* 6 */ {"data": null}
|
||||
],
|
||||
"columnDefs": [
|
||||
{
|
||||
"targets": [0, 1],
|
||||
"visible": false,
|
||||
"searchable": false
|
||||
},
|
||||
],
|
||||
|
||||
"rowCallback": function ( row, data, index ) {
|
||||
if ( data.picture) {
|
||||
var img_tag = '<img alt="' + data.name + '" src="' + data.picture_thumbnail + '" class="table-thumbnail">';
|
||||
$('td', row).eq(0).html('<a href="' + data.url_view + '">' + img_tag + '</a>');
|
||||
}
|
||||
|
||||
$('td', row).eq(2).html('<a class="load-shot-view" shot-view-url="' + data.url_edit + '" href="' + data.url_view + '">' + data.name + '</a>');
|
||||
$('td', row).eq(4).html(render_timing(data.timing));
|
||||
$('td', row).eq(5).html(render_status_label(data, data.name));
|
||||
|
||||
var view_tag = '<span class="btn btn-default btn-xs load-shot-view" shot-view-url="' + data.url_edit + '"><i class="glyphicon glyphicon-edit"></i> View</span>';
|
||||
$('td', row).eq(6).html(view_tag);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$(document).on("click", ".load-task-view", function() {
|
||||
$(".task-update").off( "click" );
|
||||
task_view_url = $(this).attr('task-edit-url');
|
||||
$.get(task_view_url, function(data) {
|
||||
$('#shot_details_container').hide();
|
||||
$('#task_details_container').html(data);
|
||||
$('#task_details_container').show();
|
||||
});
|
||||
|
||||
$('.load-task-view').removeClass('active');
|
||||
$(this).addClass('active');
|
||||
|
||||
var shots_table = $('#user_tasks').DataTable();
|
||||
var row = shots_table.row($(this).closest('tr'))
|
||||
|
||||
// Remove class 'active' from rows, and add to current one
|
||||
shots_table.rows('.active').nodes().to$().removeClass('active updated');
|
||||
shots_table.row(row).nodes().to$().addClass('active');
|
||||
|
||||
shots_table.draw();
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
| {% endblock %}
|
16
src/templates/vrview.jade
Normal file
16
src/templates/vrview.jade
Normal file
@@ -0,0 +1,16 @@
|
||||
doctype html
|
||||
html(lang='en')
|
||||
head
|
||||
title VR view
|
||||
meta(charset='utf-8')
|
||||
meta(name='viewport', content='width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0')
|
||||
meta(name='mobile-web-app-capable', content='yes')
|
||||
meta(name='apple-mobile-web-app-capable', content='yes')
|
||||
meta(name='apple-mobile-web-app-status-bar-style', content='black-translucent')
|
||||
link(rel="stylesheet", href="{{url_for('static_pillar', filename='assets/css/vrview.css')}}")
|
||||
body
|
||||
#error.dialog
|
||||
.wrap
|
||||
h1.title Error
|
||||
p.message An unknown error occurred.
|
||||
script(src="{{url_for('static_pillar', filename='assets/js/vrview-analytics.min.js')}}")
|
Reference in New Issue
Block a user