40 Commits

Author SHA1 Message Date
e076346765 Start of "production videos", a.k.a. tagged assets overview
Tagged assets are shown in a list per tag. The list is dynamically
loaded with JavaScript.
2018-09-06 15:46:31 +02:00
0b1f295480 Services: Fix layout 2018-09-06 14:33:44 +02:00
a64d3902fd Bootstrap popovers are no longer used. 2018-09-06 14:24:31 +02:00
8dd1de1018 Merge branch 'wip-redesign'
# Conflicts:
#	src/templates/homepage.pug
#	src/templates/services.pug
2018-09-06 14:13:22 +02:00
b12b320cf0 Project view: include video_plugins.min.js 2018-09-06 13:32:57 +02:00
95e51e90de Homepage cleanup. 2018-09-06 13:03:40 +02:00
92106459a0 Use Navigation Tabs for homepage and index collections 2018-09-06 13:03:22 +02:00
982047fc3b Pug: Tweaks to components 2018-09-06 12:59:48 +02:00
5a36888f61 Navigation: Dropdowns for Services and Open Projects 2018-09-06 12:58:56 +02:00
59e0adf3ca Pug: Bring new templates from Pillar 2018-09-06 12:54:15 +02:00
3fdbb92b93 Fixed typo 2018-09-05 15:11:46 +02:00
cf98883633 Make <meta property="og:url"> tags have an absolute URL
Most of those can simply use `{{ request.url }}`, as this already contains
the absolute URL of the currently displayed page.
2018-09-05 13:58:13 +02:00
7b32b97203 Remove https://cloud.blender.org from URLs
URLs should be host-relative, so that they also work on devservers.
URLs in emails should remain absolute, though; we may want to change those
to use {{ url_for(..., _external=True) }} at some point.
2018-09-05 13:57:15 +02:00
7f58be4568 Updated Blender Cloud add-on to 1.9.0
Also change the config_local.py so that we only have to change one variable
for a new version.
2018-09-05 13:40:24 +02:00
c25df6f0ad Cleanup 2018-08-31 19:33:14 +02:00
813750a006 Layout cleanup 2018-08-31 19:08:52 +02:00
9ba2735c8c CSS Cleanup 2018-08-31 19:08:23 +02:00
73e8a81f3c Minor style tweaks 2018-08-31 13:58:26 +02:00
9ffcde3348 Use styling from Pillar 2018-08-31 13:58:08 +02:00
f0b18e88f4 Use pug mixins for header, cards and navigation 2018-08-31 13:57:51 +02:00
ed211f9473 Introducing Pug mixin components
For now added jumbotron, secondary navigation, card decks and individual cards.

Thanks @sybren for the suggestion.
2018-08-31 13:57:09 +02:00
7a4c7d75f6 Project Landing uses new CSS 2018-08-31 13:55:35 +02:00
cc16351136 NPM: Upgrade libraries
New dependency is jQuery, we already depended on it it but now we use it
from npm package for easier version control and upgrades.
2018-08-31 13:54:39 +02:00
7dc1e6f9a1 Gulp: Only chmod files when in --production 2018-08-31 13:53:37 +02:00
fcf715b5b1 Services page: move to bootstrap 4 2018-08-31 13:52:40 +02:00
099984f97c Added #!/bin/sh at top of shell script 2018-08-30 12:53:34 +02:00
8bfb40ce54 Various Docker image upgrades, read the entire commit message!
- Ubuntu 17.10 → 18.04.
- Python 3.6.3 → 3.6.6.
- Use `DEBIAN_FRONTEND=noninteractive` to prevent prompts during
  installation.
- Install `tzdata` in the base image as it's required by subimages.
- Correctly set maintainer in Dockerfile.
2018-08-30 12:53:34 +02:00
d60a65c9f0 End BLENDER_ID_ENDPOINT with a slash 2018-08-30 12:46:58 +02:00
9cd2853e49 Upgrade pip after building Python 2018-08-30 12:31:31 +02:00
3d5554d9ce BLENDER_ID_ENDPOINT should end with a slash
There is always a path component in a URL.
2018-08-29 14:20:23 +02:00
764ccfa78e Add -e . to requirements-dev.txt 2018-08-29 12:24:45 +02:00
0b8ebecfea Don't import flask_login.request
`flask_login.request` is the exact same thing as `flask.request`, so
importing it from `flask_login` makes no sense. Also, it's been removed
from the new Flask-Login.
2018-08-29 12:19:40 +02:00
68d09dc886 CSS: cleanup 2018-08-28 15:56:06 +02:00
169a7f51f0 navbar-container: cleanup 2018-08-28 15:55:32 +02:00
f48a4883ae Index collection redesign 2018-08-27 16:58:01 +02:00
01b6693324 Cleanup styling. Use bootstrap classes instead 2018-08-27 16:57:34 +02:00
012ba06655 Use system fonts (see main.sass) 2018-08-27 16:55:48 +02:00
2be601d0b0 Introducing Bootstrap 4
Bootstrap (and its dependency popper.js) are now used from npm packages,
allowing better version control and custom building of only the required
components for both styling and javascript.

At this moment the whole styling of bootstrap is included, once the Cloud
redesign is over it will be stripped to only the used components.
2018-08-27 16:52:22 +02:00
4dc11b075a Gulp: watch Pillar styles folder for changes and compile Sass 2018-08-27 15:17:00 +02:00
4696d09fed Corrected rewrite rule for Caminandes 2018-07-06 14:56:40 +02:00
206 changed files with 5173 additions and 12221 deletions

4
.gitignore vendored
View File

@@ -3,9 +3,11 @@
.coverage .coverage
*.pyc *.pyc
__pycache__ __pycache__
*.js.map
*.css.map
/cloud/templates/ /cloud/templates/
/cloud/static/assets/css/ /cloud/static/assets/
node_modules/ node_modules/
/config_local.py /config_local.py

View File

@@ -41,6 +41,7 @@ class CloudExtension(PillarExtension):
'EXTERNAL_SUBSCRIPTIONS_MANAGEMENT_SERVER': 'https://store.blender.org/api/', 'EXTERNAL_SUBSCRIPTIONS_MANAGEMENT_SERVER': 'https://store.blender.org/api/',
'EXTERNAL_SUBSCRIPTIONS_TIMEOUT_SECS': 10, 'EXTERNAL_SUBSCRIPTIONS_TIMEOUT_SECS': 10,
'BLENDER_ID_WEBHOOK_USER_CHANGED_SECRET': 'oos9wah1Zoa0Yau6ahThohleiChephoi', 'BLENDER_ID_WEBHOOK_USER_CHANGED_SECRET': 'oos9wah1Zoa0Yau6ahThohleiChephoi',
'NODE_TAGS': ['animation', 'modelling', 'rigging'],
} }
def eve_settings(self): def eve_settings(self):

View File

@@ -391,6 +391,11 @@ def privacy():
return render_template('privacy.html') return render_template('privacy.html')
@blueprint.route('/production')
def production():
return render_template('production.html')
@blueprint.route('/emails/welcome.send') @blueprint.route('/emails/welcome.send')
@login_required @login_required
def emails_welcome_send(): def emails_welcome_send():

View File

@@ -1,55 +0,0 @@
/* Variables
================================================================== */
var searchToggleStatus = false
/* Selectors
================================================================== */
var searchButton = document.querySelector('#searchButton'),
searchCloseButton = document.querySelector('#searchCloseButton'),
searchNav = document.querySelector('#searchNav'),
searchNavInput = document.querySelector('#searchNav input'),
navbarNav = document.querySelector('#navbarNav'),
profileMenu = document.querySelector('#navbarNav .navbar-nav').lastElementChild
/* Interactions
================================================================== */
searchButton.addEventListener('click', showSearch)
searchCloseButton.addEventListener('click', closeSearch)
/* Functions
================================================================== */
function showSearch() {
searchToggleStatus = true
searchNav.classList.remove('hidden')
searchNavInput.focus()
navbarNav.classList.add('hidden')
profileMenu.classList.add('visible')
// $('#search-overlay').addClass('visible')
// if (searchToggleStatus == true) {
// // $(document.body).click(function() {
// // console.log('detect click outside');
// // searchToggleStatus = false
// // })
// console.log(searchToggleStatus);
// console.log('detect click outside');
// searchToggleStatus = false
// console.log(searchToggleStatus);
// } else {
// console.log(searchToggleStatus);
// console.log('not detecting clicks');
// }
// $(document.body).click(function () {
// console.log('detected click outside');
// searchToggleStatus == false
// }) else {
// }
}
function closeSearch() {
searchNav.classList.add('hidden')
navbarNav.classList.remove('hidden')
profileMenu.classList.remove('visible')
// $('#search-overlay').removeClass('active')
}

3
cloud/tagged/__init__.py Normal file
View File

@@ -0,0 +1,3 @@
"""Routes for fetching tagged assets."""

16
cloud/tagged/routes.py Normal file
View File

@@ -0,0 +1,16 @@
import logging
import datetime
import functools
from flask import Blueprint, jsonify
blueprint = Blueprint('cloud.tagged', __name__, url_prefix='/tagged')
log = logging.getLogger(__name__)
@blueprint.route('/')
def index():
"""Return all tagged assets as JSON, grouped by tag."""

View File

@@ -7,8 +7,7 @@ import json
import logging import logging
import typing import typing
from flask_login import request from flask import Blueprint, request
from flask import Blueprint
import werkzeug.exceptions as wz_exceptions import werkzeug.exceptions as wz_exceptions
from pillar import current_app from pillar import current_app

View File

@@ -2,7 +2,7 @@ import os
DEBUG = True DEBUG = True
BLENDER_ID_ENDPOINT = 'http://id.local:8000' BLENDER_ID_ENDPOINT = 'http://id.local:8000/'
SERVER_NAME = 'cloud.local:5001' SERVER_NAME = 'cloud.local:5001'
SCHEME = 'http' SCHEME = 'http'

View File

@@ -1,6 +1,10 @@
FROM ubuntu:17.10 FROM ubuntu:18.04
MAINTAINER Francesco Siddi <francesco@blender.org> LABEL maintainer="Sybren A. Stüvel <sybren@blender.studio>"
RUN apt-get update && apt-get install -qyy \ RUN set -ex; \
-o APT::Install-Recommends=false -o APT::Install-Suggests=false \ apt-get update; \
openssl ca-certificates DEBIAN_FRONTEND=noninteractive apt-get install \
-qyy -o APT::Install-Recommends=false -o APT::Install-Suggests=false \
tzdata openssl ca-certificates locales; \
locale-gen en_US.UTF-8 en_GB.UTF-8 nl_NL.UTF-8
ENV LANG en_US.UTF-8

View File

@@ -1 +0,0 @@
1325134dd525b4a2c3272a1a0214dd54 Python-3.6.4.tar.xz

View File

@@ -0,0 +1 @@
c3f30a0aff425dda77d19e02f420d6ba Python-3.6.6.tar.xz

View File

@@ -34,6 +34,9 @@ make -j8 install
# Make sure we can run Python # Make sure we can run Python
ldconfig ldconfig
# Upgrade pip
/opt/python/bin/python3 -m pip install -U pip
# Build mod-wsgi-py3 for Python 3.6 # Build mod-wsgi-py3 for Python 3.6
cd /dpkg/mod-wsgi-* cd /dpkg/mod-wsgi-*
./configure --with-python=/opt/python/bin/python3 ./configure --with-python=/opt/python/bin/python3

View File

@@ -1,9 +1,9 @@
FROM pillar_base FROM pillar_base
LABEL maintainer Sybren A. Stüvel <sybren@blender.studio> LABEL maintainer="Sybren A. Stüvel <sybren@blender.studio>"
RUN sed -i 's/^# deb-src/deb-src/' /etc/apt/sources.list && \ RUN sed -i 's/^# deb-src/deb-src/' /etc/apt/sources.list && \
apt-get update && \ apt-get update && \
apt-get install -qy \ DEBIAN_FRONTEND=noninteractive apt-get install -qy \
build-essential \ build-essential \
apache2-dev \ apache2-dev \
checkinstall \ checkinstall \
@@ -11,13 +11,13 @@ RUN sed -i 's/^# deb-src/deb-src/' /etc/apt/sources.list && \
RUN apt-get build-dep -y python3.6 RUN apt-get build-dep -y python3.6
ADD Python-3.6.4.tar.xz.md5 /Python-3.6.4.tar.xz.md5 ADD Python-3.6.6.tar.xz.md5 /Python-3.6.6.tar.xz.md5
# Install Python sources # Install Python sources
RUN curl -O https://www.python.org/ftp/python/3.6.4/Python-3.6.4.tar.xz && \ RUN curl -O https://www.python.org/ftp/python/3.6.6/Python-3.6.6.tar.xz && \
md5sum -c Python-3.6.4.tar.xz.md5 && \ md5sum -c Python-3.6.6.tar.xz.md5 && \
tar xf Python-3.6.4.tar.xz && \ tar xf Python-3.6.6.tar.xz && \
rm -v Python-3.6.4.tar.xz rm -v Python-3.6.6.tar.xz
# Install mod-wsgi sources # Install mod-wsgi sources
RUN mkdir -p /dpkg && cd /dpkg && apt-get source libapache2-mod-wsgi-py3 RUN mkdir -p /dpkg && cd /dpkg && apt-get source libapache2-mod-wsgi-py3
@@ -32,4 +32,4 @@ RUN echo /opt/python/lib > /etc/ld.so.conf.d/python.conf
RUN ldconfig RUN ldconfig
ENV PATH=/opt/python/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin ENV PATH=/opt/python/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
ENV PYTHONSOURCE=/Python-3.6.4 ENV PYTHONSOURCE=/Python-3.6.6

View File

@@ -1,5 +1,5 @@
FROM pillar_base FROM pillar_base
LABEL maintainer Sybren A. Stüvel <sybren@blender.studio> LABEL maintainer="Sybren A. Stüvel <sybren@blender.studio>"
ADD python /opt/python ADD python /opt/python
@@ -10,5 +10,4 @@ RUN echo Python is installed in /opt/python/ > README.python
ENV PATH=/opt/python/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin ENV PATH=/opt/python/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
RUN cd /opt/python/bin && \ RUN cd /opt/python/bin && \
ln -s python3 python && \ ln -s python3 python
ln -s pip3 pip

View File

@@ -1,7 +1,9 @@
FROM armadillica/pillar_py:3.6 FROM armadillica/pillar_py:3.6
LABEL maintainer Sybren A. Stüvel <sybren@blender.studio> LABEL maintainer="Sybren A. Stüvel <sybren@blender.studio>"
RUN apt-get update && apt-get install -qy \ RUN set -ex; \
apt-get update; \
DEBIAN_FRONTEND=noninteractive apt-get install -qy \
git \ git \
build-essential \ build-essential \
checkinstall \ checkinstall \

View File

@@ -1,7 +1,9 @@
FROM armadillica/pillar_py:3.6 FROM armadillica/pillar_py:3.6
LABEL maintainer Sybren A. Stüvel <sybren@blender.studio> LABEL maintainer="Sybren A. Stüvel <sybren@blender.studio>"
RUN apt-get update && apt-get install -qyy \ RUN set -ex; \
apt-get update; \
DEBIAN_FRONTEND=noninteractive apt-get install -qy \
-o APT::Install-Recommends=false -o APT::Install-Suggests=false \ -o APT::Install-Recommends=false -o APT::Install-Suggests=false \
git \ git \
apache2 \ apache2 \
@@ -10,8 +12,8 @@ libjpeg8 \
libtiff5 \ libtiff5 \
ffmpeg \ ffmpeg \
rsyslog logrotate \ rsyslog logrotate \
nano vim-tiny curl \ nano vim-tiny curl; \
&& rm -rf /var/lib/apt/lists/* rm -rf /var/lib/apt/lists/*
RUN ln -s /usr/bin/vim.tiny /usr/bin/vim RUN ln -s /usr/bin/vim.tiny /usr/bin/vim

View File

@@ -40,7 +40,7 @@
# Redirects for blender-cloud projects # Redirects for blender-cloud projects
RewriteRule "^/p/blender-cloud/?$" "/blog" [R=301,L] RewriteRule "^/p/blender-cloud/?$" "/blog" [R=301,L]
RewriteRule "^/agent327/?$" "/p/agent-327" [R=301,L] RewriteRule "^/agent327/?$" "/p/agent-327" [R=301,L]
RewriteRule "^/caminandes/?$" "/p/caminandes" [R=301,L] RewriteRule "^/caminandes/?$" "/p/caminandes-3" [R=301,L]
RewriteRule "^/cf2/?$" "/p/creature-factory-2" [R=301,L] RewriteRule "^/cf2/?$" "/p/creature-factory-2" [R=301,L]
RewriteRule "^/characters/?$" "/p/characters" [R=301,L] RewriteRule "^/characters/?$" "/p/characters" [R=301,L]
RewriteRule "^/gallery/?$" "/p/gallery" [R=301,L] RewriteRule "^/gallery/?$" "/p/gallery" [R=301,L]

View File

@@ -28,7 +28,7 @@ CACHE_REDIS_URL = 'redis://redis:6379'
PILLAR_SERVER_ENDPOINT = 'https://cloud.blender.org/api/' PILLAR_SERVER_ENDPOINT = 'https://cloud.blender.org/api/'
BLENDER_ID_ENDPOINT = 'https://www.blender.org/id' BLENDER_ID_ENDPOINT = 'https://www.blender.org/id/'
GCLOUD_APP_CREDENTIALS = '/data/config/google_app.json' GCLOUD_APP_CREDENTIALS = '/data/config/google_app.json'
GCLOUD_PROJECT = 'blender-cloud' GCLOUD_PROJECT = 'blender-cloud'
@@ -83,21 +83,22 @@ LOGGING = {
} }
} }
# Latest version of the add-on.
BLENDER_CLOUD_ADDON_VERSION = '1.9.0'
REDIRECTS = { REDIRECTS = {
# For old links, refer to the services page (hopefully it refreshes then) # For old links, refer to the services page (hopefully it refreshes then)
'downloads/blender_cloud-latest-bundle.zip': 'https://cloud.blender.org/services#blender-addon', 'downloads/blender_cloud-latest-bundle.zip': 'https://cloud.blender.org/services#blender-addon',
# Latest Blender Cloud add-on; remember to update BLENDER_CLOUD_ADDON_VERSION. # Latest Blender Cloud add-on.
'downloads/blender_cloud-latest-addon.zip': 'downloads/blender_cloud-latest-addon.zip':
'https://storage.googleapis.com/institute-storage/addons/blender_cloud-1.8.0.addon.zip', f'https://storage.googleapis.com/institute-storage/addons/'
f'blender_cloud-{BLENDER_CLOUD_ADDON_VERSION}.addon.zip',
# Redirect old Grafista endpoint to /stats # Redirect old Grafista endpoint to /stats
'/stats/': '/stats', '/stats/': '/stats',
} }
# Latest version of the add-on; remember to update REDIRECTS.
BLENDER_CLOUD_ADDON_VERSION = '1.8.0'
UTM_LINKS = { UTM_LINKS = {
'cartoon_brew': { 'cartoon_brew': {
'image': 'https://imgur.com/13nQTi3.png', 'image': 'https://imgur.com/13nQTi3.png',

View File

@@ -1,3 +1,4 @@
#!/bin/sh
if [ -f /installed ]; then if [ -f /installed ]; then
return return

View File

@@ -1,113 +1,160 @@
let argv = require('minimist')(process.argv.slice(2)); var argv = require('minimist')(process.argv.slice(2));
let autoprefixer = require('gulp-autoprefixer'); var autoprefixer = require('gulp-autoprefixer');
let cache = require('gulp-cached'); var cache = require('gulp-cached');
let concat = require('gulp-concat'); var chmod = require('gulp-chmod');
let gulp = require('gulp'); var concat = require('gulp-concat');
let gulpif = require('gulp-if'); var git = require('gulp-git');
let pug = require('gulp-pug'); var gulp = require('gulp');
let livereload = require('gulp-livereload'); var gulpif = require('gulp-if');
let plumber = require('gulp-plumber'); var pug = require('gulp-pug');
let rename = require('gulp-rename'); var livereload = require('gulp-livereload');
let sass = require('gulp-sass'); var plumber = require('gulp-plumber');
let sourcemaps = require('gulp-sourcemaps'); var rename = require('gulp-rename');
let uglify = require('gulp-uglify'); var sass = require('gulp-sass');
var sourcemaps = require('gulp-sourcemaps');
var uglify = require('gulp-uglify-es').default;
let enabled = { var enabled = {
uglify: argv.production,
maps: !argv.production,
failCheck: !argv.production, failCheck: !argv.production,
maps: argv.production,
prettyPug: !argv.production, prettyPug: !argv.production,
uglify: argv.production cachify: !argv.production,
cleanup: argv.production,
chmod: argv.production,
}; };
let destination = { var destination = {
css: 'cloud/static/assets/css', css: 'cloud/static/assets/css',
pug: 'cloud/templates', pug: 'cloud/templates',
js: 'cloud/static/assets/js' js: 'cloud/static/assets/js',
}; }
var source = {
pillar: '../pillar/',
bootstrap: 'node_modules/bootstrap/',
popper: 'node_modules/popper.js/'
}
/* CSS */ /* CSS */
gulp.task('styles', function(done) { gulp.task('styles', function() {
gulp gulp.src('src/styles/**/*.sass')
.src('src/styles/**/*.sass')
.pipe(gulpif(enabled.failCheck, plumber())) .pipe(gulpif(enabled.failCheck, plumber()))
.pipe(gulpif(enabled.maps, sourcemaps.init())) .pipe(gulpif(enabled.maps, sourcemaps.init()))
.pipe(sass({outputStyle: 'compressed'})) .pipe(sass({
outputStyle: 'compressed'}
))
.pipe(autoprefixer("last 3 versions")) .pipe(autoprefixer("last 3 versions"))
.pipe(gulpif(enabled.maps, sourcemaps.write("."))) .pipe(gulpif(enabled.maps, sourcemaps.write(".")))
.pipe(gulp.dest(destination.css)) .pipe(gulp.dest(destination.css))
.pipe(gulpif(argv.livereload, livereload())); .pipe(gulpif(argv.livereload, livereload()));
done();
}); });
/* Templates - Pug */ /* Templates - Pug */
gulp.task('templates', function(done) { gulp.task('templates', function() {
gulp.src('src/templates/**/*.pug') gulp.src('src/templates/**/*.pug')
.pipe(gulpif(enabled.failCheck, plumber())) .pipe(gulpif(enabled.failCheck, plumber()))
.pipe(cache('templating')) .pipe(gulpif(enabled.cachify, cache('templating')))
.pipe(pug({ .pipe(pug({
pretty: enabled.prettyPug pretty: enabled.prettyPug
})) }))
.pipe(gulp.dest(destination.pug)) .pipe(gulp.dest(destination.pug))
.pipe(gulpif(argv.livereload, livereload())); .pipe(gulpif(argv.livereload, livereload()));
done(); // TODO(venomgfx): please check why 'gulp watch' doesn't pick up on .txt changes.
gulp.src('src/templates/**/*.txt')
.pipe(gulpif(enabled.failCheck, plumber()))
.pipe(gulpif(enabled.cachify, cache('templating')))
.pipe(gulp.dest(destination.pug))
.pipe(gulpif(argv.livereload, livereload()));
}); });
/* Individually uglified scripts */ /* Individual Uglified Scripts */
gulp.task('scripts', function(done) { gulp.task('scripts', function() {
gulp.src('src/scripts/*.js') gulp.src('src/scripts/*.js')
.pipe(gulpif(enabled.failCheck, plumber())) .pipe(gulpif(enabled.failCheck, plumber()))
.pipe(cache('scripting')) .pipe(gulpif(enabled.cachify, cache('scripting')))
.pipe(gulpif(enabled.maps, sourcemaps.init())) .pipe(gulpif(enabled.maps, sourcemaps.init()))
.pipe(gulpif(enabled.uglify, uglify())) .pipe(gulpif(enabled.uglify, uglify()))
.pipe(rename({suffix: '.min'})) .pipe(rename({suffix: '.min'}))
.pipe(gulpif(enabled.maps, sourcemaps.write("."))) .pipe(gulpif(enabled.maps, sourcemaps.write(".")))
.pipe(gulpif(enabled.chmod, chmod(644)))
.pipe(gulp.dest(destination.js)) .pipe(gulp.dest(destination.js))
.pipe(gulpif(argv.livereload, livereload())); .pipe(gulpif(argv.livereload, livereload()));
done();
}); });
/* Collection of scripts in src/scripts/tutti/ to merge into tutti.min.js */ /* Collection of scripts in src/scripts/tutti/ to merge into tutti.min.js */
/* Since it's always loaded, it's only for functions that we want site-wide */ /* Since it's always loaded, it's only for functions that we want site-wide */
gulp.task('scripts_tutti', function(done) { gulp.task('scripts_concat_tutti', function() {
gulp.src('src/scripts/tutti/**/*.js') gulp.src('src/scripts/tutti/**/*.js')
.pipe(gulpif(enabled.failCheck, plumber())) .pipe(gulpif(enabled.failCheck, plumber()))
.pipe(gulpif(enabled.maps, sourcemaps.init())) .pipe(gulpif(enabled.maps, sourcemaps.init()))
.pipe(concat("tutti.min.js")) .pipe(concat("tutti.min.js"))
.pipe(gulpif(enabled.uglify, uglify())) .pipe(gulpif(enabled.uglify, uglify()))
.pipe(gulpif(enabled.maps, sourcemaps.write("."))) .pipe(gulpif(enabled.maps, sourcemaps.write(".")))
.pipe(gulpif(enabled.chmod, chmod(644)))
.pipe(gulp.dest(destination.js)) .pipe(gulp.dest(destination.js))
.pipe(gulpif(argv.livereload, livereload())); .pipe(gulpif(argv.livereload, livereload()));
done();
}); });
/* Simply move these vendor scripts from node_modules */ // Combine all needed Bootstrap JavaScript into a single file.
gulp.task('scripts_vendor', function(done) { gulp.task('scripts_concat_bootstrap', function() {
let toMove = [
'node_modules/photoswipe/dist/photoswipe.min.js' toUglify = [
source.popper + 'dist/umd/popper.min.js',
source.bootstrap + 'js/dist/index.js',
source.bootstrap + 'js/dist/util.js',
source.bootstrap + 'js/dist/tooltip.js',
source.bootstrap + 'js/dist/dropdown.js',
]; ];
gulp.src(toMove)
.pipe(gulp.dest(destination.js)); gulp.src(toUglify)
done(); .pipe(gulpif(enabled.failCheck, plumber()))
.pipe(gulpif(enabled.maps, sourcemaps.init()))
.pipe(concat("bootstrap.min.js"))
.pipe(gulpif(enabled.uglify, uglify()))
.pipe(gulpif(enabled.maps, sourcemaps.write(".")))
.pipe(gulpif(enabled.chmod, chmod(644)))
.pipe(gulp.dest(destination.js))
.pipe(gulpif(argv.livereload, livereload()));
}); });
// While developing, run 'gulp watch' // While developing, run 'gulp watch'
gulp.task('watch', function(done) { gulp.task('watch',function() {
// Only reload the pages if we run with --livereload // Only listen for live reloads if ran with --livereload
if (argv.livereload){ if (argv.livereload){
livereload.listen(); livereload.listen();
} }
gulp.watch('src/styles/**/*.sass', gulp.series('styles')); gulp.watch('src/styles/**/*.sass',['styles']);
gulp.watch('src/templates/**/*.pug', gulp.series('templates')); gulp.watch(source.pillar + 'src/styles/**/*.sass',['styles']);
gulp.watch('src/scripts/*.js', gulp.series('scripts'));
gulp.watch('src/scripts/tutti/*.js', gulp.series('scripts_tutti')); gulp.watch('src/templates/**/*.pug',['templates']);
gulp.watch('src/scripts/*.js',['scripts']);
gulp.watch('src/scripts/tutti/**/*.js',['scripts_concat_tutti']);
});
// Erases all generated files in output directories.
gulp.task('cleanup', function() {
var paths = [];
for (attr in destination) {
paths.push(destination[attr]);
}
git.clean({ args: '-f -X ' + paths.join(' ') }, function (err) {
if(err) throw err;
});
}); });
// Run 'gulp' to build everything at once // Run 'gulp' to build everything at once
gulp.task('default', gulp.series('styles', 'templates', 'scripts', 'scripts_tutti', 'scripts_vendor')); var tasks = [];
if (enabled.cleanup) tasks.push('cleanup');
gulp.task('default', tasks.concat(['styles', 'templates', 'scripts', 'scripts_concat_tutti', 'scripts_concat_bootstrap']));

4812
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -7,26 +7,25 @@
"url": "git://git.blender.org/blender-cloud.git" "url": "git://git.blender.org/blender-cloud.git"
}, },
"devDependencies": { "devDependencies": {
"gulp": "^4.0.0", "gulp": "~3.9.1",
"gulp-autoprefixer": "~5.0.0", "gulp-autoprefixer": "~6.0.0",
"gulp-cached": "~1.1.1", "gulp-cached": "~1.1.1",
"gulp-chmod": "~2.0.0", "gulp-chmod": "~2.0.0",
"gulp-concat": "~2.6.1", "gulp-concat": "~2.6.1",
"gulp-git": "~2.7.0",
"gulp-if": "^2.0.2", "gulp-if": "^2.0.2",
"gulp-livereload": "~3.8.1", "gulp-git": "~2.8.0",
"gulp-livereload": "~4.0.0",
"gulp-plumber": "~1.2.0", "gulp-plumber": "~1.2.0",
"gulp-pug": "~4.0.1", "gulp-pug": "~4.0.1",
"gulp-rename": "~1.3.0", "gulp-rename": "~1.4.0",
"gulp-sass": "~4.0.1", "gulp-sass": "~4.0.1",
"gulp-sourcemaps": "~2.6.4", "gulp-sourcemaps": "~2.6.4",
"gulp-uglify": "~3.0.0", "gulp-uglify-es": "^1.0.4",
"minimist": "^1.2.0" "minimist": "^1.2.0"
}, },
"dependencies": { "dependencies": {
"bootstrap": "^4.1.2", "bootstrap": "^4.1.3",
"jquery": "^3.3.1", "jquery": "^3.3.1",
"popper.js": "^1.14.3", "popper.js": "^1.14.4"
"photoswipe": "^4.1.2"
} }
} }

View File

@@ -9,3 +9,4 @@
-e ../attract -e ../attract
-e ../flamenco -e ../flamenco
-e ../pillar-svnman -e ../pillar-svnman
-e .

View File

@@ -1,42 +0,0 @@
/* Selectors
================================================================== */
var searchButton = document.querySelector('#searchButton'),
searchCloseButton = document.querySelector('#searchCloseButton'),
searchNav = document.querySelector('#searchNav'),
searchNavInput = document.querySelector('#searchNav input'),
navbarNav = document.querySelector('#navbarNav'),
profileMenu = document.querySelector('#navbarNav .navbar-nav').lastElementChild
/* Interactions
================================================================== */
searchButton.addEventListener('click', showSearch)
searchCloseButton.addEventListener('click', closeSearch)
searchNavInput.onblur = function() {
closeSearch()
}
/* Functions
================================================================== */
function showSearch() {
searchToggleStatus = true
searchNav.classList.remove('hidden')
searchNavInput.focus()
navbarNav.classList.add('hidden')
profileMenu.classList.add('visible')
document.addEventListener('keyup', onPressEscCloseSearch)
}
function closeSearch() {
searchNav.classList.add('hidden')
navbarNav.classList.remove('hidden')
profileMenu.classList.remove('visible')
document.removeEventListener('keyup', onPressEscCloseSearch)
}
function onPressEscCloseSearch(e) {
if (e.keyCode == 27) {
closeSearch()
}
}

View File

@@ -0,0 +1,109 @@
/**
* Support for fetching & rendering assets by tags.
*/
(function($) {
/* How many nodes to load initially, and when clicked on the 'Load Next' link. */
const LOAD_INITIAL_COUNT = 5;
const LOAD_NEXT_COUNT = 3;
/* Renders a node as a <li> element, returns a jQuery object. */
function renderAsset(node) {
let li = $('<li>').addClass('tagged-asset');
let link = $('<a>')
.attr('href', '/nodes/' + node._id + '/redir')
.appendTo(li);
function warnNoPicture() {
li.addClass('warning');
link.text('no picture for node ' + node._id);
}
if (!node.picture) {
warnNoPicture();
return li;
}
// TODO: show 'loading' thingy
$.get('/api/files/' + node.picture)
.fail(function(error) {
let msg = xhrErrorResponseMessage(error);
li.addClass('error').text(msg);
})
.done(function(resp) {
// Render the picture if it has the proper size.
var show_variation = null;
if (typeof resp.variations != 'undefined') {
for (variation of resp.variations) {
if (variation.size != 'm') continue;
show_variation = variation;
break;
}
}
if (show_variation == null) {
warnNoPicture();
return;
}
let img = $('<img>')
.attr('alt', node.name)
.attr('src', variation.link)
.attr('width', variation.width)
.attr('height', variation.height);
link.append(img);
});
return li;
}
function loadNext(ul_element) {
let $ul = $(ul_element);
let tagged_assets = ul_element.tagged_assets; // Stored here by loadTaggedAssets().
let already_loaded = $ul.find('li.tagged-asset').length;
let load_next = $ul.find('li.load-next');
let nodes_to_load = tagged_assets.slice(already_loaded, already_loaded + LOAD_NEXT_COUNT);
for (node of nodes_to_load) {
let li = renderAsset(node);
load_next.before(li);
}
if (already_loaded + LOAD_NEXT_COUNT >= tagged_assets.length)
load_next.remove();
}
$.fn.loadTaggedAssets = function(api_base_url) {
this.each(function(index, ul_element) {
// TODO(Sybren): show a 'loading' animation.
$.get('/api/nodes/tagged/' + ul_element.dataset.assetTag)
.fail(function(error) {
let msg = xhrErrorResponseMessage(error);
$('<li>').addClass('error').text(msg).appendTo(ul_element);
})
.done(function(resp) {
// 'resp' is a list of node documents.
// Store the response on the DOM <ul>-element so that we can later render more.
ul_element.tagged_assets = resp;
// Here render the first N.
for (node of resp.slice(0, LOAD_INITIAL_COUNT)) {
let li = renderAsset(node);
li.appendTo(ul_element);
}
// Don't bother with a 'load next' link if there is no more.
if (resp.length <= LOAD_INITIAL_COUNT) return;
// Construct the 'load next' link.
let load_next = $('<li>').addClass('load-next');
let link = $('<a>')
.attr('href', 'javascript:void(0);')
.click(function() { loadNext(ul_element); return false; })
.text('Load next')
.appendTo(load_next);
load_next.appendTo(ul_element);
});
});
};
}(jQuery));

