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:
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 %}
|
Reference in New Issue
Block a user