Videos, Lessons, and styling.

This commit is contained in:
JesseBrault0709 2024-06-11 12:36:35 +02:00
parent a95be26567
commit 3a97e0aff6
14 changed files with 296 additions and 51 deletions

View File

@ -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 }
}
}

View File

@ -20,7 +20,7 @@ class OpenGraph extends BaseWebViewComponent {
OpenGraph(@Named('baseUrl') String baseUrl, @Global('openGraphFallbackImage') String fallbackImage, Map attr) {
this.baseUrl = baseUrl
title = attr.title
type = attr.type
type = attr.type ?: 'website'
image = attr.image ?: fallbackImage
description = attr.description
path = attr.path

View File

@ -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 }
}
}

View File

@ -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>

View File

@ -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>

View 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()
}
}

View 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()
}
}

View File

@ -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>

View File

@ -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>

View File

@ -14,7 +14,7 @@ build {
basePackage 'com.jessebrault.site'
globals {
siteTagLine = 'Conductor, Composer, Developer'
menuItems = ['Biography', 'Compositions', 'Contact']
menuItems = ['Biography', 'Compositions', 'Videos', 'Lessons', 'Contact']
compositionCategories = ['Orchestra', 'Chamber', 'Solo', 'Wind Ensemble']
spotifyUrl = 'https://open.spotify.com/artist/4ea1gZnLlQTrXKIMsnlr45?si=DfR-KCDyTiycbjmYwu566w'
youtubeUrl = 'https://www.youtube.com/@JesseBrault0709'

View File

@ -29,6 +29,7 @@ body {
header {
display: flex;
align-items: flex-end;
justify-content: space-between;
padding: 15px 25px;
color: var(--off-white);
@ -36,7 +37,8 @@ header {
header .titles {
display: flex;
flex-direction: column;
align-items: baseline;
column-gap: 15px;
}
header .titles * {
@ -88,19 +90,22 @@ nav a:hover {
color: var(--off-white);
}
.banner {
.banner,
.landscape-banner {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
padding-bottom: 20px;
color: var(--off-white);
}
.banner > * {
:is(.banner, .landscape-banner) > * {
width: 100%;
}
.banner-text {
padding: 25px;
padding-inline: 20px;
letter-spacing: 0.1em;
}
@ -137,6 +142,15 @@ article h3 {
font-size: 1em;
}
article ul {
padding-inline: 40px;
text-align: left;
}
article ul li {
padding-block: 4px;
}
footer {
display: flex;
flex-direction: column;
@ -180,13 +194,15 @@ a:hover {
color: rgba(from var(--petrol) r g b / 0.5);
}
.headshot-container {
.headshot-container,
.landscape-photo-container {
display: flex;
flex-direction: column;
align-items: center;
}
.headshot {
.headshot,
.landscape-photo {
width: 100%;
}
@ -332,6 +348,19 @@ article.compositions {
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 {
font-family: var(--gothic);
}
@ -443,52 +472,32 @@ form.contact {
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) {
html {
font-size: 18px;
}
header {
display: flex;
align-items: baseline;
justify-content: space-between;
padding-inline: 30px;
}
nav .bars-wrapper {
display: none;
header .titles h2 {
display: unset;
font-size: 2em;
font-size: 18px;
letter-spacing: 0.15em;
}
nav ul {
display: flex;
}
.banner {
.banner,
.landscape-banner {
flex-direction: unset;
}
.banner > * {
padding: 15px 30px 30px;
padding: 0 30px 30px;
gap: 30px;
}
.banner-text {
padding-inline: unset;
letter-spacing: 0.15em;
padding-top: 30px;
}
article h1 {
@ -553,10 +562,32 @@ form.contact {
align-items: baseline;
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) {
header {
align-items: center;
padding-inline: 50px;
}
@ -565,9 +596,28 @@ form.contact {
letter-spacing: 0.175em;
}
.banner > * {
padding-inline: 50px;
padding-bottom: 50px;
header .titles h2 {
display: none;
}
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 {
@ -587,20 +637,16 @@ form.contact {
.biography-banner .blurb-container button {
display: unset;
}
#lessons-banner-text,
#videos-banner-text {
font-size: 2em;
}
}
@media screen and (min-width: 1200px) {
header .titles {
flex-direction: unset;
align-items: baseline;
column-gap: 15px;
}
header .titles h2 {
display: unset;
font-size: 2em;
font-size: 18px;
letter-spacing: 0.15em;
}
.contact-banner svg {

View File

@ -2,7 +2,7 @@ window.addEventListener('load', function () {
const navBars = document.getElementById('nav-bars')
const navItems = document.getElementById('nav-items')
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') {
navItems.style.display = 'none'
} else {

11
texts/Lessons.md Normal file
View 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
View 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.