First attempt at refactoring to be easier for starting new features.

master
Zed A. Shaw 1 month ago
parent b65ccc292f
commit 12b06381ca
  1. 10
      admin/init.go
  2. 59
      admin/table/api.go
  3. 6
      admin/table/db.go
  4. 11
      admin/table/init.go
  5. 28
      admin/table/pages.go
  6. 2
      auth/handlers.go
  7. 9
      common/auth.go
  8. 19
      common/web.go
  9. 119
      static/style.css
  10. 8
      views/admin/table/contents.html
  11. 2
      views/admin/table/index.html
  12. 10
      views/admin/table/new.html
  13. 12
      views/admin/table/view.html

@ -0,0 +1,10 @@
package admin
import (
"github.com/gofiber/fiber/v2"
"MY/webapp/admin/table"
)
func Setup(app *fiber.App) {
admin_table.Setup(app)
}

@ -1,4 +1,4 @@
package admin
package admin_table
import (
"maps"
@ -7,11 +7,10 @@ import (
"github.com/gofiber/fiber/v2"
"MY/webapp/data"
. "MY/webapp/common"
"MY/webapp/auth"
)
func GetApiTableIndex(c *fiber.Ctx) error {
_, err := auth.Check(c, true)
_, err := AuthCheck(c, true)
if err != nil { return c.Redirect("/") }
var tables []string
@ -24,7 +23,7 @@ func GetApiTableIndex(c *fiber.Ctx) error {
}
func GetApiSelectAll(c *fiber.Ctx) error {
_, err := auth.Check(c, true)
_, err := AuthCheck(c, true)
if err != nil { return c.Redirect("/") }
table := c.Params("table")
@ -48,15 +47,8 @@ func GetApiSelectAll(c *fiber.Ctx) error {
return c.JSON(result)
}
func GetPageSelectAll(c *fiber.Ctx) error {
_, err := auth.Check(c, true)
if err != nil { return c.Redirect("/") }
return c.Render("admin/table/contents", fiber.Map{"Table": c.Params("table")})
}
func GetApiSelectOne(c *fiber.Ctx) error {
_, err := auth.Check(c, true)
_, err := AuthCheck(c, true)
if err != nil { return c.Redirect("/") }
table := c.Params("table")
@ -69,22 +61,8 @@ func GetApiSelectOne(c *fiber.Ctx) error {
return c.JSON(result.Interface())
}
func GetPageSelectOne(c *fiber.Ctx) error {
_, err := auth.Check(c, true)
if err != nil { return c.Redirect("/") }
table := c.Params("table")
id, err := c.ParamsInt("id", -1)
if err != nil || id < 0 { return IfErrNil(err, c) }
return c.Render("admin/table/view", fiber.Map{
"Table": table,
"Id": id,
})
}
func PostApiUpdate(c *fiber.Ctx) error {
_, err := auth.Check(c, true)
_, err := AuthCheck(c, true)
if err != nil { return c.Redirect("/") }
table := c.Params("table")
@ -98,16 +76,9 @@ func PostApiUpdate(c *fiber.Ctx) error {
return c.RedirectBack("/admin/table/", 303)
}
func GetPageInsert(c *fiber.Ctx) error {
_, err := auth.Check(c, true)
if err != nil { return c.Redirect("/") }
table := c.Params("table")
return c.Render("admin/table/new", fiber.Map{ "Table": table })
}
func GetApiInsert(c *fiber.Ctx) error {
_, err := auth.Check(c, true)
_, err := AuthCheck(c, true)
if err != nil { return c.Redirect("/") }
table := c.Params("table")
@ -117,7 +88,7 @@ func GetApiInsert(c *fiber.Ctx) error {
}
func PostApiInsert(c *fiber.Ctx) error {
_, err := auth.Check(c, true)
_, err := AuthCheck(c, true)
if err != nil { return c.Redirect("/") }
table := c.Params("table")
@ -127,13 +98,14 @@ func PostApiInsert(c *fiber.Ctx) error {
if err != nil { return IfErrNil(err, c) }
id, _, err := Insert(table, obj.Elem())
if err != nil { return IfErrNil(err, c) }
return c.Redirect(fmt.Sprintf("/admin/table/%s/%d/", table, id), 303)
}
func DeleteApi(c *fiber.Ctx) error {
_, err := auth.Check(c, true)
_, err := AuthCheck(c, true)
if err != nil { return c.Redirect("/") }
table := c.Params("table")
@ -147,18 +119,7 @@ func DeleteApi(c *fiber.Ctx) error {
return c.JSON(fiber.Map{})
}
func GetPageAdminIndex(c *fiber.Ctx) error {
_, err := auth.Check(c, true)
if err != nil { return c.Redirect("/") }
return c.Render("admin/table/index", fiber.Map{})
}
func Setup(app *fiber.App) {
app.Get("/admin/table/", GetPageAdminIndex)
app.Get("/admin/table/:table/", GetPageSelectAll)
app.Get("/admin/table/new/:table/", GetPageInsert)
app.Get("/admin/table/:table/:id/", GetPageSelectOne)
func SetupApi(app *fiber.App) {
app.Get("/api/admin/table", GetApiTableIndex)
app.Get("/api/admin/table/:table", GetApiSelectAll)
app.Get("/api/admin/table/new/:table", GetApiInsert)

@ -1,4 +1,4 @@
package admin
package admin_table
import (
"reflect"
@ -107,8 +107,11 @@ func Insert(table string, value reflect.Value) (int64, int64, error) {
builder := sq.Insert(table).Columns(columns...).Values(values...)
sql_query, args, err := builder.ToSql()
if err != nil { return -1, -1, err }
result, err := data.DB.Exec(sql_query, args...)
if err != nil { return -1, -1, err }
id, err := result.LastInsertId()
if err != nil { return -1, -1, err }
@ -136,6 +139,7 @@ func Update(table string, value reflect.Value) error {
builder = builder.Where(sq.Eq{"id": value.FieldByName("Id").Interface()})
sql_query, args, err := builder.ToSql()
if err != nil { return err }
fmt.Println("UPDATE QUERY", sql_query, args)
if err != nil { return err}

@ -0,0 +1,11 @@
package admin_table
import (
"github.com/gofiber/fiber/v2"
)
func Setup(app *fiber.App) {
SetupApi(app)
SetupPages(app)
}

@ -0,0 +1,28 @@
package admin_table
import (
"github.com/gofiber/fiber/v2"
. "MY/webapp/common"
)
func GetPageSelectOne(c *fiber.Ctx) error {
_, err := AuthCheck(c, true)
if err != nil { return c.Redirect("/") }
table := c.Params("table")
id, err := c.ParamsInt("id", -1)
if err != nil || id < 0 { return IfErrNil(err, c) }
return c.Render("admin/table/view", fiber.Map{
"table": table,
"id": id,
})
}
func SetupPages(app *fiber.App) {
AddAuthedPage(app, true, "admin/table/", "admin/table/index")
AddAuthedPage(app, true, "admin/table/:table/", "admin/table/contents")
AddAuthedPage(app, true, "admin/table/new/:table/", "admin/table/new")
app.Get("/admin/table/:table/:id/", GetPageSelectOne)
}

@ -10,7 +10,7 @@ import (
)
func GetApiAuthCheck(c *fiber.Ctx) error {
_, err := Check(c, false)
_, err := AuthCheck(c, false)
// auth failure or not authed is determined by err, with nil meaning YES AUTHED
return c.JSON(fiber.Map{"is_authed": err == nil})
}

@ -1,4 +1,4 @@
package auth
package common
import (
"errors"
@ -12,15 +12,14 @@ import (
"MY/webapp/data"
"MY/webapp/config"
"MY/webapp/common"
)
func IsAdmin(user *data.User) bool {
return user.Username == config.Settings.Admin
}
func Check(c *fiber.Ctx, needs_admin bool) (*session.Session, error) {
sess, err := common.STORE.Get(c)
func AuthCheck(c *fiber.Ctx, needs_admin bool) (*session.Session, error) {
sess, err := STORE.Get(c)
if err != nil { return sess, err }
// BUG: this has to come from the databse, just temporary
@ -42,7 +41,7 @@ func Check(c *fiber.Ctx, needs_admin bool) (*session.Session, error) {
}
func LogoutUser(c *fiber.Ctx) error {
sess, err := common.STORE.Get(c)
sess, err := STORE.Get(c)
if err != nil { return err }
err = sess.Destroy()

@ -8,6 +8,25 @@ import (
var STORE *session.Store
func AddAuthedPage(app *fiber.App, must_admin bool, url string, view string) {
handler := func(c *fiber.Ctx) error {
_, err := AuthCheck(c, must_admin)
if err != nil { return c.Redirect("/") }
return c.Render(view, c.AllParams())
}
app.Get(url, handler)
}
func AddPage(app *fiber.App, url string, view string) {
handler := func(c *fiber.Ctx) error {
return c.Render(view, c.AllParams())
}
app.Get(url, handler)
}
func Page(path string) (func(c *fiber.Ctx) error) {
page_id := strings.ReplaceAll(path, "/", "-") + "-page"

@ -60,7 +60,6 @@
--radius-md: 0.375rem;
--radius-lg: 0.5rem;
--radius-xl: 0.75rem;
--ease-out: cubic-bezier(0, 0, 0.2, 1);
--aspect-video: 16 / 9;
--default-transition-duration: 150ms;
--default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
@ -229,21 +228,9 @@
left: calc(var(--spacing) * 0);
width: 100%;
}
.absolute {
position: absolute;
}
.fixed {
position: fixed;
}
.relative {
position: relative;
}
.static {
position: static;
}
.sticky {
position: sticky;
}
.top-3 {
top: calc(var(--spacing) * 3);
}
@ -256,24 +243,6 @@
.left-40 {
left: calc(var(--spacing) * 40);
}
.container {
width: 100%;
@media (width >= 40rem) {
max-width: 40rem;
}
@media (width >= 48rem) {
max-width: 48rem;
}
@media (width >= 64rem) {
max-width: 64rem;
}
@media (width >= 80rem) {
max-width: 80rem;
}
@media (width >= 96rem) {
max-width: 96rem;
}
}
.block {
display: block;
}
@ -286,9 +255,6 @@
.grid {
display: grid;
}
.hidden {
display: none;
}
.inline {
display: inline;
}
@ -343,9 +309,6 @@
.transform {
transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);
}
.resize {
resize: both;
}
.grid-cols-2 {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
@ -431,10 +394,6 @@
}
}
}
.border {
border-style: var(--tw-border-style);
border-width: 1px;
}
.border-1 {
border-style: var(--tw-border-style);
border-width: 1px;
@ -599,18 +558,11 @@
--tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
}
.filter {
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
}
.transition {
transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, visibility, content-visibility, overlay, pointer-events;
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
transition-duration: var(--tw-duration, var(--default-transition-duration));
}
.ease-out {
--tw-ease: var(--ease-out);
transition-timing-function: var(--ease-out);
}
.\*\:text-xl {
:is(& > *) {
font-size: var(--text-xl);
@ -1161,63 +1113,6 @@ table {
inherits: false;
initial-value: 0 0 #0000;
}
@property --tw-blur {
syntax: "*";
inherits: false;
}
@property --tw-brightness {
syntax: "*";
inherits: false;
}
@property --tw-contrast {
syntax: "*";
inherits: false;
}
@property --tw-grayscale {
syntax: "*";
inherits: false;
}
@property --tw-hue-rotate {
syntax: "*";
inherits: false;
}
@property --tw-invert {
syntax: "*";
inherits: false;
}
@property --tw-opacity {
syntax: "*";
inherits: false;
}
@property --tw-saturate {
syntax: "*";
inherits: false;
}
@property --tw-sepia {
syntax: "*";
inherits: false;
}
@property --tw-drop-shadow {
syntax: "*";
inherits: false;
}
@property --tw-drop-shadow-color {
syntax: "*";
inherits: false;
}
@property --tw-drop-shadow-alpha {
syntax: "<percentage>";
inherits: false;
initial-value: 100%;
}
@property --tw-drop-shadow-size {
syntax: "*";
inherits: false;
}
@property --tw-ease {
syntax: "*";
inherits: false;
}
@property --tw-outline-style {
syntax: "*";
inherits: false;
@ -1247,20 +1142,6 @@ table {
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-offset-shadow: 0 0 #0000;
--tw-blur: initial;
--tw-brightness: initial;
--tw-contrast: initial;
--tw-grayscale: initial;
--tw-hue-rotate: initial;
--tw-invert: initial;
--tw-opacity: initial;
--tw-saturate: initial;
--tw-sepia: initial;
--tw-drop-shadow: initial;
--tw-drop-shadow-color: initial;
--tw-drop-shadow-alpha: 100%;
--tw-drop-shadow-size: initial;
--tw-ease: initial;
--tw-outline-style: solid;
}
}

@ -1,12 +1,12 @@
<script>
let thePage = new PaginateTable("/api/admin/table/{{ .Table }}");
let thePage = new PaginateTable("/api/admin/table/{{ .table }}");
</script>
<h1><a href="/admin/table/">&laquo;</a> Admin {{ .Table }}</h1>
<h1><a href="/admin/table/">&laquo;</a> Admin {{ .table }}</h1>
<block x-data="thePage">
<bar>
<button type="button"><a href="/admin/table/new/{{ .Table }}/">New</a></button>
<button type="button"><a href="/admin/table/new/{{ .table }}/">New</a></button>
<button type="button" @click="page -= 1">Prev</button>
<button type="button" @click="page += 1">Next</button>
<input type="text" x-model.debounce="search_query" name="search" size="40" placeholder="Search" />
@ -22,7 +22,7 @@
<template x-for="item in contents" :key="item.Id">
<tr class="table-row">
<td>
<a x-bind:href="'/admin/table/{{ .Table }}/' + item.Id + '/'">
<a x-bind:href="'/admin/table/{{ .table }}/' + item.Id + '/'">
#
</a>
</td>

@ -9,7 +9,7 @@
<ul>
<template x-for="item in contents">
<li>
<a x-bind:href="`/admin/table/${item}`">
<a x-bind:href="`/admin/table/${item}/`">
<span x-text="item"></span>
</a>
</li>

@ -1,11 +1,11 @@
<h1><a href="/admin/table/{{ .Table }}/">&laquo;</a>Admin {{ .Table }}</h1>
<h1><a href="/admin/table/{{ .table }}/">&laquo;</a>Admin {{ .table }}</h1>
<block x-data="{item: {}}"
x-init="item = await GetJson('/api/admin/table/new/{{ .Table }}')">
x-init="item = await GetJson('/api/admin/table/new/{{ .table }}')">
<form method="POST" action="/api/admin/table/new/{{ .Table }}">
<form method="POST" action="/api/admin/table/new/{{ .table }}">
<card>
<top><h2>New {{ .Table }}</h2></top>
<top><h2>New {{ .table }}</h2></top>
<middle>
<template x-for="(value, key) in item">
@ -17,7 +17,7 @@
</middle>
<bottom>
<button type="button"><a href="/admin/table/{{ .Table }}/">Back</a></button>
<button type="button"><a href="/admin/table/{{ .table }}/">Back</a></button>
<button class="hover:btn-alert" type="button">Clear</button>
<button class="hover:btn-hover" type="submit">Insert</button>
</bottom>

@ -1,11 +1,11 @@
<h1><a href="/admin/table/{{ .Table }}/">&laquo;</a>Admin {{ .Table }}</h1>
<h1><a href="/admin/table/{{ .table }}/">&laquo;</a>Admin {{ .table }}</h1>
<block x-data="{item: {}}"
x-init="item = await GetJson('/api/admin/table/{{ .Table }}/{{ .Id }}')">
x-init="item = await GetJson('/api/admin/table/{{ .table }}/{{ .id }}')">
<form method="POST" action="/api/admin/table/{{ .Table }}/{{ .Id }}">
<form method="POST" action="/api/admin/table/{{ .table }}/{{ .id }}">
<card>
<top><h1>{{ .Table }} : {{ .Id }}</h1></top>
<top><h1>{{ .table }} : {{ .id }}</h1></top>
<middle>
<template x-for="(value, key) in item">
<div>
@ -15,8 +15,8 @@
</template>
</middle>
<bottom>
<button type="button"><a href="/admin/table/{{ .Table }}/">Back</a></button>
<button class="hover:btn-alert" type="button" @click.prevent="ConfirmDelete('{{ .Table }}', item.Id)">Delete</button>
<button type="button"><a href="/admin/table/{{ .table }}/">Back</a></button>
<button class="hover:btn-alert" type="button" @click.prevent="ConfirmDelete('{{ .table }}', item.id)">Delete</button>
<button class="hover:btn-hover" type="submit">Update</button>
</bottom>
</card>

Loading…
Cancel
Save