Better edu home page

This commit is contained in:
Ben Visness 2022-10-27 00:20:59 -05:00
parent 4e44ba0b45
commit 48af5e650d
9 changed files with 171 additions and 31 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

BIN
public/education/time.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

View File

@ -7394,7 +7394,7 @@ article code {
border-color: #aaa; border-color: #aaa;
border-color: var(--theme-color-dim); } border-color: var(--theme-color-dim); }
.c--dimmer, footer .list li:not(:last-child)::after { .c--dimmer, footer .list li:not(:last-child)::after, .edu-course .edu-article.coming-soon {
color: #999; color: #999;
color: var(--dimmer-color); } color: var(--dimmer-color); }
@ -8306,6 +8306,27 @@ nav.timecodes {
text-align: center; text-align: center;
margin: 10px 0; } margin: 10px 0; }
.edu-course .edu-article.coming-soon {
font-style: italic; }
.edu-course .edu-article::after {
content: '';
position: absolute;
width: 1rem;
height: 10rem;
border-width: 0 0 1px 1px;
border-style: solid;
border-color: #bbb;
border-color: var(--dimmest-color);
left: -1.5rem;
top: -9rem;
border-bottom-left-radius: 0.5rem; }
.edu-topic img {
width: 100%;
height: 14rem;
object-fit: cover; }
.edu-article .note { .edu-article .note {
color: red; } color: red; }

View File

