diff --git a/.gitignore b/.gitignore index b9623fc..0aacd71 100644 --- a/.gitignore +++ b/.gitignore @@ -3,9 +3,12 @@ .coverage *.pyc __pycache__ +*.js.map +*.css.map /cloud/templates/ /cloud/static/assets/css/ +/cloud/static/assets/js/bootstrap.min.js node_modules/ /config_local.py diff --git a/gulpfile.js b/gulpfile.js index 0245b31..5d2c110 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,5 +1,6 @@ var argv = require('minimist')(process.argv.slice(2)); var autoprefixer = require('gulp-autoprefixer'); +var cache = require('gulp-cached'); var chmod = require('gulp-chmod'); var concat = require('gulp-concat'); var git = require('gulp-git'); @@ -11,16 +12,16 @@ var plumber = require('gulp-plumber'); var rename = require('gulp-rename'); var sass = require('gulp-sass'); var sourcemaps = require('gulp-sourcemaps'); -var uglify = require('gulp-uglify'); -var cache = require('gulp-cached'); +var uglify = require('gulp-uglify-es').default; var enabled = { uglify: argv.production, - maps: argv.production, + maps: !argv.production, failCheck: !argv.production, prettyPug: !argv.production, cachify: !argv.production, cleanup: argv.production, + chmod: argv.production, }; var destination = { @@ -29,6 +30,12 @@ var destination = { js: 'cloud/static/assets/js', } +var source = { + pillar: '../pillar/', + bootstrap: 'node_modules/bootstrap/', + popper: 'node_modules/popper.js/' +} + /* CSS */ gulp.task('styles', function() { @@ -73,7 +80,7 @@ gulp.task('scripts', function() { .pipe(gulpif(enabled.uglify, uglify())) .pipe(rename({suffix: '.min'})) .pipe(gulpif(enabled.maps, sourcemaps.write("."))) - .pipe(chmod(644)) + .pipe(gulpif(enabled.chmod, chmod(644))) .pipe(gulp.dest(destination.js)) .pipe(gulpif(argv.livereload, livereload())); }); @@ -88,12 +95,34 @@ gulp.task('scripts_concat_tutti', function() { .pipe(concat("tutti.min.js")) .pipe(gulpif(enabled.uglify, uglify())) .pipe(gulpif(enabled.maps, sourcemaps.write("."))) - .pipe(chmod(644)) + .pipe(gulpif(enabled.chmod, chmod(644))) .pipe(gulp.dest(destination.js)) .pipe(gulpif(argv.livereload, livereload())); }); +// Combine all needed Bootstrap JavaScript into a single file. +gulp.task('scripts_concat_bootstrap', function() { + + 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(toUglify) + .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' gulp.task('watch',function() { @@ -103,6 +132,8 @@ gulp.task('watch',function() { } gulp.watch('src/styles/**/*.sass',['styles']); + gulp.watch(source.pillar + 'src/styles/**/*.sass',['styles']); + gulp.watch('src/templates/**/*.pug',['templates']); gulp.watch('src/scripts/*.js',['scripts']); gulp.watch('src/scripts/tutti/**/*.js',['scripts_concat_tutti']); @@ -125,4 +156,5 @@ gulp.task('cleanup', function() { // Run 'gulp' to build everything at once var tasks = []; if (enabled.cleanup) tasks.push('cleanup'); -gulp.task('default', tasks.concat(['styles', 'templates', 'scripts', 'scripts_concat_tutti'])); + +gulp.task('default', tasks.concat(['styles', 'templates', 'scripts', 'scripts_concat_tutti', 'scripts_concat_bootstrap'])); diff --git a/package.json b/package.json index f988f0b..1894f5d 100644 --- a/package.json +++ b/package.json @@ -8,20 +8,24 @@ }, "devDependencies": { "gulp": "~3.9.1", - "gulp-autoprefixer": "~2.3.1", - "gulp-cached": "~1.1.0", - "gulp-chmod": "~1.3.0", - "gulp-concat": "~2.6.0", - "gulp-if": "^2.0.1", - "gulp-git": "~2.4.2", - "gulp-pug": "~3.2.0", - "gulp-jade": "~1.1.0", - "gulp-livereload": "~3.8.1", - "gulp-plumber": "~1.1.0", - "gulp-rename": "~1.2.2", - "gulp-sass": "~2.3.1", - "gulp-sourcemaps": "~1.6.0", - "gulp-uglify": "~1.5.3", + "gulp-autoprefixer": "~6.0.0", + "gulp-cached": "~1.1.1", + "gulp-chmod": "~2.0.0", + "gulp-concat": "~2.6.1", + "gulp-if": "^2.0.2", + "gulp-git": "~2.8.0", + "gulp-livereload": "~4.0.0", + "gulp-plumber": "~1.2.0", + "gulp-pug": "~4.0.1", + "gulp-rename": "~1.4.0", + "gulp-sass": "~4.0.1", + "gulp-sourcemaps": "~2.6.4", + "gulp-uglify-es": "^1.0.4", "minimist": "^1.2.0" + }, + "dependencies": { + "bootstrap": "^4.1.3", + "jquery": "^3.3.1", + "popper.js": "^1.14.4" } } diff --git a/src/styles/_homepage.sass b/src/styles/_homepage.sass index ece9b66..0109102 100644 --- a/src/styles/_homepage.sass +++ b/src/styles/_homepage.sass @@ -1,613 +1,406 @@ -.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 - max-width: 100% +.title-underline + padding-bottom: 5px + position: relative + margin-bottom: 20px - section.dashboard-main - +container-box - width: 52% - - section.dashboard-secondary - width: 46% - flex-direction: column - margin-right: auto - - span.section-lead + &:before + background-color: $primary + content: ' ' display: block - padding: 10px 0 - color: $color-text-dark-secondary + height: 2px + top: 125% + position: absolute + width: 50px - section.dashboard-main, - section.dashboard-secondary - h4 - padding-bottom: 5px - margin-bottom: 20px - position: relative - &:before - position: absolute - width: 50px - height: 2px - top: 125% - content: ' ' - display: block - background-color: $color-primary +nav#nav-tabs, +nav#sub-nav-tabs + ul#nav-tabs__list, + ul#sub-nav-tabs__list + margin: 0 + padding: 0 + list-style: none + border-bottom: thin solid $color-background + +clearfix + + li.nav-tabs__list-tab + float: left + border: none + border-bottom: 3px solid transparent + color: $color-text-dark-primary + user-select: none + + &:hover + border-color: rgba($color-secondary, .3) + cursor: pointer + color: $color-text-dark + a + color: $color-text-dark a - color: $color-text - - &:hover - color: $color-primary - cursor: pointer - - nav#nav-tabs, - nav#sub-nav-tabs - ul#nav-tabs__list, - ul#sub-nav-tabs__list - margin: 0 - padding: 0 - list-style: none - border-bottom: thin solid $color-background - +clearfix - - li.nav-tabs__list-tab - float: left - border: none - border-bottom: 3px solid transparent + display: block + text-decoration: none + padding: 10px 15px 5px color: $color-text-dark-primary - user-select: none - &:hover - border-color: rgba($color-secondary, .3) - cursor: pointer - color: $color-text-dark - a - color: $color-text-dark + i + margin-right: 5px + color: $color-text-dark-secondary + font-size: .9em - a - display: block - text-decoration: none - padding: 10px 15px 5px - color: $color-text-dark-primary + &.pi-blender + margin-right: 10px - i - margin-right: 5px - color: $color-text-dark-secondary - font-size: .9em + span + color: $color-text-dark-hint + margin-left: 5px - &.pi-blender - margin-right: 10px - - span - color: $color-text-dark-hint - margin-left: 5px - - &.active - border-color: $color-secondary + &.active + border-color: $color-secondary + color: $color-secondary-dark + a, i color: $color-secondary-dark - a, i - color: $color-secondary-dark - &.disabled - border-color: $color-background-light + &.disabled + border-color: $color-background-light + color: $color-text-dark-hint + cursor: default + a, i color: $color-text-dark-hint - cursor: default - a, i - color: $color-text-dark-hint - - &:hover - border-color: $color-background-light - pointer-events: none - - li.create - cursor: pointer - 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 - background-color: white - border-bottom: thin solid $color-background-dark - - ul.activity-stream__list - list-style: none - margin: 0 - padding: 0 - - $activity-stream-thumbnail-size: 110px - > li - position: relative - display: flex - padding: 10px 0 - overflow: hidden - border-top: thin solid $color-background-dark - - &:first-child - border: none - - &.active .activity-stream__list-details .title - color: $color-primary &:hover - .title - text-decoration: underline - &.video - a.image - &:hover - i - font-size: 3.5em - img - opacity: .9 - img - opacity: .7 - z-index: 0 - transition: opacity 150ms ease-in-out + border-color: $color-background-light + pointer-events: none +.dashboard-container + word-break: break-word + +section.stream + ul.activity-stream__list + $activity-stream-thumbnail-size: 110px + + > li + position: relative + display: flex + padding: 10px 0 + overflow: hidden + border-top: thin solid $color-background-dark + + &:first-child + border: none + + &.active .activity-stream__list-details .title + color: $color-primary + + &:hover + .title + text-decoration: underline + &.video + a.image + &:hover i - +position-center-translate - z-index: 1 - color: rgba(white, .6) - font-size: 3em - transition: font-size 100ms ease-in-out - - &.comment - .activity-stream__list-thumbnail - background: transparent - color: $node-type-comment - font-size: 1.2em - box-shadow: none + font-size: 3.5em + img + opacity: .9 + img + opacity: .7 + z-index: 0 + transition: opacity 150ms ease-in-out i +position-center-translate - left: 22px - top: 19px + z-index: 1 + color: rgba(white, .6) + font-size: 3em + transition: font-size 100ms ease-in-out - .activity-stream__list-details - padding: 0 - .title - color: $color-text-dark - padding: 7px 10px 2px 10px - font-size: 1em - margin: 0 + &.comment + .activity-stream__list-details + padding: 0 + .title + color: $color-text-dark + padding: 7px 10px 2px 10px + font-size: 1em + margin: 0 - ul.meta - padding: 0 10px 7px 10px + ul.meta + +list-meta + font-size: .9em + padding: 0 10px 7px 10px - li - &.where-parent:before - content: '\e83a' - font-family: 'pillar-font' + li + &.where-parent:before + content: '\e83a' + font-family: 'pillar-font' - &.what:before - display: none + &.what:before + display: none - &.post - .activity-stream__list-thumbnail - border-color: $node-type-post - background-color: $node-type-post - .activity-stream__list-details .title - color: darken($node-type-post, 15%) - font: - size: 1.3em - weight: 500 + &.post + .activity-stream__list-thumbnail + border-color: $node-type-post + background-color: $node-type-post + .activity-stream__list-details .title + color: darken($node-type-post, 15%) + font: + size: 1.3em + weight: 500 - &.asset, &.comment, &.post + &.asset, &.comment, &.post + &:hover + cursor: pointer + &.empty + display: none + color: $color-text-dark-primary + padding: 20px + text-align: center + span + color: $color-primary &:hover + text-decoration: underline cursor: pointer - &.empty - display: none - color: $color-text-dark-primary - padding: 20px - text-align: center - span - color: $color-primary - &:hover - text-decoration: underline - cursor: pointer - &.with-picture - min-height: $activity-stream-thumbnail-size - - .activity-stream__list-thumbnail - background-color: black - width: $activity-stream-thumbnail-size * 1.69 - min-width: $activity-stream-thumbnail-size * 1.69 - - .activity-stream__list-thumbnail-icon - position: absolute - top: 0 - left: 0 - right: 0 - bottom: 0 - font-size: 1.3em - text-shadow: 1px 1px 0 rgba(black, .2) - background-image: linear-gradient(10deg, rgba(black, .5) 0%, transparent 40%) - - i - position: absolute - bottom: -8px - left: 20px - top: initial - right: initial - color: white + &.with-picture + min-height: $activity-stream-thumbnail-size .activity-stream__list-thumbnail - position: relative - display: flex - justify-content: center - align-items: center - overflow: hidden - width: 35px - height: auto - min-width: 35px - min-height: auto + background-color: black + width: $activity-stream-thumbnail-size * 1.69 + min-width: $activity-stream-thumbnail-size * 1.69 - +media-xs - display: none + .activity-stream__list-thumbnail-icon + position: absolute + top: 0 + left: 0 + right: 0 + bottom: 0 + font-size: 1.3em + text-shadow: 1px 1px 0 rgba(black, .2) + background-image: linear-gradient(10deg, rgba(black, .5) 0%, transparent 40%) + + i + position: absolute + bottom: -8px + left: 20px + top: initial + right: initial + color: white + + .activity-stream__list-thumbnail + position: relative + display: flex + justify-content: center + align-items: center + overflow: hidden + width: 35px + height: auto + min-width: 35px + min-height: auto + + +media-xs + display: none - &.image i - color: $node-type-asset_image - &.file i - color: $node-type-asset_file - &.video i - color: $node-type-asset_video + &.image i + color: $node-type-asset_image + &.file i + color: $node-type-asset_file + &.video i + color: $node-type-asset_video - i - +position-center-translate - left: 23px - top: 21px - font-size: 1.1em + i + +position-center-translate + left: 23px + top: 21px + font-size: 1.1em - img - max-height: $activity-stream-thumbnail-size - +position-center-translate + img + max-height: $activity-stream-thumbnail-size + +position-center-translate - .activity-stream__list-details - display: flex - flex-direction: column - justify-content: space-around - flex: 1 - overflow: hidden - position: relative - max-width: 100% - margin-right: auto - padding: 10px 0 - - +media-xs - margin-left: 0 - - .ribbon - +ribbon - right: -47px - top: 5px - font: - size: 12px - weight: 500 - - span - padding: 1px 50px - - .title - display: inline-block - padding: 0 10px - color: $color-text-dark - font-size: 1.1em - - span - @include badge(hsl(hue($color-success), 60%, 45%), 3px) - font-size: .7em - padding: 1px 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 - padding: 0 15px 5px - - ul - padding: 0 - - > ul - list-style-type: none - margin: 10px 0 0 - - > li - +text-overflow-ellipsis - border-top: thin solid $color-background-dark - padding: 10px 0 - - &:first-child - border: none - - > a - +text-overflow-ellipsis - color: $color-text - display: block - 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 + .activity-stream__list-details display: flex flex-direction: column - margin-bottom: 50px + justify-content: space-around + flex: 1 + overflow: hidden + position: relative + max-width: 100% + padding: 10px 0 - &:before - height: 1px - background-color: $color-background-dark - position: absolute - bottom: -26px - left: 25px - right: 25px - content: ' ' + +media-xs + margin-left: 0 - &:last-child - margin-bottom: 0 + .ribbon + +ribbon + right: -47px + top: 5px + font-size: 12px - &:before - display: none + span + padding: 1px 50px - video - max-width: 100% + .title + padding: 0 10px + color: $color-text-dark - a.item-title + span + @include badge(hsl(hue($color-success), 60%, 45%), 3px) + font-size: .7em + padding: 1px 5px + margin-right: 5px + +section.comments + padding: 0 15px 5px + + ul + padding: 0 + + > ul + list-style-type: none + margin: 10px 0 0 + + > li + +text-overflow-ellipsis + border-top: thin solid $color-background-dark + padding: 10px 0 + + &:first-child + border: none + + > a + +text-overflow-ellipsis + color: $color-text + display: block + padding-bottom: 5px + +section.random-asset + border-bottom: thin solid $color-background-dark + + ul.random-asset__list + list-style: none + padding: 0 + + > li + align-items: center + border-top: thin solid $color-background + display: flex + padding: 7px 0 + position: relative + overflow: hidden + + &:first-child + border-top: none + + .ribbon + +ribbon + right: -47px + top: 5px + font: + size: 12px + weight: 500 + + z-index: 1 + + span + padding: 1px 50px + + .random-asset__list-thumbnail + background-color: $color-background + display: block + height: 50px + margin-right: 15px + min-height: 50px + min-width: 50px + overflow: hidden + position: relative + width: 50px + + img + width: 100% + + i + +position-center-translate font-size: 1.6em - padding: 5px 15px + color: $color-text-light + + &.image + background-color: $node-type-asset_image + &.file + background-color: $node-type-asset_file + font-size: .8em + &.video + background-color: $node-type-asset_video + font-size: .8em + &.None + background-color: $node-type-group + + .random-asset__list-details + .title display: block - color: $color-text + font-size: 1em + color: $color-text-dark-primary &:hover color: $color-primary ul.meta +list-meta + padding-top: 5px font-size: .9em - padding: 15px 15px 5px + li + &:before + left: -5px + &.what + text-transform: capitalize - &.blog-non-featured - border-radius: 0 - margin: 0 + &.featured + align-items: flex-start + flex-direction: column + padding: 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 - border-bottom: thin solid $color-background-dark - - ul.random-asset__list - list-style: none - padding: 0 - - > li - align-items: center - border-top: thin solid $color-background - display: flex - padding: 7px 0 - position: relative - overflow: hidden - - &:first-child - border-top: none - - .ribbon - +ribbon - right: -47px - top: 5px - font: - size: 12px - weight: 500 - - z-index: 1 - - span - padding: 1px 50px - - .random-asset__list-thumbnail - background-color: $color-background + a.title + font-size: 1.1em + padding: 10px 0 5px + display: block + color: $color-text + + &:hover + color: $color-primary + + a.random-asset__thumbnail display: block - height: 50px - margin-right: 15px - min-height: 50px - min-width: 50px - overflow: hidden position: relative - width: 50px + + &.video + background-color: black + img + opacity: .7 img + transition: opacity 150ms ease-in-out width: 100% + max-width: 100% i +position-center-translate - font-size: 1.6em - color: $color-text-light - - &.image - background-color: $node-type-asset_image - &.file - background-color: $node-type-asset_file - font-size: .8em - &.video - background-color: $node-type-asset_video - font-size: .8em - &.None - background-color: $node-type-group - - .random-asset__list-details - .title - display: block - font-size: 1em - color: $color-text-dark-primary - - &:hover - color: $color-primary - - ul.meta - +list-meta - padding-top: 5px - font-size: .9em - - li - &:before - left: -5px - &.what - text-transform: capitalize - - &.featured - align-items: flex-start - flex-direction: column - padding: 0 - - a.title - font-size: 1.1em - padding: 10px 0 5px - display: block - color: $color-text - - &:hover - color: $color-primary - - a.random-asset__thumbnail - display: block - position: relative - - &.video - background-color: black - img - opacity: .7 - - img - transition: opacity 150ms ease-in-out - width: 100% - max-width: 100% + color: white + font-size: 3em + text-shadow: 0 0 25px black + transition: font-size 150ms ease-in-out + &:hover i - +position-center-translate - color: white - font-size: 3em - text-shadow: 0 0 25px black - transition: font-size 150ms ease-in-out + font-size: 3.5em + img + opacity: .85 - &:hover - i - font-size: 3.5em - img - opacity: .85 - - ul.meta - +list-meta - padding-bottom: 10px + ul.meta + +list-meta + padding-bottom: 10px section.announcement @@ -653,10 +446,6 @@ section.announcement .title padding-bottom: 10px - font: - family: $font-body - size: 1.4em - weight: 300 +media-xs font-size: 1.4em @@ -693,60 +482,21 @@ section.announcement justify-content: space-around 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 - .dashboard-container - .dashboard-main - +media-xs - width: 100% - background-color: transparent - box-shadow: none - width: 60% + .blog + // Custom tweak to Bootstrap grid for the only case when + // the post is inside a column (it's usually centered in the page). + .col-md-9 + flex: 1 + max-width: 100% - .dashboard-secondary - +container-box - +media-xs - width: 100% - width: 38% + .jumbotron + padding-top: 6em + padding-bottom: 6em - > section - padding: 15px + * + font-size: $h1-font-size + + .lead + font-size: $font-size-base diff --git a/src/styles/_welcome.sass b/src/styles/_welcome.sass index 99f92c5..ae4f5df 100644 --- a/src/styles/_welcome.sass +++ b/src/styles/_welcome.sass @@ -10,9 +10,6 @@ li a.navbar-item color: $color-text - .navbar-container - +container-behavior - .navbar-toggle border: 2px solid $color-text-dark-primary color: $color-text @@ -267,22 +264,6 @@ +media-xs 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 +media-sm @@ -334,9 +315,7 @@ section.pricing +button($color-primary, 3px, true) h3 - font: - size: 1.8em - family: $font-body + font-size: 1.8em padding-bottom: 0 margin: 25px 0 0 10px diff --git a/src/styles/main.sass b/src/styles/main.sass index 6d2da95..d7524a5 100644 --- a/src/styles/main.sass +++ b/src/styles/main.sass @@ -1,26 +1,99 @@ -@import ../../../pillar/src/styles/_normalize -@import ../../../pillar/src/styles/_config -@import ../../../pillar/src/styles/_utils +// Bootstrap variables and utilities. +@import "../../node_modules/bootstrap/scss/functions" +@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 */ -@import ../../../pillar/src/styles/_project -@import ../../../pillar/src/styles/_project-sharing -@import ../../../pillar/src/styles/_project-dashboard -@import ../../../pillar/src/styles/_user +@import "../../../pillar/src/styles/_project" +@import "../../../pillar/src/styles/_project-sharing" +@import "../../../pillar/src/styles/_project-dashboard" +@import "../../../pillar/src/styles/_user" + @import _welcome @import _homepage @import _services @import _about -@import ../../../pillar/src/styles/_search -@import ../../../pillar/src/styles/_organizations +@import "../../../pillar/src/styles/_search" +@import "../../../pillar/src/styles/_organizations" /* 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 */ -@import ../../../pillar/src/styles/plugins/_jstree -@import ../../../pillar/src/styles/plugins/_js_select2 +@import "../../../pillar/src/styles/plugins/_jstree" +@import "../../../pillar/src/styles/plugins/_js_select2" /* CSS for pillar-font comes from fontello.com using static/assets/font/config.json */ diff --git a/src/styles/project-landing.sass b/src/styles/project-landing.sass index 7eaa671..3d65012 100644 --- a/src/styles/project-landing.sass +++ b/src/styles/project-landing.sass @@ -1,47 +1,88 @@ -@import ../../../pillar/src/styles/_config -@import ../../../pillar/src/styles/_utils +// Bootstrap variables and utilities. +@import "../../node_modules/bootstrap/scss/functions" +@import "../../node_modules/bootstrap/scss/variables" +@import "../../node_modules/bootstrap/scss/mixins" + +// 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/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 -body - background-color: white -.page-body - background-color: white nav.navbar - background-color: white .navbar-header +media-xs width: 100% - .navbar-brand - color: $color-text - - li a.navbar-item - color: $color-text - &:hover - color: black - &:focus - color: black - &.active - color: black - .dropdown.open - a - background-color: white - .dropdown.libraries - &:hover - background: none - ul.dropdown-menu - background-color: white - li - a - color: $color-text - &:hover - color: black - background-color: white - .navbar-container - +container-behavior - .navbar-toggle border: none color: $color-text @@ -57,11 +98,11 @@ nav.navbar .node-details-container max-width: 620px - font-family: $font-body font-size: 1.3em line-height: 1.5em margin: 0 auto 40px auto padding-bottom: 40px + +media-xs padding-left: 10px padding-right: 10px @@ -106,20 +147,10 @@ section border-top: thin solid $color-background margin: 0 auto -a.btn - margin: 20px auto - font-size: 1.3em - padding: 9px 18px - border-radius: 8px - color: $color-text-dark - .navbar-secondary max-width: 620px margin: 0 auto - .navbar-container - border-bottom: 1px solid #dddddd - .navbar-collapse padding-left: 0 diff --git a/src/templates/_macros/_navigation.pug b/src/templates/_macros/_navigation.pug new file mode 100644 index 0000000..46290fe --- /dev/null +++ b/src/templates/_macros/_navigation.pug @@ -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 %} diff --git a/src/templates/homepage.pug b/src/templates/homepage.pug index 485255c..ca4eba8 100644 --- a/src/templates/homepage.pug +++ b/src/templates/homepage.pug @@ -18,238 +18,229 @@ 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 %}") | {% endblock %} +| {% block navigation_tabs %} +| {{ navigation_tabs(title) }} +| {% endblock navigation_tabs %} + | {% block body %} -.dashboard-container - section.dashboard-main +.container-fluid.dashboard-container.imgs-fluid + .row + .col-md-8 + section.blog + ul.list-unstyled + | {% if latest_posts %} + | {% for node in latest_posts %} + | {{ render_blog_post(node) }} + | {% endfor %} + | {% else %} + li + | No blog entries... yet! + | {% endif %} - section.blog-stream - ul.blog-stream__list - | {% if latest_posts %} - | {% for node in latest_posts %} - | {{ render_blog_post(node) }} - | {% endfor %} - | {% else %} - li - .blog-stream__list-details - ul.meta - li.when No blog entries... yet! - | {% endif %} + .d-block.text-center + a.d-inline-block.p-3.text-muted(href="{{ url_for('main.main_blog') }}") + | See All Blog Posts - .more - a(href="{{ url_for('main.main_blog') }}") - | See All Blog Posts + a.d-inline-block.p-3.text-muted( + href="{{ url_for('main.feeds_blogs') }}", + title="Blogs Feed", + data-toggle="tooltip", + data-placement="left") + i.pi-rss + | RSS Feed - a.feed( - href="{{ url_for('main.feeds_blogs') }}", - title="Blogs Feed", - data-toggle="tooltip", - data-placement="left") - i.pi-rss + .col-md-4 + .dashboard-sidebar + section.pt-3 + h6.title-underline In Production + a(href="/p/spring/") + img(src="{{ url_for('static', filename='assets/img/projects/spring_450x150.jpg')}}") + p.text-muted.pt-2. + A poetic short film about a mountain spirit and her wise little dog. #[a(href="/p/spring/") Check it out]. - section.dashboard-secondary - | {{ navigation_tabs(title) }} + section.stream.py-3 + h6.title-underline Latest Assets - section.dashboard-in-production - h4 In Production - span.section-lead. - Check out these projects currently in production! - - a.in-production-project(href="/p/spring/") - 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="/p/hero/") - img(src="{{ url_for('static', filename='assets/img/projects/hero_450x150.jpg')}}") - p. - #[strong Hero] - A '2D' trailer-style movie focused on getting grease pencil - production ready for Blender 2.8. - - section.stream - - h4 Latest Assets - - ul.activity-stream__list - | {% for n in activity_stream %} - li( - class="{{ n.node_type }} {{ n.properties.content_type }} {% if n.picture %}with-picture{% endif %}", - data-url="{{ n.url }}") - a.activity-stream__list-thumbnail( - class="{{ n.properties.content_type }}", - href="{{ n.url }}") - | {% if n.picture %} - img(src="{{ n.picture.thumbnail('m', api=api) }}") - | {% endif %} - - .activity-stream__list-thumbnail-icon - | {% if n.node_type == 'asset' %} - | {% if n.properties.content_type == 'video' %} - i.pi-play - | {% elif n.properties.content_type == 'image' %} - i.pi-picture - | {% elif n.properties.content_type == 'file' %} - i.pi-file-archive - | {% else %} - i.pi-folder - | {% endif %} - | {% endif %} - - - .activity-stream__list-details - a.title(href="{{ n.url }}") - | {{ n.name }} - - | {% if n.permissions.world %} - .ribbon - span free - | {% endif %} - ul.meta - | {% if not n.picture %} - li.when - a(href="{{ n.url }}", title="{{ n._created }}") {{ n._created | pretty_date_time }} - li.who {{ n.user.full_name }} - | {% endif %} - - | {% if n.attached_to %} - li.where-parent - a(href="{{ n.attached_to.url }}") {{ n.attached_to.name }} - | {% endif %} - li.where-project - a.project(href="{{ url_for('projects.view', project_url=n.project.url) }}") {{ n.project.name }} - li.what - | {% if n.node_type == 'asset' %} - | {{ n.properties.content_type | undertitle }} + ul.activity-stream__list.list-unstyled + | {% for n in activity_stream %} + li( + class="{{ n.node_type }} {{ n.properties.content_type }} {% if n.picture %}with-picture{% endif %}", + data-url="{{ n.url }}") + a.activity-stream__list-thumbnail( + class="{{ n.properties.content_type }}", + href="{{ n.url }}") + | {% if n.picture %} + img(src="{{ n.picture.thumbnail('m', api=api) }}") | {% endif %} - | {% if n.picture %} - ul.meta.extra - li.when - a(href="{{ n.url }}", title="{{ n._created }}") {{ n._created | pretty_date_time }} - li.who {{ n.user.full_name }} - | {% endif %} - | {% endfor %} - - li.activity-stream__list-item.empty#activity-stream__empty - | No items to list. + .activity-stream__list-thumbnail-icon + | {% if n.node_type == 'asset' %} + | {% if n.properties.content_type == 'video' %} + i.pi-play + | {% elif n.properties.content_type == 'image' %} + i.pi-picture + | {% elif n.properties.content_type == 'file' %} + i.pi-file-archive + | {% else %} + i.pi-folder + | {% endif %} + | {% endif %} - section.random-asset - h4 - a(href="/search") Explore the Cloud - span.section-lead Random selection of the best assets & tutorials + .activity-stream__list-details + a.title(href="{{ n.url }}") + | {{ n.name }} - ul.random-asset__list - | {% for n in random_featured %} - | {% if n.picture and loop.first %} - li.random-asset__list-item.project - | {% if n.project.picture_square %} - a.random-asset__list-thumbnail( - href="{{ n.project.url }}") - img.image(src="{{ n.project.picture_square.thumbnail('s', api=api) }}") - | {% endif %} - .random-asset__list-details - a.title(href="{{ n.project.url }}") {{ n.project.name }} - | {% if n.project.summary %} - ul.meta - li.what - a(href="{{ n.project.url }}") {{ n.project.summary }} - | {% endif %} + | {% if n.permissions.world %} + .ribbon + span free + | {% endif %} + ul.list-unstyled.d-flex.text-muted + | {% if not n.picture %} + li.when + a(href="{{ n.url }}", title="{{ n._created }}") {{ n._created | pretty_date_time }} + li.who {{ n.user.full_name }} + | {% endif %} - li.random-asset__list-item.featured - | {% if n.permissions.world %} - .ribbon - span free - | {% endif %} - a.random-asset__thumbnail( - href="{{ n.url }}", - class="{{ n.properties.content_type }}") - | {% if n.picture %} - img(src="{{ n.picture.thumbnail('l', api=api) }}") + | {% if n.attached_to %} + li.where-parent + a(href="{{ n.attached_to.url }}") {{ n.attached_to.name }} + | {% endif %} + li.where-project + a.project(href="{{ url_for('projects.view', project_url=n.project.url) }}") {{ n.project.name }} + li.what + | {% if n.node_type == 'asset' %} + | {{ n.properties.content_type | undertitle }} + | {% endif %} - | {% if n.properties.content_type == 'video' %} - i.pi-play - | {% endif %} + | {% if n.picture %} + ul.list-unstyled.d-flex.text-muted.extra + li.when + a(href="{{ n.url }}", title="{{ n._created }}") {{ n._created | pretty_date_time }} + li.who {{ n.user.full_name }} + | {% endif %} + | {% endfor %} - | {% endif %} + li.activity-stream__list-item.empty#activity-stream__empty + | No items to list. - a.title(href="{{ n.url }}") - | {{ n.name }} - ul.meta - li.what - a(href="{{ n.url }}") - | {% if n.properties.content_type %}{{ n.properties.content_type | undertitle }}{% else %}Folder{% endif %} - li.where - a(href="{{ n.project.url }}") - | {{ n.project.name }} - | {% else %} - li - | {% if n.permissions.world %} - .ribbon - span free - | {% endif %} - a.random-asset__list-thumbnail( - href="{{ n.url }}", - class="{{ n.properties.content_type }}") - | {% if n.picture %} - img.image(src="{{ n.picture.thumbnail('s', api=api) }}") + section.random-asset.py-3 + h6.title-underline + a(href="/search") Explore the Cloud + .pb-3.text-muted Random selection of the best assets & tutorials + + ul.random-asset__list.list-unstyled + | {% for n in random_featured %} + | {% if n.picture and loop.first %} + li.random-asset__list-item.project + | {% if n.project.picture_square %} + a.random-asset__list-thumbnail( + href="{{ n.project.url }}") + img.image(src="{{ n.project.picture_square.thumbnail('s', api=api) }}") + | {% endif %} + .random-asset__list-details + a.title(href="{{ n.project.url }}") {{ n.project.name }} + | {% if n.project.summary %} + ul.list-unstyled.d-flex.text-muted + li.what + a(href="{{ n.project.url }}") {{ n.project.summary }} + | {% endif %} + + li.random-asset__list-item.featured + | {% if n.permissions.world %} + .ribbon + span free + | {% endif %} + a.random-asset__thumbnail( + href="{{ n.url }}", + class="{{ n.properties.content_type }}") + | {% if n.picture %} + img(src="{{ n.picture.thumbnail('l', api=api) }}") + + | {% if n.properties.content_type == 'video' %} + i.pi-play + | {% endif %} + + | {% endif %} + + a.title(href="{{ n.url }}") + | {{ n.name }} + ul.list-unstyled.d-flex.text-muted + li.what + a(href="{{ n.url }}") + | {% if n.properties.content_type %}{{ n.properties.content_type | undertitle }}{% else %}Folder{% endif %} + li.where + a(href="{{ n.project.url }}") + | {{ n.project.name }} | {% else %} - | {% if n.properties.content_type == 'video' %} - i.pi-film-thick - | {% elif n.properties.content_type == 'image' %} - i.pi-picture - | {% elif n.properties.content_type == 'file' %} - i.pi-file-archive + + li + | {% if n.permissions.world %} + .ribbon + span free + | {% endif %} + a.random-asset__list-thumbnail( + href="{{ n.url }}", + class="{{ n.properties.content_type }}") + | {% if n.picture %} + img.image(src="{{ n.picture.thumbnail('s', api=api) }}") + | {% else %} + | {% if n.properties.content_type == 'video' %} + i.pi-film-thick + | {% elif n.properties.content_type == 'image' %} + i.pi-picture + | {% elif n.properties.content_type == 'file' %} + i.pi-file-archive + | {% else %} + i.pi-folder + | {% endif %} + | {% endif %} + .random-asset__list-details + a.title(href="{{ n.url }}") {{ n.name }} + ul.list-unstyled.d-flex.text-muted + li.what + a(href="{{ n.url }}") + | {% if n.properties.content_type %}{{ n.properties.content_type }}{% else %}Folder{% endif %} + li.where + a(href="{{ n.project.url }}") {{ n.project.name }} + + | {% endif %} + | {% endfor %} + + + section.comments.py-3 + h6.title-underline Latest Comments + + ul.list-unstyled + | {% if latest_comments %} + | {% for n in latest_comments %} + li( + class="{{ n.node_type }}", + data-url="{{ n.url }}") + + a.comment-content(href="{{ n.url }}") + | {{ n.properties.content | striptags | truncate(200) }} + + ul.list-unstyled.d-flex.text-muted + li.who {{ n.user.full_name }} + | {% if n.attached_to %} + + li.where-parent + a(href="{{ n.attached_to.url }}") {{ n.attached_to.name }} + | {% endif %} + + li.when + a(href="{{ n.url }}", title="{{ n._created }}") + | {{ n._created | pretty_date_time }} + | {% endfor %} + | {% else %} - i.pi-folder + li.activity-stream__list-item.empty#activity-stream__empty + | No comments... yet! + | {% endif %} - | {% endif %} - .random-asset__list-details - a.title(href="{{ n.url }}") {{ n.name }} - ul.meta - li.what - a(href="{{ n.url }}") - | {% if n.properties.content_type %}{{ n.properties.content_type }}{% else %}Folder{% endif %} - li.where - a(href="{{ n.project.url }}") {{ n.project.name }} - - | {% endif %} - | {% endfor %} - - - section.comments - - h4 Latest Comments - - ul - | {% if latest_comments %} - | {% for n in latest_comments %} - li( - class="{{ n.node_type }}", - data-url="{{ n.url }}") - - a.comment-content(href="{{ n.url }}") - | {{ n.properties.content | striptags | truncate(200) }} - - ul.meta - li.who {{ n.user.full_name }} - | {% if n.attached_to %} - - li.where-parent - a(href="{{ n.attached_to.url }}") {{ n.attached_to.name }} - | {% endif %} - - li.when - a(href="{{ n.url }}", title="{{ n._created }}") - | {{ n._created | pretty_date_time }} - | {% endfor %} - - | {% else %} - li.activity-stream__list-item.empty#activity-stream__empty - | No comments... yet! - - | {% endif %} | {% endblock %} diff --git a/src/templates/layout.pug b/src/templates/layout.pug index 82c69ed..5281f75 100644 --- a/src/templates/layout.pug +++ b/src/templates/layout.pug @@ -3,7 +3,7 @@ html(lang="en") head meta(charset="utf-8") title {% if self.page_title() %}{% block page_title %}{% endblock %} — {% endif %}Blender Cloud - meta(name="viewport", content="width=device-width, initial-scale=1.0") + meta(name="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="author", content="Blender Institute") meta(name="theme-color", content="#3e92aa") @@ -46,14 +46,10 @@ html(lang="en") 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_pillar', filename='assets/css/vendor/bootstrap.min.css') }}", rel="stylesheet") - link(href="{{ url_for('static', filename='assets/google-font-roboto/roboto.css') }}", rel="stylesheet") - | {% block head %}{% endblock %} | {% block css %} link(href="{{ url_for('static_pillar', filename='assets/css/font-pillar.css') }}", rel="stylesheet") - link(href="{{ url_for('static_pillar', filename='assets/css/base.css') }}", rel="stylesheet") | {% if title == 'blog' %} link(href="{{ url_for('static_pillar', filename='assets/css/blog.css') }}", rel="stylesheet") | {% else %} @@ -61,216 +57,331 @@ html(lang="en") | {% endif %} | {% endblock css %} - - | {% if not title %}{% set title="default" %}{% endif %} - + | {% if not title %}{% set title="default" %}{% endif %} body(class="{{ title }}") - .container-page - | {% with messages = get_flashed_messages(with_categories=True) %} - | {% if messages %} + | {% with messages = get_flashed_messages(with_categories=True) %} + | {% if messages %} + | {% for (category, message) in messages %} + .alert(role="alert", class="alert-{{ category }}") + i.alert-icon(class="{{ category }}") + span {{ message }} + button.close(type="button", data-dismiss="alert") + i.pi-cancel + | {% endfor %} + | {% endif %} + | {% endwith %} - | {% for (category, message) in messages %} - .alert(role="alert", class="alert-{{ category }}") - i.alert-icon(class="{{ category }}") - span {{ message }} - button.close(type="button", data-dismiss="alert") - i.pi-cancel - | {% endfor %} + nav.navbar.navbar-expand-md.fixed-top.bg-white + a.navbar-brand( + href="{{ url_for('main.homepage') }}", + title="Blender Cloud") + span.app-logo + i.pi-blender-cloud - | {% endif %} - | {% endwith %} + button.navbar-toggler.text-light( + data-target=".navbar-collapse", + data-toggle="collapse", + type="button") + span.sr-only Toggle navigation + span.navbar-toggler-icon.d-flex.align-items-center + i.pi-menu - nav.navbar - .navbar-container - header.navbar-header - button.navbar-toggle(data-target=".navbar-collapse", data-toggle="collapse", type="button") - span.sr-only Toggle navigation - i.pi-menu - a.navbar-brand( - href="{{ url_for('main.homepage') }}", - title="Blender Cloud") - span.app-logo - i.pi-blender-cloud + | {% block navigation_tabs %} + | {% endblock navigation_tabs %} - | {% block navigation_search %} - .search-input - input#cloud-search( - type="text", - placeholder="Search assets, tutorials...") - i.search-icon.pi-search - | {% endblock navigation_search %} + | {% 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 + | {% endblock navigation_search %} - nav.collapse.navbar-collapse - ul.nav.navbar-nav.navbar-right - | {% if node and node.properties and node.properties.category %} - | {% set category = node.properties.category %} - | {% else %} - | {% set category = title %} - | {% endif %} + .collapse.navbar-collapse + ul.navbar-nav.ml-auto + | {% if node and node.properties and node.properties.category %} + | {% set category = node.properties.category %} + | {% else %} + | {% set category = title %} + | {% endif %} - | {% block navigation_sections %} + | {% block navigation_sections %} + li + a.navbar-item( + href="{{ url_for('main.main_blog') }}", + title="Blender Cloud Blog", + data-toggle="tooltip", + data-placement="bottom", + class="{% if category == 'blog' %}active{% endif %}") + span Blog + + li.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('main.main_blog') }}", - title="Blender Cloud Blog", + href="{{ url_for('projects.view', project_url='hdri') }}", + title="HDRI Library", data-toggle="tooltip", - data-placement="bottom", - class="{% if category == 'blog' %}active{% endif %}") - span Blog - - li(class="dropdown libraries") - a.navbar-item.dropdown-toggle( - href="", - data-toggle="dropdown", - title="Libraries") - span Libraries - i.pi-angle-down - - ul.dropdown-menu - li - a.navbar-item( - href="{{ url_for('projects.view', project_url='hdri') }}", - title="HDRI Library", - data-toggle="tooltip", - data-placement="left") - i.pi-globe - | HDRI - li - a.navbar-item( - href="{{ url_for('projects.view', project_url='textures') }}", - title="Textures Library", - data-toggle="tooltip", - data-placement="left") - i.pi-folder-texture - | Textures - li - a.navbar-item( - href="{{ url_for('projects.view', project_url='characters') }}", - title="Character Library", - data-toggle="tooltip", - data-placement="left") - i.pi-character - | Characters - - - li(class="dropdown libraries") - a.navbar-item.dropdown-toggle( - href="", - 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 - | Courses - li - a.navbar-item( - href="{{ url_for('cloud.workshops') }}", - title="Workshops", - data-toggle="tooltip", - data-placement="left") - i.pi-lightbulb - | Workshops - 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 - | Art Gallery - + data-placement="left") + i.pi-globe + | HDRI li a.navbar-item( - href="{{ url_for('cloud.open_projects') }}", - title="Browse all the Open Projects", + href="{{ url_for('projects.view', project_url='textures') }}", + title="Textures Library", data-toggle="tooltip", - data-placement="bottom", - class="{% if category in ['open-projects', 'film'] %}active{% endif %}") - span Open Projects + data-placement="left") + i.pi-folder-texture + | Textures li a.navbar-item( - href="{{ url_for('cloud.services') }}", - title="Blender Cloud Services", + href="{{ url_for('projects.view', project_url='characters') }}", + title="Character Library", data-toggle="tooltip", - data-placement="bottom", - class="{% if category == 'services' %}active{% endif %}") - span Services - | {% endblock navigation_sections %} + data-placement="left") + i.pi-character + | Characters - | {% if current_user.is_anonymous %} + li(class="dropdown") + 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="https://store.blender.org/product/membership/", - title="Sign up") Sign up - | {% endif %} + href="{{ url_for('cloud.courses') }}", + title="Courses", + data-toggle="tooltip", + data-placement="left") + i.pi-graduation-cap + | Courses + li + a.navbar-item( + href="{{ url_for('cloud.workshops') }}", + title="Workshops", + data-toggle="tooltip", + data-placement="left") + i.pi-lightbulb + | Workshops + 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 + | Art Gallery + li(class="dropdown") + a.navbar-item.dropdown-toggle( + 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 - | {% block navigation_user %} + 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 - | {% include 'menus/notifications.html' %} - | {% include 'menus/user.html' %} + li.dropdown-divider - | {% endblock navigation_user %} + 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 - .page-content - #search-overlay - | {% block page_overlay %} - #page-overlay - | {% endblock page_overlay %} - .page-body - | {% block body %}{% endblock %} + 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 %} + + | {% block navigation_user %} + | {% include 'menus/notifications.html' %} + | {% include 'menus/user.html' %} + | {% 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 + #search-overlay + | {% block page_overlay %} + #page-overlay + | {% endblock page_overlay %} + .page-body + | {% block body %}{% endblock %} | {% block footer_container %} - #footer-container + .footer-wrapper | {% block footer_navigation %} - #footer-navigation + .footer-navigation .container .row .col-md-4.col-xs-6 - .footer-support - h4 Support & Feedback - p. - Let us know what you think or if you have any issues - just write to cloudsupport at blender dot org - - .col-md-2.col-xs-6 - ul.footer-social - li - a(href="https://www.facebook.com/BlenderCloudOfficial/", - title="Follow us on Facebook") - i.pi-social-facebook - li - a(href="https://twitter.com/Blender_Cloud", - title="Follow us on Twitter") - i.pi-social-twitter - - .col-md-2.col-xs-6 h4 a(href="{{ url_for('main.homepage') }}") - | Blender Cloud - ul.footer-links + i.pi-blender-cloud-logo + + 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") - | Blog + | HDRIs li a(href="{{ url_for('cloud.services') }}", title="Blender Cloud Services") - | Services + | Textures li a(href="{{ url_for('cloud.about') }}", title="About Blender Cloud") - | About + | 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") @@ -279,33 +390,11 @@ html(lang="en") a(href="{{ url_for('cloud.privacy') }}", title="Privacy") | Privacy - - .col-md-2.col-xs-6 - h4 - a(href="https://www.blender.org", - title="Blender official Website") - | Blender - ul.footer-links - li - a(href="https://www.blender.org", - title="Blender official Website") - | Blender.org - li - a(href="https://store.blender.org/", - title="The official Blender Store") - | Blender Store - - .col-md-2.col-xs-6.special - | With the support of the
MEDIA Programme of the European Union

- img(alt="MEDIA Programme of the European Union", - src="https://gooseberry.blender.org/wp-content/uploads/2014/01/media_programme.png") | {% endblock footer_navigation %} - | {% block footer %} - footer.container - #hop(title="Be awesome in space") - i.pi-angle-up - | {% endblock footer %} + #hop(title="Be awesome in space") + i.pi-angle-up + | {% endblock footer_container %} #notification-pop(data-url="", data-read-toggle="") @@ -318,10 +407,7 @@ html(lang="en") span.nc-date a(href="") - noscript - 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') }}") + script(src="{{ url_for('static_cloud', filename='assets/js/bootstrap.min.js') }}") | {% if current_user.is_authenticated %} script(src="{{ url_for('static_pillar', filename='assets/js/vendor/jquery.typewatch-3.0.0.min.js') }}") diff --git a/src/templates/mixins/components.pug b/src/templates/mixins/components.pug new file mode 100644 index 0000000..68826aa --- /dev/null +++ b/src/templates/mixins/components.pug @@ -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. diff --git a/src/templates/nodes/custom/blog/_macros.pug b/src/templates/nodes/custom/blog/_macros.pug new file mode 100644 index 0000000..84ec904 --- /dev/null +++ b/src/templates/nodes/custom/blog/_macros.pug @@ -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 %} diff --git a/src/templates/organizations/index.pug b/src/templates/organizations/index.pug new file mode 100644 index 0000000..4c3f6eb --- /dev/null +++ b/src/templates/organizations/index.pug @@ -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('

Opening ' + item_type + ' failed. There possibly was ' + + 'an error connecting to the server. Please check your network connection and ' + + 'try again.

'); + } + }); + + // 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 = $('

').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 %} diff --git a/src/templates/projects/home_index.pug b/src/templates/projects/home_index.pug new file mode 100644 index 0000000..610ff0d --- /dev/null +++ b/src/templates/projects/home_index.pug @@ -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. +
+ | 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 v{{ 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 +


+ a.download( + href='https://cloud.blender.org/r/downloads/blender_cloud-latest-bundle.zip') + | Download add-on + | {% endfor %} +| {% endblock %} + diff --git a/src/templates/projects/home_layout.pug b/src/templates/projects/home_layout.pug new file mode 100644 index 0000000..454f508 --- /dev/null +++ b/src/templates/projects/home_layout.pug @@ -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 %} diff --git a/src/templates/projects/index_dashboard.pug b/src/templates/projects/index_dashboard.pug new file mode 100644 index 0000000..4297dd1 --- /dev/null +++ b/src/templates/projects/index_dashboard.pug @@ -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 %} diff --git a/src/templates/projects/landing.pug b/src/templates/projects/landing.pug index eb6b009..d30b1c8 100644 --- a/src/templates/projects/landing.pug +++ b/src/templates/projects/landing.pug @@ -78,8 +78,6 @@ script(src="{{ url_for('static_pillar', filename='assets/js/vendor/videojs-hotke | {% endblock %} | {% block css %} -link(href="{{ url_for('static_pillar', filename='assets/css/font-pillar.css') }}", rel="stylesheet") -link(href="{{ url_for('static_pillar', filename='assets/css/base.css') }}", rel="stylesheet") link(href="{{ url_for('static_cloud', filename='assets/css/project-landing.css') }}", rel="stylesheet") | {% endblock %} diff --git a/src/templates/projects/view.pug b/src/templates/projects/view.pug new file mode 100644 index 0000000..ef59f6c --- /dev/null +++ b/src/templates/projects/view.pug @@ -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 folder 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($('') }); diff --git a/src/templates/users/settings/billing.pug b/src/templates/users/settings/billing.pug index befe663..2c50f16 100644 --- a/src/templates/users/settings/billing.pug +++ b/src/templates/users/settings/billing.pug @@ -65,7 +65,7 @@ p Your organisation provides you with your subscription. hr 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 diff --git a/src/templates/users/settings/emails.pug b/src/templates/users/settings/emails.pug index 2411997..cf91972 100644 --- a/src/templates/users/settings/emails.pug +++ b/src/templates/users/settings/emails.pug @@ -11,7 +11,7 @@ | {% endfor %} .buttons - button.btn.btn-default.button-submit(type='submit') + button.btn.btn-outline-success.button-submit(type='submit') i.pi-check | Save Changes | {% endblock %} diff --git a/src/templates/welcome.pug b/src/templates/welcome.pug index 62a125d..d9f5ecb 100644 --- a/src/templates/welcome.pug +++ b/src/templates/welcome.pug @@ -28,12 +28,12 @@ li | {% endblock navigation_sections %} | {% block navigation_user %} -li.nav-item-sign-in +li.pt-1.pr-1 | {% 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 | {% else %} - a.navbar-item(href="{{ url_for('main.homepage') }}") + a.btn.btn-outline-success(href="{{ url_for('main.homepage') }}") | Explore | {% endif %} | {% endblock navigation_user %} diff --git a/static/assets/google-font-roboto/-2n2p-_Y08sg57CNWQfKNvesZW2xOQ-xsNqO47m55DA.woff2 b/static/assets/google-font-roboto/-2n2p-_Y08sg57CNWQfKNvesZW2xOQ-xsNqO47m55DA.woff2 deleted file mode 100644 index 870072d..0000000 Binary files a/static/assets/google-font-roboto/-2n2p-_Y08sg57CNWQfKNvesZW2xOQ-xsNqO47m55DA.woff2 and /dev/null differ diff --git a/static/assets/google-font-roboto/-L14Jk06m6pUHB-5mXQQnRJtnKITppOI_IvcXXDNrsc.woff2 b/static/assets/google-font-roboto/-L14Jk06m6pUHB-5mXQQnRJtnKITppOI_IvcXXDNrsc.woff2 deleted file mode 100644 index 471b519..0000000 Binary files a/static/assets/google-font-roboto/-L14Jk06m6pUHB-5mXQQnRJtnKITppOI_IvcXXDNrsc.woff2 and /dev/null differ diff --git a/static/assets/google-font-roboto/0eC6fl06luXEYWpBSJvXCBJtnKITppOI_IvcXXDNrsc.woff2 b/static/assets/google-font-roboto/0eC6fl06luXEYWpBSJvXCBJtnKITppOI_IvcXXDNrsc.woff2 deleted file mode 100644 index 83e3cea..0000000 Binary files a/static/assets/google-font-roboto/0eC6fl06luXEYWpBSJvXCBJtnKITppOI_IvcXXDNrsc.woff2 and /dev/null differ diff --git a/static/assets/google-font-roboto/CWB0XYA8bzo0kSThX0UTuA.woff2 b/static/assets/google-font-roboto/CWB0XYA8bzo0kSThX0UTuA.woff2 deleted file mode 100644 index e44dd20..0000000 Binary files a/static/assets/google-font-roboto/CWB0XYA8bzo0kSThX0UTuA.woff2 and /dev/null differ diff --git a/static/assets/google-font-roboto/Fcx7Wwv8OzT71A3E1XOAjvesZW2xOQ-xsNqO47m55DA.woff2 b/static/assets/google-font-roboto/Fcx7Wwv8OzT71A3E1XOAjvesZW2xOQ-xsNqO47m55DA.woff2 deleted file mode 100644 index 719f810..0000000 Binary files a/static/assets/google-font-roboto/Fcx7Wwv8OzT71A3E1XOAjvesZW2xOQ-xsNqO47m55DA.woff2 and /dev/null differ diff --git a/static/assets/google-font-roboto/Fl4y0QdOxyyTHEGMXX8kcRJtnKITppOI_IvcXXDNrsc.woff2 b/static/assets/google-font-roboto/Fl4y0QdOxyyTHEGMXX8kcRJtnKITppOI_IvcXXDNrsc.woff2 deleted file mode 100644 index 2885a7f..0000000 Binary files a/static/assets/google-font-roboto/Fl4y0QdOxyyTHEGMXX8kcRJtnKITppOI_IvcXXDNrsc.woff2 and /dev/null differ diff --git a/static/assets/google-font-roboto/Hgo13k-tfSpn0qi1SFdUfVtXRa8TVwTICgirnJhmVJw.woff2 b/static/assets/google-font-roboto/Hgo13k-tfSpn0qi1SFdUfVtXRa8TVwTICgirnJhmVJw.woff2 deleted file mode 100644 index 6c94818..0000000 Binary files a/static/assets/google-font-roboto/Hgo13k-tfSpn0qi1SFdUfVtXRa8TVwTICgirnJhmVJw.woff2 and /dev/null differ diff --git a/static/assets/google-font-roboto/I3S1wsgSg9YCurV6PUkTORJtnKITppOI_IvcXXDNrsc.woff2 b/static/assets/google-font-roboto/I3S1wsgSg9YCurV6PUkTORJtnKITppOI_IvcXXDNrsc.woff2 deleted file mode 100644 index f85eac4..0000000 Binary files a/static/assets/google-font-roboto/I3S1wsgSg9YCurV6PUkTORJtnKITppOI_IvcXXDNrsc.woff2 and /dev/null differ diff --git a/static/assets/google-font-roboto/NYDWBdD4gIq26G5XYbHsFBJtnKITppOI_IvcXXDNrsc.woff2 b/static/assets/google-font-roboto/NYDWBdD4gIq26G5XYbHsFBJtnKITppOI_IvcXXDNrsc.woff2 deleted file mode 100644 index 83bd25a..0000000 Binary files a/static/assets/google-font-roboto/NYDWBdD4gIq26G5XYbHsFBJtnKITppOI_IvcXXDNrsc.woff2 and /dev/null differ diff --git a/static/assets/google-font-roboto/NdF9MtnOpLzo-noMoG0miPesZW2xOQ-xsNqO47m55DA.woff2 b/static/assets/google-font-roboto/NdF9MtnOpLzo-noMoG0miPesZW2xOQ-xsNqO47m55DA.woff2 deleted file mode 100644 index 8857742..0000000 Binary files a/static/assets/google-font-roboto/NdF9MtnOpLzo-noMoG0miPesZW2xOQ-xsNqO47m55DA.woff2 and /dev/null differ diff --git a/static/assets/google-font-roboto/Pru33qjShpZSmG3z6VYwnRJtnKITppOI_IvcXXDNrsc.woff2 b/static/assets/google-font-roboto/Pru33qjShpZSmG3z6VYwnRJtnKITppOI_IvcXXDNrsc.woff2 deleted file mode 100644 index 397bac3..0000000 Binary files a/static/assets/google-font-roboto/Pru33qjShpZSmG3z6VYwnRJtnKITppOI_IvcXXDNrsc.woff2 and /dev/null differ diff --git a/static/assets/google-font-roboto/ek4gzZ-GeXAPcSbHtCeQI_esZW2xOQ-xsNqO47m55DA.woff2 b/static/assets/google-font-roboto/ek4gzZ-GeXAPcSbHtCeQI_esZW2xOQ-xsNqO47m55DA.woff2 deleted file mode 100644 index e7d54f2..0000000 Binary files a/static/assets/google-font-roboto/ek4gzZ-GeXAPcSbHtCeQI_esZW2xOQ-xsNqO47m55DA.woff2 and /dev/null differ diff --git a/static/assets/google-font-roboto/mErvLBYg_cXG3rLvUsKT_fesZW2xOQ-xsNqO47m55DA.woff2 b/static/assets/google-font-roboto/mErvLBYg_cXG3rLvUsKT_fesZW2xOQ-xsNqO47m55DA.woff2 deleted file mode 100644 index ee9f1a4..0000000 Binary files a/static/assets/google-font-roboto/mErvLBYg_cXG3rLvUsKT_fesZW2xOQ-xsNqO47m55DA.woff2 and /dev/null differ diff --git a/static/assets/google-font-roboto/roboto.css b/static/assets/google-font-roboto/roboto.css deleted file mode 100644 index 56bf7b9..0000000 --- a/static/assets/google-font-roboto/roboto.css +++ /dev/null @@ -1,112 +0,0 @@ -/* cyrillic-ext */ -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 300; - src: local('Roboto Light'), local('Roboto-Light'), url(0eC6fl06luXEYWpBSJvXCBJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); - unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; -} -/* cyrillic */ -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 300; - src: local('Roboto Light'), local('Roboto-Light'), url(Fl4y0QdOxyyTHEGMXX8kcRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); - unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; -} -/* greek-ext */ -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 300; - src: local('Roboto Light'), local('Roboto-Light'), url(-L14Jk06m6pUHB-5mXQQnRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); - unicode-range: U+1F00-1FFF; -} -/* greek */ -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 300; - src: local('Roboto Light'), local('Roboto-Light'), url(I3S1wsgSg9YCurV6PUkTORJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); - unicode-range: U+0370-03FF; -} -/* vietnamese */ -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 300; - src: local('Roboto Light'), local('Roboto-Light'), url(NYDWBdD4gIq26G5XYbHsFBJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); - unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; -} -/* latin-ext */ -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 300; - src: local('Roboto Light'), local('Roboto-Light'), url(Pru33qjShpZSmG3z6VYwnRJtnKITppOI_IvcXXDNrsc.woff2) format('woff2'); - unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; -} -/* latin */ -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 300; - src: local('Roboto Light'), local('Roboto-Light'), url(Hgo13k-tfSpn0qi1SFdUfVtXRa8TVwTICgirnJhmVJw.woff2) format('woff2'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215; -} -/* cyrillic-ext */ -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 400; - src: local('Roboto'), local('Roboto-Regular'), url(ek4gzZ-GeXAPcSbHtCeQI_esZW2xOQ-xsNqO47m55DA.woff2) format('woff2'); - unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; -} -/* cyrillic */ -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 400; - src: local('Roboto'), local('Roboto-Regular'), url(mErvLBYg_cXG3rLvUsKT_fesZW2xOQ-xsNqO47m55DA.woff2) format('woff2'); - unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; -} -/* greek-ext */ -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 400; - src: local('Roboto'), local('Roboto-Regular'), url(-2n2p-_Y08sg57CNWQfKNvesZW2xOQ-xsNqO47m55DA.woff2) format('woff2'); - unicode-range: U+1F00-1FFF; -} -/* greek */ -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 400; - src: local('Roboto'), local('Roboto-Regular'), url(u0TOpm082MNkS5K0Q4rhqvesZW2xOQ-xsNqO47m55DA.woff2) format('woff2'); - unicode-range: U+0370-03FF; -} -/* vietnamese */ -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 400; - src: local('Roboto'), local('Roboto-Regular'), url(NdF9MtnOpLzo-noMoG0miPesZW2xOQ-xsNqO47m55DA.woff2) format('woff2'); - unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; -} -/* latin-ext */ -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 400; - src: local('Roboto'), local('Roboto-Regular'), url(Fcx7Wwv8OzT71A3E1XOAjvesZW2xOQ-xsNqO47m55DA.woff2) format('woff2'); - unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; -} -/* latin */ -@font-face { - font-family: 'Roboto'; - font-style: normal; - font-weight: 400; - src: local('Roboto'), local('Roboto-Regular'), url(CWB0XYA8bzo0kSThX0UTuA.woff2) format('woff2'); - unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215; -} diff --git a/static/assets/google-font-roboto/u0TOpm082MNkS5K0Q4rhqvesZW2xOQ-xsNqO47m55DA.woff2 b/static/assets/google-font-roboto/u0TOpm082MNkS5K0Q4rhqvesZW2xOQ-xsNqO47m55DA.woff2 deleted file mode 100644 index e1b700c..0000000 Binary files a/static/assets/google-font-roboto/u0TOpm082MNkS5K0Q4rhqvesZW2xOQ-xsNqO47m55DA.woff2 and /dev/null differ