View File

@@ -1,8 +0,0 @@
// Bootstrap Breakpoints
// sm 576.98px
// md 576px - 757.98px
// lg 992px to 1199.98px
// xl 1200px and up
@import ../../static/assets/bootstrap/sass/functions
@import ../../static/assets/bootstrap/sass/variables
@import ../../static/assets/bootstrap/sass/mixins/breakpoints

View File

@@ -1,36 +0,0 @@
.container.card-container
max-width: 1200px
margin-top: 56px
.col-md-4
padding: 0 20px
&:focus
outline: none;
.card
border: none
margin-bottom: 64px
.card-image
background-color: #ccc
border-radius: 0
height: 160px
max-height: 160px
min-height: 160px
margin: 0 auto
overflow: hidden
width: 100%
+media-breakpoint-up(sm)
height: 203px
max-height: 203px
min-height: 203px
img
height: 100%
object-fit: cover
.card-title
margin: 11px 0 5px
font-size: 27px
a
color: #111
text-decoration: none
.card-text
font-size: 18px
.card-body
padding: 0

View File

@@ -1,9 +0,0 @@
$primary: #0A68FF
$grey: #EBEBEB
$gray: #EBEBEB
$dark: rgba(17,17,17,1)
$muted: rgba(17,17,17,0.75)
$lightgray: #F5F5F5
// $theme-colors:
// primary: red
//

View File

@@ -1,54 +0,0 @@
@import ../styles/colors
@import ../styles/breakpoints
footer.container-fluid
background: #F8F8FB
border-top: 1px solid #E3E3E6
.container
margin-top: 11px
max-width: 1200px
.row
max-width: 1200px
.col-4
flex: 0 0 100%
flex-basis: 100%
max-width: 100%
margin-bottom: 60px
padding: 0 20px 56px
+media-breakpoint-up(sm)
padding: 0 20px 32px
+media-breakpoint-up(md)
flex: 0 0 33%
padding-bottom: 0
max-width: 33%
margin-bottom: 0px
.col
flex-basis: 50%
padding: 0 20px 32px
+media-breakpoint-up(sm)
flex-basis: 0
padding-bottom: 0
h5
color: $dark
font-weight: 600
margin-bottom: 12px
text-transform: uppercase
p
color: #6d6d6e
font-size: 16px
line-height: 30px
.list-unstyled
li
line-height: 30px
a
color: #6d6d6e
font-size: 16px
&:hover
color: #3F3F40
.social-icons
.list-inline-item:not(:last-child)
margin-right: 22px
a
opacity: 1
&:hover
opacity: 0.8

View File

@@ -1,56 +0,0 @@
@import ../styles/colors
@import ../styles/breakpoints
.gallery
.cta-arrow
margin-top: 20px
.container
max-width: 1190px
padding: 0
+media-breakpoint-up(sm)
padding-right: 15px
padding-left: 15px
.thumbnail
float: left
position: relative
width: 32.8%
padding-bottom: 32.9%
margin: 0.4%
overflow: hidden
// Fixes Thumbnail Spacing
&:nth-of-type(1),
&:nth-of-type(2),
&:nth-of-type(3)
margin-top: 0
&:nth-of-type(1),
&:nth-of-type(4),
&:nth-of-type(7)
margin-left: 0
&:nth-of-type(3),
&:nth-of-type(6)
margin-right: 0
+media-breakpoint-up(sm)
width: 22.4%
padding-bottom: 22.4%
margin: 1.73%
&:nth-of-type(4)
margin-top: 0
&:nth-of-type(1),
&:nth-of-type(5)
margin-left: 0
&:nth-of-type(4),
&:nth-of-type(7)
margin-left: 1.73%
&:nth-of-type(3),
&:nth-of-type(6)
margin-right: 1.73%
&:nth-of-type(4),
&:nth-of-type(8)
margin-right: 0
.thumbnail-container
position: absolute
width: 100%
height: 100%
img
width: 300%
transform: translate(-20%, -10%)

View File

@@ -1,58 +1,19 @@
.dashboard-container
+container-behavior
+media-xs
flex-direction: column
align-content: center
align-items: flex-start
display: flex
justify-content: space-around
word-break: break-word
section.dashboard-main,
section.dashboard-secondary
+media-xs
width: 100%
margin: 20px auto
img .title-underline
max-width: 100%
section.dashboard-main
+container-box
width: 52%
section.dashboard-secondary
width: 46%
flex-direction: column
margin-right: auto
span.section-lead
display: block
padding: 10px 0
color: $color-text-dark-secondary
section.dashboard-main,
section.dashboard-secondary
h4
padding-bottom: 5px padding-bottom: 5px
margin-bottom: 20px
position: relative position: relative
margin-bottom: 20px
&:before &:before
position: absolute background-color: $primary
width: 50px
height: 2px
top: 125%
content: ' ' content: ' '
display: block display: block
background-color: $color-primary height: 2px
top: 125%
position: absolute
width: 50px
a
color: $color-text
&:hover
color: $color-primary
cursor: pointer
nav#nav-tabs, nav#nav-tabs,
nav#sub-nav-tabs nav#sub-nav-tabs
@@ -113,37 +74,13 @@
border-color: $color-background-light border-color: $color-background-light
pointer-events: none pointer-events: none
li.create .dashboard-container
cursor: pointer word-break: break-word
display: inline-block
float: right
font:
size: 1.2em
weight: 400
padding: 5px 10px
margin-top: 3px
a
color: $color-success
text-decoration: none
&.disabled
cursor: wait
border-color: $color-success
opacity: .8
a
cursor: wait
section.stream section.stream
background-color: white
border-bottom: thin solid $color-background-dark
ul.activity-stream__list ul.activity-stream__list
list-style: none
margin: 0
padding: 0
$activity-stream-thumbnail-size: 110px $activity-stream-thumbnail-size: 110px
> li > li
position: relative position: relative
display: flex display: flex
@@ -180,17 +117,6 @@
transition: font-size 100ms ease-in-out transition: font-size 100ms ease-in-out
&.comment &.comment
.activity-stream__list-thumbnail
background: transparent
color: $node-type-comment
font-size: 1.2em
box-shadow: none
i
+position-center-translate
left: 22px
top: 19px
.activity-stream__list-details .activity-stream__list-details
padding: 0 padding: 0
.title .title
@@ -200,6 +126,8 @@
margin: 0 margin: 0
ul.meta ul.meta
+list-meta
font-size: .9em
padding: 0 10px 7px 10px padding: 0 10px 7px 10px
li li
@@ -300,7 +228,6 @@
overflow: hidden overflow: hidden
position: relative position: relative
max-width: 100% max-width: 100%
margin-right: auto
padding: 10px 0 padding: 10px 0
+media-xs +media-xs
@@ -310,18 +237,14 @@
+ribbon +ribbon
right: -47px right: -47px
top: 5px top: 5px
font: font-size: 12px
size: 12px
weight: 500
span span
padding: 1px 50px padding: 1px 50px
.title .title
display: inline-block
padding: 0 10px padding: 0 10px
color: $color-text-dark color: $color-text-dark
font-size: 1.1em
span span
@include badge(hsl(hue($color-success), 60%, 45%), 3px) @include badge(hsl(hue($color-success), 60%, 45%), 3px)
@@ -329,24 +252,6 @@
padding: 1px 5px padding: 1px 5px
margin-right: 5px margin-right: 5px
ul.meta
+list-meta
padding: 5px 10px 0 10px
font-size: .85em
color: $color-text-dark-secondary
display: flex
white-space: nowrap
&.extra
margin-top: auto
li
padding-left: 10px
&:before
left: -5px
&.where-project
+text-overflow-ellipsis
section.comments section.comments
padding: 0 15px 5px padding: 0 15px 5px
@@ -371,118 +276,6 @@
display: block display: block
padding-bottom: 5px padding-bottom: 5px
section.blog-stream
+media-md
padding-left: 10px
+media-sm
padding-left: 10px
position: relative
.feed
position: absolute
top: 10px
right: 10px
font-size: 1.4em
color: lighten($color-text-dark-hint, 10%)
&:hover
color: $color-primary
> ul
margin: 0
padding: 0
list-style: none
border-top: thin solid $color-background
.blog_index-item
+container-box
display: flex
flex-direction: column
margin-bottom: 50px
&:before
height: 1px
background-color: $color-background-dark
position: absolute
bottom: -26px
left: 25px
right: 25px
content: ' '
&:last-child
margin-bottom: 0
&:before
display: none
video
max-width: 100%
a.item-title
font-size: 1.6em
padding: 5px 15px
display: block
color: $color-text
&:hover
color: $color-primary
ul.meta
+list-meta
font-size: .9em
padding: 15px 15px 5px
&.blog-non-featured
border-radius: 0
margin: 0
.item-content
+node-details-description
padding: 10px 15px
.blog-stream__list-details
.title
color: $color-text-dark-primary
display: block
font-size: 1.3em
&:hover
color: $color-primary
ul.meta
+list-meta
padding-top: 5px
font-size: .9em
color: $color-text-dark-secondary
li
padding-left: 10px
&:before
left: -5px
.blog_index-header
display: block
position: relative
img
border-top-left-radius: 3px
border-top-right-radius: 3px
width: 100%
.more
text-align: center
a
color: $color-text
display: block
padding: 25px 0
text-decoration: underline
width: 100%
&:hover
color: $color-primary
section.random-asset section.random-asset
border-bottom: thin solid $color-background-dark border-bottom: thin solid $color-background-dark
@@ -653,10 +446,6 @@ section.announcement
.title .title
padding-bottom: 10px padding-bottom: 10px
font:
family: $font-body
size: 1.4em
weight: 300
+media-xs +media-xs
font-size: 1.4em font-size: 1.4em
@@ -693,60 +482,21 @@ section.announcement
justify-content: space-around justify-content: space-around
flex-wrap: wrap flex-wrap: wrap
a
+button($color-text-light, 3px)
padding: 5px 0
margin:
bottom: 5px
right: auto
left: auto
font-size: .9em
opacity: 1
flex: 1
+media-xs
margin: 10px auto
width: 100%
&:first-child
margin-right: 15px
&.blue
+button(hsl(hue($color-info), 60%, 45%), 3px)
&.orange
+button(hsl(hue($color-secondary), 50%, 50%), 3px)
padding: 5px 15px
&.green
+button(hsl(hue($color-success), 60%, 40%), 3px, true)
section.dashboard-in-production
.in-production-project
border-bottom: thin solid $color-background-dark
color: $color-text-dark-primary
display: block
font-size: 1.1em
margin-bottom: 15px
> img
margin-bottom: 15px
body.homepage body.homepage
.dashboard-container .blog
.dashboard-main // Custom tweak to Bootstrap grid for the only case when
+media-xs // the post is inside a column (it's usually centered in the page).
width: 100% .col-md-9
background-color: transparent flex: 1
box-shadow: none max-width: 100%
width: 60%
.dashboard-secondary .jumbotron
+container-box padding-top: 6em
+media-xs padding-bottom: 6em
width: 100%
width: 38%
> section *
padding: 15px font-size: $h1-font-size
.lead
font-size: $font-size-base

View File

@@ -1,2 +0,0 @@
.embed-responsive
margin: 48px auto

View File

@@ -1,32 +0,0 @@
@import ../styles/colors
@import ../styles/breakpoints
.jumbotron
background-color: #fff
background-repeat: no-repeat
background-position: left top
background-size: cover
height: 360px
width: 100%
margin-bottom: 0px
+media-breakpoint-up(md)
height: 500px
+media-breakpoint-up(xl)
height: 600px
.container
max-width: 1160px
display: flex
height: 100%
flex-direction: column
justify-content: center
h1.display-4
color: white
font-weight: 400
font-size: 48px
margin: 0
text-shadow: 0 2px 2px rgba(0, 0, 0, 0.30)
.lead
max-width: 722px
text-shadow: 0 2px 2px rgba(0, 0, 0, 0.80)
p
color: white

View File

@@ -1,41 +0,0 @@
@import ../styles/colors
@import ../styles/breakpoints
.nav-scroller
position: relative
z-index: 2
height: 2.75rem
overflow-y: hidden
.navbar-secondary
max-width: 700px
margin-bottom: 40px
padding-left: 0
border-bottom: 1px solid $gray
+media-breakpoint-up(sm)
margin-bottom: 56px
.nav
display: flex
flex-wrap: nowrap
overflow-x: auto
text-align: center
white-space: nowrap
-webkit-overflow-scrolling: touch
.nav-link
font-size: 18px
color: $dark
padding: 13px 4px
margin-right: 16px
margin-left: 16px
&:hover
color: $muted
.nav-title
font-weight: 600
@include media-breakpoint-up(md)
padding-left: 0
margin-left: 0
&:hover
color: $dark
.active
border-bottom: 2px solid $primary
&:hover
color: $dark

View File

@@ -1,220 +0,0 @@
@import ../styles/colors
@import ../styles/breakpoints
nav.navbar
background: #fff
height: auto
min-height: 48px
padding: 2px 20px
position: sticky
+media-breakpoint-up(md)
box-shadow: 0 2px 2px -2px rgba(0,0,0,.15)
height: 56px
padding: 10px 5px 10px 20px
&.sticky-top
+media-breakpoint-down(sm)
position: static
.navbar-brand
padding: .3125rem 0
z-index: 1002
.navbar-toggler
padding: 0
border-radius: 0
&:hover
background: none
.navbar-nav
margin-bottom: 15px
margin-top: 15px
+media-breakpoint-up(md)
margin: 0
li
line-height: 2.5
.special
top: 10px
left: 35px
a.navbar-item.active,
a.navbar-item.active:hover,
a.navbar-item:hover
box-shadow: none
li:last-of-type
// profile menu
z-index: 1002
.dropdown-menu
right: 0
left: auto
top: 54px
padding: .5rem 0
margin: .125rem 0 0
&.visible
visibility: visible
li a
padding: 0 15px 0 12px
li:hover
background-color: #f8f9fa
.dropdown ul.dropdown-menu li a
color: #111
font-family: 'Source Sans Pro', sans-serif
&:hover
color: #111
text-decoration: none
.nav-item .nav-link
font-size: 18px
color: $dark
padding: 10px
+media-breakpoint-up(lg)
padding: 6px 18px
&:hover
color: $primary
.navbar-toggler
border: 0
display: block
outline: none
+media-breakpoint-up(md)
display: none
span
width: 20px
height: 2px
background: $dark
display: block
margin-bottom: 4px
&:last-of-type
margin-bottom: 0
.collapsing
transition: none
display: none
#navbarNav
animation-timing-function: cubic-bezier(0.4,0,0.2,1)
animation-fill-mode: backwards
opacity: 1
transition: opacity .15s ease-in
visibility: visible
&.hidden
animation-fill-mode: backwards
animation-timing-function: cubic-bezier(0.4,0,0.2,1)
opacity: 0
transition: visibility 0s .15s, opacity .15s ease-in
visibility: hidden
.dropdown-toggle::after
display:none !important
&.show
padding-bottom: 75vh
.search-icon
display: flex
align-items: center
justify-content: center
padding: 0 8px
+media-breakpoint-up(lg)
padding: 0 16px
.pi-search
&::before
color: rgba(17,17,17,0.75)
font-size: 16px
&:hover
color: $primary
.nav-notifications
display: flex
align-items: center
justify-content: center
padding: 0 8px
+media-breakpoint-up(lg)
padding: 0 16px
.navbar-item
height: auto
padding: 0
.active
box-shadow: 0
.flyout
background-color: #fff
background-clip: padding-box
border: 1px solid rgba(0,0,0,.15)
border-radius: .25rem
box-shadow: 0
font-size: 16px
.flyout.notifications
right: 65px
top: 57px
.nav-notifications:hover>#notifications-toggle
display: block
.nav-notifications-icon
color: rgba(17,17,17,0.75)
&:hover
color: $primary
.gravatar
width: 32px
border-radius: 50%
.dropdown-menu
margin-top: -1px
border: 0
border-radius: 0 0 4px 4px
box-shadow: none
font-size: 1rem
color: #111
text-align: left
list-style: none
background-color: #fff
background-clip: padding-box
box-shadow: 0px 4px 4px 0px hsla(0, 0%, 80%, 0.25)
.dropdown:hover
background: none
&>.dropdown-menu
display: block
.dropdown-item
color: #111
font-size: 18px
padding: 0px 15px
i
padding-right: 8px
#userDropdown
.nav-link
padding-top: 4px
padding-bottom: 0
padding-right: 0
outline: none
#searchNav
display: flex
align-items: center
justify-content: center
background-color: #fff
max-height: 56px
position: absolute
width: calc(100% - 40px)
z-index: 1001
animation-timing-function: cubic-bezier(0.4,0,0.2,1)
animation-fill-mode: backwards
opacity: 1
transition: opacity .15s ease-in
visibility: visible
+media-breakpoint-up(md)
width: calc(100% - 25px)
&.hidden
animation-fill-mode: backwards
animation-timing-function: cubic-bezier(0.4,0,0.2,1)
opacity: 0
transition: visibility 0s .15s, opacity .15s ease-in
visibility: hidden
.search-container
position: relative
max-width: 560px
width: 100%
input
padding: 11px 20px 11px 46px
color: #4d4e53
box-shadow: none
border: 1px solid #e5e5e5
border-radius: 4px
border-bottom-color: none
background-color: #fcfcfc
font-size: 18px
transition: border-color 150ms ease-in-out, box-shadow 150ms ease-in-out
width: 100%
max-width: 560px
.search-icon
cursor: pointer
position: absolute
top: 14px
left: 11px
#searchCloseButton
cursor: pointer
position: absolute
right: 16px
top: 12px

View File

@@ -1,43 +0,0 @@
html
// changing font-size here, will change all bootstrap font-sizes
font-size: 20px
body
font-family: 'Source Sans Pro', sans-serif
-webkit-font-smoothing: antialiased
-moz-osx-font-smoothing: grayscale
color: #212529
h1, h2, h3, h4, h5
font-family: 'Source Sans Pro', sans-serif
margin-top: 0
margin-bottom: .5rem
h1
font-size: 48px
line-height: 57px
font-weight: 500
h2
font-size: 36px
line-height: 47px
font-weight: 500
h3
font-size: 27px
line-height: 38px
font-weight: 500
h4
font-size 21px
font-weight: 500
line-height: 34px
h5
font-size: 15px
letter-spacing: 0.6px
p
font-size: 20px
line-height: 1.5
margin-bottom: 1rem
.lead
font-size: 20px
letter-spacing: 0.4px
a
color: #007bff
&:hover
color: #007bff
text-decoration: underline

View File

@@ -10,9 +10,6 @@
li a.navbar-item li a.navbar-item
color: $color-text color: $color-text
.navbar-container
+container-behavior
.navbar-toggle .navbar-toggle
border: 2px solid $color-text-dark-primary border: 2px solid $color-text-dark-primary
color: $color-text color: $color-text
@@ -267,22 +264,6 @@
+media-xs +media-xs
margin-top: 20px margin-top: 20px
.navbar
.nav-item-sign-in
a.navbar-item
background-color: $color-primary
border: none
border-radius: 3px
color: white
height: auto
font-weight: bold
margin-top: 5px
margin-left: 10px
padding: 10px 20px
&:hover
background-color: lighten($color-primary, 10%)
box-shadow: none
.container.wide-on-sm .container.wide-on-sm
+media-sm +media-sm
@@ -334,9 +315,7 @@ section.pricing
+button($color-primary, 3px, true) +button($color-primary, 3px, true)
h3 h3
font: font-size: 1.8em
size: 1.8em
family: $font-body
padding-bottom: 0 padding-bottom: 0
margin: 25px 0 0 10px margin: 25px 0 0 10px

View File

@@ -1,17 +0,0 @@
/* mixins reused on every page
================================================================== */
@import ../styles/typography
@import ../styles/navbar
@import ../styles/footer
/* Undo Old Base.css, main.css
================================================================== */
.container
width: 100%
padding-right: 15px
padding-left: 15px
margin-right: auto
margin-left: auto
.navbar+.page-content
padding-top: 0

View File

@@ -1,26 +1,99 @@
@import ../../../pillar/src/styles/_normalize // Bootstrap variables and utilities.
@import ../../../pillar/src/styles/_config @import "../../node_modules/bootstrap/scss/functions"
@import ../../../pillar/src/styles/_utils @import "../../node_modules/bootstrap/scss/variables"
@import "../../node_modules/bootstrap/scss/mixins"
/* Generic styles (comments, notifications, etc) come from base.css */ // Pillar variables and utilities.
@import "../../../pillar/src/styles/config"
@import "../../../pillar/src/styles/utils"
// Bootstrap components.
@import "../../node_modules/bootstrap/scss/root"
@import "../../node_modules/bootstrap/scss/reboot"
@import "../../node_modules/bootstrap/scss/type"
@import "../../node_modules/bootstrap/scss/images"
@import "../../node_modules/bootstrap/scss/code"
@import "../../node_modules/bootstrap/scss/grid"
@import "../../node_modules/bootstrap/scss/tables"
@import "../../node_modules/bootstrap/scss/forms"
@import "../../node_modules/bootstrap/scss/buttons"
@import "../../node_modules/bootstrap/scss/transitions"
@import "../../node_modules/bootstrap/scss/dropdown"
@import "../../node_modules/bootstrap/scss/button-group"
@import "../../node_modules/bootstrap/scss/input-group"
@import "../../node_modules/bootstrap/scss/custom-forms"
@import "../../node_modules/bootstrap/scss/nav"
@import "../../node_modules/bootstrap/scss/navbar"
@import "../../node_modules/bootstrap/scss/card"
@import "../../node_modules/bootstrap/scss/breadcrumb"
@import "../../node_modules/bootstrap/scss/pagination"
@import "../../node_modules/bootstrap/scss/badge"
@import "../../node_modules/bootstrap/scss/jumbotron"
@import "../../node_modules/bootstrap/scss/alert"
@import "../../node_modules/bootstrap/scss/progress"
@import "../../node_modules/bootstrap/scss/media"
@import "../../node_modules/bootstrap/scss/list-group"
@import "../../node_modules/bootstrap/scss/close"
@import "../../node_modules/bootstrap/scss/modal"
@import "../../node_modules/bootstrap/scss/tooltip"
@import "../../node_modules/bootstrap/scss/popover"
@import "../../node_modules/bootstrap/scss/carousel"
@import "../../node_modules/bootstrap/scss/utilities"
@import "../../node_modules/bootstrap/scss/print"
// Pillar components.
@import "../../../pillar/src/styles/apps_base"
@import "../../../pillar/src/styles/error"
@import "../../../pillar/src/styles/components/base"
@import "../../../pillar/src/styles/components/jumbotron"
@import "../../../pillar/src/styles/components/alerts"
@import "../../../pillar/src/styles/components/navbar"
@import "../../../pillar/src/styles/components/dropdown"
@import "../../../pillar/src/styles/components/footer"
@import "../../../pillar/src/styles/components/shortcode"
@import "../../../pillar/src/styles/components/statusbar"
@import "../../../pillar/src/styles/components/search"
@import "../../../pillar/src/styles/components/flyout"
@import "../../../pillar/src/styles/components/forms"
@import "../../../pillar/src/styles/components/inputs"
@import "../../../pillar/src/styles/components/buttons"
@import "../../../pillar/src/styles/components/popover"
@import "../../../pillar/src/styles/components/tooltip"
@import "../../../pillar/src/styles/components/checkbox"
@import "../../../pillar/src/styles/components/overlay"
@import "../../../pillar/src/styles/components/card"
@import "../../../pillar/src/styles/comments"
@import "../../../pillar/src/styles/notifications"
/* Blender Cloud specific styles */ /* Blender Cloud specific styles */
@import ../../../pillar/src/styles/_project @import "../../../pillar/src/styles/_project"
@import ../../../pillar/src/styles/_project-sharing @import "../../../pillar/src/styles/_project-sharing"
@import ../../../pillar/src/styles/_project-dashboard @import "../../../pillar/src/styles/_project-dashboard"
@import ../../../pillar/src/styles/_user @import "../../../pillar/src/styles/_user"
@import _welcome @import _welcome
@import _homepage @import _homepage
@import _services @import _services
@import _about @import _about
@import ../../../pillar/src/styles/_search @import "../../../pillar/src/styles/_search"
@import ../../../pillar/src/styles/_organizations @import "../../../pillar/src/styles/_organizations"
/* services, about, etc */ /* services, about, etc */
@import ../../../pillar/src/styles/_pages @import "../../../pillar/src/styles/_pages"
/* plugins are included here, don't include in base unless needed by other pillar apps */ /* plugins are included here, don't include in base unless needed by other pillar apps */
@import ../../../pillar/src/styles/plugins/_jstree @import "../../../pillar/src/styles/plugins/_jstree"
@import ../../../pillar/src/styles/plugins/_js_select2 @import "../../../pillar/src/styles/plugins/_js_select2"
/* CSS for pillar-font comes from fontello.com using static/assets/font/config.json */ /* CSS for pillar-font comes from fontello.com using static/assets/font/config.json */

View File

@@ -1,60 +1,384 @@
@import ../styles/colors // Bootstrap variables and utilities.
@import ../styles/breakpoints @import "../../node_modules/bootstrap/scss/functions"
@import ../styles/jumbotron @import "../../node_modules/bootstrap/scss/variables"
@import ../styles/navbar-secondary @import "../../node_modules/bootstrap/scss/mixins"
@import ../styles/iframe
@import ../styles/gallery
@import ../styles/cards
/* Undo main.css padding // Pillar variables and utilities.
================================================================== */ @import "../../../pillar/src/styles/config"
body, @import "../../../pillar/src/styles/utils"
.container-page
background: #fff
section.node-details-container.project
padding-bottom: 0
.node-details-title
padding-top: 0
padding-bottom: 0
/* Override jumbotron to make it shorter than the default */ // Bootstrap components.
.jumbotron @import "../../node_modules/bootstrap/scss/root"
height: 400px @import "../../node_modules/bootstrap/scss/reboot"
@import "../../node_modules/bootstrap/scss/type"
@import "../../node_modules/bootstrap/scss/images"
@import "../../node_modules/bootstrap/scss/code"
@import "../../node_modules/bootstrap/scss/grid"
@import "../../node_modules/bootstrap/scss/tables"
@import "../../node_modules/bootstrap/scss/forms"
@import "../../node_modules/bootstrap/scss/buttons"
@import "../../node_modules/bootstrap/scss/transitions"
@import "../../node_modules/bootstrap/scss/dropdown"
@import "../../node_modules/bootstrap/scss/button-group"
@import "../../node_modules/bootstrap/scss/input-group"
@import "../../node_modules/bootstrap/scss/custom-forms"
@import "../../node_modules/bootstrap/scss/nav"
@import "../../node_modules/bootstrap/scss/navbar"
@import "../../node_modules/bootstrap/scss/card"
@import "../../node_modules/bootstrap/scss/breadcrumb"
@import "../../node_modules/bootstrap/scss/pagination"
@import "../../node_modules/bootstrap/scss/badge"
@import "../../node_modules/bootstrap/scss/jumbotron"
@import "../../node_modules/bootstrap/scss/alert"
@import "../../node_modules/bootstrap/scss/progress"
@import "../../node_modules/bootstrap/scss/media"
@import "../../node_modules/bootstrap/scss/list-group"
@import "../../node_modules/bootstrap/scss/close"
@import "../../node_modules/bootstrap/scss/modal"
@import "../../node_modules/bootstrap/scss/tooltip"
@import "../../node_modules/bootstrap/scss/popover"
@import "../../node_modules/bootstrap/scss/carousel"
@import "../../node_modules/bootstrap/scss/utilities"
@import "../../node_modules/bootstrap/scss/print"
// Pillar components.
@import "../../../pillar/src/styles/apps_base"
@import "../../../pillar/src/styles/error"
@import "../../../pillar/src/styles/components/base"
@import "../../../pillar/src/styles/components/jumbotron"
@import "../../../pillar/src/styles/components/alerts"
@import "../../../pillar/src/styles/components/navbar"
@import "../../../pillar/src/styles/components/dropdown"
@import "../../../pillar/src/styles/components/footer"
@import "../../../pillar/src/styles/components/shortcode"
@import "../../../pillar/src/styles/components/statusbar"
@import "../../../pillar/src/styles/components/search"
@import "../../../pillar/src/styles/components/flyout"
@import "../../../pillar/src/styles/components/inputs"
@import "../../../pillar/src/styles/components/buttons"
@import "../../../pillar/src/styles/components/popover"
@import "../../../pillar/src/styles/components/tooltip"
@import "../../../pillar/src/styles/components/checkbox"
@import "../../../pillar/src/styles/components/overlay"
@import "../../../pillar/src/styles/components/card"
@import "../../../pillar/src/styles/notifications"
@import "../../../pillar/src/styles/_search"
$node-latest-thumbnail-size: 160px
$node-latest-gallery-thumbnail-size: 200px
nav.navbar
.navbar-header
+media-xs
width: 100%
.navbar-toggle
border: none
color: $color-text
position: absolute
right: 10px
.navbar-nav
+media-xs
padding: 10px
.search-input
display: none
.node-details-container
max-width: 620px
font-size: 1.3em
line-height: 1.5em
margin: 0 auto 40px auto
padding-bottom: 40px
+media-xs
padding-left: 10px
padding-right: 10px
/* Landing Page Sass
================================================================== */
.cta-arrow
img
padding-left: 11px
.node-details-title
&.container
max-width: 1190px
h1,
h2,
h3,
ul,
p p
max-width: 700px margin-bottom: 1.3em
margin-left: auto
margin-right: auto header
section display: flex
margin-top: 104px flex-direction: column /* stack flex items vertically */
+media-breakpoint-up(sm) position: relative
margin-top: 152px img.header
&:first-child width: 100%
margin-top: 0 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%)
.landing
h2 h2
margin-bottom: 24px text-align: center
+media-breakpoint-up(sm)
margin-bottom: 40px margin-bottom: 40px
.container.card-container
margin-top: 0 section
.card max-width: 1024px
.card-image padding-top: 20px
margin-top: 0 border-top: thin solid $color-background
footer.container-fluid margin: 0 auto
margin-top: 72px
+media-breakpoint-up(sm) .navbar-secondary
margin-top: 112px max-width: 620px
+media-breakpoint-up(lg) margin: 0 auto
margin-top: 136px
.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%

View File

@@ -1,15 +0,0 @@
@import ../styles/colors
@import ../styles/breakpoints
@import ../styles/jumbotron
@import ../styles/navbar-secondary
@import ../styles/cards
body,
.container-page
background: #fff
footer.container-fluid
margin-top: 72px
+media-breakpoint-up(sm)
margin-top: 112px
+media-breakpoint-up(lg)
margin-top: 136px

View File

@@ -1,29 +0,0 @@
@import ../styles/colors
@import ../styles/breakpoints
nav.navbar
+media-breakpoint-up(md)
padding: 10px 10px 10px 20px
.nav-item-sign-in
line-height: 1.5
display: flex
align-items: center
justify-content: center
.navbar-item
.join .navbar .nav-item-sign-in a.navbar-item
background: $primary
font-size: 16px
font-weight: 600
margin: 0
padding: 8px 16px
width: 100%
&:hover
background: $primary
+media-breakpoint-up(md)
width: auto
// temporarily restore old primary color
h2,
h3
color: #68B3C8
footer.container-fluid
margin-top: 0

View File

@@ -0,0 +1,26 @@
include ../mixins/components
| {% macro navigation_tabs(title) %}
+nav-secondary()
+nav-secondary-link(
class="{% if title == 'homepage' %}active{% endif %}",
href="{{ url_for('main.homepage') }}")
| Activity
+nav-secondary-link(
class="{% if title == 'home' %}active{% endif %}",
href="{{ url_for('projects.home_project') }}")
| Home
+nav-secondary-link(
class="{% if title == 'dashboard' %}active{% endif %}",
href="{{ url_for('projects.index') }}")
| My Projects
| {% if current_user.has_organizations() %}
+nav-secondary-link(
class="{% if title == 'organizations' %}active{% endif %}",
href="{{ url_for('pillar.web.organizations.index') }}")
| My Organizations
| {% endif %}
| {% endmacro %}

