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

File diff suppressed because one or more lines are too long

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

View file

@ -16,6 +16,7 @@ import (
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/control/cron"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/control/home"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/control/legal"
"github.com/FAU-CDI/wisski-distillery/internal/dis/component/control/news"
"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/internal/dis/component/exporter"
@ -173,6 +174,7 @@ func (dis *Distillery) allComponents() []initFunc {
admin.Analytics = &dis.pool.Analytics
}),
auto[*legal.Legal],
auto[*news.News],
auto[*static.Static],
auto[*custom.Custom],