Update handling of news

This commit is contained in:
Tom Wiesing 2023-01-09 11:19:47 +01:00
parent 73d821e320
commit dcd5f910ae
No known key found for this signature in database
22 changed files with 587 additions and 61 deletions

View file

@ -2,9 +2,15 @@
{{ define "title" }}WissKI Distillery{{ end }}
{{ define "header"}}
<!-- no header -->
<p>
<a class="pure-button pure-button-primary" href="/">Home</a>
</p>
<p>
<a class="pure-button" href="/news/">News</a>
</p>
{{ end }}
{{ define "content" }}
{{ block "@custom/about" . }}
<div class="pure-u-1">
@ -23,7 +29,7 @@
<div class="pure-u-1 pure-u-md-1-3">
<h3>{{.Slug}}</h3>
<p>
<a href="{{.URL}}" target="_blank" rel="noopener noreferrer">{{.URL}}</a><br>
<a href="{{.URL}}" target="_blank" rel="noopener noreferrer" class="wisskilink">{{.URL}}</a><br>
<small>
{{ .Statistics.Bundles.Summary }}

View file

@ -0,0 +1,7 @@
---
title: Migration to go
date: 2022-09-08
---
- We have ported the distillery from a set of bash scripts to a self-contained go executable
- This makes future development easier, and allows us to develop new features easier

View file

@ -0,0 +1,10 @@
---
title: Addition of an administrative server
date: 2022-09-09
---
- We have added a new web route under `/dis/`
- Allows administrators to manage WissKI Instances and see their status
- Administrators can e.g. download pathbuilders and make backups and snapshots
- At this point it is only for administrators
- A future (public) server with statistics will follow

View file

@ -0,0 +1,8 @@
---
title: Addition of a Global Distillery Resolver
date: 2022-10-05
---
- We have added a global WissKI Resolver, that functions similarly to the WissKI resolver under `/wisski/`.
- It can resolve WissKI URIs for the entire distillery, and redirect to their view page.
- Can be called exactly like the `/wisski/get?uri=` route of individual WissKIs, but toplevel on the distillery.

View file

