Major file restructuring

This commit is contained in:
Vegard Berg 2023-09-11 23:26:50 +02:00
parent 6abacd4bed
commit cae11a2e19
23 changed files with 897 additions and 449 deletions

31
config.go Normal file
View File

@ -0,0 +1,31 @@
package main
import (
"github.com/sirupsen/logrus"
"github.com/spf13/viper"
)
func initConfig() error {
viper.SetDefault("host", "[::]")
viper.SetDefault("port", 8080)
viper.SetDefault("db_path", "bin.db")
viper.SetDefault("smtp.enabled", false)
viper.SetDefault("user.registration_enabled", false)
viper.SetConfigName("config")
viper.SetConfigType("toml")
viper.AddConfigPath("/etc/bin")
viper.AddConfigPath("$HOME/.config/bin")
viper.AddConfigPath("$XDG_CONFIG_HOME/bin")
viper.AddConfigPath(".")
if err := viper.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
logrus.Warnln("No config file found.")
} else {
logrus.WithError(err).Errorln("Config file found but could not read it.")
}
}
return nil
}

73
controllers/bin.go Normal file
View File

@ -0,0 +1,73 @@
package controllers
import (
"fmt"
"net/http"
"git.myrkvi.com/myrkvi/bin/global"
"git.myrkvi.com/myrkvi/bin/models"
"git.myrkvi.com/myrkvi/bin/utils"
"git.myrkvi.com/myrkvi/bin/views/components"
"git.myrkvi.com/myrkvi/bin/views/pages"
"github.com/labstack/echo/v4"
"github.com/sirupsen/logrus"
"gorm.io/gorm"
)
func GetBinHandler(c echo.Context) error {
file := models.File{}
result := global.DB.Where("page_key = ?", c.Param("id")).First(&file)
if result.Error == gorm.ErrRecordNotFound {
logrus.WithError(result.Error).Errorln("no file")
}
if result.Error != nil {
logrus.WithError(result.Error).Errorln("server error")
}
file.AdminKey = c.QueryParam("delcode")
return utils.RenderComponents(c, http.StatusOK,
pages.BinFull(file),
)
}
func DeleteBinHandler(c echo.Context) error {
code := c.Param("id")
adminCode := c.FormValue("adminKey")
if adminCode == "" {
return utils.RenderErrorToast(c, "deletion key cannot be empty")
}
file := models.File{}
result := global.DB.Where("page_key = ?", code).First(&file)
if result.Error != nil {
return utils.RenderErrorToast(c, "file not found")
}
if adminCode != file.AdminKey {
return utils.RenderErrorToast(c, "invalid deletion key")
}
global.DB.Delete(&file)
if file.Filename == "" {
file.Filename = "file"
}
utils.SetHeader(c, "HX-Push", "/")
return utils.RenderComponents(
c,
http.StatusOK,
pages.IndexPartial(),
components.SwapOOB(
"beforeend:#toast",
components.ToastSuccess(fmt.Sprintf("%s deleted", file.Filename)),
),
components.NavMenu(models.DefaultMenu, 0, true),
components.SetTitle(""),
)
}

View File

@ -0,0 +1,19 @@
package controllers
import (
"net/http"
"git.myrkvi.com/myrkvi/bin/utils"
"git.myrkvi.com/myrkvi/bin/views/partials"
"github.com/labstack/echo/v4"
)
func GetPartialUploadHandler(c echo.Context) error {
c.Response().Header().Add("HX-Push", "/new")
return utils.RenderComponents(c, http.StatusOK, partials.NewFileUpload())
}
func GetPartialTextHandler(c echo.Context) error {
c.Response().Header().Add("HX-Push", "/new?text")
return utils.RenderComponents(c, http.StatusOK, partials.NewTextSubmit())
}

17
controllers/index.go Normal file
View File

@ -0,0 +1,17 @@
package controllers
import (
"net/http"
"git.myrkvi.com/myrkvi/bin/utils"
"git.myrkvi.com/myrkvi/bin/views/pages"
"github.com/labstack/echo/v4"
"github.com/sirupsen/logrus"
)
func IndexHandler(c echo.Context) error {
id := c.Param("id")
logrus.Infof("id is '%s'", id)
return utils.RenderComponents(c, http.StatusOK, pages.IndexFull())
}

82
controllers/new.go Normal file
View File

@ -0,0 +1,82 @@
package controllers
import (
"fmt"
"io"
"mime/multipart"
"net/http"
"git.myrkvi.com/myrkvi/bin/global"
"git.myrkvi.com/myrkvi/bin/models"
"git.myrkvi.com/myrkvi/bin/utils"
"git.myrkvi.com/myrkvi/bin/views/components"
"git.myrkvi.com/myrkvi/bin/views/pages"
"github.com/alecthomas/chroma/lexers"
"github.com/labstack/echo/v4"
)
func GetNewHandler(c echo.Context) error {
values := c.QueryParams()
wantsText := values.Has("text")
return utils.RenderComponents(c, http.StatusOK, pages.NewFull(wantsText))
}
func PostNewHandler(c echo.Context) error {
file, err := c.FormFile("file")
text := c.FormValue("text")
name := c.FormValue("name")
description := c.FormValue("description")
lang := c.FormValue("lang")
if (file == nil || err != nil) && text == "" {
return utils.RenderErrorToast(c, "file or text must be provided")
}
code, adminCode, err := utils.GenerateCodes()
if err != nil {
return utils.RenderErrorToast(c, "server-side error occurred")
}
if file != nil {
text, err = getTextFromFile(file)
if name == "" {
name = file.Filename
}
if err != nil {
return utils.RenderErrorToast(c, "server-side error occurred")
}
}
// Determine language from file extension if not set.
if lang == "" {
lexer := lexers.Match(name)
if lexer != nil {
lang = lexer.Config().Name
}
}
createdFile, err := models.CreateNewBin(global.DB, text, name, description, lang, code, adminCode)
if err != nil {
return utils.RenderErrorToast(c, "server-side error occurred")
}
utils.SetHeader(c, "HX-Push", fmt.Sprintf("/b/%s", code))
return utils.RenderComponents(c, http.StatusOK,
pages.BinPartial(createdFile),
components.SetTitle(file.Filename),
)
}
func getTextFromFile(fileHeader *multipart.FileHeader) (text string, err error) {
f, err := fileHeader.Open()
if err != nil {
return
}
b, err := io.ReadAll(f)
if err != nil {
return
}
text = string(b)
return
}

5
global/global.go Normal file
View File

@ -0,0 +1,5 @@
package global
import "gorm.io/gorm"
var DB *gorm.DB

13
go.mod
View File

