change kontor-gin templates
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 3s

This commit is contained in:
Thomas Peetz
2026-09-24 16:06:38 +02:00
parent ba83d70764
commit 131296c644
26 changed files with 333 additions and 419 deletions
+1 -1
View File
@@ -22,6 +22,6 @@ RUN apk add --no-cache ca-certificates tzdata curl
COPY --from=builder /app/kontor-gin /app/kontor-gin
COPY --from=builder /app/templates /app/templates
COPY --from=builder /app/assets /app/assets
ENV DB_HOST=postgres DB_USER=kontor DB_PASSWORD=kontor DB_NAME=kontor DB_PORT=5432 GIN_MODE=release
ENV GIN_MODE=release
# Set the entrypoint command
ENTRYPOINT ["/app/kontor-gin"]
+1 -1
View File
@@ -4,5 +4,5 @@ import (
"embed"
)
//go:embed style/*
//go:embed style/* icons/*
var StaticFiles embed.FS

Before

Width:  |  Height:  |  Size: 544 B

After

Width:  |  Height:  |  Size: 544 B

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Before

Width:  |  Height:  |  Size: 634 B

After

Width:  |  Height:  |  Size: 634 B

-172
View File
@@ -1,172 +0,0 @@
* {
box-sizing: border-box;
}
body {
font-family: Arial;
padding: 10px;
background: lightgrey;
}
/* Header/Blog Title */
.header {
padding: 30px;
text-align: center;
background-color: lightblue;
}
.header h1 {
font-size: 50px;
}
/* Style the top navigation bar */
.topnav {
overflow: hidden;
background-color: darkgrey;
}
/* Style the topnav links */
.topnav a {
float: left;
display: block;
color: #f2f2f2;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
/* Change color on hover */
.topnav a:hover {
background-color: #ddd;
color: black;
}
.subnav {
overflow: hidden;
background-color: grey;
}
.subnav a {
float: left;
display: block;
color: #f2f2f2;
text-align: center;
padding: 14px 16px;
text-decoration: none;
}
.form-inline {
display: flex;
flex-flow: row wrap;
align-items: center;
padding-top: 10px;
padding-left: 20px;
}
.form-inline label {
margin: 5px 10px 5px 0;
}
.form-inline input {
padding-right: 50px;
margin-right: 10px;
}
.form-inline button {
padding: 10px 20px;
background-color: dodgerblue;
border: 1px solid #ddd;
color: white;
border-radius: 10px;
}
.form-inline button:hover {
background-color: royalblue;
}
.pill-nav a {
display: inline-block;
color: white;
background-color: dodgerblue;
text-align: center;
padding: 10px;
text-decoration: none;
border-radius: 10px;
margin-left: 20px;
}
/* Change the color of links on mouse-over */
.pill-nav a:hover {
background-color: royalblue;
color: white;
}
/* Add a color to the active/current link */
.pill-nav a.active {
background-color: royalblue;
color: white;
}
.maincolumn {
float:left;
width: 100%;
}
/* Create two unequal columns that floats next to each other */
/* Left column */
.leftcolumn {
float: left;
width: 75%;
}
/* Right column */
.rightcolumn {
float: left;
width: 25%;
background-color: #f1f1f1;
padding-left: 20px;
}
/* Fake image */
.fakeimg {
background-color: #aaa;
width: 100%;
padding: 20px;
}
/* Add a card effect for articles */
.card {
background-color: white;
padding: 20px;
margin-top: 20px;
}
/* Clear floats after the columns */
.row::after {
content: "";
display: table;
clear: both;
}
/* Footer */
.footer {
padding: 20px;
text-align: center;
background: #ddd;
margin-top: 20px;
}
/* Responsive layout - when the screen is less than 800px wide, make the two columns stack on top of each other instead of next to each other */
@media screen and (max-width: 800px) {
.leftcolumn, .rightcolumn {
width: 100%;
padding: 0;
}
}
/* Responsive layout - when the screen is less than 400px wide, make the navigation links stack on top of each other instead of next to each other */
@media screen and (max-width: 400px) {
.topnav a {
float: none;
width: 100%;
}
}
+15 -13
View File
@@ -15,11 +15,23 @@ import (
"github.com/gin-contrib/sessions/cookie"
gin_slog "github.com/gin-contrib/slog"
"github.com/gin-gonic/gin"
"github.com/spf13/viper"
)
func main() {
slog.Info("Kontor started")
viper.SetDefault("db.host", "localhost")
viper.SetDefault("db.port", 5432)
viper.SetDefault("db.name", "kontor")
viper.SetDefault("db.user", "kontor")
viper.SetDefault("db.password", "kontor")
viper.SetDefault("port", 8550)
if err := globals.InitConfig(); err != nil {
slog.Info("Failed to initialize config", "error", err)
}
// Set Gin mode based on environment
// Production mode disables debug output
if os.Getenv("GIN_MODE") == "release" {
@@ -57,21 +69,11 @@ func main() {
routes.SetupMediaRoutes(api)
routes.SetupComicRoutes(api)
// Setup public Webapp routes
routes.PublicRoutes(router)
// Setup protected Webapp routes
protected := router.Group("/auth")
protected.Use(middleware.AuthRequired)
routes.ProtectedRoutes(router)
comics := router.Group("/comics")
comics.Use(middleware.AuthRequired)
// Setup Webapp routes
routes.AuthRoutes(router)
routes.ComicRoutes(router)
media := router.Group("/media")
media.Use(middleware.AuthRequired)
routes.MediaRoutes(router)
routes.PublicRoutes(router)
// Start server
port := os.Getenv("PORT")
+7 -41
View File
@@ -2,7 +2,7 @@ package main
import (
// "kontor-api-gin/pkg/handler"
"fmt"
"html/template"
"kontor-api-gin/assets"
"kontor-api-gin/pkg/globals"
@@ -13,8 +13,6 @@ import (
"log"
"log/slog"
"net/http"
"os"
"strings"
"strconv"
"github.com/gin-contrib/sessions"
@@ -24,29 +22,6 @@ import (
"github.com/spf13/viper"
)
func initConfig() error {
viper.SetConfigName("kontor-gin")
viper.SetConfigType("yaml")
viper.AddConfigPath(".")
viper.AddConfigPath("$HOME/.config")
viper.AddConfigPath("/etc/kontor")
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
viper.AutomaticEnv()
// Read the config file
if err := viper.ReadInConfig(); err != nil {
// Handle the case where config file is not found
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
slog.Info("No config file found, using defaults")
return nil
}
return fmt.Errorf("error reading config file: %w", err)
}
slog.Info("initConfig", "Using config file: ", viper.ConfigFileUsed())
return nil
}
func main() {
slog.Info("Kontor started")
@@ -56,14 +31,15 @@ func main() {
viper.SetDefault("db.user", "kontor")
viper.SetDefault("db.password", "kontor")
viper.SetDefault("port", 8550)
viper.SetDefault("gin.mode", "release")
if err := initConfig(); err != nil {
if err := globals.InitConfig(); err != nil {
log.Fatalf("Failed to initialize config: %v", err)
}
// Set Gin mode based on environment
// Production mode disables debug output
if os.Getenv("GIN_MODE") == "release" {
if viper.GetString("gin.mode") == "release" {
gin.SetMode(gin.ReleaseMode)
}
@@ -100,21 +76,11 @@ func main() {
routes.SetupMediaRoutes(api)
routes.SetupComicRoutes(api)
// Setup public Webapp routes
routes.PublicRoutes(router)
// Setup protected Webapp routes
protected := router.Group("/auth")
protected.Use(middleware.AuthRequired)
routes.ProtectedRoutes(router)
comics := router.Group("/comics")
comics.Use(middleware.AuthRequired)
// Setup Webapp routes
routes.AuthRoutes(router)
routes.ComicRoutes(router)
media := router.Group("/media")
media.Use(middleware.AuthRequired)
routes.MediaRoutes(router)
routes.PublicRoutes(router)
// Start server
port := viper.GetInt("port")
+12 -12
View File
@@ -17,20 +17,20 @@ func LoginGetHandler(c *gin.Context) {
logger := slog.Get(c)
logger.Info("LoginGetHandler", globals.UserKey, user)
if user != nil {
c.HTML(http.StatusBadRequest, "login.html", gin.H{
c.HTML(http.StatusBadRequest, "login", gin.H{
"title": "Kontor Gin",
"version": "0.4.0",
"login": globals.LoginUrl,
"content": "Please logout first",
"message": "Please logout first",
"user": user,
})
return
}
c.HTML(http.StatusOK, "login.html", gin.H{
c.HTML(http.StatusOK, "login", gin.H{
"title": "Kontor Gin",
"version": "0.4.0",
"login": globals.LoginUrl,
"content": "",
"message": "",
"user": user,
})
}
@@ -41,11 +41,11 @@ func LoginPostHandler(c *gin.Context) {
logger := slog.Get(c)
logger.Info("LoginPostHandler", "user", user)
if user != nil {
c.HTML(http.StatusBadRequest, "login.html", gin.H{
c.HTML(http.StatusBadRequest, "login", gin.H{
"title": "Kontor Gin",
"version": "0.4.0",
"login": globals.LoginUrl,
"content": "Please logout first",
"message": "Please logout first",
})
return
}
@@ -54,30 +54,30 @@ func LoginPostHandler(c *gin.Context) {
password := c.PostForm("password")
if helpers.EmptyUserPass(username, password) {
c.HTML(http.StatusBadRequest, "login.html", gin.H{
c.HTML(http.StatusBadRequest, "login", gin.H{
"title": "Kontor Gin",
"version": "0.4.0",
"login": globals.LoginUrl,
"content": "Parameters can't be empty",
"message": "Parameters can't be empty",
})
}
if !helpers.CheckUserPass(username, password) {
c.HTML(http.StatusUnauthorized, "login.html", gin.H{
c.HTML(http.StatusUnauthorized, "login", gin.H{
"title": "Kontor Gin",
"version": "0.4.0",
"login": globals.LoginUrl,
"content": "Incorrect username or password",
"message": "Incorrect username or password",
})
}
session.Set(globals.UserKey, username)
if err := session.Save(); err != nil {
c.HTML(http.StatusInternalServerError, "login.html", gin.H{
c.HTML(http.StatusInternalServerError, "login", gin.H{
"title": "Kontor Gin",
"version": "0.4.0",
"login": globals.LoginUrl,
"content": "Failed to save session",
"message": "Failed to save session",
})
return
}
+3 -3
View File
@@ -18,11 +18,11 @@ func ListComicsGetHandler(c *gin.Context) {
var comics []schema.Comic
result := schema.DB.Find(&comics)
logger.Info("found Comics", "count", result.RowsAffected)
c.HTML(http.StatusOK, "comics.html", gin.H{
logger.Info("ListComicsGetHandler", "count", result.RowsAffected)
c.HTML(http.StatusOK, "comics", gin.H{
"title": "Kontor Comics",
"version": "0.4.0",
"content": "Media Files...",
"message": "Comics...",
"comics": comics,
"user": user,
})
+1 -1
View File
@@ -69,7 +69,7 @@ func ListComicStoryArcs(c *gin.Context) {
logger := slog.Get(c)
result := schema.DB.Find(&items)
logger.Info("found Comic StoryArcs", "count", result.RowsAffected)
logger.Info("ListComicStoryArcs", "count", result.RowsAffected)
c.JSON(http.StatusOK, items)
}
+2 -2
View File
@@ -14,10 +14,10 @@ func IndexGetHandler(c *gin.Context) {
user := session.Get(globals.UserKey)
logger := slog.Get(c)
logger.Info("IndexGetHandler", globals.UserKey, user)
c.HTML(http.StatusOK, "home.html", gin.H{
c.HTML(http.StatusOK, "home", gin.H{
"title": "Kontor Gin",
"version": "0.4.0",
"content": "This is an index page...",
"message": "This is an index page...",
"login": globals.LoginUrl,
"logout": globals.LogoutUrl,
"user": user,
+11 -9
View File
@@ -3,7 +3,6 @@ package controllers
import (
"kontor-api-gin/pkg/globals"
"kontor-api-gin/pkg/schema"
"log"
"net/http"
"github.com/gin-contrib/sessions"
@@ -13,11 +12,12 @@ import (
func ListMediaFiles(c *gin.Context) {
var files []schema.MediaFile
logger := slog.Get(c)
// query := schema.DB.Model(&schema.MediaFile{})
// result := query.Find(&files)
result := schema.DB.Find(&files)
log.Printf("found %d MediaFiles", result.RowsAffected)
logger.Info("ListMediaFiles", "count", result.RowsAffected)
c.JSON(http.StatusOK, gin.H{
"message": "All MediaFiles",
"files": files,
@@ -26,9 +26,10 @@ func ListMediaFiles(c *gin.Context) {
func ListMediaLoFis(c *gin.Context) {
var lofis []schema.MediaLoFi
logger := slog.Get(c)
result := schema.DB.Find(&lofis)
log.Printf("found %d MediaLoFis", result.RowsAffected)
logger.Info("ListMediaLoFis", "count", result.RowsAffected)
c.JSON(http.StatusOK, lofis)
}
@@ -41,10 +42,10 @@ func ListMediaActorsGetHandler(c *gin.Context) {
result := schema.DB.Find(&actors)
logger.Info("ListMediaActorsGetHandler", "count", result.RowsAffected)
c.HTML(http.StatusOK, "mediaactors.html", gin.H{
c.HTML(http.StatusOK, "mediaactors", gin.H{
"title": "Kontor Gin",
"version": "0.4.0",
"content": "Media Actors...",
"message": "Media Actors...",
"actors": actors,
"login": globals.LoginUrl,
"logout": globals.LogoutUrl,
@@ -61,10 +62,10 @@ func ListMediaFilesGetHandler(c *gin.Context) {
result := schema.DB.Find(&files)
logger.Info("ListMediaFilesGetHandler", "count", result.RowsAffected)
c.HTML(http.StatusOK, "mediafiles.html", gin.H{
c.HTML(http.StatusOK, "mediafiles", gin.H{
"title": "Kontor Gin",
"version": "0.4.0",
"content": "Media Files...",
"message": "Media Files...",
"files": files,
"login": globals.LoginUrl,
"logout": globals.LogoutUrl,
@@ -82,10 +83,11 @@ func ListMediaLoFisGetHandler(c *gin.Context) {
result := schema.DB.Find(&lofis)
logger.Info("ListMediaLoFisGetHandler", "count", result.RowsAffected)
c.HTML(http.StatusOK, "media_lofi.html", gin.H{
logger.Info("ListMediaLoFisGetHandler", "medialofi", lofis[0])
c.HTML(http.StatusOK, "lofi", gin.H{
"title": "Kontor Gin",
"version": "0.4.0",
"content": "Media LoFis...",
"message": "Media LoFis...",
"lofis": lofis,
"login": globals.LoginUrl,
"logout": globals.LogoutUrl,
+32
View File
@@ -0,0 +1,32 @@
package globals
import (
"fmt"
"log/slog"
"strings"
"github.com/spf13/viper"
)
func InitConfig() error {
viper.SetConfigName("kontor-gin")
viper.SetConfigType("yaml")
viper.AddConfigPath(".")
viper.AddConfigPath("$HOME/.config")
viper.AddConfigPath("/etc/kontor")
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
viper.AutomaticEnv()
// Read the config file
if err := viper.ReadInConfig(); err != nil {
// Handle the case where config file is not found
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
slog.Info("No config file found, using defaults")
return nil
}
return fmt.Errorf("error reading config file: %w", err)
}
slog.Info("initConfig", "Using config file: ", viper.ConfigFileUsed())
return nil
}
+1 -1
View File
@@ -6,6 +6,6 @@ const UserKey = "user"
const Version = "0.4.0"
const LoginUrl = "/auth/login"
const LoginUrl = "/login"
const LogoutUrl = "/auth/logout"
+1 -1
View File
@@ -27,7 +27,7 @@ func MediaRoutes(g *gin.Engine) {
media.GET("/lofis", controllers.ListMediaLoFisGetHandler)
}
func ProtectedRoutes(g *gin.Engine) {
func AuthRoutes(g *gin.Engine) {
auth := g.Group("/auth")
auth.Use(middleware.AuthRequired)
auth.GET("/logout", controllers.LogoutGetHandler)
+8 -3
View File
@@ -1,9 +1,14 @@
package schema
type MediaLoFi struct {
Base
import "time"
WebLink string `gorm:"uniqueIndex" json:"url"`
type MediaLoFi struct {
ID string `gorm:"type:string;primary_key;"`
Created_Date time.Time `json:"created_date"`
Last_Modified_date time.Time `json:"last_modified_date"`
Deleted_Date *time.Time `json:"deleted_date"`
Version int `gorm:"default:0" json:"version"`
Url string `gorm:"uniqueIndex" json:"url"`
Review bool `json:"review"`
ShouldDownload bool `json:"should_download"`
Title string `gorm:"size:300" json:"title"`
+3
View File
@@ -0,0 +1,3 @@
{{ define "footer" }}
<div class="footer">{{ .version }}</div>
{{ end }}
+13
View File
@@ -0,0 +1,13 @@
{{ define "head" }}
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.12.9/dist/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<link rel="stylesheet" href="/public/style/main.css" />
<title>{{ .title }}</title>
</head>
{{ end }}
+34 -7
View File
@@ -1,13 +1,40 @@
{{ define "navbar" }}
<div class="topnav">
<a href="/">Kontor</a>
<a href="/comic/comics">Comics</a>
<a href="/media/files">Media</a>
<a href="/media/lofis">Lofi</a>
<div class="container">
<nav class="navbar fixed-top navbar-expand-lg navbar-dark" style="background-color: darkgrey;">
<a class="navbar-brand" href="/">Kontor</a>
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-item nav-link" href="/comic/comics">Comics</a>
</li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Media</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
<a class="dropdown-item" href="/media/files">Media Files</a>
<a class="dropdown-item" href="/media/actors">Media Actors</a>
<a class="dropdown-item" href="/media/lofis">Lofi</a>
</div>
</li>
<li class="nav-item">
<a class="nav-link" href="/media/files">Media</a>
</li>
<li class="nav-item">
<a class="nav-link" href="/media/lofis">Lofis</a>
</li>
{{ if .user }}
<a style="float:right" href="{{ .logout }}">Logout</a></li>
<li class="nav-item">
<a class="nav-link" href="{{ .logout }}">Logout</a>
</li>
{{ else }}
<a style="float:right" href="{{ .login }}">Login</a></li>
<li class="nav-item">
<a class="nav-link" href="{{ .login }}">Login</a>
</li>
{{ end }}
<form class="form-inline">
<input class="form-control mr-sm-2" type="search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
</ul>
</nav>
</div>
{{ end }}
+17 -10
View File
@@ -1,16 +1,18 @@
{{ define "comics.html" }}
{{ template "main" . }}
{{ end }}
{{ define "comics" }}
<!doctype html>
<html lang="de">
{{ template "head" . }}
{{ define "content" }}
<body>
{{ template "navbar" . }}
<div class="row">
<form class="form-inline" action="/comic/comics">
<input type="text" placeholder="Search" name="query">
<label>
<input type="checkbox" name="completed" {{ if .completed }}checked{{ end }}>Completed
<input type="checkbox" name="completed" {{ if .Completed }}checked{{ end }}>Completed
</label>
<label>
<input type="checkbox" name="order" {{ if .order }}checked{{ end }}>Order
<input type="checkbox" name="order" {{ if .CurrentOrder }}checked{{ end }}>Order
</label>
<button type="submit">Search</button>
<div class="pill-nav"><a href="/comic/comic/add">Add Comic</a></div>
@@ -19,12 +21,14 @@
<div class="row">
<div class="maincolumn">
<table class="table table-hover">
<thead><tr>
<thead>
<tr>
<th scope="col">Title</th>
<th scope="col">Publisher</th>
<th scope="col">Completed</th>
<th colspan="2">Actions</th>
</tr></thead>
</tr>
</thead>
<tbody>
{{ range .comics }}
<tr>
@@ -36,9 +40,9 @@
{{ end }}
<td>
{{ if .Completed }}
<img src="/tick.png" alt="true" width="24" height="24">
<img src="/public/icons/tick.png" alt="true" width="24" height="24">
{{ else }}
<img src="/cross.png" alt="true" width="24" height="24">
<img src="/public/icons/cross.png" alt="true" width="24" height="24">
{{ end }}
</td>
<td><a href="/comic/comics/edit/{{.ID}}" class="btn btn-outline-primary btn-sm active" role="button" aria-pressed="true">Edit</a></td>
@@ -49,4 +53,7 @@
</table>
</div>
</div>
{{ template "footer" . }}
</body>
</html>
{{ end }}
+10 -5
View File
@@ -1,7 +1,12 @@
{{ define "home.html" }}
{{ template "main" . }}
{{ end }}
{{ define "home" }}
<!doctype html>
<html lang="de">
{{ template "head" . }}
{{ define "content" }}
<h1>{{ .content }}</h1>
<body>
{{ template "navbar" . }}
<h1>{{ .message }}</h1>
{{ template "footer" . }}
</body>
</html>
{{ end }}
+34 -24
View File
@@ -1,52 +1,62 @@
{{ define "media_lofi.html" }}
{{ template "main" . }}
{{ end }}
{{ define "lofi" }}
<!doctype html>
<html lang="de">
{{ template "head" . }}
{{ define "content" }}
<body>
{{ template "navbar" . }}
<div class="row">
<form class="form-inline" action="/media/lofi">
<h1>Media Lofi</h1>
</div>
<div class="row">
<form class="form-inline" action="/media/lofis">
<input type="text" placeholder="Search" name="query">
<label>
<input type="checkbox" name="review" {{ if .Review }}checked{{ end }}>Completed
<input>
<input type="checkbox" name="review" {{ if .Review }}checked{{ end }}>Review
</label>
<label>
<input type="checkbox" name="should_download" {{ if .ShouldDownload }}checked{{ end }}>Order
<input type="checkbox" name="should_download" {{ if .ShouldDownload }}checked{{ end }}>Download
</label>
<button type="submit">Search</button>
<div class="pill-nav"><a href="/media/lofi/add">Add Lofi</a></div>
<div class="pill-nav"><a href="/media/lofis/add">Add Lofi</a></div>
</form>
</div>
<div class="row">
<div class="maincolumn">
<table class="table table-hover">
<thead><tr>
<th scope="col">Title</th>
<th scope="col">Publisher</th>
<th scope="col">Completed</th>
<th colspan="2">Actions</th>
</tr></thead>
<tbody>
{{ range .comics }}
<thead>
<tr>
<th scope="row"><a href="/media/lofi/{{.ID}}">{{.Title}}</a></th>
{{ if .WebLink }}
<td><a href="{{.WebLink}}">{{.Title}}</a></td>
<th scope="col">Title</th>
<th scope="col">Weblink</th>
<th scope="col">Review</th>
<th colspan="2">Actions</th>
</tr>
</thead>
<tbody>
{{ range .lofis }}
<tr>
<th scope="row"><a href="/media/lofis/{{.ID}}">{{.Title}}</a></th>
{{ if .Url }}
<td><a href="{{.Url}}">{{.Url}}</a></td>
{{ else }}
<td>WebLink not set</td>
{{ end }}
<td>
{{ if .Review }}
<img src="/tick.png" alt="true" width="24" height="24">
<img src="/public/icons/tick.png" alt="true" width="24" height="24">
{{ else }}
<img src="/cross.png" alt="true" width="24" height="24">
<img src="/public/icons/cross.png" alt="true" width="24" height="24">
{{ end }}
</td>
<td><a href="/media/lofi/edit/{{.ID}}" class="btn btn-outline-primary btn-sm active" role="button" aria-pressed="true">Edit</a></td>
<td><a href="/media/lofi/delete/{{.ID}}" class="btn btn-outline-danger btn-sm active" role="button" aria-pressed="true">Delete</a></td>
<td><a href="/media/lofis/edit/{{.ID}}" class="btn btn-outline-primary btn-sm active" role="button" aria-pressed="true">Edit</a></td>
<td><a href="/media/lofis/delete/{{.ID}}" class="btn btn-outline-danger btn-sm active" role="button" aria-pressed="true">Delete</a></td>
</tr>
{{ end }}
</tbody>
</table>
</div>
</div>
{{ template "footer" . }}
</body>
</html>
{{ end }}
+11 -9
View File
@@ -1,15 +1,15 @@
{{ define "login.html" }}
{{ template "main" . }}
{{ end }}
{{ define "login" }}
<!doctype html>
<html lang="de">
{{ template "head" . }}
{{ define "content" }}
<body>
{{ template "navbar" . }}
<div class="content">
<form action={{ .login }} method="post">
<form action="{{ .login }}" method="post">
<div class="container" style="border: 1px solid lightgray; border-radius: 3px; padding: 15px;">
{{ if .content }}
<div class="notification is-danger">{{ .content }}</div>
<div class="notification is-danger">{{ .message }}</div>
{{ end}}
<div class="field">
@@ -24,11 +24,13 @@
<input class="input" type="password" placeholder="Enter Password" name="password" required/>
</div>
</div>
<div class="field">
<button class="button is-link">Submit</button>
</div>
</div>
</form>
</div>
{{ template "footer" . }}
</body>
</html>
{{ end }}
+12 -5
View File
@@ -1,7 +1,14 @@
{{ define "home.html" }}
{{ template "main" . }}
{{ end }}
{{ define "mediaactors" }}
<!doctype html>
<html lang="de">
{{ template "head" . }}
{{ define "content" }}
<h1>{{ .content }}</h1>
<body>
{{ template "navbar" . }}
<div>
<h1>{{ .message }}</h1>
</div>
{{ template "footer" . }}
</body>
</html>
{{ end }}
+10 -5
View File
@@ -1,7 +1,12 @@
{{ define "mediafiles.html" }}
{{ template "main" . }}
{{ end }}
{{ define "mediafiles" }}
<!doctype html>
<html lang="de">
{{ template "head" . }}
{{ define "content" }}
<h1>{{ .content }}</h1>
<body>
{{ template "navbar" . }}
<h1>{{ .message }}</h1>
{{ template "footer" . }}
</body>
</html>
{{ end }}