in progress: adding sqlite support
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,3 +3,4 @@ app
|
|||||||
*.test
|
*.test
|
||||||
*.out
|
*.out
|
||||||
tmp
|
tmp
|
||||||
|
output.css
|
||||||
|
|||||||
@@ -4,6 +4,11 @@ COPY . .
|
|||||||
ENV CGO_ENABLED=0 GOOS=linux GOPROXY=direct
|
ENV CGO_ENABLED=0 GOOS=linux GOPROXY=direct
|
||||||
RUN go build -v -o app .
|
RUN go build -v -o app .
|
||||||
|
|
||||||
|
# Install SQLite
|
||||||
|
FROM alpine:latest as db
|
||||||
|
RUN apk --no-cache add sqlite
|
||||||
|
|
||||||
FROM scratch
|
FROM scratch
|
||||||
|
COPY --from=db ./example.db .
|
||||||
COPY --from=build /go/src/app/app /go/bin/app
|
COPY --from=build /go/src/app/app /go/bin/app
|
||||||
ENTRYPOINT ["/go/bin/app"]
|
ENTRYPOINT ["/go/bin/app"]
|
||||||
|
|||||||
4
data.go
4
data.go
@@ -1,6 +1,8 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import "strconv"
|
import (
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
var data []Company
|
var data []Company
|
||||||
|
|
||||||
|
|||||||
47
data/entities.go
Normal file
47
data/entities.go
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package data
|
||||||
|
|
||||||
|
// enums
|
||||||
|
type PackingStage int
|
||||||
|
type Category int
|
||||||
|
|
||||||
|
const (
|
||||||
|
Essentials PackingStage = iota
|
||||||
|
StageOne
|
||||||
|
StageTwo
|
||||||
|
StageThree
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
Bedroom Category = iota
|
||||||
|
Bathroom
|
||||||
|
Kitchen
|
||||||
|
Office
|
||||||
|
LivingRoom
|
||||||
|
Other
|
||||||
|
)
|
||||||
|
|
||||||
|
// entities
|
||||||
|
type Item struct {
|
||||||
|
ID int
|
||||||
|
Name string
|
||||||
|
Notes *string
|
||||||
|
Description *string
|
||||||
|
Stage PackingStage
|
||||||
|
Category Category
|
||||||
|
}
|
||||||
|
|
||||||
|
type Box struct {
|
||||||
|
ID int
|
||||||
|
Name string
|
||||||
|
Notes *string
|
||||||
|
Description *string
|
||||||
|
Stage PackingStage
|
||||||
|
Category Category
|
||||||
|
}
|
||||||
|
|
||||||
|
// joins
|
||||||
|
type BoxItem struct {
|
||||||
|
ID int
|
||||||
|
BoxID int
|
||||||
|
ItemID int
|
||||||
|
}
|
||||||
51
data/seed.go
Normal file
51
data/seed.go
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
package data
|
||||||
|
|
||||||
|
func getSeedData() (items []Item, boxes []Box, boxitems []BoxItem) {
|
||||||
|
items = []Item{
|
||||||
|
{
|
||||||
|
ID: 1,
|
||||||
|
Name: "Toothbrush",
|
||||||
|
Stage: Essentials,
|
||||||
|
Category: Bathroom,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: 2,
|
||||||
|
Name: "Toothpaste",
|
||||||
|
Stage: Essentials,
|
||||||
|
Category: Bathroom,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: 3,
|
||||||
|
Name: "TV",
|
||||||
|
Stage: StageTwo,
|
||||||
|
Category: Bedroom,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
ID: 4,
|
||||||
|
Name: "Micro USB Bundle",
|
||||||
|
Stage: StageOne,
|
||||||
|
Category: Office,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
plasticTubDescription := "Plastic tub with blue lid"
|
||||||
|
|
||||||
|
boxes = []Box{
|
||||||
|
{
|
||||||
|
ID: 1,
|
||||||
|
Name: "Cable Box",
|
||||||
|
Description: &plasticTubDescription,
|
||||||
|
Stage: StageOne,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
boxitems = []BoxItem{
|
||||||
|
{
|
||||||
|
ID: 1,
|
||||||
|
BoxID: 1,
|
||||||
|
ItemID: 4,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
54
data/sql.go
Normal file
54
data/sql.go
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
package data
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"github.com/mattn/go-sqlite3"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CreateClient() (db *sql.DB, err error) {
|
||||||
|
return sql.Open("sqlite3", "./example.db")
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetAllItems() (result []Item, err error) {
|
||||||
|
db, err := CreateClient()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
rows, err := db.Query("SELECT * FROM items")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
item := Item{}
|
||||||
|
|
||||||
|
err = rows.Scan(&item.ID, &item.Name, &item.Notes, &item.Description, &item.Stage, &item.Category)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result = append(result, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetItemByID(id int) (item Item, err error) {
|
||||||
|
db, err := CreateClient()
|
||||||
|
if err != nil {
|
||||||
|
return Item{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
defer db.Close()
|
||||||
|
|
||||||
|
row := db.QueryRow("SELECT * FROM items WHERE id = ?", id)
|
||||||
|
err = row.Scan(&item.ID, &item.Name, &item.Notes, &item.Description, &item.Stage, &item.Category)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
6
go.mod
6
go.mod
@@ -1,5 +1,7 @@
|
|||||||
module github.com/jritsema/go-htmx-starter
|
module github.com/innocuous-symmetry/moving-mgmt
|
||||||
|
|
||||||
go 1.20
|
go 1.22.0
|
||||||
|
|
||||||
require github.com/jritsema/gotoolbox v0.8.0
|
require github.com/jritsema/gotoolbox v0.8.0
|
||||||
|
|
||||||
|
require github.com/mattn/go-sqlite3 v1.14.22 // indirect
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -1,4 +1,4 @@
|
|||||||
github.com/jritsema/gotoolbox v0.7.0 h1:pvEf4VnB/Gjf/UYoq8T6f9vnIb7ssteGlFJEXg0Ejpo=
|
|
||||||
github.com/jritsema/gotoolbox v0.7.0/go.mod h1:OgV4sjpMB/bx/ZZPpXWvfalGrniFvkvGtqFRQH6GGHY=
|
|
||||||
github.com/jritsema/gotoolbox v0.8.0 h1:guUvlilrUcT24i0iGnasLch6pjWJ437Qnabk6WTmPEU=
|
github.com/jritsema/gotoolbox v0.8.0 h1:guUvlilrUcT24i0iGnasLch6pjWJ437Qnabk6WTmPEU=
|
||||||
github.com/jritsema/gotoolbox v0.8.0/go.mod h1:OgV4sjpMB/bx/ZZPpXWvfalGrniFvkvGtqFRQH6GGHY=
|
github.com/jritsema/gotoolbox v0.8.0/go.mod h1:OgV4sjpMB/bx/ZZPpXWvfalGrniFvkvGtqFRQH6GGHY=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
||||||
|
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||||
|
|||||||
3
main.go
3
main.go
@@ -13,6 +13,7 @@ import (
|
|||||||
|
|
||||||
"github.com/jritsema/gotoolbox"
|
"github.com/jritsema/gotoolbox"
|
||||||
"github.com/jritsema/gotoolbox/web"
|
"github.com/jritsema/gotoolbox/web"
|
||||||
|
"github.com/mattn/go-sqlite3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -40,7 +41,7 @@ func main() {
|
|||||||
|
|
||||||
//add routes
|
//add routes
|
||||||
router := http.NewServeMux()
|
router := http.NewServeMux()
|
||||||
router.Handle("/css/output.css", http.FileServer(http.FS(css)))
|
// router.Handle("/css/output.css", http.FileServer(http.FS(css)))
|
||||||
|
|
||||||
router.Handle("/company/add", web.Action(companyAdd))
|
router.Handle("/company/add", web.Action(companyAdd))
|
||||||
router.Handle("/company/add/", web.Action(companyAdd))
|
router.Handle("/company/add/", web.Action(companyAdd))
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
sql "github.com/innocuous-symmetry/moving-mgmt/data"
|
||||||
|
|
||||||
"github.com/jritsema/gotoolbox/web"
|
"github.com/jritsema/gotoolbox/web"
|
||||||
)
|
)
|
||||||
@@ -17,9 +18,15 @@ import (
|
|||||||
// Cancel -> GET /company -> nothing, companys.html
|
// Cancel -> GET /company -> nothing, companys.html
|
||||||
|
|
||||||
func index(r *http.Request) *web.Response {
|
func index(r *http.Request) *web.Response {
|
||||||
return web.HTML(http.StatusOK, html, "index.html", data, nil)
|
result, err := sql.GetAllItems()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return web.HTML(http.StatusOK, html, "index.html", result, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// GET /company/add
|
// GET /company/add
|
||||||
func companyAdd(r *http.Request) *web.Response {
|
func companyAdd(r *http.Request) *web.Response {
|
||||||
return web.HTML(http.StatusOK, html, "company-add.html", data, nil)
|
return web.HTML(http.StatusOK, html, "company-add.html", data, nil)
|
||||||
|
|||||||
@@ -11,10 +11,10 @@
|
|||||||
<body>
|
<body>
|
||||||
<main>
|
<main>
|
||||||
<div class="md:container md:mx-auto">
|
<div class="md:container md:mx-auto">
|
||||||
<h1 class="text-3xl">Go + HTMX + Tailwind Example</h1>
|
<h1 class="text-3xl">Mikayla's Move Manager</h1>
|
||||||
<br/>
|
<br/>
|
||||||
<span class="text-xl">Companies</span>
|
<span class="text-xl">Companies</span>
|
||||||
<div>{{ template "companies.html" . }}</div>
|
<div>{{ template "items.html" . }}</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
31
templates/item-row.html
Normal file
31
templates/item-row.html
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<tr id="datarow-{{.ID}}" class="border-b dark:border-neutral-500">
|
||||||
|
<td class="whitespace-nowrap px-6 py-4">{{.ID}}</td>
|
||||||
|
<td class="whitespace-nowrap px-6 py-4">{{.Name}}</td>
|
||||||
|
<td class="whitespace-nowrap px-6 py-4">{{.Stage}}</td>
|
||||||
|
<td class="whitespace-nowrap px-6 py-4">{{.Category}}</td>
|
||||||
|
<td class="whitespace-nowrap px-6 py-4">{{.Description}}</td>
|
||||||
|
<td class="whitespace-nowrap px-6 py-4">{{.Notes}}</td>
|
||||||
|
<td class="whitespace-nowrap px-1 py-1">
|
||||||
|
<a
|
||||||
|
hx-get="/company/edit/{{.ID}}"
|
||||||
|
hx-target="#datarow-{{.ID}}"
|
||||||
|
hx-swap="outerHTML"
|
||||||
|
hx-indicator="#processing"
|
||||||
|
class="hover:underline text-blue-700"
|
||||||
|
href=""
|
||||||
|
>
|
||||||
|
Edit
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td class="whitespace-nowrap px-1 py-1">
|
||||||
|
<a
|
||||||
|
hx-delete="/company/{{.ID}}"
|
||||||
|
hx-target="#companies"
|
||||||
|
hx-confirm="Are you sure you want to delete {{.Company}}?"
|
||||||
|
hx-indicator="#processing"
|
||||||
|
class="hover:underline text-blue-700"
|
||||||
|
href=""
|
||||||
|
>Delete</a
|
||||||
|
>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
40
templates/items.html
Normal file
40
templates/items.html
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<div id="companies">
|
||||||
|
<div id="processing" class="htmx-indicator">Processing...</div>
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<div class="overflow-x-auto sm:-mx-6 lg:-mx-8">
|
||||||
|
<div class="inline-block min-w-full py-2 sm:px-6 lg:px-8">
|
||||||
|
<div class="overflow-hidden">
|
||||||
|
<!-- <div class="flex justify-end">
|
||||||
|
<button
|
||||||
|
hx-get="/company/add"
|
||||||
|
hx-target="#table-body"
|
||||||
|
hx-swap="outerHTML"
|
||||||
|
hx-indicator="#processing"
|
||||||
|
class="inline-flex items-center h-8 px-4 m-2 text-sm text-blue-100 transition-colors duration-150 bg-blue-700 rounded-lg focus:shadow-outline hover:bg-blue-800"
|
||||||
|
href=""
|
||||||
|
>
|
||||||
|
Add
|
||||||
|
</button>
|
||||||
|
</div> -->
|
||||||
|
<table class="min-w-full text-left text-sm font-light">
|
||||||
|
<thead class="border-b font-medium dark:border-neutral-500">
|
||||||
|
<tr>
|
||||||
|
<th scope="col" class="px-6 py-4">#</th>
|
||||||
|
<th scope="col" class="px-6 py-4">Name</th>
|
||||||
|
<th scope="col" class="px-6 py-4">Stage</th>
|
||||||
|
<th scope="col" class="px-6 py-4">Category</th>
|
||||||
|
<th scope="col" class="px-6 py-4">Description</th>
|
||||||
|
<th scope="col" class="px-6 py-4">Notes</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="table-body">
|
||||||
|
{{range .}}
|
||||||
|
{{ template "item-row.html". }}
|
||||||
|
{{end}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
Reference in New Issue
Block a user