really liking templ
- made multiple components for reuse in templ - going to start on actual data displaying templates
12
.air.toml
@ -5,18 +5,18 @@ tmp_dir = "tmp"
|
||||
[build]
|
||||
args_bin = []
|
||||
bin = "./tmp/main"
|
||||
pre_cmd = ["templ generate", "npx tailwindcss -i css/style.css -o public/css/style.css"]
|
||||
cmd = "go build -o ./tmp/main ."
|
||||
pre_cmd = [""]
|
||||
cmd = "templ generate && npx tailwindcss -i css/style.css -o public/css/style.css && go build -o ./tmp/main ."
|
||||
delay = 1000
|
||||
exclude_dir = ["tmp", "vendor", "testdata", "node_modules"]
|
||||
exclude_dir = ["tmp", "vendor", "testdata", "node_modules", "public"]
|
||||
exclude_file = []
|
||||
exclude_regex = ["_test.go", ".*_templ.go"]
|
||||
exclude_regex = ["_test.go", "_templ.go"]
|
||||
exclude_unchanged = false
|
||||
follow_symlink = false
|
||||
full_bin = ""
|
||||
include_dir = []
|
||||
include_ext = ["go", "css", "templ"]
|
||||
include_file = ["tailwind.config.js"]
|
||||
include_ext = ["go", "css", "templ", "config.js"]
|
||||
include_file = []
|
||||
kill_delay = "0s"
|
||||
log = "build-errors.log"
|
||||
poll = false
|
||||
|
@ -7,4 +7,9 @@
|
||||
.notimpl {
|
||||
@apply italic font-light list-image-possible;
|
||||
}
|
||||
|
||||
div.infobox {
|
||||
@apply m-2 px-4 pt-2 flex-col shadow-md rounded-2xl border-8 border-double;
|
||||
@apply divide-solid divide-y-2;
|
||||
}
|
||||
}
|
||||
|
8
go.mod
@ -2,10 +2,8 @@ module git.staur.ca/stobbsm/clustvirt
|
||||
|
||||
go 1.22.1
|
||||
|
||||
require libvirt.org/go/libvirt v1.10001.0
|
||||
|
||||
require (
|
||||
github.com/a-h/templ v0.2.598 // indirect
|
||||
github.com/go-chi/chi/v5 v5.0.12 // indirect
|
||||
gopkg.in/ffmt.v1 v1.5.6 // indirect
|
||||
github.com/a-h/templ v0.2.598
|
||||
github.com/go-chi/chi/v5 v5.0.12
|
||||
libvirt.org/go/libvirt v1.10001.0
|
||||
)
|
||||
|
4
go.sum
@ -2,7 +2,7 @@ github.com/a-h/templ v0.2.598 h1:6jMIHv6wQZvdPxTuv87erW4RqN/FPU0wk7ZHN5wVuuo=
|
||||
github.com/a-h/templ v0.2.598/go.mod h1:SA7mtYwVEajbIXFRh3vKdYm/4FYyLQAtPH1+KxzGPA8=
|
||||
github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s=
|
||||
github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
gopkg.in/ffmt.v1 v1.5.6 h1:4Bu3riZp5sAIXW2T/18JM9BkwJLodurXFR0f7PXp+cw=
|
||||
gopkg.in/ffmt.v1 v1.5.6/go.mod h1:LssvGOZFiBGoBcobkTqnyh+uN1VzIRoibW+c0JI/Ha4=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
libvirt.org/go/libvirt v1.10001.0 h1:lEVDNE7xfzmZXiDEGIS8NvJSuaz11OjRXw+ufbQEtPY=
|
||||
libvirt.org/go/libvirt v1.10001.0/go.mod h1:1WiFE8EjZfq+FCVog+rvr1yatKbKZ9FaFMZgEqxEJqQ=
|
||||
|
11
main.go
@ -40,16 +40,7 @@ func main() {
|
||||
}
|
||||
fs.ServeHTTP(w, r)
|
||||
})
|
||||
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
if DEBUG {
|
||||
w.Header().Add("Cache-Control", "no-cache, no-store, must-revalidate")
|
||||
w.Header().Add("Pragma", "no-cache")
|
||||
w.Header().Add("Expire", "0")
|
||||
}
|
||||
w.Header().Add("Content", "text/html")
|
||||
log.Println(view.ViewHome.Render(w, nil))
|
||||
})
|
||||
r.Get("/", view.HomePage)
|
||||
|
||||
log.Println(http.ListenAndServe(":3000", r))
|
||||
}
|
||||
|
41897
public/css/style.css
@ -38,7 +38,7 @@
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="m 8.3076888,12.923076 2.7692302,2.769231 4.615384,-6.4615418 m 7.384614,2.7692328 a 11.076921,11.076928 0 1 1 -22.15384198,0 11.076921,11.076928 0 0 1 22.15384198,0 z"
|
||||
d="m 6.9230763,14.767385 2.3076926,2.307694 3.8461551,-5.38462 m 6.153846,2.307695 a 9.2307704,9.2307764 0 1 1 -18.46154043,0 9.2307704,9.2307764 0 0 1 18.46154043,0 z"
|
||||
id="path1"
|
||||
style="stroke-width:1.84615;stroke:#d6d6d6;stroke-opacity:1" />
|
||||
style="stroke:#d6d6d6;stroke-width:1.53846;stroke-opacity:1" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
@ -29,16 +29,16 @@
|
||||
inkscape:zoom="9.8333333"
|
||||
inkscape:cx="9.7627119"
|
||||
inkscape:cy="9.7627119"
|
||||
inkscape:window-width="1312"
|
||||
inkscape:window-height="449"
|
||||
inkscape:window-width="1440"
|
||||
inkscape:window-height="847"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="25"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg1" />
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="m 11.076927,11.076927 0.05046,-0.02462 a 0.92307691,0.9230774 0 0 1 1.308308,1.048616 l -0.871384,3.490464 a 0.92307691,0.9230774 0 0 0 1.308308,1.049846 l 0.05046,-0.02585 m 10.153842,-4.615384 a 11.076923,11.076929 0 1 1 -22.15384598,0 11.076923,11.076929 0 0 1 22.15384598,0 z M 12.000004,7.3846176 h 0.0098 v 0.00985 h -0.0098 z"
|
||||
d="m 9.2307739,13.229418 0.04205,-0.02052 a 0.76923083,0.76923136 0 0 1 1.0902571,0.873847 l -0.7261531,2.908721 a 0.76923083,0.76923136 0 0 0 1.0902561,0.874872 l 0.04205,-0.02154 m 8.461536,-3.846154 a 9.23077,9.2307764 0 1 1 -18.46153989,0 9.23077,9.2307764 0 0 1 18.46153989,0 z m -9.230765,-3.846151 h 0.0082 v 0.0082 h -0.0082 z"
|
||||
id="path1"
|
||||
style="stroke:#d6d6d6;stroke-width:1.84615;stroke-opacity:1" />
|
||||
style="stroke:#d6d6d6;stroke-width:1.53846;stroke-opacity:1" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
@ -38,7 +38,7 @@
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M 19.833912,19.783417 A 11.082911,11.052709 0 0 0 4.1603098,4.1525257 M 19.833912,19.783417 A 11.082911,11.052709 0 0 1 4.1603098,4.1525257 M 19.833912,19.783417 4.1603098,4.1525257"
|
||||
d="M 16.532287,20.52382 A 9.23747,9.2323036 0 0 0 3.4685327,7.4673718 M 16.532287,20.52382 A 9.23747,9.2323036 0 0 1 3.4685327,7.4673718 M 16.532287,20.52382 3.4685327,7.4673718"
|
||||
id="path1"
|
||||
style="stroke:#d6d6d6;stroke-width:1.84462;stroke-opacity:1" />
|
||||
style="stroke:#d6d6d6;stroke-width:1.53913;stroke-opacity:1" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
@ -38,7 +38,7 @@
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M 15.692306,11.999999 H 8.3076904 m 14.7692306,0 a 11.076923,11.076929 0 1 1 -22.15384598,0 11.076923,11.076929 0 0 1 22.15384598,0 z"
|
||||
d="M 13.076923,13.99792 H 6.9230762 m 12.3076928,0 a 9.23077,9.2307764 0 1 1 -18.46153955,0 9.23077,9.2307764 0 0 1 18.46153955,0 z"
|
||||
id="path1"
|
||||
style="stroke:#d6d6d6;stroke-width:1.84615;stroke-opacity:1" />
|
||||
style="stroke:#d6d6d6;stroke-width:1.53846;stroke-opacity:1" />
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.4 KiB |
@ -1,6 +1,14 @@
|
||||
/** @type {import('tailwindcss').Config} */
|
||||
module.exports = {
|
||||
content: ["**/*.templ", "**/*.go"],
|
||||
safelist: [
|
||||
{
|
||||
pattern: /(bg|text|shadow|divide|border)-(aro|blade|buffy|cullen|dracula|lincoln|marcelin|morbius|nosferatu|vanhelsing|voncount)-[0-9]+/,
|
||||
},
|
||||
{
|
||||
pattern: /list-image-(accepted|informational|never|possible)/,
|
||||
},
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
listStyleImage: {
|
||||
|
15
view/components/anchor.templ
Normal file
@ -0,0 +1,15 @@
|
||||
package components
|
||||
|
||||
templ A(href string, text string) {
|
||||
<a href={ templ.URL(href) }
|
||||
class={
|
||||
"after:content-link",
|
||||
"after:w-3",
|
||||
"after:h-3",
|
||||
"after:inline-block",
|
||||
"after:invert",
|
||||
"text-base",
|
||||
"text-morbius-100" }>
|
||||
{ text }
|
||||
</a>
|
||||
}
|
77
view/components/anchor_templ.go
Normal file
@ -0,0 +1,77 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.598
|
||||
package components
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import "context"
|
||||
import "io"
|
||||
import "bytes"
|
||||
|
||||
func A(href string, text string) templ.Component {
|
||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
var templ_7745c5c3_Var2 = []any{
|
||||
"after:content-link",
|
||||
"after:w-3",
|
||||
"after:h-3",
|
||||
"after:inline-block",
|
||||
"after:invert",
|
||||
"text-base",
|
||||
"text-morbius-100"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, 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(href)
|
||||
_, 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("\" class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var2).String()))
|
||||
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_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/anchor.templ`, Line: 12, Col: 10}
|
||||
}
|
||||
_, 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("</a>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
13
view/components/contentlist.templ
Normal file
@ -0,0 +1,13 @@
|
||||
package components
|
||||
|
||||
import "fmt"
|
||||
|
||||
templ ContentList(listImage string, items []string) {
|
||||
<ul class={
|
||||
"list-inside",
|
||||
fmt.Sprintf("list-image-%s", listImage) }>
|
||||
for _, li := range items {
|
||||
<li>{ li }</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
75
view/components/contentlist_templ.go
Normal file
@ -0,0 +1,75 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.598
|
||||
package components
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import "context"
|
||||
import "io"
|
||||
import "bytes"
|
||||
|
||||
import "fmt"
|
||||
|
||||
func ContentList(listImage string, items []string) templ.Component {
|
||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
var templ_7745c5c3_Var2 = []any{
|
||||
"list-inside",
|
||||
fmt.Sprintf("list-image-%s", listImage)}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<ul class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var2).String()))
|
||||
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
|
||||
}
|
||||
for _, li := range items {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(li)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/contentlist.templ`, Line: 9, Col: 10}
|
||||
}
|
||||
_, 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("</li>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</ul>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
5
view/components/contentp.templ
Normal file
@ -0,0 +1,5 @@
|
||||
package components
|
||||
|
||||
templ ContentP(content string) {
|
||||
<p>{ content }</p>
|
||||
}
|
48
view/components/contentp_templ.go
Normal file
@ -0,0 +1,48 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.598
|
||||
package components
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import "context"
|
||||
import "io"
|
||||
import "bytes"
|
||||
|
||||
func ContentP(content string) templ.Component {
|
||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
}
|
||||
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_7745c5c3_Buffer.WriteString("<p>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(content)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/contentp.templ`, Line: 3, Col: 14}
|
||||
}
|
||||
_, 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_7745c5c3_Buffer.WriteString("</p>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
14
view/components/flexrow.templ
Normal file
@ -0,0 +1,14 @@
|
||||
package components
|
||||
|
||||
templ FlexRow(wrap bool, comps ...templ.Component) {
|
||||
<div class={
|
||||
"flex",
|
||||
templ.KV("flex-nowrap", !wrap),
|
||||
templ.KV("flex-wrap", wrap),
|
||||
templ.KV("md:flex-nowrap", wrap)
|
||||
}>
|
||||
for _, cmp := range comps {
|
||||
@cmp
|
||||
}
|
||||
</div>
|
||||
}
|
62
view/components/flexrow_templ.go
Normal file
@ -0,0 +1,62 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.598
|
||||
package components
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import "context"
|
||||
import "io"
|
||||
import "bytes"
|
||||
|
||||
func FlexRow(wrap bool, comps ...templ.Component) templ.Component {
|
||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
var templ_7745c5c3_Var2 = []any{
|
||||
"flex",
|
||||
templ.KV("flex-nowrap", !wrap),
|
||||
templ.KV("flex-wrap", wrap),
|
||||
templ.KV("md:flex-nowrap", wrap)}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var2).String()))
|
||||
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
|
||||
}
|
||||
for _, cmp := range comps {
|
||||
templ_7745c5c3_Err = cmp.Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
46
view/components/index.templ
Normal file
@ -0,0 +1,46 @@
|
||||
package components
|
||||
|
||||
templ Index(content ...templ.Component) {
|
||||
<!DOCTYPE html>
|
||||
<html class={ "text-nosferatu-100" , "bg-nosferatu-900" }>
|
||||
|
||||
<head>
|
||||
<title>Clustvirt</title>
|
||||
<link href="/static/css/style.css" type="text/css" rel="stylesheet" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<header>
|
||||
@header()
|
||||
</header>
|
||||
<div id="content" name="content">
|
||||
for _, cnt := range content {
|
||||
@cnt
|
||||
}
|
||||
</div>
|
||||
<footer>
|
||||
@footer()
|
||||
</footer>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
}
|
||||
|
||||
templ header() {
|
||||
<h1 class={ "text-2xl", "font-bold" }>Clustvirt</h1>
|
||||
<h2 class={ "text-sm", "font-thin", "italic" }>Libvirtd simplified and clustered</h2>
|
||||
<nav>
|
||||
<ul>
|
||||
<li>Server 1</li>
|
||||
<li>Server 2</li>
|
||||
</ul>
|
||||
</nav>
|
||||
}
|
||||
|
||||
templ footer() {
|
||||
<div class="flex gap-4 md:gap-6 sm:gap-8 divide divide-solid">
|
||||
<div id="footer_left" class="flex-auto basis-1/4 md:basis-1/3 p-2">Left</div>
|
||||
<div id="footer_middle" class="flex-auto basis-1/2 md:basis-1/3 p-2">Middle</div>
|
||||
<div id="footer_right" class="flex-auto basis-1/4 md:basis-1/3 p-2">Right</div>
|
||||
</div>
|
||||
}
|
156
view/components/index_templ.go
Normal file
@ -0,0 +1,156 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.598
|
||||
package components
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import "context"
|
||||
import "io"
|
||||
import "bytes"
|
||||
|
||||
func Index(content ...templ.Component) templ.Component {
|
||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
}
|
||||
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_7745c5c3_Buffer.WriteString("<!doctype html>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var2 = []any{"text-nosferatu-100", "bg-nosferatu-900"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<html class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var2).String()))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><head><title>Clustvirt</title><link href=\"/static/css/style.css\" type=\"text/css\" rel=\"stylesheet\"></head><body><header>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = header().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</header><div id=\"content\" name=\"content\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
for _, cnt := range content {
|
||||
templ_7745c5c3_Err = cnt.Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><footer>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = footer().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</footer></body></html>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func header() templ.Component {
|
||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var3 == nil {
|
||||
templ_7745c5c3_Var3 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
var templ_7745c5c3_Var4 = []any{"text-2xl", "font-bold"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var4...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<h1 class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var4).String()))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">Clustvirt</h1>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var5 = []any{"text-sm", "font-thin", "italic"}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var5...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<h2 class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var5).String()))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">Libvirtd simplified and clustered</h2><nav><ul><li>Server 1</li><li>Server 2</li></ul></nav>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func footer() templ.Component {
|
||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var6 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var6 == nil {
|
||||
templ_7745c5c3_Var6 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex gap-4 md:gap-6 sm:gap-8 divide divide-solid\"><div id=\"footer_left\" class=\"flex-auto basis-1/4 md:basis-1/3 p-2\">Left</div><div id=\"footer_middle\" class=\"flex-auto basis-1/2 md:basis-1/3 p-2\">Middle</div><div id=\"footer_right\" class=\"flex-auto basis-1/4 md:basis-1/3 p-2\">Right</div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
@ -1 +1,24 @@
|
||||
package components
|
||||
|
||||
import "fmt"
|
||||
|
||||
type InfoBoxConfig struct {
|
||||
ColourClass string
|
||||
InFlex bool
|
||||
FlexBasis string
|
||||
}
|
||||
|
||||
templ InfoBox(ibc InfoBoxConfig, title string, child templ.Component) {
|
||||
<div class={
|
||||
"infobox",
|
||||
fmt.Sprintf("bg-%s-900", ibc.ColourClass),
|
||||
fmt.Sprintf("text-%s-100", ibc.ColourClass),
|
||||
fmt.Sprintf("shadow-%s-900", ibc.ColourClass),
|
||||
fmt.Sprintf("divide-%s-800", ibc.ColourClass),
|
||||
fmt.Sprintf("border-%s-800", ibc.ColourClass),
|
||||
templ.KV(ibc.FlexBasis, ibc.InFlex),
|
||||
}>
|
||||
<h3 class="text-xl font-semibold">{ title }</h3>
|
||||
@child
|
||||
</div>
|
||||
}
|
||||
|
85
view/components/infobox_templ.go
Normal file
@ -0,0 +1,85 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.598
|
||||
package components
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import "context"
|
||||
import "io"
|
||||
import "bytes"
|
||||
|
||||
import "fmt"
|
||||
|
||||
type InfoBoxConfig struct {
|
||||
ColourClass string
|
||||
InFlex bool
|
||||
FlexBasis string
|
||||
}
|
||||
|
||||
func InfoBox(ibc InfoBoxConfig, title string, child templ.Component) templ.Component {
|
||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
templ_7745c5c3_Buffer = templ.GetBuffer()
|
||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
var templ_7745c5c3_Var2 = []any{
|
||||
"infobox",
|
||||
fmt.Sprintf("bg-%s-900", ibc.ColourClass),
|
||||
fmt.Sprintf("text-%s-100", ibc.ColourClass),
|
||||
fmt.Sprintf("shadow-%s-900", ibc.ColourClass),
|
||||
fmt.Sprintf("divide-%s-800", ibc.ColourClass),
|
||||
fmt.Sprintf("border-%s-800", ibc.ColourClass),
|
||||
templ.KV(ibc.FlexBasis, ibc.InFlex),
|
||||
}
|
||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var2).String()))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><h3 class=\"text-xl font-semibold\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/infobox.templ`, Line: 20, Col: 43}
|
||||
}
|
||||
_, 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("</h3>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = child.Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
8
view/components/util.go
Normal file
@ -0,0 +1,8 @@
|
||||
package components
|
||||
|
||||
import "fmt"
|
||||
|
||||
func NoWrapSize(size string) string {
|
||||
return fmt.Sprintf("%s:flex-nowrap", size)
|
||||
}
|
||||
|
162
view/templHome.go
Normal file
@ -0,0 +1,162 @@
|
||||
package view
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"git.staur.ca/stobbsm/clustvirt/view/components"
|
||||
)
|
||||
|
||||
// HomePage is the homepage, generated via templ components
|
||||
func HomePage(w http.ResponseWriter, r *http.Request) {
|
||||
defer r.Body.Close()
|
||||
ibWhatIsThis := components.InfoBox(
|
||||
components.InfoBoxConfig{
|
||||
ColourClass: "aro",
|
||||
InFlex: true,
|
||||
FlexBasis: "basis-1/3",
|
||||
},
|
||||
"What is this?",
|
||||
components.ContentP(
|
||||
`Clustvirt (work in progress name) aims to be the agnostic
|
||||
cluster controller for libvirtd. The server component is
|
||||
used to display both the WebUI and run the REST API used to
|
||||
control one to many libvirtd hosts to manage virual machines,
|
||||
LXC containers (through libvirtd), gather information about
|
||||
each host, and monitor each host.`,
|
||||
),
|
||||
)
|
||||
|
||||
ibWhy := components.InfoBox(
|
||||
components.InfoBoxConfig{
|
||||
ColourClass: "dracula",
|
||||
InFlex: true,
|
||||
FlexBasis: "basis-2/3",
|
||||
},
|
||||
"Why?",
|
||||
components.ContentList(
|
||||
"informational",
|
||||
[]string{
|
||||
"Broadcom buying VMWare, and VMWare losing a free teir for homelabbers pissed me off",
|
||||
"Vendor lock-in pisses me off",
|
||||
"Even good open source Hyperconverged systems (Proxmox, as an example) exhibit a form of vendor lock-in",
|
||||
"Libvirt is terrific, has the functionality for everything those other providers do, but there really is not a great option for those dipping their toes into Open Source",
|
||||
"Its fun to build things that solve a need",
|
||||
"I really want to do it",
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
ibProjectGoals := components.InfoBox(
|
||||
components.InfoBoxConfig{
|
||||
ColourClass: "blade",
|
||||
InFlex: true,
|
||||
FlexBasis: "basis-7/12",
|
||||
},
|
||||
"Project Goals",
|
||||
components.ContentList(
|
||||
"accepted",
|
||||
[]string{
|
||||
"Open source, currently on the MIT license",
|
||||
"Base OS Agnostic. If it can run libvirtd, this should be able to control it on some level",
|
||||
"Control the Virtual Machine life cycle on one or more libvirtd hosts",
|
||||
"Add clusting capabilities to libvirtd host, including;",
|
||||
"Migration of VMs",
|
||||
"Syncronizing secrets",
|
||||
"Syncronizing VLANs, bridges, host only networking",
|
||||
"Sharing HA storage availability",
|
||||
"Locking shared resources like disks",
|
||||
"Starting VMs marked for HA on another host when one goes down",
|
||||
"Manage a library of Cloud-init resources and templates to build new VMs quickly",
|
||||
"Local Storage management, including local directory, lvm, zfs (if installed)",
|
||||
"Advanced Storage management, such as Ceph, glusterfs, drbd, iscsi, nfs",
|
||||
"Storage syncronization of local disks between hosts (zfs snapshots, lvm snapshots, rsync)",
|
||||
"Backup scheduling, creation, restoration",
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
ibStretchGoals := components.InfoBox(
|
||||
components.InfoBoxConfig{
|
||||
ColourClass: "cullen",
|
||||
InFlex: true,
|
||||
FlexBasis: "basis-5/12",
|
||||
},
|
||||
"Stretch Goals",
|
||||
components.ContentList(
|
||||
"possible",
|
||||
[]string{
|
||||
"Install the OS which libvirtd is running on",
|
||||
"Install/provision libvirtd on a host that does not have it installed",
|
||||
"Tools to move from one vendor to clustvirt/libvirtd",
|
||||
"VM templates for common aspects of VM creation and management, like appliances",
|
||||
"External tool access that can be used to manage things that are not managed here (cephadm dashboard, for instance)",
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
ibRedditRequested := components.InfoBox(
|
||||
components.InfoBoxConfig{
|
||||
ColourClass: "morbius",
|
||||
InFlex: true,
|
||||
FlexBasis: "basis-8/12",
|
||||
},
|
||||
"Reddit Requested Features",
|
||||
components.ContentList(
|
||||
"possible",
|
||||
[]string{
|
||||
"Search/Filter on hosts/vms - @Lopsided_Speaker_553",
|
||||
"Balance on resource usage per host/Automattically migrate to least used host - @Lopsided_Speaker_553",
|
||||
"Support inter-vm only commmunication (VxLAN style) - @Lopsided_Speaker_553",
|
||||
"Deploy VMs using only API - @Lopsided_Speaker_553",
|
||||
"Well documented, first class API - @kasperlitheater",
|
||||
"Bootstrap service to configure a new server - @phatpappa_",
|
||||
"For the love of kitten, don't use XML as configuration files - @pascalbrax",
|
||||
"Expose the Cluster Manager functionalities as API - @raven2611",
|
||||
"CPU architecture awareness for migrations - @raven2611",
|
||||
"Inter VM Communications via VXLAN/EVPN - @raven2611",
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
ibNeverHappening := components.InfoBox(
|
||||
components.InfoBoxConfig{
|
||||
ColourClass: "marcelin",
|
||||
InFlex: true,
|
||||
FlexBasis: "basis-4/12",
|
||||
},
|
||||
"Never Going to Happen",
|
||||
components.ContentList(
|
||||
"never",
|
||||
[]string{
|
||||
"Kubernetes",
|
||||
"Application container management (docker, podman, etc)",
|
||||
"Become an OS",
|
||||
"Have a paywall",
|
||||
"Vendor lock-in",
|
||||
"Become a commercial entity (even indirectly)",
|
||||
"Anything that does not have an Open Source standard behind it",
|
||||
"Directly control a guest Operating System",
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
idx := components.Index(
|
||||
components.FlexRow(
|
||||
true,
|
||||
ibWhatIsThis,
|
||||
ibWhy,
|
||||
),
|
||||
components.FlexRow(
|
||||
true,
|
||||
ibProjectGoals,
|
||||
ibStretchGoals,
|
||||
),
|
||||
components.FlexRow(
|
||||
true,
|
||||
ibRedditRequested,
|
||||
ibNeverHappening,
|
||||
),
|
||||
)
|
||||
idx.Render(context.Background(), w)
|
||||
}
|