Skip to content

Commit

Permalink
Switch publisher to Bootstrap based tempaltes & add dark theme
Browse files Browse the repository at this point in the history
Signed-off-by: Igor Shishkin <me@teran.ru>
  • Loading branch information
teran committed Jan 2, 2025
1 parent d6e5ff2 commit 55f87ec
Show file tree
Hide file tree
Showing 22 changed files with 595 additions and 139 deletions.
8 changes: 7 additions & 1 deletion cmd/publisher/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ type config struct {
VersionsPerPage uint64 `envconfig:"VERSIONS_PER_PAGE" default:"50"`
ObjectsPerPage uint64 `envconfig:"OBJECTS_PER_PAGE" default:"50"`
ContainersPerPage uint64 `envconfig:"CONTAINERS_PER_PAGE" default:"50"`

MaxPagesInPagination uint64 `envconfig:"MAX_PAGES_IN_PAGINATION" default:"5"`
DefaultTheme htmlPresenter.Theme `envconfig:"DEFAULT_THEME" default:"dark"`
}

func main() {
Expand Down Expand Up @@ -126,7 +129,10 @@ func main() {

publisherSvc := service.NewPublisher(repo, blobRepo, cfg.VersionsPerPage, cfg.ObjectsPerPage, cfg.ContainersPerPage)

p := htmlPresenter.New(publisherSvc, cfg.HTMLTemplateDir, cfg.StaticDir, cfg.BLOBS3PreserveSchemeOnRedirect)
p := htmlPresenter.New(publisherSvc, cfg.HTMLTemplateDir, cfg.StaticDir, cfg.BLOBS3PreserveSchemeOnRedirect, htmlPresenter.DisplayConfig{
DefaultTheme: cfg.DefaultTheme,
MaxPagesInPagination: cfg.MaxPagesInPagination,
})
p.Register(e)

g.Go(func() error {
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ services:
METADATA_DSN: postgres://postgres:password@postgresql?sslmode=disable
BLOB_S3_ENDPOINT: "${ARCHIVED_BLOB_S3_ENDPOINT:-http://minio:9000}"
BLOB_S3_BUCKET: "${ARCHIVED_BLOB_S3_BUCKET:-test-bucket}"
BLOB_S3_CREATE_BUCKET: "true"
BLOB_S3_CREATE_BUCKET: "false"
BLOB_S3_ACCESS_KEY_ID: minioadmin
BLOB_S3_SECRET_KEY: minioadmin
ports:
Expand Down
36 changes: 33 additions & 3 deletions dockerfiles/Dockerfile.publisher
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,44 @@ FROM alpine:3.20.3 AS certificates
RUN apk add --update --no-cache \
ca-certificates=20240705-r0

FROM scratch
FROM index.docker.io/library/node:22.12.0 AS depsbuilder

RUN mkdir /src
WORKDIR /src
RUN npm install \
bootstrap@5.3.3 \
bootstrap-icons@1.11.3

FROM index.docker.io/library/node:22.12.0 AS tsbuilder

RUN mkdir /src
WORKDIR /src
RUN npm install -g typescript

Check failure on line 18 in dockerfiles/Dockerfile.publisher

View workflow job for this annotation

GitHub Actions / hadolint-publisher

DL3016 warning: Pin versions in npm. Instead of `npm install <package>` use `npm install <package>@<version>`
COPY publisher/presenter/html/static/scripts /src/scripts
RUN tsc scripts/index.ts --strict --removeComments --outDir /build

FROM ubuntu:24.04

RUN mkdir -p \
/static/archived/scripts \
/static/archived/styles


COPY dockerfiles/rootfs/etc/passwd /etc/passwd
COPY dockerfiles/rootfs/etc/group /etc/group

COPY --from=certificates /etc/ssl/cert.pem /etc/ssl/cert.pem
COPY --from=certificates --chown=root:root --chmod=0644 /etc/ssl/cert.pem /etc/ssl/cert.pem
COPY --chmod=0755 --chown=root:root dist/archived-publisher_linux_amd64_v3/archived-publisher /archived-publisher
COPY --chmod=0644 --chown=root:root publisher/presenter/html/templates /templates
COPY --chmod=0755 --chown=root:root publisher/presenter/html/templates /templates
COPY --chmod=0755 --chown=root:root publisher/presenter/html/static /static/archived

COPY --from=tsbuilder --chown=root:root --chmod=0644 /build /static/archived/scripts

COPY --from=depsbuilder --chown=root:root /src/node_modules/bootstrap/dist /static/bootstrap
COPY --from=depsbuilder --chown=root:root /src/node_modules/@popperjs/core/dist/umd /static/popperjs
COPY --from=depsbuilder --chown=root:root /src/node_modules/bootstrap-icons/bootstrap-icons.svg /static/bootstrap-icons/bootstrap-icons.svg
COPY --from=depsbuilder --chown=root:root /src/node_modules/bootstrap-icons/font /static/bootstrap-icons/font
COPY --from=depsbuilder --chown=root:root /src/node_modules/bootstrap-icons/icons /static/bootstrap-icons/icons

ENV HTML_TEMPLATE_DIR=/templates
ENV STATIC_DIR=/static
Expand Down
98 changes: 57 additions & 41 deletions publisher/presenter/html/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,33 @@ type Handlers interface {
Register(e *echo.Echo)
}

type Theme string

const (
ThemeDark Theme = "dark"
ThemeLight Theme = "light"
)

type DisplayConfig struct {
DefaultTheme Theme
MaxPagesInPagination uint64
}

type handlers struct {
svc service.Publisher
staticDir string
templateDir string
preserveSchemeOnRedirect bool
dc DisplayConfig
}

func New(svc service.Publisher, templateDir, staticDir string, preserveSchemeOnRedirect bool) Handlers {
func New(svc service.Publisher, templateDir, staticDir string, preserveSchemeOnRedirect bool, dc DisplayConfig) Handlers {
return &handlers{
svc: svc,
staticDir: staticDir,
templateDir: templateDir,
preserveSchemeOnRedirect: preserveSchemeOnRedirect,
dc: dc,
}
}

Expand All @@ -52,13 +66,15 @@ func (h *handlers) NamespaceIndex(c echo.Context) error {
}

type data struct {
Title string
Namespaces []string
Title string
DefaultTheme Theme
Namespaces []string
}

return c.Render(http.StatusOK, "namespace-list.html", &data{
Title: "Namespace index",
Namespaces: namespaces,
Title: "Namespace index",
DefaultTheme: h.dc.DefaultTheme,
Namespaces: namespaces,
})
}

Expand Down Expand Up @@ -86,19 +102,19 @@ func (h *handlers) ContainerIndex(c echo.Context) error {
}

type data struct {
Title string
CurrentPage uint64
PagesCount uint64
Namespace string
Containers []models.Container
Title string
DefaultTheme Theme
Pagination Pagination
Namespace string
Containers []models.Container
}

return c.Render(http.StatusOK, "container-list.html", &data{
Title: fmt.Sprintf("Container index (%s)", namespace),
CurrentPage: page,
PagesCount: pagesCount,
Namespace: namespace,
Containers: containers,
Title: fmt.Sprintf("Container index (%s)", namespace),
DefaultTheme: h.dc.DefaultTheme,
Pagination: NewPagination(pagesCount, page, h.dc.MaxPagesInPagination, fmt.Sprintf("/%s/", namespace)),
Namespace: namespace,
Containers: containers,
})
}

Expand Down Expand Up @@ -127,21 +143,21 @@ func (h *handlers) VersionIndex(c echo.Context) error {
}

type data struct {
Title string
CurrentPage uint64
PagesCount uint64
Namespace string
Container string
Versions []models.Version
Title string
DefaultTheme Theme
Pagination Pagination
Namespace string
Container string
Versions []models.Version
}

return c.Render(http.StatusOK, "version-list.html", &data{
Title: fmt.Sprintf("Version index (%s/%s)", namespace, container),
CurrentPage: page,
PagesCount: pagesCount,
Namespace: namespace,
Container: container,
Versions: versions,
Title: fmt.Sprintf("Version index (%s/%s)", namespace, container),
DefaultTheme: h.dc.DefaultTheme,
Pagination: NewPagination(pagesCount, page, h.dc.MaxPagesInPagination, fmt.Sprintf("/%s/%s/", namespace, container)),
Namespace: namespace,
Container: container,
Versions: versions,
})
}

Expand Down Expand Up @@ -171,22 +187,22 @@ func (h *handlers) ObjectIndex(c echo.Context) error {
}

type data struct {
Title string
CurrentPage uint64
PagesCount uint64
Namespace string
Container string
Version string
Objects []string
Title string
DefaultTheme Theme
Pagination Pagination
Namespace string
Container string
Version string
Objects []string
}
return c.Render(http.StatusOK, "object-list.html", &data{
Title: fmt.Sprintf("Object index (%s/%s/%s)", namespace, container, version),
CurrentPage: page,
PagesCount: pagesCount,
Namespace: namespace,
Container: container,
Version: version,
Objects: objects,
Title: fmt.Sprintf("Object index (%s/%s/%s)", namespace, container, version),
DefaultTheme: h.dc.DefaultTheme,
Pagination: NewPagination(pagesCount, page, h.dc.MaxPagesInPagination, fmt.Sprintf("/%s/%s/%s/", namespace, container, version)),
Namespace: namespace,
Container: container,
Version: version,
Objects: objects,
})
}

Expand Down
5 changes: 4 additions & 1 deletion publisher/presenter/html/handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,10 @@ func (s *handlersTestSuite) SetupTest() {

s.serviceMock = service.NewMock()

s.handlers = New(s.serviceMock, "templates", "static", true)
s.handlers = New(s.serviceMock, "templates", "static", true, DisplayConfig{
DefaultTheme: ThemeDark,
MaxPagesInPagination: 5,
})
s.handlers.Register(e)

s.srv = httptest.NewServer(e)
Expand Down
70 changes: 70 additions & 0 deletions publisher/presenter/html/pagination.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package html

import "strconv"

type Pagination struct {
HasPrevious bool
PreviousPageNum uint64
PreviousPageURL string
Pages []Page
HasNext bool
NextPageNum uint64
NextPageURL string
}

type Page struct {
IsCurrent bool
Number uint64
URL string
}

func NewPagination(total, current, maxPages uint64, pageURL string) Pagination {
pages := []Page{}
max := current + maxPages
if current+maxPages > total {
max = total
}
for i := current; i <= max; i++ {
isCurrent := false
if i == current {
isCurrent = true
}
pages = append(pages, Page{
IsCurrent: isCurrent,
Number: i,
URL: pageURL + "?page=" + strconv.FormatUint(i, 10),
})
}

var (
hasPrevious bool
previousPageNum uint64
previousPageURL string
)
if current > 1 {
hasPrevious = true
previousPageNum = current - 1
previousPageURL = pageURL + "?page=" + strconv.FormatUint(previousPageNum, 10)
}

var (
hasNext bool
nextPageNum uint64
nextPageURL string
)
if max < total {
hasNext = true
nextPageNum = current + maxPages + 1
nextPageURL = pageURL + "?page=" + strconv.FormatUint(nextPageNum, 10)
}

return Pagination{
HasPrevious: hasPrevious,
PreviousPageNum: previousPageNum,
PreviousPageURL: previousPageURL,
Pages: pages,
HasNext: hasNext,
NextPageNum: nextPageNum,
NextPageURL: nextPageURL,
}
}
27 changes: 27 additions & 0 deletions publisher/presenter/html/pagination_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package html

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestPagination(t *testing.T) {
r := require.New(t)

pagination := NewPagination(305, 10, 3, "/some/page")
r.Equal(Pagination{
HasPrevious: true,
PreviousPageNum: 9,
PreviousPageURL: "/some/page?page=9",
Pages: []Page{
{IsCurrent: true, URL: "/some/page?page=10", Number: 10},
{IsCurrent: false, URL: "/some/page?page=11", Number: 11},
{IsCurrent: false, URL: "/some/page?page=12", Number: 12},
{IsCurrent: false, URL: "/some/page?page=13", Number: 13},
},
HasNext: true,
NextPageNum: 14,
NextPageURL: "/some/page?page=14",
}, pagination)
}
26 changes: 26 additions & 0 deletions publisher/presenter/html/static/scripts/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
window.addEventListener('load', () => {
const currentSwitch = localStorage.getItem('lightSwitch')?.toString()
const htmlTag = document.getElementById('html');
const lightSwitch = document.getElementById('lightSwitch');

if (currentSwitch) {
htmlTag?.setAttribute('data-bs-theme', currentSwitch);
}

lightSwitch?.addEventListener('click', () => {
if (document.getElementById('html')?.getAttribute('data-bs-theme')?.toString() == "dark") {
htmlTag?.setAttribute('data-bs-theme', 'light');
lightSwitch?.classList.remove('dark');
lightSwitch?.classList.add('light');

localStorage.setItem('lightSwitch', 'light');
return
}
htmlTag?.setAttribute('data-bs-theme', 'dark');
lightSwitch?.classList.remove('light');
lightSwitch?.classList.add('dark');

localStorage.setItem('lightSwitch', 'dark');
return
});
});
6 changes: 6 additions & 0 deletions publisher/presenter/html/static/styles/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.container {
margin: 15px;
}
nav.pagination {
margin-left: 45px;
}
Loading

0 comments on commit 55f87ec

Please sign in to comment.