@ -1,3 +1,32 @@
.edu-course {
.edu-article.coming-soon {
@extend .c--dimmer;
font-style: italic;
}
.edu-article::after {
$height: 10rem;
content: '';
position: absolute;
width: 1rem;
height: $height;
border-width: 0 0 1px 1px;
border-style: solid;
@include usevar(border-color, dimmest-color);
left: -1.5rem;
top: 1rem - $height;
border-bottom-left-radius: 0.5rem;
}
}
.edu-topic {
img {
width: 100%;
height: 14rem;
object-fit: cover;
}
}
.edu-article { .edu-article {
.note { .note {
color: red; color: red;

View File

@ -41,7 +41,7 @@
{{ end }} {{ end }}
{{ define "content" }} {{ define "content" }}
<div class="ph2 ph0-ns"> <div class="ph3 ph0-ns">
<h1>{{ .Title }}</h1> <h1>{{ .Title }}</h1>
{{ if and .User .User.IsEduAuthor }} {{ if and .User .User.IsEduAuthor }}
<div class="mb3"> <div class="mb3">

View File

@ -1,28 +1,44 @@
{{ template "base.html" . }} {{ template "base.html" . }}
{{ define "content" }} {{ define "content" }}
<div class="ph3 ph0-ns">
<h1>Learn the Handmade way.</h1> <h1>Learn the Handmade way.</h1>
<h2>Guides</h2> <p>Dive into one of these topics and start learning.</p>
{{ if and .User .User.IsEduAuthor }} <div class="flex flex-column flex-row-ns g3 mt3 mb4">
<div class="mb2"> <a href="#compilers" class="edu-topic db flex-fair-ns bg--dim br3 overflow-hidden c--inherit flex flex-column">
<a href="{{ .NewArticleUrl }}"><span class="big pr1">+</span> New Article</a> <img src="{{ static "education/compilers.jpg" }}">
</div> <div class="pa3">
{{ end }} <h2>Compilers</h2>
<div>
<div class="flex flex-column g3 mb3"> Learn how programming languages are made.
{{ range .Articles }} </div>
<a class="c--inherit flex flex-column pa3 bg--dim br2" href="{{ .Url }}" > </div>
<h3 class="mb1 link">{{ .Title }}</h3> </a>
<div>{{ .Description }}</div> <a href="#networking" class="edu-topic db flex-fair-ns bg--dim br3 overflow-hidden c--inherit flex flex-column">
</a> <img src="{{ static "education/networking.jpg" }}">
{{ end }} <div class="pa3">
<h2>Networking</h2>
<div>
Learn how computers communicate, and how the internet actually works.
</div>
</div>
</a>
<a href="#time" class="edu-topic db flex-fair-ns bg--dim br3 overflow-hidden c--inherit flex flex-column">
<img src="{{ static "education/time.jpg" }}">
<div class="pa3">
<h2>Time</h2>
<div>
Get better at handling time, from calendars to timezones to clock sync.
</div>
</div>
</a>
</div> </div>
<h2>What makes us different?</h2> <h2>What makes us different?</h2>
<div class="flex flex-column flex-row-ns g3"> <div class="flex flex-column flex-row-ns g3 mb4">
<div class="flex-fair bg--dim pa3 br2"> <div class="flex-fair bg--dim pa3 br2">
<h3>Real material.</h3> <h3>Real material.</h3>
@ -40,10 +56,34 @@
</div> </div>
</div> </div>
{{ if and .User .User.IsEduAuthor }} <h2>All Topics</h2>
<div class="mt3">
<b>SECRET AUTHOR MAINTENANCE COMMANDS:</b> {{ range .Courses }}
<a href="{{ .RerenderUrl }}">Rerender all content</a> <div id="{{ .Slug }}" class="edu-course mv3 bg--dim pa3 br3">
<h3>{{ .Name }}</h3>
<div class="overflow-hidden">
<div class="edu-articles ml3 pl3">
{{ range .Articles }}
<div class="edu-article mt3 relative {{ if not .Published }}coming-soon{{ end }}">
{{ if or (and $.User $.User.IsEduTester) .Published }}
<a href="{{ .Url }}"><h4>{{ .Title }}</h4></a>
{{ else }}
<h4>{{ .Title }} (coming soon)</h4>
{{ end }}
<div>{{ .Description }}</div>
</div>
{{ end }}
</div>
</div>
</div> </div>
{{ end }} {{ end }}
{{ if and .User .User.IsEduAuthor }}
<div class="mt3">
<b>SECRET AUTHOR COMMANDS:</b>
<div><a href="{{ .RerenderUrl }}">Rerender all content</a></div>
<div><a href="{{ .NewArticleUrl }}"><span class="big pr1">+</span> New Article</a></div>
</div>
{{ end }}
</div>
{{ end }} {{ end }}

View File

@ -395,6 +395,12 @@ type TextEditor struct {
UploadUrl string UploadUrl string
} }
type EduCourse struct {
Name string
Slug string
Articles []EduArticle
}
type EduArticle struct { type EduArticle struct {
Title string Title string
Slug string Slug string

View File

@ -23,24 +23,68 @@ import (
func EducationIndex(c *RequestContext) ResponseData { func EducationIndex(c *RequestContext) ResponseData {
type indexData struct { type indexData struct {
templates.BaseData templates.BaseData
Articles []templates.EduArticle Courses []templates.EduCourse
NewArticleUrl string NewArticleUrl string
RerenderUrl string RerenderUrl string
} }
articles, err := fetchEduArticles(c, c.Conn, models.EduArticleTypeArticle, c.CurrentUser) // TODO: Someday this can be dynamic again? Maybe? Or not? Who knows??
if err != nil { // articles, err := fetchEduArticles(c, c.Conn, models.EduArticleTypeArticle, c.CurrentUser)
panic(err) // if err != nil {
} // panic(err)
// }
var tmplArticles []templates.EduArticle // var tmplArticles []templates.EduArticle
for _, article := range articles { // for _, article := range articles {
tmplArticles = append(tmplArticles, templates.EducationArticleToTemplate(&article)) // tmplArticles = append(tmplArticles, templates.EducationArticleToTemplate(&article))
// }
article := func(slug string) templates.EduArticle {
if article, err := fetchEduArticle(c, c.Conn, slug, models.EduArticleTypeArticle, c.CurrentUser); err == nil {
return templates.EducationArticleToTemplate(article)
} else if errors.Is(err, db.NotFound) {
return templates.EduArticle{
Title: "<UNKNOWN ARTICLE>",
}
} else {
panic(err)
}
} }
tmpl := indexData{ tmpl := indexData{
BaseData: getBaseData(c, "Handmade Education", nil), BaseData: getBaseData(c, "Handmade Education", nil),
Articles: tmplArticles, Courses: []templates.EduCourse{
{
Name: "Compilers",
Slug: "compilers",
Articles: []templates.EduArticle{
article("compilers"),
{
Title: "Baby's first language theory",
Description: "State machines, abstract datatypes, type theory...",
},
},
},
{
Name: "Networking",
Slug: "networking",
Articles: []templates.EduArticle{
article("networking"),
{
Title: "Internet infrastructure",
Description: "How does the internet actually work? How does your ISP know where to send your data? What happens to the internet if physical communication breaks down?",
},
},
},
{
Name: "Time",
Slug: "time",
Articles: []templates.EduArticle{
article("time"),
article("ntp"),
},
},
},
NewArticleUrl: hmnurl.BuildEducationArticleNew(), NewArticleUrl: hmnurl.BuildEducationArticleNew(),
RerenderUrl: hmnurl.BuildEducationRerender(), RerenderUrl: hmnurl.BuildEducationRerender(),
} }