Compare commits
No commits in common. "main" and "v5.0.0" have entirely different histories.
27 changed files with 424 additions and 408 deletions
37
Dockerfile
37
Dockerfile
|
@ -1,27 +1,34 @@
|
|||
from golang:1.23 as build
|
||||
FROM golang:1.21.4 as build
|
||||
|
||||
label author="Victor Lacasse-Beaudoin <vlbeaudoin@agecem.org>"
|
||||
label license="MIT"
|
||||
label licensee="AGECEM"
|
||||
label repo="https://git.agecem.com/agecem/babillard"
|
||||
LABEL author="Victor Lacasse-Beaudoin <vlbeaudoin@agecem.org>"
|
||||
LABEL license="MIT"
|
||||
LABEL licensee="AGECEM"
|
||||
LABEL repo="https://git.agecem.com/agecem/babillard"
|
||||
|
||||
workdir /go/src/app
|
||||
WORKDIR /go/src/app
|
||||
|
||||
copy go.mod go.sum LICENSE cmd.go config.go contenu.go data.go handlers.go response.go ./
|
||||
COPY go.mod go.sum main.go ./
|
||||
|
||||
add cmd/ cmd/
|
||||
add ui/ ui/
|
||||
ADD cmd/ cmd/
|
||||
|
||||
run CGO_ENABLED=0 go build -a ./cmd/babillard/
|
||||
ADD data/ data/
|
||||
|
||||
ADD handlers/ handlers/
|
||||
|
||||
ADD public/ public/
|
||||
|
||||
RUN CGO_ENABLED=0 go build -a -o babillard .
|
||||
|
||||
# Alpine
|
||||
|
||||
from alpine:3.21
|
||||
FROM alpine:3.18.4
|
||||
|
||||
workdir /app
|
||||
RUN apk update && apk upgrade --no-cache
|
||||
|
||||
add contenu/ contenu/
|
||||
WORKDIR /app
|
||||
|
||||
copy --from=build /go/src/app/babillard /usr/bin/babillard
|
||||
ADD contenu/ contenu/
|
||||
|
||||
cmd ["babillard", "server"]
|
||||
COPY --from=build /go/src/app/babillard /usr/bin/babillard
|
||||
|
||||
CMD ["babillard", "server"]
|
||||
|
|
20
Makefile
20
Makefile
|
@ -1,20 +0,0 @@
|
|||
## This Makefile uses the help target explained in the following blogpost:
|
||||
##
|
||||
## https://victoria.dev/blog/how-to-create-a-self-documenting-makefile/
|
||||
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
.PHONY: help
|
||||
help: ## Show this help
|
||||
@egrep -h '\s##\s' $(MAKEFILE_LIST) | \
|
||||
sort | \
|
||||
awk \
|
||||
'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
|
||||
|
||||
.PHONY: install
|
||||
install: ## Use `go install` to build and link the executable
|
||||
go install -a ./cmd/babillard/
|
||||
|
||||
.PHONY: build
|
||||
build: ## Use `docker build` to build the container image
|
||||
docker build . -f Dockerfile -t git.agecem.com/agecem/babillard:latest
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
Application web pour 'digital signage'.
|
||||
|
||||
**CE DOCUMENT N'EST PLUS À JOUR**
|
||||
|
||||
Backend: Go avec `labstack/echo/v4`
|
||||
|
||||
Frontend: html, css, jquery
|
||||
|
|
56
cmd.go
56
cmd.go
|
@ -1,56 +0,0 @@
|
|||
package babillard
|
||||
|
||||
import (
|
||||
"flag"
|
||||
|
||||
"codeberg.org/vlbeaudoin/couleuvre"
|
||||
)
|
||||
|
||||
var app couleuvre.App[Config]
|
||||
|
||||
func init() {
|
||||
app = couleuvre.App[Config]{EnvPrefix: "babillard"}
|
||||
|
||||
flag.StringVar(&app.Config.ServerContenuDir, ServerContenuDirName, ServerContenuDirDefault, ServerContenuDirDescription)
|
||||
flag.IntVar(&app.Config.ServerPort, ServerPortName, ServerPortDefault, ServerPortDescription)
|
||||
}
|
||||
|
||||
const (
|
||||
ServerContenuDirName = "servercontenudir"
|
||||
ServerContenuDirDefault = "contenu"
|
||||
ServerContenuDirDescription = "Répertoire du contenu à exposer"
|
||||
|
||||
ServerPortName = "serverport"
|
||||
ServerPortDefault int = 8080
|
||||
ServerPortDescription = "Port réseau à utiliser pour le serveur"
|
||||
)
|
||||
|
||||
const (
|
||||
ServerCmdName = "server"
|
||||
ServerCmdDesc = "Démarrer le serveur web"
|
||||
)
|
||||
|
||||
func ServerCmdExecuter(args ...string) error {
|
||||
RunServer(app.Config)
|
||||
return nil
|
||||
}
|
||||
|
||||
func Execute() error {
|
||||
if err := app.AddCommands(couleuvre.Command{
|
||||
Name: ServerCmdName,
|
||||
Description: ServerCmdDesc,
|
||||
Executer: couleuvre.ExecuterFunc(ServerCmdExecuter),
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := app.Parse(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := app.Execute(flag.Args()...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
67
cmd/cmd.go
Normal file
67
cmd/cmd.go
Normal file
|
@ -0,0 +1,67 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"os"
|
||||
|
||||
"codeberg.org/vlbeaudoin/couleuvre"
|
||||
"git.agecem.com/agecem/babillard/config"
|
||||
"git.agecem.com/agecem/babillard/handlers"
|
||||
)
|
||||
|
||||
var cfg config.Config
|
||||
|
||||
func Cfg() config.Config { return cfg }
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&cfg.ServerContenuDir, ServerContenuDirName, ServerContenuDirDefault, ServerContenuDirDescription)
|
||||
flag.IntVar(&cfg.ServerPort, ServerPortName, ServerPortDefault, ServerPortDescription)
|
||||
}
|
||||
|
||||
const (
|
||||
ServerContenuDirName = "servercontenudir"
|
||||
ServerContenuDirDefault = "contenu"
|
||||
ServerContenuDirDescription = "Répertoire du contenu à exposer"
|
||||
|
||||
ServerPortName = "serverport"
|
||||
ServerPortDefault int = 8080
|
||||
ServerPortDescription = "Port réseau à utiliser pour le serveur"
|
||||
)
|
||||
|
||||
const (
|
||||
ServerCmdName = "server"
|
||||
ServerCmdDesc = "Démarrer le serveur web"
|
||||
)
|
||||
|
||||
func ServerCmdExecuter() error {
|
||||
handlers.RunServer(Cfg())
|
||||
return nil
|
||||
}
|
||||
|
||||
func Execute() error {
|
||||
app := couleuvre.NewApp("BABILLARD_", ".", "_")
|
||||
|
||||
if err := app.Parse(&cfg); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := app.NewCommand(ServerCmdName, ServerCmdDesc, ServerCmdExecuter); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var commandName string
|
||||
if len(os.Args) > 1 {
|
||||
commandName = flag.Arg(0)
|
||||
}
|
||||
|
||||
cmd, err := app.ParseCommand(commandName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := cmd.Execute(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package babillard
|
||||
package config
|
||||
|
||||
type Config struct {
|
||||
ServerContenuDir string
|
68
contenu.go
68
contenu.go
|
@ -1,68 +0,0 @@
|
|||
package babillard
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
// pre-v2
|
||||
|
||||
type ContenuHandler struct {
|
||||
ContenuDir string
|
||||
}
|
||||
|
||||
func NewContenuHandler(contenuDir string) (h ContenuHandler) {
|
||||
h.ContenuDir = contenuDir
|
||||
return
|
||||
}
|
||||
|
||||
func (h ContenuHandler) HandleAPIContenuList(c echo.Context) error {
|
||||
contenu_dir := h.ContenuDir
|
||||
|
||||
files, err := ListContenu(contenu_dir)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{
|
||||
"message": "Internal Server Error",
|
||||
"error": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return c.String(http.StatusOK, strings.Join(files, ";"))
|
||||
}
|
||||
|
||||
func (h ContenuHandler) HandleAPIContenuFile(c echo.Context) error {
|
||||
filename := c.Param("filename")
|
||||
contenu_dir := h.ContenuDir
|
||||
|
||||
if filename == ".gitkeep" {
|
||||
return c.JSON(http.StatusNotFound, map[string]string{"message": "Not Found"})
|
||||
}
|
||||
|
||||
return c.File(fmt.Sprintf("%s/%s", contenu_dir, filename))
|
||||
}
|
||||
|
||||
// v2
|
||||
|
||||
func APIv2ListContenu(cfg Config) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
files, err := ListContenu(cfg.ServerContenuDir)
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusInternalServerError, ErrorResponse{Error: err.Error()})
|
||||
}
|
||||
|
||||
return c.JSON(http.StatusOK, NewContenuResponse(files))
|
||||
}
|
||||
}
|
||||
|
||||
// ui
|
||||
|
||||
func UIContenuFichier(cfg Config) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
return c.File(fmt.Sprintf("%s/%s", cfg.ServerContenuDir, c.Param("fichier")))
|
||||
}
|
||||
}
|
42
data.go
42
data.go
|
@ -1,42 +0,0 @@
|
|||
package babillard
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
var forbiddenFiles = []string{".gitkeep", "messages.txt", "Thumbs.db"}
|
||||
|
||||
func ListContenu(path string) (files []string, err error) {
|
||||
file, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
stats, err := file.Stat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !stats.IsDir() {
|
||||
return nil, fmt.Errorf("contenu '%s' n'est pas un répertoire", path)
|
||||
}
|
||||
|
||||
fileInfos, err := file.Readdir(-1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fileLoop:
|
||||
for _, fileInfo := range fileInfos {
|
||||
for _, forbiddenFile := range forbiddenFiles {
|
||||
if fileInfo.Name() == forbiddenFile {
|
||||
continue fileLoop
|
||||
}
|
||||
}
|
||||
files = append(files, fileInfo.Name())
|
||||
}
|
||||
|
||||
return files, nil
|
||||
}
|
24
data/data.go
Normal file
24
data/data.go
Normal file
|
@ -0,0 +1,24 @@
|
|||
package data
|
||||
|
||||
import "os"
|
||||
|
||||
func ListContenu(path string) ([]string, error) {
|
||||
var files []string
|
||||
f, err_open := os.Open(path)
|
||||
defer f.Close()
|
||||
|
||||
if err_open != nil {
|
||||
return nil, err_open
|
||||
}
|
||||
fileInfo, err_read := f.Readdir(-1)
|
||||
if err_read != nil {
|
||||
return nil, err_read
|
||||
}
|
||||
|
||||
for _, file := range fileInfo {
|
||||
if file.Name() != ".gitkeep" && file.Name() != "messages.txt" {
|
||||
files = append(files, file.Name())
|
||||
}
|
||||
}
|
||||
return files, nil
|
||||
}
|
|
@ -8,7 +8,7 @@ services:
|
|||
volumes:
|
||||
- 'config:/app/config'
|
||||
- 'contenu:/app/contenu'
|
||||
command: ['babillard', '--config', '/app/config/babillard.yaml', 'server']
|
||||
command: ['babillard', 'server', '--config', '/app/config/.babillard.yaml']
|
||||
|
||||
volumes:
|
||||
config:
|
|
@ -1,2 +0,0 @@
|
|||
serverport: 9999
|
||||
servercontenudir: '/dev/null'
|
30
go.mod
30
go.mod
|
@ -1,26 +1,30 @@
|
|||
module git.agecem.com/agecem/babillard/v8
|
||||
module git.agecem.com/agecem/babillard
|
||||
|
||||
go 1.23.0
|
||||
go 1.21.3
|
||||
|
||||
toolchain go1.23.6
|
||||
toolchain go1.21.4
|
||||
|
||||
require (
|
||||
codeberg.org/vlbeaudoin/couleuvre v0.13.0
|
||||
github.com/labstack/echo/v4 v4.13.3
|
||||
codeberg.org/vlbeaudoin/couleuvre v0.8.0
|
||||
github.com/labstack/echo/v4 v4.11.3
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/goccy/go-yaml v1.16.0 // indirect
|
||||
github.com/labstack/gommon v0.4.2 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/labstack/gommon v0.4.1 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/rogpeppe/go-internal v1.10.0 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||
golang.org/x/crypto v0.36.0 // indirect
|
||||
golang.org/x/net v0.38.0 // indirect
|
||||
golang.org/x/sys v0.31.0 // indirect
|
||||
golang.org/x/text v0.23.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
golang.org/x/crypto v0.16.0 // indirect
|
||||
golang.org/x/net v0.19.0 // indirect
|
||||
golang.org/x/sys v0.15.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
|
58
go.sum
58
go.sum
|
@ -1,35 +1,49 @@
|
|||
codeberg.org/vlbeaudoin/couleuvre v0.13.0 h1:N2gAzpItFthQ0aPzMQjntRsrqrEXwuo0u6VHSGA/V6o=
|
||||
codeberg.org/vlbeaudoin/couleuvre v0.13.0/go.mod h1:0RvzStph7J4/M+mZb903hn4GSYrTBjXYVJv72Pwpa90=
|
||||
codeberg.org/vlbeaudoin/couleuvre v0.8.0 h1:61lJ8zICGWiBX2Ao0+p1L+fU78KKibgJ5M6kCFHXjN0=
|
||||
codeberg.org/vlbeaudoin/couleuvre v0.8.0/go.mod h1:+M8nPA/3LknsY72RP0ZHCZycQ1SPxxRoXpnyHeSNE7U=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/goccy/go-yaml v1.16.0 h1:d7m1G7A0t+logajVtklHfDYJs2Et9g3gHwdBNNFou0w=
|
||||
github.com/goccy/go-yaml v1.16.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||
github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY=
|
||||
github.com/labstack/echo/v4 v4.13.3/go.mod h1:o90YNEeQWjDozo584l7AwhJMHN0bOC4tAfg+Xox9q5g=
|
||||
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
|
||||
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
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/v4 v4.11.3 h1:Upyu3olaqSHkCjs1EJJwQ3WId8b8b1hxbogyommKktM=
|
||||
github.com/labstack/echo/v4 v4.11.3/go.mod h1:UcGuQ8V6ZNRmSweBIJkPvGfwCMIlFmiqrPqiEBfPYws=
|
||||
github.com/labstack/gommon v0.4.1 h1:gqEff0p/hTENGMABzezPoPSRtIh1Cvw0ueMOe0/dfOk=
|
||||
github.com/labstack/gommon v0.4.1/go.mod h1:TyTrpPqxR5KMk8LKVtLmfMjeQ5FEkBYdxLYPw/WfrOM=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
||||
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
||||
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||
golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
|
||||
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
47
handlers/contenu.go
Normal file
47
handlers/contenu.go
Normal file
|
@ -0,0 +1,47 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"git.agecem.com/agecem/babillard/config"
|
||||
"git.agecem.com/agecem/babillard/data"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
type ContenuHandler struct {
|
||||
Cfg config.Config
|
||||
}
|
||||
|
||||
func NewContenuHandler(cfg config.Config) (h ContenuHandler) {
|
||||
h.Cfg = cfg
|
||||
return
|
||||
}
|
||||
|
||||
func (h ContenuHandler) HandleAPIContenuList(c echo.Context) error {
|
||||
contenu_dir := h.Cfg.ServerContenuDir
|
||||
|
||||
files, err := data.ListContenu(contenu_dir)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return c.JSON(http.StatusInternalServerError, map[string]string{
|
||||
"message": "Internal Server Error",
|
||||
"error": err.Error(),
|
||||
})
|
||||
}
|
||||
|
||||
return c.String(http.StatusOK, strings.Join(files, ";"))
|
||||
}
|
||||
|
||||
func (h ContenuHandler) HandleAPIContenuFile(c echo.Context) error {
|
||||
filename := c.Param("filename")
|
||||
contenu_dir := h.Cfg.ServerContenuDir
|
||||
|
||||
if filename == ".gitkeep" {
|
||||
return c.JSON(http.StatusNotFound, map[string]string{"message": "Not Found"})
|
||||
}
|
||||
|
||||
return c.File(fmt.Sprintf("%s/%s", contenu_dir, filename))
|
||||
}
|
|
@ -1,11 +1,12 @@
|
|||
package babillard
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"git.agecem.com/agecem/babillard/v8/ui"
|
||||
"git.agecem.com/agecem/babillard/config"
|
||||
"git.agecem.com/agecem/babillard/public"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/labstack/echo/v4/middleware"
|
||||
)
|
||||
|
@ -18,16 +19,12 @@ API Specifications
|
|||
'/api' | GET | Affiche les spécifications API
|
||||
'/api/contenu' | GET | Affiche le nom des fichiers dans 'contenu/'
|
||||
'/api/contenu/{filename}' | GET | Affiche le fichier 'contenu/{filename}'
|
||||
-----
|
||||
-----`
|
||||
|
||||
v2
|
||||
--
|
||||
'/api/v2/contenu' | GET | Affiche les noms des fichiers dans 'contenu/'
|
||||
`
|
||||
return c.String(http.StatusOK, apispec)
|
||||
}
|
||||
|
||||
func RunServer(cfg Config) {
|
||||
func RunServer(cfg config.Config) {
|
||||
log.Print("[I] Starting webserver")
|
||||
|
||||
e := echo.New()
|
||||
|
@ -36,30 +33,24 @@ func RunServer(cfg Config) {
|
|||
|
||||
e.Group("").Use(middleware.StaticWithConfig(middleware.StaticConfig{
|
||||
Root: "/html/",
|
||||
Filesystem: http.FS(ui.HTMLFS()),
|
||||
Filesystem: http.FS(public.HTMLFS()),
|
||||
}))
|
||||
e.Group("/public/css").Use(middleware.StaticWithConfig(middleware.StaticConfig{
|
||||
Root: "/css/",
|
||||
Filesystem: http.FS(ui.CSSFS()),
|
||||
Filesystem: http.FS(public.CSSFS()),
|
||||
}))
|
||||
e.Group("/public/js").Use(middleware.StaticWithConfig(middleware.StaticConfig{
|
||||
Root: "/js/",
|
||||
Filesystem: http.FS(ui.JSFS()),
|
||||
Filesystem: http.FS(public.JSFS()),
|
||||
}))
|
||||
|
||||
groupAPI := e.Group("/api")
|
||||
|
||||
contenuHandler := NewContenuHandler(cfg.ServerContenuDir)
|
||||
contenuHandler := NewContenuHandler(cfg)
|
||||
|
||||
groupAPI.GET("/", HandleAPIShow)
|
||||
groupAPI.GET("/contenu/", contenuHandler.HandleAPIContenuList)
|
||||
groupAPI.GET("/contenu/:filename/", contenuHandler.HandleAPIContenuFile)
|
||||
|
||||
groupAPI.GET("/v2/contenu/", APIv2ListContenu(cfg))
|
||||
|
||||
groupUI := e.Group("/ui")
|
||||
|
||||
groupUI.GET("/contenu/:fichier/", UIContenuFichier(cfg))
|
||||
|
||||
e.Logger.Fatal(e.Start(fmt.Sprintf(":%d", cfg.ServerPort)))
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: babillard-deployment
|
||||
labels:
|
||||
app: babillard
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: babillard
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: babillard
|
||||
spec:
|
||||
containers:
|
||||
- name: babillard
|
||||
image: git.agecem.com/agecem/babillard:latest
|
||||
imagePullPolicy: Always
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
volumeMounts:
|
||||
- name: babillard-nfs
|
||||
mountPath: "/app/contenu"
|
||||
volumes:
|
||||
- name: babillard-nfs
|
||||
nfs:
|
||||
server: fs.agecem.com
|
||||
path: /mnt/Pool1/babillard
|
||||
readOnly: true
|
|
@ -1,13 +0,0 @@
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: babillard-service
|
||||
spec:
|
||||
type: NodePort
|
||||
selector:
|
||||
app: babillard
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8080
|
||||
targetPort: 8080
|
||||
nodePort: 30001
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright © 2021-2025 AGECEM
|
||||
Copyright © 2021 AGECEM
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -24,11 +24,11 @@ package main
|
|||
import (
|
||||
"log"
|
||||
|
||||
"git.agecem.com/agecem/babillard/v8"
|
||||
"git.agecem.com/agecem/babillard/cmd"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if err := babillard.Execute(); err != nil {
|
||||
if err := cmd.Execute(); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
79
public/css/style.css
Normal file
79
public/css/style.css
Normal file
|
@ -0,0 +1,79 @@
|
|||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
embed {
|
||||
max-width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
#contenu {
|
||||
background-color: black;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
#bar {
|
||||
width: 100%;
|
||||
background-image: linear-gradient(to right, #033ead, #3093d1);
|
||||
color: white;
|
||||
font-family: 'Roboto', sans-serif;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
min-height: 75px;
|
||||
}
|
||||
|
||||
img#bar-bg {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
#time {
|
||||
font-size: 300%;
|
||||
height: 53px;
|
||||
}
|
||||
|
||||
#text-content {
|
||||
white-space: nowrap;
|
||||
z-index: 1;
|
||||
display: block;
|
||||
height: 100%;
|
||||
padding-top: 55px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#text-container {
|
||||
height: 100%;
|
||||
background-image: linear-gradient(to right, #033ead, #3093d1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 20px;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
#text-content div {
|
||||
display: block;
|
||||
position: fixed;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#date-time {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
background-color: #033ead;
|
||||
z-index: 1;
|
||||
width: 225px;
|
||||
}
|
|
@ -1,18 +1,18 @@
|
|||
package ui
|
||||
package public
|
||||
|
||||
import "embed"
|
||||
|
||||
//go:embed html/*.html
|
||||
//go:embed html/*
|
||||
var htmlFS embed.FS
|
||||
|
||||
func HTMLFS() embed.FS { return htmlFS }
|
||||
|
||||
//go:embed css/*.css
|
||||
//go:embed css/*
|
||||
var cssFS embed.FS
|
||||
|
||||
func CSSFS() embed.FS { return cssFS }
|
||||
|
||||
//go:embed js/*.js
|
||||
//go:embed js/*
|
||||
var jsFS embed.FS
|
||||
|
||||
func JSFS() embed.FS { return jsFS }
|
43
public/html/index.html
Normal file
43
public/html/index.html
Normal file
|
@ -0,0 +1,43 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<title>AGECEM | slider</title>
|
||||
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
|
||||
|
||||
<script src="/public/js/slider.js"></script>
|
||||
|
||||
<!-- BROKEN, brise slider.js quand inclu
|
||||
<script src="text.js"></script>
|
||||
!-->
|
||||
|
||||
<link rel="stylesheet" href="/public/css/style.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p id="debug"></p>
|
||||
|
||||
<div id="contenu">
|
||||
<embed id="image"/>
|
||||
</div>
|
||||
|
||||
<!-- BROKEN
|
||||
<div id="bar">
|
||||
|
||||
<div id="date-time">
|
||||
<div id="time"></div>
|
||||
<div id="date"></div>
|
||||
</div>
|
||||
|
||||
<div id="text-container">
|
||||
<div id="text-content">
|
||||
<div>Ce texte sera remplacé par jQuery!</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
--!>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -10,14 +10,15 @@ function afficherImage() {
|
|||
}
|
||||
|
||||
function augmenterIndex() {
|
||||
if (indexImages >= images.length - 1) {
|
||||
indexImages = 0;
|
||||
} else {
|
||||
indexImages ++;
|
||||
}
|
||||
}
|
||||
|
||||
function executionLoop(){
|
||||
if (indexImages >= images.length) {
|
||||
location.reload();
|
||||
}
|
||||
|
||||
//afficherIndex();
|
||||
afficherImage();
|
||||
augmenterIndex();
|
||||
}
|
||||
|
@ -40,6 +41,5 @@ function obtenirContenu(){
|
|||
|
||||
$(function(){
|
||||
obtenirContenu();
|
||||
executionLoop();
|
||||
var executionInterval = setInterval(executionLoop, (Math.floor(Math.random() * 6)+15)*1000);
|
||||
var executionInterval = setInterval(executionLoop, 10000);
|
||||
});
|
65
public/js/text.js
Normal file
65
public/js/text.js
Normal file
|
@ -0,0 +1,65 @@
|
|||
// VARS
|
||||
// Vitesses
|
||||
var vitesseTexte = 4000; // En millisecondes
|
||||
|
||||
// Coordonnées
|
||||
var pointInitial = '100%';
|
||||
var pointDestination = '-=2000px';
|
||||
|
||||
// Messages
|
||||
var messageDiv = '#text-content div'
|
||||
var messages = [];
|
||||
var indexMessages = 0;
|
||||
|
||||
var fontSize;
|
||||
var fontSizeLength;
|
||||
|
||||
// FUNCS
|
||||
function animerTexte(){
|
||||
// Diriger le texte vers la droite jusqu'à `pointDestination'.
|
||||
// Récursivement reset la position du texte.
|
||||
$(messageDiv).animate({left: pointDestination}, vitesseTexte, 'linear', resetTexte);
|
||||
}
|
||||
|
||||
function resetTexte(){
|
||||
// Remettre le texte au point initial
|
||||
$(messageDiv).css('left', pointInitial);
|
||||
|
||||
// Récursivement animer le texte
|
||||
animerTexte();
|
||||
}
|
||||
|
||||
function updateTexte(){
|
||||
var message = messages[indexMessages];
|
||||
|
||||
$(messageDiv).text(message);
|
||||
|
||||
augmenterIndex();
|
||||
}
|
||||
|
||||
function augmenterIndex() {
|
||||
if (indexMessages >= messages.length - 1) {
|
||||
indexMessages = 0;
|
||||
} else {
|
||||
indexMessages ++;
|
||||
}
|
||||
}
|
||||
|
||||
function initialiserMessages(){
|
||||
fontSize = $(messageDiv).css('fontSize');
|
||||
fontSizeLength = fontSize.length;
|
||||
|
||||
// TODO Importer messages
|
||||
messages = ['hello, world!'];
|
||||
|
||||
|
||||
// TODO pointDestination = -1 * longueurMessage
|
||||
//pointDestination = messages[0].width * fontSize.substring(fontSize.length-2);
|
||||
pointDestination = messages[indexMessages].width;
|
||||
}
|
||||
|
||||
// EXEC
|
||||
$(function(){
|
||||
//initialiserMessages();
|
||||
resetTexte();
|
||||
});
|
20
response.go
20
response.go
|
@ -1,20 +0,0 @@
|
|||
package babillard
|
||||
|
||||
type ErrorResponse struct {
|
||||
Error string
|
||||
}
|
||||
|
||||
type MessageResponse struct {
|
||||
Message string
|
||||
}
|
||||
|
||||
type ContenuResponse struct {
|
||||
Data struct {
|
||||
Contenu []string
|
||||
}
|
||||
}
|
||||
|
||||
func NewContenuResponse(fichiers []string) (response ContenuResponse) {
|
||||
response.Data.Contenu = fichiers
|
||||
return
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
embed {
|
||||
max-width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
#contenu {
|
||||
background-color: black;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
<html>
|
||||
|
||||
<head>
|
||||
<title>AGECEM | babillard</title>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
|
||||
<link rel="stylesheet" href="/public/css/style.css">
|
||||
<!--<script src="/public/js/carousel.js"></script>--!>
|
||||
<script src="/public/js/slider.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="contenu">
|
||||
<embed id="image"/>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -1,32 +0,0 @@
|
|||
// 2025-02 Victor Lacasse-Beaudoin, AGECEM
|
||||
//
|
||||
// Carousel d'images à afficher sur https://babillard.agecem.com/ ainsi que
|
||||
// sur la télévision du Centre-Multi Services de l'AGECEM.
|
||||
//
|
||||
// WIP
|
||||
async function getContenu() {
|
||||
const url = "/api/v2/contenu/";
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
//TODO start interval then refresh page to try again
|
||||
throw new Error(`Response status: ${response.status}`);
|
||||
}
|
||||
json = await response.json();
|
||||
console.log("[i] got contenu");
|
||||
console.log(json);
|
||||
|
||||
//startCarousel(json);
|
||||
}
|
||||
catch (error) {
|
||||
console.error(error.message);
|
||||
}
|
||||
}
|
||||
|
||||
function run(){
|
||||
console.log("[i] run");
|
||||
|
||||
getContenu();
|
||||
}
|
||||
|
||||
run();
|
Loading…
Add table
Reference in a new issue