View File

@@ -193,16 +193,16 @@ style.
small October 30th, 2015 small October 30th, 2015
.page-card-summary .page-card-summary
| Introducing integrated blogs in Blender Cloud projects. Glass Half is the first project fully developed on the new Blender Cloud. It's also the first and only project to have share its | Introducing integrated blogs in Blender Cloud projects. Glass Half is the first project fully developed on the new Blender Cloud. It's also the first and only project to have share its
a(href='https://cloud.blender.org/p/glass-half/5627bb22f0e7220061109c9f') animation dailies a(href='/p/glass-half/5627bb22f0e7220061109c9f') animation dailies
| ! But the biggest outcome from Glass Half was definitely | ! But the biggest outcome from Glass Half was definitely
a(href='https://cloud.blender.org/p/glass-half/569d6044c379cf445461293e') Flexirig a(href='/p/glass-half/569d6044c379cf445461293e') Flexirig
| . | .
.page-card-side .page-card-side
a(href='https://cloud.blender.org/p/glass-half/blog/glass-half-premiere') a(href='/p/glass-half/blog/glass-half-premiere')
img.img-responsive(src="{{ url_for('static_cloud', filename='img/2015_10_30_glass.jpg') }}", alt="Glass Half") img.img-responsive(src="{{ url_for('static_cloud', filename='img/2015_10_30_glass.jpg') }}", alt="Glass Half")
section.page-card section.page-card
.page-card-side .page-card-side
a(href='https://cloud.blender.org/blog/new-art-gallery-with-gleb-alexandrov') a(href='/blog/new-art-gallery-with-gleb-alexandrov')
img.img-responsive(src="{{ url_for('static_cloud', filename='img/2015_11_19_art.jpg') }}", alt="Art Gallery") img.img-responsive(src="{{ url_for('static_cloud', filename='img/2015_11_19_art.jpg') }}", alt="Art Gallery")
.page-card-side .page-card-side
h2.page-card-title h2.page-card-title
@@ -218,11 +218,11 @@ style.
.page-card-summary .page-card-summary
| With so much going on in the Cloud at at the studio. The Blender Institute Podcast was born! Sharing our daily studio work, Blender community news, and interacting with the awesome Blender Cloud subscribers. | With so much going on in the Cloud at at the studio. The Blender Institute Podcast was born! Sharing our daily studio work, Blender community news, and interacting with the awesome Blender Cloud subscribers.
.page-card-side .page-card-side
a(href='https://cloud.blender.org/blog/introducing-blender-institute-podcast') a(href='/blog/introducing-blender-institute-podcast')
img.img-responsive(src="{{ url_for('static_cloud', filename='img/2015_11_24_bip.jpg') }}", alt="Blender Institute Podcast") img.img-responsive(src="{{ url_for('static_cloud', filename='img/2015_11_24_bip.jpg') }}", alt="Blender Institute Podcast")
section.page-card section.page-card
.page-card-side .page-card-side
a(href='https://cloud.blender.org/p/blenrig/blog/welcome-to-the-blenrig-project') a(href='/p/blenrig/blog/welcome-to-the-blenrig-project')
img.img-responsive(src="{{ url_for('static_cloud', filename='img/2015_12_01_blenrig.jpg') }}", alt="Blenrig") img.img-responsive(src="{{ url_for('static_cloud', filename='img/2015_12_01_blenrig.jpg') }}", alt="Blenrig")
.page-card-side .page-card-side
h2.page-card-title h2.page-card-title
@@ -238,11 +238,11 @@ style.
.page-card-summary .page-card-summary
| The biggest source for CC0/Public Domain textures on the interwebs goes live. First as beta, as a quick gift right before Xmas 2015! | The biggest source for CC0/Public Domain textures on the interwebs goes live. First as beta, as a quick gift right before Xmas 2015!
.page-card-side .page-card-side
a(href='https://cloud.blender.org/blog/new-texture-library') a(href='/blog/new-texture-library')
img.img-responsive(src="{{ url_for('static_cloud', filename='img/2015_12_23_textures.jpg') }}", alt="Texture Library") img.img-responsive(src="{{ url_for('static_cloud', filename='img/2015_12_23_textures.jpg') }}", alt="Texture Library")
section.page-card section.page-card
.page-card-side .page-card-side
a(href='https://cloud.blender.org/blog/nraryew-the-character-lib') a(href='/blog/nraryew-the-character-lib')
img.img-responsive(src="{{ url_for('static_cloud', filename='img/2016_01_05_charlib.jpg') }}", alt="Character Library") img.img-responsive(src="{{ url_for('static_cloud', filename='img/2016_01_05_charlib.jpg') }}", alt="Character Library")
.page-card-side .page-card-side
h2.page-card-title h2.page-card-title
@@ -262,11 +262,11 @@ style.
a(href='https://www.youtube.com/watch?v=kQH897V9bDg&list=PLI2TkLMzCSr_H6ppmzDtU0ut0RwxGvXjv') nicely edited Weekly video reports a(href='https://www.youtube.com/watch?v=kQH897V9bDg&list=PLI2TkLMzCSr_H6ppmzDtU0ut0RwxGvXjv') nicely edited Weekly video reports
| . | .
.page-card-side .page-card-side
a(href='https://cloud.blender.org/p/caminandes-3/blog/caminandes-llamigos') a(href='/p/caminandes-3/blog/caminandes-llamigos')
img.img-responsive(src="{{ url_for('static_cloud', filename='img/2016_01_30_llamigos.jpg') }}", alt="Caminandes: Llamigos") img.img-responsive(src="{{ url_for('static_cloud', filename='img/2016_01_30_llamigos.jpg') }}", alt="Caminandes: Llamigos")
section.page-card section.page-card
.page-card-side .page-card-side
a(href='https://cloud.blender.org/blog/welcome-sybren') a(href='/blog/welcome-sybren')
img.img-responsive(src="{{ url_for('static_cloud', filename='img/2016_03_01_sybren.jpg') }}", alt="Dr. Sybren!") img.img-responsive(src="{{ url_for('static_cloud', filename='img/2016_03_01_sybren.jpg') }}", alt="Dr. Sybren!")
.page-card-side .page-card-side
h2.page-card-title h2.page-card-title
@@ -282,11 +282,11 @@ style.
.page-card-summary .page-card-summary
| Create your own private projects on Blender Cloud. | Create your own private projects on Blender Cloud.
.page-card-side .page-card-side
a(href='https://cloud.blender.org/blog/welcome-sybren') a(href='/blog/welcome-sybren')
img.img-responsive(src="{{ url_for('static_cloud', filename='img/2016_05_03_projects.jpg') }}", alt="Projects") img.img-responsive(src="{{ url_for('static_cloud', filename='img/2016_05_03_projects.jpg') }}", alt="Projects")
section.page-card section.page-card
.page-card-side .page-card-side
a(href='https://cloud.blender.org/blog/introducing-project-sharing') a(href='/blog/introducing-project-sharing')
img.img-responsive(src="{{ url_for('static_cloud', filename='img/2016_05_09_projectsharing.jpg') }}", alt="Sharing") img.img-responsive(src="{{ url_for('static_cloud', filename='img/2016_05_09_projectsharing.jpg') }}", alt="Sharing")
.page-card-side .page-card-side
h2.page-card-title h2.page-card-title
@@ -302,11 +302,11 @@ style.
.page-card-summary .page-card-summary
| Browse the textures from within Blender! | Browse the textures from within Blender!
.page-card-side .page-card-side
a(href='https://cloud.blender.org/blog/introducing-project-sharing') a(href='/blog/introducing-project-sharing')
img.img-responsive(src="{{ url_for('static_cloud', filename='img/2016_05_11_addon.jpg') }}", alt="Blender Cloud Add-on") img.img-responsive(src="{{ url_for('static_cloud', filename='img/2016_05_11_addon.jpg') }}", alt="Blender Cloud Add-on")
section.page-card section.page-card
.page-card-side .page-card-side
a(href='https://cloud.blender.org/blog/introducing-private-texture-libraries') a(href='/blog/introducing-private-texture-libraries')
img.img-responsive(src="{{ url_for('static_cloud', filename='img/2016_05_23_privtextures.jpg') }}", alt="Texture Libraries") img.img-responsive(src="{{ url_for('static_cloud', filename='img/2016_05_23_privtextures.jpg') }}", alt="Texture Libraries")
.page-card-side .page-card-side
h2.page-card-title h2.page-card-title
@@ -322,11 +322,11 @@ style.
.page-card-summary .page-card-summary
| Sync your Blender preferences across multiple devices. | Sync your Blender preferences across multiple devices.
.page-card-side .page-card-side
a(href='https://cloud.blender.org/blog/introducing-blender-sync') a(href='/blog/introducing-blender-sync')
img.img-responsive(src="{{ url_for('static_cloud', filename='img/2016_06_30_sync.jpg') }}", alt="Blender Sync") img.img-responsive(src="{{ url_for('static_cloud', filename='img/2016_06_30_sync.jpg') }}", alt="Blender Sync")
section.page-card section.page-card
.page-card-side .page-card-side
a(href='https://cloud.blender.org/blog/introducing-image-sharing') a(href='/blog/introducing-image-sharing')
img.img-responsive(src="{{ url_for('static_cloud', filename='img/2016_07_14_image.jpg') }}", alt="Image Sharing") img.img-responsive(src="{{ url_for('static_cloud', filename='img/2016_07_14_image.jpg') }}", alt="Image Sharing")
.page-card-side .page-card-side
h2.page-card-title h2.page-card-title
@@ -337,21 +337,21 @@ style.
section.page-card section.page-card
.page-card-side .page-card-side
h2.page-card-title h2.page-card-title
a(href='https://cloud.blender.org/blog/introducing-the-hdri-library') a(href='/blog/introducing-the-hdri-library')
| HDRI Library | HDRI Library
small July 27th, 2016 small July 27th, 2016
.page-card-summary .page-card-summary
| High-dynamic range images are now available on Blender Cloud! With their own special viewer. Also available via the Blender Cloud add-on. | High-dynamic range images are now available on Blender Cloud! With their own special viewer. Also available via the Blender Cloud add-on.
.page-card-side .page-card-side
a(href='https://cloud.blender.org/blog/introducing-the-hdri-library') a(href='/blog/introducing-the-hdri-library')
img.img-responsive(src="{{ url_for('static_cloud', filename='img/2016_07_27_hdri.jpg') }}", alt="HDRI Library") img.img-responsive(src="{{ url_for('static_cloud', filename='img/2016_07_27_hdri.jpg') }}", alt="HDRI Library")
section.page-card section.page-card
.page-card-side .page-card-side
a(href='https://cloud.blender.org/blog/introducing-the-hdri-library') a(href='/blog/introducing-the-hdri-library')
img.img-responsive(src="{{ url_for('static_cloud', filename='img/2016_12_06_toon.jpg') }}", alt="Hdri Library") img.img-responsive(src="{{ url_for('static_cloud', filename='img/2016_12_06_toon.jpg') }}", alt="Hdri Library")
.page-card-side .page-card-side
h2.page-card-title h2.page-card-title
a(href='https://cloud.blender.org/blog/new-training-toon-character-workflow') a(href='/blog/new-training-toon-character-workflow')
| Toon Character Workflow | Toon Character Workflow
small December 6th, 2016 small December 6th, 2016
.page-card-summary .page-card-summary
@@ -366,7 +366,7 @@ style.
| to all resources and training produced so far! | to all resources and training produced so far!
a.page-card-cta(href='https://store.blender.org/product/membership/') Subscribe a.page-card-cta(href='https://store.blender.org/product/membership/') Subscribe
.page-card-side .page-card-side
a(href='https://cloud.blender.org/p/agent-327') a(href='/p/agent-327')
img.img-responsive(src="{{ url_for('static_cloud', filename='img/2017_03_10_agent.jpg') }}", alt="Agent 327") img.img-responsive(src="{{ url_for('static_cloud', filename='img/2017_03_10_agent.jpg') }}", alt="Agent 327")

View File