@ -29,7 +29,9 @@ require (
github.com/goccy/go-json v0.10.2 // indirect github.com/goccy/go-json v0.10.2 // indirect
github.com/gohugoio/hugo v0.118.2 // indirect github.com/gohugoio/hugo v0.118.2 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/google/uuid v1.3.0 // indirect github.com/google/uuid v1.3.1 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect github.com/jinzhu/now v1.1.5 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect
@ -37,9 +39,11 @@ require (
github.com/labstack/echo/v4 v4.11.1 // indirect github.com/labstack/echo/v4 v4.11.1 // indirect
github.com/labstack/gommon v0.4.0 // indirect github.com/labstack/gommon v0.4.0 // indirect
github.com/leodido/go-urn v1.2.4 // indirect github.com/leodido/go-urn v1.2.4 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml v1.9.5 // indirect
@ -47,6 +51,12 @@ require (
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/sirupsen/logrus v1.9.3 // indirect github.com/sirupsen/logrus v1.9.3 // indirect
github.com/spf13/afero v1.9.5 // indirect github.com/spf13/afero v1.9.5 // indirect
github.com/spf13/cast v1.5.1 // indirect
github.com/spf13/cobra v1.7.0 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.16.0 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
github.com/tdewolff/parse/v2 v2.6.8 // indirect github.com/tdewolff/parse/v2 v2.6.8 // indirect
github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569 // indirect github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
@ -64,6 +74,7 @@ require (
golang.org/x/text v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect
golang.org/x/time v0.3.0 // indirect golang.org/x/time v0.3.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
gorm.io/gorm v1.25.4 // indirect gorm.io/gorm v1.25.4 // indirect
modernc.org/libc v1.22.5 // indirect modernc.org/libc v1.22.5 // indirect

27
go.sum
View File

@ -69,6 +69,7 @@ github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnht
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cosmtrek/air v1.45.0 h1:JwNWE61dXW2SmGDy8bB28KTX+v0KFh+xqaF4kFJav6U= github.com/cosmtrek/air v1.45.0 h1:JwNWE61dXW2SmGDy8bB28KTX+v0KFh+xqaF4kFJav6U=
github.com/cosmtrek/air v1.45.0/go.mod h1:yOz9vy7edZ75KRN9+Ofqwm3OU0wuv4Csc+ikMeZxxS8= github.com/cosmtrek/air v1.45.0/go.mod h1:yOz9vy7edZ75KRN9+Ofqwm3OU0wuv4Csc+ikMeZxxS8=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
@ -172,13 +173,19 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
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 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
@ -203,6 +210,8 @@ github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8
github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= 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-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
@ -212,6 +221,8 @@ github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APP
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
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/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@ -232,13 +243,25 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM= github.com/spf13/afero v1.9.5 h1:stMpOSZFs//0Lv29HduCmli3GUfpFoF3Y1Q/aXj/wVM=
github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ= github.com/spf13/afero v1.9.5/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.16.0 h1:rGGH0XDZhdUOryiDWjmIvUSWpbNqisK8Wk0Vyefw8hc=
github.com/spf13/viper v1.16.0/go.mod h1:yg78JgCJcbrQOvV9YLXgkLaZqUidkY9K+Dd1FofRzQg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
@ -249,6 +272,8 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
github.com/tdewolff/parse/v2 v2.6.8 h1:mhNZXYCx//xG7Yq2e/kVLNZw4YfYmeHbhx+Zc0OvFMA= github.com/tdewolff/parse/v2 v2.6.8 h1:mhNZXYCx//xG7Yq2e/kVLNZw4YfYmeHbhx+Zc0OvFMA=
github.com/tdewolff/parse/v2 v2.6.8/go.mod h1:XHDhaU6IBgsryfdnpzUXBlT6leW/l25yrFBTEb4eIyM= github.com/tdewolff/parse/v2 v2.6.8/go.mod h1:XHDhaU6IBgsryfdnpzUXBlT6leW/l25yrFBTEb4eIyM=
github.com/tdewolff/test v1.0.9/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= github.com/tdewolff/test v1.0.9/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
@ -603,6 +628,8 @@ google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -1,142 +0,0 @@
package main
import (
"fmt"
"net/http"
"github.com/alecthomas/chroma/lexers"
"github.com/labstack/echo/v4"
"github.com/sirupsen/logrus"
"gorm.io/gorm"
)
func indexHandler(c echo.Context) error {
id := c.Param("id")
logrus.Infof("id is '%s'", id)
return RenderComponent(c, http.StatusOK, indexFull())
}
// ░█▀█░█▀▀░█░█░░░░░█░░░█▀▀░█░█░█▀▄░█▄█░▀█▀░▀█▀░░░█▀█░█▀█░█▀▀░█▀▀
// ░█░█░█▀▀░█▄█░░░▄▀░░░░▀▀█░█░█░█▀▄░█░█░░█░░░█░░░░█▀▀░█▀█░█░█░█▀▀
// ░▀░▀░▀▀▀░▀░▀░░░▀░░░░░▀▀▀░▀▀▀░▀▀░░▀░▀░▀▀▀░░▀░░░░▀░░░▀░▀░▀▀▀░▀▀▀
func getNewHandler(c echo.Context) error {
values := c.QueryParams()
wantsText := values.Has("text")
return RenderComponent(c, http.StatusOK, newFull(wantsText))
}
func postNewHandler(c echo.Context) error {
file, err := c.FormFile("file")
text := c.FormValue("text")
wantsText := c.FormValue("wantsText") == "true"
name := c.FormValue("name")
description := c.FormValue("description")
lang := c.FormValue("lang")
if (file == nil || err != nil) && text == "" {
/* return RenderComponent(c, http.StatusOK,
CombineTempls(
newPartial(wantsText),
ErrorMessage("file or text must be provided", "error-span"),
),
) */
return RenderErrorToast(c, "File or text must be provided.")
}
code, adminCode, err := generateCodes()
if err != nil {
return RenderComponent(c, http.StatusOK,
CombineTempls(
newPartial(wantsText),
ErrorMessage("server-side error occurred", "error-span"),
),
)
}
if file != nil {
text, err = getTextFromFile(file)
if name == "" {
name = file.Filename
}
if err != nil {
return RenderComponent(c, http.StatusOK,
CombineTempls(
newPartial(wantsText),
ErrorMessage("server-side error occurred", "error-span"),
),
)
}
}
// Determine language from file extension if not set.
if lang == "" {
lexer := lexers.Match(name)
if lexer != nil {
lang = lexer.Config().Name
}
}
createdFile, err := createNewBin(text, name, description, lang, code, adminCode)
if err != nil {
return RenderComponent(c, http.StatusOK,
CombineTempls(
newPartial(wantsText),
ErrorMessage("server-side error occurred", "error-span"),
),
)
}
c.Response().Header().Add("HX-Push", fmt.Sprintf("/b/%s", code))
return RenderComponent(c, http.StatusOK,
binPartial(createdFile),
)
}
// ░█▀▄░▀█▀░█▀█░░░░░█░░░█▀▀░▀█▀░█░░░█▀▀░█▀▀
// ░█▀▄░░█░░█░█░░░▄▀░░░░█▀▀░░█░░█░░░█▀▀░▀▀█
// ░▀▀░░▀▀▀░▀░▀░░░▀░░░░░▀░░░▀▀▀░▀▀▀░▀▀▀░▀▀▀
// Individual pages of uploaded files.
func getBinHandler(c echo.Context) error {
file := File{}
result := db.Where("page_key = ?", c.Param("id")).First(&file)
if result.Error == gorm.ErrRecordNotFound {
logrus.WithError(result.Error).Errorln("no file")
}
if result.Error != nil {
logrus.WithError(result.Error).Errorln("server error")
}
file.AdminKey = c.QueryParam("delcode")
return RenderComponent(c, http.StatusOK,
binFull(file),
)
}
func deleteBinHandler(c echo.Context) error {
code := c.Param("id")
adminCode := c.FormValue("adminKey")
if adminCode == "" {
return RenderErrorToast(c, "deletion key cannot be empty")
}
file := File{}
result := db.Where("page_key = ?", code).First(&file)
if result.Error != nil {
return RenderErrorToast(c, "file not found")
}
if adminCode != file.AdminKey {
return RenderErrorToast(c, "invalid deletion key")
}
db.Delete(&file)
return c.HTML(http.StatusOK, "<h1>file deleted!</h1>")
}

View File

@ -1,17 +0,0 @@
package main
import (
"net/http"
"github.com/labstack/echo/v4"
)
func getPartialUploadHandler(c echo.Context) error {
c.Response().Header().Add("HX-Push", "/new")
return RenderComponent(c, http.StatusOK, newFileUpload())
}
func getPartialTextHandler(c echo.Context) error {
c.Response().Header().Add("HX-Push", "/new?text")
return RenderComponent(c, http.StatusOK, newTextSubmit())
}

53
main.go
View File

@ -1,34 +1,31 @@
package main package main
import ( import (
"io" "fmt"
"mime/multipart"
"git.myrkvi.com/myrkvi/bin/controllers"
"git.myrkvi.com/myrkvi/bin/global"
"git.myrkvi.com/myrkvi/bin/models"
"github.com/glebarez/sqlite" "github.com/glebarez/sqlite"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
"github.com/labstack/echo/v4/middleware" "github.com/labstack/echo/v4/middleware"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"github.com/spf13/viper"
prefixed "github.com/x-cray/logrus-prefixed-formatter" prefixed "github.com/x-cray/logrus-prefixed-formatter"
"gorm.io/gorm" "gorm.io/gorm"
) )
type MenuItem struct {
label string
href string
}
var db *gorm.DB
func main() { func main() {
logrus.SetLevel(logrus.DebugLevel) logrus.SetLevel(logrus.DebugLevel)
logrus.SetFormatter(&prefixed.TextFormatter{ logrus.SetFormatter(&prefixed.TextFormatter{
FullTimestamp: true, FullTimestamp: true,
}) })
logrus.Infoln("Application started.") logrus.Infoln("Application started.")
initConfig()
db_string := "bin.db" db_string := "bin.db"
var err error var err error
db, err = gorm.Open(sqlite.Open(db_string), &gorm.Config{}) global.DB, err = gorm.Open(sqlite.Open(db_string), &gorm.Config{})
if err != nil { if err != nil {
logrus.WithError(err).Fatalln("Could not open database connection.") logrus.WithError(err).Fatalln("Could not open database connection.")
} }
@ -36,7 +33,7 @@ func main() {
"db connection": db_string, "db connection": db_string,
}).Infoln("Connected to database.") }).Infoln("Connected to database.")
databaseMigrations(db) models.DatabaseMigrations(global.DB)
e := echo.New() e := echo.New()
e.Debug = false e.Debug = false
@ -58,29 +55,21 @@ func main() {
e.Static("/static", "static") e.Static("/static", "static")
e.GET("/", indexHandler) e.GET("/", controllers.IndexHandler)
e.GET("/new", getNewHandler) e.GET("/new", controllers.GetNewHandler)
e.POST("/new", postNewHandler) e.POST("/new", controllers.PostNewHandler)
e.GET("/b/:id", getBinHandler) e.GET("/b/:id", controllers.GetBinHandler)
e.POST("/b/:id/delete", deleteBinHandler) e.POST("/b/:id/delete", controllers.DeleteBinHandler)
partial := e.Group("/partial") partial := e.Group("/partial")
new := partial.Group("/new") new := partial.Group("/new")
new.GET("/upload", getPartialUploadHandler) new.GET("/upload", controllers.GetPartialUploadHandler)
new.GET("/text", getPartialTextHandler) new.GET("/text", controllers.GetPartialTextHandler)
e.Logger.Fatal(e.Start(":8080"))
}
func getTextFromFile(fileHeader *multipart.FileHeader) (text string, err error) { listenAt := fmt.Sprintf(
f, err := fileHeader.Open() "%s:%d",
if err != nil { viper.GetString("host"),
return viper.GetUint16("port"),
} )
b, err := io.ReadAll(f) e.Logger.Fatal(e.Start(listenAt))
if err != nil {
return
}
text = string(b)
return
} }

View File

@ -1,49 +0,0 @@
package main
import (
"github.com/sirupsen/logrus"
"gorm.io/gorm"
)
type File struct {
gorm.Model
PageKey string `gorm:"index:idx_pagekey,unique"`
AdminKey string `gorm:"index:idx_adminkey"`
// The "virtual" filename.
Filename string
// The description of the file submission.
Description string
Language string
// The contents of the file must be valid text.
Data string
}
func databaseMigrations(db *gorm.DB) {
logrus.Infoln("Running database migrations.")
err := db.AutoMigrate(&File{})
if err != nil {
logrus.WithError(err).Fatalln("Failed to run database migration.")
}
logrus.Infoln("Migrations ran successfully.")
}
func createNewBin(text, name, description, language, key, adminKey string) (File, error) {
bin := File{
Filename: name,
Description: description,
Language: language,
PageKey: key,
AdminKey: adminKey,
Data: text,
}
result := db.Create(&bin)
if result.Error != nil {
return File{}, result.Error
}
return bin, nil
}

21
models/menuitem.go Normal file
View File

@ -0,0 +1,21 @@
package models
type MenuItem struct {
Label string
Href string
}
var DefaultMenu []MenuItem = []MenuItem{
{
Label: "home",
Href: "/",
},
{
Label: "new",
Href: "/new",
},
{
Label: "about",
Href: "/about",
},
}

80
models/models.go Normal file
View File

@ -0,0 +1,80 @@
package models
import (
"reflect"
"github.com/sirupsen/logrus"
"golang.org/x/crypto/bcrypt"
"gorm.io/gorm"
)
type File struct {
gorm.Model
PageKey string `gorm:"index:idx_pagekey,unique;unique"`
AdminKey string `gorm:"index:idx_adminkey"`
// The "virtual" filename.
Filename string
// The description of the file submission.
Description string
Language string
// The contents of the file must be valid text.
Data string
UserID uint
User User
}
type User struct {
gorm.Model
DisplayName string
Email string `gorm:"unique"`
Salt string
HashedPassword []byte
}
func (u *User) MatchesPassword(password string) bool {
combined := append([]byte(u.Salt), []byte(password)...)
return bcrypt.CompareHashAndPassword(u.HashedPassword, []byte(combined)) == nil
}
func DatabaseMigrations(db *gorm.DB) {
tables := []interface{}{
File{},
User{},
}
logrus.Infoln("Running database migrations.")
for _, table := range tables {
name := reflect.TypeOf(table).Name()
err := db.AutoMigrate(&table)
if err != nil {
logrus.WithError(err).WithField("table", name).Fatalln("Migration failed.")
} else {
logrus.WithField("table", name).Infoln("Migration successful.")
}
}
logrus.Infoln("Migrations ran successfully.")
}
func CreateNewBin(db *gorm.DB, text, name, description, language, key, adminKey string) (File, error) {
bin := File{
Filename: name,
Description: description,
Language: language,
PageKey: key,
AdminKey: adminKey,
Data: text,
}
result := db.Create(&bin)
if result.Error != nil {
return File{}, result.Error
}
return bin, nil
}

30
models/models_test.go Normal file
View File

@ -0,0 +1,30 @@
package models
import (
"testing"
"golang.org/x/crypto/bcrypt"
)
func TestHashPassword(t *testing.T) {
salt := "BlahHa!?591"
password := "MyPassword123"
combined := append([]byte(salt), []byte(password)...)
hashed, err := bcrypt.GenerateFromPassword(combined, 10)
if err != nil {
t.Fatalf("Failed to generate password: %v\n", err)
}
user := User{
Salt: salt,
HashedPassword: hashed[:],
}
matches := user.MatchesPassword(password)
if !matches {
t.Fatal("Password does not match")
} else {
t.Log("Password matches")
}
}

View File

@ -642,8 +642,8 @@ video {
margin-right: 1rem; margin-right: 1rem;
} }
.mt-12 { .mt-4 {
margin-top: 3rem; margin-top: 1rem;
} }
.block { .block {
@ -775,8 +775,12 @@ video {
border-bottom-width: 4px; border-bottom-width: 4px;
} }
.border-t-4 { .border-r-4 {
border-top-width: 4px; border-right-width: 4px;
}
.border-t-0 {
border-top-width: 0px;
} }
.border-amber-300 { .border-amber-300 {
@ -789,6 +793,11 @@ video {
border-color: rgb(0 0 0 / var(--tw-border-opacity)); border-color: rgb(0 0 0 / var(--tw-border-opacity));
} }
.border-emerald-600 {
--tw-border-opacity: 1;
border-color: rgb(5 150 105 / var(--tw-border-opacity));
}
.border-rose-600 { .border-rose-600 {
--tw-border-opacity: 1; --tw-border-opacity: 1;
border-color: rgb(225 29 72 / var(--tw-border-opacity)); border-color: rgb(225 29 72 / var(--tw-border-opacity));
@ -799,6 +808,11 @@ video {
background-color: rgb(255 251 235 / var(--tw-bg-opacity)); background-color: rgb(255 251 235 / var(--tw-bg-opacity));
} }
.bg-emerald-400 {
--tw-bg-opacity: 1;
background-color: rgb(52 211 153 / var(--tw-bg-opacity));
}
.bg-rose-400 { .bg-rose-400 {
--tw-bg-opacity: 1; --tw-bg-opacity: 1;
background-color: rgb(251 113 133 / var(--tw-bg-opacity)); background-color: rgb(251 113 133 / var(--tw-bg-opacity));
@ -809,6 +823,11 @@ video {
padding-right: 0.25rem; padding-right: 0.25rem;
} }
.px-2 {
padding-left: 0.5rem;
padding-right: 0.5rem;
}
.px-4 { .px-4 {
padding-left: 1rem; padding-left: 1rem;
padding-right: 1rem; padding-right: 1rem;
@ -961,6 +980,15 @@ video {
margin-right: 6rem; margin-right: 6rem;
} }
.sm\:my-2 {
margin-top: 0.5rem;
margin-bottom: 0.5rem;
}
.sm\:mt-12 {
margin-top: 3rem;
}
.sm\:grid-cols-3 { .sm\:grid-cols-3 {
grid-template-columns: repeat(3, minmax(0, 1fr)); grid-template-columns: repeat(3, minmax(0, 1fr));
} }
@ -968,6 +996,19 @@ video {
.sm\:flex-row { .sm\:flex-row {
flex-direction: row; flex-direction: row;
} }
.sm\:border-r-0 {
border-right-width: 0px;
}
.sm\:border-t-4 {
border-top-width: 4px;
}
.sm\:px-0 {
padding-left: 0px;
padding-right: 0px;
}
} }
@media (min-width: 768px) { @media (min-width: 768px) {
@ -975,11 +1016,6 @@ video {
grid-column: span 4 / span 4; grid-column: span 4 / span 4;
} }
.md\:mx-2 {
margin-left: 0.5rem;
margin-right: 0.5rem;
}
.md\:mx-32 { .md\:mx-32 {
margin-left: 8rem; margin-left: 8rem;
margin-right: 8rem; margin-right: 8rem;

View File

@ -1,25 +1,35 @@
package main package utils
import ( import (
"context" "context"
"git.myrkvi.com/myrkvi/bin/views/components"
"github.com/a-h/templ" "github.com/a-h/templ"
"github.com/labstack/echo/v4" "github.com/labstack/echo/v4"
"github.com/teris-io/shortid" "github.com/teris-io/shortid"
) )
func RenderComponent(c echo.Context, status int, component templ.Component) error { // func RenderComponent(c echo.Context, status int, component templ.Component) error {
// w := c.Response().Writer
// c.Response().Status = status
// return component.Render(context.Background(), w)
// }
func RenderComponents(c echo.Context, status int, comps ...templ.Component) error {
w := c.Response().Writer w := c.Response().Writer
c.Response().Status = status c.Response().Status = status
return component.Render(context.Background(), w) combine := components.CombineTempls(comps...)
return combine.Render(context.Background(), w)
} }
func RenderErrorToast(c echo.Context, message string) error { func RenderErrorToast(c echo.Context, message string) error {
SetHeader(c, "HX-Retarget", "#toast") SetHeader(c, "HX-Retarget", "#toast")
SetHeader(c, "HX-Reswap", "beforeend") SetHeader(c, "HX-Reswap", "beforeend")
return RenderComponent(c, 200, ToastError(message)) return RenderComponents(c, 200, components.ToastError(message))
} }
func AddHeader(c echo.Context, key, value string) { func AddHeader(c echo.Context, key, value string) {
@ -34,7 +44,7 @@ func SetContentType(c echo.Context, value string) {
SetHeader(c, "Content-Type", value) SetHeader(c, "Content-Type", value)
} }
func generateCodes() (code string, adminCode string, err error) { func GenerateCodes() (code string, adminCode string, err error) {
code, err = shortid.Generate() code, err = shortid.Generate()
if err != nil { if err != nil {
return return

View File

@ -1,6 +1,9 @@
package main package components
import "github.com/alecthomas/chroma/lexers" import (
"github.com/alecthomas/chroma/lexers"
"git.myrkvi.com/myrkvi/bin/models"
)
func getLanguages() []string { func getLanguages() []string {
names := lexers.Names(false) names := lexers.Names(false)
@ -9,7 +12,7 @@ func getLanguages() []string {
return names return names
} }
templ chooseSyntax(name string) { templ ChooseSyntax(name string) {
<select class="max-w-full bg-amber-50" name={ name } id={ name }> <select class="max-w-full bg-amber-50" name={ name } id={ name }>
for i, lang := range getLanguages() { for i, lang := range getLanguages() {
if i == 0 { if i == 0 {
@ -21,7 +24,7 @@ templ chooseSyntax(name string) {
</select> </select>
} }
templ fileUpload(text, name, id string) { templ FileUpload(text, name, id string) {
<span> <span>
<label <label
role="button" role="button"
@ -55,7 +58,7 @@ templ fileUpload(text, name, id string) {
</span> </span>
} }
templ boostButton(label, to string) { templ BoostButton(label, to string) {
<span hx-boost="true"> <span hx-boost="true">
<a <a
role="button" role="button"
@ -72,7 +75,7 @@ templ boostButton(label, to string) {
</span> </span>
} }
templ submitFormButton(label string) { templ SubmitFormButton(label string) {
<input <input
type="submit" type="submit"
value={ label } value={ label }
@ -86,7 +89,7 @@ templ submitFormButton(label string) {
/> />
} }
templ NavMenu(items []MenuItem, current int, swapOob bool) { templ NavMenu(items []models.MenuItem, current int, swapOob bool) {
<nav <nav
id="page-nav" id="page-nav"
class="flex flex-col sm:flex-row justify-around" class="flex flex-col sm:flex-row justify-around"
@ -96,24 +99,36 @@ templ NavMenu(items []MenuItem, current int, swapOob bool) {
hx-boost="true"> hx-boost="true">
for i, item := range items { for i, item := range items {
if i == current { if i == current {
<span class="mx-4 md:mx-2 my-2 current-page border-t-4 border-black cursor-pointer"> <span class="px-2 sm:px-0 sm:mx-2 sm:my-2
<b>{ item.label }</b> border-t-0 border-r-4
sm:border-t-4 sm:border-r-0
border-black cursor-pointer">
<b>{ item.Label }</b>
</span> </span>
} else { } else {
<a <a
class="mx-4 sm:mx-2 my-2 border-t-4 border-amber-300" class="px-2 sm:px-0 sm:mx-2 my-2
href={ templ.URL(item.href) } border-t-0 border-r-4
sm:border-t-4 sm:border-r-0
border-amber-300"
href={ templ.URL(item.Href) }
> >
{ item.label } { item.Label }
</a> </a>
} }
} }
</nav> </nav>
} }
templ CombineTempls(top, bottom templ.Component) { // templ CombineTempls(top, bottom templ.Component) {
{! top } // {! top }
{! bottom } // {! bottom }
// }
templ CombineTempls(comps ...templ.Component) {
for _, comp := range comps {
{! comp }
}
} }
templ ErrorMessage(msg, id string) { templ ErrorMessage(msg, id string) {
@ -145,3 +160,39 @@ templ ToastError(message string) {
{ message } { message }
</div> </div>
} }
templ ToastSuccess(message string) {
<div
class="relative px-4 py-2 bg-emerald-400 opacity-0
border border-emerald-600 rounded-lg m-1"
_="init transition my opacity to 1 over 250ms"
>
<span
tabindex="0"
role="button" aria-label="Close the toast message"
class="absolute top-0 right-1 cursor-pointer select-none"
_="on click set prnt to my parentElement
then transition element prnt's opacity to 0 over 500ms
then remove my parentElement"
>
<sup>&#x1F7AC;</sup>
</span>
{ message }
</div>
}
templ SwapOOB(swapspec string, component templ.Component) {
<div hx-swap-oob={ swapspec }>
{! component }
</div>
}
templ SetTitle(title string) {
<title id="title" hx-swap-oob="true">
if title == "" {
bin
} else {
{ title } - bin
}
</title>
}

View File

@ -1,6 +1,6 @@
// Code generated by templ@v0.2.316 DO NOT EDIT. // Code generated by templ@v0.2.316 DO NOT EDIT.
package main package components
//lint:file-ignore SA4006 This context is only used if a nested component is present. //lint:file-ignore SA4006 This context is only used if a nested component is present.
@ -9,7 +9,10 @@ import "context"
import "io" import "io"
import "bytes" import "bytes"
import "github.com/alecthomas/chroma/lexers" import (
"git.myrkvi.com/myrkvi/bin/models"
"github.com/alecthomas/chroma/lexers"
)
func getLanguages() []string { func getLanguages() []string {
names := lexers.Names(false) names := lexers.Names(false)
@ -18,7 +21,7 @@ func getLanguages() []string {
return names return names
} }
func chooseSyntax(name string) templ.Component { func ChooseSyntax(name string) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) { return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
templBuffer, templIsBuffer := w.(*bytes.Buffer) templBuffer, templIsBuffer := w.(*bytes.Buffer)
if !templIsBuffer { if !templIsBuffer {
@ -93,7 +96,7 @@ func chooseSyntax(name string) templ.Component {
}) })
} }
func fileUpload(text, name, id string) templ.Component { func FileUpload(text, name, id string) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) { return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
templBuffer, templIsBuffer := w.(*bytes.Buffer) templBuffer, templIsBuffer := w.(*bytes.Buffer)
if !templIsBuffer { if !templIsBuffer {
@ -183,7 +186,7 @@ func fileUpload(text, name, id string) templ.Component {
}) })
} }
func boostButton(label, to string) templ.Component { func BoostButton(label, to string) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) { return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
templBuffer, templIsBuffer := w.(*bytes.Buffer) templBuffer, templIsBuffer := w.(*bytes.Buffer)
if !templIsBuffer { if !templIsBuffer {
@ -225,7 +228,7 @@ func boostButton(label, to string) templ.Component {
}) })
} }
func submitFormButton(label string) templ.Component { func SubmitFormButton(label string) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) { return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
templBuffer, templIsBuffer := w.(*bytes.Buffer) templBuffer, templIsBuffer := w.(*bytes.Buffer)
if !templIsBuffer { if !templIsBuffer {
@ -257,7 +260,7 @@ func submitFormButton(label string) templ.Component {
}) })
} }
func NavMenu(items []MenuItem, current int, swapOob bool) templ.Component { func NavMenu(items []models.MenuItem, current int, swapOob bool) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) { return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
templBuffer, templIsBuffer := w.(*bytes.Buffer) templBuffer, templIsBuffer := w.(*bytes.Buffer)
if !templIsBuffer { if !templIsBuffer {
@ -286,11 +289,11 @@ func NavMenu(items []MenuItem, current int, swapOob bool) templ.Component {
} }
for i, item := range items { for i, item := range items {
if i == current { if i == current {
_, err = templBuffer.WriteString("<span class=\"mx-4 md:mx-2 my-2 current-page border-t-4 border-black cursor-pointer\"><b>") _, err = templBuffer.WriteString("<span class=\"px-2 sm:px-0 sm:mx-2 sm:my-2\n border-t-0 border-r-4 \n sm:border-t-4 sm:border-r-0 \n border-black cursor-pointer\"><b>")
if err != nil { if err != nil {
return err return err
} }
var var_12 string = item.label var var_12 string = item.Label
_, err = templBuffer.WriteString(templ.EscapeString(var_12)) _, err = templBuffer.WriteString(templ.EscapeString(var_12))
if err != nil { if err != nil {
return err return err
@ -300,11 +303,11 @@ func NavMenu(items []MenuItem, current int, swapOob bool) templ.Component {
return err return err
} }
} else { } else {
_, err = templBuffer.WriteString("<a class=\"mx-4 sm:mx-2 my-2 border-t-4 border-amber-300\" href=\"") _, err = templBuffer.WriteString("<a class=\"px-2 sm:px-0 sm:mx-2 my-2 \n border-t-0 border-r-4\n sm:border-t-4 sm:border-r-0\n border-amber-300\" href=\"")
if err != nil { if err != nil {
return err return err
} }
var var_13 templ.SafeURL = templ.URL(item.href) var var_13 templ.SafeURL = templ.URL(item.Href)
_, err = templBuffer.WriteString(templ.EscapeString(string(var_13))) _, err = templBuffer.WriteString(templ.EscapeString(string(var_13)))
if err != nil { if err != nil {
return err return err
@ -313,7 +316,7 @@ func NavMenu(items []MenuItem, current int, swapOob bool) templ.Component {
if err != nil { if err != nil {
return err return err
} }
var var_14 string = item.label var var_14 string = item.Label
_, err = templBuffer.WriteString(templ.EscapeString(var_14)) _, err = templBuffer.WriteString(templ.EscapeString(var_14))
if err != nil { if err != nil {
return err return err
@ -335,7 +338,12 @@ func NavMenu(items []MenuItem, current int, swapOob bool) templ.Component {
}) })
} }
func CombineTempls(top, bottom templ.Component) templ.Component { // templ CombineTempls(top, bottom templ.Component) {
// {! top }
// {! bottom }
// }
func CombineTempls(comps ...templ.Component) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) { return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
templBuffer, templIsBuffer := w.(*bytes.Buffer) templBuffer, templIsBuffer := w.(*bytes.Buffer)
if !templIsBuffer { if !templIsBuffer {
@ -348,13 +356,11 @@ func CombineTempls(top, bottom templ.Component) templ.Component {
var_15 = templ.NopComponent var_15 = templ.NopComponent
} }
ctx = templ.ClearChildren(ctx) ctx = templ.ClearChildren(ctx)
err = top.Render(ctx, templBuffer) for _, comp := range comps {
if err != nil { err = comp.Render(ctx, templBuffer)
return err if err != nil {
} return err
err = bottom.Render(ctx, templBuffer) }
if err != nil {
return err
} }
if !templIsBuffer { if !templIsBuffer {
_, err = io.Copy(w, templBuffer) _, err = io.Copy(w, templBuffer)
@ -445,3 +451,135 @@ func ToastError(message string) templ.Component {
return err return err
}) })
} }
func ToastSuccess(message string) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
templBuffer, templIsBuffer := w.(*bytes.Buffer)
if !templIsBuffer {
templBuffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templBuffer)
}
ctx = templ.InitializeContext(ctx)
var_21 := templ.GetChildren(ctx)
if var_21 == nil {
var_21 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
_, err = templBuffer.WriteString("<div class=\"relative px-4 py-2 bg-emerald-400 opacity-0\n border border-emerald-600 rounded-lg m-1\" _=\"init transition my opacity to 1 over 250ms\"><span tabindex=\"0\" role=\"button\" aria-label=\"Close the toast message\" class=\"absolute top-0 right-1 cursor-pointer select-none\" _=\"on click set prnt to my parentElement\n then transition element prnt&#39;s opacity to 0 over 500ms\n then remove my parentElement\"><sup>")
if err != nil {
return err
}
var_22 := `&#x1F7AC;`
_, err = templBuffer.WriteString(var_22)
if err != nil {
return err
}
_, err = templBuffer.WriteString("</sup></span>")
if err != nil {
return err
}
var var_23 string = message
_, err = templBuffer.WriteString(templ.EscapeString(var_23))
if err != nil {
return err
}
_, err = templBuffer.WriteString("</div>")
if err != nil {
return err
}
if !templIsBuffer {
_, err = io.Copy(w, templBuffer)
}
return err
})
}
func SwapOOB(swapspec string, component templ.Component) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
templBuffer, templIsBuffer := w.(*bytes.Buffer)
if !templIsBuffer {
templBuffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templBuffer)
}
ctx = templ.InitializeContext(ctx)
var_24 := templ.GetChildren(ctx)
if var_24 == nil {
var_24 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
_, err = templBuffer.WriteString("<div hx-swap-oob=\"")
if err != nil {
return err
}
_, err = templBuffer.WriteString(templ.EscapeString(swapspec))
if err != nil {
return err
}
_, err = templBuffer.WriteString("\">")
if err != nil {
return err
}
err = component.Render(ctx, templBuffer)
if err != nil {
return err
}
_, err = templBuffer.WriteString("</div>")
if err != nil {
return err
}
if !templIsBuffer {
_, err = io.Copy(w, templBuffer)
}
return err
})
}
func SetTitle(title string) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
templBuffer, templIsBuffer := w.(*bytes.Buffer)
if !templIsBuffer {
templBuffer = templ.GetBuffer()
defer templ.ReleaseBuffer(templBuffer)
}
ctx = templ.InitializeContext(ctx)
var_25 := templ.GetChildren(ctx)
if var_25 == nil {
var_25 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
_, err = templBuffer.WriteString("<title id=\"title\" hx-swap-oob=\"true\">")
if err != nil {
return err
}
if title == "" {
var_26 := `bin`
_, err = templBuffer.WriteString(var_26)
if err != nil {
return err
}
} else {
var var_27 string = title
_, err = templBuffer.WriteString(templ.EscapeString(var_27))
if err != nil {
return err
}
_, err = templBuffer.WriteString(" ")
if err != nil {
return err
}
var_28 := `- bin`
_, err = templBuffer.WriteString(var_28)
if err != nil {
return err
}
}
_, err = templBuffer.WriteString("</title>")
if err != nil {
return err
}
if !templIsBuffer {
_, err = io.Copy(w, templBuffer)
}
return err
})
}

View File

@ -1,8 +1,13 @@
package main package pages
import "fmt" import (
"fmt"
"git.myrkvi.com/myrkvi/bin/models"
"git.myrkvi.com/myrkvi/bin/views/components"
"git.myrkvi.com/myrkvi/bin/views/partials"
)
templ page(inner templ.Component, menu []MenuItem, currentMenu int, args interface{}) { templ page(inner templ.Component, menu []models.MenuItem, currentMenu int, title string) {
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
@ -10,12 +15,16 @@ templ page(inner templ.Component, menu []MenuItem, currentMenu int, args interfa
<script src="/static/htmx.min.js"></script> <script src="/static/htmx.min.js"></script>
<script src="/static/_hyperscript.min.js"></script> <script src="/static/_hyperscript.min.js"></script>
<link rel="stylesheet" href="/static/tailwind.css" /> <link rel="stylesheet" href="/static/tailwind.css" />
<title>bin</title> if title == "" {
<title id="title">bin</title>
} else {
<title id="title">{ title } - bin</title>
}
</head> </head>
<body class="mt-12 mx-16 xl:mx-72 lg:mx-64 md:mx-32 sm:mx-24 bg-amber-50"> <body class="mt-4 sm:mt-12 mx-16 xl:mx-72 lg:mx-64 md:mx-32 sm:mx-24 bg-amber-50">
<header class="flex flex-row justify-between my-16"> <header class="flex flex-row justify-between my-16">
<h1 class="text-5xl">bin</h1> <h1 class="text-5xl">bin</h1>
@NavMenu(menu, currentMenu, false) @components.NavMenu(menu, currentMenu, false)
</header> </header>
<main id="main-content"> <main id="main-content">
{! inner } {! inner }
@ -29,46 +38,30 @@ templ page(inner templ.Component, menu []MenuItem, currentMenu int, args interfa
</html> </html>
} }
var defaultMenu []MenuItem = []MenuItem{ templ IndexFull() {
{
label: "home",
href: "/",
},
{
label: "new",
href: "/new",
},
{
label: "about",
href: "/about",
},
}
templ indexFull() {
@page( @page(
indexPartial(), IndexPartial(),
defaultMenu, models.DefaultMenu,
0, 0,
nil, "",
) )
} }
templ indexPartial() { templ IndexPartial() {
<h2 class="text-xl">Welcome to <i>bin</i></h2> <h2 class="text-xl">Welcome to <i>bin</i></h2>
<p>bin is a simple paste bin.</p> <p>bin is a simple paste bin.</p>
<br /> <br />
@boostButton("new", "/new") @components.BoostButton("new", "/new")
} }
templ newFull(wantsText bool) { templ NewFull(wantsText bool) {
@page( @page(
newPartial(wantsText), NewPartial(wantsText),
defaultMenu, models.DefaultMenu,
1, 1,
nil, "upload",
) )
} }
@ -80,7 +73,7 @@ int main(int argc, char *argv[]) {
return 0; return 0;
}` }`
templ newPartial(wantsText bool) { templ NewPartial(wantsText bool) {
<h2 class="text-xl">submit a new file</h2> <h2 class="text-xl">submit a new file</h2>
<form <form
hx-post="/new" hx-post="/new"
@ -105,7 +98,7 @@ templ newPartial(wantsText bool) {
_="on change set #description's @placeholder to `some stuff about ${my value} ...`" _="on change set #description's @placeholder to `some stuff about ${my value} ...`"
/> />
<label for="lang" class="col-span-1">language:</label> <label for="lang" class="col-span-1">language:</label>
<div class="col-span-2 md:col-span-4">@chooseSyntax("lang")</div> <div class="col-span-2 md:col-span-4">@components.ChooseSyntax("lang")</div>
<label class="col-span-1" for="description">description:</label> <label class="col-span-1" for="description">description:</label>
<textarea <textarea
class="col-span-2 md:col-span-4 resize-none hover:resize justify-self-start class="col-span-2 md:col-span-4 resize-none hover:resize justify-self-start
@ -120,25 +113,25 @@ templ newPartial(wantsText bool) {
/> />
</div> </div>
if wantsText { if wantsText {
@newTextSubmit() @partials.NewTextSubmit()
<input type="text" name="wantsText" hidden value="true" /> <input type="text" name="wantsText" hidden value="true" />
} else { } else {
@newFileUpload() @partials.NewFileUpload()
} }
@submitFormButton("submit") @components.SubmitFormButton("submit")
</form> </form>
} }
templ binFull(file File) { templ BinFull(file models.File) {
@page( @page(
binPartial(file), BinPartial(file),
defaultMenu, models.DefaultMenu,
-1, -1,
nil, file.Filename,
) )
} }
templ binPartial(file File) { templ BinPartial(file models.File) {
<div> <div>
<h1 class="text-xl my-2 inline-block">{ file.Filename } <h1 class="text-xl my-2 inline-block">{ file.Filename }
if file.Language != "" { if file.Language != "" {
@ -152,6 +145,7 @@ templ binPartial(file File) {
class="absolute -bottom-32" class="absolute -bottom-32"
hx-post={ "/b/" + file.PageKey + "/delete" } hx-post={ "/b/" + file.PageKey + "/delete" }
hx-confirm="Are you sure you want to delete this?" hx-confirm="Are you sure you want to delete this?"
hx-target="#main-content"
> >
<input <input
name="adminKey" name="adminKey"
@ -164,7 +158,7 @@ templ binPartial(file File) {
placeholder="deletion key" placeholder="deletion key"
value={ file.AdminKey } value={ file.AdminKey }
/> />
@submitFormButton("delete") @components.SubmitFormButton("delete")
if file.AdminKey != "" { if file.AdminKey != "" {
<a class="text-blue-500 mx-4" href={ templ.URL(fmt.Sprintf("/b/%s?delcode=%s", file.PageKey, file.AdminKey))}><sup>permalink with deletion key</sup></a> <a class="text-blue-500 mx-4" href={ templ.URL(fmt.Sprintf("/b/%s?delcode=%s", file.PageKey, file.AdminKey))}><sup>permalink with deletion key</sup></a>
} }

View File

@ -1,6 +1,6 @@
// Code generated by templ@v0.2.316 DO NOT EDIT. // Code generated by templ@v0.2.316 DO NOT EDIT.
package main package pages
//lint:file-ignore SA4006 This context is only used if a nested component is present. //lint:file-ignore SA4006 This context is only used if a nested component is present.
@ -9,9 +9,14 @@ import "context"
import "io" import "io"
import "bytes" import "bytes"
import "fmt" import (
"fmt"
"git.myrkvi.com/myrkvi/bin/models"
"git.myrkvi.com/myrkvi/bin/views/components"
"git.myrkvi.com/myrkvi/bin/views/partials"
)
func page(inner templ.Component, menu []MenuItem, currentMenu int, args interface{}) templ.Component { func page(inner templ.Component, menu []models.MenuItem, currentMenu int, title string) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) { return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
templBuffer, templIsBuffer := w.(*bytes.Buffer) templBuffer, templIsBuffer := w.(*bytes.Buffer)
if !templIsBuffer { if !templIsBuffer {
@ -42,21 +47,54 @@ func page(inner templ.Component, menu []MenuItem, currentMenu int, args interfac
if err != nil { if err != nil {
return err return err
} }
_, err = templBuffer.WriteString("</script><link rel=\"stylesheet\" href=\"/static/tailwind.css\"><title>") _, err = templBuffer.WriteString("</script><link rel=\"stylesheet\" href=\"/static/tailwind.css\">")
if err != nil { if err != nil {
return err return err
} }
var_4 := `bin` if title == "" {
_, err = templBuffer.WriteString(var_4) _, err = templBuffer.WriteString("<title id=\"title\">")
if err != nil {
return err
}
var_4 := `bin`
_, err = templBuffer.WriteString(var_4)
if err != nil {
return err
}
_, err = templBuffer.WriteString("</title>")
if err != nil {
return err
}
} else {
_, err = templBuffer.WriteString("<title id=\"title\">")
if err != nil {
return err
}
var var_5 string = title
_, err = templBuffer.WriteString(templ.EscapeString(var_5))
if err != nil {
return err
}
_, err = templBuffer.WriteString(" ")
if err != nil {
return err
}
var_6 := `- bin`
_, err = templBuffer.WriteString(var_6)
if err != nil {
return err
}
_, err = templBuffer.WriteString("</title>")
if err != nil {
return err
}
}
_, err = templBuffer.WriteString("</head><body class=\"mt-4 sm:mt-12 mx-16 xl:mx-72 lg:mx-64 md:mx-32 sm:mx-24 bg-amber-50\"><header class=\"flex flex-row justify-between my-16\"><h1 class=\"text-5xl\">")
if err != nil { if err != nil {
return err return err
} }
_, err = templBuffer.WriteString("</title></head><body class=\"mt-12 mx-16 xl:mx-72 lg:mx-64 md:mx-32 sm:mx-24 bg-amber-50\"><header class=\"flex flex-row justify-between my-16\"><h1 class=\"text-5xl\">") var_7 := `bin`
if err != nil { _, err = templBuffer.WriteString(var_7)
return err
}
var_5 := `bin`
_, err = templBuffer.WriteString(var_5)
if err != nil { if err != nil {
return err return err
} }
@ -64,7 +102,7 @@ func page(inner templ.Component, menu []MenuItem, currentMenu int, args interfac
if err != nil { if err != nil {
return err return err
} }
err = NavMenu(menu, currentMenu, false).Render(ctx, templBuffer) err = components.NavMenu(menu, currentMenu, false).Render(ctx, templBuffer)
if err != nil { if err != nil {
return err return err
} }
@ -87,22 +125,7 @@ func page(inner templ.Component, menu []MenuItem, currentMenu int, args interfac
}) })
} }
var defaultMenu []MenuItem = []MenuItem{ func IndexFull() templ.Component {
{
label: "home",
href: "/",
},
{
label: "new",
href: "/new",
},
{
label: "about",
href: "/about",
},
}
func indexFull() templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) { return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
templBuffer, templIsBuffer := w.(*bytes.Buffer) templBuffer, templIsBuffer := w.(*bytes.Buffer)
if !templIsBuffer { if !templIsBuffer {
@ -110,16 +133,16 @@ func indexFull() templ.Component {
defer templ.ReleaseBuffer(templBuffer) defer templ.ReleaseBuffer(templBuffer)
} }
ctx = templ.InitializeContext(ctx) ctx = templ.InitializeContext(ctx)
var_6 := templ.GetChildren(ctx) var_8 := templ.GetChildren(ctx)
if var_6 == nil { if var_8 == nil {
var_6 = templ.NopComponent var_8 = templ.NopComponent
} }
ctx = templ.ClearChildren(ctx) ctx = templ.ClearChildren(ctx)
err = page( err = page(
indexPartial(), IndexPartial(),
defaultMenu, models.DefaultMenu,
0, 0,
nil, "",
).Render(ctx, templBuffer) ).Render(ctx, templBuffer)
if err != nil { if err != nil {
return err return err
@ -131,7 +154,7 @@ func indexFull() templ.Component {
}) })
} }
func indexPartial() templ.Component { func IndexPartial() templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) { return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
templBuffer, templIsBuffer := w.(*bytes.Buffer) templBuffer, templIsBuffer := w.(*bytes.Buffer)
if !templIsBuffer { if !templIsBuffer {
@ -139,17 +162,17 @@ func indexPartial() templ.Component {
defer templ.ReleaseBuffer(templBuffer) defer templ.ReleaseBuffer(templBuffer)
} }
ctx = templ.InitializeContext(ctx) ctx = templ.InitializeContext(ctx)
var_7 := templ.GetChildren(ctx) var_9 := templ.GetChildren(ctx)
if var_7 == nil { if var_9 == nil {
var_7 = templ.NopComponent var_9 = templ.NopComponent
} }
ctx = templ.ClearChildren(ctx) ctx = templ.ClearChildren(ctx)
_, err = templBuffer.WriteString("<h2 class=\"text-xl\">") _, err = templBuffer.WriteString("<h2 class=\"text-xl\">")
if err != nil { if err != nil {
return err return err
} }
var_8 := `Welcome to ` var_10 := `Welcome to `
_, err = templBuffer.WriteString(var_8) _, err = templBuffer.WriteString(var_10)
if err != nil { if err != nil {
return err return err
} }
@ -157,8 +180,8 @@ func indexPartial() templ.Component {
if err != nil { if err != nil {
return err return err
} }
var_9 := `bin` var_11 := `bin`
_, err = templBuffer.WriteString(var_9) _, err = templBuffer.WriteString(var_11)
if err != nil { if err != nil {
return err return err
} }
@ -166,8 +189,8 @@ func indexPartial() templ.Component {
if err != nil { if err != nil {
return err return err
} }
var_10 := `bin is a simple paste bin.` var_12 := `bin is a simple paste bin.`
_, err = templBuffer.WriteString(var_10) _, err = templBuffer.WriteString(var_12)
if err != nil { if err != nil {
return err return err
} }
@ -175,7 +198,7 @@ func indexPartial() templ.Component {
if err != nil { if err != nil {
return err return err
} }
err = boostButton("new", "/new").Render(ctx, templBuffer) err = components.BoostButton("new", "/new").Render(ctx, templBuffer)
if err != nil { if err != nil {
return err return err
} }
@ -186,7 +209,7 @@ func indexPartial() templ.Component {
}) })
} }
func newFull(wantsText bool) templ.Component { func NewFull(wantsText bool) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) { return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
templBuffer, templIsBuffer := w.(*bytes.Buffer) templBuffer, templIsBuffer := w.(*bytes.Buffer)
if !templIsBuffer { if !templIsBuffer {
@ -194,16 +217,16 @@ func newFull(wantsText bool) templ.Component {
defer templ.ReleaseBuffer(templBuffer) defer templ.ReleaseBuffer(templBuffer)
} }
ctx = templ.InitializeContext(ctx) ctx = templ.InitializeContext(ctx)
var_11 := templ.GetChildren(ctx) var_13 := templ.GetChildren(ctx)
if var_11 == nil { if var_13 == nil {
var_11 = templ.NopComponent var_13 = templ.NopComponent
} }
ctx = templ.ClearChildren(ctx) ctx = templ.ClearChildren(ctx)
err = page( err = page(
newPartial(wantsText), NewPartial(wantsText),
defaultMenu, models.DefaultMenu,
1, 1,
nil, "upload",
).Render(ctx, templBuffer) ).Render(ctx, templBuffer)
if err != nil { if err != nil {
return err return err
@ -223,7 +246,7 @@ int main(int argc, char *argv[]) {
return 0; return 0;
}` }`
func newPartial(wantsText bool) templ.Component { func NewPartial(wantsText bool) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) { return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
templBuffer, templIsBuffer := w.(*bytes.Buffer) templBuffer, templIsBuffer := w.(*bytes.Buffer)
if !templIsBuffer { if !templIsBuffer {
@ -231,17 +254,17 @@ func newPartial(wantsText bool) templ.Component {
defer templ.ReleaseBuffer(templBuffer) defer templ.ReleaseBuffer(templBuffer)
} }
ctx = templ.InitializeContext(ctx) ctx = templ.InitializeContext(ctx)
var_12 := templ.GetChildren(ctx) var_14 := templ.GetChildren(ctx)
if var_12 == nil { if var_14 == nil {
var_12 = templ.NopComponent var_14 = templ.NopComponent
} }
ctx = templ.ClearChildren(ctx) ctx = templ.ClearChildren(ctx)
_, err = templBuffer.WriteString("<h2 class=\"text-xl\">") _, err = templBuffer.WriteString("<h2 class=\"text-xl\">")
if err != nil { if err != nil {
return err return err
} }
var_13 := `submit a new file` var_15 := `submit a new file`
_, err = templBuffer.WriteString(var_13) _, err = templBuffer.WriteString(var_15)
if err != nil { if err != nil {
return err return err
} }
@ -249,8 +272,8 @@ func newPartial(wantsText bool) templ.Component {
if err != nil { if err != nil {
return err return err
} }
var_14 := `file name:` var_16 := `file name:`
_, err = templBuffer.WriteString(var_14) _, err = templBuffer.WriteString(var_16)
if err != nil { if err != nil {
return err return err
} }
@ -258,8 +281,8 @@ func newPartial(wantsText bool) templ.Component {
if err != nil { if err != nil {
return err return err
} }
var_15 := `language:` var_17 := `language:`
_, err = templBuffer.WriteString(var_15) _, err = templBuffer.WriteString(var_17)
if err != nil { if err != nil {
return err return err
} }
@ -267,7 +290,7 @@ func newPartial(wantsText bool) templ.Component {
if err != nil { if err != nil {
return err return err
} }
err = chooseSyntax("lang").Render(ctx, templBuffer) err = components.ChooseSyntax("lang").Render(ctx, templBuffer)
if err != nil { if err != nil {
return err return err
} }
@ -275,8 +298,8 @@ func newPartial(wantsText bool) templ.Component {
if err != nil { if err != nil {
return err return err
} }
var_16 := `description:` var_18 := `description:`
_, err = templBuffer.WriteString(var_16) _, err = templBuffer.WriteString(var_18)
if err != nil { if err != nil {
return err return err
} }
@ -285,7 +308,7 @@ func newPartial(wantsText bool) templ.Component {
return err return err
} }
if wantsText { if wantsText {
err = newTextSubmit().Render(ctx, templBuffer) err = partials.NewTextSubmit().Render(ctx, templBuffer)
if err != nil { if err != nil {
return err return err
} }
@ -294,12 +317,12 @@ func newPartial(wantsText bool) templ.Component {
return err return err
} }
} else { } else {
err = newFileUpload().Render(ctx, templBuffer) err = partials.NewFileUpload().Render(ctx, templBuffer)
if err != nil { if err != nil {
return err return err
} }
} }
err = submitFormButton("submit").Render(ctx, templBuffer) err = components.SubmitFormButton("submit").Render(ctx, templBuffer)
if err != nil { if err != nil {
return err return err
} }
@ -314,7 +337,7 @@ func newPartial(wantsText bool) templ.Component {
}) })
} }
func binFull(file File) templ.Component { func BinFull(file models.File) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) { return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
templBuffer, templIsBuffer := w.(*bytes.Buffer) templBuffer, templIsBuffer := w.(*bytes.Buffer)
if !templIsBuffer { if !templIsBuffer {
@ -322,16 +345,16 @@ func binFull(file File) templ.Component {
defer templ.ReleaseBuffer(templBuffer) defer templ.ReleaseBuffer(templBuffer)
} }
ctx = templ.InitializeContext(ctx) ctx = templ.InitializeContext(ctx)
var_17 := templ.GetChildren(ctx) var_19 := templ.GetChildren(ctx)
if var_17 == nil { if var_19 == nil {
var_17 = templ.NopComponent var_19 = templ.NopComponent
} }
ctx = templ.ClearChildren(ctx) ctx = templ.ClearChildren(ctx)
err = page( err = page(
binPartial(file), BinPartial(file),
defaultMenu, models.DefaultMenu,
-1, -1,
nil, file.Filename,
).Render(ctx, templBuffer) ).Render(ctx, templBuffer)
if err != nil { if err != nil {
return err return err
@ -343,7 +366,7 @@ func binFull(file File) templ.Component {
}) })
} }
func binPartial(file File) templ.Component { func BinPartial(file models.File) templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) { return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
templBuffer, templIsBuffer := w.(*bytes.Buffer) templBuffer, templIsBuffer := w.(*bytes.Buffer)
if !templIsBuffer { if !templIsBuffer {
@ -351,17 +374,17 @@ func binPartial(file File) templ.Component {
defer templ.ReleaseBuffer(templBuffer) defer templ.ReleaseBuffer(templBuffer)
} }
ctx = templ.InitializeContext(ctx) ctx = templ.InitializeContext(ctx)
var_18 := templ.GetChildren(ctx) var_20 := templ.GetChildren(ctx)
if var_18 == nil { if var_20 == nil {
var_18 = templ.NopComponent var_20 = templ.NopComponent
} }
ctx = templ.ClearChildren(ctx) ctx = templ.ClearChildren(ctx)
_, err = templBuffer.WriteString("<div><h1 class=\"text-xl my-2 inline-block\">") _, err = templBuffer.WriteString("<div><h1 class=\"text-xl my-2 inline-block\">")
if err != nil { if err != nil {
return err return err
} }
var var_19 string = file.Filename var var_21 string = file.Filename
_, err = templBuffer.WriteString(templ.EscapeString(var_19)) _, err = templBuffer.WriteString(templ.EscapeString(var_21))
if err != nil { if err != nil {
return err return err
} }
@ -370,21 +393,21 @@ func binPartial(file File) templ.Component {
if err != nil { if err != nil {
return err return err
} }
var_20 := `(` var_22 := `(`
_, err = templBuffer.WriteString(var_20)
if err != nil {
return err
}
var var_21 string = file.Language
_, err = templBuffer.WriteString(templ.EscapeString(var_21))
if err != nil {
return err
}
var_22 := `)`
_, err = templBuffer.WriteString(var_22) _, err = templBuffer.WriteString(var_22)
if err != nil { if err != nil {
return err return err
} }
var var_23 string = file.Language
_, err = templBuffer.WriteString(templ.EscapeString(var_23))
if err != nil {
return err
}
var_24 := `)`
_, err = templBuffer.WriteString(var_24)
if err != nil {
return err
}
_, err = templBuffer.WriteString("</sup>") _, err = templBuffer.WriteString("</sup>")
if err != nil { if err != nil {
return err return err
@ -394,8 +417,8 @@ func binPartial(file File) templ.Component {
if err != nil { if err != nil {
return err return err
} }
var var_23 string = file.Description var var_25 string = file.Description
_, err = templBuffer.WriteString(templ.EscapeString(var_23)) _, err = templBuffer.WriteString(templ.EscapeString(var_25))
if err != nil { if err != nil {
return err return err
} }
@ -403,8 +426,8 @@ func binPartial(file File) templ.Component {
if err != nil { if err != nil {
return err return err
} }
var var_24 string = file.Data var var_26 string = file.Data
_, err = templBuffer.WriteString(templ.EscapeString(var_24)) _, err = templBuffer.WriteString(templ.EscapeString(var_26))
if err != nil { if err != nil {
return err return err
} }
@ -416,7 +439,7 @@ func binPartial(file File) templ.Component {
if err != nil { if err != nil {
return err return err
} }
_, err = templBuffer.WriteString("\" hx-confirm=\"Are you sure you want to delete this?\"><input name=\"adminKey\" id=\"adminKey\" type=\"text\" class=\"mr-4 w-24 bg-amber-50\n hover:outline-slate-400 hover:outline-dotted \n focus:outline-slate-600 focus:outline-dashed\n active:outline-green-600\" placeholder=\"deletion key\" value=\"") _, err = templBuffer.WriteString("\" hx-confirm=\"Are you sure you want to delete this?\" hx-target=\"#main-content\"><input name=\"adminKey\" id=\"adminKey\" type=\"text\" class=\"mr-4 w-24 bg-amber-50\n hover:outline-slate-400 hover:outline-dotted \n focus:outline-slate-600 focus:outline-dashed\n active:outline-green-600\" placeholder=\"deletion key\" value=\"")
if err != nil { if err != nil {
return err return err
} }
@ -428,7 +451,7 @@ func binPartial(file File) templ.Component {
if err != nil { if err != nil {
return err return err
} }
err = submitFormButton("delete").Render(ctx, templBuffer) err = components.SubmitFormButton("delete").Render(ctx, templBuffer)
if err != nil { if err != nil {
return err return err
} }
@ -437,8 +460,8 @@ func binPartial(file File) templ.Component {
if err != nil { if err != nil {
return err return err
} }
var var_25 templ.SafeURL = templ.URL(fmt.Sprintf("/b/%s?delcode=%s", file.PageKey, file.AdminKey)) var var_27 templ.SafeURL = templ.URL(fmt.Sprintf("/b/%s?delcode=%s", file.PageKey, file.AdminKey))
_, err = templBuffer.WriteString(templ.EscapeString(string(var_25))) _, err = templBuffer.WriteString(templ.EscapeString(string(var_27)))
if err != nil { if err != nil {
return err return err
} }
@ -446,8 +469,8 @@ func binPartial(file File) templ.Component {
if err != nil { if err != nil {
return err return err
} }
var_26 := `permalink with deletion key` var_28 := `permalink with deletion key`
_, err = templBuffer.WriteString(var_26) _, err = templBuffer.WriteString(var_28)
if err != nil { if err != nil {
return err return err
} }
@ -460,8 +483,8 @@ func binPartial(file File) templ.Component {
if err != nil { if err != nil {
return err return err
} }
var_27 := `this is your deletion key! ` var_29 := `this is your deletion key! `
_, err = templBuffer.WriteString(var_27) _, err = templBuffer.WriteString(var_29)
if err != nil { if err != nil {
return err return err
} }
@ -469,8 +492,8 @@ func binPartial(file File) templ.Component {
if err != nil { if err != nil {
return err return err
} }
var_28 := `you will need to store it if you want to delete the file.` var_30 := `you will need to store it if you want to delete the file.`
_, err = templBuffer.WriteString(var_28) _, err = templBuffer.WriteString(var_30)
if err != nil { if err != nil {
return err return err
} }

View File

@ -1,7 +1,16 @@
package main package partials
import "git.myrkvi.com/myrkvi/bin/views/components"
templ newFileUpload() { const placeholderCode string = `#include <stdio.h>
int main(int argc, char *argv[]) {
printf("Hello, world!\n");
return 0;
}`
templ NewFileUpload() {
<div id="file-submission" class="my-2"> <div id="file-submission" class="my-2">
<div class="mb-4 flex flex-row justify-start space-x-4"> <div class="mb-4 flex flex-row justify-start space-x-4">
<span <span
@ -18,11 +27,11 @@ templ newFileUpload() {
text text
</a> </a>
</div> </div>
@fileUpload("browse ...", "file", "file") @components.FileUpload("browse ...", "file", "file")
</div> </div>
} }
templ newTextSubmit() { templ NewTextSubmit() {
<div id="file-submission" class="my-2"> <div id="file-submission" class="my-2">
<div class="mb-4 flex flex-row justify-start space-x-4"> <div class="mb-4 flex flex-row justify-start space-x-4">
<a <a

View File

@ -1,6 +1,6 @@
// Code generated by templ@v0.2.316 DO NOT EDIT. // Code generated by templ@v0.2.316 DO NOT EDIT.
package main package partials
//lint:file-ignore SA4006 This context is only used if a nested component is present. //lint:file-ignore SA4006 This context is only used if a nested component is present.
@ -9,7 +9,17 @@ import "context"
import "io" import "io"
import "bytes" import "bytes"
func newFileUpload() templ.Component { import "git.myrkvi.com/myrkvi/bin/views/components"
const placeholderCode string = `#include <stdio.h>
int main(int argc, char *argv[]) {
printf("Hello, world!\n");
return 0;
}`
func NewFileUpload() templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) { return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
templBuffer, templIsBuffer := w.(*bytes.Buffer) templBuffer, templIsBuffer := w.(*bytes.Buffer)
if !templIsBuffer { if !templIsBuffer {
@ -44,7 +54,7 @@ func newFileUpload() templ.Component {
if err != nil { if err != nil {
return err return err
} }
err = fileUpload("browse ...", "file", "file").Render(ctx, templBuffer) err = components.FileUpload("browse ...", "file", "file").Render(ctx, templBuffer)
if err != nil { if err != nil {
return err return err
} }
@ -59,7 +69,7 @@ func newFileUpload() templ.Component {
}) })
} }
func newTextSubmit() templ.Component { func NewTextSubmit() templ.Component {
return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) { return templ.ComponentFunc(func(ctx context.Context, w io.Writer) (err error) {
templBuffer, templIsBuffer := w.(*bytes.Buffer) templBuffer, templIsBuffer := w.(*bytes.Buffer)
if !templIsBuffer { if !templIsBuffer {