@ -0,0 +1,8 @@
---
title: Migration to Traefik & Support for HTTP3
date: 2022-10-12
---
- We have migrated the entry point from nginx to [traefik](https://traefik.io/traefik/)
- This enables much cleaner support for automatically fetching and renewing SSL certificates
- It is now possible to turn on http3 support for the entire distillery

View file

@ -0,0 +1,8 @@
---
title: Refactored SSH Support
date: 2022-11-12
---
- Fully refactored ssh for users to use a real OpenSSH Server along with a small custom proxy in between
- It is now possible for developers to directly use e.g. [VSCode Remote SSH](https://code.visualstudio.com/docs/remote/ssh) to develop new WissKI features directly on the distillery.
- No configuration beyond regular ssh access is neccessary

View file

@ -0,0 +1,7 @@
---
title: Showing Statistics
date: 2022-11-16
---
- The distillery nows shows generic statistics on the public homepage
- detailed statistics can be found on the admin interface

View file

@ -0,0 +1,6 @@
---
title: Login using Distillery Administration
date: 2022-11-23
---
- The admin interface now allows login to individual user accounts

View file

@ -0,0 +1,6 @@
---
title: Automatic Password Checking
date: 2022-11-25
---
- Implemented automatic password checking

View file

@ -0,0 +1,15 @@
---
title: User And Instance Management
date: 2023-01-07
---
- the concept of distillery user accounts has been added
- their accounts have a password as well as TOTP
- users can manage their own account details
- administrators can reset user passwords, and disable TOTP
- distillery accounts can be linked to multiple drupal accounts
- users can sign into the account without entering further passwords
- users must have two-factor-authentication enabled to use this functionality
- administrators have access to the distillery admin panel
- the functionality to manage distillery accounts has been added
- the functionality to link distillery and drupal accounts has been added

View file

@ -0,0 +1,6 @@
---
title: News on the homepage
date: 2023-01-09
---
- we are now linking and showing the news section from the homepage

View file

@ -0,0 +1,135 @@
package news
import (
"context"
"embed"
"html/template"
"io/fs"
"net/http"
"strings"
"time"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/control/static"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/control/static/custom"
"github.com/FAU-CDI/wisski-distillery/pkg/httpx"
"github.com/FAU-CDI/wisski-distillery/pkg/lazy"
"github.com/yuin/goldmark"
gmmeta "github.com/yuin/goldmark-meta"
"github.com/yuin/goldmark/parser"
"golang.org/x/exp/slices"
)
type News struct {
component.Base
Dependencies struct {
Custom *custom.Custom
}
}
var (
_ component.Routeable = (*News)(nil)
)
func (*News) Routes() component.Routes {
return component.Routes{
Paths: []string{"/news/"},
CSRF: false,
}
}
type Item struct {
ID string
Date time.Time
Title string
Content template.HTML
}
func (item *Item) parse(path string, builder *strings.Builder) error {
builder.Reset()
// open file
content, err := fs.ReadFile(newsFS, path)
if err != nil {
return err
}
// parse and read metadata
reader := goldmark.New(goldmark.WithExtensions(
gmmeta.Meta,
))
context := parser.NewContext()
if err := reader.Convert(content, builder, parser.WithContext(context)); err != nil {
return err
}
meta := gmmeta.Get(context)
// read title
item.Title, _ = meta["title"].(string)
// read date
date, _ := meta["date"].(string)
item.Date, err = time.Parse("2006-01-02", date)
if err != nil {
return err
}
// write content
item.Content = template.HTML(builder.String())
return nil
}
//go:embed "NEWS/*.md"
var newsFS embed.FS
var news lazy.Lazy[[]Item]
// Items returns a list of all news items
func Items() []Item {
return news.Get(func() (items []Item) {
var builder strings.Builder
files, err := fs.Glob(newsFS, "NEWS/*.md")
if err != nil {
panic(err)
}
items = make([]Item, len(files))
for i, file := range files {
items[i].ID = file[len("NEWS/") : len(file)-len(".md")]
if err := items[i].parse(file, &builder); err != nil {
panic(err)
}
}
slices.SortFunc(items, func(a, b Item) bool {
return !a.Date.Before(b.Date)
})
return
})
}
//go:embed "news.html"
var newsHTMLStr string
var newsTemplate = static.AssetsHome.MustParseShared("news.html", newsHTMLStr)
type newsContext struct {
custom.BaseContext
Items []Item
}
// HandleRoute returns the handler for the requested path
func (news *News) HandleRoute(ctx context.Context, path string) (http.Handler, error) {
newsTemplate := news.Dependencies.Custom.Template(newsTemplate)
return httpx.HTMLHandler[newsContext]{
Handler: func(r *http.Request) (nc newsContext, err error) {
news.Dependencies.Custom.Update(&nc, r)
nc.Items = Items()
return
},
Template: newsTemplate,
}, nil
}

View file

@ -0,0 +1,25 @@
{{ template "_base.html" . }}
{{ define "title" }}News{{ end }}
{{ define "header"}}
<p>
<a class="pure-button" href="/">Home</a> &gt;
<a class="pure-button pure-button-primary" href="/news/">News</a>
</p>
{{ end }}
{{ define "content" }}
<div class="pure-u-1">
This page contains news items from the distillery.
</div>
{{range .Items}}
<div class="pure-u-1">
<h2 id="{{.ID}}">{{.Title}}</h3>
<b>{{ .Date.Format "2006-01-02" }}</b>
{{ .Content }}
</div>
{{ end }}
{{ end }}

View file

@ -10,7 +10,7 @@ var AssetsDisclaimer string
// AssetsHome contains assets for the 'Home' entrypoint.
var AssetsHome = Assets{
Scripts: `<script type="module" src="/static/Home.38d394c2.js"></script><script src="/static/Home.38d394c2.js" nomodule="" defer></script><script type="module" src="/static/Home.38d394c2.js"></script><script src="/static/Home.38d394c2.js" nomodule="" defer></script>`,
Styles: `<link rel="stylesheet" href="/static/Home.4b303448.css"><link rel="stylesheet" href="/static/Home.2353e048.css">`,
Styles: `<link rel="stylesheet" href="/static/Home.4b303448.css"><link rel="stylesheet" href="/static/Home.f9675eae.css">`,
}
// AssetsUser contains assets for the 'User' entrypoint.

View file

@ -1 +0,0 @@
a{color:#00f!important}

View file

@ -0,0 +1 @@
a.wisskilink{color:#00f!important}

View file

@ -1,3 +1,3 @@
a {
a.wisskilink {
color: blue !important;
}