@@ -6,7 +6,7 @@
| {% block og %} | {% block og %}
meta(property="og:type", content="website") meta(property="og:type", content="website")
meta(property="og:url", content="https://cloud.blender.org/") meta(property="og:url", content="{{ request.url }}")
meta(property="og:title", content="Blender Cloud") meta(property="og:title", content="Blender Cloud")
meta(name="twitter:title", content="Blender Cloud") meta(name="twitter:title", content="Blender Cloud")
@@ -18,59 +18,51 @@ meta(property="og:image", content="{% if main_project.picture_header %}{{ main_p
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_agent327_04.jpg')}}{% endif %}") 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_agent327_04.jpg')}}{% endif %}")
| {% endblock %} | {% endblock %}
| {% block body %} | {% block navigation_tabs %}
.dashboard-container | {{ navigation_tabs(title) }}
section.dashboard-main | {% endblock navigation_tabs %}
section.blog-stream | {% block body %}
ul.blog-stream__list .container-fluid.dashboard-container.imgs-fluid
.row
.col-md-8
section.blog
ul.list-unstyled
| {% if latest_posts %} | {% if latest_posts %}
| {% for node in latest_posts %} | {% for node in latest_posts %}
| {{ render_blog_post(node) }} | {{ render_blog_post(node) }}
| {% endfor %} | {% endfor %}
| {% else %} | {% else %}
li li
.blog-stream__list-details | No blog entries... yet!
ul.meta
li.when No blog entries... yet!
| {% endif %} | {% endif %}
.more .d-block.text-center
a(href="{{ url_for('main.main_blog') }}") a.d-inline-block.p-3.text-muted(href="{{ url_for('main.main_blog') }}")
| See All Blog Posts | See All Blog Posts
a.feed( a.d-inline-block.p-3.text-muted(
href="{{ url_for('main.feeds_blogs') }}", href="{{ url_for('main.feeds_blogs') }}",
title="Blogs Feed", title="Blogs Feed",
data-toggle="tooltip", data-toggle="tooltip",
data-placement="left") data-placement="left")
i.pi-rss i.pi-rss
| RSS Feed
.col-md-4
section.dashboard-secondary .dashboard-sidebar
| {{ navigation_tabs(title) }} section.pt-3
h6.title-underline In Production
section.dashboard-in-production a(href="/p/spring/")
h4 In Production
span.section-lead.
Check out these projects currently in production!
a.in-production-project(href="https://cloud.blender.org/p/spring/")
img(src="{{ url_for('static', filename='assets/img/projects/spring_450x150.jpg')}}") img(src="{{ url_for('static', filename='assets/img/projects/spring_450x150.jpg')}}")
p.
#[strong Spring] - A poetic short film about a mountain spirit and her wise little dog.
a.in-production-project(href="https://cloud.blender.org/p/hero/") p.text-muted.pt-2.
img(src="{{ url_for('static', filename='assets/img/projects/hero_450x150.jpg')}}") A poetic short film about a mountain spirit and her wise little dog. #[a(href="/p/spring/") Check it out].
p.
#[strong Hero] - A '2D' trailer-style movie focused on getting grease pencil
production ready for Blender 2.8.
section.stream section.stream.py-3
h6.title-underline Latest Assets
h4 Latest Assets ul.activity-stream__list.list-unstyled
ul.activity-stream__list
| {% for n in activity_stream %} | {% for n in activity_stream %}
li( li(
class="{{ n.node_type }} {{ n.properties.content_type }} {% if n.picture %}with-picture{% endif %}", class="{{ n.node_type }} {{ n.properties.content_type }} {% if n.picture %}with-picture{% endif %}",
@@ -104,7 +96,7 @@ meta(name="twitter:image", content="{% if main_project.picture_header %}{{ main_
.ribbon .ribbon
span free span free
| {% endif %} | {% endif %}
ul.meta ul.list-unstyled.d-flex.text-muted
| {% if not n.picture %} | {% if not n.picture %}
li.when li.when
a(href="{{ n.url }}", title="{{ n._created }}") {{ n._created | pretty_date_time }} a(href="{{ n.url }}", title="{{ n._created }}") {{ n._created | pretty_date_time }}
@@ -123,7 +115,7 @@ meta(name="twitter:image", content="{% if main_project.picture_header %}{{ main_
| {% endif %} | {% endif %}
| {% if n.picture %} | {% if n.picture %}
ul.meta.extra ul.list-unstyled.d-flex.text-muted.extra
li.when li.when
a(href="{{ n.url }}", title="{{ n._created }}") {{ n._created | pretty_date_time }} a(href="{{ n.url }}", title="{{ n._created }}") {{ n._created | pretty_date_time }}
li.who {{ n.user.full_name }} li.who {{ n.user.full_name }}
@@ -134,12 +126,12 @@ meta(name="twitter:image", content="{% if main_project.picture_header %}{{ main_
| No items to list. | No items to list.
section.random-asset section.random-asset.py-3
h4 h6.title-underline
a(href="/search") Explore the Cloud a(href="/search") Explore the Cloud
span.section-lead Random selection of the best assets &amp; tutorials .pb-3.text-muted Random selection of the best assets &amp; tutorials
ul.random-asset__list ul.random-asset__list.list-unstyled
| {% for n in random_featured %} | {% for n in random_featured %}
| {% if n.picture and loop.first %} | {% if n.picture and loop.first %}
li.random-asset__list-item.project li.random-asset__list-item.project
@@ -151,7 +143,7 @@ meta(name="twitter:image", content="{% if main_project.picture_header %}{{ main_
.random-asset__list-details .random-asset__list-details
a.title(href="{{ n.project.url }}") {{ n.project.name }} a.title(href="{{ n.project.url }}") {{ n.project.name }}
| {% if n.project.summary %} | {% if n.project.summary %}
ul.meta ul.list-unstyled.d-flex.text-muted
li.what li.what
a(href="{{ n.project.url }}") {{ n.project.summary }} a(href="{{ n.project.url }}") {{ n.project.summary }}
| {% endif %} | {% endif %}
@@ -175,7 +167,7 @@ meta(name="twitter:image", content="{% if main_project.picture_header %}{{ main_
a.title(href="{{ n.url }}") a.title(href="{{ n.url }}")
| {{ n.name }} | {{ n.name }}
ul.meta ul.list-unstyled.d-flex.text-muted
li.what li.what
a(href="{{ n.url }}") a(href="{{ n.url }}")
| {% if n.properties.content_type %}{{ n.properties.content_type | undertitle }}{% else %}Folder{% endif %} | {% if n.properties.content_type %}{{ n.properties.content_type | undertitle }}{% else %}Folder{% endif %}
@@ -207,7 +199,7 @@ meta(name="twitter:image", content="{% if main_project.picture_header %}{{ main_
| {% endif %} | {% endif %}
.random-asset__list-details .random-asset__list-details
a.title(href="{{ n.url }}") {{ n.name }} a.title(href="{{ n.url }}") {{ n.name }}
ul.meta ul.list-unstyled.d-flex.text-muted
li.what li.what
a(href="{{ n.url }}") a(href="{{ n.url }}")
| {% if n.properties.content_type %}{{ n.properties.content_type }}{% else %}Folder{% endif %} | {% if n.properties.content_type %}{{ n.properties.content_type }}{% else %}Folder{% endif %}
@@ -218,11 +210,10 @@ meta(name="twitter:image", content="{% if main_project.picture_header %}{{ main_
| {% endfor %} | {% endfor %}
section.comments section.comments.py-3
h6.title-underline Latest Comments
h4 Latest Comments ul.list-unstyled
ul
| {% if latest_comments %} | {% if latest_comments %}
| {% for n in latest_comments %} | {% for n in latest_comments %}
li( li(
@@ -232,7 +223,7 @@ meta(name="twitter:image", content="{% if main_project.picture_header %}{{ main_
a.comment-content(href="{{ n.url }}") a.comment-content(href="{{ n.url }}")
| {{ n.properties.content | striptags | truncate(200) }} | {{ n.properties.content | striptags | truncate(200) }}
ul.meta ul.list-unstyled.d-flex.text-muted
li.who {{ n.user.full_name }} li.who {{ n.user.full_name }}
| {% if n.attached_to %} | {% if n.attached_to %}

View File

@@ -3,7 +3,7 @@ html(lang="en")
head head
meta(charset="utf-8") meta(charset="utf-8")
title {% if self.page_title() %}{% block page_title %}{% endblock %} — {% endif %}Blender Cloud 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="viewport", content="width=device-width, initial-scale=1, shrink-to-fit=no")
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="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="author", content="Blender Institute")
meta(name="theme-color", content="#3e92aa") meta(name="theme-color", content="#3e92aa")
@@ -19,7 +19,7 @@ html(lang="en")
| {% block og %} | {% block og %}
meta(property="og:title", content="Blender Cloud") meta(property="og:title", content="Blender Cloud")
meta(property="og:url", content="https://cloud.blender.org") meta(property="og:url", content="{{ request.url }}")
meta(property="og:type", content="website") meta(property="og:type", content="website")
meta(property="og:image", content="{{ url_for('static', filename='assets/img/backgrounds/background_gleb_locomotive.jpg')}}") meta(property="og:image", content="{{ url_for('static', filename='assets/img/backgrounds/background_gleb_locomotive.jpg')}}")
meta(property="og: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(property="og: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.")
@@ -45,33 +45,22 @@ html(lang="en")
link(href="{{ url_for('static', filename='assets/img/favicon.png') }}", rel="shortcut icon") link(href="{{ url_for('static', filename='assets/img/favicon.png') }}", rel="shortcut icon")
link(href="{{ url_for('static', filename='assets/img/apple-touch-icon-precomposed.png') }}", rel="icon apple-touch-icon-precomposed", sizes="192x192") link(href="{{ url_for('static', filename='assets/img/apple-touch-icon-precomposed.png') }}", rel="icon apple-touch-icon-precomposed", sizes="192x192")
link(rel="stylesheet", href="{{ url_for('static', filename='assets/bootstrap/css/bootstrap.min.css') }}")
link(href="{{ url_for('static_pillar', filename='assets/css/font-pillar.css') }}", rel="stylesheet")
link(rel="stylesheet", href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,600")
link(href="{{ url_for('static', filename='assets/google-font-roboto/roboto.css') }}", rel="stylesheet")
| {% block head %}{% endblock %} | {% block head %}{% endblock %}
| {% block css %} | {% 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/font-pillar.css') }}", rel="stylesheet")
link(href="{{ url_for('static_pillar', filename='assets/css/base.css') }}", rel="stylesheet")
| {% if title == 'blog' %} | {% if title == 'blog' %}
link(href="{{ url_for('static_pillar', filename='assets/css/blog.css') }}", rel="stylesheet") link(href="{{ url_for('static_pillar', filename='assets/css/blog.css') }}", rel="stylesheet")
| {% else %} | {% else %}
link(href="{{ url_for('static_cloud', filename='assets/css/main.css') }}", rel="stylesheet") link(href="{{ url_for('static_cloud', filename='assets/css/main.css') }}", rel="stylesheet")
link(href="{{ url_for('static_cloud', filename='assets/css/base.css') }}", rel="stylesheet")
| {% endif %} | {% endif %}
| {% endblock css %} | {% endblock css %}
| {% if not title %}{% set title="default" %}{% endif %} | {% if not title %}{% set title="default" %}{% endif %}
body(class="{{ title }}") body(class="{{ title }}")
.container-page
| {% with messages = get_flashed_messages(with_categories=True) %} | {% with messages = get_flashed_messages(with_categories=True) %}
| {% if messages %} | {% if messages %}
| {% for (category, message) in messages %} | {% for (category, message) in messages %}
.alert(role="alert", class="alert-{{ category }}") .alert(role="alert", class="alert-{{ category }}")
i.alert-icon(class="{{ category }}") i.alert-icon(class="{{ category }}")
@@ -79,30 +68,38 @@ html(lang="en")
button.close(type="button", data-dismiss="alert") button.close(type="button", data-dismiss="alert")
i.pi-cancel i.pi-cancel
| {% endfor %} | {% endfor %}
| {% endif %} | {% endif %}
| {% endwith %} | {% endwith %}
//- Navigation Bar nav.navbar.navbar-expand-md.fixed-top.bg-white
nav.navbar.navbar-expand-md.navbar-light.sticky-top a.navbar-brand(
//- Logo href="{{ url_for('main.homepage') }}",
a.navbar-brand(href="{{ url_for('main.homepage') }}") title="Blender Cloud")
img(src="{{ url_for('static', filename='assets/img/logo-blender-cloud-text.svg') }}", alt="alt") span.app-logo
//- Mobile Nav Button i.pi-blender-cloud
button.navbar-toggler(type='button', data-toggle='collapse', data-target='#navbarNav', aria-controls="navbarNav", aria-expanded="false", aria-label="Toggle navigation")
span button.navbar-toggler.text-light(
span data-target=".navbar-collapse",
span data-toggle="collapse",
//- Search Bar type="button")
#searchNav.hidden span.sr-only Toggle navigation
span.search-container span.navbar-toggler-icon.d-flex.align-items-center
input#cloud-search(type="text", placeholder="Search Blender Cloud") i.pi-menu
| {% block navigation_tabs %}
| {% endblock navigation_tabs %}
| {% block navigation_search %}
// TODO (pablo) - bring it back asap
.search-input
input#cloud-search(
type="text",
placeholder="Search assets, tutorials...")
i.search-icon.pi-search i.search-icon.pi-search
a#searchCloseButton(ahref="#") | {% endblock navigation_search %}
img(src="{{ url_for('static', filename='assets/img/icons/icon-close-button.svg') }}", alt="alt")
//- Links .collapse.navbar-collapse
#navbarNav.collapse.navbar-collapse.justify-content-end ul.navbar-nav.ml-auto
ul.navbar-nav
| {% if node and node.properties and node.properties.category %} | {% if node and node.properties and node.properties.category %}
| {% set category = node.properties.category %} | {% set category = node.properties.category %}
| {% else %} | {% else %}
@@ -110,60 +107,177 @@ html(lang="en")
| {% endif %} | {% endif %}
| {% block navigation_sections %} | {% block navigation_sections %}
li.nav-item li
a.nav-link(href="{{ url_for('main.main_blog') }}", class="{% if category == 'blog' %}active{% endif %}") Blog a.navbar-item(
li.nav-item.dropdown href="{{ url_for('main.main_blog') }}",
a.nav-link.dropdown-toggle(href="#", data-toggle="dropdown") Libraries title="Blender Cloud Blog",
.dropdown-menu data-toggle="tooltip",
a.dropdown-item( data-placement="bottom",
href="{{ url_for('projects.view', project_url='hdri') }}") class="{% if category == 'blog' %}active{% endif %}")
span Blog
li.dropdown
a.navbar-item.dropdown-toggle(
href="",
data-toggle="dropdown",
title="Libraries")
span Libraries
i.pi-angle-down
ul.dropdown-menu.p-0
li
a.navbar-item(
href="{{ url_for('projects.view', project_url='hdri') }}",
title="HDRI Library",
data-toggle="tooltip",
data-placement="left")
i.pi-globe i.pi-globe
| HDRI | HDRI
a.dropdown-item( li
href="{{ url_for('projects.view', project_url='textures') }}") a.navbar-item(
href="{{ url_for('projects.view', project_url='textures') }}",
title="Textures Library",
data-toggle="tooltip",
data-placement="left")
i.pi-folder-texture i.pi-folder-texture
| Textures | Textures
a.dropdown-item( li
href="{{ url_for('projects.view', project_url='characters') }}") a.navbar-item(
href="{{ url_for('projects.view', project_url='characters') }}",
title="Character Library",
data-toggle="tooltip",
data-placement="left")
i.pi-character i.pi-character
| Characters | Characters
li.nav-item.dropdown
a.nav-link.dropdown-toggle(href="#", data-toggle="dropdown") Training
.dropdown-menu li(class="dropdown")
a.dropdown-item(href="{{ url_for('cloud.courses') }}") a.navbar-item.dropdown-toggle(
href="{{ url_for('cloud.workshops') }}"
data-toggle="dropdown",
title="Training")
span Training
i.pi-angle-down
ul.dropdown-menu
li
a.navbar-item(
href="{{ url_for('cloud.courses') }}",
title="Courses",
data-toggle="tooltip",
data-placement="left")
i.pi-graduation-cap i.pi-graduation-cap
| Courses | Courses
a.dropdown-item(href="{{ url_for('cloud.workshops') }}") li
a.navbar-item(
href="{{ url_for('cloud.workshops') }}",
title="Workshops",
data-toggle="tooltip",
data-placement="left")
i.pi-lightbulb i.pi-lightbulb
| Workshops | Workshops
a.dropdown-item(href="{{ url_for('projects.view', project_url='gallery') }}") li
a.navbar-item(
href="{{ url_for('projects.view', project_url='gallery') }}",
title="Curated artwork collection",
data-toggle="tooltip",
data-placement="left")
i.pi-image i.pi-image
| Art Gallery | Art Gallery
li.nav-item
a.nav-link(href="{{ url_for('cloud.open_projects') }}",
class="{% if category in ['open-projects', 'film'] %}active{% endif %}") Open Projects
li.nav-item
a.nav-link(href="{{ url_for('cloud.services') }}",
class="{% if category == 'services' %}active{% endif %}") Services
li.nav-item.search-icon li(class="dropdown")
a#searchButton.navbar-item(data-toggle='collpase', data-target='#searchbarNav', href="#") a.navbar-item.dropdown-toggle(
i.pi-search href="{{ url_for('cloud.open_projects') }}",
title="Browse all the Open Projects",
data-toggle="dropdown",
class="{% if category in ['open-projects', 'film'] %}active{% endif %}")
span Open Projects
i.pi-angle-down
ul.dropdown-menu
li
a.navbar-item(href="/p/spring")
span.px-2 Spring
li
a.navbar-item(href="/p/hero")
span.px-2 Hero
li
a.navbar-item(href="/p/dailydweebs")
span.px-2 The Daily Dweebs
li
a.navbar-item(href="/p/agent-327")
span.px-2 Agent 327
li
a.navbar-item(href="/p/caminandes-3")
span.px-2 Caminandes: Llamigos
li.dropdown-divider
li
a.navbar-item(href="{{ url_for('cloud.open_projects') }}")
span.pl-2 All Open Projects
li(class="dropdown")
a.navbar-item.dropdown-toggle(
href="{{ url_for('cloud.services') }}",
title="Blender Cloud Services",
data-toggle="dropdown",
class="{% if category == 'services' %}active{% endif %}")
span Services
i.pi-angle-down
ul.dropdown-menu
li
a.navbar-item(
href="/attract",
title="Production Management",
data-toggle="tooltip",
data-placement="left")
i.pi-attract
| Attract
li
a.navbar-item(
href="/flamenco",
title="Render Management",
data-toggle="tooltip",
data-placement="left")
i.pi-flamenco
| Flamenco
li
a.navbar-item(
href="/services#blender-cloud-add-on",
title="Blender Sync, Texture Browser and more",
data-toggle="tooltip",
data-placement="left")
i.pi-blender
| Blender Cloud Add-on
li.dropdown-divider
li
a.navbar-item(
href="{{ url_for('cloud.services') }}",
title="All Blender Cloud services",
data-toggle="tooltip",
data-placement="left")
i.pi-list
| All Services
| {% endblock navigation_sections %} | {% endblock navigation_sections %}
| {% if current_user.is_anonymous %}
li.nav-item
a.nav-link(
href="https://store.blender.org/product/membership/",
title="Sign up") Sign up
| {% endif %}
| {% block navigation_user %} | {% block navigation_user %}
| {% include 'menus/notifications.html' %} | {% include 'menus/notifications.html' %}
| {% include 'menus/user.html' %} | {% include 'menus/user.html' %}
| {% endblock navigation_user %} | {% endblock navigation_user %}
| {% if current_user.is_anonymous %}
li.pt-1
a.btn.btn-sm.btn-primary.px-3.mx-1(
href="https://store.blender.org/product/membership/",
title="Sign up") Sign up
| {% endif %}
.page-content .page-content
#search-overlay #search-overlay
| {% block page_overlay %} | {% block page_overlay %}
@@ -173,79 +287,114 @@ html(lang="en")
| {% block body %}{% endblock %} | {% block body %}{% endblock %}
| {% block footer_container %} | {% block footer_container %}
footer.container-fluid .footer-wrapper
| {% block footer_navigation %} | {% block footer_navigation %}
.container.py-5 .footer-navigation
.container
.row .row
.col-4 .col-md-4.col-xs-6
h5 Blender Cloud h4
p A creative hub for your projects, powered by free and open source software. a(href="{{ url_for('main.homepage') }}")
ul.list-inline.social-icons i.pi-blender-cloud-logo
li.list-inline-item
a(href="https://www.facebook.com/BlenderCloudOfficial/")
img(src="../../static/assets/img/icons/icon-social-facebook.svg", alt="alt")
li.list-inline-item
a(href="https://twitter.com/Blender_Cloud")
img(src="../../static/assets/img/icons/icon-social-twitter.svg", alt="alt")
li.list-inline-item
a(href="https://www.youtube.com/channel/UC5qvW9fotdsSJkCguB_t-kQ")
img(src="../../static/assets/img/icons/icon-social-youtube.svg", alt="alt")
.col
h5 Libraries
ul.list-unstyled.text-small
li
a(href="{{ url_for('projects.view', project_url='hdri') }}") HDRI
li
a(href="{{ url_for('projects.view', project_url='textures') }}") Textures
li
a(href="{{ url_for('projects.view', project_url='characters') }}") Characters
.col
h5 Training
ul.list-unstyled.text-small
li
a(href="{{ url_for('projects.view', project_url='gallery') }}") Art Gallery
li
a(href="{{ url_for('cloud.courses') }}") Courses
li
a(href="{{ url_for('cloud.workshops') }}") Workshops
.col
h5 Resources
ul.list-unstyled.text-small
li
a(href="https://www.blender.org") Blender
li
a(href="https://store.blender.org/") Blender Store
li
a(href="https://www.blender.org/foundation/") Contact Us
li
a(href="{{ url_for('cloud.terms_and_conditions') }}") Terms and Conditions
li
a(href="{{ url_for('cloud.privacy') }}") Privacy
.col
h5 Services
ul.list-unstyled.text-small
li
a(href="https://cloud.blender.org/services#attract") Attract
li
a(href="https://cloud.blender.org/services#blender-cloud-add-on") Blender Cloud Add-on
li
a(href="https://cloud.blender.org/services#blender-sync") Blender Sync
li
a(href="https://cloud.blender.org/services#flamenco") Flamenco
li
a(href="https://cloud.blender.org/services#image-sharing") Image Sharing
li
a(href="https://cloud.blender.org/services#projects") Private Projects
li
a(href="https://cloud.blender.org/services#texture-browser") Texture Browser
p.pl-2.
Blender Cloud is the creative hub for your projects,
powered by Free and Open Source Software.
h5.d-flex
a.px-2(href="https://twitter.com/Blender_Cloud",
title="Follow us on Twitter")
i.pi-social-youtube
a.px-2(href="https://twitter.com/Blender_Cloud",
title="Follow us on Twitter")
i.pi-social-twitter
a.px-2(href="https://www.facebook.com/BlenderCloudOfficial/",
title="Follow us on Facebook")
i.pi-social-facebook
.col-md-2.col-xs-6
h7.font-weight-bold
| TRAINING
ul.list-unstyled
li
a(href="{{ url_for('cloud.courses') }}")
| Courses
li
a(href="{{ url_for('cloud.workshops') }}")
| Workshops
li
a(href="{{ url_for('projects.view', project_url='gallery') }}")
| Art Gallery
.col-md-2.col-xs-6
h7.font-weight-bold
| LIBRARIES
ul.list-unstyled
li
a(href="{{ url_for('main.main_blog') }}",
title="Blender Cloud Blog")
| HDRIs
li
a(href="{{ url_for('cloud.services') }}",
title="Blender Cloud Services")
| Textures
li
a(href="{{ url_for('cloud.about') }}",
title="About Blender Cloud")
| Characters
.col-md-2.col-xs-6
h7.font-weight-bold
a(href="{{ url_for('cloud.services') }}")
| SERVICES
ul.list-unstyled
li
a(href="{{ url_for('main.main_blog') }}",
title="Blender Cloud Blog")
| Add-on
li
a(href="{{ url_for('main.main_blog') }}",
title="Blender Cloud Blog")
| Blender Sync
li
a(href="{{ url_for('cloud.services') }}",
title="Blender Cloud Services")
| Attract
li
a(href="{{ url_for('cloud.about') }}",
title="About Blender Cloud")
| Flamenco
li
a(href="{{ url_for('cloud.about') }}",
title="About Blender Cloud")
| Image Sharing
.col-md-2.col-xs-6
h7.font-weight-bold
| BLENDER
ul.list-unstyled
li
a(href="{{ url_for('main.main_blog') }}",
title="Blender Cloud Blog")
| blender.org
li
a(href="{{ url_for('cloud.terms_and_conditions') }}",
title="Terms and Conditions")
| Terms and Conditions
li
a(href="{{ url_for('cloud.privacy') }}",
title="Privacy")
| Privacy
| {% endblock footer_navigation %} | {% endblock footer_navigation %}
//- Scroll Up Arrow. Not sure if it's necessary
//- | {% block footer %} #hop(title="Be awesome in space")
//- footer.container i.pi-angle-up
//- #hop(title="Be awesome in space")
//- i.pi-angle-up
//- | {% endblock footer %}
| {% endblock footer_container %} | {% endblock footer_container %}
#notification-pop(data-url="", data-read-toggle="") #notification-pop(data-url="", data-read-toggle="")
@@ -258,19 +407,7 @@ html(lang="en")
span.nc-date span.nc-date
a(href="") a(href="")
noscript script(src="{{ url_for('static_cloud', filename='assets/js/bootstrap.min.js') }}")
link(href='//fonts.googleapis.com/css?family=Roboto:300,400', rel='stylesheet', type='text/css')
//- script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.bootstrap-3.3.7.min.js') }}")
//- local bootstrap js returns error message, investigate later
//- script(src="{{ url_for('static', filename='assets/jquery/jquery.slim.min.js') }}")
//- script(src="{{ url_for('static', filename='assets/popper.js/popper.min.js') }}")
//- script(src="{{ url_for('static', filename='assets/bootstrap/js/bootstrap.min.js') }}")
script(src="https://code.jquery.com/jquery-3.3.1.min.js", integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=", crossorigin="anonymous")
script(src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js", integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49", crossorigin="anonymous")
script(src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.2/js/bootstrap.min.js", integrity="sha384-o+RDsa0aLu++PJvFqy8fFScvbHFLtbvScb8AjopnFD+iEQ7wo/CG0xlczd+2O/em", crossorigin="anonymous")
script(src="{{ url_for('static_cloud', filename='assets/js/layout.min.js') }}")
| {% if current_user.is_authenticated %} | {% if current_user.is_authenticated %}
script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.typewatch-3.0.0.min.js') }}") script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.typewatch-3.0.0.min.js') }}")
@@ -299,9 +436,6 @@ html(lang="en")
if (typeof $().tooltip != 'undefined'){ if (typeof $().tooltip != 'undefined'){
$('[data-toggle="tooltip"]').tooltip({'delay' : {'show': 0, 'hide': 0}}); $('[data-toggle="tooltip"]').tooltip({'delay' : {'show': 0, 'hide': 0}});
} }
if(typeof($.fn.popover) != 'undefined'){
$('[data-toggle="popover"]').popover();
}
| {% block footer_scripts_pre %}{% endblock %} | {% block footer_scripts_pre %}{% endblock %}
| {% block footer_scripts %}{% endblock %} | {% block footer_scripts %}{% endblock %}

View File

@@ -9,7 +9,7 @@
| {% endif %} | {% endif %}
| {% block menu_avatar %} | {% block menu_avatar %}
a.nav-link.dropdown-toggle(href="#", data-toggle="dropdown", title="{{ current_user.email }}", aria-haspopup="true", aria-expanded="false") a.navbar-item.dropdown-toggle(href="#", data-toggle="dropdown", title="{{ current_user.email }}")
img.gravatar( img.gravatar(
src="{{ current_user.gravatar }}", src="{{ current_user.gravatar }}",
class="{{ subscription }}", class="{{ subscription }}",
@@ -26,26 +26,26 @@ a.nav-link.dropdown-toggle(href="#", data-toggle="dropdown", title="{{ current_u
| {% block menu_list %} | {% block menu_list %}
.dropdown-menu.subscription-status(class="{{ subscription }}", aria-labelledby="dropdownMenuLink") li.subscription-status(class="{{ subscription }}")
| {% if subscription == 'subscriber' %} | {% if subscription == 'subscriber' %}
a.dropdown-item( a.navbar-item(
href="{{url_for('settings.billing')}}" href="{{url_for('settings.billing')}}"
title="View subscription info") title="View subscription info")
i.pi-grin i.pi-grin
span Your subscription is active! span Your subscription is active!
| {% elif subscription == 'demo' %} | {% elif subscription == 'demo' %}
a.dropdown-item( a.navbar-item(
href="{{url_for('settings.billing')}}" href="{{url_for('settings.billing')}}"
title="View subscription info") title="View subscription info")
i.pi-heart-filled i.pi-heart-filled
span You have a free account. span You have a free account.
| {% elif current_user.has_cap('can-renew-subscription') %} | {% elif current_user.has_cap('can-renew-subscription') %}
a.dropdown-item(target='_blank', href="/renew", title="Renew subscription") a.navbar-item(target='_blank', href="/renew", title="Renew subscription")
i.pi-heart i.pi-heart
span.info Your subscription is not active. span.info Your subscription is not active.
span.renew Click here to renew. span.renew Click here to renew.
| {% else %} | {% else %}
a.dropdown-item( a.navbar-item(
href="https://store.blender.org/product/membership/" href="https://store.blender.org/product/membership/"
title="Renew subscription") title="Renew subscription")
i.pi-unhappy i.pi-unhappy
@@ -56,7 +56,7 @@ a.nav-link.dropdown-toggle(href="#", data-toggle="dropdown", title="{{ current_u
| {{ super() }} | {{ super() }}
li li
a.dropdown-item( a.navbar-item(
href="{{ url_for('settings.billing') }}" href="{{ url_for('settings.billing') }}"
title="Billing") title="Billing")
i.pi-credit-card i.pi-credit-card

View File

@@ -0,0 +1,69 @@
// {#
// Header of landing pages. title or text can be skipped:
// +jumbotron("{{ page_title }}", null, "{{ page_header_image }}")
// Any extra attributes added (in a separate group) will be passed as is:
// +jumbotron("{{ page_title }}", null, "{{ page_header_image }}")(data-node-id='{{ node._id }}')
// #}
mixin jumbotron(title, text, image, url)
if url
a.jumbotron.jumbotron-overlay.text-white(
style='background-image: url(' + image + ');',
href=url)&attributes(attributes)
.container
.row
.col-md-9
if title
.display-4.text-uppercase.font-weight-bold
=title
if text
.lead
=text
else
.jumbotron.jumbotron-overlay.text-white(style='background-image: url(' + image + ');')&attributes(attributes)
.container
.row
.col-md-9
if title
.display-4.text-uppercase.font-weight-bold
=title
if text
.lead
=text
// {# Secondary navigation.
// e.g. Workshops, Courses. #}
mixin nav-secondary(title)
ul.nav.nav-secondary&attributes(attributes)
if title
li.font-weight-bold.px-2
=title
if block
block
else
p No items defined.
mixin nav-secondary-link()
li.nav-item
a.nav-link&attributes(attributes)
block
// {# Takes as argument the number of columns to use in this deck. 1-6 #}
mixin card-deck(columns)
.card-deck.card-padless(class='card-' + columns + '-columns')
if block
block
else
p No cards defined.
// {#
// Passes all attributes to the card.
// You can do fun stuff in a loop even like:
// +card(data-url="{{ url_for('projects.view', project_url=project.url) }}", tabindex='{{ loop.index }}')
// #}
mixin card()
.card.card-fade.cursor-pointer.mb-4.js-project-go&attributes(attributes)
if block
block
else
p No card content defined.

View File

@@ -0,0 +1,164 @@
include ../../../mixins/components
| {% import 'projects/_macros.html' as projectmacros %}
| {% macro render_blog_post(node, project=None, pages=None) %}
.expand-image-links.imgs-fluid
| {% if node.picture %}
+jumbotron(
"{{ node.name }}",
"{{ node._created | pretty_date }}",
"{{ node.picture.thumbnail('h', api=api) }}",
"{{ node.url }}")(class="row")
| {% else %}
.pt-3.text-center.text-muted
h2
a.text-muted(href="{{ node.url }}")
| {{ node.name }}
ul.d-flex.list-unstyled.justify-content-center
| {% if node.project.name %}
li.pr-2 {{ node.project.name }}
| {% endif %}
| {% if node.user.full_name %}
li.pr-2
| {{ node.user.full_name }}
| {% endif %}
li
a.px-2.text-muted(href="{{ node.url }}",
title="Updated {{ node._updated | pretty_date }}")
| {{ node._created | pretty_date }}
li
a.px-2(href="{{ node.url }}#comments")
| Leave a comment
| {% if node.has_method('PUT') %}
li
a.px-2(href="{{url_for('nodes.edit', node_id=node._id)}}")
i.pi-edit
| Edit Post
| {% endif %}
| {% endif %}
| {% if project and project._id != config.MAIN_PROJECT_ID %}
| {{ projectmacros.render_secondary_navigation(project, pages=pages) }}
| {% endif %}
.row
.col-md-9.mx-auto
.item-content.pt-4
| {{ node.properties | markdowned('content') }}
hr.my-4
| {% endmacro %}
//- ******************************************************* -//
| {% macro render_blog_list_item(node) %}
.row.position-relative.py-2
.col-md-1
| {% if node.picture %}
a.imgs-fluid(href="{{ node.url }}")
img(src="{{ node.picture.thumbnail('s', api=api) }}")
| {% else %}
.bg-primary.rounded.h-100
a.d-flex.align-items-center.justify-content-center.h-100.text-white(href="{{ node.url }}")
i.pi-document-text
| {% endif %}
.col-md-11
h5
a.text-muted(href="{{ node.url }}") {{node.name}}
.text-muted.
#[span(title="{{node._created}}") {{node._created | pretty_date }}]
{% if node._created != node._updated %}
#[span(title="{{node._updated}}") (updated {{node._updated | pretty_date }})]
{% endif %}
{% if node.properties.category %} · {{node.properties.category}}{% endif %}
· {{node.user.full_name}}
{% if node.properties.status != 'published' %} · {{ node.properties.status}} {% endif %}
| {% endmacro %}
//- ******************************************************* -//
| {% macro render_blog_index(project, posts, can_create_blog_posts, api, more_posts_available, posts_meta, pages=None) %}
| {% if can_create_blog_posts %}
+nav-secondary
+nav-secondary-link(href="{{url_for('nodes.posts_create', project_id=project._id)}}")
span.text-success
i.pi-plus
| Create New Blog Post
| {% endif %}
| {% if posts %}
| {{ render_blog_post(posts[0], project=project, pages=pages) }}
.container
.row
.col-md-9.mx-auto
| {% for node in posts[1:] %}
| {% if loop.first %}
h5.text-muted.text-center Blasts from the past
| {% endif %}
| {{ render_blog_list_item(node) }}
| {% endfor %}
| {% if more_posts_available %}
.blog-archive-navigation
a(href="{{ project.blog_archive_url }}")
| {{posts_meta.total - posts|length}} more blog posts over here
i.pi-angle-right
| {% endif %}
| {% else %}
.text-center
p No posts... yet!
| {% endif %} {# posts #}
| {% endmacro %}
//- Macro for rendering the navigation buttons for prev/next pages -//
| {% macro render_archive_pagination(project) %}
.blog-archive-navigation
| {% if project.blog_archive_prev %}
a.archive-nav-button(
href="{{ project.blog_archive_prev }}", rel="prev")
i.pi-angle-left
| Previous page
| {% else %}
span.archive-nav-button
i.pi-angle-left
| Previous page
| {% endif %}
a.archive-nav-button(
href="{{ url_for('main.project_blog', project_url=project.url) }}")
| Blog Index
| {% if project.blog_archive_next %}
a.archive-nav-button(
href="{{ project.blog_archive_next }}", rel="next")
| Next page
i.pi-angle-right
| {% else %}
span.archive-nav-button
| Next page
i.pi-angle-right
| {% endif %}
| {% endmacro %}
| {% macro render_archive(project, posts, posts_meta) %}
| {{ render_archive_pagination(project) }}
| {% for node in posts %}
| {{ render_blog_list_item(node) }}
| {% endfor %}
| {{ render_archive_pagination(project) }}
| {% endmacro %}

View File

@@ -0,0 +1,213 @@
| {% extends 'layout.html' %}
| {% from '_macros/_navigation.html' import navigation_tabs %}
include ../mixins/components
| {% set title = 'organizations' %}
| {% block page_title %}Organizations{% endblock %}
| {% block og %}
meta(property="og:title", content="Dashboard")
meta(name="twitter:title", content="Blender Cloud")
meta(property="og:url", content="https://cloud.blender.org/{{ request.path }}")
meta(property="og:type", content="website")
meta(property="og:image", content="{{ url_for('static', filename='assets/img/backgrounds/cloud_services_oti.jpg')}}")
meta(name="twitter:image", content="{{ url_for('static', filename='assets/img/backgrounds/cloud_services_oti.jpg')}}")
| {% endblock %}
| {% block navigation_tabs %}
| {{ navigation_tabs(title) }}
| {% endblock navigation_tabs %}
| {% block body %}
+nav-secondary
| {% if can_create_organization %}
+nav-secondary-link(
class="create",
onclick='createNewOrganization(this)')
span.text-success
i.pi-plus
| Create Organization
| {% endif %}
li#create_organization_result_panel.result
.container-fluid.dashboard-container
.row
.col-md-6
ul.projects__list
| {% if organizations %}
| {% for organization in organizations['_items'] %}
| {% set link_url = url_for('pillar.web.organizations.view_embed', organization_id=organization._id) %}
li.projects__list-item(
data-url="{{ link_url }}",
id="organization-{{ organization._id }}")
a.projects__list-thumbnail(
href="{{ link_url }}")
i.pi-users
.projects__list-details
a.title(href="{{ link_url }}")
| {{ organization.name }}
ul.meta
li(title="Members")
| {{ organization.members|hide_none|count }} Member{{ organization.members|hide_none|count|pluralize }}
| {% if (organization.unknown_members|count) != 0 %}
| ({{ organization.unknown_members|hide_none|count }} pending)
| {% endif %}
li(title="Seats")
| {{ organization.seat_count }} Seat{{ organization.seat_count|pluralize }}
| {% endfor %}
| {% else %}
li.projects__list-item
a.projects__list-thumbnail
i.pi-blender-cloud
.projects__list-details
span Create an Organization to get started!
| {% endif %}
.col-md-6.py-1.pb-3
#item-details
| {% endblock %}
| {% block footer_scripts %}
script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.typeahead-0.11.1.min.js')}}")
script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.autocomplete-0.22.0.min.js') }}", async=true)
script.
/* Returns a more-or-less reasonable message given an error response object. */
function xhrErrorResponseMessage(err) {
if (typeof err.responseJSON == 'undefined')
return err.statusText;
if (typeof err.responseJSON._error != 'undefined' && typeof err.responseJSON._error.message != 'undefined')
return err.responseJSON._error.message;
if (typeof err.responseJSON._message != 'undefined')
return err.responseJSON._message
return err.statusText;
}
/**
* Open an organization in the #item-details div.
*/
function item_open(item_id, pushState)
{
if (item_id === undefined ) {
throw new ReferenceError("item_open(" + item_id + ") called.");
}
// Style elements starting with item_type and dash, e.g. "#job-uuid"
var clean_classes = 'active processing';
var current_item = $('#organization-' + item_id);
$('[id^="organization-"]').removeClass(clean_classes);
current_item
.removeClass(clean_classes)
.addClass('processing');
var item_url = '/o/' + item_id;
$.get(item_url, function(item_data) {
$('#item-details').html(item_data);
current_item
.removeClass(clean_classes)
.addClass('active');
}).fail(function(xhr) {
if (console) {
console.log('Error fetching organization', item_id, 'from', item_url);
console.log('XHR:', xhr);
}
current_item.removeClass(clean_classes);
toastr.error('Failed to open organization');
if (xhr.status) {
$('#item-details').html(xhr.responseText);
} else {
$('#item-details').html('<p class="text-danger">Opening ' + item_type + ' failed. There possibly was ' +
'an error connecting to the server. Please check your network connection and ' +
'try again.</p>');
}
});
// 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 = {itemId: item_id};
window.history.pushState(
push_state,
'Organization: ' + item_id,
item_url
);
}
$('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');
});
{% if open_organization_id %}
$(function() { item_open('{{ open_organization_id }}', false); });
{% endif %}
{% if can_create_organization %}
function createNewOrganization(button) {
$(button)
.attr('disabled', 'disabled')
.fadeTo(200, 0.1);
$('#create_organization_result_panel').html('');
// TODO: create a form to get the initial info from the user.
$.post(
'{{ url_for('pillar.web.organizations.create_new') }}',
{
name: 'New Organization',
seat_count: 1,
}
)
.done(function(result) {
var $p = $('<p>').text('organization created, reloading list.')
$('#create_organization_result_panel').html($p);
window.location.href = result.location;
})
.fail(function(err) {
var msg = xhrErrorResponseMessage(err);
$('#create_organization_result_panel').html('Error creating organization: ' + msg);
$(button)
.fadeTo(1000, 1.0)
.queue(function() {
$(this)
.removeAttr('disabled')
.dequeue()
;
})
})
;
return false;
}
{% endif %}
| {% endblock %}

View File

@@ -0,0 +1,35 @@
| {% extends 'layout.html' %}
| {% block page_title %}Production of Stuff{% endblock %}
| {% block head %}
script(src="{{ url_for('static_cloud', filename='assets/js/tagged_assets.min.js') }}")
script.
$(function() {
$('ul.asset-list').loadTaggedAssets();
})
| {% endblock %}
| {% block body %}
#page-container
#page-content
h2 Production of Stuff
p.
Here are our hand-selected assets 'bout stuff.
h3 Animation
ul.asset-list(data-asset-tag="animation")
h3 Modelling
ul.asset-list(data-asset-tag="modelling")
h3 Rigging
ul.asset-list(data-asset-tag="rigging")
h3 pipeline
ul.asset-list(data-asset-tag="pipeline")
h3 lookdev
ul.asset-list(data-asset-tag="lookdev")
h3 crazyspace
ul.asset-list(data-asset-tag="crazyspace")
| {% endblock body%}

View File

@@ -0,0 +1,59 @@
| {% extends 'projects/home_layout.html' %}
| {% set subtab = 'blender_sync' %}
| {% set learn_more_btn_url = '/blog/introducing-blender-sync' %}
| {% block currenttab %}
.container-fluid
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 and keymaps 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.
| {% if show_addon_download_buttons %}
.row
.col-md-6
a.btn.btn-block.btn-outline-success(
href="https://cloud.blender.org/r/downloads/blender_cloud-latest-bundle.zip")
i.pi-download
| Download <small>v</small>{{ config.BLENDER_CLOUD_ADDON_VERSION }}
.col-md-6
a.btn.btn-link(
href="{{ learn_more_btn_url }}")
| Learn More
i.pi-angle-right
| {% endif %}
.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
h5.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 %}

View File

@@ -0,0 +1,51 @@
| {% extends 'layout.html' %}
| {% from '_macros/_navigation.html' import navigation_tabs %}
include ../mixins/components
| {% set title = 'home' %}
| {% block og %}
meta(property="og:type", content="website")
meta(property="og:url", content="https://cloud.blender.org{{ request.path }}")
meta(property="og:title", content="Blender Cloud - Home")
meta(name="twitter:title", content="Blender Cloud")
meta(property="og:image", content="{{ url_for('static', filename='assets/img/backgrounds/cloud_services_oti.jpg')}}")
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 navigation_tabs %}
| {{ navigation_tabs(title) }}
| {% endblock navigation_tabs %}
| {% block body %}
.dashboard-container
section#projects.bg-white
+nav-secondary()(id='sub-nav-tabs__list')
+nav-secondary-link(id="subtab-blender_sync", data-tab-url="{{ url_for('projects.home_project')}}")
| Blender Sync
+nav-secondary-link(id="subtab-images", data-tab-url="{{ url_for('projects.home_project_shared_images')}}")
| Images
| {% block currenttab %}{% endblock %}
| {% endblock %}
| {% block footer_scripts %}
script.
$(document).ready(function () {
$('#subtab-{{ subtab }}').addClass('active');
var $nav_tabs = $('#sub-nav-tabs__list').find('a.nav-link');
$nav_tabs.on('click', function (e) {
console.log($(this));
window.location = $(this).attr('data-tab-url');
});
});
| {% endblock %}

View File

@@ -0,0 +1,300 @@
| {% extends 'layout.html' %}
| {% from '_macros/_navigation.html' import navigation_tabs %}
include ../mixins/components
| {% set title = 'dashboard' %}
| {% block og %}
meta(property="og:title", content="Dashboard")
meta(name="twitter:title", content="Blender Cloud")
meta(property="og:url", content="https://cloud.blender.org/{{ request.path }}")
meta(property="og:type", content="website")
meta(property="og:image", content="{{ url_for('static', filename='assets/img/backgrounds/cloud_services_oti.jpg')}}")
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 css %}
| {{ super() }}
style.
.deleted-projects-toggle {
z-index: 10;
position: absolute;
right: 0;
font-size: 20px;
padding: 3px;
text-shadow: 0 0 2px white;
}
.deleted-projects-toggle .show-deleted {
color: #aaa;
}
.deleted-projects-toggle .hide-deleted {
color: #bbb;
}
| {% endblock %}
| {% block navigation_tabs %}
| {{ navigation_tabs(title) }}
| {% endblock navigation_tabs %}
| {% block body %}
.dashboard-container
section.dashboard-main
section#projects.bg-white
+nav-secondary()(id='sub-nav-tabs__list')
+nav-secondary-link(data-tab-toggle='own_projects', class="active")
| Own Projects
| {% if projects_user|length != 0 %}
span ({{ projects_user|length }})
| {% endif %}
+nav-secondary-link(data-tab-toggle='shared')
| Shared with me
| {% if projects_shared|length != 0 %}
span ({{ projects_shared|length }})
| {% endif %}
| {% if current_user.has_cap('subscriber') %}
+nav-secondary-link(
id="project-create",
data-url="{{ url_for('projects.create') }}",
href="{{ url_for('projects.create') }}")
span.text-success
| #[i.pi-plus] Create New Project
| {% elif current_user.has_cap('can-renew-subscription') %}
+nav-secondary-link(
id="project-create",
data-url="{{ url_for('projects.create') }}",
href="/renew",
target="_blank")
| #[i.pi-heart-filled.text-danger] Resubscribe to Create a Project
| {% endif %}
nav.nav-tabs__tab.active#own_projects
.deleted-projects-toggle
| {% if show_deleted_projects %}
a.hide-deleted(href="{{ request.base_url }}", title='Hide deleted projects')
i.pi-trash
| {% else %}
a.show-deleted(href="{{ request.base_url }}?deleted=1", title='Show deleted projects')
i.pi-trash
| {% endif %}
ul.projects__list
| {% for project in projects_deleted %}
li.projects__list-item.deleted
span.projects__list-thumbnail
| {% if project.picture_square %}
img(src="{{ project.picture_square.thumbnail('s', api=api) }}")
| {% else %}
i.pi-blender-cloud
| {% endif %}
.projects__list-details
span.title {{ project.name }}
ul.meta
li.status.deleted Deleted
li.edit
a(href="javascript:undelete_project('{{ project._id }}')") Restore project
| {% else %}
| {% if show_deleted_projects %}
li.projects__list-item.deleted You have no recenly deleted projects. Deleted projects can be restored within a month after deletion.
| {% endif %}
| {% endfor %}
| {% 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.status(
class="{{ project.is_private | yesno('private,public,') }}",
title="{{ project.is_private | yesno('Private Project,Public Project,') }}")
| {{ project.is_private | yesno('Private,Public,') }}
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.has_cap('view-pending-nodes') %}
li.pending Not Published
| {% endif %}
| {% else %}
| {% if current_user.has_cap('subscriber') %}
li.projects__list-item(data-url="{{ url_for('projects.create') }}")
a.projects__list-thumbnail
i.pi-plus
.projects__list-details
a.title(href="{{ url_for('projects.create') }}")
| Create a project to get started!
| {% elif current_user.has_cap('can-renew-subscription') %}
li.projects__list-item(data-url="https://store.blender.org/renew-my-subscription.php")
a.projects__list-thumbnail
i.pi-plus
.projects__list-details
a.title(href="https://store.blender.org/renew-my-subscription.php")
| Renew your Blender Cloud subscription to create your own projects!
| {% else %}
li.projects__list-item(data-url="/join")
a.projects__list-thumbnail
i.pi-plus
.projects__list-details
a.title(href="/join")
| Join Blender Cloud to create your own projects!
| {% endif %}
| {% endfor %}
section.nav-tabs__tab#shared(style='display: none')
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.status(
class="{{ project.is_private | yesno('private,public,') }}",
title="{{ project.is_private | yesno('Private Project,Public Project,') }}")
| {{ project.is_private | yesno('Private,Public,') }}
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.has_cap('view-pending-nodes') %}
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-broken
.projects__list-details
.title
| No projects shared with you... yet!
| {% endif %}
| {% 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('a.nav-link');
$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();
});
// 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
});
var patch_url = '{{ url_for('projects.patch.patch_project', project_id='PROJECTID') }}';
function undelete_project(project_id) {
console.log('undeleting project', project_id);
$.ajax({
url: patch_url.replace('PROJECTID', project_id),
method: 'PATCH',
data: JSON.stringify({'op': 'undelete'}),
contentType: 'application/json'
})
.done(function(data, textStatus, jqXHR) {
location.href = jqXHR.getResponseHeader('Location');
})
.fail(function(err) {
toastr.error(xhrErrorResponseMessage(err), 'Undeletion failed');
})
}
| {% endblock %}

View File

@@ -51,7 +51,7 @@ meta(name="twitter:description", content="Blender Cloud, your source for open co
| {% endif %} | {% endif %}
meta(property="og:url", content="{{url_for('projects.view_node', project_url=project.url, node_id=node._id)}}") meta(property="og:url", content="{{url_for('projects.view_node', project_url=project.url, node_id=node._id, _external=True)}}")
| {% else %} | {% else %}
meta(property="og:title", content="{{ project.name }} Blog on Blender Cloud") meta(property="og:title", content="{{ project.name }} Blog on Blender Cloud")
meta(name="twitter:title", content="{{ project.name }} Blog on Blender Cloud") meta(name="twitter:title", content="{{ project.name }} Blog on Blender Cloud")
@@ -75,45 +75,47 @@ meta(property="og:url", content="{{url_for('projects.view', project_url=project.
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-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-ga-0.4.2.min.js') }}")
script(src="{{ url_for('static_pillar', filename='assets/js/vendor/videojs-hotkeys-0.2.20.min.js') }}") script(src="{{ url_for('static_pillar', filename='assets/js/vendor/videojs-hotkeys-0.2.20.min.js') }}")
script(src="{{ url_for('static_cloud', filename='assets/js/photoswipe.min.js') }}")
| {% endblock %} | {% endblock %}
| {% block css %} | {% block css %}
| {{ super() }}
link(href="{{ url_for('static_cloud', filename='assets/css/project-landing.css') }}", rel="stylesheet") link(href="{{ url_for('static_cloud', filename='assets/css/project-landing.css') }}", rel="stylesheet")
| {% endblock %} | {% endblock %}
| {% block body %} | {% block body %}
header header
.jumbotron.jumbotron-fluid( //a(href="{{ url_for( 'projects.view', project_url=project.url) }}")
style="background-image: url('{{ project.picture_header.thumbnail('h', api=api) }}'); background-position: 50% 50%;") img.header(src="{{ project.picture_header.thumbnail('h', api=api) }}")
| {# Secondary Navigation #}
| {% block navbar_secondary %} | {% block navbar_secondary %}
| {{ projectmacros.render_secondary_navigation(project, pages=pages) }} | {{ projectmacros.render_secondary_navigation(project, pages=pages) }}
| {% endblock navbar_secondary %}
.container.landing | {% endblock navbar_secondary %}
#container.landing
section.node-details-container.project section.node-details-container.project
.node-details-title.container .node-details-title
h1 {{ project.name }} h1 {{ project.name }}
| {% if project.description %} | {% if project.description %}
.node-details-description
| {{ project | markdowned('description') }} | {{ project | markdowned('description') }}
| {% endif %} | {% endif %}
section.gallery section.gallery
h2.text-center Gallery h2 Gallery
.container
| {% for n in activity_stream %} | {% for n in activity_stream %}
| {% if n.node_type not in ['comment', 'post'] and n.picture %} | {% if n.node_type not in ['comment', 'post'] and n.picture %}
.thumbnail.expand-image-links .thumbnail.expand-image-links
.thumbnail-container .img-container
a(href="{{ n.picture.thumbnail('l', api=api) }}", data-node_id="{{ n._id }}") 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(src="{{ n.picture.thumbnail('l', api=api) }}", alt="{{ n.name }}")
.img-caption.table
| {# Not using for the moment
span.table-cell {{ n.name }}
| #}
| {% endif %} | {% endif %}
| {% endfor %} | {% endfor %}
.clearfix div(class="clearfix")
| {% if project.nodes_featured %} | {% if project.nodes_featured %}
| {# In some cases featured_nodes might might be embedded #} | {# In some cases featured_nodes might might be embedded #}
| {% if '_id' in project.nodes_featured[0] %} | {% if '_id' in project.nodes_featured[0] %}
@@ -121,39 +123,42 @@ header
| {% else %} | {% else %}
| {% set featured_node_id=project.nodes_featured[0] %} | {% set featured_node_id=project.nodes_featured[0] %}
| {% endif %} | {% endif %}
p.cta-arrow.text-center a.btn(href="{{ url_for('projects.view_node', project_url=project.url, node_id=featured_node_id) }}") See more
a(href="{{ url_for('projects.view_node', project_url=project.url, node_id=featured_node_id) }}")
| See more
i.pi-angle-right
| {% endif %} | {% endif %}
section.node-extra section.node-extra
h2.text-center Latest Updates h2 Latest Updates
| {% if activity_stream %} | {% if activity_stream %}
.container.card-container .node-updates
.row ul.node-updates-list
| {% for n in activity_stream %} | {% for n in activity_stream %}
| {% if n.node_type == 'post' %} | {% if n.node_type == 'post' %}
.col-md-4 li.node-updates-list-item(
.card data-node_id="{{ n._id }}",
a.card-image(href="{{ url_for_node(node=n) }}") class="{{ n.node_type }} {{ n.properties.content_type | hide_none }}")
a.image(href="{{ url_for_node(node=n) }}")
| {% if n.picture %} | {% if n.picture %}
img.card-img-top(src="{{ n.picture.thumbnail('l', api=api) }}") img(src="{{ n.picture.thumbnail('l', api=api) }}")
| {% endif %} | {% endif %}
.card-body
h4.card-title .info
a(href="{{ url_for_node(node=n) }}") {{ n.name }} a.title(href="{{ url_for_node(node=n) }}") {{ n.name }}
p.card-text {{ n.properties | markdowned('content') | striptags | truncate(140, end="... <small>read more</small>") | safe | hide_none }} p.description(href="{{ url_for_node(node=n) }}")
| {% if n.node_type == 'post' %}
| {{ n.properties | markdowned('content') | striptags | truncate(140, end="... <small>read more</small>") | safe | hide_none }}
| {% else %}
| {{ n | markdowned('description') | striptags | truncate(140, end="... <small>read more</small>") | 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 %} | {% endif %}
| {% endfor %} | {% endfor %}
| {% endif %} | {% endif %}
.clearfix a.btn(href="{{ url_for('main.project_blog', project_url=project.url) }}") See all updates
p.cta-arrow.text-center
a(href="{{ url_for('main.project_blog', project_url=project.url) }}")
| See all updates
i.pi-angle-right
| {% endblock body %} | {% endblock body %}

View File

@@ -0,0 +1,688 @@
| {% extends 'layout.html' %}
| {% from '_macros/_add_new_menu.html' import add_new_menu %}
include ../mixins/components
| {% block page_title %}{{ project.name }}{% endblock%}
| {% set title = 'project' %}
| {% 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 %}
| {% block head %}
link(href="{{ url_for('static_pillar', filename='assets/jstree/themes/default/style.min.css') }}", rel="stylesheet")
| {% if node %}
link(rel="amphtml", href="{{ url_for('nodes.view', node_id=node._id, _external=True, format='amp') }}")
| {% endif %}
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') }}")
script(src="{{ url_for('static_pillar', filename='assets/js/video_plugins.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/project-main.css') }}", rel="stylesheet")
| {% endblock %}
| {% block navigation_tabs %}
+nav-secondary()(class="bg-white")
| {% if project.category == 'course' %}
li.text-capitalize
a.nav-link.text-muted.px-0(href="{{ url_for('cloud.courses') }}")
| Courses
| {% elif project.category == 'workshop' %}
li.text-capitalize
a.nav-link.text-muted.px-0(href="{{ url_for('cloud.workshops') }}")
| Workshops
li.px-1
i.pi-angle-right
| {% endif %}
+nav-secondary-link(
class="px-0",
href="{{url_for('projects.view', project_url=project.url, _external=True)}}")
| {{ project.name }}
| {% if project.category == "open_project" %}
+nav-secondary-link(
class="active",
href="{{url_for('projects.view', project_url=project.url, _external=True)}}")
| Explore
+nav-secondary-link(
href="{{url_for('projects.view', project_url=project.url, _external=True)}}")
| Blog
+nav-secondary-link(
href="{{url_for('projects.view', project_url=project.url, _external=True)}}")
| About
+nav-secondary-link(
href="{{url_for('projects.view', project_url=project.url, _external=True)}}")
| Team
+nav-secondary-link(
href="{{url_for('projects.view', project_url=project.url, _external=True)}}")
| Awards
| {% endif %}
| {% endblock navigation_tabs %}
| {% block body %}
#project-container
#project-side-container
#project_sidebar.bg-white
ul.project-tabs.p-0
//- li.tabs-thumbnail(class="{% if project.picture_square %}image{% endif %}")
//- a(href="{{url_for('projects.view', project_url=project.url)}}")
//- #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="right",
class="active")
a(href="{{url_for('projects.view', project_url=project.url, _external=True)}}")
i.pi-folder
| {% if not project.is_private %}
| {% if current_user_is_subscriber %}
li.tabs-search(
title="Search",
data-toggle="tooltip",
data-placement="right")
a(href="{{ url_for('projects.search', project_url=project.url, _external=True)}} ")
i.pi-search
| {% else %}
li.tabs-search(
title="Search (subscribers only)",
data-toggle="tooltip",
data-placement="right")
a(href="{{ url_for('cloud.join') }}")
i.pi-search
| {% endif %}
| {% endif %}
| {{ extension_sidebar_links }}
| {% if project.has_method('PUT') %}
li(
title="Edit Project",
data-toggle="tooltip",
data-placement="right")
a(href="{{ url_for('projects.edit', project_url=project.url) }}")
i.pi-cog
| {% endif %}
#project_nav(class="{{ title }}")
#project_nav-container
| {% if title != 'about' %}
//- +nav-secondary(class="bg-white")
//- +nav-secondary-link(
//- class="active",
//- href="{{url_for('projects.view', project_url=project.url, _external=True)}}")
//- | {{ project.name }}
//- #project_nav-header.bg-white
//- a.project-title.p-2.font-weight-bold.text-dark(
//- href="{{url_for('projects.view', project_url=project.url, _external=True)}}")
//- | {{ project.name }}
| {% block project_tree %}
#project_tree.bg-white
| {% endblock project_tree %}
| {% endif %}
#project_context-container.border-left
| {% if project.has_method('PUT') %}
#project_context-header.bg-white
span#status-bar
ul.project-edit-tools.disabled
li.dropdown
button#item_add.project-mode-view.btn.btn-sm.btn-outline-secondary.dropdown-toggle(
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.btn.btn-sm.btn-outline-secondary.ml-2(
href="javascript:void(0);",
title="Edit",
data-project_id="{{project._id}}")
i.button-edit-icon.pi-edit
| Edit Project
li.dropdown
button.dropdown-toggle.project-mode-view.btn.btn-sm.btn-outline-secondary.mx-2(
type="button",
data-toggle="dropdown",
aria-haspopup="true",
aria-expanded="false")
i.pi-more-vertical.p-0
ul.dropdown-menu
| {% if current_user.has_cap('admin') %}
li.dropdown-item
a#item_featured(
href="javascript:void(0);",
title="Feature on project's homepage",
data-toggle="tooltip",
data-placement="left")
i.pi-star
| Toggle Featured
li.dropdown-item
a#item_toggle_public(
href="javascript:void(0);",
title="Make it accessible to anyone",
data-toggle="tooltip",
data-placement="left")
i.pi-lock-open
| Toggle Public
| {% endif %}
li.dropdown-item
a#item_toggle_projheader(
href="javascript:void(0);",
title="Feature as project's header",
data-toggle="tooltip",
data-placement="left")
i.pi-star
| Toggle Project Header video
li.dropdown-item.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.dropdown-item.button-delete
a#item_delete(
href="javascript:void(0);",
title="Can be undone within a month",
data-toggle="tooltip",
data-placement="left")
i.pi-trash
| Delete Project
// Edit Mode
li.button-cancel
a#item_cancel.project-mode-edit.btn.btn-outline-secondary(
href="javascript:void(0);",
title="Cancel changes")
i.button-cancel-icon.pi-cancel
| Cancel
li.button-save
a#item_save.project-mode-edit.btn.btn-outline-success.mx-2(
href="javascript:void(0);",
title="Save changes")
i.button-save-icon.pi-check
| Save Changes
| {% endif %}
| {% set utm_source = request.args.get('utm_source') %}
| {% if config.UTM_LINKS and utm_source in config.UTM_LINKS %}
#utm_container
a(href="{{config.UTM_LINKS[utm_source]['link']}}")
img(src="{{config.UTM_LINKS[utm_source]['image']}}", alt="gift", class="img-responsive")
| {% endif %}
#project_context
| {% block project_context %}
| {% if show_project %}
| {% include "projects/view_embed.html" %}
| {% endif %}
| {% endblock project_context %}
#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_container %}{% endblock %}
| {% block footer_scripts_pre %}
| {% 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') }}")
| {% endif %}
script.
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').displayAs('inline-block');
$('.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').displayAs('inline-block');
} 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();
// Set the page title on the document
var page_title = $('#node-title').text() + " - {{ project.name }} — Blender Cloud";
DocumentTitleAPI.set_page_title(page_title);
// 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');
}
| {% endblock %}
| {% block footer_scripts %}
script(src="{{ url_for('static_pillar', filename='assets/jstree/jstree.min.js') }}")
script.
{% if show_project %}
ProjectUtils.setProjectAttributes({projectId: "{{project._id}}", isProject: true, nodeId: ''});
{% else %}
{% if node %}
ProjectUtils.setProjectAttributes({projectId: "{{project._id}}", isProject: false, nodeId: '{{node._id}}'});
{% endif %}
{% endif %}
var projectTree = document.getElementById('project_tree');
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 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').displayAs('inline-block');
$('.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-document", "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-play", "max_children": 0},
"blog" : {"icon": "pi-newspaper", "max_children": 0},
"page" : {"icon": "pi-document-text", "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.custom_view) {
window.location = data.node.a_attr.href;
} 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);
}
});
};
{% if is_embedded_edit is not defined or is_embedded_edit %}
// Initialize the page if we are not directly editing a node (most of the time)
loadContent();
{% endif %}
var project_container = document.getElementById('project-container');
/* UI Stuff */
$(window).on("load resize",function(){
containerResizeY($(window).height());
if ($(window).width() > 480) {
project_container.style.height = (window.innerHeight - project_container.offsetTop) + "px";
}
});
{% if current_user_is_subscriber %}
$(projectTree).addClass('is_subscriber');
{% endif %}
| {% endblock %}
| {% block comment_scripts %} {% endblock%}

View File

@@ -1,28 +1,30 @@
| {% extends 'layout.html' %} | {% extends 'layout.html' %}
include mixins/components
| {# Default case is Open Projects #} | {# Default case is Open Projects #}
| {% set page_title = 'Open Projects' %} | {% set page_title = 'Open Projects' %}
| {% set page_description = 'Full production data and tutorials from all open movies, for you to use freely' %} | {% set page_description = 'Full production data and tutorials from all open movies, for you to use freely' %}
| {% set page_header_image = url_for('static', filename='assets/img/backgrounds/banner-open-projects.jpg') %} | {% set page_header_image = url_for('static', filename='assets/img/backgrounds/background_agent327_01.jpg') %}
| {% set page_header_text = 'See how each film came to be. Explore our production files, assets, artwork and more. Get full access to behind the scenes at the Blender Animation Studio. Follow along as we share our process and techniques for each movie.' %} | {% set page_header_text = 'The iconic Blender Institute Open Movies. Featuring all the production files, assets, artwork, and never-seen-before content.' %}
| {% if title == 'courses' or title == 'workshops' %} | {% if title == 'courses' %}
| {% set page_title = 'Training' %} | {% set page_title = 'Courses' %}
| {% set page_description = 'Production quality training by 3D professionals' %} | {% set page_description = 'Production quality training by 3D professionals' %}
| {% set page_header_image = url_for('static', filename='assets/img/backgrounds/banner-training.jpg') %} | {% set page_header_image = url_for('static', filename='assets/img/backgrounds/background_agent327_04.jpg') %}
| {% set page_header_text = 'Browse through our structured courses. Choose a workshop where top Blender Artists walk you through professional techniques to build a specific project. Visit the Art Gallery where you can download and study source files from your favorite artists.' %} | {% set page_header_text = 'Character modeling, 3D printing, VFX, rigging and more.' %}
//- | {% elif title == 'workshops' %} | {% elif title == 'workshops' %}
//- | {% set page_title = 'Workshops' %} | {% set page_title = 'Workshops' %}
//- | {% set page_description = 'Production quality training by 3D professionals' %} | {% set page_description = 'Production quality training by 3D professionals' %}
//- | {% set page_header_image = url_for('static', filename='assets/img/backgrounds/background_caminandes_3_03.jpg') %} | {% set page_header_image = url_for('static', filename='assets/img/backgrounds/background_agent327_04.jpg') %}
//- | {% set page_header_text = 'Enter the artist workshop and learn by example.' %} | {% set page_header_text = 'Enter the artist workshop and learn by example.' %}
| {% endif %} | {% endif %}
| {% block og %} | {% block og %}
meta(property="og:type", content="website") meta(property="og:type", content="website")
meta(property="og:url", content="https://cloud.blender.org") meta(property="og:url", content="{{ request.url }}")
meta(property="og:title", content="{{ page_title }} on Blender Cloud") meta(property="og:title", content="{{ page_title }} on Blender Cloud")
meta(name="twitter:title", content="{{ page_title }} on Blender Cloud") meta(name="twitter:title", content="{{ page_title }} on Blender Cloud")
@@ -33,53 +35,57 @@ meta(name="twitter:description", content="{{ page_description }}")
meta(property="og:image", content="{{ page_header_image }}") meta(property="og:image", content="{{ page_header_image }}")
meta(name="twitter:image", content="{{ page_header_image }}") meta(name="twitter:image", content="{{ page_header_image }}")
| {% endblock %} | {% endblock %}
| {% block css %}
| {{ super() }}
link(href="{{ url_for('static_cloud', filename='assets/css/projects-index-collection.css') }}", rel="stylesheet")
| {% endblock css %}
| {% block page_title %} | {% block page_title %}
| {{ page_title }} | {{ page_title }}
| {% endblock %} | {% endblock %}
| {% block navigation_tabs %}
| {% if title in ['courses', 'workshops'] %}
+nav-secondary
+nav-secondary-link(
class="{% if title == 'workshops' %}active{% endif %}",
href="{{ url_for('cloud.workshops') }}")
| Workshops
+nav-secondary-link(
class="{% if title == 'courses' %}active{% endif %}",
href="{{ url_for('cloud.courses') }}")
| Courses
+nav-secondary-link(
class="{% if title == 'gallery' %}active{% endif %}",
href="{{ url_for('projects.view', project_url='gallery') }}")
| Art Gallery
| {% endif %}
| {% endblock navigation_tabs %}
| {% block body %} | {% block body %}
//- Jumbotron .container.pb-5
.jumbotron.jumbotron-fluid(style="background-image: url('{{ page_header_image }}')") .pt-4
.container h2.text-uppercase.font-weight-bold
h1.display-4.node_index-collection-name {{ page_title }} | {{ page_title }}
p.lead.node_index-collection-description {{ page_header_text }} .lead
//- Secondary Navigation | {{ page_header_text }}
| {% if title == 'courses' or title == 'workshops' %}
.container.navbar-secondary
ul.nav.justify-content-left
li.nav-item
a.nav-link.nav-title(href="#") Training
li.nav-item
a.nav-link(href="#", class="{% if title == 'courses' %}active{% endif %}") Courses
li.nav-item
a.nav-link(href="#", class="{% if title == 'workshops' %}active{% endif %}") Workshops
li.nav-item
a.nav-link(href="#") Art Gallery
| {% endif %}
//- Project Cards
.container.card-container
.row
| {% for project in projects %}
| {% if (project.status == 'published') or (project.status == 'pending' and current_user.is_authenticated) and project._id != config.MAIN_PROJECT_ID %}
.col-md-4( hr.pb-2
data-url="{{ url_for('projects.view', project_url=project.url) }}",
tabindex="{{ loop.index }}") +card-deck(3)
.card | {% for project in projects %}
| {% if (project.status == 'published') or (project.status == 'pending' and current_user.is_authenticated) and project._id != config.MAIN_PROJECT_ID %}
+card(data-url="{{ url_for('projects.view', project_url=project.url) }}", tabindex='{{ loop.index }}')
| {% if project.picture_header %} | {% if project.picture_header %}
a.card-image(href="{{ url_for('projects.view', project_url=project.url) }}") a(href="{{ url_for('projects.view', project_url=project.url) }}")
img.card-img-top(src="{{ project.picture_header.thumbnail('l', api=api) }}") img.card-img-top(
src="{{ project.picture_header.thumbnail('l', api=api) }}", alt="{{ project.name }}")
| {% endif %} | {% endif %}
.card-body .card-body
h4.card-title h5.card-title
a(href="{{ url_for('projects.view', project_url=project.url) }}")
| {{ project.name }} | {{ project.name }}
| {% if project.status == 'pending' and current_user.is_authenticated and current_user.has_role('admin') %} | {% if project.status == 'pending' and current_user.is_authenticated and current_user.has_role('admin') %}
small (pending) small (pending)
@@ -89,18 +95,16 @@ link(href="{{ url_for('static_cloud', filename='assets/css/projects-index-collec
p.card-text p.card-text
| {{project.summary|safe}} | {{project.summary|safe}}
| {% endif %} | {% endif %}
| {% endif %} | {% endif %}
| {% endfor %} | {% endfor %}
| {% endblock %} | {% endblock %}
| {% block footer_scripts %} | {% block footer_scripts %}
//- script. script.
//- $('.node_index-collection-card.project').on('click', function(e){ $('.js-project-go').on('click', function(e){
//- e.preventDefault(); e.preventDefault();
//- window.location.href = $(this).data('url'); window.location.href = $(this).data('url');
//- }); });
| {% endblock %} | {% endblock %}

View File

@@ -1,10 +1,11 @@
| {% extends 'layout.html' %} | {% extends 'layout.html' %}
| {% block page_title %}Services{% endblock %} | {% block page_title %}Services{% endblock %}
| {% set title = 'services' %} | {% set title = 'services' %}
include mixins/components
| {% block og %} | {% block og %}
meta(property="og:type", content="website") meta(property="og:type", content="website")
meta(property="og:url", content="{{ url_for('cloud.services') }}") meta(property="og:url", content="{{ request.url }}")
meta(property="og:title", content="Services - Blender Cloud") meta(property="og:title", content="Services - Blender Cloud")
meta(name="twitter:title", content="Services - Blender Cloud") meta(name="twitter:title", content="Services - Blender Cloud")
@@ -20,26 +21,10 @@ meta(name="twitter:image", content="{{ url_for('static', filename='assets/img/ba
| {% endblock %} | {% endblock %}
| {% block body %} | {% block body %}
#page-container - var header_text = "On Blender Cloud you can create and share personal projects, access our texture and HDRI library (or create your own), keep track of your production, manage your renders and much more!";
#page-header(style="background-image: url({{ url_for('static', filename='assets/img/backgrounds/services_projects.jpg')}})") +jumbotron("Services", header_text, "{{ url_for('static', filename='assets/img/backgrounds/services_projects.jpg')}}")
.container
.page-title
| Blender Cloud Services
.page-title-summary
span.text-background
p.
Blender Cloud is the creative hub for your projects, powered by Free and Open Source software.
p.
On Blender Cloud you can create and share personal projects, access our texture and HDRI
library (or create your own), keep track of your production, manage your renders and much more!
.navbar-backdrop-overlay
- var addon_text = 'Available through the <a href="{{ url_for(\'cloud.services\') }}#blender-cloud-add-on">Blender Cloud add-on</a>'
#page-content
- var addon_text = 'Available through the <a href="{{ url_for(\'cloud.services\') }}#blender-cloud-add-on">Blender Cloud add-on</a>';
section#blender-cloud-add-on.page-card section#blender-cloud-add-on.page-card
.page-card-side .page-card-side
h2.page-card-title h2.page-card-title
@@ -54,8 +39,8 @@ meta(name="twitter:image", content="{{ url_for('static', filename='assets/img/ba
small Blender Cloud add-on requires Blender 2.78 or newer small Blender Cloud add-on requires Blender 2.78 or newer
a.page-card-cta.download( a.btn.btn-primary(
href="https://cloud.blender.org/r/downloads/blender_cloud-latest-addon.zip") href="/r/downloads/blender_cloud-latest-addon.zip")
i.pi-download i.pi-download
| Download add-on &nbsp;<small>v</small> {{ config.BLENDER_CLOUD_ADDON_VERSION }} | Download add-on &nbsp;<small>v</small> {{ config.BLENDER_CLOUD_ADDON_VERSION }}
@@ -76,10 +61,15 @@ meta(name="twitter:image", content="{{ url_for('static', filename='assets/img/ba
.tip !{addon_text} .tip !{addon_text}
a.btn.btn-outline-primary(
href="/r/downloads/blender_cloud-latest-addon.zip")
i.pi-download
| Download add-on &nbsp;<small>v</small> {{ config.BLENDER_CLOUD_ADDON_VERSION }}
a.page-card-cta( a.btn.btn-link(
href="https://cloud.blender.org/blog/introducing-blender-sync") href="/blog/introducing-blender-sync")
| Learn More | Learn More
i.pi-angle-right
.page-card-side .page-card-side
img( img(
@@ -91,13 +81,13 @@ meta(name="twitter:image", content="{{ url_for('static', filename='assets/img/ba
h2.page-card-title Texture & HDRI Browser h2.page-card-title Texture & HDRI Browser
.page-card-summary .page-card-summary
p. p.
Access the <a href="https://cloud.blender.org/p/textures/">Blender Cloud Textures</a> Access the <a href="/p/textures/">Blender Cloud Textures</a>
library from within Blender using our exclusive add-on. library from within Blender using our exclusive add-on.
Create, manage and share <em>your own</em> texture libraries! Create, manage and share <em>your own</em> texture libraries!
.tip !{addon_text} .tip !{addon_text}
a.page-card-cta.js-watch-video.download( a.btn.btn-outline-primary.js-watch-video(
href="https://www.youtube.com/watch?v=-srXYv2Osjw", href="https://www.youtube.com/watch?v=-srXYv2Osjw",
data-youtube-id="-srXYv2Osjw") data-youtube-id="-srXYv2Osjw")
i.pi-play i.pi-play
@@ -117,15 +107,16 @@ meta(name="twitter:image", content="{{ url_for('static', filename='assets/img/ba
.tip !{addon_text} .tip !{addon_text}
a.page-card-cta.download.js-watch-video( a.btn.btn-outline-primary.js-watch-video(
href="https://www.youtube.com/watch?v=yvtqeMBOAyk", href="https://www.youtube.com/watch?v=yvtqeMBOAyk",
data-youtube-id="yvtqeMBOAyk") data-youtube-id="yvtqeMBOAyk")
i.pi-play i.pi-play
| Watch Video | Watch Video
a.page-card-cta.outline( a.btn.btn-link(
href="https://cloud.blender.org/blog/introducing-image-sharing") href="/blog/introducing-image-sharing")
| Learn More | Learn More
i.pi-angle-right
.page-card-side .page-card-side
img( img(
@@ -139,9 +130,10 @@ meta(name="twitter:image", content="{{ url_for('static', filename='assets/img/ba
Create and manage your own personal projects. Create and manage your own personal projects.
Upload assets and collaborate with other Blender Cloud members. Upload assets and collaborate with other Blender Cloud members.
a.page-card-cta( a.btn.btn-link(
href="https://cloud.blender.org/blog/introducing-private-projects") href="/blog/introducing-private-projects")
| Learn More | Learn More
i.pi-angle-right
.page-card-side .page-card-side
img( img(
@@ -155,16 +147,17 @@ meta(name="twitter:image", content="{{ url_for('static', filename='assets/img/ba
.page-card-summary. .page-card-summary.
Production-management software for your film, game, or commercial projects. Production-management software for your film, game, or commercial projects.
a.page-card-cta.download.js-watch-video( a.btn.btn-outline-primary.js-watch-video(
href="https://www.youtube.com/watch?v=b9x1rlyyt_o", href="https://www.youtube.com/watch?v=b9x1rlyyt_o",
data-youtube-id="b9x1rlyyt_o") data-youtube-id="b9x1rlyyt_o")
i.pi-play i.pi-play
| Watch Video | Watch Video
a.page-card-cta( a.btn.btn-link(
href="https://cloud.blender.org/blog/attract-and-flamenco-public-beta", href="/blog/attract-and-flamenco-public-beta",
title="Learn more about Attract") title="Learn more about Attract")
| Learn More | Learn More
i.pi-angle-right
.page-card-side .page-card-side
img( img(
@@ -178,16 +171,17 @@ meta(name="twitter:image", content="{{ url_for('static', filename='assets/img/ba
.page-card-summary. .page-card-summary.
Take control of your computing infrastructure and get things done. Take control of your computing infrastructure and get things done.
a.page-card-cta.download.js-watch-video( a.btn.btn-outline-primary.js-watch-video(
href="https://www.youtube.com/watch?v=7cnFKhsM67Q", href="https://www.youtube.com/watch?v=7cnFKhsM67Q",
data-youtube-id="7cnFKhsM67Q") data-youtube-id="7cnFKhsM67Q")
i.pi-play i.pi-play
| Watch Video | Watch Video
a.page-card-cta( a.btn.btn-link(
href="https://flamenco.io", href="https://flamenco.io",
title="Learn more about Flamenco") title="Learn more about Flamenco")
| Learn More | Learn More
i.pi-angle-right
.page-card-side .page-card-side
img( img(
@@ -195,15 +189,18 @@ meta(name="twitter:image", content="{{ url_for('static', filename='assets/img/ba
| {% if not current_user.has_role('subscriber') %} | {% if not current_user.has_role('subscriber') %}
section.page-card.subscribe( section.page-card(
style="background-image: url({{ url_for('static', filename='assets/img/backgrounds/pattern_01.jpg')}})") style="background-image: url({{ url_for('static', filename='assets/img/backgrounds/pattern_01.jpg')}})")
.page-card-side .page-card-side
h2.page-card-title h2.page-card-title
| All of this, plus hours of training and production assets. | All of this, plus hours of training and production assets.
.page-card-summary
.page-card-summary.text-white
| Join us for only $9.90/month! | Join us for only $9.90/month!
a.page-card-cta(
href="https://store.blender.org/product/membership/") a.btn.btn-outline-light.px-3(href="https://store.blender.org/product/membership/")
i.pi-heart.mr-2
| Subscribe Now | Subscribe Now
| {% endif %} | {% endif %}
@@ -212,12 +209,13 @@ meta(name="twitter:image", content="{{ url_for('static', filename='assets/img/ba
| {% block footer_scripts %} | {% block footer_scripts %}
script. script.
// Click anywhere in the page to hide the overlay // Hide the video overlay.
function hideOverlay() { function hideOverlay() {
$('#page-overlay.video').removeClass('active'); $('#page-overlay.video').removeClass('active');
$('#page-overlay.video .video-embed').html(''); $('#page-overlay.video .video-embed').html('');
} }
// Click anywhere in the page or hit Esc to hide the overlay.
$(document).click(function() { $(document).click(function() {
hideOverlay(); hideOverlay();
}); });
@@ -229,12 +227,12 @@ script.
}); });
$('a.js-watch-video').click(function(e){ $('a.js-watch-video').click(function(e){
var videoId = $(this).attr('data-youtube-id');
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
$('#page-overlay.video').addClass('active'); $('#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&amp;showinfo=0;autoplay=1" frameborder="0" allowfullscreen></iframe>') $('#page-overlay .video-embed').html('<iframe src="https://www.youtube.com/embed/' + videoId +'?rel=0&amp;showinfo=0;autoplay=1" frameborder="0" allowfullscreen></iframe>')
}); });

View File

@@ -5,7 +5,7 @@
| {% block og %} | {% block og %}
meta(property="og:title", content="Blender Cloud Statistics") meta(property="og:title", content="Blender Cloud Statistics")
meta(property="og:url", content="https://cloud.blender.org/stats") meta(property="og:url", content="{{ request.url }}")
meta(property="og:image", content="{{ url_for('static', filename='assets/img/backgrounds/background_andy_hdribot_01.jpg')}}") meta(property="og:image", content="{{ url_for('static', filename='assets/img/backgrounds/background_andy_hdribot_01.jpg')}}")
| {% endblock %} | {% endblock %}

View File

@@ -65,7 +65,7 @@ p Your organisation provides you with your subscription.
hr hr
p p
button#recheck_subscription.btn.btn-default(onclick="javascript:recheck_subscription(this)") Re-check my subscription button#recheck_subscription.btn.btn-outline-secondary(onclick="javascript:recheck_subscription(this)") Re-check my subscription
hr hr

View File

@@ -11,7 +11,7 @@
| {% endfor %} | {% endfor %}
.buttons .buttons
button.btn.btn-default.button-submit(type='submit') button.btn.btn-outline-success.button-submit(type='submit')
i.pi-check i.pi-check
| Save Changes | Save Changes
| {% endblock %} | {% endblock %}

View File

@@ -8,13 +8,9 @@
| {% block og %} | {% block og %}
meta(property="og:title", content="Blender Cloud - Open Content Production Platform") meta(property="og:title", content="Blender Cloud - Open Content Production Platform")
meta(property="og:url", content="https://cloud.blender.org/") meta(property="og:url", content="{{ request.url }}")
meta(property="og:image", content="{{ url_for('static', filename='assets/img/backgrounds/background_dweebs_01.jpg')}}") meta(property="og:image", content="{{ url_for('static', filename='assets/img/backgrounds/background_dweebs_01.jpg')}}")
| {% endblock og %} | {% endblock og %}
| {% block css %}
| {{ super() }}
link(href="{{ url_for('static_cloud', filename='assets/css/welcome.css') }}", rel="stylesheet")
| {% endblock css %}
| {% block page_overlay %} | {% block page_overlay %}
#page-overlay.video #page-overlay.video
@@ -23,19 +19,21 @@ link(href="{{ url_for('static_cloud', filename='assets/css/welcome.css') }}", re
| {% block navigation_search %}{% endblock %} | {% block navigation_search %}{% endblock %}
| {% block navigation_sections %} | {% block navigation_sections %}
li.nav-item li
a.nav-link(href="{{ url_for('main.main_blog') }}") Blog a.navbar-item(href="{{ url_for('main.main_blog') }}")
li.nav-item span Blog
a.nav-link(href="#pricing") Pricing li
a.navbar-item(href="#pricing")
span Pricing
| {% endblock navigation_sections %} | {% endblock navigation_sections %}
| {% block navigation_user %} | {% block navigation_user %}
li.nav-item-sign-in li.pt-1.pr-1
| {% if current_user.is_anonymous %} | {% if current_user.is_anonymous %}
a.navbar-item(href="{{ url_for('users.login', next='/') }}") a.btn.btn-outline-success(href="{{ url_for('users.login', next='/') }}")
| Log in and Explore | Log in and Explore
| {% else %} | {% else %}
a.navbar-item(href="{{ url_for('main.homepage') }}") a.btn.btn-outline-success(href="{{ url_for('main.homepage') }}")
| Explore | Explore
| {% endif %} | {% endif %}
| {% endblock navigation_user %} | {% endblock navigation_user %}
@@ -72,7 +70,7 @@ li.nav-item-sign-in
improve it for everyone's benefit. improve it for everyone's benefit.
.page-card-side .page-card-side
a.page-card-image(href="https://cloud.blender.org/p/caminandes-3/56bdacccc379cf00797160b0", target="_blank") a.page-card-image(href="/p/caminandes-3/56bdacccc379cf00797160b0", target="_blank")
video(autoplay, loop) video(autoplay, loop)
source(src="{{ url_for('static', filename='assets/img/features/animation_review_01.mp4')}}") source(src="{{ url_for('static', filename='assets/img/features/animation_review_01.mp4')}}")
@@ -94,7 +92,7 @@ li.nav-item-sign-in
Access high quality content, organized in Access high quality content, organized in
#[a(href="{{ url_for('cloud.courses') }}") classes], #[a(href="{{ url_for('cloud.courses') }}") classes],
#[a(href="{{ url_for('cloud.workshops') }}") workshop] and the #[a(href="{{ url_for('cloud.workshops') }}") workshop] and the
#[a(href="https://cloud.blender.org/p/gallery") art gallery], #[a(href="/p/gallery") art gallery],
a curated artwork selection, where you can open a a curated artwork selection, where you can open a
.blend file and see how it was made. .blend file and see how it was made.
@@ -110,7 +108,7 @@ li.nav-item-sign-in
| See #[a.learn(href="{{ url_for('cloud.courses') }}") Courses] & #[a.learn(href="{{ url_for('cloud.courses') }}") Workshops] | See #[a.learn(href="{{ url_for('cloud.courses') }}") Courses] & #[a.learn(href="{{ url_for('cloud.courses') }}") Workshops]
.page-card-side .page-card-side
a.page-card-image(href="https://cloud.blender.org/p/scripting-for-artists/") a.page-card-image(href="/p/scripting-for-artists/")
img( img(
alt="Sybren teaches Python Scripting with Blender", alt="Sybren teaches Python Scripting with Blender",
src="{{ url_for('static', filename='assets/img/backgrounds/background_sybren_01.jpg')}}") src="{{ url_for('static', filename='assets/img/backgrounds/background_sybren_01.jpg')}}")
@@ -123,7 +121,7 @@ li.nav-item-sign-in
.page-triplet-container.homepage .page-triplet-container.homepage
.row .row
.col-md-4 .col-md-4
.triplet-card(data-url="https://cloud.blender.org/p/minecraft-animation-workshop/") .triplet-card(data-url="/p/minecraft-animation-workshop/")
.triplet-card-thumbnail .triplet-card-thumbnail
img( img(
alt="Textures", alt="Textures",
@@ -132,11 +130,11 @@ li.nav-item-sign-in
h3 Minecraft Animation h3 Minecraft Animation
p. p.
Learn how to make animations with this workshop by Dillon Gu. Learn how to make animations with this workshop by Dillon Gu.
a.triplet-cta(href="https://cloud.blender.org/p/minecraft-animation-workshop/") a.triplet-cta(href="/p/minecraft-animation-workshop/")
| LEARN MORE | LEARN MORE
.col-md-4 .col-md-4
.triplet-card(data-url="https://cloud.blender.org/p/motion-graphics/") .triplet-card(data-url="/p/motion-graphics/")
.triplet-card-thumbnail .triplet-card-thumbnail
img( img(
alt="HDRI", alt="HDRI",
@@ -145,11 +143,11 @@ li.nav-item-sign-in
h3 Motion Graphics h3 Motion Graphics
p. p.
A comprehensive guide to motion graphics techniques using Blender. A comprehensive guide to motion graphics techniques using Blender.
a.triplet-cta(href="https://cloud.blender.org/p/motion-graphics/") a.triplet-cta(href="/p/motion-graphics/")
| LEARN MORE | LEARN MORE
.col-md-4 .col-md-4
.triplet-card(data-url="https://cloud.blender.org/p/gallery") .triplet-card(data-url="/p/gallery")
.triplet-card-thumbnail .triplet-card-thumbnail
img( img(
alt="Characters", alt="Characters",
@@ -158,25 +156,25 @@ li.nav-item-sign-in
h3 Art Walk-throughs h3 Art Walk-throughs
p. p.
Follow the creative process and techniques behind stunning artwork. Follow the creative process and techniques behind stunning artwork.
a.triplet-cta(href="https://cloud.blender.org/p/gallery") a.triplet-cta(href="/p/gallery")
| LEARN MORE | LEARN MORE
.row.training-other .row.training-other
.col-md-10.col-md-offset-1 .col-md-10.col-md-offset-1
p. p.
Other training: Other training:
#[a(href="https://cloud.blender.org/p/toon-character-workflow/") Toon Character Workflow], #[a(href="/p/toon-character-workflow/") Toon Character Workflow],
#[a(href="https://cloud.blender.org/p/3d-printing/") Blender for 3D Printing], #[a(href="/p/3d-printing/") Blender for 3D Printing],
#[a(href="https://cloud.blender.org/p/game-asset-creation/") Game Asset Creation], #[a(href="/p/game-asset-creation/") Game Asset Creation],
#[a(href="https://cloud.blender.org/p/blenderella/") Character Modeling], #[a(href="/p/blenderella/") Character Modeling],
#[a(href="https://cloud.blender.org/p/character-animation/") Character Animation], #[a(href="/p/character-animation/") Character Animation],
#[a(href="https://cloud.blender.org/p/humane-rigging/") Introduction] and #[a(href="/p/humane-rigging/") Introduction] and
#[a(href="https://cloud.blender.org/p/blenrig/") Advanced Rigging], #[a(href="/p/blenrig/") Advanced Rigging],
#[a(href="https://cloud.blender.org/p/track-match-2/") VFX Workflow], #[a(href="/p/track-match-2/") VFX Workflow],
#[a(href="https://cloud.blender.org/p/creature-factory-2/") Creature] and #[a(href="/p/creature-factory-2/") Creature] and
#[a(href="https://cloud.blender.org/p/venoms-lab-2/") Cartoon Character creation], #[a(href="/p/venoms-lab-2/") Cartoon Character creation],
#[a(href="https://cloud.blender.org/p/chaos-evolution/") Advanced] #[a(href="/p/chaos-evolution/") Advanced]
#[a(href="https://cloud.blender.org/p/blend-and-paint/") Digital Painting] and #[a(href="/p/blend-and-paint/") Digital Painting] and
#[a(href="{{ url_for('cloud.courses') }}") much more]! #[a(href="{{ url_for('cloud.courses') }}") much more]!
@@ -217,7 +215,7 @@ li.nav-item-sign-in
.page-triplet-container.homepage .page-triplet-container.homepage
.row .row
.col-md-4 .col-md-4
.triplet-card(data-url="https://cloud.blender.org/p/hero/") .triplet-card(data-url="/p/hero/")
.triplet-card-thumbnail .triplet-card-thumbnail
img( img(
alt="Hero", alt="Hero",
@@ -226,11 +224,11 @@ li.nav-item-sign-in
h3 Hero h3 Hero
p. p.
The first ever Grease Pencil open movie made with Blender 2.8 The first ever Grease Pencil open movie made with Blender 2.8
a.triplet-cta(href="https://cloud.blender.org/p/hero/") a.triplet-cta(href="/p/hero/")
| LEARN MORE | LEARN MORE
.col-md-4 .col-md-4
.triplet-card(data-url="https://cloud.blender.org/p/spring/") .triplet-card(data-url="/p/spring/")
.triplet-card-thumbnail .triplet-card-thumbnail
img( img(
alt="Spring", alt="Spring",
@@ -239,11 +237,11 @@ li.nav-item-sign-in
h3 Spring h3 Spring
p. p.
A poetic fantasy film. #[br] A stunning visual journey. A poetic fantasy film. #[br] A stunning visual journey.
a.triplet-cta(href="https://cloud.blender.org/p/spring/") a.triplet-cta(href="/p/spring/")
| LEARN MORE | LEARN MORE
.col-md-4 .col-md-4
.triplet-card(data-url="https://cloud.blender.org/p/caminandes-3/") .triplet-card(data-url="/p/caminandes-3/")
.triplet-card-thumbnail .triplet-card-thumbnail
img( img(
alt="Caminandes", alt="Caminandes",
@@ -252,21 +250,21 @@ li.nav-item-sign-in
h3 Caminandes h3 Caminandes
p. p.
Follow the adventures of Koro through the Patagonian pampas. Follow the adventures of Koro through the Patagonian pampas.
a.triplet-cta(href="https://cloud.blender.org/p/caminandes-3/") a.triplet-cta(href="/p/caminandes-3/")
| LEARN MORE | LEARN MORE
.row.training-other .row.training-other
.col-md-10.col-md-offset-1 .col-md-10.col-md-offset-1
p. p.
Other open movies: Other open movies:
#[a(href="https://cloud.blender.org/p/elephants-dream/") Elephants Dream], #[a(href="/p/elephants-dream/") Elephants Dream],
#[a(href="https://cloud.blender.org/p/big-buck-bunny/") Big Buck Bunny], #[a(href="/p/big-buck-bunny/") Big Buck Bunny],
#[a(href="https://cloud.blender.org/p/sintel/") Sintel], #[a(href="/p/sintel/") Sintel],
#[a(href="https://cloud.blender.org/p/tears-of-steel/") Tears of Steel], #[a(href="/p/tears-of-steel/") Tears of Steel],
#[a(href="https://cloud.blender.org/p/cosmos-laundromat/") Cosmos Laundromat], #[a(href="/p/cosmos-laundromat/") Cosmos Laundromat],
#[a(href="https://cloud.blender.org/p/glass-half/") Glass Half], #[a(href="/p/glass-half/") Glass Half],
#[a(href="https://cloud.blender.org/p/dailydweebs/") The Daily Dweebs], #[a(href="/p/dailydweebs/") The Daily Dweebs],
#[a(href="https://cloud.blender.org/p/agent-327/") Agent 327] #[a(href="/p/agent-327/") Agent 327]
and #[a(href="{{ url_for('cloud.open_projects') }}") more] and #[a(href="{{ url_for('cloud.open_projects') }}") more]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,43 +0,0 @@
//
// Base styles
//
.alert
position: relative
padding: $alert-padding-y $alert-padding-x
margin-bottom: $alert-margin-bottom
border: $alert-border-width solid transparent
+border-radius($alert-border-radius)
// Headings for larger alerts
.alert-heading
// Specified to prevent conflicts of changing $headings-color
color: inherit
// Provide class for links that match alerts
.alert-link
font-weight: $alert-link-font-weight
// Dismissible alerts
//
// Expand the right padding and account for the close button's positioning.
.alert-dismissible
padding-right: $close-font-size + $alert-padding-x * 2
// Adjust close link position
.close
position: absolute
top: 0
right: 0
padding: $alert-padding-y $alert-padding-x
color: inherit
// Alternate styles
//
// Generate contextual modifier classes for colorizing the alert.
@each $color, $value in $theme-colors
.alert-#{$color}
+alert-variant(theme-color-level($color, $alert-bg-level), theme-color-level($color, $alert-border-level), theme-color-level($color, $alert-color-level))

View File

@@ -1,43 +0,0 @@
// Base class
//
// Requires one of the contextual, color modifier classes for `color` and
// `background-color`.
.badge
display: inline-block
padding: $badge-padding-y $badge-padding-x
font-size: $badge-font-size
font-weight: $badge-font-weight
line-height: 1
text-align: center
white-space: nowrap
vertical-align: baseline
+border-radius($badge-border-radius)
// Empty badges collapse automatically
&:empty
display: none
// Quick fix for badges in buttons
.btn .badge
position: relative
top: -1px
// Pill badges
//
// Make them extra rounded with a modifier to replace v3's badges.
.badge-pill
padding-right: $badge-pill-padding-x
padding-left: $badge-pill-padding-x
+border-radius($badge-pill-border-radius)
// Colors
//
// Contextual variations (linked badges get darker on :hover).
@each $color, $value in $theme-colors
.badge-#{$color}
+badge-variant($value)

View File

@@ -1,38 +0,0 @@
.breadcrumb
display: flex
flex-wrap: wrap
padding: $breadcrumb-padding-y $breadcrumb-padding-x
margin-bottom: $breadcrumb-margin-bottom
list-style: none
background-color: $breadcrumb-bg
+border-radius($breadcrumb-border-radius)
.breadcrumb-item
// The separator between breadcrumbs (by default, a forward-slash: "/")
+ .breadcrumb-item
padding-left: $breadcrumb-item-padding
&::before
display: inline-block
// Suppress underlining of the separator in modern browsers
padding-right: $breadcrumb-item-padding
color: $breadcrumb-divider-color
content: $breadcrumb-divider
// IE9-11 hack to properly handle hyperlink underlines for breadcrumbs built
// without `<ul>`s. The `::before` pseudo-element generates an element
// *within* the .breadcrumb-item and thereby inherits the `text-decoration`.
//
// To trick IE into suppressing the underline, we give the pseudo-element an
// underline and then immediately remove it.
+ .breadcrumb-item:hover::before
text-decoration: underline
// stylelint-disable-next-line no-duplicate-selectors
+ .breadcrumb-item:hover::before
text-decoration: none
&.active
color: $breadcrumb-active-color

View File

@@ -1,151 +0,0 @@
// stylelint-disable selector-no-qualifying-type
// Make the div behave like a button
.btn-group,
.btn-group-vertical
position: relative
display: inline-flex
vertical-align: middle
// match .btn alignment given font-size hack above
> .btn
position: relative
flex: 0 1 auto
// Bring the hover, focused, and "active" buttons to the front to overlay
// the borders properly
+hover
z-index: 1
&:focus,
&:active,
&.active
z-index: 1
// Prevent double borders when buttons are next to each other
.btn + .btn,
.btn + .btn-group,
.btn-group + .btn,
.btn-group + .btn-group
margin-left: -$btn-border-width
// Optional: Group multiple button groups together for a toolbar
.btn-toolbar
display: flex
flex-wrap: wrap
justify-content: flex-start
.input-group
width: auto
.btn-group
> .btn:first-child
margin-left: 0
// Reset rounded corners
> .btn:not(:last-child):not(.dropdown-toggle),
> .btn-group:not(:last-child) > .btn
+border-right-radius(0)
> .btn:not(:first-child),
> .btn-group:not(:first-child) > .btn
+border-left-radius(0)
// Sizing
//
// Remix the default button sizing classes into new ones for easier manipulation.
.btn-group-sm > .btn
@extend .btn-sm
.btn-group-lg > .btn
@extend .btn-lg
//
// Split button dropdowns
//
.dropdown-toggle-split
padding-right: $btn-padding-x * 0.75
padding-left: $btn-padding-x * 0.75
&::after,
.dropup &::after,
.dropright &::after
margin-left: 0
.dropleft &::before
margin-right: 0
.btn-sm + .dropdown-toggle-split
padding-right: $btn-padding-x-sm * 0.75
padding-left: $btn-padding-x-sm * 0.75
.btn-lg + .dropdown-toggle-split
padding-right: $btn-padding-x-lg * 0.75
padding-left: $btn-padding-x-lg * 0.75
// The clickable button for toggling the menu
// Set the same inset shadow as the :active state
.btn-group.show .dropdown-toggle
+box-shadow($btn-active-box-shadow)
// Show no shadow for `.btn-link` since it has no other button styles.
&.btn-link
+box-shadow(none)
//
// Vertical button groups
//
.btn-group-vertical
flex-direction: column
align-items: flex-start
justify-content: center
.btn,
.btn-group
width: 100%
> .btn + .btn,
> .btn + .btn-group,
> .btn-group + .btn,
> .btn-group + .btn-group
margin-top: -$btn-border-width
margin-left: 0
// Reset rounded corners
> .btn:not(:last-child):not(.dropdown-toggle),
> .btn-group:not(:last-child) > .btn
+border-bottom-radius(0)
> .btn:not(:first-child),
> .btn-group:not(:first-child) > .btn
+border-top-radius(0)
// Checkbox and radio options
//
// In order to support the browser's form validation feedback, powered by the
// `required` attribute, we have to "hide" the inputs via `clip`. We cannot use
// `display: none;` or `visibility: hidden;` as that also hides the popover.
// Simply visually hiding the inputs via `opacity` would leave them clickable in
// certain cases which is prevented by using `clip` and `pointer-events`.
// This way, we ensure a DOM element is visible to position the popover from.
//
// See https://github.com/twbs/bootstrap/pull/12794 and
// https://github.com/twbs/bootstrap/pull/14559 for more information.
.btn-group-toggle
> .btn,
> .btn-group > .btn
margin-bottom: 0
// Override default `<label>` value
input[type="radio"],
input[type="checkbox"]
position: absolute
clip: rect(0, 0, 0, 0)
pointer-events: none

View File

@@ -1,123 +0,0 @@
// stylelint-disable selector-no-qualifying-type
//
// Base styles
//
.btn
display: inline-block
font-weight: $btn-font-weight
text-align: center
white-space: nowrap
vertical-align: middle
user-select: none
border: $btn-border-width solid transparent
+button-size($btn-padding-y, $btn-padding-x, $font-size-base, $btn-line-height, $btn-border-radius)
+transition($btn-transition)
// Share hover and focus styles
+hover-focus
text-decoration: none
&:focus,
&.focus
outline: 0
box-shadow: $btn-focus-box-shadow
// Disabled comes first so active can properly restyle
&.disabled,
&:disabled
opacity: $btn-disabled-opacity
+box-shadow(none)
// Opinionated: add "hand" cursor to non-disabled .btn elements
&:not(:disabled):not(.disabled)
cursor: pointer
&:not(:disabled):not(.disabled):active,
&:not(:disabled):not(.disabled).active
background-image: none
+box-shadow($btn-active-box-shadow)
&:focus
+box-shadow($btn-focus-box-shadow, $btn-active-box-shadow)
// Future-proof disabling of clicks on `<a>` elements
a.btn.disabled,
fieldset:disabled a.btn
pointer-events: none
//
// Alternate buttons
//
@each $color, $value in $theme-colors
.btn-#{$color}
+button-variant($value, $value)
@each $color, $value in $theme-colors
.btn-outline-#{$color}
+button-outline-variant($value)
//
// Link buttons
//
// Make a button look and behave like a link
.btn-link
font-weight: $font-weight-normal
color: $link-color
background-color: transparent
+hover
color: $link-hover-color
text-decoration: $link-hover-decoration
background-color: transparent
border-color: transparent
&:focus,
&.focus
text-decoration: $link-hover-decoration
border-color: transparent
box-shadow: none
&:disabled,
&.disabled
color: $btn-link-disabled-color
pointer-events: none
// No need for an active state here
//
// Button Sizes
//
.btn-lg
+button-size($btn-padding-y-lg, $btn-padding-x-lg, $font-size-lg, $btn-line-height-lg, $btn-border-radius-lg)
.btn-sm
+button-size($btn-padding-y-sm, $btn-padding-x-sm, $font-size-sm, $btn-line-height-sm, $btn-border-radius-sm)
//
// Block button
//
.btn-block
display: block
width: 100%
// Vertically space out multiple block buttons
+ .btn-block
margin-top: $btn-block-spacing-y
// Specificity overrides
input[type="submit"],
input[type="reset"],
input[type="button"]
&.btn-block
width: 100%

View File

@@ -1,261 +0,0 @@
//
// Base styles
//
.card
position: relative
display: flex
flex-direction: column
min-width: 0
word-wrap: break-word
background-color: $card-bg
background-clip: border-box
border: $card-border-width solid $card-border-color
+border-radius($card-border-radius)
> hr
margin-right: 0
margin-left: 0
> .list-group:first-child
.list-group-item:first-child
+border-top-radius($card-border-radius)
> .list-group:last-child
.list-group-item:last-child
+border-bottom-radius($card-border-radius)
.card-body
// Enable `flex-grow: 1` for decks and groups so that card blocks take up
// as much space as possible, ensuring footers are aligned to the bottom.
flex: 1 1 auto
padding: $card-spacer-x
.card-title
margin-bottom: $card-spacer-y
.card-subtitle
margin-top: -($card-spacer-y / 2)
margin-bottom: 0
.card-text:last-child
margin-bottom: 0
.card-link
+hover
text-decoration: none
+ .card-link
margin-left: $card-spacer-x
//
// Optional textual caps
//
.card-header
padding: $card-spacer-y $card-spacer-x
margin-bottom: 0
// Removes the default margin-bottom of <hN>
background-color: $card-cap-bg
border-bottom: $card-border-width solid $card-border-color
&:first-child
+border-radius($card-inner-border-radius $card-inner-border-radius 0 0)
+ .list-group
.list-group-item:first-child
border-top: 0
.card-footer
padding: $card-spacer-y $card-spacer-x
background-color: $card-cap-bg
border-top: $card-border-width solid $card-border-color
&:last-child
+border-radius(0 0 $card-inner-border-radius $card-inner-border-radius)
//
// Header navs
//
.card-header-tabs
margin-right: -($card-spacer-x / 2)
margin-bottom: -$card-spacer-y
margin-left: -($card-spacer-x / 2)
border-bottom: 0
.card-header-pills
margin-right: -($card-spacer-x / 2)
margin-left: -($card-spacer-x / 2)
// Card image
.card-img-overlay
position: absolute
top: 0
right: 0
bottom: 0
left: 0
padding: $card-img-overlay-padding
.card-img
width: 100%
// Required because we use flexbox and this inherently applies align-self: stretch
+border-radius($card-inner-border-radius)
// Card image caps
.card-img-top
width: 100%
// Required because we use flexbox and this inherently applies align-self: stretch
+border-top-radius($card-inner-border-radius)
.card-img-bottom
width: 100%
// Required because we use flexbox and this inherently applies align-self: stretch
+border-bottom-radius($card-inner-border-radius)
// Card deck
.card-deck
display: flex
flex-direction: column
.card
margin-bottom: $card-deck-margin
+media-breakpoint-up(sm)
flex-flow: row wrap
margin-right: -$card-deck-margin
margin-left: -$card-deck-margin
.card
display: flex
// Flexbugs #4: https://github.com/philipwalton/flexbugs#flexbug-4
flex: 1 0 0%
flex-direction: column
margin-right: $card-deck-margin
margin-bottom: 0
// Override the default
margin-left: $card-deck-margin
//
// Card groups
//
.card-group
display: flex
flex-direction: column
// The child selector allows nested `.card` within `.card-group`
// to display properly.
> .card
margin-bottom: $card-group-margin
+media-breakpoint-up(sm)
flex-flow: row wrap
// The child selector allows nested `.card` within `.card-group`
// to display properly.
> .card
// Flexbugs #4: https://github.com/philipwalton/flexbugs#flexbug-4
flex: 1 0 0%
margin-bottom: 0
+ .card
margin-left: 0
border-left: 0
// Handle rounded corners
@if $enable-rounded
&:first-child
+border-right-radius(0)
.card-img-top,
.card-header
border-top-right-radius: 0
.card-img-bottom,
.card-footer
border-bottom-right-radius: 0
&:last-child
+border-left-radius(0)
.card-img-top,
.card-header
border-top-left-radius: 0
.card-img-bottom,
.card-footer
border-bottom-left-radius: 0
&:only-child
+border-radius($card-border-radius)
.card-img-top,
.card-header
+border-top-radius($card-border-radius)
.card-img-bottom,
.card-footer
+border-bottom-radius($card-border-radius)
&:not(:first-child):not(:last-child):not(:only-child)
+border-radius(0)
.card-img-top,
.card-img-bottom,
.card-header,
.card-footer
+border-radius(0)
//
// Columns
//
.card-columns
.card
margin-bottom: $card-columns-margin
+media-breakpoint-up(sm)
column-count: $card-columns-count
column-gap: $card-columns-gap
orphans: 1
widows: 1
.card
display: inline-block
// Don't let them vertically span multiple columns
width: 100%
// Don't let their width change
//
// Accordion
//
.accordion
.card:not(:first-of-type):not(:last-of-type)
border-bottom: 0
border-radius: 0
.card:not(:first-of-type)
.card-header:first-child
border-radius: 0
.card:first-of-type
border-bottom: 0
border-bottom-right-radius: 0
border-bottom-left-radius: 0
.card:last-of-type
border-top-left-radius: 0
border-top-right-radius: 0

View File

@@ -1,218 +0,0 @@
// Notes on the classes:
//
// 1. The .carousel-item-left and .carousel-item-right is used to indicate where
// the active slide is heading.
// 2. .active.carousel-item is the current slide.
// 3. .active.carousel-item-left and .active.carousel-item-right is the current
// slide in its in-transition state. Only one of these occurs at a time.
// 4. .carousel-item-next.carousel-item-left and .carousel-item-prev.carousel-item-right
// is the upcoming slide in transition.
.carousel
position: relative
.carousel-inner
position: relative
width: 100%
overflow: hidden
.carousel-item
position: relative
display: none
align-items: center
width: 100%
backface-visibility: hidden
perspective: 1000px
.carousel-item.active,
.carousel-item-next,
.carousel-item-prev
display: block
+transition($carousel-transition)
.carousel-item-next,
.carousel-item-prev
position: absolute
top: 0
.carousel-item-next.carousel-item-left,
.carousel-item-prev.carousel-item-right
transform: translateX(0)
@supports (transform-style: preserve-3d)
transform: translate3d(0, 0, 0)
.carousel-item-next,
.active.carousel-item-right
transform: translateX(100%)
@supports (transform-style: preserve-3d)
transform: translate3d(100%, 0, 0)
.carousel-item-prev,
.active.carousel-item-left
transform: translateX(-100%)
@supports (transform-style: preserve-3d)
transform: translate3d(-100%, 0, 0)
//
// Alternate transitions
//
.carousel-fade
.carousel-item
opacity: 0
transition-duration: .6s
transition-property: opacity
.carousel-item.active,
.carousel-item-next.carousel-item-left,
.carousel-item-prev.carousel-item-right
opacity: 1
.active.carousel-item-left,
.active.carousel-item-right
opacity: 0
.carousel-item-next,
.carousel-item-prev,
.carousel-item.active,
.active.carousel-item-left,
.active.carousel-item-prev
transform: translateX(0)
@supports (transform-style: preserve-3d)
transform: translate3d(0, 0, 0)
//
// Left/right controls for nav
//
.carousel-control-prev,
.carousel-control-next
position: absolute
top: 0
bottom: 0
// Use flex for alignment (1-3)
display: flex
// 1. allow flex styles
align-items: center
// 2. vertically center contents
justify-content: center
// 3. horizontally center contents
width: $carousel-control-width
color: $carousel-control-color
text-align: center
opacity: $carousel-control-opacity
// We can't have a transition here because WebKit cancels the carousel
// animation if you trip this while in the middle of another animation.
// Hover/focus state
+hover-focus
color: $carousel-control-color
text-decoration: none
outline: 0
opacity: .9
.carousel-control-prev
left: 0
@if $enable-gradients
background: linear-gradient(90deg, rgba($black, 0.25), rgba($black, 0.001))
.carousel-control-next
right: 0
@if $enable-gradients
background: linear-gradient(270deg, rgba($black, 0.25), rgba($black, 0.001))
// Icons for within
.carousel-control-prev-icon,
.carousel-control-next-icon
display: inline-block
width: $carousel-control-icon-width
height: $carousel-control-icon-width
background: transparent no-repeat center center
background-size: 100% 100%
.carousel-control-prev-icon
background-image: $carousel-control-prev-icon-bg
.carousel-control-next-icon
background-image: $carousel-control-next-icon-bg
// Optional indicator pips
//
// Add an ordered list with the following class and add a list item for each
// slide your carousel holds.
.carousel-indicators
position: absolute
right: 0
bottom: 10px
left: 0
z-index: 15
display: flex
justify-content: center
padding-left: 0
// override <ol> default
// Use the .carousel-control's width as margin so we don't overlay those
margin-right: $carousel-control-width
margin-left: $carousel-control-width
list-style: none
li
position: relative
flex: 0 1 auto
width: $carousel-indicator-width
height: $carousel-indicator-height
margin-right: $carousel-indicator-spacer
margin-left: $carousel-indicator-spacer
text-indent: -999px
cursor: pointer
background-color: rgba($carousel-indicator-active-bg, 0.5)
// Use pseudo classes to increase the hit area by 10px on top and bottom.
&::before
position: absolute
top: -10px
left: 0
display: inline-block
width: 100%
height: 10px
content: ""
&::after
position: absolute
bottom: -10px
left: 0
display: inline-block
width: 100%
height: 10px
content: ""
.active
background-color: $carousel-indicator-active-bg
// Optional captions
//
//
.carousel-caption
position: absolute
right: (100% - $carousel-caption-width) / 2
bottom: 20px
left: (100% - $carousel-caption-width) / 2
z-index: 10
padding-top: 20px
padding-bottom: 20px
color: $carousel-caption-color
text-align: center

View File

@@ -1,32 +0,0 @@
.close
float: right
font-size: $close-font-size
font-weight: $close-font-weight
line-height: 1
color: $close-color
text-shadow: $close-text-shadow
opacity: .5
&:not(:disabled):not(.disabled)
+hover-focus
color: $close-color
text-decoration: none
opacity: .75
// Opinionated: add "hand" cursor to non-disabled .close elements
cursor: pointer
// Additional properties for button version
// iOS requires the button element instead of an anchor tag.
// If you want the anchor version, it requires `href="#"`.
// See https://developer.mozilla.org/en-US/docs/Web/Events/click#Safari_Mobile
// stylelint-disable property-no-vendor-prefix, selector-no-qualifying-type
button.close
padding: 0
background-color: transparent
border: 0
-webkit-appearance: none
// stylelint-enable

View File

@@ -1,43 +0,0 @@
// Inline code
code
font-size: $code-font-size
color: $code-color
word-break: break-word
// Streamline the style when inside anchors to avoid broken underline and more
a > &
color: inherit
// User input typically entered via keyboard
kbd
padding: $kbd-padding-y $kbd-padding-x
font-size: $kbd-font-size
color: $kbd-color
background-color: $kbd-bg
+border-radius($border-radius-sm)
+box-shadow($kbd-box-shadow)
kbd
padding: 0
font-size: 100%
font-weight: $nested-kbd-font-weight
+box-shadow(none)
// Blocks of code
pre
display: block
font-size: $code-font-size
color: $pre-color
// Account for some code outputs that place code tags in pre tags
code
font-size: inherit
color: inherit
word-break: normal
// Enable scrollable blocks of code
.pre-scrollable
max-height: $pre-scrollable-max-height
overflow-y: scroll

View File

@@ -1,416 +0,0 @@
// Embedded icons from Open Iconic.
// Released under MIT and copyright 2014 Waybury.
// https://useiconic.com/open
// Checkboxes and radios
//
// Base class takes care of all the key behavioral aspects.
.custom-control
position: relative
display: block
min-height: 1rem * $line-height-base
padding-left: $custom-control-gutter
.custom-control-inline
display: inline-flex
margin-right: $custom-control-spacer-x
.custom-control-input
position: absolute
z-index: -1
// Put the input behind the label so it doesn't overlay text
opacity: 0
&:checked ~ .custom-control-label::before
color: $custom-control-indicator-checked-color
+gradient-bg($custom-control-indicator-checked-bg)
+box-shadow($custom-control-indicator-checked-box-shadow)
&:focus ~ .custom-control-label::before
// the mixin is not used here to make sure there is feedback
box-shadow: $custom-control-indicator-focus-box-shadow
&:active ~ .custom-control-label::before
color: $custom-control-indicator-active-color
background-color: $custom-control-indicator-active-bg
+box-shadow($custom-control-indicator-active-box-shadow)
&:disabled
~ .custom-control-label
color: $custom-control-label-disabled-color
&::before
background-color: $custom-control-indicator-disabled-bg
// Custom control indicators
//
// Build the custom controls out of pseudo-elements.
.custom-control-label
position: relative
margin-bottom: 0
// Background-color and (when enabled) gradient
&::before
position: absolute
top: ($line-height-base - $custom-control-indicator-size) / 2
left: -$custom-control-gutter
display: block
width: $custom-control-indicator-size
height: $custom-control-indicator-size
pointer-events: none
content: ""
user-select: none
background-color: $custom-control-indicator-bg
+box-shadow($custom-control-indicator-box-shadow)
// Foreground (icon)
&::after
position: absolute
top: ($line-height-base - $custom-control-indicator-size) / 2
left: -$custom-control-gutter
display: block
width: $custom-control-indicator-size
height: $custom-control-indicator-size
content: ""
background-repeat: no-repeat
background-position: center center
background-size: $custom-control-indicator-bg-size
// Checkboxes
//
// Tweak just a few things for checkboxes.
.custom-checkbox
.custom-control-label::before
+border-radius($custom-checkbox-indicator-border-radius)
.custom-control-input:checked ~ .custom-control-label
&::before
+gradient-bg($custom-control-indicator-checked-bg)
&::after
background-image: $custom-checkbox-indicator-icon-checked
.custom-control-input:indeterminate ~ .custom-control-label
&::before
+gradient-bg($custom-checkbox-indicator-indeterminate-bg)
+box-shadow($custom-checkbox-indicator-indeterminate-box-shadow)
&::after
background-image: $custom-checkbox-indicator-icon-indeterminate
.custom-control-input:disabled
&:checked ~ .custom-control-label::before
background-color: $custom-control-indicator-checked-disabled-bg
&:indeterminate ~ .custom-control-label::before
background-color: $custom-control-indicator-checked-disabled-bg
// Radios
//
// Tweak just a few things for radios.
.custom-radio
.custom-control-label::before
border-radius: $custom-radio-indicator-border-radius
.custom-control-input:checked ~ .custom-control-label
&::before
+gradient-bg($custom-control-indicator-checked-bg)
&::after
background-image: $custom-radio-indicator-icon-checked
.custom-control-input:disabled
&:checked ~ .custom-control-label::before
background-color: $custom-control-indicator-checked-disabled-bg
// Select
//
// Replaces the browser default select with a custom one, mostly pulled from
// https://primer.github.io/.
//
.custom-select
display: inline-block
width: 100%
height: $custom-select-height
padding: $custom-select-padding-y ($custom-select-padding-x + $custom-select-indicator-padding) $custom-select-padding-y $custom-select-padding-x
line-height: $custom-select-line-height
color: $custom-select-color
vertical-align: middle
background: $custom-select-bg $custom-select-indicator no-repeat right $custom-select-padding-x center
background-size: $custom-select-bg-size
border: $custom-select-border-width solid $custom-select-border-color
@if $enable-rounded
border-radius: $custom-select-border-radius
@else
border-radius: 0
+box-shadow($custom-select-box-shadow)
appearance: none
&:focus
border-color: $custom-select-focus-border-color
outline: 0
@if $enable-shadows
box-shadow: $custom-select-box-shadow, $custom-select-focus-box-shadow
@else
box-shadow: $custom-select-focus-box-shadow
&::-ms-value
// For visual consistency with other platforms/browsers,
// suppress the default white text on blue background highlight given to
// the selected option text when the (still closed) <select> receives focus
// in IE and (under certain conditions) Edge.
// See https://github.com/twbs/bootstrap/issues/19398.
color: $input-color
background-color: $input-bg
&[multiple],
&[size]:not([size="1"])
height: auto
padding-right: $custom-select-padding-x
background-image: none
&:disabled
color: $custom-select-disabled-color
background-color: $custom-select-disabled-bg
// Hides the default caret in IE11
&::-ms-expand
opacity: 0
.custom-select-sm
height: $custom-select-height-sm
padding-top: $custom-select-padding-y
padding-bottom: $custom-select-padding-y
font-size: $custom-select-font-size-sm
.custom-select-lg
height: $custom-select-height-lg
padding-top: $custom-select-padding-y
padding-bottom: $custom-select-padding-y
font-size: $custom-select-font-size-lg
// File
//
// Custom file input.
.custom-file
position: relative
display: inline-block
width: 100%
height: $custom-file-height
margin-bottom: 0
.custom-file-input
position: relative
z-index: 2
width: 100%
height: $custom-file-height
margin: 0
opacity: 0
&:focus ~ .custom-file-label
border-color: $custom-file-focus-border-color
box-shadow: $custom-file-focus-box-shadow
&::after
border-color: $custom-file-focus-border-color
&:disabled ~ .custom-file-label
background-color: $custom-file-disabled-bg
@each $lang, $value in $custom-file-text
&:lang(#{$lang}) ~ .custom-file-label::after
content: $value
.custom-file-label
position: absolute
top: 0
right: 0
left: 0
z-index: 1
height: $custom-file-height
padding: $custom-file-padding-y $custom-file-padding-x
line-height: $custom-file-line-height
color: $custom-file-color
background-color: $custom-file-bg
border: $custom-file-border-width solid $custom-file-border-color
+border-radius($custom-file-border-radius)
+box-shadow($custom-file-box-shadow)
&::after
position: absolute
top: 0
right: 0
bottom: 0
z-index: 3
display: block
height: $custom-file-height-inner
padding: $custom-file-padding-y $custom-file-padding-x
line-height: $custom-file-line-height
color: $custom-file-button-color
content: "Browse"
+gradient-bg($custom-file-button-bg)
border-left: $custom-file-border-width solid $custom-file-border-color
+border-radius(0 $custom-file-border-radius $custom-file-border-radius 0)
// Range
//
// Style range inputs the same across browsers. Vendor-specific rules for pseudo
// elements cannot be mixed. As such, there are no shared styles for focus or
// active states on prefixed selectors.
.custom-range
width: 100%
padding-left: 0
// Firefox specific
background-color: transparent
appearance: none
&:focus
outline: none
&::-moz-focus-outer
border: 0
&::-webkit-slider-thumb
width: $custom-range-thumb-width
height: $custom-range-thumb-height
margin-top: -($custom-range-thumb-width * 0.25)
// Webkit specific?
+gradient-bg($custom-range-thumb-bg)
border: $custom-range-thumb-border
+border-radius($custom-range-thumb-border-radius)
+box-shadow($custom-range-thumb-box-shadow)
+transition($custom-forms-transition)
appearance: none
&:focus
outline: none
box-shadow: $custom-range-thumb-focus-box-shadow
// No mixin for focus accessibility
&:active
+gradient-bg($custom-range-thumb-active-bg)
&::-webkit-slider-runnable-track
width: $custom-range-track-width
height: $custom-range-track-height
color: transparent
// Why?
cursor: $custom-range-track-cursor
background-color: $custom-range-track-bg
border-color: transparent
+border-radius($custom-range-track-border-radius)
+box-shadow($custom-range-track-box-shadow)
&::-moz-range-thumb
width: $custom-range-thumb-width
height: $custom-range-thumb-height
+gradient-bg($custom-range-thumb-bg)
border: $custom-range-thumb-border
+border-radius($custom-range-thumb-border-radius)
+box-shadow($custom-range-thumb-box-shadow)
+transition($custom-forms-transition)
appearance: none
&:focus
outline: none
box-shadow: $custom-range-thumb-focus-box-shadow
// No mixin for focus accessibility
&:active
+gradient-bg($custom-range-thumb-active-bg)
&::-moz-range-track
width: $custom-range-track-width
height: $custom-range-track-height
color: transparent
cursor: $custom-range-track-cursor
background-color: $custom-range-track-bg
border-color: transparent
// Firefox specific?
+border-radius($custom-range-track-border-radius)
+box-shadow($custom-range-track-box-shadow)
&::-ms-thumb
width: $custom-range-thumb-width
height: $custom-range-thumb-height
+gradient-bg($custom-range-thumb-bg)
border: $custom-range-thumb-border
+border-radius($custom-range-thumb-border-radius)
+box-shadow($custom-range-thumb-box-shadow)
+transition($custom-forms-transition)
appearance: none
&:focus
outline: none
box-shadow: $custom-range-thumb-focus-box-shadow
// No mixin for focus accessibility
&:active
+gradient-bg($custom-range-thumb-active-bg)
&::-ms-track
width: $custom-range-track-width
height: $custom-range-track-height
color: transparent
cursor: $custom-range-track-cursor
background-color: transparent
border-color: transparent
border-width: $custom-range-thumb-height * 0.5
+box-shadow($custom-range-track-box-shadow)
&::-ms-fill-lower
background-color: $custom-range-track-bg
+border-radius($custom-range-track-border-radius)
&::-ms-fill-upper
margin-right: 15px
// arbitrary?
background-color: $custom-range-track-bg
+border-radius($custom-range-track-border-radius)
.custom-control-label::before,
.custom-file-label,
.custom-select
+transition($custom-forms-transition)

View File

@@ -1,170 +0,0 @@
// The dropdown wrapper (`<div>`)
.dropup,
.dropright,
.dropdown,
.dropleft
position: relative
.dropdown-toggle
// Generate the caret automatically
+caret
// The dropdown menu
.dropdown-menu
position: absolute
top: 100%
left: 0
z-index: $zindex-dropdown
display: none
// none by default, but block on "open" of the menu
float: left
min-width: $dropdown-min-width
padding: $dropdown-padding-y 0
margin: $dropdown-spacer 0 0
// override default ul
font-size: $font-size-base
// Redeclare because nesting can cause inheritance issues
color: $body-color
text-align: left
// Ensures proper alignment if parent has it changed (e.g., modal footer)
list-style: none
background-color: $dropdown-bg
background-clip: padding-box
border: $dropdown-border-width solid $dropdown-border-color
+border-radius($dropdown-border-radius)
+box-shadow($dropdown-box-shadow)
.dropdown-menu-right
right: 0
left: auto
// Allow for dropdowns to go bottom up (aka, dropup-menu)
// Just add .dropup after the standard .dropdown class and you're set.
.dropup
.dropdown-menu
top: auto
bottom: 100%
margin-top: 0
margin-bottom: $dropdown-spacer
.dropdown-toggle
+caret(up)
.dropright
.dropdown-menu
top: 0
right: auto
left: 100%
margin-top: 0
margin-left: $dropdown-spacer
.dropdown-toggle
+caret(right)
&::after
vertical-align: 0
.dropleft
.dropdown-menu
top: 0
right: 100%
left: auto
margin-top: 0
margin-right: $dropdown-spacer
.dropdown-toggle
+caret(left)
&::before
vertical-align: 0
// When enabled Popper.js, reset basic dropdown position
// stylelint-disable no-duplicate-selectors
.dropdown-menu
&[x-placement^="top"],
&[x-placement^="right"],
&[x-placement^="bottom"],
&[x-placement^="left"]
right: auto
bottom: auto
// stylelint-enable no-duplicate-selectors
// Dividers (basically an `<hr>`) within the dropdown
.dropdown-divider
+nav-divider($dropdown-divider-bg)
// Links, buttons, and more within the dropdown menu
//
// `<button>`-specific styles are denoted with `// For <button>s`
.dropdown-item
display: block
width: 100%
// For `<button>`s
padding: $dropdown-item-padding-y $dropdown-item-padding-x
clear: both
font-weight: $font-weight-normal
color: $dropdown-link-color
text-align: inherit
// For `<button>`s
white-space: nowrap
// prevent links from randomly breaking onto new lines
background-color: transparent
// For `<button>`s
border: 0
// For `<button>`s
+hover-focus
color: $dropdown-link-hover-color
text-decoration: none
+gradient-bg($dropdown-link-hover-bg)
&.active,
&:active
color: $dropdown-link-active-color
text-decoration: none
+gradient-bg($dropdown-link-active-bg)
&.disabled,
&:disabled
color: $dropdown-link-disabled-color
background-color: transparent
// Remove CSS gradients if they're enabled
@if $enable-gradients
background-image: none
.dropdown-menu.show
display: block
// Dropdown section headers
.dropdown-header
display: block
padding: $dropdown-padding-y $dropdown-item-padding-x
margin-bottom: 0
// for use with heading elements
font-size: $font-size-sm
color: $dropdown-header-color
white-space: nowrap
// as with > li > a
// Dropdown text
.dropdown-item-text
display: block
padding: $dropdown-item-padding-y $dropdown-item-padding-x
color: $dropdown-link-color

View File

@@ -1,306 +0,0 @@
// stylelint-disable selector-no-qualifying-type
//
// Textual form controls
//
.form-control
display: block
width: 100%
padding: $input-padding-y $input-padding-x
font-size: $font-size-base
line-height: $input-line-height
color: $input-color
background-color: $input-bg
background-clip: padding-box
border: $input-border-width solid $input-border-color
// Note: This has no effect on <select>s in some browsers, due to the limited stylability of `<select>`s in CSS.
@if $enable-rounded
// Manually use the if/else instead of the mixin to account for iOS override
border-radius: $input-border-radius
@else
// Otherwise undo the iOS default
border-radius: 0
+box-shadow($input-box-shadow)
+transition($input-transition)
// Unstyle the caret on `<select>`s in IE10+.
&::-ms-expand
background-color: transparent
border: 0
// Customize the `:focus` state to imitate native WebKit styles.
+form-control-focus
// Placeholder
&::placeholder
color: $input-placeholder-color
// Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526.
opacity: 1
// Disabled and read-only inputs
//
// HTML5 says that controls under a fieldset > legend:first-child won't be
// disabled if the fieldset is disabled. Due to implementation difficulty, we
// don't honor that edge case; we style them as disabled anyway.
&:disabled,
&[readonly]
background-color: $input-disabled-bg
// iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655.
opacity: 1
select.form-control
&:not([size]):not([multiple])
height: $input-height
&:focus::-ms-value
// Suppress the nested default white text on blue background highlight given to
// the selected option text when the (still closed) <select> receives focus
// in IE and (under certain conditions) Edge, as it looks bad and cannot be made to
// match the appearance of the native widget.
// See https://github.com/twbs/bootstrap/issues/19398.
color: $input-color
background-color: $input-bg
// Make file inputs better match text inputs by forcing them to new lines.
.form-control-file,
.form-control-range
display: block
width: 100%
//
// Labels
//
// For use with horizontal and inline forms, when you need the label (or legend)
// text to align with the form controls.
.col-form-label
padding-top: calc(#{$input-padding-y} + #{$input-border-width})
padding-bottom: calc(#{$input-padding-y} + #{$input-border-width})
margin-bottom: 0
// Override the `<label>/<legend>` default
font-size: inherit
// Override the `<legend>` default
line-height: $input-line-height
.col-form-label-lg
padding-top: calc(#{$input-padding-y-lg} + #{$input-border-width})
padding-bottom: calc(#{$input-padding-y-lg} + #{$input-border-width})
font-size: $font-size-lg
line-height: $input-line-height-lg
.col-form-label-sm
padding-top: calc(#{$input-padding-y-sm} + #{$input-border-width})
padding-bottom: calc(#{$input-padding-y-sm} + #{$input-border-width})
font-size: $font-size-sm
line-height: $input-line-height-sm
// Readonly controls as plain text
//
// Apply class to a readonly input to make it appear like regular plain
// text (without any border, background color, focus indicator)
.form-control-plaintext
display: block
width: 100%
padding-top: $input-padding-y
padding-bottom: $input-padding-y
margin-bottom: 0
// match inputs if this class comes on inputs with default margins
line-height: $input-line-height
color: $input-plaintext-color
background-color: transparent
border: solid transparent
border-width: $input-border-width 0
&.form-control-sm,
&.form-control-lg
padding-right: 0
padding-left: 0
// Form control sizing
//
// Build on `.form-control` with modifier classes to decrease or increase the
// height and font-size of form controls.
//
// The `.form-group-* form-control` variations are sadly duplicated to avoid the
// issue documented in https://github.com/twbs/bootstrap/issues/15074.
.form-control-sm
padding: $input-padding-y-sm $input-padding-x-sm
font-size: $font-size-sm
line-height: $input-line-height-sm
+border-radius($input-border-radius-sm)
select.form-control-sm
&:not([size]):not([multiple])
height: $input-height-sm
.form-control-lg
padding: $input-padding-y-lg $input-padding-x-lg
font-size: $font-size-lg
line-height: $input-line-height-lg
+border-radius($input-border-radius-lg)
select.form-control-lg
&:not([size]):not([multiple])
height: $input-height-lg
// Form groups
//
// Designed to help with the organization and spacing of vertical forms. For
// horizontal forms, use the predefined grid classes.
.form-group
margin-bottom: $form-group-margin-bottom
.form-text
display: block
margin-top: $form-text-margin-top
// Form grid
//
// Special replacement for our grid system's `.row` for tighter form layouts.
.form-row
display: flex
flex-wrap: wrap
margin-right: -5px
margin-left: -5px
> .col,
> [class*="col-"]
padding-right: 5px
padding-left: 5px
// Checkboxes and radios
//
// Indent the labels to position radios/checkboxes as hanging controls.
.form-check
position: relative
display: block
padding-left: $form-check-input-gutter
.form-check-input
position: absolute
margin-top: $form-check-input-margin-y
margin-left: -$form-check-input-gutter
&:disabled ~ .form-check-label
color: $text-muted
.form-check-label
margin-bottom: 0
// Override default `<label>` bottom margin
.form-check-inline
display: inline-flex
align-items: center
padding-left: 0
// Override base .form-check
margin-right: $form-check-inline-margin-x
// Undo .form-check-input defaults and add some `margin-right`.
.form-check-input
position: static
margin-top: 0
margin-right: $form-check-inline-input-margin-x
margin-left: 0
// Form validation
//
// Provide feedback to users when form field values are valid or invalid. Works
// primarily for client-side validation via scoped `:invalid` and `:valid`
// pseudo-classes but also includes `.is-invalid` and `.is-valid` classes for
// server side validation.
+form-validation-state("valid", $form-feedback-valid-color)
+form-validation-state("invalid", $form-feedback-invalid-color)
// Inline forms
//
// Make forms appear inline(-block) by adding the `.form-inline` class. Inline
// forms begin stacked on extra small (mobile) devices and then go inline when
// viewports reach <768px.
//
// Requires wrapping inputs and labels with `.form-group` for proper display of
// default HTML form controls and our custom form controls (e.g., input groups).
.form-inline
display: flex
flex-flow: row wrap
align-items: center
// Prevent shorter elements from growing to same height as others (e.g., small buttons growing to normal sized button height)
// Because we use flex, the initial sizing of checkboxes is collapsed and
// doesn't occupy the full-width (which is what we want for xs grid tier),
// so we force that here.
.form-check
width: 100%
// Kick in the inline
+media-breakpoint-up(sm)
label
display: flex
align-items: center
justify-content: center
margin-bottom: 0
// Inline-block all the things for "inline"
.form-group
display: flex
flex: 0 0 auto
flex-flow: row wrap
align-items: center
margin-bottom: 0
// Allow folks to *not* use `.form-group`
.form-control
display: inline-block
width: auto
// Prevent labels from stacking above inputs in `.form-group`
vertical-align: middle
// Make static controls behave like regular ones
.form-control-plaintext
display: inline-block
.input-group,
.custom-select
width: auto
// Remove default margin on radios/checkboxes that were used for stacking, and
// then undo the floating of radios and checkboxes to match.
.form-check
display: flex
align-items: center
justify-content: center
width: auto
padding-left: 0
.form-check-input
position: relative
margin-top: 0
margin-right: $form-check-input-margin-x
margin-left: 0
.custom-control
align-items: center
justify-content: center
.custom-control-label
margin-bottom: 0

View File

@@ -1,76 +0,0 @@
// Bootstrap functions
//
// Utility mixins and functions for evaluating source code across our variables, maps, and mixins.
// Ascending
// Used to evaluate Sass maps like our grid breakpoints.
=_assert-ascending($map, $map-name)
$prev-key: null
$prev-num: null
@each $key, $num in $map
@if $prev-num == null
// Do nothing
@else if not comparable($prev-num, $num)
@warn "Potentially invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} whose unit makes it incomparable to #{$prev-num}, the value of the previous key '#{$prev-key}' !"
@else if $prev-num >= $num
@warn "Invalid value for #{$map-name}: This map must be in ascending order, but key '#{$key}' has value #{$num} which isn't greater than #{$prev-num}, the value of the previous key '#{$prev-key}' !"
$prev-key: $key
$prev-num: $num
// Starts at zero
// Another grid mixin that ensures the min-width of the lowest breakpoint starts at 0.
=_assert-starts-at-zero($map)
$values: map-values($map)
$first-value: nth($values, 1)
@if $first-value != 0
@warn "First breakpoint in `$grid-breakpoints` must start at 0, but starts at #{$first-value}."
// Replace `$search` with `$replace` in `$string`
// Used on our SVG icon backgrounds for custom forms.
//
// @author Hugo Giraudel
// @param {String} $string - Initial string
// @param {String} $search - Substring to replace
// @param {String} $replace ('') - New value
// @return {String} - Updated string
@function str-replace($string, $search, $replace: "")
$index: str-index($string, $search)
@if $index
@return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace)
@return $string
// Color contrast
@function color-yiq($color)
$r: red($color)
$g: green($color)
$b: blue($color)
$yiq: ($r * 299 + $g * 587 + $b * 114) / 1000
@if $yiq >= $yiq-contrasted-threshold
@return $yiq-text-dark
@else
@return $yiq-text-light
// Retrieve color Sass maps
@function color($key: "blue")
@return map-get($colors, $key)
@function theme-color($key: "primary")
@return map-get($theme-colors, $key)
@function gray($key: "100")
@return map-get($grays, $key)
// Request a theme color level
@function theme-color-level($color-name: "primary", $level: 0)
$color: theme-color($color-name)
$color-base: if($level > 0, $black, $white)
$level: abs($level)
@return mix($color-base, $color, $level * $theme-color-interval)

View File

@@ -1,43 +0,0 @@
// Container widths
//
// Set the container width, and override it for fixed navbars in media queries.
@if $enable-grid-classes
.container
+make-container
+make-container-max-widths
// Fluid container
//
// Utilizes the mixin meant for fixed width containers, but with 100% width for
// fluid, full width layouts.
@if $enable-grid-classes
.container-fluid
+make-container
// Row
//
// Rows contain and clear the floats of your columns.
@if $enable-grid-classes
.row
+make-row
// Remove the negative margin from default .row, then the horizontal padding
// from all immediate children columns (to prevent runaway style inheritance).
.no-gutters
margin-right: 0
margin-left: 0
> .col,
> [class*="col-"]
padding-right: 0
padding-left: 0
// Columns
//
// Common styles for small and large grid columns
@if $enable-grid-classes
+make-grid-columns

View File

@@ -1,37 +0,0 @@
// Responsive images (ensure images don't scale beyond their parents)
//
// This is purposefully opt-in via an explicit class rather than being the default for all `<img>`s.
// We previously tried the "images are responsive by default" approach in Bootstrap v2,
// and abandoned it in Bootstrap v3 because it breaks lots of third-party widgets (including Google Maps)
// which weren't expecting the images within themselves to be involuntarily resized.
// See also https://github.com/twbs/bootstrap/issues/18178
.img-fluid
+img-fluid
// Image thumbnails
.img-thumbnail
padding: $thumbnail-padding
background-color: $thumbnail-bg
border: $thumbnail-border-width solid $thumbnail-border-color
+border-radius($thumbnail-border-radius)
+box-shadow($thumbnail-box-shadow)
// Keep them at most 100% wide
+img-fluid
//
// Figures
//
.figure
// Ensures the caption's text aligns with the image.
display: inline-block
.figure-img
margin-bottom: $spacer / 2
line-height: 1
.figure-caption
font-size: $figure-caption-font-size
color: $figure-caption-color

View File

@@ -1,159 +0,0 @@
// stylelint-disable selector-no-qualifying-type
//
// Base styles
//
.input-group
position: relative
display: flex
flex-wrap: wrap
// For form validation feedback
align-items: stretch
width: 100%
> .form-control,
> .custom-select,
> .custom-file
position: relative
// For focus state's z-index
flex: 1 1 auto
// Add width 1% and flex-basis auto to ensure that button will not wrap out
// the column. Applies to IE Edge+ and Firefox. Chrome does not require this.
width: 1%
margin-bottom: 0
+ .form-control,
+ .custom-select,
+ .custom-file
margin-left: -$input-border-width
// Bring the "active" form control to the top of surrounding elements
> .form-control:focus,
> .custom-select:focus,
> .custom-file .custom-file-input:focus ~ .custom-file-label
z-index: 3
> .form-control,
> .custom-select
&:not(:last-child)
+border-right-radius(0)
&:not(:first-child)
+border-left-radius(0)
// Custom file inputs have more complex markup, thus requiring different
// border-radius overrides.
> .custom-file
display: flex
align-items: center
&:not(:last-child) .custom-file-label,
&:not(:last-child) .custom-file-label::after
+border-right-radius(0)
&:not(:first-child) .custom-file-label
+border-left-radius(0)
// Prepend and append
//
// While it requires one extra layer of HTML for each, dedicated prepend and
// append elements allow us to 1) be less clever, 2) simplify our selectors, and
// 3) support HTML5 form validation.
.input-group-prepend,
.input-group-append
display: flex
// Ensure buttons are always above inputs for more visually pleasing borders.
// This isn't needed for `.input-group-text` since it shares the same border-color
// as our inputs.
.btn
position: relative
z-index: 2
.btn + .btn,
.btn + .input-group-text,
.input-group-text + .input-group-text,
.input-group-text + .btn
margin-left: -$input-border-width
.input-group-prepend
margin-right: -$input-border-width
.input-group-append
margin-left: -$input-border-width
// Textual addons
//
// Serves as a catch-all element for any text or radio/checkbox input you wish
// to prepend or append to an input.
.input-group-text
display: flex
align-items: center
padding: $input-padding-y $input-padding-x
margin-bottom: 0
// Allow use of <label> elements by overriding our default margin-bottom
font-size: $font-size-base
// Match inputs
font-weight: $font-weight-normal
line-height: $input-line-height
color: $input-group-addon-color
text-align: center
white-space: nowrap
background-color: $input-group-addon-bg
border: $input-border-width solid $input-group-addon-border-color
+border-radius($input-border-radius)
// Nuke default margins from checkboxes and radios to vertically center within.
input[type="radio"],
input[type="checkbox"]
margin-top: 0
// Sizing
//
// Remix the default form control sizing classes into new ones for easier
// manipulation.
.input-group-lg > .form-control,
.input-group-lg > .input-group-prepend > .input-group-text,
.input-group-lg > .input-group-append > .input-group-text,
.input-group-lg > .input-group-prepend > .btn,
.input-group-lg > .input-group-append > .btn
@extend .form-control-lg
.input-group-sm > .form-control,
.input-group-sm > .input-group-prepend > .input-group-text,
.input-group-sm > .input-group-append > .input-group-text,
.input-group-sm > .input-group-prepend > .btn,
.input-group-sm > .input-group-append > .btn
@extend .form-control-sm
// Prepend and append rounded corners
//
// These rulesets must come after the sizing ones to properly override sm and lg
// border-radius values when extending. They're more specific than we'd like
// with the `.input-group >` part, but without it, we cannot override the sizing.
.input-group > .input-group-prepend > .btn,
.input-group > .input-group-prepend > .input-group-text,
.input-group > .input-group-append:not(:last-child) > .btn,
.input-group > .input-group-append:not(:last-child) > .input-group-text,
.input-group > .input-group-append:last-child > .btn:not(:last-child):not(.dropdown-toggle),
.input-group > .input-group-append:last-child > .input-group-text:not(:last-child)
+border-right-radius(0)
.input-group > .input-group-append > .btn,
.input-group > .input-group-append > .input-group-text,
.input-group > .input-group-prepend:not(:first-child) > .btn,
.input-group > .input-group-prepend:not(:first-child) > .input-group-text,
.input-group > .input-group-prepend:first-child > .btn:not(:first-child),
.input-group > .input-group-prepend:first-child > .input-group-text:not(:first-child)
+border-left-radius(0)

View File

@@ -1,15 +0,0 @@
.jumbotron
padding: $jumbotron-padding ($jumbotron-padding / 2)
margin-bottom: $jumbotron-padding
background-color: $jumbotron-bg
+border-radius($border-radius-lg)
+media-breakpoint-up(sm)
padding: ($jumbotron-padding * 2) $jumbotron-padding
.jumbotron-fluid
padding-right: 0
padding-left: 0
+border-radius(0)

View File

@@ -1,109 +0,0 @@
// Base class
//
// Easily usable on <ul>, <ol>, or <div>.
.list-group
display: flex
flex-direction: column
// No need to set list-style: none; since .list-group-item is block level
padding-left: 0
// reset padding because ul and ol
margin-bottom: 0
// Interactive list items
//
// Use anchor or button elements instead of `li`s or `div`s to create interactive
// list items. Includes an extra `.active` modifier class for selected items.
.list-group-item-action
width: 100%
// For `<button>`s (anchors become 100% by default though)
color: $list-group-action-color
text-align: inherit
// For `<button>`s (anchors inherit)
// Hover state
+hover-focus
color: $list-group-action-hover-color
text-decoration: none
background-color: $list-group-hover-bg
&:active
color: $list-group-action-active-color
background-color: $list-group-action-active-bg
// Individual list items
//
// Use on `li`s or `div`s within the `.list-group` parent.
.list-group-item
position: relative
display: block
padding: $list-group-item-padding-y $list-group-item-padding-x
// Place the border on the list items and negative margin up for better styling
margin-bottom: -$list-group-border-width
background-color: $list-group-bg
border: $list-group-border-width solid $list-group-border-color
&:first-child
+border-top-radius($list-group-border-radius)
&:last-child
margin-bottom: 0
+border-bottom-radius($list-group-border-radius)
+hover-focus
z-index: 1
// Place hover/active items above their siblings for proper border styling
text-decoration: none
&.disabled,
&:disabled
color: $list-group-disabled-color
background-color: $list-group-disabled-bg
// Include both here for `<a>`s and `<button>`s
&.active
z-index: 2
// Place active items above their siblings for proper border styling
color: $list-group-active-color
background-color: $list-group-active-bg
border-color: $list-group-active-border-color
// Flush list items
//
// Remove borders and border-radius to keep list group items edge-to-edge. Most
// useful within other components (e.g., cards).
.list-group-flush
.list-group-item
border-right: 0
border-left: 0
+border-radius(0)
&:first-child
.list-group-item:first-child
border-top: 0
&:last-child
.list-group-item:last-child
border-bottom: 0
// Contextual variants
//
// Add modifier classes to change text and background color on individual items.
// Organizationally, this must come after the `:hover` states.
@each $color, $value in $theme-colors
+list-group-item-variant($color, theme-color-level($color, -9), theme-color-level($color, 6))

View File

@@ -1,6 +0,0 @@
.media
display: flex
align-items: flex-start
.media-body
flex: 1

View File

@@ -1,41 +0,0 @@
// Toggles
//
// Used in conjunction with global variables to enable certain theme features.
// Utilities
@import mixins/breakpoints
@import mixins/hover
@import mixins/image
@import mixins/badge
@import mixins/resize
@import mixins/screen-reader
@import mixins/size
@import mixins/reset-text
@import mixins/text-emphasis
@import mixins/text-hide
@import mixins/text-truncate
@import mixins/visibility
// // Components
@import mixins/alert
@import mixins/buttons
@import mixins/caret
@import mixins/pagination
@import mixins/lists
@import mixins/list-group
@import mixins/nav-divider
@import mixins/forms
@import mixins/table-row
// // Skins
@import mixins/background-variant
@import mixins/border-radius
@import mixins/box-shadow
@import mixins/gradients
@import mixins/transition
// // Layout
@import mixins/clearfix
@import mixins/grid-framework
@import mixins/grid
@import mixins/float

View File

@@ -1,175 +0,0 @@
// .modal-open - body class for killing the scroll
// .modal - container to scroll within
// .modal-dialog - positioning shell for the actual modal
// .modal-content - actual modal w/ bg and corners and stuff
// Kill the scroll on the body
.modal-open
overflow: hidden
// Container that the modal scrolls within
.modal
position: fixed
top: 0
right: 0
bottom: 0
left: 0
z-index: $zindex-modal
display: none
overflow: hidden
// Prevent Chrome on Windows from adding a focus outline. For details, see
// https://github.com/twbs/bootstrap/pull/10951.
outline: 0
// We deliberately don't use `-webkit-overflow-scrolling: touch;` due to a
// gnarly iOS Safari bug: https://bugs.webkit.org/show_bug.cgi?id=158342
// See also https://github.com/twbs/bootstrap/issues/17695
.modal-open &
overflow-x: hidden
overflow-y: auto
// Shell div to position the modal with bottom padding
.modal-dialog
position: relative
width: auto
margin: $modal-dialog-margin
// allow clicks to pass through for custom click handling to close modal
pointer-events: none
// When fading in the modal, animate it to slide down
.modal.fade &
+transition($modal-transition)
transform: translate(0, -25%)
.modal.show &
transform: translate(0, 0)
.modal-dialog-centered
display: flex
align-items: center
min-height: calc(100% - (#{$modal-dialog-margin} * 2))
// Actual modal
.modal-content
position: relative
display: flex
flex-direction: column
width: 100%
// Ensure `.modal-content` extends the full width of the parent `.modal-dialog`
// counteract the pointer-events: none; in the .modal-dialog
pointer-events: auto
background-color: $modal-content-bg
background-clip: padding-box
border: $modal-content-border-width solid $modal-content-border-color
+border-radius($modal-content-border-radius)
+box-shadow($modal-content-box-shadow-xs)
// Remove focus outline from opened modal
outline: 0
// Modal background
.modal-backdrop
position: fixed
top: 0
right: 0
bottom: 0
left: 0
z-index: $zindex-modal-backdrop
background-color: $modal-backdrop-bg
// Fade for backdrop
&.fade
opacity: 0
&.show
opacity: $modal-backdrop-opacity
// Modal header
// Top section of the modal w/ title and dismiss
.modal-header
display: flex
align-items: flex-start
// so the close btn always stays on the upper right corner
justify-content: space-between
// Put modal header elements (title and dismiss) on opposite ends
padding: $modal-header-padding
border-bottom: $modal-header-border-width solid $modal-header-border-color
+border-top-radius($modal-content-border-radius)
.close
padding: $modal-header-padding
// auto on the left force icon to the right even when there is no .modal-title
margin: (-$modal-header-padding) (-$modal-header-padding) (-$modal-header-padding) auto
// Title text within header
.modal-title
margin-bottom: 0
line-height: $modal-title-line-height
// Modal body
// Where all modal content resides (sibling of .modal-header and .modal-footer)
.modal-body
position: relative
// Enable `flex-grow: 1` so that the body take up as much space as possible
// when should there be a fixed height on `.modal-dialog`.
flex: 1 1 auto
padding: $modal-inner-padding
// Footer (for actions)
.modal-footer
display: flex
align-items: center
// vertically center
justify-content: flex-end
// Right align buttons with flex property because text-align doesn't work on flex items
padding: $modal-inner-padding
border-top: $modal-footer-border-width solid $modal-footer-border-color
// Easily place margin between footer elements
> :not(:first-child)
margin-left: .25rem
> :not(:last-child)
margin-right: .25rem
// Measure scrollbar width for padding body during modal show/hide
.modal-scrollbar-measure
position: absolute
top: -9999px
width: 50px
height: 50px
overflow: scroll
// Scale up the modal
+media-breakpoint-up(sm)
// Automatically set modal's width for larger viewports
.modal-dialog
max-width: $modal-md
margin: $modal-dialog-margin-y-sm-up auto
.modal-dialog-centered
min-height: calc(100% - (#{$modal-dialog-margin-y-sm-up} * 2))
.modal-content
+box-shadow($modal-content-box-shadow-sm-up)
.modal-sm
max-width: $modal-sm
+media-breakpoint-up(lg)
.modal-lg
max-width: $modal-lg

View File

@@ -1,99 +0,0 @@
// Base class
//
// Kickstart any navigation component with a set of style resets. Works with
// `<nav>`s or `<ul>`s.
.nav
display: flex
flex-wrap: wrap
padding-left: 0
margin-bottom: 0
list-style: none
.nav-link
display: block
padding: $nav-link-padding-y $nav-link-padding-x
+hover-focus
text-decoration: none
// Disabled state lightens text
&.disabled
color: $nav-link-disabled-color
//
// Tabs
//
.nav-tabs
border-bottom: $nav-tabs-border-width solid $nav-tabs-border-color
.nav-item
margin-bottom: -$nav-tabs-border-width
.nav-link
border: $nav-tabs-border-width solid transparent
+border-top-radius($nav-tabs-border-radius)
+hover-focus
border-color: $nav-tabs-link-hover-border-color
&.disabled
color: $nav-link-disabled-color
background-color: transparent
border-color: transparent
.nav-link.active,
.nav-item.show .nav-link
color: $nav-tabs-link-active-color
background-color: $nav-tabs-link-active-bg
border-color: $nav-tabs-link-active-border-color
.dropdown-menu
// Make dropdown border overlap tab border
margin-top: -$nav-tabs-border-width
// Remove the top rounded corners here since there is a hard edge above the menu
+border-top-radius(0)
//
// Pills
//
.nav-pills
.nav-link
+border-radius($nav-pills-border-radius)
.nav-link.active,
.show > .nav-link
color: $nav-pills-link-active-color
background-color: $nav-pills-link-active-bg
//
// Justified variants
//
.nav-fill
.nav-item
flex: 1 1 auto
text-align: center
.nav-justified
.nav-item
flex-basis: 0
flex-grow: 1
text-align: center
// Tabbable tabs
//
// Hide tabbable panes to start, show them when `.active`
.tab-content
> .tab-pane
display: none
> .active
display: block

View File

@@ -1,261 +0,0 @@
// Contents
//
// Navbar
// Navbar brand
// Navbar nav
// Navbar text
// Navbar divider
// Responsive navbar
// Navbar position
// Navbar themes
// Navbar
//
// Provide a static navbar from which we expand to create full-width, fixed, and
// other navbar variations.
.navbar
position: relative
display: flex
flex-wrap: wrap
// allow us to do the line break for collapsing content
align-items: center
justify-content: space-between
// space out brand from logo
padding: $navbar-padding-y $navbar-padding-x
// Because flex properties aren't inherited, we need to redeclare these first
// few properties so that content nested within behave properly.
> .container,
> .container-fluid
display: flex
flex-wrap: wrap
align-items: center
justify-content: space-between
// Navbar brand
//
// Used for brand, project, or site names.
.navbar-brand
display: inline-block
padding-top: $navbar-brand-padding-y
padding-bottom: $navbar-brand-padding-y
margin-right: $navbar-padding-x
font-size: $navbar-brand-font-size
line-height: inherit
white-space: nowrap
+hover-focus
text-decoration: none
// Navbar nav
//
// Custom navbar navigation (doesn't require `.nav`, but does make use of `.nav-link`).
.navbar-nav
display: flex
flex-direction: column
// cannot use `inherit` to get the `.navbar`s value
padding-left: 0
margin-bottom: 0
list-style: none
.nav-link
padding-right: 0
padding-left: 0
.dropdown-menu
position: static
float: none
// Navbar text
//
//
.navbar-text
display: inline-block
padding-top: $nav-link-padding-y
padding-bottom: $nav-link-padding-y
// Responsive navbar
//
// Custom styles for responsive collapsing and toggling of navbar contents.
// Powered by the collapse Bootstrap JavaScript plugin.
// When collapsed, prevent the toggleable navbar contents from appearing in
// the default flexbox row orientation. Requires the use of `flex-wrap: wrap`
// on the `.navbar` parent.
.navbar-collapse
flex-basis: 100%
flex-grow: 1
// For always expanded or extra full navbars, ensure content aligns itself
// properly vertically. Can be easily overridden with flex utilities.
align-items: center
// Button for toggling the navbar when in its collapsed state
.navbar-toggler
padding: $navbar-toggler-padding-y $navbar-toggler-padding-x
font-size: $navbar-toggler-font-size
line-height: 1
background-color: transparent
// remove default button style
border: $border-width solid transparent
// remove default button style
+border-radius($navbar-toggler-border-radius)
+hover-focus
text-decoration: none
// Opinionated: add "hand" cursor to non-disabled .navbar-toggler elements
&:not(:disabled):not(.disabled)
cursor: pointer
// Keep as a separate element so folks can easily override it with another icon
// or image file as needed.
.navbar-toggler-icon
display: inline-block
width: 1.5em
height: 1.5em
vertical-align: middle
content: ""
background: no-repeat center center
background-size: 100% 100%
// Generate series of `.navbar-expand-*` responsive classes for configuring
// where your navbar collapses.
.navbar-expand
@each $breakpoint in map-keys($grid-breakpoints)
$next: breakpoint-next($breakpoint, $grid-breakpoints)
$infix: breakpoint-infix($next, $grid-breakpoints)
&#{$infix}
+media-breakpoint-down($breakpoint)
> .container,
> .container-fluid
padding-right: 0
padding-left: 0
+media-breakpoint-up($next)
flex-flow: row nowrap
justify-content: flex-start
.navbar-nav
flex-direction: row
.dropdown-menu
position: absolute
.nav-link
padding-right: $navbar-nav-link-padding-x
padding-left: $navbar-nav-link-padding-x
// For nesting containers, have to redeclare for alignment purposes
> .container,
> .container-fluid
flex-wrap: nowrap
.navbar-collapse
display: flex !important
// stylelint-disable-line declaration-no-important
// Changes flex-bases to auto because of an IE10 bug
flex-basis: auto
.navbar-toggler
display: none
// Navbar themes
//
// Styles for switching between navbars with light or dark background.
// Dark links against a light background
.navbar-light
.navbar-brand
color: $navbar-light-active-color
+hover-focus
color: $navbar-light-active-color
.navbar-nav
.nav-link
color: $navbar-light-color
+hover-focus
color: $navbar-light-hover-color
&.disabled
color: $navbar-light-disabled-color
.show > .nav-link,
.active > .nav-link,
.nav-link.show,
.nav-link.active
color: $navbar-light-active-color
.navbar-toggler
color: $navbar-light-color
border-color: $navbar-light-toggler-border-color
.navbar-toggler-icon
background-image: $navbar-light-toggler-icon-bg
.navbar-text
color: $navbar-light-color
a
color: $navbar-light-active-color
+hover-focus
color: $navbar-light-active-color
// White links against a dark background
.navbar-dark
.navbar-brand
color: $navbar-dark-active-color
+hover-focus
color: $navbar-dark-active-color
.navbar-nav
.nav-link
color: $navbar-dark-color
+hover-focus
color: $navbar-dark-hover-color
&.disabled
color: $navbar-dark-disabled-color
.show > .nav-link,
.active > .nav-link,
.nav-link.show,
.nav-link.active
color: $navbar-dark-active-color
.navbar-toggler
color: $navbar-dark-color
border-color: $navbar-dark-toggler-border-color
.navbar-toggler-icon
background-image: $navbar-dark-toggler-icon-bg
.navbar-text
color: $navbar-dark-color
a
color: $navbar-dark-active-color
+hover-focus
color: $navbar-dark-active-color

View File

@@ -1,67 +0,0 @@
.pagination
display: flex
+list-unstyled
+border-radius
.page-link
position: relative
display: block
padding: $pagination-padding-y $pagination-padding-x
margin-left: -$pagination-border-width
line-height: $pagination-line-height
color: $pagination-color
background-color: $pagination-bg
border: $pagination-border-width solid $pagination-border-color
&:hover
z-index: 2
color: $pagination-hover-color
text-decoration: none
background-color: $pagination-hover-bg
border-color: $pagination-hover-border-color
&:focus
z-index: 2
outline: $pagination-focus-outline
box-shadow: $pagination-focus-box-shadow
// Opinionated: add "hand" cursor to non-disabled .page-link elements
&:not(:disabled):not(.disabled)
cursor: pointer
.page-item
&:first-child
.page-link
margin-left: 0
+border-left-radius($border-radius)
&:last-child
.page-link
+border-right-radius($border-radius)
&.active .page-link
z-index: 1
color: $pagination-active-color
background-color: $pagination-active-bg
border-color: $pagination-active-border-color
&.disabled .page-link
color: $pagination-disabled-color
pointer-events: none
// Opinionated: remove the "hand" cursor set previously for .page-link
cursor: auto
background-color: $pagination-disabled-bg
border-color: $pagination-disabled-border-color
//
// Sizing
//
.pagination-lg
+pagination-size($pagination-padding-y-lg, $pagination-padding-x-lg, $font-size-lg, $line-height-lg, $border-radius-lg)
.pagination-sm
+pagination-size($pagination-padding-y-sm, $pagination-padding-x-sm, $font-size-sm, $line-height-sm, $border-radius-sm)

View File

@@ -1,165 +0,0 @@
.popover
position: absolute
top: 0
left: 0
z-index: $zindex-popover
display: block
max-width: $popover-max-width
// Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element.
// So reset our font and text properties to avoid inheriting weird values.
+reset-text
font-size: $popover-font-size
// Allow breaking very long words so they don't overflow the popover's bounds
word-wrap: break-word
background-color: $popover-bg
background-clip: padding-box
border: $popover-border-width solid $popover-border-color
+border-radius($popover-border-radius)
+box-shadow($popover-box-shadow)
.arrow
position: absolute
display: block
width: $popover-arrow-width
height: $popover-arrow-height
margin: 0 $border-radius-lg
&::before,
&::after
position: absolute
display: block
content: ""
border-color: transparent
border-style: solid
.bs-popover-top
margin-bottom: $popover-arrow-height
.arrow
bottom: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1)
.arrow::before,
.arrow::after
border-width: $popover-arrow-height ($popover-arrow-width / 2) 0
.arrow::before
bottom: 0
border-top-color: $popover-arrow-outer-color
.arrow::after
bottom: $popover-border-width
border-top-color: $popover-arrow-color
.bs-popover-right
margin-left: $popover-arrow-height
.arrow
left: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1)
width: $popover-arrow-height
height: $popover-arrow-width
margin: $border-radius-lg 0
// make sure the arrow does not touch the popover's rounded corners
.arrow::before,
.arrow::after
border-width: ($popover-arrow-width / 2) $popover-arrow-height ($popover-arrow-width / 2) 0
.arrow::before
left: 0
border-right-color: $popover-arrow-outer-color
.arrow::after
left: $popover-border-width
border-right-color: $popover-arrow-color
.bs-popover-bottom
margin-top: $popover-arrow-height
.arrow
top: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1)
.arrow::before,
.arrow::after
border-width: 0 ($popover-arrow-width / 2) $popover-arrow-height ($popover-arrow-width / 2)
.arrow::before
top: 0
border-bottom-color: $popover-arrow-outer-color
.arrow::after
top: $popover-border-width
border-bottom-color: $popover-arrow-color
// This will remove the popover-header's border just below the arrow
.popover-header::before
position: absolute
top: 0
left: 50%
display: block
width: $popover-arrow-width
margin-left: $popover-arrow-width / -2
content: ""
border-bottom: $popover-border-width solid $popover-header-bg
.bs-popover-left
margin-right: $popover-arrow-height
.arrow
right: calc((#{$popover-arrow-height} + #{$popover-border-width}) * -1)
width: $popover-arrow-height
height: $popover-arrow-width
margin: $border-radius-lg 0
// make sure the arrow does not touch the popover's rounded corners
.arrow::before,
.arrow::after
border-width: ($popover-arrow-width / 2) 0 ($popover-arrow-width / 2) $popover-arrow-height
.arrow::before
right: 0
border-left-color: $popover-arrow-outer-color
.arrow::after
right: $popover-border-width
border-left-color: $popover-arrow-color
.bs-popover-auto
&[x-placement^="top"]
@extend .bs-popover-top
&[x-placement^="right"]
@extend .bs-popover-right
&[x-placement^="bottom"]
@extend .bs-popover-bottom
&[x-placement^="left"]
@extend .bs-popover-left
// Offset the popover to account for the popover arrow
.popover-header
padding: $popover-header-padding-y $popover-header-padding-x
margin-bottom: 0
// Reset the default from Reboot
font-size: $font-size-base
color: $popover-header-color
background-color: $popover-header-bg
border-bottom: $popover-border-width solid darken($popover-header-bg, 5%)
$offset-border-width: calc(#{$border-radius-lg} - #{$popover-border-width})
+border-top-radius($offset-border-width)
&:empty
display: none
.popover-body
padding: $popover-body-padding-y $popover-body-padding-x
color: $popover-body-color

View File

@@ -1,124 +0,0 @@
// stylelint-disable declaration-no-important, selector-no-qualifying-type
// Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css
// ==========================================================================
// Print styles.
// Inlined to avoid the additional HTTP request:
// https://www.phpied.com/delay-loading-your-print-css/
// ==========================================================================
@if $enable-print-styles
@media print
*,
*::before,
*::after
// Bootstrap specific; comment out `color` and `background`
//color: $black !important; // Black prints faster
text-shadow: none !important
//background: transparent !important;
box-shadow: none !important
a
&:not(.btn)
text-decoration: underline
// Bootstrap specific; comment the following selector out
//a[href]::after {
// content: " (" attr(href) ")";
//}
abbr[title]::after
content: " (" attr(title) ")"
// Bootstrap specific; comment the following selector out
//
// Don't show links that are fragment identifiers,
// or use the `javascript:` pseudo protocol
//
//a[href^="#"]::after,
//a[href^="javascript:"]::after {
// content: "";
//}
pre
white-space: pre-wrap !important
pre,
blockquote
border: $border-width solid $gray-500
// Bootstrap custom code; using `$border-width` instead of 1px
page-break-inside: avoid
//
// Printing Tables:
// http://css-discuss.incutio.com/wiki/Printing_Tables
//
thead
display: table-header-group
tr,
img
page-break-inside: avoid
p,
h2,
h3
orphans: 3
widows: 3
h2,
h3
page-break-after: avoid
// Bootstrap specific changes start
// Specify a size and min-width to make printing closer across browsers.
// We don't set margin here because it breaks `size` in Chrome. We also
// don't use `!important` on `size` as it breaks in Chrome.
@page
size: $print-page-size
body
min-width: $print-body-min-width !important
.container
min-width: $print-body-min-width !important
// Bootstrap components
.navbar
display: none
.badge
border: $border-width solid $black
.table
border-collapse: collapse !important
td,
th
background-color: $white !important
.table-bordered
th,
td
border: 1px solid $gray-300 !important
.table-dark
color: inherit
th,
td,
thead th,
tbody + tbody
border-color: $table-border-color
.table .thead-dark th
color: inherit
border-color: $table-border-color
// Bootstrap specific changes end

View File

@@ -1,37 +0,0 @@
@keyframes progress-bar-stripes
from
background-position: $progress-height 0
to
background-position: 0 0
.progress
display: flex
height: $progress-height
overflow: hidden
// force rounded corners by cropping it
font-size: $progress-font-size
background-color: $progress-bg
+border-radius($progress-border-radius)
+box-shadow($progress-box-shadow)
.progress-bar
display: flex
flex-direction: column
justify-content: center
color: $progress-bar-color
text-align: center
white-space: nowrap
background-color: $progress-bar-bg
+transition($progress-bar-transition)
.progress-bar-striped
+gradient-striped
background-size: $progress-height $progress-height
.progress-bar-animated
animation: progress-bar-stripes $progress-bar-animation-timing

View File

@@ -1,513 +0,0 @@
// stylelint-disable at-rule-no-vendor-prefix, declaration-no-important, selector-no-qualifying-type, property-no-vendor-prefix
// Reboot
//
// Normalization of HTML elements, manually forked from Normalize.css to remove
// styles targeting irrelevant browsers while applying new styles.
//
// Normalize is licensed MIT. https://github.com/necolas/normalize.css
// Document
//
// 1. Change from `box-sizing: content-box` so that `width` is not affected by `padding` or `border`.
// 2. Change the default font family in all browsers.
// 3. Correct the line height in all browsers.
// 4. Prevent adjustments of font size after orientation changes in IE on Windows Phone and in iOS.
// 5. Setting @viewport causes scrollbars to overlap content in IE11 and Edge, so
// we force a non-overlapping, non-auto-hiding scrollbar to counteract.
// 6. Change the default tap highlight to be completely transparent in iOS.
*,
*::before,
*::after
box-sizing: border-box
// 1
html
font-family: sans-serif
// 2
line-height: 1.15
// 3
-webkit-text-size-adjust: 100%
// 4
-ms-text-size-adjust: 100%
// 4
-ms-overflow-style: scrollbar
// 5
-webkit-tap-highlight-color: rgba($black, 0)
// 6
// IE10+ doesn't honor `<meta name="viewport">` in some cases.
@at-root
@-ms-viewport
width: device-width
// stylelint-disable selector-list-comma-newline-after
// Shim for "new" HTML5 structural elements to display correctly (IE10, older browsers)
article, aside, figcaption, figure, footer, header, hgroup, main, nav, section
display: block
// stylelint-enable selector-list-comma-newline-after
// Body
//
// 1. Remove the margin in all browsers.
// 2. As a best practice, apply a default `background-color`.
// 3. Set an explicit initial text-align value so that we can later use the
// the `inherit` value on things like `<th>` elements.
body
margin: 0
// 1
font-family: $font-family-base
font-size: $font-size-base
font-weight: $font-weight-base
line-height: $line-height-base
color: $body-color
text-align: left
// 3
background-color: $body-bg
// 2
// Suppress the focus outline on elements that cannot be accessed via keyboard.
// This prevents an unwanted focus outline from appearing around elements that
// might still respond to pointer events.
//
// Credit: https://github.com/suitcss/base
[tabindex="-1"]:focus
outline: 0 !important
// Content grouping
//
// 1. Add the correct box sizing in Firefox.
// 2. Show the overflow in Edge and IE.
hr
box-sizing: content-box
// 1
height: 0
// 1
overflow: visible
// 2
//
// Typography
//
// Remove top margins from headings
//
// By default, `<h1>`-`<h6>` all receive top and bottom margins. We nuke the top
// margin for easier control within type scales as it avoids margin collapsing.
// stylelint-disable selector-list-comma-newline-after
h1, h2, h3, h4, h5, h6
margin-top: 0
margin-bottom: $headings-margin-bottom
// stylelint-enable selector-list-comma-newline-after
// Reset margins on paragraphs
//
// Similarly, the top margin on `<p>`s get reset. However, we also reset the
// bottom margin to use `rem` units instead of `em`.
p
margin-top: 0
margin-bottom: $paragraph-margin-bottom
// Abbreviations
//
// 1. Remove the bottom border in Firefox 39-.
// 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
// 3. Add explicit cursor to indicate changed behavior.
// 4. Duplicate behavior to the data-* attribute for our tooltip plugin
abbr[title],
abbr[data-original-title]
// 4
text-decoration: underline
// 2
text-decoration: underline dotted
// 2
cursor: help
// 3
border-bottom: 0
// 1
address
margin-bottom: 1rem
font-style: normal
line-height: inherit
ol,
ul,
dl
margin-top: 0
margin-bottom: 1rem
ol ol,
ul ul,
ol ul,
ul ol
margin-bottom: 0
dt
font-weight: $dt-font-weight
dd
margin-bottom: .5rem
margin-left: 0
// Undo browser default
blockquote
margin: 0 0 1rem
dfn
font-style: italic
// Add the correct font style in Android 4.3-
// stylelint-disable font-weight-notation
b,
strong
font-weight: bolder
// Add the correct font weight in Chrome, Edge, and Safari
// stylelint-enable font-weight-notation
small
font-size: 80%
// Add the correct font size in all browsers
//
// Prevent `sub` and `sup` elements from affecting the line height in
// all browsers.
//
sub,
sup
position: relative
font-size: 75%
line-height: 0
vertical-align: baseline
sub
bottom: -.25em
sup
top: -.5em
//
// Links
//
a
color: $link-color
text-decoration: $link-decoration
background-color: transparent
// Remove the gray background on active links in IE 10.
-webkit-text-decoration-skip: objects
// Remove gaps in links underline in iOS 8+ and Safari 8+.
+hover
color: $link-hover-color
text-decoration: $link-hover-decoration
// And undo these styles for placeholder links/named anchors (without href)
// which have not been made explicitly keyboard-focusable (without tabindex).
// It would be more straightforward to just use a[href] in previous block, but that
// causes specificity issues in many other styles that are too complex to fix.
// See https://github.com/twbs/bootstrap/issues/19402
a:not([href]):not([tabindex])
color: inherit
text-decoration: none
+hover-focus
color: inherit
text-decoration: none
&:focus
outline: 0
//
// Code
//
pre,
code,
kbd,
samp
font-family: $font-family-monospace
font-size: 1em
// Correct the odd `em` font sizing in all browsers.
pre
// Remove browser default top margin
margin-top: 0
// Reset browser default of `1em` to use `rem`s
margin-bottom: 1rem
// Don't allow content to break outside
overflow: auto
// We have @viewport set which causes scrollbars to overlap content in IE11 and Edge, so
// we force a non-overlapping, non-auto-hiding scrollbar to counteract.
-ms-overflow-style: scrollbar
//
// Figures
//
figure
// Apply a consistent margin strategy (matches our type styles).
margin: 0 0 1rem
//
// Images and content
//
img
vertical-align: middle
border-style: none
// Remove the border on images inside links in IE 10-.
svg:not(:root)
overflow: hidden
// Hide the overflow in IE
vertical-align: middle
//
// Tables
//
table
border-collapse: collapse
// Prevent double borders
caption
padding-top: $table-cell-padding
padding-bottom: $table-cell-padding
color: $table-caption-color
text-align: left
caption-side: bottom
th
// Matches default `<td>` alignment by inheriting from the `<body>`, or the
// closest parent with a set `text-align`.
text-align: inherit
//
// Forms
//
label
// Allow labels to use `margin` for spacing.
display: inline-block
margin-bottom: $label-margin-bottom
// Remove the default `border-radius` that macOS Chrome adds.
//
// Details at https://github.com/twbs/bootstrap/issues/24093
button
border-radius: 0
// Work around a Firefox/IE bug where the transparent `button` background
// results in a loss of the default `button` focus styles.
//
// Credit: https://github.com/suitcss/base/
button:focus
outline: 1px dotted
outline: 5px auto -webkit-focus-ring-color
input,
button,
select,
optgroup,
textarea
margin: 0
// Remove the margin in Firefox and Safari
font-family: inherit
font-size: inherit
line-height: inherit
button,
input
overflow: visible
// Show the overflow in Edge
button,
select
text-transform: none
// Remove the inheritance of text transform in Firefox
// 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
// controls in Android 4.
// 2. Correct the inability to style clickable types in iOS and Safari.
button,
html [type="button"],
[type="reset"],
[type="submit"]
-webkit-appearance: button
// 2
// Remove inner border and padding from Firefox, but don't restore the outline like Normalize.
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner
padding: 0
border-style: none
input[type="radio"],
input[type="checkbox"]
box-sizing: border-box
// 1. Add the correct box sizing in IE 10-
padding: 0
// 2. Remove the padding in IE 10-
input[type="date"],
input[type="time"],
input[type="datetime-local"],
input[type="month"]
// Remove the default appearance of temporal inputs to avoid a Mobile Safari
// bug where setting a custom line-height prevents text from being vertically
// centered within the input.
// See https://bugs.webkit.org/show_bug.cgi?id=139848
// and https://github.com/twbs/bootstrap/issues/11266
-webkit-appearance: listbox
textarea
overflow: auto
// Remove the default vertical scrollbar in IE.
// Textareas should really only resize vertically so they don't break their (horizontal) containers.
resize: vertical
fieldset
// Browsers set a default `min-width: min-content;` on fieldsets,
// unlike e.g. `<div>`s, which have `min-width: 0;` by default.
// So we reset that to ensure fieldsets behave more like a standard block element.
// See https://github.com/twbs/bootstrap/issues/12359
// and https://html.spec.whatwg.org/multipage/#the-fieldset-and-legend-elements
min-width: 0
// Reset the default outline behavior of fieldsets so they don't affect page layout.
padding: 0
margin: 0
border: 0
// 1. Correct the text wrapping in Edge and IE.
// 2. Correct the color inheritance from `fieldset` elements in IE.
legend
display: block
width: 100%
max-width: 100%
// 1
padding: 0
margin-bottom: .5rem
font-size: 1.5rem
line-height: inherit
color: inherit
// 2
white-space: normal
// 1
progress
vertical-align: baseline
// Add the correct vertical alignment in Chrome, Firefox, and Opera.
// Correct the cursor style of increment and decrement buttons in Chrome.
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button
height: auto
[type="search"]
// This overrides the extra rounded corners on search inputs in iOS so that our
// `.form-control` class can properly style them. Note that this cannot simply
// be added to `.form-control` as it's not specific enough. For details, see
// https://github.com/twbs/bootstrap/issues/11586.
outline-offset: -2px
// 2. Correct the outline style in Safari.
-webkit-appearance: none
//
// Remove the inner padding and cancel buttons in Chrome and Safari on macOS.
//
[type="search"]::-webkit-search-cancel-button,
[type="search"]::-webkit-search-decoration
-webkit-appearance: none
//
// 1. Correct the inability to style clickable types in iOS and Safari.
// 2. Change font properties to `inherit` in Safari.
//
\::-webkit-file-upload-button
font: inherit
// 2
-webkit-appearance: button
// 1
//
// Correct element displays
//
output
display: inline-block
summary
display: list-item
// Add the correct display in all browsers
cursor: pointer
template
display: none
// Add the correct display in IE
// Always hide an element with the `hidden` HTML attribute (from PureCSS).
// Needed for proper display in IE 10-.
[hidden]
display: none !important

View File

@@ -1,15 +0,0 @@
\:root
// Custom variable values only support SassScript inside `#{}`.
@each $color, $value in $colors
--#{$color}: #{$value}
@each $color, $value in $theme-colors
--#{$color}: #{$value}
@each $bp, $value in $grid-breakpoints
--breakpoint-#{$bp}: #{$value}
// Use `inspect` for lists so that quoted items keep the quotes.
// See https://github.com/sass/sass/issues/2383#issuecomment-336349172
--font-family-sans-serif: #{inspect($font-family-sans-serif)}
--font-family-monospace: #{inspect($font-family-monospace)}

View File

@@ -1,149 +0,0 @@
//
// Basic Bootstrap table
//
.table
width: 100%
max-width: 100%
margin-bottom: $spacer
background-color: $table-bg
// Reset for nesting within parents with `background-color`.
th,
td
padding: $table-cell-padding
vertical-align: top
border-top: $table-border-width solid $table-border-color
thead th
vertical-align: bottom
border-bottom: (2 * $table-border-width) solid $table-border-color
tbody + tbody
border-top: (2 * $table-border-width) solid $table-border-color
.table
background-color: $body-bg
//
// Condensed table w/ half padding
//
.table-sm
th,
td
padding: $table-cell-padding-sm
// Border versions
//
// Add or remove borders all around the table and between all the columns.
.table-bordered
border: $table-border-width solid $table-border-color
th,
td
border: $table-border-width solid $table-border-color
thead
th,
td
border-bottom-width: 2 * $table-border-width
.table-borderless
th,
td,
thead th,
tbody + tbody
border: 0
// Zebra-striping
//
// Default zebra-stripe styles (alternating gray and transparent backgrounds)
.table-striped
tbody tr:nth-of-type(#{$table-striped-order})
background-color: $table-accent-bg
// Hover effect
//
// Placed here since it has to come after the potential zebra striping
.table-hover
tbody tr
+hover
background-color: $table-hover-bg
// Table backgrounds
//
// Exact selectors below required to override `.table-striped` and prevent
// inheritance to nested tables.
@each $color, $value in $theme-colors
+table-row-variant($color, theme-color-level($color, -9))
+table-row-variant(active, $table-active-bg)
// Dark styles
//
// Same table markup, but inverted color scheme: dark background and light text.
// stylelint-disable-next-line no-duplicate-selectors
.table
.thead-dark
th
color: $table-dark-color
background-color: $table-dark-bg
border-color: $table-dark-border-color
.thead-light
th
color: $table-head-color
background-color: $table-head-bg
border-color: $table-border-color
.table-dark
color: $table-dark-color
background-color: $table-dark-bg
th,
td,
thead th
border-color: $table-dark-border-color
&.table-bordered
border: 0
&.table-striped
tbody tr:nth-of-type(odd)
background-color: $table-dark-accent-bg
&.table-hover
tbody tr
+hover
background-color: $table-dark-hover-bg
// Responsive tables
//
// Generate series of `.table-responsive-*` classes for configuring the screen
// size of where your table will overflow.
.table-responsive
@each $breakpoint in map-keys($grid-breakpoints)
$next: breakpoint-next($breakpoint, $grid-breakpoints)
$infix: breakpoint-infix($next, $grid-breakpoints)
&#{$infix}
+media-breakpoint-down($breakpoint)
display: block
width: 100%
overflow-x: auto
-webkit-overflow-scrolling: touch
-ms-overflow-style: -ms-autohiding-scrollbar
// See https://github.com/twbs/bootstrap/pull/10057
// Prevent double border on horizontal scroll due to use of `display: block;`
> .table-bordered
border: 0

View File

@@ -1,102 +0,0 @@
// Base class
.tooltip
position: absolute
z-index: $zindex-tooltip
display: block
margin: $tooltip-margin
// Our parent element can be arbitrary since tooltips are by default inserted as a sibling of their target element.
// So reset our font and text properties to avoid inheriting weird values.
+reset-text
font-size: $tooltip-font-size
// Allow breaking very long words so they don't overflow the tooltip's bounds
word-wrap: break-word
opacity: 0
&.show
opacity: $tooltip-opacity
.arrow
position: absolute
display: block
width: $tooltip-arrow-width
height: $tooltip-arrow-height
&::before
position: absolute
content: ""
border-color: transparent
border-style: solid
.bs-tooltip-top
padding: $tooltip-arrow-height 0
.arrow
bottom: 0
&::before
top: 0
border-width: $tooltip-arrow-height ($tooltip-arrow-width / 2) 0
border-top-color: $tooltip-arrow-color
.bs-tooltip-right
padding: 0 $tooltip-arrow-height
.arrow
left: 0
width: $tooltip-arrow-height
height: $tooltip-arrow-width
&::before
right: 0
border-width: ($tooltip-arrow-width / 2) $tooltip-arrow-height ($tooltip-arrow-width / 2) 0
border-right-color: $tooltip-arrow-color
.bs-tooltip-bottom
padding: $tooltip-arrow-height 0
.arrow
top: 0
&::before
bottom: 0
border-width: 0 ($tooltip-arrow-width / 2) $tooltip-arrow-height
border-bottom-color: $tooltip-arrow-color
.bs-tooltip-left
padding: 0 $tooltip-arrow-height
.arrow
right: 0
width: $tooltip-arrow-height
height: $tooltip-arrow-width
&::before
left: 0
border-width: ($tooltip-arrow-width / 2) 0 ($tooltip-arrow-width / 2) $tooltip-arrow-height
border-left-color: $tooltip-arrow-color
.bs-tooltip-auto
&[x-placement^="top"]
@extend .bs-tooltip-top
&[x-placement^="right"]
@extend .bs-tooltip-right
&[x-placement^="bottom"]
@extend .bs-tooltip-bottom
&[x-placement^="left"]
@extend .bs-tooltip-left
// Wrapper for the tooltip content
.tooltip-inner
max-width: $tooltip-max-width
padding: $tooltip-padding-y $tooltip-padding-x
color: $tooltip-color
text-align: center
background-color: $tooltip-bg
+border-radius($tooltip-border-radius)

View File

@@ -1,18 +0,0 @@
// stylelint-disable selector-no-qualifying-type
.fade
+transition($transition-fade)
&:not(.show)
opacity: 0
.collapse
&:not(.show)
display: none
.collapsing
position: relative
height: 0
overflow: hidden
+transition($transition-collapse)

View File

@@ -1,123 +0,0 @@
// stylelint-disable declaration-no-important, selector-list-comma-newline-after
//
// Headings
//
h1, h2, h3, h4, h5, h6,
.h1, .h2, .h3, .h4, .h5, .h6
margin-bottom: $headings-margin-bottom
font-family: $headings-font-family
font-weight: $headings-font-weight
line-height: $headings-line-height
color: $headings-color
h1, .h1
font-size: $h1-font-size
h2, .h2
font-size: $h2-font-size
h3, .h3
font-size: $h3-font-size
h4, .h4
font-size: $h4-font-size
h5, .h5
font-size: $h5-font-size
h6, .h6
font-size: $h6-font-size
.lead
font-size: $lead-font-size
font-weight: $lead-font-weight
// Type display classes
.display-1
font-size: $display1-size
font-weight: $display1-weight
line-height: $display-line-height
.display-2
font-size: $display2-size
font-weight: $display2-weight
line-height: $display-line-height
.display-3
font-size: $display3-size
font-weight: $display3-weight
line-height: $display-line-height
.display-4
font-size: $display4-size
font-weight: $display4-weight
line-height: $display-line-height
//
// Horizontal rules
//
hr
margin-top: $hr-margin-y
margin-bottom: $hr-margin-y
border: 0
border-top: $hr-border-width solid $hr-border-color
//
// Emphasis
//
small,
.small
font-size: $small-font-size
font-weight: $font-weight-normal
mark,
.mark
padding: $mark-padding
background-color: $mark-bg
//
// Lists
//
.list-unstyled
+list-unstyled
// Inline turns list items into inline-block
.list-inline
+list-unstyled
.list-inline-item
display: inline-block
&:not(:last-child)
margin-right: $list-inline-padding
//
// Misc
//
// Builds on `abbr`
.initialism
font-size: 90%
text-transform: uppercase
// Blockquotes
.blockquote
margin-bottom: $spacer
font-size: $blockquote-font-size
.blockquote-footer
display: block
font-size: 80%
// back to default font-size
color: $blockquote-small-color
&::before
content: "\2014 \00A0"
// em dash, nbsp

View File

@@ -1,15 +0,0 @@
@import utilities/align
@import utilities/background
@import utilities/borders
@import utilities/clearfix
@import utilities/display
@import utilities/embed
@import utilities/flex
@import utilities/float
@import utilities/position
@import utilities/screenreaders
@import utilities/shadows
@import utilities/sizing
@import utilities/spacing
@import utilities/text
@import utilities/visibility

Some files were not shown because too many files have changed in this diff Show More