From 4769e2e904aeaf9131dbfde1329ef9292fbca9d6 Mon Sep 17 00:00:00 2001 From: Francesco Siddi Date: Mon, 16 Apr 2018 14:38:08 +0200 Subject: [PATCH] New landing page for Hero project --- cloud/routes.py | 28 +++ src/styles/project-landing.sass | 347 +++++++++++++++++++++++++++++ src/templates/projects/landing.pug | 294 ++++++++++++++++++++++++ 3 files changed, 669 insertions(+) create mode 100644 src/styles/project-landing.sass create mode 100644 src/templates/projects/landing.pug diff --git a/cloud/routes.py b/cloud/routes.py index 9128049..c05e7f1 100644 --- a/cloud/routes.py +++ b/cloud/routes.py @@ -17,6 +17,8 @@ from pillar.web.utils import attach_project_pictures from pillar.web.settings import blueprint as blueprint_settings from pillar.web.nodes.routes import url_for_node from pillar.web.nodes.custom.comments import render_comments_for_node +from pillar.web.projects.routes import render_project +from pillar.web.projects.routes import find_project_or_404 blueprint = Blueprint('cloud', __name__) @@ -434,6 +436,32 @@ def comments_for_node(node_id): return render_comments_for_node(node_id, can_post_comments=can_post_comments) +@blueprint.route('/p/hero') +def project_hero(): + api = system_util.pillar_api() + project = find_project_or_404('hero', + embedded={'header_node': 1}, + api=api) + # Load the header video file, if there is any. + header_video_file = None + header_video_node = None + if project.header_node and project.header_node.node_type == 'asset' and \ + project.header_node.properties.content_type == 'video': + header_video_node = project.header_node + header_video_file = get_file(project.header_node.properties.file) + header_video_node.picture = get_file(header_video_node.picture) + + pages = Node.all({ + 'where': {'project': project._id, 'node_type': 'page'}, + 'projection': {'name': 1}}, api=api) + + return render_project(project, api, + extra_context={'header_video_file': header_video_file, + 'header_video_node': header_video_node, + 'pages': pages._items,}, + template_name='projects/landing.html') + + def setup_app(app): global _homepage_context cached = app.cache.cached(timeout=300) diff --git a/src/styles/project-landing.sass b/src/styles/project-landing.sass new file mode 100644 index 0000000..170cfd4 --- /dev/null +++ b/src/styles/project-landing.sass @@ -0,0 +1,347 @@ +@import ../../../pillar/src/styles/_config +@import ../../../pillar/src/styles/_utils + +$node-latest-thumbnail-size: 160px +$node-latest-gallery-thumbnail-size: 200px +body + background-color: white +.page-body + background-color: white + +nav.navbar + background-color: white + + .navbar-brand + color: $color-text + + li a.navbar-item + color: $color-text + &:hover + color: black + &:focus + color: black + &.active + color: black + .dropdown.open + a + background-color: white + .dropdown.libraries + &:hover + background: none + ul.dropdown-menu + background-color: white + li + a + color: $color-text + &:hover + color: black + background-color: white + .navbar-container + +container-behavior + + .navbar-toggle + border: 2px solid $color-text-dark-primary + color: $color-text + + .navbar-nav + +media-xs + padding: 10px + + .search-input + display: none + +.node-details-container + max-width: 620px + font-family: $font-body + font-size: 1.3em + line-height: 1.5em + margin: 0 auto 40px auto + padding-bottom: 40px + border-bottom: thin solid $color-background + + + p + margin-bottom: 1.3em + +header + display: flex + flex-direction: column /* stack flex items vertically */ + position: relative + img.header + width: 100% + flex-direction: column /* stack flex items vertically */ + position: relative + a.page-card-cta + position: absolute + left: 76% + top: 50% + transform: translate(-50%, -50%) + color: white + font-weight: bold + background: #ff4970 + border-radius: 3px + border: none + box-shadow: 1px 1px 0 rgba(black, .2) + padding: 7px 20px + text-decoration: none + text-shadow: none + + &:hover + background: lighten(#ff4970, 5%) + + +h2 + text-align: center + margin-bottom: 40px + +section + max-width: 1024px + padding-top: 20px + border-top: thin solid $color-background + margin: 0 auto + +a.btn + margin: 20px auto + font-size: 1.3em + padding: 9px 18px + border-radius: 8px + color: $color-text-dark + +.navbar-secondary + max-width: 620px + margin: 0 auto + + .navbar-container + border-bottom: 1px solid #dddddd + + .navbar-collapse + padding-left: 0 + + li + a + padding-left: 20px + padding-right: 20px + color: $color-text + &:hover + &.active + background: none + color: black + box-shadow: 0px 2px 0 rgba(red, .8) + +.node-extra + display: flex + flex-direction: column + + //padding: 0 20px + width: 100% + + + .node-updates + flex: 1 + font-size: 1.1em + + ul + padding: 0 + margin: 0 0 15px 0 + display: flex + flex-direction: row + flex-wrap: wrap + + li + display: flex + flex-direction: column + list-style: none + padding: 5px + cursor: pointer + width: 33.3333% + + +media-xs + width: 100% + + &.texture, &.group_texture + width: 25% + + &:hover + img + opacity: .9 + a.title + //color: $color-primary + text-decoration: underline + + &.post + .info .title + //color: $node-type-post + font-size: 1.1em + a.image + border: none + //border-color: $node-type-post + background-color: hsl(hue($node-type-post), 20%, 55%) + + &.asset.image a.image + border-color: $node-type-asset_image + background-color: hsl(hue($node-type-asset_image), 20%, 55%) + &.asset.file a.image + border-color: $node-type-asset_file + background-color: hsl(hue($node-type-asset_file), 20%, 55%) + &.asset.video a.image + border-color: $node-type-asset_video + background-color: hsl(hue($node-type-asset_video), 20%, 55%) + + .image + width: 100% + height: $node-latest-thumbnail-size + min-height: $node-latest-thumbnail-size + max-height: $node-latest-thumbnail-size + background-color: $color-background + margin: 5px auto 10px auto + position: relative + overflow: hidden + border-radius: 0 + + img + max-height: $node-latest-thumbnail-size + +position-center-translate + + i + color: rgba(white, .9) + font-size: 1.8em + position: absolute + bottom: 3px + left: 5px + text-shadow: 1px 1px 0 rgba(black, .2) + + &.pi-file-archive + font-size: 1.5em + bottom: 5px + &.pi-newspaper + font-size: 1.6em + left: 7px + + .ribbon + +ribbon + + .info + width: 100% + height: 100% + display: flex + flex-direction: column + justify-content: space-between + word-break: break-word + + .description + font-size: 1em + line-height: 1.8em + padding-top: 8px + color: $color-text-dark-primary + + .title + display: block + font-size: 1.3em + color: $color-text-dark + font-weight: 600 + +clearfix + +text-overflow-ellipsis + + span.details + width: 100% + display: block + font-size: 1em + line-height: 1.2em + padding: 5px 0 + color: $color-text-dark-secondary + +clearfix + + .who + margin-left: 3px + .what + text-transform: capitalize + + +$bg-color: #444 +$bg-color2: #666 +$yellow: rgb(249,229,89) +$almost-white: rgb(255,255,255) +$btn-transparent-color: rgba(249,229,89,1) +$btn-transparent-bg: rgba(249,229,89,0) + + +section.gallery + max-width: 1024px + margin: 60px auto 0 auto + text-align: center + padding-bottom: 40px + + p + color: $almost-white + padding: 0 40px + + + .thumbnail + float: left + position: relative + width: 23% + padding-bottom: 23% + margin: 0.83% + overflow: hidden + &:hover + box-shadow: 2px 2px 50px 0 rgba(0,0,0,0.3) + + .img-container + position: absolute + width: 100% + height: 100% + + img + width: 300% + transform: translate(-20%,-10%) + + &:hover .img-caption + top: 0 + left: 0 + .btn-trans + background: rgba(255,255,255,0.4) + + .img-caption + position: absolute + width: 100% + height: 100% + background: rgba(0, 0, 0, 0.3) + text-align: center + + .table + display: table + .table-cell + display: table-cell + vertical-align: bottom + border: none + + @media screen and (max-width: 992px) + .thumbnail + width: 22% + padding-bottom: 22% + margin: 1.5% + + .img-container:hover .img-caption + top: 0 + left: 0 + + .img-caption + position: absolute + width: 100% + height: 100% + background: rgba(0, 0, 0, .7) + text-align: center + a + color: $yellow + + @media screen and (max-width: 720px) + .thumbnail + width: 29% + padding-bottom: 29% + margin: 2.16% + + @media screen and (max-width: 470px) + .thumbnail + width: 44% + padding-bottom: 44% + margin: 3% diff --git a/src/templates/projects/landing.pug b/src/templates/projects/landing.pug new file mode 100644 index 0000000..003ec3a --- /dev/null +++ b/src/templates/projects/landing.pug @@ -0,0 +1,294 @@ +| {% extends 'layout.html' %} + +| {% 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) }}") +meta(name="twitter:image", content="{{ og_picture.thumbnail('l', api=api) }}") +| {% elif node and node.picture %} +meta(property="og:image", content="{{ node.picture.thumbnail('l', api=api) }}") +meta(name="twitter:image", content="{{ node.picture.thumbnail('l', api=api) }}") +| {% elif project.picture_header %} +meta(property="og:image", content="{{ project.picture_header.thumbnail('l', api=api) }}") +meta(name="twitter:image", content="{{ project.picture_header.thumbnail('l', api=api) }}") +| {% endif %} + +| {% if show_project %} +meta(property="og:title", content="{{ project.name }} - Blender Cloud") +meta(name="twitter:title", content="{{ project.name }} - Blender Cloud") +meta(property="og:description", content="{{ project.summary }}") +meta(name="twitter:description", content="{{ project.summary }}") +meta(property="og:url", content="{{ url_for('projects.view', project_url=project.url, _external=True) }}") +| {% else %} + +| {% if node %} +meta(property="og:title", content="{{ node.name }} - Blender Cloud") +meta(name="twitter:title", content="{{ node.name }} on Blender Cloud") + +| {% if node.node_type == 'post' %} + +| {% if node.properties.content %} +meta(property="og:description", content="{{ node.properties.content | truncate(180) }}") +meta(name="twitter:description", content="{{ node.properties.content | truncate(180) }}") +| {% else %} +meta(property="og:description", content="Blender Cloud, your source for open content and training") +meta(name="twitter:description", content="Blender Cloud, your source for open content and training") +| {% endif %} + +| {% else %} + +| {% if node.description %} +meta(property="og:description", content="{{ node.description | truncate(180) }}") +meta(name="twitter:description", content="{{ node.description | truncate(180) }}") +| {% else %} +meta(property="og:description", content="Blender Cloud, your source for open content and training") +meta(name="twitter:description", content="Blender Cloud, your source for open content and training") +| {% endif %} + +| {% endif %} + +meta(property="og:url", content="{{url_for('projects.view_node', project_url=project.url, node_id=node._id)}}") +| {% else %} +meta(property="og:title", content="{{ project.name }} Blog on Blender Cloud") +meta(name="twitter:title", content="{{ project.name }} Blog on Blender Cloud") +meta(property="og:description", content="{{ project.summary }}") +meta(name="twitter:description", content="{{ project.summary }}") + +meta(property="og:url", content="{{url_for('projects.view', project_url=project.url, _external=True)}}") +| {% endif %} + +| {% endif %} +| {% endblock og %} + +| {% block page_overlay %} +#page-overlay.video + .video-embed +#others +| {% endblock %} + +| {% block head %} + +script(src="{{ url_for('static_pillar', filename='assets/js/vendor/videojs-6.2.8.min.js') }}") +script(src="{{ url_for('static_pillar', filename='assets/js/vendor/videojs-ga-0.4.2.min.js') }}") +script(src="{{ url_for('static_pillar', filename='assets/js/vendor/videojs-hotkeys-0.2.20.min.js') }}") +| {% endblock %} + +| {% block css %} +link(href="{{ url_for('static_pillar', filename='assets/css/font-pillar.css') }}", rel="stylesheet") +link(href="{{ url_for('static_pillar', filename='assets/css/base.css') }}", rel="stylesheet") +link(href="{{ url_for('static_cloud', filename='assets/css/project-landing.css') }}", rel="stylesheet") +| {% endblock %} + +| {% block body %} +header + //a(href="{{ url_for( 'projects.view', project_url=project.url) }}") + img.header(src="{{ project.picture_header.thumbnail('l', api=api) }}") + + a.page-card-cta.js-watch-video( + href="https://www.youtube.com/watch?v=NwVGvcIrNWA", + data-youtube-id="NwVGvcIrNWA") + i.pi-play + | Watch Film +| {% block navbar_secondary %} +nav.navbar-secondary + .navbar-container + nav.collapse.navbar-collapse + ul.nav.navbar-nav.navbar-right + li + a.navbar-item( + href="{{ url_for('projects.view', project_url=project.url) }}", + title="{{ project.name }} Homepage") + span + b {{ project.name }} + li + a.navbar-item( + href="{{ url_for('main.project_blog', project_url=project.url) }}", + title="Project Blog", + class="{% if category == 'blog' %}active{% endif %}") + span Blog + | {% for p in pages %} + li + a.navbar-item( + href="{{ url_for('projects.view_node', project_url=project.url, node_id=p._id) }}", + title="{{ p.name }}", + class="{% if category == 'page' %}active{% endif %}") + span {{ p.name }} + | {% endfor %} + li + a.navbar-item( + href="{{ url_for('projects.view_node', project_url=project.url, node_id='5ad24dd91effe4181aff5930') }}", + title="Blender Cloud Blog", + class="{% if category == 'blog' %}active{% endif %}") + span Explore +| {% endblock navbar_secondary %} +#container + section.node-details-container.project + .node-details-title + h1 {{ project.name }} + + | {% if project.description %} + .node-details-description + | {{ project | markdowned('description') }} + | {% endif %} + + + section.gallery + h2 Gallery + | {% for n in activity_stream %} + | {% if n.node_type not in ['comment', 'post'] %} + .thumbnail.expand-image-links + .img-container + a(href="{{ n.picture.thumbnail('l', api=api) }}", data-node_id="{{ n._id }}") + img(src="{{ n.picture.thumbnail('l', api=api) }}", alt="{{ n.name }}") + .img-caption.table + | {# Not using for the moment + span.table-cell {{ n.name }} + | #} + | {% endif %} + | {% endfor %} + div(class="clearfix") + a.btn(href="{{ url_for('main.project_blog', project_url=project.url) }}") See more + + section.node-extra + h2 Latest Updates + + | {% if activity_stream %} + .node-updates + ul.node-updates-list + | {% for n in activity_stream %} + | {% if n.node_type == 'post' %} + li.node-updates-list-item( + data-node_id="{{ n._id }}", + class="{{ n.node_type }} {{ n.properties.content_type | hide_none }}") + a.image(href="{{ url_for_node(node=n) }}") + | {% if n.picture %} + img(src="{{ n.picture.thumbnail('l', api=api) }}") + | {% endif %} + + .info + a.title(href="{{ url_for_node(node=n) }}") {{ n.name }} + p.description(href="{{ url_for_node(node=n) }}") + | {% if n.node_type == 'post' %} + | {{ n.properties | markdowned('content') | striptags | truncate(140, end="... read more") | safe | hide_none }} + | {% else %} + | {{ n | markdowned('description') | striptags | truncate(140, end="... read more") | safe | hide_none }} + | {% endif %} + //span.details + // span.what {% if n.properties.content_type %}{{ n.properties.content_type | undertitle }}{% else %}{{ n.node_type | undertitle }}{% endif %} ยท + // span.when {{ n._updated | pretty_date }} by + // span.who {{ n.user.full_name }} + | {% endif %} + | {% endfor %} + | {% endif %} + a.btn(href="{{ url_for('main.project_blog', project_url=project.url) }}") See all updates + section.social + h2 Contact + p. + Blender Animation Studio + ton@blender.org + + Entrepotdok 57A + 1018 AD Amsterdam + the Netherlands + ul.footer-social + li + a(href="https://www.facebook.com/BlenderCloudOfficial/", + title="Follow us on Facebook") + i.pi-social-facebook + li + a(href="https://twitter.com/Blender_Cloud", + title="Follow us on Twitter") + i.pi-social-twitter + +| {% endblock body %} + + +| {% 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.js-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('') + }); + + function loadNodeContent(url, nodeId) { + + $('#project-loading').addClass('active'); + $.get(url, function (dataHtml) { + // Update the DOM injecting the generate HTML into the page + $('#page-overlay').addClass('active'); + $('#others').html(dataHtml); + // $('#project_context').html(dataHtml); + }) + .done(function () { + // updateUi(nodeId, 'view'); + }) + .fail(function (dataResponse) { + $('#project_context').html($('