Множество улучшений
This commit is contained in:
parent
e9a64f3b41
commit
ce3111b0ef
37 changed files with 1047 additions and 402 deletions
|
@ -12,6 +12,7 @@ before:
|
|||
hooks:
|
||||
- go mod tidy
|
||||
- go generate ./...
|
||||
- templ generate
|
||||
|
||||
builds:
|
||||
- env:
|
||||
|
|
|
@ -17,35 +17,83 @@ var migrateCmd = &cobra.Command{
|
|||
Long: `Up and down migrations`,
|
||||
}
|
||||
|
||||
var migrateUp = &cobra.Command{
|
||||
Use: "up",
|
||||
Short: "Migrate up",
|
||||
Long: `Up migrations`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
db, err := sql.Open("sqlite3", dbFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("open db failed: %w", err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
driver, err := sqlite.WithInstance(db, &sqlite.Config{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed create migration driver: %w", err)
|
||||
}
|
||||
sourceDriver, err := iofs.New(migrations.FS, ".")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed open migrations: %w", err)
|
||||
}
|
||||
|
||||
m, err := migrate.NewWithInstance("fs", sourceDriver, "sqlite3", driver)
|
||||
if err != nil {
|
||||
return fmt.Errorf("open migration failed: %w", err)
|
||||
}
|
||||
|
||||
if err := m.Up(); err != nil && err != migrate.ErrNoChange {
|
||||
return fmt.Errorf("do migration failed: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
func init() {
|
||||
migrateCmd.AddCommand(
|
||||
&cobra.Command{
|
||||
Use: "up",
|
||||
Short: "Migrate up",
|
||||
Long: `Up migrations`,
|
||||
RunE: up,
|
||||
},
|
||||
&cobra.Command{
|
||||
Use: "down",
|
||||
Short: "Migrate down",
|
||||
Long: `Down migrations`,
|
||||
RunE: down,
|
||||
},
|
||||
&cobra.Command{
|
||||
Use: "drop",
|
||||
Short: "Drop db",
|
||||
Long: `Deletes everything in the database`,
|
||||
RunE: drop,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func up(_ *cobra.Command, _ []string) error {
|
||||
m, err := initMigrate()
|
||||
if err != nil {
|
||||
return fmt.Errorf("open migration failed: %w", err)
|
||||
}
|
||||
defer m.Close()
|
||||
if err := m.Up(); err != nil && err != migrate.ErrNoChange {
|
||||
return fmt.Errorf("do migration failed: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func down(_ *cobra.Command, _ []string) error {
|
||||
m, err := initMigrate()
|
||||
if err != nil {
|
||||
return fmt.Errorf("open migration failed: %w", err)
|
||||
}
|
||||
defer m.Close()
|
||||
if err := m.Down(); err != nil && err != migrate.ErrNoChange {
|
||||
return fmt.Errorf("do migration failed: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func drop(_ *cobra.Command, _ []string) error {
|
||||
m, err := initMigrate()
|
||||
if err != nil {
|
||||
return fmt.Errorf("open migration failed: %w", err)
|
||||
}
|
||||
defer m.Close()
|
||||
if err := m.Drop(); err != nil && err != migrate.ErrNoChange {
|
||||
return fmt.Errorf("do migration failed: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func initMigrate() (*migrate.Migrate, error) {
|
||||
db, err := sql.Open("sqlite3", dbFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("open db failed: %w", err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
driver, err := sqlite.WithInstance(db, &sqlite.Config{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed create migration driver: %w", err)
|
||||
}
|
||||
sourceDriver, err := iofs.New(migrations.FS, ".")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed open migrations: %w", err)
|
||||
}
|
||||
|
||||
return migrate.NewWithInstance("fs", sourceDriver, "sqlite3", driver)
|
||||
}
|
||||
|
|
|
@ -19,10 +19,14 @@ var (
|
|||
func init() {
|
||||
cobra.OnInitialize(initLogger)
|
||||
cobra.OnInitialize(initConfig)
|
||||
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "gorum.yaml", "config file (default is 'gorum.yaml')")
|
||||
rootCmd.PersistentFlags().StringVar(&dbFile, "db", "gorum.db", "database file (default is 'gorum.db')")
|
||||
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "gorum.yaml", "config file")
|
||||
rootCmd.PersistentFlags().StringVar(&dbFile, "db", "gorum.db", "database file")
|
||||
rootCmd.PersistentFlags().BoolVar(&debug, "debug", false, "verbose debug output")
|
||||
viper.BindPFlag("db", serverCmd.Flags().Lookup("db"))
|
||||
|
||||
rootCmd.AddCommand(serverCmd)
|
||||
rootCmd.AddCommand(migrateCmd)
|
||||
rootCmd.AddCommand(userCmd)
|
||||
}
|
||||
|
||||
func initLogger() {
|
||||
|
@ -43,8 +47,6 @@ func initConfig() {
|
|||
}
|
||||
|
||||
func Execute() {
|
||||
rootCmd.AddCommand(serverCmd)
|
||||
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
|
|
|
@ -2,7 +2,6 @@ package cmd
|
|||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net"
|
||||
|
@ -15,10 +14,8 @@ import (
|
|||
"github.com/michaeljs1990/sqlitestore"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/uptrace/bun"
|
||||
"github.com/uptrace/bun/dialect/sqlitedialect"
|
||||
"github.com/uptrace/bun/extra/bundebug"
|
||||
"gitrepo.ru/neonxp/gorum/contextlib"
|
||||
"gitrepo.ru/neonxp/gorum/db"
|
||||
"gitrepo.ru/neonxp/gorum/middleware"
|
||||
"gitrepo.ru/neonxp/gorum/repository"
|
||||
"gitrepo.ru/neonxp/gorum/routes"
|
||||
|
@ -42,9 +39,9 @@ var (
|
|||
)
|
||||
|
||||
func init() {
|
||||
serverCmd.PersistentFlags().StringVar(&theme, "theme", "default", "theme to use (default is 'default')")
|
||||
serverCmd.PersistentFlags().StringVar(&listen, "listen", ":8000", "bind address to listen (default is ':8000')")
|
||||
serverCmd.PersistentFlags().StringVar(&sessionSecret, "session_secret", "s3cr3t", "sessions secret (default is 's3cr3t')")
|
||||
serverCmd.PersistentFlags().StringVar(&theme, "theme", "default", "theme to use")
|
||||
serverCmd.PersistentFlags().StringVar(&listen, "listen", ":8000", "bind address to listen")
|
||||
serverCmd.PersistentFlags().StringVar(&sessionSecret, "session_secret", "s3cr3t", "sessions secret")
|
||||
viper.BindPFlag("theme", serverCmd.Flags().Lookup("theme"))
|
||||
viper.BindPFlag("listen", serverCmd.Flags().Lookup("listen"))
|
||||
viper.BindPFlag("session_secret", serverCmd.Flags().Lookup("session_secret"))
|
||||
|
@ -60,14 +57,12 @@ func serve(ctx context.Context) error {
|
|||
)
|
||||
ctx = context.WithValue(ctx, contextlib.ThemeKey, theme)
|
||||
|
||||
db, err := sql.Open("sqlite3", dbFile)
|
||||
orm, err := db.GetDB(dbFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("open db failed: %w", err)
|
||||
return err
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
orm := bun.NewDB(db, sqlitedialect.New())
|
||||
orm.AddQueryHook(bundebug.NewQueryHook(bundebug.WithVerbose(true)))
|
||||
defer orm.Close()
|
||||
|
||||
userRepo := repository.NewUser(orm)
|
||||
nodeRepo := repository.NewNode(orm)
|
||||
|
@ -82,11 +77,7 @@ func serve(ctx context.Context) error {
|
|||
_ = utils.Render(c, views.ErrorPage(err))
|
||||
}
|
||||
|
||||
e.Server.BaseContext = func(l net.Listener) context.Context {
|
||||
return ctx
|
||||
}
|
||||
|
||||
sessionStore, err := sqlitestore.NewSqliteStoreFromConnection(db, "sessions", "", 0, []byte(sessionSecret))
|
||||
sessionStore, err := sqlitestore.NewSqliteStoreFromConnection(orm.DB, "sessions", "", 0, []byte(sessionSecret))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed init session store: %w", err)
|
||||
}
|
||||
|
@ -94,14 +85,14 @@ func serve(ctx context.Context) error {
|
|||
e.Use(
|
||||
echomiddleware.Recover(),
|
||||
echomiddleware.Gzip(),
|
||||
echomiddleware.CSRFWithConfig(echomiddleware.CSRFConfig{
|
||||
Skipper: echomiddleware.DefaultSkipper,
|
||||
TokenLength: 32,
|
||||
TokenLookup: "form:" + echo.HeaderXCSRFToken,
|
||||
ContextKey: "csrf",
|
||||
CookieName: "_csrf",
|
||||
CookieMaxAge: 86400,
|
||||
}),
|
||||
// echomiddleware.CSRFWithConfig(echomiddleware.CSRFConfig{
|
||||
// Skipper: echomiddleware.DefaultSkipper,
|
||||
// TokenLength: 32,
|
||||
// TokenLookup: "form:" + echo.HeaderXCSRFToken,
|
||||
// ContextKey: "csrf",
|
||||
// CookieName: "_csrf",
|
||||
// CookieMaxAge: 86400,
|
||||
// }),
|
||||
session.Middleware(sessionStore),
|
||||
middleware.UserMiddleware(),
|
||||
)
|
||||
|
@ -113,9 +104,12 @@ func serve(ctx context.Context) error {
|
|||
e.POST("/logout", r.Logout)
|
||||
|
||||
e.GET("/", r.Node)
|
||||
e.GET("/n/:id", r.Node)
|
||||
e.GET("/n/:id/new", r.NewPost)
|
||||
e.POST("/n/:id/new", r.NewPost)
|
||||
e.GET("/p/:id", r.Node)
|
||||
e.GET("/p/:id/new", r.NewPost)
|
||||
e.POST("/p/:id/new", r.NewPost)
|
||||
e.GET("/t/:id", r.Node)
|
||||
e.GET("/t/:id/new", r.NewTopic)
|
||||
e.POST("/t/:id/new", r.NewTopic)
|
||||
|
||||
e.StaticFS("/assets", assets.FS)
|
||||
|
||||
|
@ -125,6 +119,9 @@ func serve(ctx context.Context) error {
|
|||
Addr: listen,
|
||||
Handler: e,
|
||||
ErrorLog: slog.NewLogLogger(slog.Default().Handler(), slog.LevelError),
|
||||
ConnContext: func(cctx context.Context, c net.Conn) context.Context {
|
||||
return ctx
|
||||
},
|
||||
}
|
||||
if err := server.ListenAndServe(); err != http.ErrServerClosed {
|
||||
return fmt.Errorf("server failed: %w", err)
|
||||
|
|
80
app/cmd/user.go
Normal file
80
app/cmd/user.go
Normal file
|
@ -0,0 +1,80 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"gitrepo.ru/neonxp/gorum/db"
|
||||
"gitrepo.ru/neonxp/gorum/models"
|
||||
"gitrepo.ru/neonxp/gorum/repository"
|
||||
)
|
||||
|
||||
var userCmd = &cobra.Command{
|
||||
Use: "user",
|
||||
Short: "User managment",
|
||||
}
|
||||
|
||||
var createUserCmd = &cobra.Command{
|
||||
Use: "add",
|
||||
Args: cobra.ExactArgs(3),
|
||||
ArgAliases: []string{"username", "email", "role"},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
orm, err := db.GetDB(dbFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed init db: %w", err)
|
||||
}
|
||||
username := args[0]
|
||||
email := args[1]
|
||||
role := args[2]
|
||||
iRole := models.RoleUser
|
||||
switch role {
|
||||
case "admin":
|
||||
iRole = models.RoleAdmin
|
||||
case "moderator":
|
||||
iRole = models.RoleModerator
|
||||
}
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
fmt.Printf("Enter password for user %s: ", username)
|
||||
password, _ := reader.ReadString('\n')
|
||||
|
||||
ur := repository.NewUser(orm)
|
||||
id, err := ur.Create(cmd.Context(), email, password, username, iRole)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed create user: %w", err)
|
||||
}
|
||||
|
||||
fmt.Printf("Created user %s (id=%d, email=%s, role_id=%d)\n", username, id, email, iRole)
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var listUserCmd = &cobra.Command{
|
||||
Use: "list",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
orm, err := db.GetDB(dbFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed init db: %w", err)
|
||||
}
|
||||
|
||||
ur := repository.NewUser(orm)
|
||||
users, err := ur.List(cmd.Context())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("ID\tUsername\tEmail\tRole\n")
|
||||
for _, u := range users {
|
||||
fmt.Printf("%d\t%s\t%s\t%d\n", u.ID, u.Username, u.Email, u.Role)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
userCmd.AddCommand(createUserCmd)
|
||||
userCmd.AddCommand(listUserCmd)
|
||||
}
|
34
db/db.go
Normal file
34
db/db.go
Normal file
|
@ -0,0 +1,34 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/uptrace/bun"
|
||||
"github.com/uptrace/bun/dialect/sqlitedialect"
|
||||
)
|
||||
|
||||
func GetDB(dbFile string) (*bun.DB, error) {
|
||||
db, err := sql.Open("sqlite3", dbFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("open db failed: %w", err)
|
||||
}
|
||||
|
||||
orm := bun.NewDB(db, sqlitedialect.New())
|
||||
orm.AddQueryHook(&queryHook{})
|
||||
|
||||
return orm, nil
|
||||
}
|
||||
|
||||
type queryHook struct {
|
||||
}
|
||||
|
||||
func (*queryHook) BeforeQuery(ctx context.Context, qe *bun.QueryEvent) context.Context {
|
||||
return ctx
|
||||
}
|
||||
|
||||
func (*queryHook) AfterQuery(ctx context.Context, qe *bun.QueryEvent) {
|
||||
slog.Debug("query", slog.String("query", qe.Query))
|
||||
}
|
2
go.mod
2
go.mod
|
@ -11,7 +11,6 @@ require (
|
|||
)
|
||||
|
||||
require (
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/google/uuid v1.4.0 // indirect
|
||||
github.com/gorilla/context v1.1.2 // indirect
|
||||
|
@ -67,7 +66,6 @@ require (
|
|||
github.com/spf13/viper v1.19.0
|
||||
github.com/uptrace/bun v1.2.1
|
||||
github.com/uptrace/bun/dialect/sqlitedialect v1.2.1
|
||||
github.com/uptrace/bun/extra/bundebug v1.2.1
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||
golang.org/x/crypto v0.22.0
|
||||
|
|
26
go.sum
26
go.sum
|
@ -2,12 +2,13 @@ github.com/a-h/templ v0.2.747 h1:D0dQ2lxC3W7Dxl6fxQ/1zZHBQslSkTSvl5FxP/CfdKg=
|
|||
github.com/a-h/templ v0.2.747/go.mod h1:69ObQIbrcuwPCU32ohNaWce3Cb7qM5GMiqN1K+2yop4=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/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/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
|
@ -43,6 +44,10 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD
|
|||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
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-contrib v0.17.1 h1:7I/he7ylVKsDUieaGRZ9XxxTYOjfQwVzHzUYrNykfCU=
|
||||
github.com/labstack/echo-contrib v0.17.1/go.mod h1:SnsCZtwHBAZm5uBSAtQtXQHI3wqEA73hvTn0bYMKnZA=
|
||||
github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0=
|
||||
|
@ -65,12 +70,17 @@ github.com/michaeljs1990/sqlitestore v0.0.0-20210507162135-8585425bc864 h1:NkqeB
|
|||
github.com/michaeljs1990/sqlitestore v0.0.0-20210507162135-8585425bc864/go.mod h1:N6aiMetO+sSN0h4VC8RjkwiljKaZmgPsWzZG+mk6oec=
|
||||
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/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
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/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
|
||||
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
|
||||
|
@ -105,8 +115,6 @@ github.com/uptrace/bun v1.2.1 h1:2ENAcfeCfaY5+2e7z5pXrzFKy3vS8VXvkCag6N2Yzfk=
|
|||
github.com/uptrace/bun v1.2.1/go.mod h1:cNg+pWBUMmJ8rHnETgf65CEvn3aIKErrwOD6IA8e+Ec=
|
||||
github.com/uptrace/bun/dialect/sqlitedialect v1.2.1 h1:IprvkIKUjEjvt4VKpcmLpbMIucjrsmUPJOSlg19+a0Q=
|
||||
github.com/uptrace/bun/dialect/sqlitedialect v1.2.1/go.mod h1:mMQf4NUpgY8bnOanxGmxNiHCdALOggS4cZ3v63a9D/o=
|
||||
github.com/uptrace/bun/extra/bundebug v1.2.1 h1:85MYpX3QESYI02YerKxUi1CD9mHuLrc2BXs1eOCtQus=
|
||||
github.com/uptrace/bun/extra/bundebug v1.2.1/go.mod h1:sfGKIi0HSGxsTC/sgIHGwpnYduHHYhdMeOIwurgSY+Y=
|
||||
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=
|
||||
|
@ -137,8 +145,8 @@ golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
|||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
|
||||
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -164,6 +172,8 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T
|
|||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
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.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
30
middleware/session/store.go
Normal file
30
middleware/session/store.go
Normal file
|
@ -0,0 +1,30 @@
|
|||
package session
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/sessions"
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
type SessionStore struct {
|
||||
orm *bun.DB
|
||||
}
|
||||
|
||||
// Get should return a cached session.
|
||||
func (s *SessionStore) Get(r *http.Request, name string) (*sessions.Session, error) {
|
||||
panic("not implemented") // TODO: Implement
|
||||
}
|
||||
|
||||
// New should create and return a new session.
|
||||
//
|
||||
// Note that New should never return a nil session, even in the case of
|
||||
// an error if using the Registry infrastructure to cache the session.
|
||||
func (s *SessionStore) New(r *http.Request, name string) (*sessions.Session, error) {
|
||||
panic("not implemented") // TODO: Implement
|
||||
}
|
||||
|
||||
// Save should persist session to the underlying store implementation.
|
||||
func (s *SessionStore) Save(r *http.Request, w http.ResponseWriter, ss *sessions.Session) error {
|
||||
panic("not implemented") // TODO: Implement
|
||||
}
|
|
@ -21,6 +21,7 @@ type Node struct {
|
|||
CreatedAt int64 `bun:",nullzero,notnull,default:current_timestamp"`
|
||||
UpdatedAt int64 `bun:",nullzero,notnull,default:current_timestamp"`
|
||||
DeletedAt int64
|
||||
Children []*Node `bun:"rel:has-many,join:id=parent_id"`
|
||||
}
|
||||
|
||||
var _ bun.BeforeAppendModelHook = (*Node)(nil)
|
||||
|
|
|
@ -18,4 +18,13 @@ type User struct {
|
|||
Password string
|
||||
Username string
|
||||
Photo *string
|
||||
Role UserRole
|
||||
}
|
||||
|
||||
type UserRole int
|
||||
|
||||
const (
|
||||
RoleUser UserRole = iota
|
||||
RoleModerator
|
||||
RoleAdmin
|
||||
)
|
||||
|
|
|
@ -42,17 +42,17 @@ func (t *Node) Get(ctx context.Context, topicID int) (*models.Node, error) {
|
|||
Model(node).
|
||||
Where(`n.id = ?`, topicID).
|
||||
Relation("Author").
|
||||
Relation("Parent").
|
||||
Scan(ctx)
|
||||
}
|
||||
|
||||
func (t *Node) List(ctx context.Context, topicID int) ([]*models.Node, int, error) {
|
||||
func (t *Node) List(ctx context.Context, topicID int) ([]*models.Node, error) {
|
||||
posts := make([]*models.Node, 0)
|
||||
|
||||
count, err := t.db.NewSelect().
|
||||
return posts, t.db.NewSelect().
|
||||
Model(&posts).
|
||||
Where(`parent_id = ?`, topicID).
|
||||
Relation("Author").
|
||||
ScanAndCount(ctx)
|
||||
|
||||
return posts, count, err
|
||||
Relation("Children").
|
||||
Scan(ctx)
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ func NewUser(db *bun.DB) *User {
|
|||
}
|
||||
}
|
||||
|
||||
func (u *User) Create(ctx context.Context, email, password, username string) (int, error) {
|
||||
func (u *User) Create(ctx context.Context, email, password, username string, role models.UserRole) (int, error) {
|
||||
|
||||
hpassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
|
@ -30,6 +30,7 @@ func (u *User) Create(ctx context.Context, email, password, username string) (in
|
|||
Email: email,
|
||||
Password: string(hpassword),
|
||||
Username: username,
|
||||
Role: role,
|
||||
}
|
||||
|
||||
if _, err := u.db.NewInsert().Model(user).Returning("id").Exec(ctx); err != nil {
|
||||
|
@ -52,3 +53,9 @@ func (u *User) Login(ctx context.Context, email, password string) (*models.User,
|
|||
|
||||
return user, nil
|
||||
}
|
||||
|
||||
func (u *User) List(ctx context.Context) ([]*models.User, error) {
|
||||
ret := make([]*models.User, 0)
|
||||
|
||||
return ret, u.db.NewSelect().Model(&ret).Scan(ctx)
|
||||
}
|
||||
|
|
|
@ -34,12 +34,23 @@ func (r *Router) Node(c echo.Context) error {
|
|||
}
|
||||
}
|
||||
|
||||
nodes, count, err := r.nodeRepo.List(c.Request().Context(), parentID)
|
||||
nodes, err := r.nodeRepo.List(c.Request().Context(), parentID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utils.Render(c, views.Node(node, nodes, count))
|
||||
topics := make([]*models.Node, 0, len(nodes))
|
||||
posts := make([]*models.Node, 0, len(nodes))
|
||||
for _, n := range nodes {
|
||||
switch n.Type {
|
||||
case models.PostType:
|
||||
posts = append(posts, n)
|
||||
case models.TopicType:
|
||||
topics = append(topics, n)
|
||||
}
|
||||
}
|
||||
|
||||
return utils.Render(c, views.Node(node, topics, posts))
|
||||
}
|
||||
|
||||
func (r *Router) NewPost(c echo.Context) error {
|
||||
|
@ -63,7 +74,7 @@ func (r *Router) NewPost(c echo.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
return c.Redirect(302, fmt.Sprintf("/n/%d#post%d", parentID, postID))
|
||||
return c.Redirect(302, fmt.Sprintf("/t/%d#post%d", parentID, postID))
|
||||
}
|
||||
|
||||
node, err := r.nodeRepo.Get(c.Request().Context(), parentID)
|
||||
|
@ -71,5 +82,36 @@ func (r *Router) NewPost(c echo.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
return utils.Render(c, views.NewNode(node))
|
||||
return utils.Render(c, views.NewPost(node))
|
||||
}
|
||||
func (r *Router) NewTopic(c echo.Context) error {
|
||||
req := new(nodeRequest)
|
||||
if err := c.Bind(req); err != nil {
|
||||
return err
|
||||
}
|
||||
user := contextlib.GetUser(c.Request().Context())
|
||||
if user == nil {
|
||||
return echo.ErrForbidden
|
||||
}
|
||||
sParentID := c.Param("id")
|
||||
parentID, err := strconv.Atoi(sParentID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if c.Request().Method == http.MethodPost {
|
||||
postID, err := r.nodeRepo.Create(c.Request().Context(), req.Type, req.Text, user.ID, parentID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.Redirect(302, fmt.Sprintf("/t/%d", postID))
|
||||
}
|
||||
|
||||
node, err := r.nodeRepo.Get(c.Request().Context(), parentID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return utils.Render(c, views.NewTopic(node))
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/gorilla/sessions"
|
||||
"github.com/labstack/echo-contrib/session"
|
||||
"github.com/labstack/echo/v4"
|
||||
"gitrepo.ru/neonxp/gorum/models"
|
||||
"gitrepo.ru/neonxp/gorum/utils"
|
||||
"gitrepo.ru/neonxp/gorum/views"
|
||||
)
|
||||
|
@ -72,7 +73,7 @@ func (r *Router) Register(c echo.Context) error {
|
|||
return err
|
||||
}
|
||||
if c.Request().Method == http.MethodPost {
|
||||
uid, err := r.userRepo.Create(c.Request().Context(), req.Email, req.Password, req.Username)
|
||||
uid, err := r.userRepo.Create(c.Request().Context(), req.Email, req.Password, req.Username, models.RoleUser)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package views
|
||||
|
||||
import "github.com/labstack/echo/v4"
|
||||
|
||||
templ CSRF() {
|
||||
<input type="hidden" name={echo.HeaderXCSRFToken} value={ ctx.Value("csrf").(string) }/>
|
||||
// <input type="hidden" name={echo.HeaderXCSRFToken} value={ ctx.Value("csrf").(string) } />
|
||||
}
|
||||
|
|
31
views/csrf_templ.go
Normal file
31
views/csrf_templ.go
Normal file
|
@ -0,0 +1,31 @@
|
|||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.747
|
||||
package views
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
func CSRF() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
package views
|
||||
|
||||
templ ErrorPage(err error) {
|
||||
@Layout() {
|
||||
<h1>Ошибка</h1>
|
||||
{err.Error()}
|
||||
}
|
||||
@Layout(nil) {
|
||||
<h1>Ошибка</h1>
|
||||
{ err.Error() }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,14 +38,14 @@ func ErrorPage(err error) templ.Component {
|
|||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<h1>Ошибка</h1>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(err.Error())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/error.templ`, Line: 6, Col: 20}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/error.templ`, Line: 6, Col: 15}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
|
@ -53,7 +53,7 @@ func ErrorPage(err error) templ.Component {
|
|||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = Layout().Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
||||
templ_7745c5c3_Err = Layout(nil).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
<h1>Ошибка</h1>
|
|
@ -2,11 +2,12 @@ package views
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"gitrepo.ru/neonxp/gorum/contextlib"
|
||||
"gitrepo.ru/neonxp/gorum/models"
|
||||
)
|
||||
|
||||
templ Layout() {
|
||||
templ Layout(parent *models.Node) {
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
|
@ -14,7 +15,7 @@ templ Layout() {
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
||||
<meta name="color-scheme" content="light dark"/>
|
||||
<link rel="stylesheet" href={ "/assets/css/pico." + ctx.Value(contextlib.ThemeKey).(string) + ".min.css" }/>
|
||||
<link rel="stylesheet" href="/assets/css/style.css" />
|
||||
<link rel="stylesheet" href="/assets/css/style.css"/>
|
||||
<title>Gorum</title>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -23,9 +24,23 @@ templ Layout() {
|
|||
<li>
|
||||
<strong>Gorum BBS</strong>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/">Список тем</a>
|
||||
</li>
|
||||
if parent != nil {
|
||||
<li>
|
||||
<a href="/">Список тем</a>
|
||||
</li>
|
||||
<li>
|
||||
switch parent.Type {
|
||||
case models.PostType:
|
||||
<a href={ templ.URL(fmt.Sprintf("/p/%d", parent.ID)) }>На уровень выше</a>
|
||||
case models.TopicType:
|
||||
<a href={ templ.URL(fmt.Sprintf("/t/%d", parent.ID)) }>К предыдущей теме</a>
|
||||
}
|
||||
</li>
|
||||
} else {
|
||||
<li>
|
||||
<a href="/">Список тем</a>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
<ul>
|
||||
if isAuthorized(ctx) {
|
||||
|
@ -42,7 +57,7 @@ templ Layout() {
|
|||
{ children... }
|
||||
</main>
|
||||
<footer class="container-fluid">
|
||||
<small>Работает на <a href="https://gorum.tech/">Gorum</a>.</small>
|
||||
<small>Работает на <a href="https://neonxp.ru/gorum">Gorum</a>.</small>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -10,11 +10,12 @@ import templruntime "github.com/a-h/templ/runtime"
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"gitrepo.ru/neonxp/gorum/contextlib"
|
||||
"gitrepo.ru/neonxp/gorum/models"
|
||||
)
|
||||
|
||||
func Layout() templ.Component {
|
||||
func Layout(parent *models.Node) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
|
@ -32,48 +33,97 @@ func Layout() templ.Component {
|
|||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<!doctype html><html lang=\"ru\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><meta name=\"color-scheme\" content=\"light dark\"><link rel=\"stylesheet\" href=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs("/assets/css/pico." + ctx.Value(contextlib.ThemeKey).(string) + ".min.css")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/layouts.templ`, Line: 16, Col: 107}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/layouts.templ`, Line: 17, Col: 107}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><link rel=\"stylesheet\" href=\"/assets/css/style.css\"><title>Gorum</title></head><body><nav class=\"container-fluid\"><ul><li><strong>Gorum BBS</strong></li>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if isAuthorized(ctx) {
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3)
|
||||
if parent != nil {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li><a href=\"/\">Список тем</a></li><li>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(getUser(ctx).Username)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/layouts.templ`, Line: 33, Col: 33}
|
||||
switch parent.Type {
|
||||
case models.PostType:
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a href=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 templ.SafeURL = templ.URL(fmt.Sprintf("/p/%d", parent.ID))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var3)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">На уровень выше</a>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
case models.TopicType:
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a href=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 templ.SafeURL = templ.URL(fmt.Sprintf("/t/%d", parent.ID))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var4)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">К предыдущей теме</a>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 4)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</li>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
} else {
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 5)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li><a href=\"/\">Список тем</a></li>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 6)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</ul><ul>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if isAuthorized(ctx) {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <li>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var5 string
|
||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(getUser(ctx).Username)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/layouts.templ`, Line: 48, Col: 33}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</li><li><form action=\"/logout\" method=\"POST\"><input type=\"submit\" value=\"Выход\"></form></li>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
} else {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li><a href=\"/login\">Вход</a></li><li><a href=\"/register\">Регистрация</a></li>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</ul></nav><main class=\"container\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
@ -81,7 +131,7 @@ func Layout() templ.Component {
|
|||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 7)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</main><footer class=\"container-fluid\"><small>Работает на <a href=\"https://neonxp.ru/gorum\">Gorum</a>.</small></footer></body></html>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
<!doctype html><html lang=\"ru\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><meta name=\"color-scheme\" content=\"light dark\"><link rel=\"stylesheet\" href=\"
|
||||
\"><link rel=\"stylesheet\" href=\"/assets/css/style.css\"><title>Gorum</title></head><body><nav class=\"container-fluid\"><ul><li><strong>Gorum BBS</strong></li><li><a href=\"/\">Список тем</a></li></ul><ul>
|
||||
<li>
|
||||
</li><li><form action=\"/logout\" method=\"POST\"><input type=\"submit\" value=\"Выход\"></form></li>
|
||||
<li><a href=\"/login\">Вход</a></li><li><a href=\"/register\">Регистрация</a></li>
|
||||
</ul></nav><main class=\"container\">
|
||||
</main><footer class=\"container-fluid\"><small>Работает на <a href=\"https://gorum.tech/\">Gorum</a>.</small></footer></body></html>
|
|
@ -1,7 +1,7 @@
|
|||
package views
|
||||
|
||||
templ Login(email string) {
|
||||
@Layout() {
|
||||
@Layout(nil) {
|
||||
<h1>Вход</h1>
|
||||
<form method="post">
|
||||
<label for="email">Электропочта:</label>
|
||||
|
|
|
@ -38,7 +38,7 @@ func Login(email string) templ.Component {
|
|||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<h1>Вход</h1><form method=\"post\"><label for=\"email\">Электропочта:</label> <input type=\"email\" id=\"email\" name=\"email\" required=\"true\" placeholder=\"имя@mail.ru\" value=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
@ -51,13 +51,13 @@ func Login(email string) templ.Component {
|
|||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"> <label for=\"password\">Пароль:</label> <input type=\"password\" id=\"password\" name=\"password\" required=\"true\" placeholder=\"пароль\"> <label for=\"remember\"><input type=\"checkbox\" id=\"remember\" name=\"remember\" checked=\"checked\"> Запомнить меня?</label> <input type=\"submit\" value=\"Войти\"></form>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = Layout().Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
||||
templ_7745c5c3_Err = Layout(nil).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
<h1>Вход</h1><form method=\"post\"><label for=\"email\">Электропочта:</label> <input type=\"email\" id=\"email\" name=\"email\" required=\"true\" placeholder=\"имя@mail.ru\" value=\"
|
||||
\"> <label for=\"password\">Пароль:</label> <input type=\"password\" id=\"password\" name=\"password\" required=\"true\" placeholder=\"пароль\"> <label for=\"remember\"><input type=\"checkbox\" id=\"remember\" name=\"remember\" checked=\"checked\"> Запомнить меня?</label> <input type=\"submit\" value=\"Войти\"></form>
|
|
@ -1,30 +0,0 @@
|
|||
package views
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gitrepo.ru/neonxp/gorum/models"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
templ NewNode(parent *models.Node) {
|
||||
<details>
|
||||
<summary>Создать топик</summary>
|
||||
<form method="post" action={ templ.URL(fmt.Sprintf("/n/%d/new", parent.ID)) }>
|
||||
@CSRF()
|
||||
<input type="hidden" name="type" value={ strconv.Itoa(int(models.TopicType)) }/>
|
||||
<label for="text">Топик</label>
|
||||
<input type="text" name="text" id="text" placeholder="имя темы..."/>
|
||||
<input type="submit" value="Создать"/>
|
||||
</form>
|
||||
</details>
|
||||
<details>
|
||||
<summary>Создать пост</summary>
|
||||
<form method="post" action={ templ.URL(fmt.Sprintf("/n/%d/new", parent.ID)) }>
|
||||
@CSRF()
|
||||
<input type="hidden" name="type" value={ strconv.Itoa(int(models.PostType)) }/>
|
||||
<label for="text">Текст</label>
|
||||
<textarea name="text" id="text" placeholder="текст..." rows="10"></textarea>
|
||||
<input type="submit" value="Создать"/>
|
||||
</form>
|
||||
</details>
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.747
|
||||
package views
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gitrepo.ru/neonxp/gorum/models"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func NewNode(parent *models.Node) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var2 templ.SafeURL = templ.URL(fmt.Sprintf("/n/%d/new", parent.ID))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var2)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(int(models.TopicType)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/new-node.templ`, Line: 13, Col: 79}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 templ.SafeURL = templ.URL(fmt.Sprintf("/n/%d/new", parent.ID))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var4)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 4)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var5 string
|
||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(int(models.PostType)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/new-node.templ`, Line: 22, Col: 78}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 5)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
|
@ -1,5 +0,0 @@
|
|||
<details><summary>Создать топик</summary><form method=\"post\" action=\"
|
||||
\"><input type=\"hidden\" name=\"type\" value=\"
|
||||
\"> <label for=\"text\">Топик</label> <input type=\"text\" name=\"text\" id=\"text\" placeholder=\"имя темы...\"> <input type=\"submit\" value=\"Создать\"></form></details> <details><summary>Создать пост</summary><form method=\"post\" action=\"
|
||||
\"><input type=\"hidden\" name=\"type\" value=\"
|
||||
\"> <label for=\"text\">Текст</label> <textarea name=\"text\" id=\"text\" placeholder=\"текст...\" rows=\"10\"></textarea> <input type=\"submit\" value=\"Создать\"></form></details>
|
51
views/new.templ
Normal file
51
views/new.templ
Normal file
|
@ -0,0 +1,51 @@
|
|||
package views
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gitrepo.ru/neonxp/gorum/models"
|
||||
"gitrepo.ru/neonxp/gorum/utils"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
templ NewPost(parent *models.Node) {
|
||||
@Layout(parent.Parent) {
|
||||
<article>
|
||||
<header class="post-header">
|
||||
<span>
|
||||
{ parent.Author.Username }
|
||||
</span>
|
||||
<span>
|
||||
{ utils.FormatDate(parent.CreatedAt) }
|
||||
</span>
|
||||
</header>
|
||||
@templ.Raw(utils.MarkdownToHTML(parent.Text))
|
||||
</article>
|
||||
@NewPostForm(parent)
|
||||
}
|
||||
}
|
||||
templ NewTopic(parent *models.Node) {
|
||||
@Layout(parent.Parent) {
|
||||
<h1>{parent.Text}</h1>
|
||||
@NewTopicForm(parent)
|
||||
}
|
||||
}
|
||||
|
||||
templ NewPostForm(parent *models.Node) {
|
||||
<form method="post" action={ templ.URL(fmt.Sprintf("/p/%d/new", parent.ID)) }>
|
||||
@CSRF()
|
||||
<input type="hidden" name="type" value={ strconv.Itoa(int(models.PostType)) }/>
|
||||
<label for="text"><strong>Ответ</strong></label>
|
||||
<textarea name="text" id="text" placeholder="текст..." rows="5"></textarea>
|
||||
<input type="submit" value="Создать"/>
|
||||
</form>
|
||||
}
|
||||
|
||||
templ NewTopicForm(parent *models.Node) {
|
||||
<form method="post" action={ templ.URL(fmt.Sprintf("/t/%d/new", parent.ID)) }>
|
||||
@CSRF()
|
||||
<input type="hidden" name="type" value={ strconv.Itoa(int(models.TopicType)) }/>
|
||||
<label for="text"><strong>Новая тема</strong></label>
|
||||
<input type="text" name="text" id="text" placeholder="название темы..." />
|
||||
<input type="submit" value="Создать"/>
|
||||
</form>
|
||||
}
|
271
views/new_templ.go
Normal file
271
views/new_templ.go
Normal file
|
@ -0,0 +1,271 @@
|
|||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.747
|
||||
package views
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"gitrepo.ru/neonxp/gorum/models"
|
||||
"gitrepo.ru/neonxp/gorum/utils"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func NewPost(parent *models.Node) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<article><header class=\"post-header\"><span>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(parent.Author.Username)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/new.templ`, Line: 15, Col: 29}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</span> <span>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(utils.FormatDate(parent.CreatedAt))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/new.templ`, Line: 18, Col: 41}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</span></header>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.Raw(utils.MarkdownToHTML(parent.Text)).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</article>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = NewPostForm(parent).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = Layout(parent.Parent).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func NewTopic(parent *models.Node) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var5 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var5 == nil {
|
||||
templ_7745c5c3_Var5 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Var6 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<h1>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var7 string
|
||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(parent.Text)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/new.templ`, Line: 28, Col: 18}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</h1>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = NewTopicForm(parent).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = Layout(parent.Parent).Render(templ.WithChildren(ctx, templ_7745c5c3_Var6), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func NewPostForm(parent *models.Node) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var8 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var8 == nil {
|
||||
templ_7745c5c3_Var8 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<form method=\"post\" action=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var9 templ.SafeURL = templ.URL(fmt.Sprintf("/p/%d/new", parent.ID))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var9)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = CSRF().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<input type=\"hidden\" name=\"type\" value=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var10 string
|
||||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(int(models.PostType)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/new.templ`, Line: 36, Col: 77}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"> <label for=\"text\"><strong>Ответ</strong></label> <textarea name=\"text\" id=\"text\" placeholder=\"текст...\" rows=\"5\"></textarea> <input type=\"submit\" value=\"Создать\"></form>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func NewTopicForm(parent *models.Node) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var11 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var11 == nil {
|
||||
templ_7745c5c3_Var11 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<form method=\"post\" action=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var12 templ.SafeURL = templ.URL(fmt.Sprintf("/t/%d/new", parent.ID))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var12)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = CSRF().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<input type=\"hidden\" name=\"type\" value=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var13 string
|
||||
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(int(models.TopicType)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/new.templ`, Line: 46, Col: 78}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"> <label for=\"text\"><strong>Новая тема</strong></label> <input type=\"text\" name=\"text\" id=\"text\" placeholder=\"название темы...\"> <input type=\"submit\" value=\"Создать\"></form>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
|
@ -4,44 +4,46 @@ import (
|
|||
"fmt"
|
||||
"gitrepo.ru/neonxp/gorum/models"
|
||||
"gitrepo.ru/neonxp/gorum/utils"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
templ Node(node *models.Node, nodes []*models.Node, count int) {
|
||||
@Layout() {
|
||||
<h1>{ node.Text }</h1>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Тема</th>
|
||||
<th>Дата</th>
|
||||
<th>Автор</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
for _, n := range nodes {
|
||||
if n.Type == models.TopicType {
|
||||
templ Node(node *models.Node, topics []*models.Node, nodes []*models.Node) {
|
||||
@Layout(node.Parent) {
|
||||
switch node.Type {
|
||||
case models.TopicType:
|
||||
<h1>{ node.Text }</h1>
|
||||
<div>
|
||||
<a href={ templ.URL(fmt.Sprintf("/t/%d/new", node.ID)) }>Новая подтема</a>
|
||||
</div>
|
||||
case models.PostType:
|
||||
<h1>Пост</h1>
|
||||
@Post(node, 0, false)
|
||||
}
|
||||
if len(topics) != 0 {
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Тема</th>
|
||||
<th>Тем/Ответов</th>
|
||||
<th>Дата</th>
|
||||
<th>Автор</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
for _, n := range topics {
|
||||
@Topic(n)
|
||||
}
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<strong>Тем нет</strong>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
<strong>Постов нет</strong>
|
||||
}
|
||||
for _, n := range nodes {
|
||||
if n.Type == models.PostType {
|
||||
@Post(n)
|
||||
}
|
||||
@Post(n, level(node), true)
|
||||
}
|
||||
if isAuthorized(ctx) {
|
||||
@NewNode(node)
|
||||
@NewPostForm(node)
|
||||
} else {
|
||||
<a href="/login">Войдите</a> чтобы ответить в тему.
|
||||
}
|
||||
|
@ -51,7 +53,10 @@ templ Node(node *models.Node, nodes []*models.Node, count int) {
|
|||
templ Topic(n *models.Node) {
|
||||
<tr>
|
||||
<td>
|
||||
<a href={ templ.URL(fmt.Sprintf("/n/%d", n.ID)) }>{ n.Text }</a>
|
||||
<a href={ templ.URL(fmt.Sprintf("/t/%d", n.ID)) }>{ n.Text }</a>
|
||||
</td>
|
||||
<td>
|
||||
{ strconv.Itoa(len(n.Children)) }
|
||||
</td>
|
||||
<td>
|
||||
{ utils.FormatDate(n.CreatedAt) }
|
||||
|
@ -62,21 +67,33 @@ templ Topic(n *models.Node) {
|
|||
</tr>
|
||||
}
|
||||
|
||||
templ Post(n *models.Node) {
|
||||
<article id={ fmt.Sprintf("post%d", n.ID) }>
|
||||
css levelStyle(level int) {
|
||||
margin-left: { fmt.Sprintf("%dem", level) };
|
||||
}
|
||||
|
||||
templ Post(n *models.Node, level int, withFooter bool) {
|
||||
<article id={ fmt.Sprintf("post%d", n.ID) } class={ levelStyle(level) }>
|
||||
<header class="post-header">
|
||||
<span>Пост</span>
|
||||
<span>
|
||||
{ n.Author.Username }
|
||||
в
|
||||
</span>
|
||||
<span>
|
||||
{ utils.FormatDate(n.CreatedAt) }
|
||||
<a
|
||||
href={ templ.URL(fmt.Sprintf("/n/%d#post%d", n.ParentID, n.ID)) }
|
||||
>
|
||||
#
|
||||
</a>
|
||||
</span>
|
||||
</header>
|
||||
@templ.Raw(utils.MarkdownToHTML(n.Text))
|
||||
if withFooter {
|
||||
<footer class="post-header">
|
||||
<a href={ templ.URL(fmt.Sprintf("/p/%d/new", n.ID)) }>Ответить</a>
|
||||
<a href={ templ.URL(fmt.Sprintf("/p/%d", n.ID)) }>Ответов: { strconv.Itoa(len(n.Children)) }</a>
|
||||
</footer>
|
||||
}
|
||||
</article>
|
||||
}
|
||||
|
||||
func level(node *models.Node) int {
|
||||
if node.Type == models.PostType {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
|
|
@ -12,9 +12,10 @@ import (
|
|||
"fmt"
|
||||
"gitrepo.ru/neonxp/gorum/models"
|
||||
"gitrepo.ru/neonxp/gorum/utils"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func Node(node *models.Node, nodes []*models.Node, count int) templ.Component {
|
||||
func Node(node *models.Node, topics []*models.Node, nodes []*models.Node) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
|
@ -44,73 +45,98 @@ func Node(node *models.Node, nodes []*models.Node, count int) templ.Component {
|
|||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1)
|
||||
switch node.Type {
|
||||
case models.TopicType:
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<h1>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(node.Text)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/nodes.templ`, Line: 14, Col: 19}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</h1><div><a href=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 templ.SafeURL = templ.URL(fmt.Sprintf("/t/%d/new", node.ID))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var4)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">Новая подтема</a></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
case models.PostType:
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<h1>Пост</h1>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = Post(node, 0, false).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(node.Text)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/nodes.templ`, Line: 11, Col: 17}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
for _, n := range nodes {
|
||||
if n.Type == models.TopicType {
|
||||
if len(topics) != 0 {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<table><thead><tr><th>Тема</th><th>Тем/Ответов</th><th>Дата</th><th>Автор</th></tr></thead> <tbody>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
for _, n := range topics {
|
||||
templ_7745c5c3_Err = Topic(n).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</tbody></table>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 4)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if len(nodes) == 0 {
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 5)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<strong>Постов нет</strong> ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
for _, n := range nodes {
|
||||
if n.Type == models.PostType {
|
||||
templ_7745c5c3_Err = Post(n).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = Post(n, level(node), true).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 6)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if isAuthorized(ctx) {
|
||||
templ_7745c5c3_Err = NewNode(node).Render(ctx, templ_7745c5c3_Buffer)
|
||||
templ_7745c5c3_Err = NewPostForm(node).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
} else {
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 7)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a href=\"/login\">Войдите</a> чтобы ответить в тему.")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = Layout().Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
||||
templ_7745c5c3_Err = Layout(node.Parent).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
@ -131,60 +157,73 @@ func Topic(n *models.Node) templ.Component {
|
|||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var4 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var4 == nil {
|
||||
templ_7745c5c3_Var4 = templ.NopComponent
|
||||
templ_7745c5c3_Var5 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var5 == nil {
|
||||
templ_7745c5c3_Var5 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 8)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<tr><td><a href=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var5 templ.SafeURL = templ.URL(fmt.Sprintf("/n/%d", n.ID))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var5)))
|
||||
var templ_7745c5c3_Var6 templ.SafeURL = templ.URL(fmt.Sprintf("/t/%d", n.ID))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var6)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 9)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var6 string
|
||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(n.Text)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/nodes.templ`, Line: 54, Col: 61}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 10)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var7 string
|
||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(utils.FormatDate(n.CreatedAt))
|
||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(n.Text)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/nodes.templ`, Line: 57, Col: 34}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/nodes.templ`, Line: 56, Col: 61}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 11)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></td><td>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var8 string
|
||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(n.Author.Username)
|
||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(len(n.Children)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/nodes.templ`, Line: 60, Col: 22}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/nodes.templ`, Line: 59, Col: 34}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 12)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td><td>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var9 string
|
||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(utils.FormatDate(n.CreatedAt))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/nodes.templ`, Line: 62, Col: 34}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td><td>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var10 string
|
||||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(n.Author.Username)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/nodes.templ`, Line: 65, Col: 22}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</td></tr>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
@ -192,7 +231,17 @@ func Topic(n *models.Node) templ.Component {
|
|||
})
|
||||
}
|
||||
|
||||
func Post(n *models.Node) templ.Component {
|
||||
func levelStyle(level int) templ.CSSClass {
|
||||
templ_7745c5c3_CSSBuilder := templruntime.GetBuilder()
|
||||
templ_7745c5c3_CSSBuilder.WriteString(string(templ.SanitizeCSS(`margin-left`, fmt.Sprintf("%dem", level))))
|
||||
templ_7745c5c3_CSSID := templ.CSSID(`levelStyle`, templ_7745c5c3_CSSBuilder.String())
|
||||
return templ.ComponentCSSClass{
|
||||
ID: templ_7745c5c3_CSSID,
|
||||
Class: templ.SafeCSS(`.` + templ_7745c5c3_CSSID + `{` + templ_7745c5c3_CSSBuilder.String() + `}`),
|
||||
}
|
||||
}
|
||||
|
||||
func Post(n *models.Node, level int, withFooter bool) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
|
@ -205,60 +254,69 @@ func Post(n *models.Node) templ.Component {
|
|||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var9 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var9 == nil {
|
||||
templ_7745c5c3_Var9 = templ.NopComponent
|
||||
templ_7745c5c3_Var11 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var11 == nil {
|
||||
templ_7745c5c3_Var11 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 13)
|
||||
var templ_7745c5c3_Var12 = []any{levelStyle(level)}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var12...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var10 string
|
||||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("post%d", n.ID))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/nodes.templ`, Line: 66, Col: 42}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<article id=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 14)
|
||||
var templ_7745c5c3_Var13 string
|
||||
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("post%d", n.ID))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/nodes.templ`, Line: 75, Col: 42}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var11 string
|
||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(n.Author.Username)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/nodes.templ`, Line: 70, Col: 23}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 15)
|
||||
var templ_7745c5c3_Var14 string
|
||||
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(templ.CSSClasses(templ_7745c5c3_Var12).String())
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/nodes.templ`, Line: 1, Col: 0}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var12 string
|
||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(utils.FormatDate(n.CreatedAt))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/nodes.templ`, Line: 72, Col: 35}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><header class=\"post-header\"><span>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 16)
|
||||
var templ_7745c5c3_Var15 string
|
||||
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(n.Author.Username)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/nodes.templ`, Line: 78, Col: 23}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var13 templ.SafeURL = templ.URL(fmt.Sprintf("/n/%d#post%d", n.ParentID, n.ID))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var13)))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</span> <span>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 17)
|
||||
var templ_7745c5c3_Var16 string
|
||||
templ_7745c5c3_Var16, templ_7745c5c3_Err = templ.JoinStringErrs(utils.FormatDate(n.CreatedAt))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/nodes.templ`, Line: 81, Col: 35}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var16))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</span></header>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
@ -266,10 +324,54 @@ func Post(n *models.Node) templ.Component {
|
|||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 18)
|
||||
if withFooter {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<footer class=\"post-header\"><a href=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var17 templ.SafeURL = templ.URL(fmt.Sprintf("/p/%d/new", n.ID))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var17)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">Ответить</a> <a href=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var18 templ.SafeURL = templ.URL(fmt.Sprintf("/p/%d", n.ID))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var18)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">Ответов: ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var19 string
|
||||
templ_7745c5c3_Var19, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.Itoa(len(n.Children)))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/nodes.templ`, Line: 88, Col: 101}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var19))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></footer>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</article>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func level(node *models.Node) int {
|
||||
if node.Type == models.PostType {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
<h1>
|
||||
</h1><table><thead><tr><th>Тема</th><th>Дата</th><th>Автор</th></tr></thead> <tbody>
|
||||
<tr><td colspan=\"3\"><strong>Тем нет</strong></td></tr>
|
||||
</tbody></table>
|
||||
<strong>Постов нет</strong>
|
||||
|
||||
<a href=\"/login\">Войдите</a> чтобы ответить в тему.
|
||||
<tr><td><a href=\"
|
||||
\">
|
||||
</a></td><td>
|
||||
</td><td>
|
||||
</td></tr>
|
||||
<article id=\"
|
||||
\"><header class=\"post-header\"><span>Пост</span> <span>
|
||||
в
|
||||
<a href=\"
|
||||
\">#</a></span></header>
|
||||
</article>
|
|
@ -1,7 +1,7 @@
|
|||
package views
|
||||
|
||||
templ Register(username, email string) {
|
||||
@Layout() {
|
||||
@Layout(nil) {
|
||||
<h1>Регистрация</h1>
|
||||
<form method="post">
|
||||
<label for="username">Имя пользователя:</label>
|
||||
|
|
|
@ -38,7 +38,7 @@ func Register(username, email string) templ.Component {
|
|||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 1)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<h1>Регистрация</h1><form method=\"post\"><label for=\"username\">Имя пользователя:</label> <input type=\"text\" id=\"username\" name=\"username\" required=\"true\" placeholder=\"имя пользователя\" value=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ func Register(username, email string) templ.Component {
|
|||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 2)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"> <label for=\"email\">Электропочта:</label> <input type=\"email\" id=\"email\" name=\"email\" required=\"true\" placeholder=\"имя@mail.ru\" value=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
@ -64,13 +64,13 @@ func Register(username, email string) templ.Component {
|
|||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.WriteWatchModeString(templ_7745c5c3_Buffer, 3)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"> <label for=\"password\">Пароль:</label> <input type=\"password\" id=\"password\" name=\"password\" required=\"true\" placeholder=\"пароль\"> <label for=\"password2\">Повторите пароль:</label> <input type=\"password\" id=\"password2\" name=\"password2\" required=\"true\" placeholder=\"повторите пароль\"> <input type=\"submit\" value=\"Регистрация\"></form>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = Layout().Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
||||
templ_7745c5c3_Err = Layout(nil).Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
<h1>Регистрация</h1><form method=\"post\"><label for=\"username\">Имя пользователя:</label> <input type=\"text\" id=\"username\" name=\"username\" required=\"true\" placeholder=\"имя пользователя\" value=\"
|
||||
\"> <label for=\"email\">Электропочта:</label> <input type=\"email\" id=\"email\" name=\"email\" required=\"true\" placeholder=\"имя@mail.ru\" value=\"
|
||||
\"> <label for=\"password\">Пароль:</label> <input type=\"password\" id=\"password\" name=\"password\" required=\"true\" placeholder=\"пароль\"> <label for=\"password2\">Повторите пароль:</label> <input type=\"password\" id=\"password2\" name=\"password2\" required=\"true\" placeholder=\"повторите пароль\"> <input type=\"submit\" value=\"Регистрация\"></form>
|
Loading…
Reference in a new issue