kontor-echo: setup project to show homepage
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# ---------- Stage 1: Build ----------
|
||||
FROM docker.io/library/golang:1.25-alpine AS builder
|
||||
FROM docker.io/library/golang:1.26-alpine AS builder
|
||||
# Set the working directory
|
||||
WORKDIR /app
|
||||
# Ensure a portable, static-ish binary
|
||||
@@ -9,8 +9,12 @@ COPY go.mod go.sum ./
|
||||
RUN go mod download
|
||||
# Copy the source code
|
||||
COPY . .
|
||||
ARG VERSION="dev"
|
||||
ARG COMMIT="unset"
|
||||
ARG DATE="unset"
|
||||
# Build the Go application (strip debug info for smaller size)
|
||||
RUN go build -trimpath -ldflags="-s -w" -o kontor cmd/kontor/main.go
|
||||
RUN go build -trimpath -ldflags="-s -w -X kontor-api-echo/internal/globals.Version=${VERSION} -X kontor-api-echo/internal/globals.Commit=${COMMIT} -X kontor-api-echo/internal/globals.Date=${DATE}" -o kontor cmd/kontor-echo/main.go
|
||||
|
||||
|
||||
# ---------- Stage 2: Final ----------
|
||||
FROM alpine:latest
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package assets
|
||||
|
||||
import (
|
||||
"embed"
|
||||
)
|
||||
|
||||
//go:embed style/* icons/*
|
||||
var StaticFiles embed.FS
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 544 B |
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 634 B |
@@ -0,0 +1,174 @@
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: Arial;
|
||||
padding: 10px;
|
||||
background: lightgrey;
|
||||
padding-top: 56px;
|
||||
padding-bottom: 56px;
|
||||
}
|
||||
|
||||
/* 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%;
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,8 @@ func main() {
|
||||
defer stop()
|
||||
|
||||
sc := echo.StartConfig{
|
||||
Address: ":1323",
|
||||
//Address: fmt.Sprintf(":%d", config.ServerConfig.Server.Port),
|
||||
Address: ":8400",
|
||||
GracefulTimeout: 10 * time.Second,
|
||||
}
|
||||
if err := sc.Start(ctx, e); err != nil {
|
||||
|
||||
@@ -20,7 +20,6 @@ func main() {
|
||||
}
|
||||
|
||||
e := echo.New()
|
||||
e.GET("/health", handler.GetHealth)
|
||||
e.POST("/login", handler.Login)
|
||||
|
||||
skipper := func(c echo.Context) bool {
|
||||
@@ -47,7 +46,6 @@ func main() {
|
||||
group := e.Group("/api")
|
||||
group.Use(echojwt.WithConfig(echojwt.Config{SigningKey: []byte("secret")}))
|
||||
handler.SetupComicRoutes(group)
|
||||
handler.SetupMediaRoutes(group)
|
||||
|
||||
e.Logger.Fatal(e.Start(":8400"))
|
||||
log.Println("Kontor finished")
|
||||
|
||||
+5
-6
@@ -6,18 +6,18 @@ require (
|
||||
github.com/golang-jwt/jwt/v5 v5.3.1
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/labstack/echo-jwt/v4 v4.4.0
|
||||
github.com/labstack/echo-jwt/v5 v5.0.2
|
||||
github.com/labstack/echo/v4 v4.15.0
|
||||
github.com/labstack/echo/v5 v5.4.4
|
||||
github.com/stretchr/testify v1.11.1
|
||||
github.com/uptrace/bun v1.3.0
|
||||
github.com/uptrace/bun/dialect/pgdialect v1.2.16
|
||||
github.com/uptrace/bun/dialect/pgdialect v1.3.0
|
||||
github.com/uptrace/bun/driver/pgdriver v1.2.16
|
||||
golang.org/x/crypto v0.54.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/labstack/echo-jwt/v5 v5.0.2 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.34 // indirect
|
||||
github.com/ncruces/go-strftime v1.0.0 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
@@ -42,12 +42,11 @@ require (
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/puzpuzpuz/xsync/v3 v3.5.1 // indirect
|
||||
github.com/sagikazarmark/locafero v0.12.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
|
||||
github.com/spf13/afero v1.15.0 // indirect
|
||||
github.com/spf13/cast v1.10.0 // indirect
|
||||
github.com/spf13/cobra v1.10.2 // indirect
|
||||
github.com/spf13/cobra v1.10.2
|
||||
github.com/spf13/pflag v1.1.0 // indirect
|
||||
github.com/spf13/viper v1.21.0 // indirect
|
||||
github.com/spf13/viper v1.21.0
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect
|
||||
github.com/uptrace/bun/dialect/sqlitedialect v1.3.0
|
||||
@@ -60,7 +59,7 @@ require (
|
||||
go.opentelemetry.io/otel/trace v1.39.0 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.6 // indirect
|
||||
golang.org/x/net v0.57.0 // indirect
|
||||
golang.org/x/sys v0.49.0 // indirect
|
||||
golang.org/x/sys v0.50.0 // indirect
|
||||
golang.org/x/text v0.43.0 // indirect
|
||||
golang.org/x/time v0.16.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
|
||||
+40
-12
@@ -5,6 +5,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho=
|
||||
github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo=
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
|
||||
@@ -13,12 +15,18 @@ github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63Y
|
||||
github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs=
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/labstack/echo-jwt/v4 v4.4.0 h1:nrXaEnJupfc2R4XChcLRDyghhMZup77F8nIzHnBK19U=
|
||||
@@ -49,11 +57,11 @@ github.com/puzpuzpuz/xsync/v3 v3.5.1 h1:GJYJZwO6IdxN/IKbneznS6yPkVC+c3zyY/j19c++
|
||||
github.com/puzpuzpuz/xsync/v3 v3.5.1/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sagikazarmark/locafero v0.12.0 h1:/NQhBAkUb4+fH1jivKHWusDYFjMOOKU88eegjfxfHb4=
|
||||
github.com/sagikazarmark/locafero v0.12.0/go.mod h1:sZh36u/YSZ918v0Io+U9ogLYQJ9tLLBmM4eneO6WwsI=
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U=
|
||||
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
|
||||
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
|
||||
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
|
||||
@@ -71,12 +79,10 @@ github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo=
|
||||
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs=
|
||||
github.com/uptrace/bun v1.2.16 h1:QlObi6ZIK5Ao7kAALnh91HWYNZUBbVwye52fmlQM9kc=
|
||||
github.com/uptrace/bun v1.2.16/go.mod h1:jMoNg2n56ckaawi/O/J92BHaECmrz6IRjuMWqlMaMTM=
|
||||
github.com/uptrace/bun v1.3.0 h1:hUcbfRpbQk4/upFSI+uZf6jSJw5A0lkIKt0XdpvbUZo=
|
||||
github.com/uptrace/bun v1.3.0/go.mod h1:wNltaKJk4JtOt4SG5I5zmA7v0/Mzjh1+/S906Rayd3Y=
|
||||
github.com/uptrace/bun/dialect/pgdialect v1.2.16 h1:KFNZ0LxAyczKNfK/IJWMyaleO6eI9/Z5tUv3DE1NVL4=
|
||||
github.com/uptrace/bun/dialect/pgdialect v1.2.16/go.mod h1:IJdMeV4sLfh0LDUZl7TIxLI0LipF1vwTK3hBC7p5qLo=
|
||||
github.com/uptrace/bun/dialect/pgdialect v1.3.0 h1:0ZkGqGugxaPCxko4DV2f4d7i+FnM2Qj3rNpChfhiv54=
|
||||
github.com/uptrace/bun/dialect/pgdialect v1.3.0/go.mod h1:kP5HGEpAX8iJCqj3WHm04XnoeBPacdCN1P2HiwMtHpg=
|
||||
github.com/uptrace/bun/dialect/sqlitedialect v1.3.0 h1:XzxkORYksxkLsIQLJHFYUb3yDvqSQHzTungyKpJhHTw=
|
||||
github.com/uptrace/bun/dialect/sqlitedialect v1.3.0/go.mod h1:x2D1sY50Itio0I/FVdNe30oMUT2ObiAS+oILcMR+Wys=
|
||||
github.com/uptrace/bun/driver/pgdriver v1.2.16 h1:b1kpXKUxtTSGYow5Vlsb+dKV3z0R7aSAJNfMfKp61ZU=
|
||||
@@ -102,19 +108,21 @@ golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
|
||||
golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
|
||||
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa h1:Zt3DZoOFFYkKhDT3v7Lm9FDMEV06GpzjG2jrqW+QTE0=
|
||||
golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa/go.mod h1:K79w1Vqn7PoiZn+TkNpx3BUWUQksGO3JcVX6qIjytmA=
|
||||
golang.org/x/mod v0.41.0 h1:qJmnOUb4YB+FsEuM3HcWucdZASCPGhsX6uljO6pog0c=
|
||||
golang.org/x/mod v0.41.0/go.mod h1:Ek9pY8RKWXwsWvd3rQiHYtMqkjSUV+s1Rj7j4H5Ur6o=
|
||||
golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE=
|
||||
golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU=
|
||||
golang.org/x/sync v0.24.0 h1:iqiDrGoDgyuvAKrhLQthUEzU/R378N78gXbBjxed7oA=
|
||||
golang.org/x/sync v0.24.0/go.mod h1:sUUOizhqBxiL6pEWpqNLUiaJn1ShEbZ6BBqskPbjZm0=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
|
||||
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/sys v0.49.0 h1:XbzkgYJHdqh/8m2Uu0W/dQv8nktxx4BFHp1M0gROTXA=
|
||||
golang.org/x/sys v0.49.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og=
|
||||
golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs=
|
||||
golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY=
|
||||
golang.org/x/sys v0.50.0 h1:dkKZEFTEKaLr1sjhs0WiKqoi8Jj5nHbS3Njmx1UoMJs=
|
||||
golang.org/x/sys v0.50.0/go.mod h1:hNLxWAXmnKAxqDtdwIYC4bM9oQPEecfsnNMuSxOs3og=
|
||||
golang.org/x/text v0.43.0 h1:1QivrlhwAsnMOcqgOdl9my7s9OyZl8O5/UGUTJVXoWc=
|
||||
golang.org/x/text v0.43.0/go.mod h1:hbSIYA/amXcRXTFSZqh8tWHEoqRvvbKPJ2uz/KU+a+s=
|
||||
golang.org/x/time v0.16.0 h1:vMb6ptszcQMkcwiRTAuNNU50gom6++Q/6gY2hDM6VDE=
|
||||
golang.org/x/time v0.16.0/go.mod h1:rVKOqvZeKvrDKTQiAHJ7wmwP0RzleSphoEA9RcdLA0s=
|
||||
golang.org/x/tools v0.51.0 h1:k4Xc/1Om9jwkBJBo4NVLMSARBoWtK10mx+W5BnXCeAI=
|
||||
golang.org/x/tools v0.51.0/go.mod h1:9eEncMayCV6zRMGhR5eZEC2iBx98qWcF1HZ9Z7wJOoA=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
@@ -122,11 +130,31 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
mellium.im/sasl v0.3.2 h1:PT6Xp7ccn9XaXAnJ03FcEjmAn7kK1x7aoXV6F+Vmrl0=
|
||||
mellium.im/sasl v0.3.2/go.mod h1:NKXDi1zkr+BlMHLQjY3ofYuU4KSPFxknb8mfEu6SveY=
|
||||
modernc.org/cc/v4 v4.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis=
|
||||
modernc.org/cc/v4 v4.27.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
|
||||
modernc.org/ccgo/v4 v4.30.2 h1:4yPaaq9dXYXZ2V8s1UgrC3KIj580l2N4ClrLwnbv2so=
|
||||
modernc.org/ccgo/v4 v4.30.2/go.mod h1:yZMnhWEdW0qw3EtCndG1+ldRrVGS+bIwyWmAWzS0XEw=
|
||||
modernc.org/fileutil v1.3.40 h1:ZGMswMNc9JOCrcrakF1HrvmergNLAmxOPjizirpfqBA=
|
||||
modernc.org/fileutil v1.3.40/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
|
||||
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
|
||||
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
|
||||
modernc.org/gc/v3 v3.1.2 h1:ZtDCnhonXSZexk/AYsegNRV1lJGgaNZJuKjJSWKyEqo=
|
||||
modernc.org/gc/v3 v3.1.2/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY=
|
||||
modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
|
||||
modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
|
||||
modernc.org/libc v1.68.0 h1:PJ5ikFOV5pwpW+VqCK1hKJuEWsonkIJhhIXyuF/91pQ=
|
||||
modernc.org/libc v1.68.0/go.mod h1:NnKCYeoYgsEqnY3PgvNgAeaJnso968ygU8Z0DxjoEc0=
|
||||
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
|
||||
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
|
||||
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
|
||||
modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw=
|
||||
modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
|
||||
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
|
||||
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
|
||||
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
|
||||
modernc.org/sqlite v1.46.1 h1:eFJ2ShBLIEnUWlLy12raN0Z1plqmFX9Qe3rjQTKt6sU=
|
||||
modernc.org/sqlite v1.46.1/go.mod h1:CzbrU2lSB1DKUusvwGz7rqEKIq+NUd8GWuBBZDs9/nA=
|
||||
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
|
||||
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
|
||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
|
||||
@@ -138,8 +138,8 @@ func InitConfig() error {
|
||||
viper.SetDefault("db.user", "kontor")
|
||||
viper.SetDefault("db.password", "kontor")
|
||||
viper.SetDefault("db.path", "data/kontor.db")
|
||||
viper.SetDefault("server.port", 8550)
|
||||
viper.SetDefault("gin.mode", "release")
|
||||
viper.SetDefault("server.host", "127.0.0.1")
|
||||
viper.SetDefault("server.port", 8400)
|
||||
// Read the config file
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
// Handle the case where config file is not found
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"kontor-api-echo/internal/config"
|
||||
"kontor-api-echo/internal/globals"
|
||||
"kontor-api-echo/internal/helpers"
|
||||
"kontor-api-echo/internal/models"
|
||||
"kontor-api-echo/internal/repository"
|
||||
"kontor-api-echo/internal/service"
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v5"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
type AuthHandler struct {
|
||||
Service *service.AuthService
|
||||
Secret []byte
|
||||
}
|
||||
|
||||
func NewAuthHandler(db *bun.DB) *AuthHandler {
|
||||
handler := &AuthHandler{Service: service.NewAuthService(repository.NewProfileRepository(db)), Secret: config.ServerConfig.ApiSecret}
|
||||
return handler
|
||||
}
|
||||
|
||||
func (handler *AuthHandler) Login(c *echo.Context) error {
|
||||
var input models.LoginInput
|
||||
|
||||
if err := c.Bind(&input); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]any{"error": err.Error()})
|
||||
}
|
||||
|
||||
profile_id, err := handler.Service.LoginCheck(input.Email, input.Password)
|
||||
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]any{"error": "username or password is incorrect."})
|
||||
}
|
||||
|
||||
token, err := helpers.GenerateToken(profile_id)
|
||||
logger := c.Logger()
|
||||
if err != nil {
|
||||
logger.Info("Login", "GenerateToken error", err.Error())
|
||||
}
|
||||
return c.JSON(http.StatusOK, map[string]any{"token": token})
|
||||
}
|
||||
|
||||
func (handler *AuthHandler) LoginPage(c *echo.Context) error {
|
||||
cookie, _ := c.Cookie(globals.UserKey)
|
||||
user := cookie.Value
|
||||
logger := c.Logger()
|
||||
logger.Info("LoginPage", globals.UserKey, user)
|
||||
data := globals.GetDefaultValues(user, "Please logout first")
|
||||
if user != "" {
|
||||
return c.Render(http.StatusBadRequest, "login", data)
|
||||
}
|
||||
data["message"] = ""
|
||||
return c.Render(http.StatusOK, "login", data)
|
||||
}
|
||||
|
||||
func (handler *AuthHandler) LoginPost(c *echo.Context) error {
|
||||
cookie, _ := c.Cookie(globals.UserKey)
|
||||
user := cookie.Value
|
||||
logger := c.Logger()
|
||||
logger.Info("LoginPost", "user", user)
|
||||
data := globals.GetDefaultValues(user, "Please logout first")
|
||||
if user != "" {
|
||||
return c.Render(http.StatusBadRequest, "login", data)
|
||||
}
|
||||
|
||||
username := c.FormValue("username")
|
||||
password := c.FormValue("password")
|
||||
|
||||
if helpers.EmptyUserPass(username, password) {
|
||||
data["message"] = "Parameters can't be empty"
|
||||
c.Render(http.StatusBadRequest, "login", data)
|
||||
}
|
||||
|
||||
profile_id, err := handler.Service.LoginCheck(username, password)
|
||||
if err != nil {
|
||||
data["message"] = "Incorrect username or password"
|
||||
c.Render(http.StatusUnauthorized, "login", data)
|
||||
}
|
||||
c.SetCookie(&http.Cookie{
|
||||
Name: globals.UserKey,
|
||||
Value: profile_id,
|
||||
MaxAge: 3600,
|
||||
Path: "/",
|
||||
Domain: "",
|
||||
HttpOnly: true,
|
||||
})
|
||||
logger.Info("LoginPost: redirect to index")
|
||||
return c.Redirect(http.StatusMovedPermanently, "/")
|
||||
}
|
||||
|
||||
func (handler *AuthHandler) LogoutPage(c *echo.Context) error {
|
||||
cookie, _ := c.Cookie(globals.UserKey)
|
||||
user := cookie.Value
|
||||
logger := c.Logger()
|
||||
logger.Info("LogoutPage", globals.UserKey, user)
|
||||
if user == "" {
|
||||
logger.Info("Invalid session token")
|
||||
return c.Redirect(http.StatusMovedPermanently, "/")
|
||||
}
|
||||
c.SetCookie(&http.Cookie{
|
||||
Name: globals.UserKey,
|
||||
Value: "",
|
||||
MaxAge: -1, // Deletes the cookie immediately
|
||||
Path: "/",
|
||||
Domain: "",
|
||||
HttpOnly: true,
|
||||
})
|
||||
logger.Info("LogoutPage: redirect to index page")
|
||||
return c.Redirect(http.StatusMovedPermanently, "/")
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"kontor-api-echo/internal/globals"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/labstack/echo/v5"
|
||||
)
|
||||
|
||||
func Health(c *echo.Context) error {
|
||||
return c.JSON(200, map[string]string{
|
||||
"ok": "true",
|
||||
"status": "healthy",
|
||||
"version": globals.Version,
|
||||
"time": time.Now().UTC().Format(time.RFC3339),
|
||||
})
|
||||
}
|
||||
|
||||
func Index(c *echo.Context) error {
|
||||
logger := c.Logger()
|
||||
cookie, err := c.Cookie(globals.UserKey)
|
||||
user := ""
|
||||
if err != nil {
|
||||
logger.Info("error reading cookie", "error", err.Error())
|
||||
} else {
|
||||
user = cookie.Value
|
||||
}
|
||||
|
||||
logger.Info("IndexGetHandler", globals.UserKey, user)
|
||||
data := globals.GetDefaultValues(user, "This is an index page...")
|
||||
return c.Render(http.StatusOK, "home", data)
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"kontor-api-echo/internal/models"
|
||||
"kontor-api-echo/internal/repository"
|
||||
"kontor-api-echo/internal/service"
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v5"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
type MailHandler struct {
|
||||
Service *service.MailService
|
||||
}
|
||||
|
||||
func NewMailHandler(db *bun.DB) *MailHandler {
|
||||
handler := &MailHandler{Service: service.NewMailService(repository.NewMailRepository(db))}
|
||||
return handler
|
||||
}
|
||||
|
||||
func (handler *MailHandler) List(c *echo.Context) {
|
||||
mails, err := handler.Service.List(c.Request().Context())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, map[string]any{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
dtos := models.ConvertMailsToDtos(mails)
|
||||
c.JSON(http.StatusOK, dtos)
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"kontor-api-echo/internal/models"
|
||||
"kontor-api-echo/internal/repository"
|
||||
"kontor-api-echo/internal/service"
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v5"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
type MailAccountHandler struct {
|
||||
Service *service.MailAccountService
|
||||
}
|
||||
|
||||
func NewMailAccountHandler(db *bun.DB) *MailAccountHandler {
|
||||
handler := &MailAccountHandler{Service: service.NewMailAccountService(repository.NewMailAccountRepository(db))}
|
||||
return handler
|
||||
}
|
||||
|
||||
func (handler *MailAccountHandler) List(c *echo.Context) {
|
||||
mailaccounts, err := handler.Service.List(c.Request().Context())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, map[string]any{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
dtos := models.ConvertMailAccountsToDtos(mailaccounts)
|
||||
c.JSON(http.StatusOK, dtos)
|
||||
}
|
||||
@@ -67,35 +67,35 @@ func (handler *MediaActorHandler) Delete(c *echo.Context) {
|
||||
c.JSON(http.StatusOK, map[string]string{"ok": "true"})
|
||||
}
|
||||
|
||||
func (handler *MediaActorHandler) ListPage(c *echo.Context) {
|
||||
func (handler *MediaActorHandler) ListPage(c *echo.Context) error {
|
||||
cookie, err := c.Cookie(globals.UserKey)
|
||||
user := cookie.Value
|
||||
actors, err := handler.Service.List(c.Request().Context())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return err
|
||||
}
|
||||
data := globals.GetDefaultValues(user, "MediaActors...")
|
||||
data["actors"] = actors
|
||||
c.Render(http.StatusOK, "media_actors", data)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (handler *MediaActorHandler) EditPage(c *echo.Context) {
|
||||
func (handler *MediaActorHandler) EditPage(c *echo.Context) error {
|
||||
cookie, err := c.Cookie(globals.UserKey)
|
||||
user := cookie.Value
|
||||
id := c.Param("id")
|
||||
//logger := slog.Get(c)
|
||||
actor, err := handler.Service.Get(c.Request().Context(), id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
data := globals.GetDefaultValues(user, "MediaActors...")
|
||||
data["actor"] = actor
|
||||
c.Render(http.StatusOK, "actor_detail", data)
|
||||
return c.Render(http.StatusOK, "actor_detail", data)
|
||||
}
|
||||
|
||||
func (handler *MediaActorHandler) UpdatePage(c *echo.Context) {
|
||||
func (handler *MediaActorHandler) UpdatePage(c *echo.Context) error {
|
||||
cookie, err := c.Cookie(globals.UserKey)
|
||||
user := cookie.Value
|
||||
id := c.Param("id")
|
||||
@@ -103,8 +103,7 @@ func (handler *MediaActorHandler) UpdatePage(c *echo.Context) {
|
||||
actor, err := handler.Service.Get(c.Request().Context(), id)
|
||||
if err != nil {
|
||||
logger.Info("MediaActorHandler#UpdatePage", "error", err.Error())
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
var form models.MediaActorForm
|
||||
if err := c.Bind(&form); err != nil {
|
||||
@@ -113,15 +112,14 @@ func (handler *MediaActorHandler) UpdatePage(c *echo.Context) {
|
||||
data["actor"] = actor
|
||||
data["Form"] = form
|
||||
data["Errors"] = err.Error()
|
||||
c.Render(http.StatusBadRequest, "actor_detail", data)
|
||||
return
|
||||
return c.Render(http.StatusBadRequest, "actor_detail", data)
|
||||
}
|
||||
logger.Info("MediaActorHandler#UpdatePage", "actor", actor)
|
||||
//handler.Service.Update(c.Request.Context(), form.ConvertFormToMediaLofiDTO())
|
||||
c.Redirect(http.StatusFound, globals.MediaActorLink)
|
||||
return c.Redirect(http.StatusFound, globals.MediaActorLink)
|
||||
}
|
||||
|
||||
func (handler *MediaActorHandler) DeletePage(c *echo.Context) {
|
||||
func (handler *MediaActorHandler) DeletePage(c *echo.Context) error {
|
||||
//session := sessions.Default(c)
|
||||
//user := session.Get(globals.UserKey)
|
||||
id := c.Param("id")
|
||||
@@ -129,9 +127,9 @@ func (handler *MediaActorHandler) DeletePage(c *echo.Context) {
|
||||
//actor, err := handler.Service.Get(c.Request.Context(), id)
|
||||
// if err != nil {
|
||||
// logger.Info("MediaActorHandler#DeletePage", "error", err.Error())
|
||||
// c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
// c.JSON(http.StatusInternalServerError, map[string]any{"error": err.Error()})
|
||||
// return
|
||||
// }
|
||||
logger.Info("MediaActorHandler#DeletePage", "actor", id)
|
||||
c.Redirect(http.StatusFound, globals.MediaActorLink)
|
||||
return c.Redirect(http.StatusFound, globals.MediaActorLink)
|
||||
}
|
||||
|
||||
@@ -22,44 +22,41 @@ func NewMediaArticleHandler(db *bun.DB) *MediaArticleHandler {
|
||||
return mediaFileHandler
|
||||
}
|
||||
|
||||
func (handler *MediaArticleHandler) List(c *echo.Context) {
|
||||
func (handler *MediaArticleHandler) List(c *echo.Context) error {
|
||||
logger := c.Logger()
|
||||
logger.Info("MediaArticleHandler#List")
|
||||
articles, err := handler.Service.List(c.Request().Context())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
dtos := models.ConvertMediaArticlesToDtos(articles)
|
||||
c.JSON(http.StatusOK, dtos)
|
||||
return c.JSON(http.StatusOK, dtos)
|
||||
}
|
||||
|
||||
func (handler *MediaArticleHandler) Delete(c *echo.Context) {
|
||||
func (handler *MediaArticleHandler) Delete(c *echo.Context) error {
|
||||
id := c.Param("id")
|
||||
err := handler.Service.Delete(c.Request().Context(), id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not found"})
|
||||
return
|
||||
return c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not found"})
|
||||
}
|
||||
c.JSON(http.StatusOK, map[string]string{"ok": "true"})
|
||||
return c.JSON(http.StatusOK, map[string]string{"ok": "true"})
|
||||
}
|
||||
|
||||
func (handler *MediaArticleHandler) ListPage(c *echo.Context) {
|
||||
func (handler *MediaArticleHandler) ListPage(c *echo.Context) error {
|
||||
cookie, err := c.Cookie(globals.UserKey)
|
||||
user := cookie.Value
|
||||
files, err := handler.Service.List(c.Request().Context())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
data := globals.GetDefaultValues(user, "MediaArticles...")
|
||||
data["title"] = "Kontor MediaArticles"
|
||||
data["media_links"] = files
|
||||
data["MediaLinksUrl"] = globals.MediaArticleLink
|
||||
c.Render(http.StatusOK, "media_links", data)
|
||||
return c.Render(http.StatusOK, "media_links", data)
|
||||
}
|
||||
|
||||
func (handler *MediaArticleHandler) EditPage(c *echo.Context) {
|
||||
func (handler *MediaArticleHandler) EditPage(c *echo.Context) error {
|
||||
cookie, err := c.Cookie(globals.UserKey)
|
||||
user := cookie.Value
|
||||
id := c.Param("id")
|
||||
@@ -67,16 +64,15 @@ func (handler *MediaArticleHandler) EditPage(c *echo.Context) {
|
||||
media_file, err := handler.Service.Get(c.Request().Context(), id)
|
||||
if err != nil {
|
||||
logger.Info("MediaArticleHandler#EditPage", "error", err.Error())
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
logger.Info("MediaArticleHandler#EditPage", "media_file", media_file)
|
||||
data := globals.GetDefaultValues(user, "MediaArticle Details...")
|
||||
data["lofi"] = media_file
|
||||
c.Render(http.StatusOK, "lofi_detail", data)
|
||||
return c.Render(http.StatusOK, "lofi_detail", data)
|
||||
}
|
||||
|
||||
func (handler *MediaArticleHandler) UpdatePage(c *echo.Context) {
|
||||
func (handler *MediaArticleHandler) UpdatePage(c *echo.Context) error {
|
||||
cookie, err := c.Cookie(globals.UserKey)
|
||||
user := cookie.Value
|
||||
id := c.Param("id")
|
||||
@@ -84,8 +80,7 @@ func (handler *MediaArticleHandler) UpdatePage(c *echo.Context) {
|
||||
media_article, err := handler.Service.Get(c.Request().Context(), id)
|
||||
if err != nil {
|
||||
logger.Info("MediaArticleHandler#UpdatePage", "error", err.Error())
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
var form models.MediaArticleForm
|
||||
if err := c.Bind(&form); err != nil {
|
||||
@@ -93,23 +88,21 @@ func (handler *MediaArticleHandler) UpdatePage(c *echo.Context) {
|
||||
data := globals.GetDefaultValues(user, "MediaArticle Details...")
|
||||
data["Form"] = form
|
||||
data["Errors"] = err.Error()
|
||||
c.Render(http.StatusBadRequest, "lofi_detail", data)
|
||||
return
|
||||
return c.Render(http.StatusBadRequest, "lofi_detail", data)
|
||||
}
|
||||
logger.Info("MediaArticleHandler#UpdatePage", "media_article", media_article)
|
||||
//handler.Service.Update(c.Request.Context(), form.ConvertFormToMediaFileDTO())
|
||||
c.Redirect(http.StatusFound, globals.MediaArticleLink)
|
||||
return c.Redirect(http.StatusFound, globals.MediaArticleLink)
|
||||
}
|
||||
|
||||
func (handler *MediaArticleHandler) DeletePage(c *echo.Context) {
|
||||
func (handler *MediaArticleHandler) DeletePage(c *echo.Context) error {
|
||||
id := c.Param("id")
|
||||
logger := c.Logger()
|
||||
err := handler.Service.Delete(c.Request().Context(), id)
|
||||
if err != nil {
|
||||
logger.Info("MediaArticleHandler#DeletePage", "error", err.Error())
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
logger.Info("MediaArticleHandler#DeletePage", "lofi", id)
|
||||
c.Redirect(http.StatusFound, globals.MediaArticleLink)
|
||||
return c.Redirect(http.StatusFound, globals.MediaArticleLink)
|
||||
}
|
||||
|
||||
@@ -22,59 +22,57 @@ func NewMediaFileHandler(db *bun.DB) *MediaFileHandler {
|
||||
return mediaFileHandler
|
||||
}
|
||||
|
||||
func (handler *MediaFileHandler) List(c *echo.Context) {
|
||||
func (handler *MediaFileHandler) List(c *echo.Context) error {
|
||||
logger := c.Logger()
|
||||
logger.Info("MediaFileHandler#List")
|
||||
files, err := handler.Service.List(c.Request().Context())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return err
|
||||
}
|
||||
dtos := models.ConvertMediaFilesToDtos(files)
|
||||
c.JSON(http.StatusOK, dtos)
|
||||
return c.JSON(http.StatusOK, dtos)
|
||||
}
|
||||
|
||||
func (handler *MediaFileHandler) Add(c *echo.Context) {
|
||||
func (handler *MediaFileHandler) Add(c *echo.Context) error {
|
||||
var input models.MediaFileAdd
|
||||
|
||||
if err := c.Bind(&input); err != nil {
|
||||
c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return err
|
||||
}
|
||||
lofi, err := handler.Service.Add(c.Request().Context(), input.Url)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not added"})
|
||||
return
|
||||
return err
|
||||
}
|
||||
c.JSON(http.StatusOK, lofi)
|
||||
return c.JSON(http.StatusOK, lofi)
|
||||
}
|
||||
|
||||
func (handler *MediaFileHandler) Delete(c *echo.Context) {
|
||||
func (handler *MediaFileHandler) Delete(c *echo.Context) error {
|
||||
id := c.Param("id")
|
||||
err := handler.Service.Delete(c.Request().Context(), id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not found"})
|
||||
return
|
||||
return c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not found"})
|
||||
}
|
||||
c.JSON(http.StatusOK, map[string]string{"ok": "true"})
|
||||
return c.JSON(http.StatusOK, map[string]string{"ok": "true"})
|
||||
}
|
||||
|
||||
func (handler *MediaFileHandler) ListPage(c *echo.Context) {
|
||||
func (handler *MediaFileHandler) ListPage(c *echo.Context) error {
|
||||
cookie, err := c.Cookie(globals.UserKey)
|
||||
user := cookie.Value
|
||||
files, err := handler.Service.List(c.Request().Context())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
data := globals.GetDefaultValues(user, "MediaFiles...")
|
||||
data["title"] = "Kontor MediaFiles"
|
||||
data["media_links"] = files
|
||||
data["MediaLinksUrl"] = globals.MediaVideoLink
|
||||
c.Render(http.StatusOK, "media_links", data)
|
||||
return c.Render(http.StatusOK, "media_links", data)
|
||||
}
|
||||
|
||||
func (handler *MediaFileHandler) EditPage(c *echo.Context) {
|
||||
func (handler *MediaFileHandler) EditPage(c *echo.Context) error {
|
||||
cookie, err := c.Cookie(globals.UserKey)
|
||||
user := cookie.Value
|
||||
id := c.Param("id")
|
||||
@@ -82,16 +80,15 @@ func (handler *MediaFileHandler) EditPage(c *echo.Context) {
|
||||
media_file, err := handler.Service.Get(c.Request().Context(), id)
|
||||
if err != nil {
|
||||
logger.Info("MediaLoFiHandler#EditPage", "error", err.Error())
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
logger.Info("MediaLoFiHandler#EditPage", "media_file", media_file)
|
||||
data := globals.GetDefaultValues(user, "MediaFile Details...")
|
||||
data["lofi"] = media_file
|
||||
c.Render(http.StatusOK, "lofi_detail", data)
|
||||
return c.Render(http.StatusOK, "lofi_detail", data)
|
||||
}
|
||||
|
||||
func (handler *MediaFileHandler) UpdatePage(c *echo.Context) {
|
||||
func (handler *MediaFileHandler) UpdatePage(c *echo.Context) error {
|
||||
cookie, err := c.Cookie(globals.UserKey)
|
||||
user := cookie.Value
|
||||
id := c.Param("id")
|
||||
@@ -99,8 +96,7 @@ func (handler *MediaFileHandler) UpdatePage(c *echo.Context) {
|
||||
media_file, err := handler.Service.Get(c.Request().Context(), id)
|
||||
if err != nil {
|
||||
logger.Info("MediaFileHandler#UpdatePage", "error", err.Error())
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
var form models.MediaFileForm
|
||||
if err := c.Bind(&form); err != nil {
|
||||
@@ -108,15 +104,14 @@ func (handler *MediaFileHandler) UpdatePage(c *echo.Context) {
|
||||
data := globals.GetDefaultValues(user, "MediaFile Details...")
|
||||
data["Form"] = form
|
||||
data["Errors"] = err.Error()
|
||||
c.Render(http.StatusBadRequest, "lofi_detail", data)
|
||||
return
|
||||
return c.Render(http.StatusBadRequest, "lofi_detail", data)
|
||||
}
|
||||
logger.Info("MediaFileHandler#UpdatePage", "media_file", media_file)
|
||||
//handler.Service.Update(c.Request.Context(), form.ConvertFormToMediaFileDTO())
|
||||
c.Redirect(http.StatusFound, globals.MediaFileLink)
|
||||
return c.Redirect(http.StatusFound, globals.MediaFileLink)
|
||||
}
|
||||
|
||||
func (handler *MediaFileHandler) DeletePage(c *echo.Context) {
|
||||
func (handler *MediaFileHandler) DeletePage(c *echo.Context) error {
|
||||
//session := sessions.Default(c)
|
||||
//user := session.Get(globals.UserKey)
|
||||
id := c.Param("id")
|
||||
@@ -124,9 +119,8 @@ func (handler *MediaFileHandler) DeletePage(c *echo.Context) {
|
||||
err := handler.Service.Delete(c.Request().Context(), id)
|
||||
if err != nil {
|
||||
logger.Info("MediaFileHandler#DeletePage", "error", err.Error())
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
logger.Info("MediaFileHandler#DeletePage", "lofi", id)
|
||||
c.Redirect(http.StatusFound, globals.MediaFileLink)
|
||||
return c.Redirect(http.StatusFound, globals.MediaFileLink)
|
||||
}
|
||||
|
||||
@@ -59,33 +59,31 @@ func (handler *MediaLoFiHandler) Add(c *echo.Context) {
|
||||
c.JSON(http.StatusOK, lofi)
|
||||
}
|
||||
|
||||
func (handler *MediaLoFiHandler) Update(c *echo.Context) {
|
||||
func (handler *MediaLoFiHandler) Update(c *echo.Context) error {
|
||||
var input models.MediaLoFiDTO
|
||||
|
||||
if err := c.Bind(&input); err != nil {
|
||||
c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
}
|
||||
lofi, err := handler.Service.Update(c.Request().Context(), input)
|
||||
if err != nil {
|
||||
logger := c.Logger()
|
||||
logger.Info("MediaLoFiHandler#Update", "error", err.Error())
|
||||
c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not updated"})
|
||||
return
|
||||
return c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not updated"})
|
||||
}
|
||||
c.JSON(http.StatusOK, lofi)
|
||||
return c.JSON(http.StatusOK, lofi)
|
||||
}
|
||||
func (handler *MediaLoFiHandler) Delete(c *echo.Context) {
|
||||
|
||||
func (handler *MediaLoFiHandler) Delete(c *echo.Context) error {
|
||||
id := c.Param("id")
|
||||
err := handler.Service.Delete(c.Request().Context(), id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not found"})
|
||||
return
|
||||
return c.JSON(http.StatusNotFound, map[string]string{"error": "lofi not found"})
|
||||
}
|
||||
c.JSON(http.StatusOK, map[string]string{"ok": "true"})
|
||||
return c.JSON(http.StatusOK, map[string]string{"ok": "true"})
|
||||
}
|
||||
|
||||
func (handler *MediaLoFiHandler) ListPage(c *echo.Context) {
|
||||
func (handler *MediaLoFiHandler) ListPage(c *echo.Context) error {
|
||||
cookie, err := c.Cookie(globals.UserKey)
|
||||
user := cookie.Value
|
||||
logger := c.Logger()
|
||||
@@ -113,8 +111,7 @@ func (handler *MediaLoFiHandler) ListPage(c *echo.Context) {
|
||||
lofis, err := handler.Service.List(c.Request().Context())
|
||||
if err != nil {
|
||||
logger.Info("MediaLoFiHandler#ListPage", "error", err.Error())
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
logger.Info("MediaLoFiHandler#ListPage", "lofis count", len(lofis))
|
||||
data := globals.GetDefaultValues(user, "MediaFiles...")
|
||||
@@ -122,10 +119,10 @@ func (handler *MediaLoFiHandler) ListPage(c *echo.Context) {
|
||||
data["isReview"] = review
|
||||
data["isDownload"] = download
|
||||
data["MediaLinksUrl"] = globals.MediaLofiLink
|
||||
c.Render(http.StatusOK, "media_links", data)
|
||||
return c.Render(http.StatusOK, "media_links", data)
|
||||
}
|
||||
|
||||
func (handler *MediaLoFiHandler) EditPage(c *echo.Context) {
|
||||
func (handler *MediaLoFiHandler) EditPage(c *echo.Context) error {
|
||||
cookie, err := c.Cookie(globals.UserKey)
|
||||
user := cookie.Value
|
||||
id := c.Param("id")
|
||||
@@ -146,25 +143,23 @@ func (handler *MediaLoFiHandler) EditPage(c *echo.Context) {
|
||||
lofi, err = handler.Service.Get(c.Request().Context(), id)
|
||||
if err != nil {
|
||||
logger.Info("MediaLoFiHandler#EditPage", "error", err.Error())
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
}
|
||||
logger.Info("MediaLoFiHandler#EditPage", "lofi", lofi)
|
||||
data := globals.GetDefaultValues(user, "MediaLofis...")
|
||||
data["media"] = lofi
|
||||
data["MediaLinksUrl"] = globals.MediaLofiLink
|
||||
c.Render(http.StatusOK, "media_detail", data)
|
||||
return c.Render(http.StatusOK, "media_detail", data)
|
||||
}
|
||||
|
||||
func (handler *MediaLoFiHandler) ChangeReviewPage(c *echo.Context) {
|
||||
func (handler *MediaLoFiHandler) ChangeReviewPage(c *echo.Context) error {
|
||||
id := c.Param("id")
|
||||
logger := c.Logger()
|
||||
lofi, err := handler.Service.Get(c.Request().Context(), id)
|
||||
if err != nil {
|
||||
logger.Info("MediaLoFiHandler#ChangeReviewPage", "error", err.Error())
|
||||
c.Redirect(http.StatusNotFound, globals.MediaLofiLink)
|
||||
return
|
||||
return c.Redirect(http.StatusNotFound, globals.MediaLofiLink)
|
||||
}
|
||||
lofi.Review = !lofi.Review
|
||||
handler.Service.Update(c.Request().Context(), lofi.ConvertMediaLoFiToDTO())
|
||||
@@ -174,17 +169,16 @@ func (handler *MediaLoFiHandler) ChangeReviewPage(c *echo.Context) {
|
||||
lofis, err := handler.Service.List(c.Request().Context())
|
||||
if err != nil {
|
||||
logger.Info("MediaLoFiHandler#ChangeReviewPage", "error", err.Error())
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
logger.Info("MediaLoFiHandler#ListPage", "lofis count", len(lofis))
|
||||
data := globals.GetDefaultValues(user, "MediaLofis...")
|
||||
data["lofis"] = lofis
|
||||
//c.HTML(http.StatusOK, "lofi", data)
|
||||
c.Redirect(http.StatusCreated, globals.MediaLofiLink)
|
||||
//c.Render(http.StatusOK, "lofi", data)
|
||||
return c.Redirect(http.StatusCreated, globals.MediaLofiLink)
|
||||
}
|
||||
|
||||
func (handler *MediaLoFiHandler) UpdatePage(c *echo.Context) {
|
||||
func (handler *MediaLoFiHandler) UpdatePage(c *echo.Context) error {
|
||||
cookie, err := c.Cookie(globals.UserKey)
|
||||
user := cookie.Value
|
||||
id := c.Param("id")
|
||||
@@ -192,25 +186,23 @@ func (handler *MediaLoFiHandler) UpdatePage(c *echo.Context) {
|
||||
lofi, err := handler.Service.Get(c.Request().Context(), id)
|
||||
if err != nil {
|
||||
logger.Info("MediaLoFiHandler#UpdatePage", "error", err.Error())
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
var form models.MediaLoFiForm
|
||||
if err := c.Bind(&form); err != nil {
|
||||
logger.Info("MediaLoFiHandler#UpdatePage", "error", err.Error())
|
||||
c.Render(http.StatusBadRequest, "lofi_detail", map[string]any{
|
||||
return c.Render(http.StatusBadRequest, "lofi_detail", map[string]any{
|
||||
"Form": form,
|
||||
"Errors": err.Error(),
|
||||
"user": user,
|
||||
})
|
||||
return
|
||||
}
|
||||
logger.Info("MediaLoFiHandler#UpdatePage", "lofi", lofi)
|
||||
//handler.Service.Update(c.Request.Context(), form.ConvertFormToMediaLofiDTO())
|
||||
c.Redirect(http.StatusFound, globals.MediaLofiLink)
|
||||
return c.Redirect(http.StatusFound, globals.MediaLofiLink)
|
||||
}
|
||||
|
||||
func (handler *MediaLoFiHandler) DeletePage(c *echo.Context) {
|
||||
func (handler *MediaLoFiHandler) DeletePage(c *echo.Context) error {
|
||||
cookie, err := c.Cookie(globals.UserKey)
|
||||
user := cookie.Value
|
||||
id := c.Param("id")
|
||||
@@ -218,11 +210,10 @@ func (handler *MediaLoFiHandler) DeletePage(c *echo.Context) {
|
||||
lofi, err := handler.Service.Get(c.Request().Context(), id)
|
||||
if err != nil {
|
||||
logger.Info("MediaLoFiHandler#DeletePage", "error", err.Error())
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
logger.Info("MediaLoFiHandler#DeletePage", "lofi", id)
|
||||
c.Render(http.StatusOK, "lofi_delete", map[string]any{
|
||||
return c.Render(http.StatusOK, "lofi_delete", map[string]any{
|
||||
"title": "Kontor MediaFiles",
|
||||
"version": "0.4.0",
|
||||
"message": "MediaFiles...",
|
||||
|
||||
@@ -22,68 +22,62 @@ func NewMediaMusicHandler(db *bun.DB) *MediaMusicHandler {
|
||||
return mediaMusicHandler
|
||||
}
|
||||
|
||||
func (handler *MediaMusicHandler) List(c *echo.Context) {
|
||||
func (handler *MediaMusicHandler) List(c *echo.Context) error {
|
||||
musics, err := handler.Service.List(c.Request().Context())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
dtos := models.ConvertMediaMusicsToDtos(musics)
|
||||
c.JSON(http.StatusOK, dtos)
|
||||
return c.JSON(http.StatusOK, dtos)
|
||||
}
|
||||
|
||||
func (handler *MediaMusicHandler) Get(c *echo.Context) {
|
||||
func (handler *MediaMusicHandler) Get(c *echo.Context) error {
|
||||
id := c.Param("id")
|
||||
music, err := handler.Service.Get(c.Request().Context(), id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, map[string]string{"error": "MediaMusic not found"})
|
||||
return
|
||||
return c.JSON(http.StatusNotFound, map[string]string{"error": "MediaMusic not found"})
|
||||
}
|
||||
c.JSON(http.StatusOK, music)
|
||||
return c.JSON(http.StatusOK, music)
|
||||
}
|
||||
|
||||
func (handler *MediaMusicHandler) Add(c *echo.Context) {
|
||||
func (handler *MediaMusicHandler) Add(c *echo.Context) error {
|
||||
var input models.MediaLofiAdd
|
||||
|
||||
if err := c.Bind(&input); err != nil {
|
||||
c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
}
|
||||
music, err := handler.Service.Add(c.Request().Context(), input.Url)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, map[string]string{"error": "MediaMusic not added"})
|
||||
return
|
||||
return c.JSON(http.StatusNotFound, map[string]string{"error": "MediaMusic not added"})
|
||||
}
|
||||
c.JSON(http.StatusOK, music)
|
||||
return c.JSON(http.StatusOK, music)
|
||||
}
|
||||
|
||||
func (handler *MediaMusicHandler) Update(c *echo.Context) {
|
||||
func (handler *MediaMusicHandler) Update(c *echo.Context) error {
|
||||
var input models.MediaMusicDTO
|
||||
|
||||
if err := c.Bind(&input); err != nil {
|
||||
c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": err.Error()})
|
||||
}
|
||||
music, err := handler.Service.Update(c.Request().Context(), input)
|
||||
if err != nil {
|
||||
logger := c.Logger()
|
||||
logger.Info("MediaMusicHandler#Update", "error", err.Error())
|
||||
c.JSON(http.StatusNotFound, map[string]string{"error": "MediaMusic not updated"})
|
||||
return
|
||||
return c.JSON(http.StatusNotFound, map[string]string{"error": "MediaMusic not updated"})
|
||||
}
|
||||
c.JSON(http.StatusOK, music)
|
||||
return c.JSON(http.StatusOK, music)
|
||||
}
|
||||
func (handler *MediaMusicHandler) Delete(c *echo.Context) {
|
||||
|
||||
func (handler *MediaMusicHandler) Delete(c *echo.Context) error {
|
||||
id := c.Param("id")
|
||||
err := handler.Service.Delete(c.Request().Context(), id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, map[string]string{"error": "MediaMusic not found"})
|
||||
return
|
||||
return c.JSON(http.StatusNotFound, map[string]string{"error": "MediaMusic not found"})
|
||||
}
|
||||
c.JSON(http.StatusOK, map[string]string{"ok": "true"})
|
||||
return c.JSON(http.StatusOK, map[string]string{"ok": "true"})
|
||||
}
|
||||
|
||||
func (handler *MediaMusicHandler) ListPage(c *echo.Context) {
|
||||
func (handler *MediaMusicHandler) ListPage(c *echo.Context) error {
|
||||
cookie, err := c.Cookie(globals.UserKey)
|
||||
user := cookie.Value
|
||||
logger := c.Logger()
|
||||
@@ -111,8 +105,7 @@ func (handler *MediaMusicHandler) ListPage(c *echo.Context) {
|
||||
musics, err := handler.Service.List(c.Request().Context())
|
||||
if err != nil {
|
||||
logger.Info("MediaMusicHandler#ListPage", "error", err.Error())
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
logger.Info("MediaMusicHandler#ListPage", "MediaMusic count", len(musics))
|
||||
data := globals.GetDefaultValues(user, "MediaMusic...")
|
||||
@@ -120,10 +113,10 @@ func (handler *MediaMusicHandler) ListPage(c *echo.Context) {
|
||||
data["MediaLinksUrl"] = globals.MediaMusicLink
|
||||
data["isReview"] = review
|
||||
data["isDownload"] = download
|
||||
c.Render(http.StatusOK, "media_links", data)
|
||||
return c.Render(http.StatusOK, "media_links", data)
|
||||
}
|
||||
|
||||
func (handler *MediaMusicHandler) EditPage(c *echo.Context) {
|
||||
func (handler *MediaMusicHandler) EditPage(c *echo.Context) error {
|
||||
cookie, err := c.Cookie(globals.UserKey)
|
||||
user := cookie.Value
|
||||
id := c.Param("id")
|
||||
@@ -131,16 +124,15 @@ func (handler *MediaMusicHandler) EditPage(c *echo.Context) {
|
||||
music, err := handler.Service.Get(c.Request().Context(), id)
|
||||
if err != nil {
|
||||
logger.Info("MediaMusicHandler#EditPage", "error", err.Error())
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
logger.Info("MediaMusicHandler#EditPage", "music", music)
|
||||
data := globals.GetDefaultValues(user, "MediaMusic...")
|
||||
data["lofi"] = music
|
||||
c.Render(http.StatusOK, "lofi_detail", data)
|
||||
return c.Render(http.StatusOK, "lofi_detail", data)
|
||||
}
|
||||
|
||||
func (handler *MediaMusicHandler) UpdatePage(c *echo.Context) {
|
||||
func (handler *MediaMusicHandler) UpdatePage(c *echo.Context) error {
|
||||
cookie, err := c.Cookie(globals.UserKey)
|
||||
user := cookie.Value
|
||||
id := c.Param("id")
|
||||
@@ -148,8 +140,7 @@ func (handler *MediaMusicHandler) UpdatePage(c *echo.Context) {
|
||||
music, err := handler.Service.Get(c.Request().Context(), id)
|
||||
if err != nil {
|
||||
logger.Info("MediaMusicHandler#UpdatePage", "error", err.Error())
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
var form models.MediaMusicForm
|
||||
if err := c.Bind(&form); err != nil {
|
||||
@@ -157,15 +148,14 @@ func (handler *MediaMusicHandler) UpdatePage(c *echo.Context) {
|
||||
data := globals.GetDefaultValues(user, "MediaMusic...")
|
||||
data["Form"] = form
|
||||
data["Errors"] = err.Error()
|
||||
c.Render(http.StatusBadRequest, "lofi_detail", data)
|
||||
return
|
||||
return c.Render(http.StatusBadRequest, "lofi_detail", data)
|
||||
}
|
||||
logger.Info("MediaMusicHandler#UpdatePage", "music", music)
|
||||
//handler.Service.Update(c.Request.Context(), form.ConvertFormToMediaLofiDTO())
|
||||
c.Redirect(http.StatusFound, globals.MediaMusicLink)
|
||||
return c.Redirect(http.StatusFound, globals.MediaMusicLink)
|
||||
}
|
||||
|
||||
func (handler *MediaMusicHandler) DeletePage(c *echo.Context) {
|
||||
func (handler *MediaMusicHandler) DeletePage(c *echo.Context) error {
|
||||
// session := sessions.Default(c)
|
||||
// user := session.Get(globals.UserKey)
|
||||
id := c.Param("id")
|
||||
@@ -173,9 +163,8 @@ func (handler *MediaMusicHandler) DeletePage(c *echo.Context) {
|
||||
err := handler.Service.Delete(c.Request().Context(), id)
|
||||
if err != nil {
|
||||
logger.Info("MediaMusicHandler#DeletePage", "error", err.Error())
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
logger.Info("MediaMusicHandler#DeletePage", "music", id)
|
||||
c.Redirect(http.StatusFound, globals.MediaMusicLink)
|
||||
return c.Redirect(http.StatusFound, globals.MediaMusicLink)
|
||||
}
|
||||
|
||||
@@ -20,36 +20,34 @@ func NewMediaVideoHandler(db *bun.DB) *MediaVideoHandler {
|
||||
return handler
|
||||
}
|
||||
|
||||
func (handler *MediaVideoHandler) List(c *echo.Context) {
|
||||
func (handler *MediaVideoHandler) List(c *echo.Context) error {
|
||||
logger := c.Logger()
|
||||
logger.Info("MediaVideoHandler#List")
|
||||
videos, err := handler.Service.List(c.Request().Context())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
dtos := models.ConvertMediaVideosToDtos(videos)
|
||||
c.JSON(http.StatusOK, dtos)
|
||||
return c.JSON(http.StatusOK, dtos)
|
||||
}
|
||||
|
||||
func (handler *MediaVideoHandler) ListPage(c *echo.Context) {
|
||||
func (handler *MediaVideoHandler) ListPage(c *echo.Context) error {
|
||||
cookie, err := c.Cookie(globals.UserKey)
|
||||
user := cookie.Value
|
||||
logger := c.Logger()
|
||||
videos, err := handler.Service.List(c.Request().Context())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
logger.Info("MediaVideoHandler#ListPage", "videos count", len(videos))
|
||||
data := globals.GetDefaultValues(user, "MediaVideos...")
|
||||
data["title"] = "Kontor MediaVideos"
|
||||
data["media_links"] = videos
|
||||
data["MediaLinksUrl"] = globals.MediaVideoLink
|
||||
c.Render(http.StatusOK, "media_links", data)
|
||||
return c.Render(http.StatusOK, "media_links", data)
|
||||
}
|
||||
|
||||
func (handler *MediaVideoHandler) EditPage(c *echo.Context) {
|
||||
func (handler *MediaVideoHandler) EditPage(c *echo.Context) error {
|
||||
cookie, err := c.Cookie(globals.UserKey)
|
||||
user := cookie.Value
|
||||
id := c.Param("id")
|
||||
@@ -57,16 +55,15 @@ func (handler *MediaVideoHandler) EditPage(c *echo.Context) {
|
||||
video, err := handler.Service.Get(c.Request().Context(), id)
|
||||
if err != nil {
|
||||
logger.Info("MediaVideoHandler#EditPage", "error", err.Error())
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
logger.Info("MediaVideoHandler#EditPage", "lofi", video)
|
||||
data := globals.GetDefaultValues(user, "MediaLofis...")
|
||||
data["lofi"] = video
|
||||
c.Render(http.StatusOK, "lofi_detail", data)
|
||||
return c.Render(http.StatusOK, "lofi_detail", data)
|
||||
}
|
||||
|
||||
func (handler *MediaVideoHandler) UpdatePage(c *echo.Context) {
|
||||
func (handler *MediaVideoHandler) UpdatePage(c *echo.Context) error {
|
||||
cookie, err := c.Cookie(globals.UserKey)
|
||||
user := cookie.Value
|
||||
id := c.Param("id")
|
||||
@@ -74,25 +71,23 @@ func (handler *MediaVideoHandler) UpdatePage(c *echo.Context) {
|
||||
video, err := handler.Service.Get(c.Request().Context(), id)
|
||||
if err != nil {
|
||||
logger.Info("MediaVideoHandler#UpdatePage", "error", err.Error())
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
var form models.MediaVideoForm
|
||||
if err := c.Bind(&form); err != nil {
|
||||
logger.Info("MediaVideoHandler#UpdatePage", "error", err.Error())
|
||||
c.Render(http.StatusBadRequest, "lofi_detail", map[string]any{
|
||||
return c.Render(http.StatusBadRequest, "lofi_detail", map[string]any{
|
||||
"Form": form,
|
||||
"Errors": err.Error(),
|
||||
"user": user,
|
||||
})
|
||||
return
|
||||
}
|
||||
logger.Info("MediaVideoHandler#UpdatePage", "lofi", video)
|
||||
//handler.Service.Update(c.Request.Context(), form.ConvertFormToMediaLofiDTO())
|
||||
c.Redirect(http.StatusFound, globals.MediaVideoLink)
|
||||
return c.Redirect(http.StatusFound, globals.MediaVideoLink)
|
||||
}
|
||||
|
||||
func (handler *MediaVideoHandler) DeletePage(c *echo.Context) {
|
||||
func (handler *MediaVideoHandler) DeletePage(c *echo.Context) error {
|
||||
cookie, err := c.Cookie(globals.UserKey)
|
||||
user := cookie.Value
|
||||
id := c.Param("id")
|
||||
@@ -100,11 +95,10 @@ func (handler *MediaVideoHandler) DeletePage(c *echo.Context) {
|
||||
err = handler.Service.Delete(c.Request().Context(), id)
|
||||
if err != nil {
|
||||
logger.Info("MediaVideoHandler#DeletePage", "error", err.Error())
|
||||
c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
return
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
logger.Info("MediaVideoHandler#DeletePage", "video", id)
|
||||
c.Render(http.StatusOK, "lofi_delete", map[string]string{
|
||||
return c.Render(http.StatusOK, "lofi_delete", map[string]string{
|
||||
"title": "Kontor MediaFiles",
|
||||
"version": "0.4.0",
|
||||
"message": "MediaFiles...",
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"kontor-api-echo/internal/models"
|
||||
"kontor-api-echo/internal/repository"
|
||||
"kontor-api-echo/internal/service"
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v5"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
type TokenHandler struct {
|
||||
Service *service.TokenService
|
||||
}
|
||||
|
||||
func NewTokenHandler(db *bun.DB) *TokenHandler {
|
||||
handler := &TokenHandler{Service: service.NewTokenService(repository.NewTokenRepository(db))}
|
||||
return handler
|
||||
}
|
||||
|
||||
func (handler *TokenHandler) List(c *echo.Context) {
|
||||
tokens, err := handler.Service.List(c.Request().Context())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, map[string]any{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
dtos := models.ConvertTokensToDtos(tokens)
|
||||
c.JSON(http.StatusOK, dtos)
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package helpers
|
||||
|
||||
import "strings"
|
||||
|
||||
func EmptyUserPass(username, password string) bool {
|
||||
return strings.Trim(username, " ") == "" || strings.Trim(password, " ") == ""
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/labstack/echo/v5"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
func GenerateToken(profile_id string) (string, error) {
|
||||
|
||||
// token_lifespan := viper.GetInt("token_hour_lifespan")
|
||||
|
||||
claims := jwt.MapClaims{
|
||||
"name": "Thomas Peetz",
|
||||
"admin": true,
|
||||
"authorized": true,
|
||||
"sub": profile_id,
|
||||
"exp": time.Now().Add(time.Hour * 72).Unix(),
|
||||
}
|
||||
// claims["authorized"] = true
|
||||
// claims["profile_id"] = profile_id
|
||||
// claims["exp"] = time.Now().Add(time.Hour * time.Duration(token_lifespan)).Unix()
|
||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||
|
||||
return token.SignedString([]byte(viper.GetString("api_secret")))
|
||||
|
||||
}
|
||||
|
||||
func TokenValid(c *echo.Context) error {
|
||||
logger := c.Logger()
|
||||
|
||||
tokenString := ExtractToken(c)
|
||||
_, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
||||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||
logger.Info("TokenValid", "Unexpected signing method", token.Header["alg"])
|
||||
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
|
||||
}
|
||||
return []byte(viper.GetString("api_secret")), nil
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ExtractToken(c *echo.Context) string {
|
||||
logger := c.Logger()
|
||||
|
||||
token := c.QueryParam("token")
|
||||
if token != "" {
|
||||
logger.Info("ExtractToken", "token from query", token)
|
||||
return token
|
||||
}
|
||||
bearerToken := c.Request().Header.Get("Authorization")
|
||||
if len(strings.Split(bearerToken, " ")) == 2 {
|
||||
logger.Info("ExtractToken", "token from query", token)
|
||||
|
||||
return strings.Split(bearerToken, " ")[1]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func ExtractTokenID(c *echo.Context) (string, error) {
|
||||
|
||||
tokenString := ExtractToken(c)
|
||||
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
||||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||
return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
|
||||
}
|
||||
return []byte(viper.GetString("api_secret")), nil
|
||||
})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
claims, ok := token.Claims.(jwt.MapClaims)
|
||||
if ok && token.Valid {
|
||||
uid, ok := claims["profile_id"].(string)
|
||||
if !ok {
|
||||
return "", err
|
||||
}
|
||||
return uid, nil
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
func StripUrl(webLink string, keepParam string) string {
|
||||
u, err := url.Parse(webLink)
|
||||
if err != nil {
|
||||
slog.Info("StripUrl", "error", err)
|
||||
return webLink
|
||||
}
|
||||
values := u.Query()
|
||||
for key := range values {
|
||||
if key != keepParam {
|
||||
values.Del(key)
|
||||
}
|
||||
}
|
||||
u.RawQuery = values.Encode()
|
||||
return u.String()
|
||||
}
|
||||
|
||||
func GetParam(webLink string, param string) string {
|
||||
u, err := url.Parse(webLink)
|
||||
if err != nil {
|
||||
slog.Info("StripUrl", "error", err)
|
||||
return webLink
|
||||
}
|
||||
values := u.Query()
|
||||
for key := range values {
|
||||
if key == param {
|
||||
return values.Get(key)
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type OEmbedResponse struct {
|
||||
Title string `json:"title"`
|
||||
}
|
||||
|
||||
func GetVideoTitle(videoUrl string) (string, error) {
|
||||
videoID := GetParam(videoUrl, "v")
|
||||
// Construct the oEmbed URL
|
||||
url := fmt.Sprintf("https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v=%s&format=json", videoID)
|
||||
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var data OEmbedResponse
|
||||
if err := json.Unmarshal(body, &data); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return data.Title, nil
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"kontor-api-echo/internal/helpers"
|
||||
"time"
|
||||
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
type Mail struct {
|
||||
bun.BaseModel `bun:"table:mail"`
|
||||
|
||||
ID string `bun:"id,pk"`
|
||||
CreatedAt time.Time `bun:"created_date,nullzero,notnull,default:current_timestamp"`
|
||||
UpdatedAt time.Time `bun:"last_modified_date,nullzero,notnull,default:current_timestamp"`
|
||||
DeletedAt *time.Time `bun:"deleted_date,nullzero"`
|
||||
Version int `bun:"version,default:0"`
|
||||
Folder string `bun:"folder"`
|
||||
Subject string `bun:"subject"`
|
||||
Body string `bun:"body"`
|
||||
SendAt time.Time `bun:"sent_date"`
|
||||
ReceivedAt time.Time `bun:"received_date"`
|
||||
}
|
||||
|
||||
type MailDTO struct {
|
||||
ID string `json:"id" binding:"required"`
|
||||
CreatedAt helpers.KontorTime `json:"created_date"`
|
||||
UpdatedAt helpers.KontorTime `json:"last_modified_date"`
|
||||
DeletedAt *time.Time `json:"deleted_date.omitempty"`
|
||||
Version int `json:"version"`
|
||||
Folder string `json:"folder"`
|
||||
Subject string `json:"subject"`
|
||||
Body string `json:"body"`
|
||||
SendAt time.Time `json:"sent_date"`
|
||||
ReceivedAt time.Time `json:"received_date"`
|
||||
}
|
||||
|
||||
func (dto MailDTO) ConvertDTOToModel() Mail {
|
||||
model := Mail{
|
||||
ID: dto.ID,
|
||||
CreatedAt: dto.CreatedAt.Time,
|
||||
UpdatedAt: dto.UpdatedAt.Time,
|
||||
DeletedAt: dto.DeletedAt,
|
||||
Version: dto.Version,
|
||||
Folder: dto.Folder,
|
||||
Subject: dto.Subject,
|
||||
Body: dto.Body,
|
||||
SendAt: dto.SendAt,
|
||||
ReceivedAt: dto.ReceivedAt,
|
||||
}
|
||||
return model
|
||||
}
|
||||
|
||||
func ConvertMailsToDtos(mails []Mail) []MailDTO {
|
||||
dtos := make([]MailDTO, len(mails))
|
||||
for i, mail := range mails {
|
||||
dtos[i] = MailDTO{
|
||||
ID: mail.ID,
|
||||
CreatedAt: helpers.KontorTime{Time: mail.CreatedAt},
|
||||
UpdatedAt: helpers.KontorTime{Time: mail.UpdatedAt},
|
||||
DeletedAt: mail.DeletedAt,
|
||||
Version: mail.Version,
|
||||
Folder: mail.Folder,
|
||||
Subject: mail.Subject,
|
||||
Body: mail.Body,
|
||||
SendAt: mail.SendAt,
|
||||
ReceivedAt: mail.ReceivedAt,
|
||||
}
|
||||
}
|
||||
return dtos
|
||||
}
|
||||
|
||||
type MailDTOList []MailDTO
|
||||
@@ -0,0 +1,77 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"kontor-api-echo/internal/helpers"
|
||||
"time"
|
||||
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
type MailAccount struct {
|
||||
bun.BaseModel `bun:"table:mail_account"`
|
||||
|
||||
ID string `bun:"id,pk"`
|
||||
CreatedAt time.Time `bun:"created_date,nullzero,notnull,default:current_timestamp"`
|
||||
UpdatedAt time.Time `bun:"last_modified_date,nullzero,notnull,default:current_timestamp"`
|
||||
DeletedAt *time.Time `bun:"deleted_date,nullzero"`
|
||||
Version int `bun:"version,default:0"`
|
||||
Host string `bun:"host"`
|
||||
Port int `bun:"port"`
|
||||
Protocol string `bun:"protocol"`
|
||||
UserName string `bun:"user_name"`
|
||||
Password string `bun:"password"`
|
||||
StartTLS bool `bun:"start_tls"`
|
||||
}
|
||||
|
||||
type MailAccountDTO struct {
|
||||
ID string `json:"id" binding:"required"`
|
||||
CreatedAt helpers.KontorTime `json:"created_date"`
|
||||
UpdatedAt helpers.KontorTime `json:"last_modified_date"`
|
||||
DeletedAt *time.Time `json:"deleted_date,omitempty"`
|
||||
Version int `json:"version"`
|
||||
Host string `json:"host"`
|
||||
Port int `json:"port"`
|
||||
Protocol string `json:"protocol"`
|
||||
UserName string `json:"user_name"`
|
||||
Password string `json:"password"`
|
||||
StartTLS bool `json:"start_tls"`
|
||||
}
|
||||
|
||||
func (dto MailAccountDTO) ConvertDTOToModel() MailAccount {
|
||||
model := MailAccount{
|
||||
ID: dto.ID,
|
||||
CreatedAt: dto.CreatedAt.Time,
|
||||
UpdatedAt: dto.UpdatedAt.Time,
|
||||
DeletedAt: dto.DeletedAt,
|
||||
Version: dto.Version,
|
||||
Host: dto.Host,
|
||||
Port: dto.Port,
|
||||
Protocol: dto.Protocol,
|
||||
UserName: dto.UserName,
|
||||
Password: dto.Password,
|
||||
StartTLS: dto.StartTLS,
|
||||
}
|
||||
return model
|
||||
}
|
||||
|
||||
func ConvertMailAccountsToDtos(mailaccounts []MailAccount) []MailAccountDTO {
|
||||
dtos := make([]MailAccountDTO, len(mailaccounts))
|
||||
for i, mailaccount := range mailaccounts {
|
||||
dtos[i] = MailAccountDTO{
|
||||
ID: mailaccount.ID,
|
||||
CreatedAt: helpers.KontorTime{Time: mailaccount.CreatedAt},
|
||||
UpdatedAt: helpers.KontorTime{Time: mailaccount.UpdatedAt},
|
||||
DeletedAt: mailaccount.DeletedAt,
|
||||
Version: mailaccount.Version,
|
||||
Host: mailaccount.Host,
|
||||
Port: mailaccount.Port,
|
||||
Protocol: mailaccount.Protocol,
|
||||
UserName: mailaccount.UserName,
|
||||
Password: mailaccount.Password,
|
||||
StartTLS: mailaccount.StartTLS,
|
||||
}
|
||||
}
|
||||
return dtos
|
||||
}
|
||||
|
||||
type MailAccountDTOList []MailAccountDTO
|
||||
@@ -4,7 +4,9 @@ import (
|
||||
"context"
|
||||
"kontor-api-echo/internal/models"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"github.com/labstack/echo/v5"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
@@ -19,41 +21,48 @@ func NewAssignmentRepository(db *bun.DB) *AssignmentRepository {
|
||||
|
||||
func (repository *AssignmentRepository) FindAll(context context.Context) ([]models.Assignment, error) {
|
||||
var assignments []models.Assignment
|
||||
|
||||
result := repository.db.Find(&assignments)
|
||||
slog.Info("AssignmentRepository#FindAll", "count", result.RowsAffected)
|
||||
err := repository.db.NewSelect().Model(&assignments).Scan(context)
|
||||
if err != nil {
|
||||
slog.Info(err.Error())
|
||||
return nil, echo.ErrInternalServerError
|
||||
}
|
||||
slog.Info("AssignmentRepository#FindAll", "count", len(assignments))
|
||||
|
||||
return assignments, nil
|
||||
}
|
||||
|
||||
func (repository *AssignmentRepository) GetById(context context.Context, id string) (models.Assignment, error) {
|
||||
func (repository *AssignmentRepository) GetById(context context.Context, id string) (*models.Assignment, error) {
|
||||
var assignment = models.Assignment{ID: id}
|
||||
slog.Info("AssignmentRepository#GetById", "id", id)
|
||||
result := repository.db.First(&assignment)
|
||||
if result.Error != nil {
|
||||
slog.Info("AssignmentRepository#GetById", "error", result.Error.Error())
|
||||
err := repository.db.NewSelect().Model(&assignment).Where("id = ?", id).Scan(context)
|
||||
if err != nil {
|
||||
slog.Info("AssignmentRepository#GetById", "error", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
return assignment, result.Error
|
||||
return &assignment, err
|
||||
}
|
||||
|
||||
func (repository *AssignmentRepository) Import(assignments models.AssignmentDTOList) {
|
||||
func (repository *AssignmentRepository) Import(dtos models.AssignmentDTOList) {
|
||||
slog.Info("AssignmentRepository#Import")
|
||||
for index, assignment := range assignments {
|
||||
slog.Info("importing", "index", index, "profile", assignment)
|
||||
model := assignment.ConvertDTOToModel()
|
||||
existing_item := models.Assignment{ID: assignment.ID}
|
||||
result_existing := repository.db.First(&existing_item)
|
||||
if result_existing.Error != nil {
|
||||
for index, dto := range dtos {
|
||||
slog.Info("importing", "index", index, "assignment", dto)
|
||||
model := dto.ConvertDTOToModel()
|
||||
existing_item := models.Assignment{ID: dto.ID}
|
||||
err := repository.db.NewSelect().Model(&existing_item).Where("id = ?", dto.ID).Scan(context.Background())
|
||||
if err != nil {
|
||||
slog.Info("check existing id: not found - inserting")
|
||||
result := repository.db.Create(&model)
|
||||
if result.Error != nil {
|
||||
slog.Info("error during import", "error", result.Error.Error())
|
||||
_, err := repository.db.NewInsert().Model(&model).Exec(context.Background())
|
||||
if err != nil {
|
||||
slog.Info("error during import", "error", err.Error())
|
||||
}
|
||||
} else {
|
||||
slog.Info("check existing id: found - updating")
|
||||
result := repository.db.Save(&model)
|
||||
if result.Error != nil {
|
||||
slog.Info("error during updating", "error", result.Error.Error())
|
||||
_, err := repository.db.NewUpdate().Model(&model).
|
||||
Set("updated_at = ? ", time.Now).
|
||||
Where("id = ?", model.ID).
|
||||
Exec(context.Background())
|
||||
if err != nil {
|
||||
slog.Info("error during updating", "error", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"kontor-api-echo/internal/models"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"github.com/labstack/echo/v5"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
type MailRepository struct {
|
||||
db *bun.DB
|
||||
}
|
||||
|
||||
func NewMailRepository(db *bun.DB) *MailRepository {
|
||||
repository := &MailRepository{db: db}
|
||||
return repository
|
||||
}
|
||||
|
||||
func (repository *MailRepository) FindAll(context context.Context) ([]models.Mail, error) {
|
||||
var models []models.Mail
|
||||
|
||||
err := repository.db.NewSelect().Model(&models).Scan(context)
|
||||
if err != nil {
|
||||
slog.Info(err.Error())
|
||||
return nil, echo.ErrInternalServerError
|
||||
}
|
||||
slog.Info("MailRepository#FindAll", "count", len(models))
|
||||
|
||||
return models, nil
|
||||
}
|
||||
|
||||
func (repository *MailRepository) GetById(context context.Context, id string) (*models.Mail, error) {
|
||||
var model = models.Mail{ID: id}
|
||||
slog.Info("MailRepository#GetById", "id", id)
|
||||
err := repository.db.NewSelect().Model(&model).Where("id = ?", id).Scan(context)
|
||||
if err != nil {
|
||||
slog.Info("AssignmentRepository#GetById", "error", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
return &model, err
|
||||
}
|
||||
|
||||
func (repository *MailRepository) Import(dtos models.MailDTOList) {
|
||||
slog.Info("MailRepository#Import")
|
||||
for index, dto := range dtos {
|
||||
slog.Info("importing", "index", index, "profile", dto)
|
||||
model := dto.ConvertDTOToModel()
|
||||
existing_item := models.Mail{ID: dto.ID}
|
||||
err := repository.db.NewSelect().Model(&existing_item).Where("id = ?", dto.ID).Scan(context.Background())
|
||||
if err != nil {
|
||||
slog.Info("check existing id: not found - inserting")
|
||||
_, err := repository.db.NewInsert().Model(&model).Exec(context.Background())
|
||||
if err != nil {
|
||||
slog.Info("error during import", "error", err.Error())
|
||||
}
|
||||
} else {
|
||||
slog.Info("check existing id: found - updating")
|
||||
_, err := repository.db.NewUpdate().Model(&model).
|
||||
Set("updated_at = ? ", time.Now).
|
||||
Where("id = ?", model.ID).
|
||||
Exec(context.Background())
|
||||
if err != nil {
|
||||
slog.Info("error during updating", "error", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"kontor-api-echo/internal/models"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"github.com/labstack/echo/v5"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
type MailAccountRepository struct {
|
||||
db *bun.DB
|
||||
}
|
||||
|
||||
func (repository *MailAccountRepository) Import(dtos models.MailAccountDTOList) {
|
||||
slog.Info("MailAccountRepository#Import")
|
||||
for index, dto := range dtos {
|
||||
slog.Info("importing", "index", index, "mailaccount", dto)
|
||||
model := dto.ConvertDTOToModel()
|
||||
existing_item := models.MailAccount{ID: dto.ID}
|
||||
err := repository.db.NewSelect().Model(&existing_item).Where("id = ?", dto.ID).Scan(context.Background())
|
||||
if err != nil {
|
||||
slog.Info("check existing id: not found - inserting")
|
||||
_, err := repository.db.NewInsert().Model(&model).Exec(context.Background())
|
||||
if err != nil {
|
||||
slog.Info("error during import", "error", err.Error())
|
||||
}
|
||||
} else {
|
||||
slog.Info("check existing id: found - updating")
|
||||
_, err := repository.db.NewUpdate().Model(&model).
|
||||
Set("updated_at = ? ", time.Now).
|
||||
Where("id = ?", model.ID).
|
||||
Exec(context.Background())
|
||||
if err != nil {
|
||||
slog.Info("error during updating", "error", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func NewMailAccountRepository(db *bun.DB) *MailAccountRepository {
|
||||
repository := &MailAccountRepository{db: db}
|
||||
return repository
|
||||
}
|
||||
|
||||
func (repository *MailAccountRepository) FindAll(context context.Context) ([]models.MailAccount, error) {
|
||||
var models []models.MailAccount
|
||||
|
||||
err := repository.db.NewSelect().Model(&models).Scan(context)
|
||||
if err != nil {
|
||||
slog.Info(err.Error())
|
||||
return nil, echo.ErrInternalServerError
|
||||
}
|
||||
slog.Info("MailRepository#FindAll", "count", len(models))
|
||||
|
||||
return models, nil
|
||||
}
|
||||
|
||||
func (repository *MailAccountRepository) GetById(context context.Context, id string) (*models.MailAccount, error) {
|
||||
var model = models.MailAccount{ID: id}
|
||||
slog.Info("MailAccountRepository#GetById", "id", id)
|
||||
err := repository.db.NewSelect().Model(&model).Where("id = ?", id).Scan(context)
|
||||
if err != nil {
|
||||
slog.Info("AssignmentRepository#GetById", "error", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
return &model, err
|
||||
}
|
||||
@@ -5,7 +5,9 @@ import (
|
||||
"fmt"
|
||||
"kontor-api-echo/internal/models"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"github.com/labstack/echo/v5"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
@@ -19,18 +21,21 @@ func (repository *MediaActorRepository) Import(dtos models.MediaActorDTOList) {
|
||||
slog.Info("importing", "index", index, "video", dto)
|
||||
model := dto.ConvertDTOToModel()
|
||||
existing_item := models.MediaActor{ID: dto.ID}
|
||||
result_existing := repository.db.First(&existing_item)
|
||||
if result_existing.Error != nil {
|
||||
err := repository.db.NewSelect().Model(&existing_item).Where("id = ?", dto.ID).Scan(context.Background())
|
||||
if err != nil {
|
||||
slog.Info("check existing id: not found - inserting")
|
||||
result := repository.db.Create(&model)
|
||||
if result.Error != nil {
|
||||
slog.Info("error during import", "error", result.Error.Error())
|
||||
_, err := repository.db.NewInsert().Model(&model).Exec(context.Background())
|
||||
if err != nil {
|
||||
slog.Info("error during import", "error", err.Error())
|
||||
}
|
||||
} else {
|
||||
slog.Info("check existing id: found - updating")
|
||||
result := repository.db.Save(&model)
|
||||
if result.Error != nil {
|
||||
slog.Info("error during updating", "error", result.Error.Error())
|
||||
_, err := repository.db.NewUpdate().Model(&model).
|
||||
Set("updated_at = ? ", time.Now).
|
||||
Where("id = ?", model.ID).
|
||||
Exec(context.Background())
|
||||
if err != nil {
|
||||
slog.Info("error during updating", "error", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,22 +47,27 @@ func NewMediaActorRepository(db *bun.DB) *MediaActorRepository {
|
||||
}
|
||||
|
||||
func (repository *MediaActorRepository) FindAll(context context.Context) ([]models.MediaActor, error) {
|
||||
var actors []models.MediaActor
|
||||
var models []models.MediaActor
|
||||
|
||||
result := repository.db.Find(&actors)
|
||||
slog.Info("MediaActorRepository#FindAll", "count", result.RowsAffected)
|
||||
err := repository.db.NewSelect().Model(&models).Scan(context)
|
||||
if err != nil {
|
||||
slog.Info(err.Error())
|
||||
return nil, echo.ErrInternalServerError
|
||||
}
|
||||
slog.Info("MailRepository#FindAll", "count", len(models))
|
||||
|
||||
return actors, nil
|
||||
return models, nil
|
||||
}
|
||||
|
||||
func (repository *MediaActorRepository) GetById(context context.Context, id string) (*models.MediaActor, error) {
|
||||
var actor = models.MediaActor{ID: id}
|
||||
var model = models.MediaActor{ID: id}
|
||||
slog.Info("MediaActorRepository#GetById", "id", id)
|
||||
result := repository.db.First(&actor)
|
||||
if result.Error != nil {
|
||||
slog.Info("SportRepository#GetById", "error", result.Error.Error())
|
||||
err := repository.db.NewSelect().Model(&model).Where("id = ?", id).Scan(context)
|
||||
if err != nil {
|
||||
slog.Info("AssignmentRepository#GetById", "error", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
return &actor, result.Error
|
||||
return &model, err
|
||||
}
|
||||
|
||||
func (repository *MediaActorRepository) Add(context context.Context, url string) (*models.MediaActor, error) {
|
||||
|
||||
@@ -5,7 +5,9 @@ import (
|
||||
"fmt"
|
||||
"kontor-api-echo/internal/models"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"github.com/labstack/echo/v5"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
@@ -19,18 +21,21 @@ func (repository *MediaActorFileRepository) Import(dtos models.MediaActorFileDTO
|
||||
slog.Info("importing", "index", index, "video", dto)
|
||||
model := dto.ConvertDTOToModel()
|
||||
existing_item := models.MediaActorFile{ID: dto.ID}
|
||||
result_existing := repository.db.First(&existing_item)
|
||||
if result_existing.Error != nil {
|
||||
err := repository.db.NewSelect().Model(&existing_item).Where("id = ?", dto.ID).Scan(context.Background())
|
||||
if err != nil {
|
||||
slog.Info("check existing id: not found - inserting")
|
||||
result := repository.db.Create(&model)
|
||||
if result.Error != nil {
|
||||
slog.Info("error during import", "error", result.Error.Error())
|
||||
_, err := repository.db.NewInsert().Model(&model).Exec(context.Background())
|
||||
if err != nil {
|
||||
slog.Info("error during import", "error", err.Error())
|
||||
}
|
||||
} else {
|
||||
slog.Info("check existing id: found - updating")
|
||||
result := repository.db.Save(&model)
|
||||
if result.Error != nil {
|
||||
slog.Info("error during updating", "error", result.Error.Error())
|
||||
_, err := repository.db.NewUpdate().Model(&model).
|
||||
Set("updated_at = ? ", time.Now).
|
||||
Where("id = ?", model.ID).
|
||||
Exec(context.Background())
|
||||
if err != nil {
|
||||
slog.Info("error during updating", "error", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,23 +47,27 @@ func NewMediaActorFileRepository(db *bun.DB) *MediaActorFileRepository {
|
||||
}
|
||||
|
||||
func (repository *MediaActorFileRepository) FindAll(context context.Context) ([]models.MediaActorFile, error) {
|
||||
var actor_files []models.MediaActorFile
|
||||
var models []models.MediaActorFile
|
||||
|
||||
result := repository.db.Find(&actor_files)
|
||||
slog.Info("MediaActorFileRepository#FindAll", "count", result.RowsAffected)
|
||||
err := repository.db.NewSelect().Model(&models).Scan(context)
|
||||
if err != nil {
|
||||
slog.Info(err.Error())
|
||||
return nil, echo.ErrInternalServerError
|
||||
}
|
||||
slog.Info("MailRepository#FindAll", "count", len(models))
|
||||
|
||||
return actor_files, nil
|
||||
return models, nil
|
||||
}
|
||||
|
||||
func (repository *MediaActorFileRepository) GetById(context context.Context, id string) (*models.MediaActorFile, error) {
|
||||
var actorfile = models.MediaActorFile{ID: id}
|
||||
var model = models.MediaActorFile{ID: id}
|
||||
slog.Info("MediaActorFileRepository#GetById", "id", id)
|
||||
result := repository.db.First(&actorfile)
|
||||
if result.Error != nil {
|
||||
slog.Info("MediaActorFileRepository#GetById", "error", result.Error.Error())
|
||||
return nil, result.Error
|
||||
err := repository.db.NewSelect().Model(&model).Where("id = ?", id).Scan(context)
|
||||
if err != nil {
|
||||
slog.Info("AssignmentRepository#GetById", "error", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
return &actorfile, result.Error
|
||||
return &model, err
|
||||
}
|
||||
|
||||
func (repository *MediaActorFileRepository) Add(context context.Context, media_actor_id, media_file_id string) (*models.MediaActorFile, error) {
|
||||
|
||||
@@ -5,7 +5,9 @@ import (
|
||||
"fmt"
|
||||
"kontor-api-echo/internal/models"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"github.com/labstack/echo/v5"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
@@ -19,18 +21,21 @@ func (repository *MediaFileRepository) Import(dtos models.MediaFileDTOList) {
|
||||
slog.Info("importing", "index", index, "video", dto)
|
||||
model := dto.ConvertDTOToModel()
|
||||
existing_item := models.MediaFile{ID: dto.ID}
|
||||
result_existing := repository.db.First(&existing_item)
|
||||
if result_existing.Error != nil {
|
||||
err := repository.db.NewSelect().Model(&existing_item).Where("id = ?", dto.ID).Scan(context.Background())
|
||||
if err != nil {
|
||||
slog.Info("check existing id: not found - inserting")
|
||||
result := repository.db.Create(&model)
|
||||
if result.Error != nil {
|
||||
slog.Info("error during import", "error", result.Error.Error())
|
||||
_, err := repository.db.NewInsert().Model(&model).Exec(context.Background())
|
||||
if err != nil {
|
||||
slog.Info("error during import", "error", err.Error())
|
||||
}
|
||||
} else {
|
||||
slog.Info("check existing id: found - updating")
|
||||
result := repository.db.Save(&model)
|
||||
if result.Error != nil {
|
||||
slog.Info("error during updating", "error", result.Error.Error())
|
||||
_, err := repository.db.NewUpdate().Model(&model).
|
||||
Set("updated_at = ? ", time.Now).
|
||||
Where("id = ?", model.ID).
|
||||
Exec(context.Background())
|
||||
if err != nil {
|
||||
slog.Info("error during updating", "error", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,23 +47,27 @@ func NewMediaFileRepository(db *bun.DB) *MediaFileRepository {
|
||||
}
|
||||
|
||||
func (repository *MediaFileRepository) FindAll(context context.Context) ([]models.MediaFile, error) {
|
||||
var files []models.MediaFile
|
||||
var models []models.MediaFile
|
||||
|
||||
result := repository.db.Find(&files)
|
||||
slog.Info("MediaFileRepository#FindAll", "count", result.RowsAffected)
|
||||
err := repository.db.NewSelect().Model(&models).Scan(context)
|
||||
if err != nil {
|
||||
slog.Info(err.Error())
|
||||
return nil, echo.ErrInternalServerError
|
||||
}
|
||||
slog.Info("MailRepository#FindAll", "count", len(models))
|
||||
|
||||
return files, nil
|
||||
return models, nil
|
||||
}
|
||||
|
||||
func (repository *MediaFileRepository) GetById(context context.Context, id string) (*models.MediaFile, error) {
|
||||
var file = models.MediaFile{ID: id}
|
||||
var model = models.MediaFile{ID: id}
|
||||
slog.Info("MediaFileRepository#GetById", "id", id)
|
||||
result := repository.db.First(&file)
|
||||
if result.Error != nil {
|
||||
slog.Info("MediaFileRepository#GetById", "error", result.Error.Error())
|
||||
return nil, result.Error
|
||||
err := repository.db.NewSelect().Model(&model).Where("id = ?", id).Scan(context)
|
||||
if err != nil {
|
||||
slog.Info("AssignmentRepository#GetById", "error", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
return &file, result.Error
|
||||
return &model, err
|
||||
}
|
||||
|
||||
func (repository *MediaFileRepository) Add(context context.Context, url string) (*models.MediaFile, error) {
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"kontor-api-echo/internal/helpers"
|
||||
"kontor-api-echo/internal/models"
|
||||
"log/slog"
|
||||
@@ -25,18 +24,21 @@ func (repository *MediaLoFiRepository) Import(dtos models.MediaLoFiDTOList) {
|
||||
slog.Info("importing", "index", index, "video", dto)
|
||||
model := dto.ConvertDTOToModel()
|
||||
existing_item := models.MediaLoFi{ID: dto.ID}
|
||||
result_existing := repository.db.First(&existing_item)
|
||||
if result_existing.Error != nil {
|
||||
err := repository.db.NewSelect().Model(&existing_item).Where("id = ?", dto.ID).Scan(context.Background())
|
||||
if err != nil {
|
||||
slog.Info("check existing id: not found - inserting")
|
||||
result := repository.db.Create(&model)
|
||||
if result.Error != nil {
|
||||
slog.Info("error during import", "error", result.Error.Error())
|
||||
_, err := repository.db.NewInsert().Model(&model).Exec(context.Background())
|
||||
if err != nil {
|
||||
slog.Info("error during import", "error", err.Error())
|
||||
}
|
||||
} else {
|
||||
slog.Info("check existing id: found - updating")
|
||||
result := repository.db.Save(&model)
|
||||
if result.Error != nil {
|
||||
slog.Info("error during updating", "error", result.Error.Error())
|
||||
_, err := repository.db.NewUpdate().Model(&model).
|
||||
Set("updated_at = ? ", time.Now).
|
||||
Where("id = ?", model.ID).
|
||||
Exec(context.Background())
|
||||
if err != nil {
|
||||
slog.Info("error during updating", "error", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -48,41 +50,37 @@ func NewMediaLoFiRepository(db *bun.DB) *MediaLoFiRepository {
|
||||
}
|
||||
|
||||
func (repository *MediaLoFiRepository) FindAll(context context.Context) ([]models.MediaLoFi, error) {
|
||||
var lofis []models.MediaLoFi
|
||||
var models []models.MediaLoFi
|
||||
|
||||
err := repository.db.NewSelect().Model(&lofis).Scan(context)
|
||||
err := repository.db.NewSelect().Model(&models).Scan(context)
|
||||
if err != nil {
|
||||
slog.Info(err.Error())
|
||||
return nil, echo.ErrInternalServerError
|
||||
}
|
||||
slog.Info("MediaLoFiRepository#FindAll", "count", len(lofis))
|
||||
slog.Info("MailRepository#FindAll", "count", len(models))
|
||||
|
||||
return lofis, nil
|
||||
return models, nil
|
||||
}
|
||||
|
||||
func (repository *MediaLoFiRepository) GetById(context context.Context, id string) (*models.MediaLoFi, error) {
|
||||
var lofi = models.MediaLoFi{ID: id}
|
||||
var model = models.MediaLoFi{ID: id}
|
||||
slog.Info("MediaLoFiRepository#GetById", "id", id)
|
||||
err := repository.db.NewSelect().Model(&lofi).Where("id = ?", id).Scan(context)
|
||||
err := repository.db.NewSelect().Model(&model).Where("id = ?", id).Scan(context)
|
||||
if err != nil {
|
||||
slog.Info("MediaLoFiRepository#GetById", "error", err.Error())
|
||||
slog.Info("AssignmentRepository#GetById", "error", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
return &lofi, err
|
||||
return &model, err
|
||||
}
|
||||
|
||||
func (repository *MediaLoFiRepository) Add(context context.Context, url string) (*models.MediaLoFi, error) {
|
||||
slog.Info("MediaLoFiRepository#Add", "url", url)
|
||||
webLink := helpers.StripUrl(url, "v")
|
||||
var lofi models.MediaLoFi
|
||||
search_result := repository.db.Where("url = ?", webLink).First(&lofi)
|
||||
if search_result.RowsAffected > 0 {
|
||||
slog.Info("search for existing url", "result", search_result, "lofi", lofi)
|
||||
return &lofi, nil
|
||||
}
|
||||
if errors.Is(search_result.Error, sql.ErrNoRows) {
|
||||
var model models.MediaLoFi
|
||||
err := repository.db.NewSelect().Model(&model).Where("url = ?", url).Scan(context)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
slog.Info("MediaLoFiRepository#Add URL not found", "url", webLink)
|
||||
lofi = models.MediaLoFi{
|
||||
lofi := models.MediaLoFi{
|
||||
ID: uuid.NewString(),
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
@@ -94,32 +92,32 @@ func (repository *MediaLoFiRepository) Add(context context.Context, url string)
|
||||
Title: "",
|
||||
FileName: "",
|
||||
}
|
||||
add_result := repository.db.Create(&lofi)
|
||||
if add_result.Error != nil {
|
||||
slog.Info("add new MediaLofi", "error", add_result.Error)
|
||||
return nil, add_result.Error
|
||||
_, add_error := repository.db.NewInsert().Model(&model).Exec(context)
|
||||
if add_error != nil {
|
||||
slog.Info("add new MediaLofi", "error", add_error)
|
||||
return nil, add_error
|
||||
}
|
||||
slog.Info("add new MediaLofi", "lofi", lofi)
|
||||
return &lofi, nil
|
||||
} else {
|
||||
slog.Info("search for existing url", "lofi", model)
|
||||
return &model, nil
|
||||
}
|
||||
if search_result.Error != nil {
|
||||
return nil, search_result.Error
|
||||
}
|
||||
return nil, fmt.Errorf("MediaLoFiRepository#Add unknown error")
|
||||
}
|
||||
|
||||
func (repository *MediaLoFiRepository) Update(context context.Context, update models.MediaLoFiDTO) (*models.MediaLoFi, error) {
|
||||
slog.Info("MediaLoFiRepository#Update", "lofi", update)
|
||||
var lofi = models.MediaLoFi{ID: update.ID}
|
||||
var model = models.MediaLoFi{ID: update.ID}
|
||||
model.Update(update)
|
||||
slog.Info("MediaLoFiRepository#Update", "id", update.ID)
|
||||
result := repository.db.First(&lofi)
|
||||
if result.Error != nil {
|
||||
slog.Info("MediaLoFiRepository#Update", "error", result.Error.Error())
|
||||
return nil, result.Error
|
||||
_, err := repository.db.NewUpdate().Model(&model).
|
||||
Set("updated_at = ? ", time.Now).
|
||||
Where("id = ?", update.ID).
|
||||
Exec(context)
|
||||
if err != nil {
|
||||
slog.Info("MediaLoFiRepository#Update", "error", err.Error())
|
||||
}
|
||||
lofi.Update(update)
|
||||
repository.db.Save(&lofi)
|
||||
return &lofi, nil
|
||||
return &model, nil
|
||||
}
|
||||
|
||||
func (repository *MediaLoFiRepository) Delete(context context.Context, id string) error {
|
||||
|
||||
@@ -4,13 +4,13 @@ import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"kontor-api-echo/internal/helpers"
|
||||
"kontor-api-echo/internal/models"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/labstack/echo/v5"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
@@ -24,18 +24,21 @@ func (repository *MediaMusicRepository) Import(dtos models.MediaMusicDTOList) {
|
||||
slog.Info("importing", "index", index, "video", dto)
|
||||
model := dto.ConvertDTOToModel()
|
||||
existing_item := models.MediaMusic{ID: dto.ID}
|
||||
result_existing := repository.db.First(&existing_item)
|
||||
if result_existing.Error != nil {
|
||||
err := repository.db.NewSelect().Model(&existing_item).Where("id = ?", dto.ID).Scan(context.Background())
|
||||
if err != nil {
|
||||
slog.Info("check existing id: not found - inserting")
|
||||
result := repository.db.Create(&model)
|
||||
if result.Error != nil {
|
||||
slog.Info("error during import", "error", result.Error.Error())
|
||||
_, err := repository.db.NewInsert().Model(&model).Exec(context.Background())
|
||||
if err != nil {
|
||||
slog.Info("error during import", "error", err.Error())
|
||||
}
|
||||
} else {
|
||||
slog.Info("check existing id: found - updating")
|
||||
result := repository.db.Save(&model)
|
||||
if result.Error != nil {
|
||||
slog.Info("error during updating", "error", result.Error.Error())
|
||||
_, err := repository.db.NewUpdate().Model(&model).
|
||||
Set("updated_at = ? ", time.Now).
|
||||
Where("id = ?", model.ID).
|
||||
Exec(context.Background())
|
||||
if err != nil {
|
||||
slog.Info("error during updating", "error", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,36 +50,37 @@ func NewMediaMusicRepository(db *bun.DB) *MediaMusicRepository {
|
||||
}
|
||||
|
||||
func (repository *MediaMusicRepository) FindAll(context context.Context) ([]models.MediaMusic, error) {
|
||||
var musics []models.MediaMusic
|
||||
var models []models.MediaMusic
|
||||
|
||||
result := repository.db.Find(&musics)
|
||||
slog.Info("MediaMusicRepository#FindAll", "count", result.RowsAffected)
|
||||
err := repository.db.NewSelect().Model(&models).Scan(context)
|
||||
if err != nil {
|
||||
slog.Info(err.Error())
|
||||
return nil, echo.ErrInternalServerError
|
||||
}
|
||||
slog.Info("MailRepository#FindAll", "count", len(models))
|
||||
|
||||
return musics, nil
|
||||
return models, nil
|
||||
}
|
||||
|
||||
func (repository *MediaMusicRepository) GetById(context context.Context, id string) (*models.MediaMusic, error) {
|
||||
var music = models.MediaMusic{ID: id}
|
||||
var model = models.MediaMusic{ID: id}
|
||||
slog.Info("MediaMusicRepository#GetById", "id", id)
|
||||
result := repository.db.First(&music)
|
||||
if result.Error != nil {
|
||||
slog.Info("MediaMusicRepository#GetById", "error", result.Error.Error())
|
||||
err := repository.db.NewSelect().Model(&model).Where("id = ?", id).Scan(context)
|
||||
if err != nil {
|
||||
slog.Info("AssignmentRepository#GetById", "error", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
return &music, result.Error
|
||||
return &model, err
|
||||
}
|
||||
|
||||
func (repository *MediaMusicRepository) Add(context context.Context, url string) (*models.MediaMusic, error) {
|
||||
slog.Info("MediaMusicRepository#Add", "url", url)
|
||||
webLink := helpers.StripUrl(url, "v")
|
||||
var music models.MediaMusic
|
||||
search_result := repository.db.Where("url = ?", webLink).First(&music)
|
||||
if search_result.RowsAffected > 0 {
|
||||
slog.Info("search for existing url", "result", search_result, "music", music)
|
||||
return &music, nil
|
||||
}
|
||||
if errors.Is(search_result.Error, sql.ErrNoRows) {
|
||||
var model models.MediaMusic
|
||||
err := repository.db.NewSelect().Model(&model).Where("url = ?", url).Scan(context)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
slog.Info("MediaMusicRepository#Add URL not found", "url", webLink)
|
||||
music = models.MediaMusic{
|
||||
music := models.MediaMusic{
|
||||
ID: uuid.NewString(),
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
@@ -88,32 +92,32 @@ func (repository *MediaMusicRepository) Add(context context.Context, url string)
|
||||
Title: "",
|
||||
FileName: "",
|
||||
}
|
||||
add_result := repository.db.Create(&music)
|
||||
if add_result.Error != nil {
|
||||
slog.Info("add new MediaMusic", "error", add_result.Error)
|
||||
return nil, add_result.Error
|
||||
_, add_error := repository.db.NewInsert().Model(&model).Exec(context)
|
||||
if add_error != nil {
|
||||
slog.Info("add new MediaMusic", "error", add_error)
|
||||
return nil, add_error
|
||||
}
|
||||
slog.Info("add new MediaMusic", "music", music)
|
||||
slog.Info("add new MediaMusic", "lofi", music)
|
||||
return &music, nil
|
||||
} else {
|
||||
slog.Info("search for existing url", "lofi", model)
|
||||
return &model, nil
|
||||
}
|
||||
if search_result.Error != nil {
|
||||
return nil, search_result.Error
|
||||
}
|
||||
return nil, fmt.Errorf("MediaMusicRepository#Add unknown error")
|
||||
}
|
||||
|
||||
func (repository *MediaMusicRepository) Update(context context.Context, update models.MediaMusicDTO) (*models.MediaMusic, error) {
|
||||
slog.Info("MediaMusicRepository#Update", "music", update)
|
||||
var music = models.MediaMusic{ID: update.ID}
|
||||
slog.Info("MediaMusicRepository#Update", "id", update.ID)
|
||||
result := repository.db.First(&music)
|
||||
if result.Error != nil {
|
||||
slog.Info("MediaMusicRepository#Update", "error", result.Error.Error())
|
||||
return nil, result.Error
|
||||
var model = models.MediaMusic{ID: update.ID}
|
||||
model.Update(update)
|
||||
slog.Info("MediaLoFiRepository#Update", "id", update.ID)
|
||||
_, err := repository.db.NewUpdate().Model(&model).
|
||||
Set("updated_at = ? ", time.Now).
|
||||
Where("id = ?", update.ID).
|
||||
Exec(context)
|
||||
if err != nil {
|
||||
slog.Info("MediaLoFiRepository#Update", "error", err.Error())
|
||||
}
|
||||
music.Update(update)
|
||||
repository.db.Save(&music)
|
||||
return &music, nil
|
||||
return &model, nil
|
||||
}
|
||||
|
||||
func (repository *MediaMusicRepository) Delete(context context.Context, id string) error {
|
||||
|
||||
@@ -2,10 +2,14 @@ package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"errors"
|
||||
"kontor-api-echo/internal/helpers"
|
||||
"kontor-api-echo/internal/models"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/labstack/echo/v5"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
@@ -68,42 +72,37 @@ func (repository *MediaVideoRepository) GetById(context context.Context, id stri
|
||||
return &video, nil
|
||||
}
|
||||
|
||||
// func (repository *MediaVideoRepository) Add(context context.Context, url string) (*models.MediaVideo, error) {
|
||||
// slog.Info("MediaVideoRepository#Add", "url", url)
|
||||
// webLink := helpers.StripUrl(url, "v")
|
||||
// var video models.MediaVideo
|
||||
// search_result := repository.db.Where("url = ?", webLink).First(&video)
|
||||
// if search_result.RowsAffected > 0 {
|
||||
// slog.Info("search for existing url", "result", search_result, "video", video)
|
||||
// return &video, nil
|
||||
// }
|
||||
// if errors.Is(search_result.Error, sql.ErrNoRows) {
|
||||
// slog.Info("MediaVideoRepository#Add URL not found", "url", webLink)
|
||||
// video = models.MediaVideo{
|
||||
// ID: uuid.NewString(),
|
||||
// CreatedAt: time.Now(),
|
||||
// UpdatedAt: time.Now(),
|
||||
// DeletedAt: nil,
|
||||
// Version: 0,
|
||||
// WebLink: webLink,
|
||||
// ShouldDownload: false,
|
||||
// Review: true,
|
||||
// Title: "",
|
||||
// FileName: "",
|
||||
// }
|
||||
// add_result := repository.db.Create(&video)
|
||||
// if add_result.Error != nil {
|
||||
// slog.Info("add new MediaVideo", "error", add_result.Error)
|
||||
// return nil, add_result.Error
|
||||
// }
|
||||
// slog.Info("add new MediaVideo", "music", video)
|
||||
// return &video, nil
|
||||
// }
|
||||
// if search_result.Error != nil {
|
||||
// return nil, search_result.Error
|
||||
// }
|
||||
// return nil, fmt.Errorf("MediaVideoRepository#Add unknown error")
|
||||
// }
|
||||
func (repository *MediaVideoRepository) Add(context context.Context, url string) (*models.MediaVideo, error) {
|
||||
slog.Info("MediaVideoRepository#Add", "url", url)
|
||||
webLink := helpers.StripUrl(url, "v")
|
||||
var model models.MediaVideo
|
||||
err := repository.db.NewSelect().Model(&model).Where("url = ?", url).Scan(context)
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
slog.Info("MediaMusicRepository#Add URL not found", "url", webLink)
|
||||
video := models.MediaVideo{
|
||||
ID: uuid.NewString(),
|
||||
CreatedAt: time.Now(),
|
||||
UpdatedAt: time.Now(),
|
||||
DeletedAt: nil,
|
||||
Version: 0,
|
||||
WebLink: webLink,
|
||||
ShouldDownload: false,
|
||||
Review: true,
|
||||
Title: "",
|
||||
FileName: "",
|
||||
}
|
||||
_, add_error := repository.db.NewInsert().Model(&model).Exec(context)
|
||||
if add_error != nil {
|
||||
slog.Info("add new MediaMusic", "error", add_error)
|
||||
return nil, add_error
|
||||
}
|
||||
slog.Info("add new MediaMusic", "lofi", video)
|
||||
return &video, nil
|
||||
} else {
|
||||
slog.Info("search for existing url", "lofi", model)
|
||||
return &model, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (repository *MediaVideoRepository) Update(context context.Context, update models.MediaVideoDTO) (*models.MediaVideo, error) {
|
||||
slog.Info("MediaVideoRepository#Update", "video", update)
|
||||
|
||||
@@ -31,9 +31,10 @@ func (repository *ProfileRepository) FindAll(context context.Context) ([]models.
|
||||
return profiles, nil
|
||||
}
|
||||
|
||||
func (repository *ProfileRepository) FindProfileByEmail(context context.Context, email string) (*models.Profile, error) {
|
||||
func (repository *ProfileRepository) FindProfileByEmail(email string) (*models.Profile, error) {
|
||||
var profile models.Profile
|
||||
slog.Info("MediaArticleRepository#GetById", "email", email)
|
||||
context := context.Background()
|
||||
|
||||
err := repository.db.NewSelect().Model(&profile).Where("email = ?", email).Scan(context)
|
||||
if err != nil {
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"kontor-api-echo/internal/models"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"github.com/labstack/echo/v5"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
type TokenRepository struct {
|
||||
db *bun.DB
|
||||
}
|
||||
|
||||
func (repository *TokenRepository) Import(dtos models.TokenDTOList) {
|
||||
slog.Info("TokenRepository#Import")
|
||||
for index, dto := range dtos {
|
||||
slog.Info("importing", "index", index, "video", dto)
|
||||
model := dto.ConvertDTOToModel()
|
||||
existing_item := models.Token{ID: dto.ID}
|
||||
err := repository.db.NewSelect().Model(&existing_item).Where("id = ?", dto.ID).Scan(context.Background())
|
||||
if err != nil {
|
||||
slog.Info("check existing id: not found - inserting")
|
||||
_, err := repository.db.NewInsert().Model(&model).Exec(context.Background())
|
||||
if err != nil {
|
||||
slog.Info("error during import", "error", err.Error())
|
||||
}
|
||||
} else {
|
||||
slog.Info("check existing id: found - updating")
|
||||
_, err := repository.db.NewUpdate().Model(&model).
|
||||
Set("updated_at = ? ", time.Now).
|
||||
Where("id = ?", model.ID).
|
||||
Exec(context.Background())
|
||||
if err != nil {
|
||||
slog.Info("error during updating", "error", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func NewTokenRepository(db *bun.DB) *TokenRepository {
|
||||
repository := &TokenRepository{db: db}
|
||||
return repository
|
||||
}
|
||||
|
||||
func (repository *TokenRepository) FindAll(context context.Context) ([]models.Token, error) {
|
||||
var models []models.Token
|
||||
|
||||
err := repository.db.NewSelect().Model(&models).Scan(context)
|
||||
if err != nil {
|
||||
slog.Info(err.Error())
|
||||
return nil, echo.ErrInternalServerError
|
||||
}
|
||||
slog.Info("MailRepository#FindAll", "count", len(models))
|
||||
|
||||
return models, nil
|
||||
}
|
||||
|
||||
func (repository *TokenRepository) GetById(context context.Context, id string) (*models.Token, error) {
|
||||
var model = models.Token{ID: id}
|
||||
slog.Info("TokenRepository#GetById", "id", id)
|
||||
err := repository.db.NewSelect().Model(&model).Where("id = ?", id).Scan(context)
|
||||
if err != nil {
|
||||
slog.Info("AssignmentRepository#GetById", "error", err.Error())
|
||||
return nil, err
|
||||
}
|
||||
return &model, err
|
||||
}
|
||||
@@ -1,34 +1,154 @@
|
||||
package router
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"io"
|
||||
"kontor-api-echo/assets"
|
||||
"kontor-api-echo/internal/config"
|
||||
"kontor-api-echo/internal/handlers"
|
||||
"kontor-api-echo/templates"
|
||||
"log/slog"
|
||||
"os"
|
||||
|
||||
echojwt "github.com/labstack/echo-jwt/v5"
|
||||
"github.com/labstack/echo/v5"
|
||||
"github.com/labstack/echo/v5/middleware"
|
||||
)
|
||||
|
||||
type Template struct {
|
||||
templates *template.Template
|
||||
}
|
||||
|
||||
func (t *Template) Render(c *echo.Context, w io.Writer, name string, data any) error {
|
||||
return t.templates.ExecuteTemplate(w, name, data)
|
||||
}
|
||||
|
||||
func New(admin *handlers.AdminHandler, media *handlers.MediaHandler) *echo.Echo {
|
||||
e := echo.New()
|
||||
|
||||
skipper := func(c *echo.Context) bool {
|
||||
// Skip health check endpoint
|
||||
return c.Request().URL.Path == "/health"
|
||||
}
|
||||
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
|
||||
|
||||
e.Use(middleware.Recover())
|
||||
|
||||
e.Use(middleware.RequestLoggerWithConfig(middleware.RequestLoggerConfig{
|
||||
LogStatus: true,
|
||||
LogURI: true,
|
||||
LogStatus: true,
|
||||
HandleError: true,
|
||||
Skipper: skipper,
|
||||
Skipper: func(c *echo.Context) bool {
|
||||
// Skip health check endpoint
|
||||
return c.Path() == "/health"
|
||||
},
|
||||
LogValuesFunc: func(c *echo.Context, v middleware.RequestLoggerValues) error {
|
||||
if v.Error == nil {
|
||||
slog.Info("REQUEST", "uri", v.URI, "status", v.Status)
|
||||
} else {
|
||||
slog.Info("REQUEST-ERROR", "uri", v.URI, "status", v.Status, "err", v.Error.Error())
|
||||
if v.Error != nil {
|
||||
logger.Error("request failed", "uri", v.URI, "status", v.Status, "error", v.Error)
|
||||
return nil
|
||||
}
|
||||
logger.Info("request", "uri", v.URI, "status", v.Status)
|
||||
return nil
|
||||
},
|
||||
}))
|
||||
|
||||
e.StaticFS("/public", echo.MustSubFS(assets.StaticFiles, "assets"))
|
||||
|
||||
templ := template.Must(template.New("").ParseFS(templates.TemplateFiles, "layouts/*.html", "pages/*.html"))
|
||||
|
||||
t := &Template{
|
||||
templates: templ,
|
||||
}
|
||||
|
||||
e.Renderer = t
|
||||
|
||||
e.GET("/health", handlers.Health)
|
||||
e.GET("/", handlers.Index)
|
||||
e.GET("/login", admin.AuthHandler.LoginPage)
|
||||
e.POST("/login", admin.AuthHandler.LoginPost)
|
||||
e.GET("/logout", admin.AuthHandler.LogoutPage)
|
||||
|
||||
mediaGroup := e.Group("/media")
|
||||
//mediaGroup.Use(middleware.AuthRequired())
|
||||
mediaGroup.GET("/actors", media.MediaActorHandler.ListPage)
|
||||
mediaGroup.GET("/actors/:id", media.MediaActorHandler.EditPage)
|
||||
mediaGroup.POST("/actors/:id", media.MediaActorHandler.UpdatePage)
|
||||
mediaGroup.GET("/articles", media.MediaArticleHandler.ListPage)
|
||||
mediaGroup.GET("/files", media.MediaFileHandler.ListPage)
|
||||
mediaGroup.GET("/files/edit/:id", media.MediaFileHandler.EditPage)
|
||||
mediaGroup.POST("/files/edit/:id", media.MediaFileHandler.UpdatePage)
|
||||
mediaGroup.GET("/files/delete/:id", media.MediaFileHandler.DeletePage)
|
||||
mediaGroup.GET("/videos", media.MediaVideoHandler.ListPage)
|
||||
mediaGroup.GET("/videos/edit/:id", media.MediaVideoHandler.EditPage)
|
||||
mediaGroup.POST("/videos/edit/:id", media.MediaVideoHandler.UpdatePage)
|
||||
mediaGroup.GET("/videos/delete/:id", media.MediaVideoHandler.DeletePage)
|
||||
mediaGroup.GET("/lofis", media.MediaLoFiHandler.ListPage)
|
||||
mediaGroup.GET("/lofis/edit", media.MediaLoFiHandler.EditPage)
|
||||
mediaGroup.GET("/lofis/edit/:id", media.MediaLoFiHandler.EditPage)
|
||||
mediaGroup.POST("/lofis/edit/:id", media.MediaLoFiHandler.UpdatePage)
|
||||
mediaGroup.GET("/lofis/review/:id", media.MediaLoFiHandler.ChangeReviewPage)
|
||||
mediaGroup.GET("/lofis/delete/:id", media.MediaLoFiHandler.DeletePage)
|
||||
mediaGroup.GET("/musics", media.MediaMusicHandler.ListPage)
|
||||
mediaGroup.GET("/musics/edit/:id", media.MediaMusicHandler.EditPage)
|
||||
mediaGroup.POST("/musics/edit/:id", media.MediaMusicHandler.UpdatePage)
|
||||
mediaGroup.GET("/musics/delete/:id", media.MediaMusicHandler.DeletePage)
|
||||
|
||||
api := e.Group("/api")
|
||||
api.POST("/login", admin.AuthHandler.Login)
|
||||
|
||||
v1 := api.Group("/v1")
|
||||
{
|
||||
secured := v1.Group("")
|
||||
secured.Use(echojwt.WithConfig(echojwt.Config{SigningKey: config.ServerConfig.ApiSecret}))
|
||||
//secured.Use(middleware.JWT(admin.Secret))
|
||||
// secured.GET("admin/mailaccounts", admin.MailAccountHandler.List)
|
||||
// secured.GET("user/profiles", admin.ProfileHandler.List)
|
||||
// secured.GET("user/permissions", admin.PermissionHandler.List)
|
||||
// secured.GET("user/assignments", admin.AssignmentHandler.List)
|
||||
// secured.GET("user/mails", admin.MailHandler.List)
|
||||
// secured.GET("user/tokens", admin.TokenHandler.List)
|
||||
// secured.GET("tysc/sports", tysc.SportHandler.List)
|
||||
// secured.GET("tysc/sports/:id", tysc.SportHandler.Get)
|
||||
// secured.GET("tysc/players", tysc.PlayerHandler.List)
|
||||
// secured.GET("tysc/teams", tysc.TeamHandler.List)
|
||||
// secured.GET("tysc/positions", tysc.PositionHandler.List)
|
||||
// secured.GET("tysc/roosters", tysc.RoosterHandler.List)
|
||||
// secured.GET("tysc/vendors", tysc.VendorHandler.List)
|
||||
// secured.GET("tysc/cardsets", tysc.CardSetHandler.List)
|
||||
// secured.GET("tysc/cards", tysc.CardHandler.List)
|
||||
// secured.GET("bookshelf/articles", bookshelf.ArticleHandler.List)
|
||||
// secured.GET("bookshelf/publishers", bookshelf.BookshelfPublisherHandler.List)
|
||||
// secured.GET("bookshelf/books", bookshelf.BookHandler.List)
|
||||
// secured.GET("bookshelf/authors", bookshelf.AuthorHandler.List)
|
||||
// secured.GET("bookshelf/articleauthors", bookshelf.ArticleAuthorHandler.List)
|
||||
// secured.GET("bookshelf/bookauthors", bookshelf.BookAuthorHandler.List)
|
||||
// secured.GET("comics/comics", comics.ComicHandler.List)
|
||||
// secured.GET("comics/publishers", comics.PublisherHandler.List)
|
||||
// secured.GET("comics/artists", comics.ArtistHandler.List)
|
||||
// secured.GET("comics/issues", comics.IssueHandler.List)
|
||||
// secured.GET("comics/tradepaperbacks", comics.TradePaperbackHandler.List)
|
||||
// secured.GET("comics/worktypes", comics.WorkTypeHandler.List)
|
||||
// secured.GET("comics/volumes", comics.VolumeHandler.List)
|
||||
// secured.GET("comics/storyarcs", comics.StoryArcHandler.List)
|
||||
// secured.GET("comics/comicworks", comics.ComicworkHandler.List)
|
||||
// secured.GET("comics/issueworks", comics.IssueworkHandler.List)
|
||||
mediaGroup := secured.Group("media")
|
||||
mediaGroup.GET("/files", media.MediaFileHandler.List)
|
||||
mediaGroup.POST("/files", media.MediaFileHandler.Add)
|
||||
// mediaGroup.GET("/videos", media.MediaVideoHandler.List)
|
||||
// mediaGroup.GET("/lofis", media.MediaLoFiHandler.List)
|
||||
// mediaGroup.POST("/lofis", media.MediaLoFiHandler.Add)
|
||||
// mediaGroup.GET("/lofis/:id", media.MediaLoFiHandler.Get)
|
||||
// mediaGroup.POST("/lofis/:id", media.MediaLoFiHandler.Update)
|
||||
// mediaGroup.DELETE("/lofis/:id", media.MediaLoFiHandler.Delete)
|
||||
// mediaGroup.POST("/musics", media.MediaMusicHandler.Add)
|
||||
// mediaGroup.GET("/musics/:id", media.MediaMusicHandler.Get)
|
||||
// mediaGroup.POST("/musics/:id", media.MediaMusicHandler.Update)
|
||||
// mediaGroup.DELETE("/musics/:id", media.MediaMusicHandler.Delete)
|
||||
// mediaGroup.GET("/actors", media.MediaActorHandler.List)
|
||||
// mediaGroup.POST("/actors", media.MediaActorHandler.Add)
|
||||
// mediaGroup.GET("/actors/:id", media.MediaActorHandler.Get)
|
||||
// mediaGroup.DELETE("/actors/:id", media.MediaActorHandler.Delete)
|
||||
// mediaGroup.GET("/actorfiles", media.MediaActorFileHandler.List)
|
||||
// mediaGroup.POST("/actorfiles", media.MediaActorFileHandler.Add)
|
||||
// mediaGroup.DELETE("/actorfiles", media.MediaActorFileHandler.Delete)
|
||||
}
|
||||
|
||||
return e
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ func (service *AssignmentService) List(context context.Context) ([]models.Assign
|
||||
return service.repository.FindAll(context)
|
||||
}
|
||||
|
||||
func (service *AssignmentService) Get(context context.Context, id string) (models.Assignment, error) {
|
||||
func (service *AssignmentService) Get(context context.Context, id string) (*models.Assignment, error) {
|
||||
slog.Info("AssignmentService#Get")
|
||||
return service.repository.GetById(context, id)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"kontor-api-echo/internal/helpers"
|
||||
"kontor-api-echo/internal/repository"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
type AuthService struct {
|
||||
repository *repository.ProfileRepository
|
||||
}
|
||||
|
||||
func NewAuthService(repository *repository.ProfileRepository) *AuthService {
|
||||
service := &AuthService{repository: repository}
|
||||
return service
|
||||
}
|
||||
|
||||
func VerifyPassword(password, hashedPassword string) error {
|
||||
return bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password))
|
||||
}
|
||||
|
||||
func (service *AuthService) LoginCheck(email string, password string) (string, error) {
|
||||
|
||||
var err error
|
||||
|
||||
profile, err := service.repository.FindProfileByEmail(email)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
err = VerifyPassword(password, profile.Password)
|
||||
|
||||
if err != nil && err == bcrypt.ErrMismatchedHashAndPassword {
|
||||
return "", err
|
||||
}
|
||||
|
||||
token, err := helpers.GenerateToken(profile.ID)
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return token, nil
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"kontor-api-echo/internal/models"
|
||||
"kontor-api-echo/internal/repository"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
type MailService struct {
|
||||
repository *repository.MailRepository
|
||||
}
|
||||
|
||||
func NewMailService(repo *repository.MailRepository) *MailService {
|
||||
service := &MailService{repository: repo}
|
||||
return service
|
||||
}
|
||||
|
||||
func (service *MailService) List(context context.Context) ([]models.Mail, error) {
|
||||
slog.Info("MailService#List")
|
||||
return service.repository.FindAll(context)
|
||||
}
|
||||
|
||||
func (service *MailService) Get(context context.Context, id string) (*models.Mail, error) {
|
||||
slog.Info("MailService#Get")
|
||||
return service.repository.GetById(context, id)
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"kontor-api-echo/internal/models"
|
||||
"kontor-api-echo/internal/repository"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
type MailAccountService struct {
|
||||
repository *repository.MailAccountRepository
|
||||
}
|
||||
|
||||
func NewMailAccountService(repo *repository.MailAccountRepository) *MailAccountService {
|
||||
service := &MailAccountService{repository: repo}
|
||||
return service
|
||||
}
|
||||
|
||||
func (service *MailAccountService) List(context context.Context) ([]models.MailAccount, error) {
|
||||
slog.Info("MailAccountService#List")
|
||||
return service.repository.FindAll(context)
|
||||
}
|
||||
|
||||
func (service *MailAccountService) Get(context context.Context, id string) (*models.MailAccount, error) {
|
||||
slog.Info("MailAccountService#Get")
|
||||
return service.repository.GetById(context, id)
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"kontor-api-echo/internal/models"
|
||||
"kontor-api-echo/internal/repository"
|
||||
"log/slog"
|
||||
)
|
||||
|
||||
type TokenService struct {
|
||||
repository *repository.TokenRepository
|
||||
}
|
||||
|
||||
func NewTokenService(repo *repository.TokenRepository) *TokenService {
|
||||
service := &TokenService{repository: repo}
|
||||
return service
|
||||
}
|
||||
|
||||
func (service *TokenService) List(context context.Context) ([]models.Token, error) {
|
||||
slog.Info("TokenService#List")
|
||||
return service.repository.FindAll(context)
|
||||
}
|
||||
|
||||
func (service *TokenService) Get(context context.Context, id string) (*models.Token, error) {
|
||||
slog.Info("TokenService#Get")
|
||||
return service.repository.GetById(context, id)
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
type Status struct {
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
func GetHealth(c echo.Context) error {
|
||||
status := new(Status)
|
||||
status.Status = "ok"
|
||||
return c.JSON(http.StatusOK, status)
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"kontor-api-echo/pkg/schema"
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
func SetupMediaRoutes(api *echo.Group) {
|
||||
media := api.Group("/media")
|
||||
media.GET("/files", GetAllFiles)
|
||||
media.POST("/files", AddFile)
|
||||
}
|
||||
|
||||
func GetAllFiles(c echo.Context) error {
|
||||
var files []schema.MediaFile
|
||||
var err error
|
||||
var db *bun.DB
|
||||
ctx := context.Background()
|
||||
|
||||
db, err = schema.GetDatabase()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = db.NewSelect().Model(&files).Relation("MediaActorFiles").Scan(ctx)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
return echo.ErrInternalServerError
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, files)
|
||||
}
|
||||
|
||||
type Link struct {
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
func AddFile(c echo.Context) error {
|
||||
var err error
|
||||
var db *bun.DB
|
||||
ctx := context.Background()
|
||||
link := new(Link)
|
||||
if err = c.Bind(link); err != nil {
|
||||
return err
|
||||
}
|
||||
log.Printf("URL %s has been sent", link)
|
||||
|
||||
db, err = schema.GetDatabase()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
id := uuid.NewString()
|
||||
timestamp := time.Now()
|
||||
mediafile := &schema.MediaFile{ID: id, CreatedAt: timestamp, UpdatedAt: timestamp, WebLink: fmt.Sprintf("%s", link), Version: 1, ShouldDownload: true, Review: true}
|
||||
_, err = db.NewInsert().Model(mediafile).Exec(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.String(http.StatusCreated, "Link created")
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
{{ define "footer" }}
|
||||
<footer class="mt-auto py-3 bg-light fixed-bottom mt-auto">
|
||||
<div class="container text-center">
|
||||
<span class="text-muted">{{ .version }}</span>
|
||||
</div>
|
||||
</footer>
|
||||
<!-- Bootstrap JS einbinden -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
{{ end }}
|
||||
@@ -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 }}
|
||||
@@ -0,0 +1,24 @@
|
||||
{{ define "main" }}
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link
|
||||
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css"
|
||||
rel="stylesheet"
|
||||
integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl"
|
||||
crossorigin="anonymous"
|
||||
/>
|
||||
<link rel="stylesheet" href="/public/style/main.css" />
|
||||
<title>{{ .title }}</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="header"></div>
|
||||
{{ template "navbar" . }}
|
||||
{{ template "content" . }}
|
||||
<div class="footer">{{ .version }}</div>
|
||||
</body>
|
||||
</html>
|
||||
{{ end }}
|
||||
@@ -0,0 +1,88 @@
|
||||
{{ define "navbar" }}
|
||||
<!-- 1. Kopfzeile & Navigation -->
|
||||
<header>
|
||||
<nav class="navbar navbar-expand-lg navbar-dark fixed-top" style="background-color:darkgrey;">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand" href="#">Kontor</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarComicsMenuLink" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Comics</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarComicsMenuLink">
|
||||
<a class="dropdown-item" href="/comics/comics">Comics</a>
|
||||
<a class="dropdown-item" href="/comics/publishers">Publisher</a>
|
||||
<a class="dropdown-item" href="/comics/artists">Artist</a>
|
||||
<a class="dropdown-item" href="/comics/issues">Issue</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarWebMenuLink" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Media</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarWebMenuLink">
|
||||
<a class="dropdown-item" href="{{.media_file_link}}">Media Files</a>
|
||||
<a class="dropdown-item" href="{{.media_actor_link}}">Media Actors</a>
|
||||
<a class="dropdown-item" href="{{.media_lofi_link}}">Media Lofi</a>
|
||||
<a class="dropdown-item" href="{{.media_music_link}}">Media Music</a>
|
||||
<a class="dropdown-item" href="{{.media_video_link}}">Media Videos</a>
|
||||
<a class="dropdown-item" href="{{.media_article_link}}">Artikel</a>
|
||||
</div>
|
||||
</li>
|
||||
{{ if .user }}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/logout">Logout</a>
|
||||
</li>
|
||||
{{ else }}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/login">Login</a>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
|
||||
|
||||
<!-- <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="/">Kontor</a>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarComicsMenuLink" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Comics</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarComicsMenuLink">
|
||||
<a class="dropdown-item" href="/comics/comics">Comics</a>
|
||||
<a class="dropdown-item" href="/comics/publishers">Publisher</a>
|
||||
<a class="dropdown-item" href="/comics/artists">Artist</a>
|
||||
<a class="dropdown-item" href="/comics/issues">Issue</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarWebMenuLink" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Media</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarWebMenuLink">
|
||||
<a class="dropdown-item" href="/web/media-files">Media Files</a>
|
||||
<a class="dropdown-item" href="/web/actors">Media Actors</a>
|
||||
<a class="dropdown-item" href="/web/media-lofis">Lofi</a>
|
||||
<a class="dropdown-item" href="/web/articles">Artikel</a>
|
||||
</div>
|
||||
</li>
|
||||
{{ if .user }}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/logout">Logout</a>
|
||||
</li>
|
||||
{{ else }}
|
||||
<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> -->
|
||||
{{ end }}
|
||||
@@ -0,0 +1,59 @@
|
||||
{{ define "comics" }}
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
{{ template "head" . }}
|
||||
|
||||
<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
|
||||
</label>
|
||||
<label>
|
||||
<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>
|
||||
</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 }}
|
||||
<tr>
|
||||
<th scope="row"><a href="/comic/comics/{{.ID}}">{{.Title}}</a></th>
|
||||
{{ if .Publisher }}
|
||||
<td><a href="/comic/publishers/{{.Publisher.ID}}">{{.Publisher.Name}}</a></td>
|
||||
{{ else }}
|
||||
<td>Publisher not set</td>
|
||||
{{ end }}
|
||||
<td>
|
||||
{{ if .Completed }}
|
||||
<img src="/public/icons/tick.png" alt="true" width="24" height="24">
|
||||
{{ else }}
|
||||
<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>
|
||||
<td><a href="/comic/comics/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 }}
|
||||
@@ -0,0 +1,27 @@
|
||||
{{ define "home" }}
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
{{ template "head" . }}
|
||||
|
||||
<body class="d-flex flex-column h-100">
|
||||
{{ template "navbar" . }}
|
||||
<main class="flex-shrink-0">
|
||||
<div class="container my-4">
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<h1>Hauptinhalt</h1>
|
||||
<p>{{ .message }}</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<aside class="bg-light p-3">
|
||||
<h3>Seitenbereich</h3>
|
||||
<p>Optionale Sidebar oder Zusatzinformationen.</p>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
{{ template "footer" . }}
|
||||
</body>
|
||||
</html>
|
||||
{{ end }}
|
||||
@@ -0,0 +1,69 @@
|
||||
{{ define "lofi" }}
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
{{ template "head" . }}
|
||||
|
||||
<body>
|
||||
{{ template "navbar" . }}
|
||||
<main>
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<h1>Media Lofi</h1>
|
||||
<p>Hier steht der wesentliche Inhalt der Seite.</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<aside class="bg-light p-3">
|
||||
<h3>Seitenbereich</h3>
|
||||
<p>Optionale Sidebar oder Zusatzinformationen.</p>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<form class="form-inline" action="/web/media-lofis">
|
||||
<input type="text" placeholder="Search" name="query">
|
||||
<label>
|
||||
<input type="checkbox" name="review" {{if .isReview}}checked{{end}}>Review
|
||||
</label>
|
||||
<label>
|
||||
<input type="checkbox" name="should_download" {{if .isDownload}}checked{{end}}>Download
|
||||
</label>
|
||||
<button type="submit">Search</button>
|
||||
<div class="pill-nav"><a href="/web/media-lofis/add">Add Lofi</a></div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="row">
|
||||
<table class="table table-hover">
|
||||
<thead><tr>
|
||||
<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="/web/media-lofis/{{.ID}}/edit">{{.Title}}</a></th>
|
||||
{{ if .WebLink }}
|
||||
<td><a href="{{.WebLink}}">{{.WebLink}}</a></td>
|
||||
{{ else }}
|
||||
<td>WebLink not set</td>
|
||||
{{ end }}
|
||||
<td>
|
||||
{{ if .Review }}
|
||||
<a href="/web/media-lofis/{{.ID}}/change-review"><img src="/public/icons/tick.png" alt="true" width="24" height="24"></a>
|
||||
{{ else }}
|
||||
<a href="/web/media-lofis/{{.ID}}/change-review"><img src="/public/icons/cross.png" alt="true" width="24" height="24"></a>
|
||||
{{ end }}
|
||||
</td>
|
||||
<td><a href="/web/media-lofis/{{.ID}}/edit" class="btn btn-outline-primary btn-sm active" role="button" aria-pressed="true">Edit</a></td>
|
||||
<td><a href="/web/media-lofis/{{.ID}}/delete" class="btn btn-outline-danger btn-sm active" role="button" aria-pressed="true">Delete</a></td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</main>
|
||||
{{ template "footer" . }}
|
||||
</body>
|
||||
</html>
|
||||
{{ end }}
|
||||
@@ -0,0 +1,54 @@
|
||||
{{ define "lofi_detail" }}
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
{{ template "head" . }}
|
||||
|
||||
<body>
|
||||
{{ template "navbar" . }}
|
||||
<main>
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<h1>Media Lofi</h1>
|
||||
<p>Hier steht der wesentliche Inhalt der Seite.</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<aside class="bg-light p-3">
|
||||
<h3>Seitenbereich</h3>
|
||||
<p>Optionale Sidebar oder Zusatzinformationen.</p>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
{{ if .Errors }}
|
||||
<div class="notification is-danger">{{ .Errors }}</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<form action="/web/media-lofis/{{.lofi.ID}}/edit" method="POST">
|
||||
<div class="form-group row">
|
||||
<label for="inputWeblink" class="col-sm-2 -col-form-label">URL</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputWeblink" name="weblink" value="{{.lofi.WebLink}}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="inputTitle" class="col-sm-2 -col-form-label">Title</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputTitle" name="title" value="{{.lofi.Title}}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-10">
|
||||
<button class="btn btn-primary" type="submit">Update</button>
|
||||
<button class="btn" type="button" onclick="/web/media-lofis">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
{{ template "footer" . }}
|
||||
</body>
|
||||
</html>
|
||||
{{ end }}
|
||||
@@ -0,0 +1,36 @@
|
||||
{{ define "login" }}
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
{{ template "head" . }}
|
||||
|
||||
<body>
|
||||
{{ template "navbar" . }}
|
||||
<div class="content">
|
||||
<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">{{ .message }}</div>
|
||||
{{ end}}
|
||||
|
||||
<div class="field">
|
||||
<label class="label">Username</label>
|
||||
<div class="control">
|
||||
<input class="input" type="text" placeholder="Enter Username" name="username" required/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label">Passwort</label>
|
||||
<div class="control">
|
||||
<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 }}
|
||||
@@ -0,0 +1,54 @@
|
||||
{{ define "actor_detail" }}
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
{{ template "head" . }}
|
||||
|
||||
<body>
|
||||
{{ template "navbar" . }}
|
||||
<main>
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<h1>Media Actor</h1>
|
||||
<p>Hier steht der wesentliche Inhalt der Seite.</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<aside class="bg-light p-3">
|
||||
<h3>Seitenbereich</h3>
|
||||
<p>Optionale Sidebar oder Zusatzinformationen.</p>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
{{ if .Errors }}
|
||||
<div class="notification is-danger">{{ .Errors }}</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<form action="/web/actors/{{.actor.ID}}/edit" method="POST">
|
||||
<div class="form-group row">
|
||||
<label for="inputName" class="col-sm-2 -col-form-label">Name</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputName" name="name" value="{{.actor.Name}}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="inputWeblink" class="col-sm-2 -col-form-label">Link</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputWeblink" name="weblink" value="{{.actor.WebLink}}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-10">
|
||||
<button class="btn btn-primary" type="submit">Update</button>
|
||||
<button class="btn" type="button" onclick="/web/actors">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
{{ template "footer" . }}
|
||||
</body>
|
||||
</html>
|
||||
{{ end }}
|
||||
@@ -0,0 +1,41 @@
|
||||
{{ define "media_actors" }}
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
{{ template "head" . }}
|
||||
|
||||
<body>
|
||||
{{ template "navbar" . }}
|
||||
<main>
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<h1>Media Actors</h1>
|
||||
<p>Hier steht der wesentliche Inhalt der Seite.</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<aside class="bg-light p-3">
|
||||
<h3>Seitenbereich</h3>
|
||||
<p>Optionale Sidebar oder Zusatzinformationen.</p>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<form class="form-inline" action="{{ .MediaLinksUrl }}">
|
||||
<input type="text" placeholder="Search" name="query">
|
||||
<button type="submit">Search</button>
|
||||
<div class="pill-nav"><a href="{{ .MediaLinksUrl }}/edit">Add Lofi</a></div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="row">
|
||||
{{ range .actors }}
|
||||
<div class="card shadow p-3 mb-2 bg-body rounded" style="width: 18rem;">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">{{.Name}}</h5>
|
||||
<a href="{{ $.media_actor_link }}/{{.ID}}" class="btn btn-primary">Read more</a>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
{{ end }}
|
||||
@@ -0,0 +1,54 @@
|
||||
{{ define "media_detail" }}
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
{{ template "head" . }}
|
||||
|
||||
<body>
|
||||
{{ template "navbar" . }}
|
||||
<main>
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<h1>{{.message}}</h1>
|
||||
<p>Hier steht der wesentliche Inhalt der Seite.</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<aside class="bg-light p-3">
|
||||
<h3>Seitenbereich</h3>
|
||||
<p>Optionale Sidebar oder Zusatzinformationen.</p>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
{{ if .Errors }}
|
||||
<div class="notification is-danger">{{ .Errors }}</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<form action="{{ .MediaLinksUrl }}/edit/{{.media.ID}}" method="POST">
|
||||
<div class="form-group row">
|
||||
<label for="inputWeblink" class="col-sm-2 -col-form-label">URL</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputWeblink" name="weblink" value="{{.media.WebLink}}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="inputTitle" class="col-sm-2 -col-form-label">Title</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="inputTitle" name="title" value="{{.media.Title}}"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-10">
|
||||
<button class="btn btn-primary" type="submit">Update</button>
|
||||
<button class="btn" type="button" onclick="window.history.back()">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
{{ template "footer" . }}
|
||||
</body>
|
||||
</html>
|
||||
{{ end }}
|
||||
@@ -0,0 +1,71 @@
|
||||
{{ define "media_links" }}
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
{{ template "head" . }}
|
||||
|
||||
<body>
|
||||
{{ template "navbar" . }}
|
||||
<main>
|
||||
<div class="row">
|
||||
<form class="form-inline" action="{{ .MediaLinksUrl }}">
|
||||
<input type="text" placeholder="Search" name="query">
|
||||
<label>
|
||||
<input type="checkbox" name="review" {{ if .Review }}checked{{ end }}>Review
|
||||
</label>
|
||||
<label>
|
||||
<input type="checkbox" name="download" {{ if .ShouldDownload }}checked{{ end }}>Download
|
||||
</label>
|
||||
<button type="submit">Search</button>
|
||||
<div class="pill-nav"><a href="{{ .MediaLinksUrl }}/edit">Add {{.title}}</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">Weblink</th>
|
||||
<th scope="col">Review</th>
|
||||
<th scope="col">Download</th>
|
||||
<th colspan="2">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{ range .media_links }}
|
||||
<tr>
|
||||
<th scope="row"><a href="{{ $.MediaLinksUrl }}/edit/{{.ID}}">{{.Title}}</a></th>
|
||||
{{ if .WebLink }}
|
||||
<td><a href="{{.WebLink}}">{{.WebLink}}</a></td>
|
||||
{{ else }}
|
||||
<td>no link</td>
|
||||
{{ end }}
|
||||
<td>
|
||||
{{ if .Review }}
|
||||
<img src="/public/icons/tick.png" alt="true" width="24" height="24">
|
||||
{{ else }}
|
||||
<img src="/public/icons/cross.png" alt="true" width="24" height="24">
|
||||
{{ end }}
|
||||
</td>
|
||||
<td>
|
||||
{{ if .ShouldDownload }}
|
||||
<img src="/public/icons/tick.png" alt="true" width="24" height="24">
|
||||
{{ else }}
|
||||
<img src="/public/icons/cross.png" alt="true" width="24" height="24">
|
||||
{{ end }}
|
||||
</td>
|
||||
<td><a href="{{ $.MediaLinksUrl }}/edit/{{.ID}}" class="btn btn-outline-primary btn-sm active" role="button"
|
||||
aria-pressed="true">Edit</a></td>
|
||||
<td><a href="{ $.MediaLinksUrl }/delete/{{.ID}}" class="btn btn-outline-danger btn-sm active"
|
||||
role="button" aria-pressed="true">Delete</a></td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
{{ template "footer" . }}
|
||||
</body>
|
||||
</html>
|
||||
{{ end }}
|
||||
@@ -0,0 +1,71 @@
|
||||
{{ define "mediafiles" }}
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
{{ template "head" . }}
|
||||
|
||||
<body>
|
||||
{{ template "navbar" . }}
|
||||
<main>
|
||||
<div class="row">
|
||||
<form class="form-inline" action="/web/files">
|
||||
<input type="text" placeholder="Search" name="query">
|
||||
<label>
|
||||
<input type="checkbox" name="review" {{ if .Review }}checked{{ end }}>Review
|
||||
</label>
|
||||
<label>
|
||||
<input type="checkbox" name="download" {{ if .ShouldDownload }}checked{{ end }}>Download
|
||||
</label>
|
||||
<button type="submit">Search</button>
|
||||
<div class="pill-nav"><a href="/web/files/add">Add MediaFile</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">Weblink</th>
|
||||
<th scope="col">Review</th>
|
||||
<th scope="col">Download</th>
|
||||
<th colspan="2">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{ range .mediafiles }}
|
||||
<tr>
|
||||
<th scope="row"><a href="/web/files/{{.ID}}">{{.Title}}</a></th>
|
||||
{{ if .WebLink }}
|
||||
<td><a href="{{.WebLink}}">{{.WebLink}}</a></td>
|
||||
{{ else }}
|
||||
<td>no link</td>
|
||||
{{ end }}
|
||||
<td>
|
||||
{{ if .Review }}
|
||||
<img src="/public/icons/tick.png" alt="true" width="24" height="24">
|
||||
{{ else }}
|
||||
<img src="/public/icons/cross.png" alt="true" width="24" height="24">
|
||||
{{ end }}
|
||||
</td>
|
||||
<td>
|
||||
{{ if .ShouldDownload }}
|
||||
<img src="/public/icons/tick.png" alt="true" width="24" height="24">
|
||||
{{ else }}
|
||||
<img src="/public/icons/cross.png" alt="true" width="24" height="24">
|
||||
{{ end }}
|
||||
</td>
|
||||
<td><a href="/web/files/edit/{{.ID}}" class="btn btn-outline-primary btn-sm active" role="button"
|
||||
aria-pressed="true">Edit</a></td>
|
||||
<td><a href="/web/files/delete/{{.ID}}" class="btn btn-outline-danger btn-sm active"
|
||||
role="button" aria-pressed="true">Delete</a></td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
{{ template "footer" . }}
|
||||
</body>
|
||||
</html>
|
||||
{{ end }}
|
||||
@@ -0,0 +1,71 @@
|
||||
{{ define "mediavideos" }}
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
{{ template "head" . }}
|
||||
|
||||
<body>
|
||||
{{ template "navbar" . }}
|
||||
<main>
|
||||
<div class="row">
|
||||
<form class="form-inline" action="/web/media-videos">
|
||||
<input type="text" placeholder="Search" name="query">
|
||||
<label>
|
||||
<input type="checkbox" name="review" {{ if .Review }}checked{{ end }}>Review
|
||||
</label>
|
||||
<label>
|
||||
<input type="checkbox" name="download" {{ if .ShouldDownload }}checked{{ end }}>Download
|
||||
</label>
|
||||
<button type="submit">Search</button>
|
||||
<div class="pill-nav"><a href="/web/media-videos/add">Add MediaFile</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">Weblink</th>
|
||||
<th scope="col">Review</th>
|
||||
<th scope="col">Download</th>
|
||||
<th colspan="2">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{ range .mediavideos }}
|
||||
<tr>
|
||||
<th scope="row"><a href="/web/media-videos/{{.ID}}">{{.Title}}</a></th>
|
||||
{{ if .WebLink }}
|
||||
<td><a href="{{.WebLink}}">{{.WebLink}}</a></td>
|
||||
{{ else }}
|
||||
<td>no link</td>
|
||||
{{ end }}
|
||||
<td>
|
||||
{{ if .Review }}
|
||||
<img src="/public/icons/tick.png" alt="true" width="24" height="24">
|
||||
{{ else }}
|
||||
<img src="/public/icons/cross.png" alt="true" width="24" height="24">
|
||||
{{ end }}
|
||||
</td>
|
||||
<td>
|
||||
{{ if .ShouldDownload }}
|
||||
<img src="/public/icons/tick.png" alt="true" width="24" height="24">
|
||||
{{ else }}
|
||||
<img src="/public/icons/cross.png" alt="true" width="24" height="24">
|
||||
{{ end }}
|
||||
</td>
|
||||
<td><a href="/web/media-videos/{{.ID}}" class="btn btn-outline-primary btn-sm active" role="button"
|
||||
aria-pressed="true">Edit</a></td>
|
||||
<td><a href="/web/media-videos/{{.ID}}/delete" class="btn btn-outline-danger btn-sm active"
|
||||
role="button" aria-pressed="true">Delete</a></td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
{{ template "footer" . }}
|
||||
</body>
|
||||
</html>
|
||||
{{ end }}
|
||||
@@ -0,0 +1,42 @@
|
||||
{{ define "publishers" }}
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
{{ template "head" . }}
|
||||
|
||||
<body>
|
||||
{{ template "navbar" . }}
|
||||
<main>
|
||||
<div class="row">
|
||||
<div class="col-md-8">
|
||||
<h1>Comic Publishers</h1>
|
||||
<p>Hier steht der wesentliche Inhalt der Seite.</p>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<aside class="bg-light p-3">
|
||||
<h3>Seitenbereich</h3>
|
||||
<p>Optionale Sidebar oder Zusatzinformationen.</p>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<form class="form-inline" action="/comic/publishers">
|
||||
<input type="text" placeholder="Search" name="query">
|
||||
<button type="submit">Search</button>
|
||||
<div class="pill-nav"><a href="/comic/publishers/add">Add Lofi</a></div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="row">
|
||||
{{ range .publishers }}
|
||||
<div class="card shadow p-3 mb-2 bg-body rounded" style="width: 18rem;">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">{{.Name}}</h5>
|
||||
<a href="/comic/publishers/{{.ID}}" class="btn btn-primary">Read more</a>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</main>
|
||||
{{ template "footer" . }}
|
||||
</body>
|
||||
</html>
|
||||
{{ end }}
|
||||
@@ -0,0 +1,8 @@
|
||||
package templates
|
||||
|
||||
import (
|
||||
"embed"
|
||||
)
|
||||
|
||||
//go:embed layouts/* pages/*
|
||||
var TemplateFiles embed.FS
|
||||
Reference in New Issue
Block a user