in progress: adding sqlite support
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,3 +3,4 @@ app
|
||||
*.test
|
||||
*.out
|
||||
tmp
|
||||
output.css
|
||||
|
||||
@@ -4,6 +4,11 @@ COPY . .
|
||||
ENV CGO_ENABLED=0 GOOS=linux GOPROXY=direct
|
||||
RUN go build -v -o app .
|
||||
|
||||
# Install SQLite
|
||||
FROM alpine:latest as db
|
||||
RUN apk --no-cache add sqlite
|
||||
|
||||
FROM scratch
|
||||
COPY --from=db ./example.db .
|
||||
COPY --from=build /go/src/app/app /go/bin/app
|
||||
ENTRYPOINT ["/go/bin/app"]
|
||||
|
||||
4
data.go
4
data.go
@@ -1,6 +1,8 @@
|
||||
package main
|
||||
|
||||
import "strconv"
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
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/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/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/web"
|
||||
"github.com/mattn/go-sqlite3"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -40,7 +41,7 @@ func main() {
|
||||
|
||||
//add routes
|
||||
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))
|
||||
|
||||
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
sql "github.com/innocuous-symmetry/moving-mgmt/data"
|
||||
|
||||
"github.com/jritsema/gotoolbox/web"
|
||||
)
|
||||
@@ -17,9 +18,15 @@ import (
|
||||
// Cancel -> GET /company -> nothing, companys.html
|
||||
|
||||
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
|
||||
func companyAdd(r *http.Request) *web.Response {
|
||||
return web.HTML(http.StatusOK, html, "company-add.html", data, nil)
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
<body>
|
||||
<main>
|
||||
<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/>
|
||||
<span class="text-xl">Companies</span>
|
||||
<div>{{ template "companies.html" . }}</div>
|
||||
<div>{{ template "items.html" . }}</div>
|
||||
</div>
|
||||
</main>
|
||||
</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