Videos, Lessons, and styling.
This commit is contained in:
parent
a95be26567
commit
3a97e0aff6
@ -0,0 +1,17 @@
|
|||||||
|
package com.jessebrault.site.lessons
|
||||||
|
|
||||||
|
import com.jessebrault.ssg.view.SkipTemplate
|
||||||
|
import groowt.view.View
|
||||||
|
import groowt.view.component.web.lib.DelegatingWebViewComponent
|
||||||
|
|
||||||
|
@SkipTemplate
|
||||||
|
class LessonsBanner extends DelegatingWebViewComponent {
|
||||||
|
|
||||||
|
private static final String lessonsBannerText = LessonsBanner.getResource('LessonsBanner.txt').text
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected View getDelegate() {
|
||||||
|
return { Writer w -> w << lessonsBannerText }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -20,7 +20,7 @@ class OpenGraph extends BaseWebViewComponent {
|
|||||||
OpenGraph(@Named('baseUrl') String baseUrl, @Global('openGraphFallbackImage') String fallbackImage, Map attr) {
|
OpenGraph(@Named('baseUrl') String baseUrl, @Global('openGraphFallbackImage') String fallbackImage, Map attr) {
|
||||||
this.baseUrl = baseUrl
|
this.baseUrl = baseUrl
|
||||||
title = attr.title
|
title = attr.title
|
||||||
type = attr.type
|
type = attr.type ?: 'website'
|
||||||
image = attr.image ?: fallbackImage
|
image = attr.image ?: fallbackImage
|
||||||
description = attr.description
|
description = attr.description
|
||||||
path = attr.path
|
path = attr.path
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.jessebrault.site.videos
|
||||||
|
|
||||||
|
import com.jessebrault.ssg.view.SkipTemplate
|
||||||
|
import groowt.view.View
|
||||||
|
import groowt.view.component.web.lib.DelegatingWebViewComponent
|
||||||
|
|
||||||
|
@SkipTemplate
|
||||||
|
class VideosBanner extends DelegatingWebViewComponent {
|
||||||
|
|
||||||
|
private static final String videosBannerText = VideosBanner.getResource('VideosBanner.txt').text
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected View getDelegate() {
|
||||||
|
return { Writer w -> w << videosBannerText }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
<div id="lessons-banner" class="landscape-banner">
|
||||||
|
<div class="landscape-photo-container">
|
||||||
|
<img
|
||||||
|
src="https://jessebrault.nyc3.cdn.digitaloceanspaces.com/images/jesse-brault-bratislava.jpg"
|
||||||
|
class="landscape-photo"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div id="lessons-banner-text" class="banner-text">
|
||||||
|
<p>Now offering lessons to students of all ages!</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,14 @@
|
|||||||
|
<div id="videos-banner" class="banner">
|
||||||
|
<div class="headshot-container">
|
||||||
|
<img
|
||||||
|
src="https://jessebrault.nyc3.cdn.digitaloceanspaces.com/images/portrait4.jpg"
|
||||||
|
class="headshot"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div id="videos-banner-text" class="banner-text">
|
||||||
|
<p>
|
||||||
|
Click <a href="https://www.youtube.com/watch?v=Z46hkMmBtiY">here</a>
|
||||||
|
for a portfolio video, or scroll below for individual works.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
37
pages/groovy/com/jessebrault/site/lessons/LessonsPage.groovy
Normal file
37
pages/groovy/com/jessebrault/site/lessons/LessonsPage.groovy
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package com.jessebrault.site.lessons
|
||||||
|
|
||||||
|
import com.jessebrault.site.util.TitleMaker
|
||||||
|
import com.jessebrault.ssg.di.InjectText
|
||||||
|
import com.jessebrault.ssg.di.InjectTexts
|
||||||
|
import com.jessebrault.ssg.di.SelfPage
|
||||||
|
import com.jessebrault.ssg.page.Page
|
||||||
|
import com.jessebrault.ssg.page.PageSpec
|
||||||
|
import com.jessebrault.ssg.text.Text
|
||||||
|
import com.jessebrault.ssg.view.WvcPageView
|
||||||
|
import jakarta.inject.Inject
|
||||||
|
|
||||||
|
@PageSpec(name = 'Lessons', path = '/lessons')
|
||||||
|
class LessonsPage extends WvcPageView {
|
||||||
|
|
||||||
|
static final String description = 'Information about lessons offered by Jesse Brault.'
|
||||||
|
|
||||||
|
final Page selfPage
|
||||||
|
private final TitleMaker titleMaker
|
||||||
|
private final Text lessonsText
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
LessonsPage(@SelfPage Page selfPage, TitleMaker titleMaker, @InjectText('/Lessons.md') Text lessonsText) {
|
||||||
|
this.selfPage = selfPage
|
||||||
|
this.titleMaker = titleMaker
|
||||||
|
this.lessonsText = lessonsText
|
||||||
|
}
|
||||||
|
|
||||||
|
String getPageTitle() {
|
||||||
|
titleMaker.makeTitle(selfPage.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
String renderLessons() {
|
||||||
|
this.lessonsText.render()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
37
pages/groovy/com/jessebrault/site/videos/VideosPage.groovy
Normal file
37
pages/groovy/com/jessebrault/site/videos/VideosPage.groovy
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
package com.jessebrault.site.videos
|
||||||
|
|
||||||
|
import com.jessebrault.site.util.TitleMaker
|
||||||
|
import com.jessebrault.ssg.di.InjectText
|
||||||
|
import com.jessebrault.ssg.di.InjectTexts
|
||||||
|
import com.jessebrault.ssg.di.SelfPage
|
||||||
|
import com.jessebrault.ssg.page.Page
|
||||||
|
import com.jessebrault.ssg.page.PageSpec
|
||||||
|
import com.jessebrault.ssg.text.Text
|
||||||
|
import com.jessebrault.ssg.view.WvcPageView
|
||||||
|
import jakarta.inject.Inject
|
||||||
|
|
||||||
|
@PageSpec(name = 'Videos', path = '/videos')
|
||||||
|
class VideosPage extends WvcPageView {
|
||||||
|
|
||||||
|
static final String description = 'Conducting videos of Jesse Brault.'
|
||||||
|
|
||||||
|
final Page selfPage
|
||||||
|
private final TitleMaker titleMaker
|
||||||
|
private final Text videosText
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
VideosPage(@SelfPage Page selfPage, TitleMaker titleMaker, @InjectText('/Videos.md') Text videosText) {
|
||||||
|
this.selfPage = selfPage
|
||||||
|
this.titleMaker = titleMaker
|
||||||
|
this.videosText = videosText
|
||||||
|
}
|
||||||
|
|
||||||
|
String getPageTitle() {
|
||||||
|
titleMaker.makeTitle(selfPage.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
String renderVideos() {
|
||||||
|
videosText.render()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
package com.jessebrault.site.lessons
|
||||||
|
|
||||||
|
import com.jessebrault.site.StandardPage
|
||||||
|
import com.jessebrault.site.util.OpenGraph
|
||||||
|
---
|
||||||
|
<StandardPage
|
||||||
|
title={pageTitle}
|
||||||
|
description={description}
|
||||||
|
openGraph={<OpenGraph
|
||||||
|
title={selfPage.name}
|
||||||
|
description={description}
|
||||||
|
path={selfPage.path}
|
||||||
|
/>}
|
||||||
|
banner={<LessonsBanner />}
|
||||||
|
>
|
||||||
|
<div class="article-container">
|
||||||
|
<article id="lessons-article">
|
||||||
|
<%= renderLessons() %>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
</StandardPage>
|
@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
package com.jessebrault.site.videos
|
||||||
|
|
||||||
|
import com.jessebrault.site.StandardPage
|
||||||
|
import com.jessebrault.site.util.OpenGraph
|
||||||
|
---
|
||||||
|
<StandardPage
|
||||||
|
title={pageTitle}
|
||||||
|
description={description}
|
||||||
|
openGraph={<OpenGraph
|
||||||
|
title={selfPage.name}
|
||||||
|
description={description}
|
||||||
|
path={selfPage.path}
|
||||||
|
/>}
|
||||||
|
banner={<VideosBanner />}
|
||||||
|
>
|
||||||
|
<div class="article-container">
|
||||||
|
<article id="videos-article">
|
||||||
|
<%= renderVideos() %>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
</StandardPage>
|
@ -14,7 +14,7 @@ build {
|
|||||||
basePackage 'com.jessebrault.site'
|
basePackage 'com.jessebrault.site'
|
||||||
globals {
|
globals {
|
||||||
siteTagLine = 'Conductor, Composer, Developer'
|
siteTagLine = 'Conductor, Composer, Developer'
|
||||||
menuItems = ['Biography', 'Compositions', 'Contact']
|
menuItems = ['Biography', 'Compositions', 'Videos', 'Lessons', 'Contact']
|
||||||
compositionCategories = ['Orchestra', 'Chamber', 'Solo', 'Wind Ensemble']
|
compositionCategories = ['Orchestra', 'Chamber', 'Solo', 'Wind Ensemble']
|
||||||
spotifyUrl = 'https://open.spotify.com/artist/4ea1gZnLlQTrXKIMsnlr45?si=DfR-KCDyTiycbjmYwu566w'
|
spotifyUrl = 'https://open.spotify.com/artist/4ea1gZnLlQTrXKIMsnlr45?si=DfR-KCDyTiycbjmYwu566w'
|
||||||
youtubeUrl = 'https://www.youtube.com/@JesseBrault0709'
|
youtubeUrl = 'https://www.youtube.com/@JesseBrault0709'
|
||||||
|
142
static/main.css
142
static/main.css
@ -29,6 +29,7 @@ body {
|
|||||||
|
|
||||||
header {
|
header {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: flex-end;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 15px 25px;
|
padding: 15px 25px;
|
||||||
color: var(--off-white);
|
color: var(--off-white);
|
||||||
@ -36,7 +37,8 @@ header {
|
|||||||
|
|
||||||
header .titles {
|
header .titles {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
align-items: baseline;
|
||||||
|
column-gap: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
header .titles * {
|
header .titles * {
|
||||||
@ -88,19 +90,22 @@ nav a:hover {
|
|||||||
color: var(--off-white);
|
color: var(--off-white);
|
||||||
}
|
}
|
||||||
|
|
||||||
.banner {
|
.banner,
|
||||||
|
.landscape-banner {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
padding-bottom: 20px;
|
||||||
color: var(--off-white);
|
color: var(--off-white);
|
||||||
}
|
}
|
||||||
|
|
||||||
.banner > * {
|
:is(.banner, .landscape-banner) > * {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.banner-text {
|
.banner-text {
|
||||||
padding: 25px;
|
padding-inline: 20px;
|
||||||
letter-spacing: 0.1em;
|
letter-spacing: 0.1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,6 +142,15 @@ article h3 {
|
|||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
article ul {
|
||||||
|
padding-inline: 40px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
article ul li {
|
||||||
|
padding-block: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
footer {
|
footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -180,13 +194,15 @@ a:hover {
|
|||||||
color: rgba(from var(--petrol) r g b / 0.5);
|
color: rgba(from var(--petrol) r g b / 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
.headshot-container {
|
.headshot-container,
|
||||||
|
.landscape-photo-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.headshot {
|
.headshot,
|
||||||
|
.landscape-photo {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,6 +348,19 @@ article.compositions {
|
|||||||
margin-block-start: 2em;
|
margin-block-start: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#lessons-banner-text,
|
||||||
|
#videos-banner-text {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#videos-banner-text :is(a, a:visited) {
|
||||||
|
color: var(--light-gray);
|
||||||
|
}
|
||||||
|
|
||||||
|
#videos-banner-text a:hover {
|
||||||
|
color: var(--off-white);
|
||||||
|
}
|
||||||
|
|
||||||
.contact-banner article.social-media-links {
|
.contact-banner article.social-media-links {
|
||||||
font-family: var(--gothic);
|
font-family: var(--gothic);
|
||||||
}
|
}
|
||||||
@ -443,52 +472,32 @@ form.contact {
|
|||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (max-width: 767px) {
|
|
||||||
nav ul {
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
z-index: 1;
|
|
||||||
width: 100%;
|
|
||||||
display: none;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
row-gap: 10px;
|
|
||||||
background-color: var(--petrol);
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (min-width: 768px) {
|
@media screen and (min-width: 768px) {
|
||||||
html {
|
html {
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
header {
|
header {
|
||||||
display: flex;
|
|
||||||
align-items: baseline;
|
|
||||||
justify-content: space-between;
|
|
||||||
padding-inline: 30px;
|
padding-inline: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
nav .bars-wrapper {
|
header .titles h2 {
|
||||||
display: none;
|
display: unset;
|
||||||
|
font-size: 2em;
|
||||||
|
font-size: 18px;
|
||||||
|
letter-spacing: 0.15em;
|
||||||
}
|
}
|
||||||
|
|
||||||
nav ul {
|
.banner,
|
||||||
display: flex;
|
.landscape-banner {
|
||||||
}
|
|
||||||
|
|
||||||
.banner {
|
|
||||||
flex-direction: unset;
|
flex-direction: unset;
|
||||||
}
|
padding: 0 30px 30px;
|
||||||
|
gap: 30px;
|
||||||
.banner > * {
|
|
||||||
padding: 15px 30px 30px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.banner-text {
|
.banner-text {
|
||||||
|
padding-inline: unset;
|
||||||
letter-spacing: 0.15em;
|
letter-spacing: 0.15em;
|
||||||
padding-top: 30px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
article h1 {
|
article h1 {
|
||||||
@ -553,10 +562,32 @@ form.contact {
|
|||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#lessons-banner-text,
|
||||||
|
#videos-banner-text {
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 1023px) {
|
||||||
|
nav ul {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
z-index: 1;
|
||||||
|
width: 100%;
|
||||||
|
display: none;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
row-gap: 10px;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: var(--petrol);
|
||||||
|
border-bottom: 1px solid var(--charcoal);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (min-width: 1024px) {
|
@media screen and (min-width: 1024px) {
|
||||||
header {
|
header {
|
||||||
|
align-items: center;
|
||||||
padding-inline: 50px;
|
padding-inline: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -565,9 +596,28 @@ form.contact {
|
|||||||
letter-spacing: 0.175em;
|
letter-spacing: 0.175em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.banner > * {
|
header .titles h2 {
|
||||||
padding-inline: 50px;
|
display: none;
|
||||||
padding-bottom: 50px;
|
}
|
||||||
|
|
||||||
|
nav .bars-wrapper {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav ul {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner,
|
||||||
|
.landscape-banner {
|
||||||
|
padding: 0 50px 50px;
|
||||||
|
gap: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.landscape-banner {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1.5fr 1fr;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
footer {
|
footer {
|
||||||
@ -587,20 +637,16 @@ form.contact {
|
|||||||
.biography-banner .blurb-container button {
|
.biography-banner .blurb-container button {
|
||||||
display: unset;
|
display: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#lessons-banner-text,
|
||||||
|
#videos-banner-text {
|
||||||
|
font-size: 2em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen and (min-width: 1200px) {
|
@media screen and (min-width: 1200px) {
|
||||||
header .titles {
|
|
||||||
flex-direction: unset;
|
|
||||||
align-items: baseline;
|
|
||||||
column-gap: 15px;
|
|
||||||
}
|
|
||||||
|
|
||||||
header .titles h2 {
|
header .titles h2 {
|
||||||
display: unset;
|
display: unset;
|
||||||
font-size: 2em;
|
|
||||||
font-size: 18px;
|
|
||||||
letter-spacing: 0.15em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.contact-banner svg {
|
.contact-banner svg {
|
||||||
|
@ -2,7 +2,7 @@ window.addEventListener('load', function () {
|
|||||||
const navBars = document.getElementById('nav-bars')
|
const navBars = document.getElementById('nav-bars')
|
||||||
const navItems = document.getElementById('nav-items')
|
const navItems = document.getElementById('nav-items')
|
||||||
navBars.addEventListener('click', function () {
|
navBars.addEventListener('click', function () {
|
||||||
if (window.matchMedia('screen and (max-width: 767px)').matches) {
|
if (window.matchMedia('screen and (max-width: 1023px)').matches) {
|
||||||
if (navItems.style.display === 'flex') {
|
if (navItems.style.display === 'flex') {
|
||||||
navItems.style.display = 'none'
|
navItems.style.display = 'none'
|
||||||
} else {
|
} else {
|
||||||
|
11
texts/Lessons.md
Normal file
11
texts/Lessons.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# Lessons
|
||||||
|
|
||||||
|
I offer remote lessons (as well as in-person lessons in Berlin, Germany) for the following subjects:
|
||||||
|
|
||||||
|
- Music Theory
|
||||||
|
- Ear Training
|
||||||
|
- Music Composition
|
||||||
|
- Score Study
|
||||||
|
- Beginning and Intermediate Piano (in person in Berlin only)
|
||||||
|
|
||||||
|
I offer flexible hourly rates. Please [contact](/contact) me to schedule your first lesson!
|
11
texts/Videos.md
Normal file
11
texts/Videos.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# Conducting Videos
|
||||||
|
|
||||||
|
Videos of the following works are available on YouTube:
|
||||||
|
|
||||||
|
- [Beethoven: Symphony no. 4: II. Adagio](https://www.youtube.com/watch?v=QfqlwB8cnTA)
|
||||||
|
- [Brahms: Symphony no. 3: II. Andante](https://www.youtube.com/watch?v=Js8EXhM2kOQ)
|
||||||
|
- [Brahms: Symphony no. 4: IV. Allegro energico e passionato](https://www.youtube.com/watch?v=3gZl0NPuxOc)
|
||||||
|
- [Britten: Four Sea Interludes: II. Sunday Morning](https://www.youtube.com/watch?v=j9LUHck6B7M)
|
||||||
|
- [Debussy: Prélude à l'après-midi d'un Faune](https://www.youtube.com/watch?v=qMjjrYCfI8s)
|
||||||
|
|
||||||
|
If you require additional video material, please [contact](/contact) me.
|
Loading…
Reference in New Issue
Block a user