add method to handlers
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s
Gitea Actions Demo / build-and-test (push) Failing after 29m54s

This commit is contained in:
Thomas Peetz
2026-10-26 22:41:15 +01:00
parent 9ab4f2103f
commit 72c08f9731
11 changed files with 198 additions and 52 deletions
-17
View File
@@ -1,12 +1,10 @@
package api
import (
"encoding/json"
"fmt"
"kontor-api-gin/internal/config"
"kontor-api-gin/internal/models"
"log/slog"
"os"
"resty.dev/v3"
)
@@ -220,21 +218,6 @@ func UpdateData(target config.Server, path string, v any) {
PostJSON(client, target, token, config.Config.ApiVersion, path, v, &result)
}
func WriteJson(data *ExportData, fileName string) error {
jsonData, err := json.MarshalIndent(data, "", " ")
if err != nil {
slog.Info("JSON MarshalIndent failed", "Error:", err)
return err
}
// Write bytes to file
err = os.WriteFile(fileName, jsonData, 0644)
if err != nil {
slog.Info("Error writing file:", "Error", err)
return err
}
return nil
}
func GetJSON(client *resty.Client, token string, server config.Server, path string, v any) {
url := fmt.Sprintf("%s/%s/%s", server.Url, config.Config.ApiVersion, path)
if config.Verbose > 2 {
+22
View File
@@ -0,0 +1,22 @@
package api
import (
"encoding/json"
"log/slog"
"os"
)
func WriteJson(data *ExportData, fileName string) error {
jsonData, err := json.MarshalIndent(data, "", " ")
if err != nil {
slog.Info("JSON MarshalIndent failed", "Error:", err)
return err
}
// Write bytes to file
err = os.WriteFile(fileName, jsonData, 0644)
if err != nil {
slog.Info("Error writing file:", "Error", err)
return err
}
return nil
}
+1 -9
View File
@@ -7,12 +7,9 @@ import (
"log/slog"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"resty.dev/v3"
)
var filename string
var exportCmd = &cobra.Command{
Use: "export",
Short: "Export Kontor Database",
@@ -28,7 +25,7 @@ var exportCmd = &cobra.Command{
localServer := config.Config.Server[config.ServerName]
export, _ := api.GetData(localServer, config.Config.ApiVersion)
err := api.WriteJson(export, filename)
err := api.WriteJson(export, config.FileName)
if err != nil {
slog.Info("WriteJon failed", "Error:", err)
}
@@ -38,9 +35,4 @@ var exportCmd = &cobra.Command{
func init() {
rootCmd.AddCommand(exportCmd)
exportCmd.PersistentFlags().StringVarP(&filename, "file", "f", "/home/tpeetz/.sync/media/data-gin.json", "Filename to store data")
viper.BindPFlag("file", exportCmd.PersistentFlags().Lookup("file"))
exportCmd.PersistentFlags().StringVarP(&config.Config.ApiVersion, "api", "a", "api/v1", "API Version")
viper.BindPFlag("api", exportCmd.PersistentFlags().Lookup("api"))
}
+11
View File
@@ -35,10 +35,21 @@ func init() {
rootCmd.PersistentFlags().StringVarP(&config.CfgFile, "config", "c", "/home/tpeetz/.config/kli.yaml", "config file")
rootCmd.PersistentFlags().CountVarP(&config.Verbose, "verbose", "v", "increase verbosity (-v, -vv, -vvv)")
viper.BindPFlag("config", rootCmd.PersistentFlags().Lookup("config"))
exportCmd.Flags().StringVarP(&config.ServerName, "servername", "s", "local", "Define server to get Kontor items")
updateTitleCmd.Flags().StringVarP(&config.ServerName, "servername", "s", "local", "Define server to get Kontor items")
addLinksCmd.Flags().StringVarP(&config.ServerName, "servername", "s", "local", "Define server to get Kontor items")
addLinksCmd.Flags().Var(&config.Mediatype, "mediatype", "MediaType: allowed values are: media, videos, lofi")
exportCmd.PersistentFlags().StringVarP(&config.FileName, "file", "f", "/home/tpeetz/.sync/media/data-gin.json", "Filename to store data")
importCmd.PersistentFlags().StringVarP(&config.FileName, "file", "f", "/home/tpeetz/.sync/media/data-gin.json", "Filename to import data from")
viper.BindPFlag("file", exportCmd.PersistentFlags().Lookup("file"))
exportCmd.PersistentFlags().StringVarP(&config.Config.ApiVersion, "api", "a", "api/v1", "API Version")
viper.BindPFlag("api", exportCmd.PersistentFlags().Lookup("api"))
viper.BindPFlag("server", exportCmd.PersistentFlags().Lookup("server"))
cobra.OnInitialize(config.InitCliConfig)
}
+12 -11
View File
@@ -10,7 +10,16 @@ import (
"github.com/spf13/viper"
)
type MediaType string
var (
CfgFile string
Verbose int
Overwrite bool
ServerName string
Mediatype MediaType
Config CliConfig
DryRun bool
FileName string
)
const (
mediaTypeMedia MediaType = "media"
@@ -18,6 +27,8 @@ const (
mediaTypeLofi MediaType = "lofi"
)
type MediaType string
func (e *MediaType) String() string {
return string(*e)
}
@@ -44,16 +55,6 @@ func myEnumCompletion(cmd *cobra.Command, args []string, toComplete string) ([]s
}, cobra.ShellCompDirectiveDefault
}
var (
CfgFile string
Verbose int
Overwrite bool
ServerName string
Mediatype MediaType
Config CliConfig
DryRun bool
)
type Server struct {
Url string `mapstructure:"url"`
Username string `mapstructure:"username"`
+61 -7
View File
@@ -69,11 +69,65 @@ func (handler *MediaFileHandler) ListPage(c *gin.Context) {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
c.HTML(http.StatusOK, "mediafiles", gin.H{
"title": "Kontor MediaFiles",
"version": "0.4.0",
"message": "MediaFiles...",
"mediafiles": files,
"user": user,
})
data := globals.GetDefaultValues(user, "MediaFiles...")
data["title"] = "Kontor MediaFiles"
data["mediafiles"] = files
c.HTML(http.StatusOK, "mediafiles", data)
}
func (handler *MediaFileHandler) EditPage(c *gin.Context) {
session := sessions.Default(c)
user := session.Get(globals.UserKey)
id := c.Param("id")
logger := slog.Get(c)
media_file, err := handler.Service.Get(c.Request.Context(), id)
if err != nil {
logger.Info("MediaLoFiHandler#EditPage", "error", err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
logger.Info("MediaLoFiHandler#EditPage", "media_file", media_file)
data := globals.GetDefaultValues(user, "MediaFile Details...")
data["lofi"] = media_file
c.HTML(http.StatusOK, "lofi_detail", data)
}
func (handler *MediaFileHandler) UpdatePage(c *gin.Context) {
session := sessions.Default(c)
user := session.Get(globals.UserKey)
id := c.Param("id")
logger := slog.Get(c)
media_file, err := handler.Service.Get(c.Request.Context(), id)
if err != nil {
logger.Info("MediaFileHandler#UpdatePage", "error", err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
var form models.MediaFileForm
if err := c.ShouldBind(&form); err != nil {
logger.Info("MediaFileHandler#UpdatePage", "error", err.Error())
data := globals.GetDefaultValues(user, "MediaFile Details...")
data["Form"] = form
data["Errors"] = err.Error()
c.HTML(http.StatusBadRequest, "lofi_detail", data)
return
}
logger.Info("MediaFileHandler#UpdatePage", "media_file", media_file)
//handler.Service.Update(c.Request.Context(), form.ConvertFormToMediaFileDTO())
c.Redirect(http.StatusFound, "web/media-files")
}
func (handler *MediaFileHandler) DeletePage(c *gin.Context) {
//session := sessions.Default(c)
//user := session.Get(globals.UserKey)
id := c.Param("id")
logger := slog.Get(c)
err := handler.Service.Delete(c.Request.Context(), id)
if err != nil {
logger.Info("MediaFileHandler#DeletePage", "error", err.Error())
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
logger.Info("MediaFileHandler#DeletePage", "lofi", id)
c.Redirect(http.StatusFound, "web/media-files")
}
+1 -1
View File
@@ -43,7 +43,7 @@ func (handler *MediaVideoHandler) ListPage(c *gin.Context) {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
logger.Info("MediaLoFiHandler#ListPage", "videos count", len(videos))
logger.Info("MediaVideoHandler#ListPage", "videos count", len(videos))
data := globals.GetDefaultValues(user, "MediaVideos...")
data["title"] = "Kontor MediaVideos"
data["mediavideos"] = videos
+1 -1
View File
@@ -16,7 +16,7 @@ func RequestID(skipPaths []string) gin.HandlerFunc {
id = uuid.NewString()
}
if len(skipPaths) > 0 && !slices.Contains(skipPaths, c.Request.URL.Path) {
logger.Info("RequestID", "id", id)
logger.Info("RequestID", "id", id, "path", c.Request.URL.Path)
}
c.Set("request_id", id)
c.Writer.Header().Set("X-Request-ID", id)
+10
View File
@@ -30,6 +30,16 @@ type MediaFileAdd struct {
Url string `json:"url"`
}
type MediaFileForm struct {
Title string `form:"title" binding:"required"`
Url string `form:"url" binding:"required"`
}
func (form *MediaFileForm) ConvertFormToMediaFileDTO() MediaFileDTO {
media_file := MediaFileDTO{}
return media_file
}
type MediaFileDTO struct {
ID string `json:"id" binding:"required"`
CreatedAt helpers.KontorTime `json:"created_date"`
+2
View File
@@ -63,6 +63,8 @@ func New(admin *handlers.AdminHandler, bookshelf *handlers.BookshelfHandler, com
m.POST("/actors/:id/edit", media.MediaActorHandler.UpdatePage)
m.GET("/articles", media.MediaFileHandler.ListPage)
m.GET("/media-files", media.MediaFileHandler.ListPage)
m.GET("/media-files/:id", media.MediaFileHandler.EditPage)
m.POST("/media-files/:id", media.MediaFileHandler.UpdatePage)
m.GET("/media-videos", media.MediaVideoHandler.ListPage)
m.GET("/media-lofis", media.MediaLoFiHandler.ListPage)
m.GET("/media-lofis/:id/edit", media.MediaLoFiHandler.EditPage)
@@ -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 }}