Update handling of news
This commit is contained in:
parent
73d821e320
commit
dcd5f910ae
22 changed files with 587 additions and 61 deletions
File diff suppressed because one or more lines are too long
|
|
@ -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 }}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
10
internal/dis/component/control/news/NEWS/2022-09-09-admin.md
Normal file
10
internal/dis/component/control/news/NEWS/2022-09-09-admin.md
Normal 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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: Login using Distillery Administration
|
||||
date: 2022-11-23
|
||||
---
|
||||
|
||||
- The admin interface now allows login to individual user accounts
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
title: Automatic Password Checking
|
||||
date: 2022-11-25
|
||||
---
|
||||
|
||||
- Implemented automatic password checking
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
135
internal/dis/component/control/news/news.go
Normal file
135
internal/dis/component/control/news/news.go
Normal 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
|
||||
}
|
||||
25
internal/dis/component/control/news/news.html
Normal file
25
internal/dis/component/control/news/news.html
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
{{ template "_base.html" . }}
|
||||
{{ define "title" }}News{{ end }}
|
||||
|
||||
{{ define "header"}}
|
||||
<p>
|
||||
<a class="pure-button" href="/">Home</a> >
|
||||
<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 }}
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
a{color:#00f!important}
|
||||
1
internal/dis/component/control/static/dist/Home.f9675eae.css
vendored
Normal file
1
internal/dis/component/control/static/dist/Home.f9675eae.css
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
a.wisskilink{color:#00f!important}
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
a {
|
||||
a.wisskilink {
|
||||
color: blue !important;
|
||||
}
|
||||
|
|
@ -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],
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue