Skip to content
Snippets Groups Projects
Unverified Commit 3aabe782 authored by Kevin Lyda's avatar Kevin Lyda
Browse files

Get static website working

parent eb90c0a6
Branches
No related tags found
No related merge requests found
# Boxes - a home inventory system
I live out in the country and have a number of hobbies. Some projects
require certain tools or materials which can take time to acquire.
In an effort to make this easier to organise, I wanted a way to store
information on where I put things over the weeks, months and years it
takes to gain the skills or things I need.
The model for this app is that contents go in boxes and boxes go in
locations. Contents can be tagged. So you can have a "bird house"
tag for a bird house project and look for where all the things you need
for a bird house.
## References
* Simple PWA [tutorial](https://www.geeksforgeeks.org/making-a-simple-pwa-under-5-minutes/)
and also [this tutorial](https://viblo.asia/p/creating-a-basic-progressive-web-app-using-vanillajs-m68Z0RVX5kG)
* App manifest [generator](https://app-manifest.firebaseapp.com/)
* Echo [embed resources](https://echo.labstack.com/docs/cookbook/embed-resources)
* [Mithril](https://mithril.js.org/)
* Pure Go [database/sql](https://pkg.go.dev/database/sql) implementation
of a [sqlite driver](https://pkg.go.dev/modernc.org/sqlite)
* [sqlc docs](https://docs.sqlc.dev/en/latest/index.html)
* [sqlite docs](https://www.sqlite.org/docs.html)
......@@ -15,7 +15,7 @@ servers:
- url: https://localhost:8080/
paths:
/location/{lid}:
/api/location/{lid}:
get:
summary: Location
description: Get a location.
......@@ -89,7 +89,7 @@ paths:
'404':
$ref: '#/components/responses/Error'
/locations:
/api/locations:
get:
summary: Locations
description: Get a list of locations.
......@@ -104,7 +104,7 @@ paths:
'500':
$ref: '#/components/responses/Error'
/box/{bid}:
/api/box/{bid}:
get:
summary: Get a box
description: |
......@@ -180,7 +180,7 @@ paths:
'404':
$ref: '#/components/responses/Error'
/boxes:
/api/boxes:
get:
summary: Boxes
description: Get a list of boxes.
......@@ -196,7 +196,7 @@ paths:
'500':
$ref: '#/components/responses/Error'
/content/{cid}:
/api/content/{cid}:
get:
summary: Content
description: Get a content.
......@@ -270,7 +270,7 @@ paths:
'404':
$ref: '#/components/responses/Error'
/contents:
/api/contents:
get:
summary: Contents
description: Get a list of contents.
......
......@@ -82,4 +82,16 @@ SELECT * FROM contents;
SELECT * FROM contents
WHERE description LIKE ?;
-- name: GetContentsWithBox :many
SELECT * FROM contents
WHERE box = ?;
-- name: GetContentsWithLocation :many
SELECT c.* FROM contents AS c, boxes AS b
WHERE c.box = b.id AND b.location = ?;
-- name: GetContentsWithTag :many
SELECT * FROM contents
WHERE tags LIKE ?;
-- vim:et
......@@ -135,10 +135,24 @@ func (ep *Endpoints) DeleteContent(ctx context.Context, req api.DeleteContentReq
func (ep *Endpoints) GetContents(ctx context.Context, req api.GetContentsRequestObject) (api.GetContentsResponseObject, error) {
var contents []store.Content
var err error
if req.Params.Filter == nil {
if req.Params.Filter != nil {
contents, err = ep.db.GetContentsWithFilter(ctx, fmt.Sprintf("%%%s%%", *req.Params.Filter))
} else if req.Params.Box == nil {
contents, err = ep.db.GetContentsWithBox(ctx, *req.Params.Box)
} else if req.Params.Location == nil {
contents, err = ep.db.GetContentsWithLocation(ctx, *req.Params.Location)
} else if req.Params.Tags == nil {
if len(*req.Params.Tags) == 1 {
contents, err = ep.db.GetContentsWithTag(ctx, sql.NullString{
String: fmt.Sprintf("%%,%s,%%", (*req.Params.Tags)[0]),
Valid: true,
})
} else {
// TODO: figure out more than one tag.
contents, err = ep.db.GetContents(ctx)
}
} else {
contents, err = ep.db.GetContentsWithFilter(ctx, fmt.Sprintf("%%%s%%", *req.Params.Filter))
contents, err = ep.db.GetContents(ctx)
}
if err != nil {
log.Printf("error: %+v", err)
......
......@@ -5,12 +5,16 @@ import (
"context"
"database/sql"
"fmt"
"io/fs"
"mime"
"net/http"
// The sqlite db and migration driver.
_ "github.com/golang-migrate/migrate/v4/database/sqlite"
"git.lyda.ie/kevin/boxes/api"
"git.lyda.ie/kevin/boxes/database"
"git.lyda.ie/kevin/boxes/web"
"github.com/golang-migrate/migrate/v4"
"github.com/golang-migrate/migrate/v4/source/iofs"
"github.com/labstack/echo/v4"
......@@ -19,6 +23,10 @@ import (
"modernc.org/sqlite"
)
func init() {
mime.AddExtensionType(".ico", "image/vnd.microsoft.icon")
}
// Run starts the metrics and API servers.
func Run(cmd *cobra.Command, _ []string) {
// Get configuration and basic pieces.
......@@ -55,6 +63,14 @@ func Run(cmd *cobra.Command, _ []string) {
db, err := sql.Open("sqlite", dbfile)
cobra.CheckErr(err)
// Get the static files served.
filesTree, err := fs.Sub(web.Files, "files")
cobra.CheckErr(err)
filesHandler := http.FileServer(http.FS(filesTree))
e.GET("/", echo.WrapHandler(filesHandler))
e.GET("/*.*", echo.WrapHandler(filesHandler))
//e.GET("/images/*", echo.WrapHandler(http.StripPrefix("/images/", filesHandler)))
// Get the endpoint handler set up.
endpoints := NewEndpoints(db)
server := api.NewStrictHandler(endpoints, nil)
......
web/files/favicon.ico

1.12 KiB

web/files/images/icon-192x192.png

4.25 KiB

web/files/images/icon-512x512.png

12 KiB

<!DOCTYPE html>
<html>
<head>
<!-- Responsive -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<!-- Title -->
<title>PWA Tutorial</title>
<!-- Meta Tags required for
Progressive Web App -->
<meta name="apple-mobile-web-app-status-bar" content="#aa7700">
<meta name="theme-color" content="black">
<!-- Manifest File link -->
<link rel="manifest" href="manifest.json">
</head>
<body>
<h1>Boxes</h1>
<div id="app"></div>
<footer>
<p>Credits:</p>
<ul>
<li><a href="https://www.flaticon.com/free-icons/open-box" title="open box icons">Open box icons created by yoyonpujiono - Flaticon</a></li>
</ul>
</footer>
<!--
<script src="https://cdnjs.cloudflare.com/ajax/libs/mithril/2.2.11/mithril.min.js" integrity="sha512-2/N5u5OSxz7VyKmGbko8Jwx6o8fudoJ70t/Nvu16UoKCyqeDNfvxkDTmj11ibe4fwXSDdojQAxuV+y1Ut1JSkQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/mithril/2.2.11/mithril.js" integrity="sha512-HQxrYG+jkimFdOc2fdtpe7urylm7yRsmYekrLMACDZk8GwF7UBnEfjG/e86r+lPUvfNsifVdQKK5iS6IBe70Og==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script>
var LocationsRoute = {
view: function() {
return m("p", "TODO: a list of locations");
}
}
var BoxesRoute = {
view: function() {
return m("p", "TODO: a list of boxes");
}
}
var ContentsRoute = {
view: function() {
return m("p", "TODO: a list of contents");
}
}
window.addEventListener('load', () => {
registerSW();
var root = document.getElementById("app");
m.route(root,
"/", {
"/": LocationsRoute,
"/locations": LocationsRoute,
"/Boxes": BoxesRoute,
"/Contents": ContentsRoute,
}
);
});
// Register the Service Worker
async function registerSW() {
if ('serviceWorker' in navigator) {
try {
await navigator
.serviceWorker
.register('serviceworker.js');
}
catch (e) {
console.log('SW registration failed');
}
}
console.log('SW registration succeeded');
}
</script>
</body>
</html>
{
"name":"Boxes",
"short_name":"PWA",
"start_url":"index.html",
"display":"standalone",
"background_color":"#5900b3",
"theme_color":"black",
"scope": ".",
"description":"This is a home inventory tool.",
"icons":[
{
"src":"images/icon-192x192.png",
"sizes":"192x192",
"type":"image/png"
},
{
"src":"images/icon-512x512.png",
"sizes":"512x512",
"type":"image/png"
}
]
}
var staticCacheName = "pwa";
self.addEventListener("install", function (e) {
e.waitUntil(
caches.open(staticCacheName).then(function (cache) {
return cache.addAll(["/"]);
})
);
});
self.addEventListener("fetch", function (event) {
console.log(event.request.url);
event.respondWith(
caches.match(event.request).then(function (response) {
return response || fetch(event.request);
})
);
});
// Package web contains the files for the static web elements.
package web
import "embed"
// Files contains all the static files that make up the website.
//
//go:embed files
var Files embed.FS
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment