nav bar!
Added a navbar that doesn't do anything to the homepage
This commit is contained in:
parent
8a736a57f9
commit
5fd215d6dd
@ -12,4 +12,16 @@
|
|||||||
@apply m-2 px-4 pt-2 flex-col shadow-md rounded-2xl border-8 border-double;
|
@apply m-2 px-4 pt-2 flex-col shadow-md rounded-2xl border-8 border-double;
|
||||||
@apply divide-solid divide-y-2;
|
@apply divide-solid divide-y-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
span>a::after {
|
||||||
|
@apply content-link w-3 h-3 inline-block invert;
|
||||||
|
}
|
||||||
|
|
||||||
|
span>a {
|
||||||
|
@apply text-base text-uiblue-400;
|
||||||
|
}
|
||||||
|
|
||||||
|
span>a:visited {
|
||||||
|
@apply text-base text-uiorange-400;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
3
main.go
3
main.go
@ -7,6 +7,7 @@ import (
|
|||||||
"git.staur.ca/stobbsm/clustvirt/view/static"
|
"git.staur.ca/stobbsm/clustvirt/view/static"
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
"github.com/go-chi/chi/v5/middleware"
|
"github.com/go-chi/chi/v5/middleware"
|
||||||
|
"github.com/a-h/templ"
|
||||||
)
|
)
|
||||||
|
|
||||||
const DEBUG bool = true
|
const DEBUG bool = true
|
||||||
@ -40,7 +41,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
fs.ServeHTTP(w, r)
|
fs.ServeHTTP(w, r)
|
||||||
})
|
})
|
||||||
r.Get("/", static.HomePage)
|
r.Get("/", templ.Handler(static.Home()).ServeHTTP)
|
||||||
|
|
||||||
log.Println(http.ListenAndServe(":3000", r))
|
log.Println(http.ListenAndServe(":3000", r))
|
||||||
}
|
}
|
||||||
|
110896
public/css/style.css
110896
public/css/style.css
File diff suppressed because it is too large
Load Diff
@ -6,7 +6,7 @@ module.exports = {
|
|||||||
pattern: /list-image-(accepted|informational|never|possible)/,
|
pattern: /list-image-(accepted|informational|never|possible)/,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
pattern: /[a-z]+-(uiblue|uired|uigreen|uiyellow|uiorange)-[0-9]+/
|
pattern: /[a-z]+-ui(blue|cyan|green|grey|orange|pink|purple|red|yellow)-[0-9]+/
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
theme: {
|
theme: {
|
||||||
@ -22,28 +22,28 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
colors: {
|
colors: {
|
||||||
'uiblue': {
|
'uiblue': {
|
||||||
50: '#eff2f8',
|
50: '#eef3fb',
|
||||||
100: '#dee6f2',
|
100: '#dde7f8',
|
||||||
200: '#becce4',
|
200: '#bbcff1',
|
||||||
300: '#9db3d7',
|
300: '#99b6e9',
|
||||||
400: '#7d99c9',
|
400: '#779ee2',
|
||||||
500: '#5c80bc',
|
500: '#5586db',
|
||||||
600: '#4a6696',
|
600: '#446baf',
|
||||||
700: '#374d71',
|
700: '#335083',
|
||||||
800: '#25334b',
|
800: '#223658',
|
||||||
900: '#121a26',
|
900: '#111b2c',
|
||||||
},
|
},
|
||||||
'uired': {
|
'uicyan': {
|
||||||
50: '#fbe9ef',
|
50: '#f2fefd',
|
||||||
100: '#f7d2de',
|
100: '#e5fdfc',
|
||||||
200: '#efa5bd',
|
200: '#cbfaf9',
|
||||||
300: '#e8789d',
|
300: '#b2f8f5',
|
||||||
400: '#e04b7c',
|
400: '#98f5f2',
|
||||||
500: '#d81e5b',
|
500: '#7ef3ef',
|
||||||
600: '#ad1849',
|
600: '#65c2bf',
|
||||||
700: '#821237',
|
700: '#4c928f',
|
||||||
800: '#560c24',
|
800: '#326160',
|
||||||
900: '#2b0612',
|
900: '#193130',
|
||||||
},
|
},
|
||||||
'uigreen': {
|
'uigreen': {
|
||||||
50: '#f5f9f5',
|
50: '#f5f9f5',
|
||||||
@ -57,17 +57,17 @@ module.exports = {
|
|||||||
800: '#3f4c3f',
|
800: '#3f4c3f',
|
||||||
900: '#1f2620',
|
900: '#1f2620',
|
||||||
},
|
},
|
||||||
'uiyellow': {
|
'uigrey': {
|
||||||
50: '#fffff5',
|
50: '#f5f5f5',
|
||||||
100: '#ffffea',
|
100: '#eaeaea',
|
||||||
200: '#fffed6',
|
200: '#d6d6d6',
|
||||||
300: '#fffec1',
|
300: '#c1c1c1',
|
||||||
400: '#fffdad',
|
400: '#adadad',
|
||||||
500: '#fffd98',
|
500: '#989898',
|
||||||
600: '#ccca7a',
|
600: '#7a7a7a',
|
||||||
700: '#99985b',
|
700: '#5b5b5b',
|
||||||
800: '#66653d',
|
800: '#3d3d3d',
|
||||||
900: '#33331e',
|
900: '#1e1e1e',
|
||||||
},
|
},
|
||||||
'uiorange': {
|
'uiorange': {
|
||||||
50: '#f9f3ef',
|
50: '#f9f3ef',
|
||||||
@ -81,6 +81,54 @@ module.exports = {
|
|||||||
800: '#4c3726',
|
800: '#4c3726',
|
||||||
900: '#261c13',
|
900: '#261c13',
|
||||||
},
|
},
|
||||||
|
'uipink': {
|
||||||
|
50: '#faf0f9',
|
||||||
|
100: '#f5e1f3',
|
||||||
|
200: '#ebc3e7',
|
||||||
|
300: '#e0a5d8',
|
||||||
|
400: '#d687cf',
|
||||||
|
500: '#cc69c3',
|
||||||
|
600: '#a3549c',
|
||||||
|
700: '#7a3f75',
|
||||||
|
800: '#522a4e',
|
||||||
|
900: '#291527',
|
||||||
|
},
|
||||||
|
'uipurple': {
|
||||||
|
50: '#fceefc',
|
||||||
|
100: '#f8dcf8',
|
||||||
|
200: '#f1b9f2',
|
||||||
|
300: '#ea97eb',
|
||||||
|
400: '#e374e5',
|
||||||
|
500: '#dc51de',
|
||||||
|
600: '#b041b2',
|
||||||
|
700: '#843185',
|
||||||
|
800: '#582059',
|
||||||
|
900: '#2c102c',
|
||||||
|
},
|
||||||
|
'uired': {
|
||||||
|
50: '#fbe9ef',
|
||||||
|
100: '#f7d2de',
|
||||||
|
200: '#efa5bd',
|
||||||
|
300: '#e8789d',
|
||||||
|
400: '#e04b7c',
|
||||||
|
500: '#d81e5b',
|
||||||
|
600: '#ad1849',
|
||||||
|
700: '#821237',
|
||||||
|
800: '#560c24',
|
||||||
|
900: '#2b0612',
|
||||||
|
},
|
||||||
|
'uiyellow': {
|
||||||
|
50: '#fffff5',
|
||||||
|
100: '#ffffea',
|
||||||
|
200: '#fffed6',
|
||||||
|
300: '#fffec1',
|
||||||
|
400: '#fffdad',
|
||||||
|
500: '#fffd98',
|
||||||
|
600: '#ccca7a',
|
||||||
|
700: '#99985b',
|
||||||
|
800: '#66653d',
|
||||||
|
900: '#33331e',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
package components
|
package components
|
||||||
|
|
||||||
templ A(href string, text string) {
|
templ A(href string, text string) {
|
||||||
<a href={ templ.URL(href) }
|
<a href={ templ.URL(href) }>
|
||||||
class={
|
{ text }
|
||||||
"after:content-link",
|
</a>
|
||||||
"after:w-3",
|
}
|
||||||
"after:h-3",
|
|
||||||
"after:inline-block",
|
templ ANewTab(href string, text string) {
|
||||||
"after:invert",
|
<a href={ templ.URL(href) } target="_blank">
|
||||||
"text-base",
|
|
||||||
"text-morbius-100" }>
|
|
||||||
{ text }
|
{ text }
|
||||||
</a>
|
</a>
|
||||||
}
|
}
|
||||||
|
@ -23,32 +23,12 @@ func A(href string, text string) templ.Component {
|
|||||||
templ_7745c5c3_Var1 = templ.NopComponent
|
templ_7745c5c3_Var1 = templ.NopComponent
|
||||||
}
|
}
|
||||||
ctx = templ.ClearChildren(ctx)
|
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=\"")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a href=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var3 templ.SafeURL = templ.URL(href)
|
var templ_7745c5c3_Var2 templ.SafeURL = templ.URL(href)
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var3)))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var2)))
|
||||||
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 {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -56,12 +36,58 @@ func A(href string, text string) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var4 string
|
var templ_7745c5c3_Var3 string
|
||||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/anchor.templ`, Line: 12, Col: 10}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/anchor.templ`, Line: 4, Col: 10}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
_, 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("</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
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func ANewTab(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_Var4 := templ.GetChildren(ctx)
|
||||||
|
if templ_7745c5c3_Var4 == nil {
|
||||||
|
templ_7745c5c3_Var4 = templ.NopComponent
|
||||||
|
}
|
||||||
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a href=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var5 templ.SafeURL = templ.URL(href)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(string(templ_7745c5c3_Var5)))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" target=\"_blank\">")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var6 string
|
||||||
|
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/components/anchor.templ`, Line: 10, Col: 10}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,14 @@ package components
|
|||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
templ ContentList(listImage string, items []string) {
|
templ List(listImage string) {
|
||||||
<ul class={
|
<ul class={
|
||||||
"list-inside",
|
"list-inside",
|
||||||
fmt.Sprintf("list-image-%s", listImage) }>
|
fmt.Sprintf("list-image-%s", listImage) }>
|
||||||
for _, li := range items {
|
{ children... }
|
||||||
<li>{ li }</li>
|
|
||||||
}
|
|
||||||
</ul>
|
</ul>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
templ ListItem() {
|
||||||
|
<li>{ children... }</li>
|
||||||
|
}
|
||||||
|
@ -12,7 +12,7 @@ import "bytes"
|
|||||||
|
|
||||||
import "fmt"
|
import "fmt"
|
||||||
|
|
||||||
func ContentList(listImage string, items []string) templ.Component {
|
func List(listImage string) templ.Component {
|
||||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
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)
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
if !templ_7745c5c3_IsBuffer {
|
if !templ_7745c5c3_IsBuffer {
|
||||||
@ -44,25 +44,10 @@ func ContentList(listImage string, items []string) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
for _, li := range items {
|
templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer)
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
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>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</ul>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
@ -73,3 +58,35 @@ func ContentList(listImage string, items []string) templ.Component {
|
|||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ListItem() 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)
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = templ_7745c5c3_Var3.Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
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
|
||||||
|
}
|
||||||
|
if !templ_7745c5c3_IsBuffer {
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
|
}
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
package components
|
package components
|
||||||
|
|
||||||
templ ContentP(content string) {
|
templ ContentP() {
|
||||||
<p>{ content }</p>
|
<p>{ children... }</p>
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import "context"
|
|||||||
import "io"
|
import "io"
|
||||||
import "bytes"
|
import "bytes"
|
||||||
|
|
||||||
func ContentP(content string) templ.Component {
|
func ContentP() templ.Component {
|
||||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
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)
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
if !templ_7745c5c3_IsBuffer {
|
if !templ_7745c5c3_IsBuffer {
|
||||||
@ -27,12 +27,7 @@ func ContentP(content string) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var2 string
|
templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer)
|
||||||
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 {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,12 @@
|
|||||||
package components
|
package components
|
||||||
|
|
||||||
templ FlexRow(wrap bool, comps ...templ.Component) {
|
templ FlexRow(wrap bool) {
|
||||||
<div class={
|
<div class={
|
||||||
"flex",
|
"flex",
|
||||||
templ.KV("flex-nowrap", !wrap),
|
templ.KV("flex-nowrap", !wrap),
|
||||||
templ.KV("flex-wrap", wrap),
|
templ.KV("flex-wrap", wrap),
|
||||||
templ.KV("md:flex-nowrap", wrap)
|
templ.KV("md:flex-nowrap", wrap)
|
||||||
}>
|
}>
|
||||||
for _, cmp := range comps {
|
{ children... }
|
||||||
@cmp
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import "context"
|
|||||||
import "io"
|
import "io"
|
||||||
import "bytes"
|
import "bytes"
|
||||||
|
|
||||||
func FlexRow(wrap bool, comps ...templ.Component) templ.Component {
|
func FlexRow(wrap bool) templ.Component {
|
||||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
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)
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
if !templ_7745c5c3_IsBuffer {
|
if !templ_7745c5c3_IsBuffer {
|
||||||
@ -44,12 +44,10 @@ func FlexRow(wrap bool, comps ...templ.Component) templ.Component {
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
for _, cmp := range comps {
|
templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer)
|
||||||
templ_7745c5c3_Err = cmp.Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
|
@ -8,17 +8,17 @@ type InfoBoxConfig struct {
|
|||||||
FlexBasis string
|
FlexBasis string
|
||||||
}
|
}
|
||||||
|
|
||||||
templ InfoBox(ibc InfoBoxConfig, title string, child templ.Component) {
|
templ InfoBox(title string, colour string) {
|
||||||
<div class={
|
<div class={
|
||||||
"infobox",
|
"infobox",
|
||||||
fmt.Sprintf("bg-%s-900", ibc.ColourClass),
|
"h-full",
|
||||||
fmt.Sprintf("text-%s-100", ibc.ColourClass),
|
fmt.Sprintf("bg-%s-900", colour),
|
||||||
fmt.Sprintf("shadow-%s-900", ibc.ColourClass),
|
fmt.Sprintf("text-%s-100", colour),
|
||||||
fmt.Sprintf("divide-%s-800", ibc.ColourClass),
|
fmt.Sprintf("shadow-%s-900", colour),
|
||||||
fmt.Sprintf("border-%s-800", ibc.ColourClass),
|
fmt.Sprintf("divide-%s-800", colour),
|
||||||
templ.KV(ibc.FlexBasis, ibc.InFlex),
|
fmt.Sprintf("border-%s-800", colour),
|
||||||
}>
|
}>
|
||||||
<h3 class="text-xl font-semibold">{ title }</h3>
|
<h3 class="text-xl font-semibold">{ title }</h3>
|
||||||
@child
|
{ children... }
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ type InfoBoxConfig struct {
|
|||||||
FlexBasis string
|
FlexBasis string
|
||||||
}
|
}
|
||||||
|
|
||||||
func InfoBox(ibc InfoBoxConfig, title string, child templ.Component) templ.Component {
|
func InfoBox(title string, colour string) templ.Component {
|
||||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
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)
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
if !templ_7745c5c3_IsBuffer {
|
if !templ_7745c5c3_IsBuffer {
|
||||||
@ -33,12 +33,12 @@ func InfoBox(ibc InfoBoxConfig, title string, child templ.Component) templ.Compo
|
|||||||
ctx = templ.ClearChildren(ctx)
|
ctx = templ.ClearChildren(ctx)
|
||||||
var templ_7745c5c3_Var2 = []any{
|
var templ_7745c5c3_Var2 = []any{
|
||||||
"infobox",
|
"infobox",
|
||||||
fmt.Sprintf("bg-%s-900", ibc.ColourClass),
|
"h-full",
|
||||||
fmt.Sprintf("text-%s-100", ibc.ColourClass),
|
fmt.Sprintf("bg-%s-900", colour),
|
||||||
fmt.Sprintf("shadow-%s-900", ibc.ColourClass),
|
fmt.Sprintf("text-%s-100", colour),
|
||||||
fmt.Sprintf("divide-%s-800", ibc.ColourClass),
|
fmt.Sprintf("shadow-%s-900", colour),
|
||||||
fmt.Sprintf("border-%s-800", ibc.ColourClass),
|
fmt.Sprintf("divide-%s-800", colour),
|
||||||
templ.KV(ibc.FlexBasis, ibc.InFlex),
|
fmt.Sprintf("border-%s-800", colour),
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...)
|
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
@ -69,7 +69,7 @@ func InfoBox(ibc InfoBoxConfig, title string, child templ.Component) templ.Compo
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = child.Render(ctx, templ_7745c5c3_Buffer)
|
templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
package components
|
package components
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
func NoWrapSize(size string) string {
|
func NoWrapSize(size string) string {
|
||||||
return fmt.Sprintf("%s:flex-nowrap", size)
|
return fmt.Sprintf("%s:flex-nowrap", size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
7
view/layouts/common.go
Normal file
7
view/layouts/common.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package layouts
|
||||||
|
|
||||||
|
// LayoutConfig specifics common elements of layouts
|
||||||
|
type LayoutConfig struct {
|
||||||
|
MainTitle string
|
||||||
|
SubTitle string
|
||||||
|
}
|
21
view/layouts/manager.templ
Normal file
21
view/layouts/manager.templ
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package layouts
|
||||||
|
|
||||||
|
templ Manager(config LayoutConfig) {
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html class={ "text-slate-50", "bg-slate-900" }>
|
||||||
|
<head>
|
||||||
|
<title>ClustVirt</title>
|
||||||
|
<link href="/static/css/style.css" type="text/css" rel="stylesheet" />
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<header class={}>
|
||||||
|
@header(config.MainTitle, config.SubTitle)
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
@footer()
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
}
|
85
view/layouts/manager_templ.go
Normal file
85
view/layouts/manager_templ.go
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
// Code generated by templ - DO NOT EDIT.
|
||||||
|
|
||||||
|
// templ: version: v0.2.598
|
||||||
|
package layouts
|
||||||
|
|
||||||
|
//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 Manager(config LayoutConfig) 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-slate-50", "bg-slate-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>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var3 = []any{}
|
||||||
|
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<header class=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var3).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
|
||||||
|
}
|
||||||
|
templ_7745c5c3_Err = header(config.MainTitle, config.SubTitle).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</header><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
|
||||||
|
})
|
||||||
|
}
|
@ -1,13 +1,8 @@
|
|||||||
package layouts
|
package layouts
|
||||||
|
|
||||||
type StaticPageConfig struct {
|
templ StaticPage(title string, subtitle string) {
|
||||||
MainTitle string
|
|
||||||
SubTitle string
|
|
||||||
}
|
|
||||||
|
|
||||||
templ StaticPage(config StaticPageConfig, children ...templ.Component) {
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html class={ "text-slate-100" , "bg-slate-900" }>
|
<html class={ "text-uigrey-100" , "bg-uigrey-900" }>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>Clustvirt</title>
|
<title>Clustvirt</title>
|
||||||
@ -15,18 +10,11 @@ templ StaticPage(config StaticPageConfig, children ...templ.Component) {
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<header class={
|
<header>
|
||||||
"flex",
|
@header(title, subtitle)
|
||||||
"sm:flex-col", "sm:h20", "sm:justify-start",
|
|
||||||
"lg:flex-row", "lg:h-8", "lg:items-end", "lg:justify-center",
|
|
||||||
"gap-x-2",
|
|
||||||
}>
|
|
||||||
@header(config.MainTitle, config.SubTitle)
|
|
||||||
</header>
|
</header>
|
||||||
<div id="content" name="content">
|
<div id="content" name="content" class={ "flex" , "flex-col" , "gap-2" }>
|
||||||
for _, child := range children {
|
{ children... }
|
||||||
@child
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
<footer>
|
<footer>
|
||||||
@footer()
|
@footer()
|
||||||
@ -37,14 +25,38 @@ templ StaticPage(config StaticPageConfig, children ...templ.Component) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
templ header(title string, subtitle string) {
|
templ header(title string, subtitle string) {
|
||||||
<h1 class={ "text-2xl", "font-bold", "h-8" }>{ title }</h1>
|
<h2 class={ "text-lg" , "font-semibold" , "italic" , "h-6" }>{ subtitle }</h2>
|
||||||
<h2 class={ "text-sm", "font-thin", "italic", "h-4", "align-bottom" }>{ subtitle }</h2>
|
@nav(title)
|
||||||
<nav>
|
|
||||||
@nav()
|
|
||||||
</nav>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
templ nav() {
|
templ nav(title string) {
|
||||||
|
<nav class={ "w-100" , "bg-uigrey-600" , "shadow" , "shadow-uigrey-700" , "md:px-auto" }>
|
||||||
|
<div class={
|
||||||
|
"md:h-16",
|
||||||
|
"h-28",
|
||||||
|
"mx-auto",
|
||||||
|
"md:px-4",
|
||||||
|
"container",
|
||||||
|
"flex",
|
||||||
|
"items-center",
|
||||||
|
"justify-between",
|
||||||
|
"flex-wrap",
|
||||||
|
"md:flex-nowrap" }>
|
||||||
|
<h1 class={ "text-2xl", "font-bold", "text-uiblue-200", "md:order-1" }>{ title }</h1>
|
||||||
|
<div class={"text-uigrey-200", "font-semibold", "md:w-auto", "md:order-2", "order-3"}>
|
||||||
|
<ul class={ "flex", "justify-between", "sm:w-full", "md:w-auto" }>
|
||||||
|
<li class={ "hover:text-uiblue-200", "md:px-4", "md:py-2" }><a href="#">What</a></li>
|
||||||
|
<li class={ "hover:text-uiblue-200", "md:px-4", "md:py-2" }><a href="#">Why</a></li>
|
||||||
|
<li class={ "hover:text-uiblue-200", "md:px-4", "md:py-2" }><a href="#">Goals</a></li>
|
||||||
|
<li class={ "hover:text-uiblue-200", "md:px-4", "md:py-2" }><a href="#">Stretch</a></li>
|
||||||
|
<li class={ "hover:text-uiblue-200", "md:px-4", "md:py-2" }><a href="#">Requests</a></li>
|
||||||
|
<li class={ "hover:text-uiblue-200", "md:px-4", "md:py-2" }><a href="#">Never</a></li>
|
||||||
|
<li class={ "hover:text-uiblue-200", "md:px-4", "md:py-2" }><a href="#">Notes</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class={"order-2", "md:order-3"}>Login</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
}
|
}
|
||||||
|
|
||||||
templ footer() {
|
templ footer() {
|
||||||
|
@ -10,12 +10,7 @@ import "context"
|
|||||||
import "io"
|
import "io"
|
||||||
import "bytes"
|
import "bytes"
|
||||||
|
|
||||||
type StaticPageConfig struct {
|
func StaticPage(title string, subtitle string) templ.Component {
|
||||||
MainTitle string
|
|
||||||
SubTitle string
|
|
||||||
}
|
|
||||||
|
|
||||||
func StaticPage(config StaticPageConfig, children ...templ.Component) templ.Component {
|
|
||||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
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)
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
if !templ_7745c5c3_IsBuffer {
|
if !templ_7745c5c3_IsBuffer {
|
||||||
@ -32,7 +27,7 @@ func StaticPage(config StaticPageConfig, children ...templ.Component) templ.Comp
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var2 = []any{"text-slate-100", "bg-slate-900"}
|
var templ_7745c5c3_Var2 = []any{"text-uigrey-100", "bg-uigrey-900"}
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...)
|
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var2...)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
@ -45,21 +40,24 @@ func StaticPage(config StaticPageConfig, children ...templ.Component) templ.Comp
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
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>")
|
_, 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 {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var3 = []any{
|
templ_7745c5c3_Err = header(title, subtitle).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
"flex",
|
if templ_7745c5c3_Err != nil {
|
||||||
"sm:flex-col", "sm:h20", "sm:justify-start",
|
return templ_7745c5c3_Err
|
||||||
"lg:flex-row", "lg:h-8", "lg:items-end", "lg:justify-center",
|
|
||||||
"gap-x-2",
|
|
||||||
}
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</header>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var3 = []any{"flex", "flex-col", "gap-2"}
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...)
|
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var3...)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<header class=\"")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div id=\"content\" name=\"content\" class=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -71,20 +69,10 @@ func StaticPage(config StaticPageConfig, children ...templ.Component) templ.Comp
|
|||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
templ_7745c5c3_Err = header(config.MainTitle, config.SubTitle).Render(ctx, templ_7745c5c3_Buffer)
|
templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
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 _, child := range children {
|
|
||||||
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><footer>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><footer>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
@ -117,12 +105,12 @@ func header(title string, subtitle string) templ.Component {
|
|||||||
templ_7745c5c3_Var4 = templ.NopComponent
|
templ_7745c5c3_Var4 = templ.NopComponent
|
||||||
}
|
}
|
||||||
ctx = templ.ClearChildren(ctx)
|
ctx = templ.ClearChildren(ctx)
|
||||||
var templ_7745c5c3_Var5 = []any{"text-2xl", "font-bold", "h-8"}
|
var templ_7745c5c3_Var5 = []any{"text-lg", "font-semibold", "italic", "h-6"}
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var5...)
|
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var5...)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<h1 class=\"")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<h2 class=\"")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -135,53 +123,19 @@ func header(title string, subtitle string) templ.Component {
|
|||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var6 string
|
var templ_7745c5c3_Var6 string
|
||||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(subtitle)
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/staticpage.templ`, Line: 39, Col: 52}
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/staticpage.templ`, Line: 27, Col: 71}
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</h1>")
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</h2>")
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
var templ_7745c5c3_Var7 = []any{"text-sm", "font-thin", "italic", "h-4", "align-bottom"}
|
templ_7745c5c3_Err = nav(title).Render(ctx, templ_7745c5c3_Buffer)
|
||||||
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var7...)
|
|
||||||
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_Var7).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_Var8 string
|
|
||||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(subtitle)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/staticpage.templ`, Line: 40, Col: 80}
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</h2><nav>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
templ_7745c5c3_Err = nav().Render(ctx, templ_7745c5c3_Buffer)
|
|
||||||
if templ_7745c5c3_Err != nil {
|
|
||||||
return templ_7745c5c3_Err
|
|
||||||
}
|
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</nav>")
|
|
||||||
if templ_7745c5c3_Err != nil {
|
if templ_7745c5c3_Err != nil {
|
||||||
return templ_7745c5c3_Err
|
return templ_7745c5c3_Err
|
||||||
}
|
}
|
||||||
@ -192,7 +146,7 @@ func header(title string, subtitle string) templ.Component {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func nav() templ.Component {
|
func nav(title string) templ.Component {
|
||||||
return templ.ComponentFunc(func(ctx context.Context, templ_7745c5c3_W io.Writer) (templ_7745c5c3_Err error) {
|
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)
|
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templ_7745c5c3_W.(*bytes.Buffer)
|
||||||
if !templ_7745c5c3_IsBuffer {
|
if !templ_7745c5c3_IsBuffer {
|
||||||
@ -200,11 +154,255 @@ func nav() templ.Component {
|
|||||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
}
|
}
|
||||||
ctx = templ.InitializeContext(ctx)
|
ctx = templ.InitializeContext(ctx)
|
||||||
templ_7745c5c3_Var9 := templ.GetChildren(ctx)
|
templ_7745c5c3_Var7 := templ.GetChildren(ctx)
|
||||||
if templ_7745c5c3_Var9 == nil {
|
if templ_7745c5c3_Var7 == nil {
|
||||||
templ_7745c5c3_Var9 = templ.NopComponent
|
templ_7745c5c3_Var7 = templ.NopComponent
|
||||||
}
|
}
|
||||||
ctx = templ.ClearChildren(ctx)
|
ctx = templ.ClearChildren(ctx)
|
||||||
|
var templ_7745c5c3_Var8 = []any{"w-100", "bg-uigrey-600", "shadow", "shadow-uigrey-700", "md:px-auto"}
|
||||||
|
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var8...)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<nav class=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var8).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_Var9 = []any{
|
||||||
|
"md:h-16",
|
||||||
|
"h-28",
|
||||||
|
"mx-auto",
|
||||||
|
"md:px-4",
|
||||||
|
"container",
|
||||||
|
"flex",
|
||||||
|
"items-center",
|
||||||
|
"justify-between",
|
||||||
|
"flex-wrap",
|
||||||
|
"md:flex-nowrap"}
|
||||||
|
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var9...)
|
||||||
|
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_Var9).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_Var10 = []any{"text-2xl", "font-bold", "text-uiblue-200", "md:order-1"}
|
||||||
|
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var10...)
|
||||||
|
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_Var10).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_Var11 string
|
||||||
|
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ.Error{Err: templ_7745c5c3_Err, FileName: `view/layouts/staticpage.templ`, Line: 44, Col: 82}
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</h1>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var12 = []any{"text-uigrey-200", "font-semibold", "md:w-auto", "md:order-2", "order-3"}
|
||||||
|
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var12...)
|
||||||
|
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_Var12).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_Var13 = []any{"flex", "justify-between", "sm:w-full", "md:w-auto"}
|
||||||
|
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var13...)
|
||||||
|
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_Var13).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_Var14 = []any{"hover:text-uiblue-200", "md:px-4", "md:py-2"}
|
||||||
|
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var14...)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li class=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var14).String()))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><a href=\"#\">What</a></li>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var15 = []any{"hover:text-uiblue-200", "md:px-4", "md:py-2"}
|
||||||
|
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var15...)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li class=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var15).String()))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><a href=\"#\">Why</a></li>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var16 = []any{"hover:text-uiblue-200", "md:px-4", "md:py-2"}
|
||||||
|
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var16...)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li class=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var16).String()))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><a href=\"#\">Goals</a></li>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var17 = []any{"hover:text-uiblue-200", "md:px-4", "md:py-2"}
|
||||||
|
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var17...)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li class=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var17).String()))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><a href=\"#\">Stretch</a></li>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var18 = []any{"hover:text-uiblue-200", "md:px-4", "md:py-2"}
|
||||||
|
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var18...)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li class=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var18).String()))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><a href=\"#\">Requests</a></li>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var19 = []any{"hover:text-uiblue-200", "md:px-4", "md:py-2"}
|
||||||
|
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var19...)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li class=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var19).String()))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><a href=\"#\">Never</a></li>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var20 = []any{"hover:text-uiblue-200", "md:px-4", "md:py-2"}
|
||||||
|
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var20...)
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li class=\"")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ.CSSClasses(templ_7745c5c3_Var20).String()))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"><a href=\"#\">Notes</a></li></ul></div>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
var templ_7745c5c3_Var21 = []any{"order-2", "md:order-3"}
|
||||||
|
templ_7745c5c3_Err = templ.RenderCSSItems(ctx, templ_7745c5c3_Buffer, templ_7745c5c3_Var21...)
|
||||||
|
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_Var21).String()))
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">Login</div></div></nav>")
|
||||||
|
if templ_7745c5c3_Err != nil {
|
||||||
|
return templ_7745c5c3_Err
|
||||||
|
}
|
||||||
if !templ_7745c5c3_IsBuffer {
|
if !templ_7745c5c3_IsBuffer {
|
||||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteTo(templ_7745c5c3_W)
|
||||||
}
|
}
|
||||||
@ -220,9 +418,9 @@ func footer() templ.Component {
|
|||||||
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
defer templ.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||||
}
|
}
|
||||||
ctx = templ.InitializeContext(ctx)
|
ctx = templ.InitializeContext(ctx)
|
||||||
templ_7745c5c3_Var10 := templ.GetChildren(ctx)
|
templ_7745c5c3_Var22 := templ.GetChildren(ctx)
|
||||||
if templ_7745c5c3_Var10 == nil {
|
if templ_7745c5c3_Var22 == nil {
|
||||||
templ_7745c5c3_Var10 = templ.NopComponent
|
templ_7745c5c3_Var22 = templ.NopComponent
|
||||||
}
|
}
|
||||||
ctx = templ.ClearChildren(ctx)
|
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>")
|
_, 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>")
|
||||||
|
@ -1,167 +0,0 @@
|
|||||||
package static
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"git.staur.ca/stobbsm/clustvirt/view/layouts"
|
|
||||||
"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: "uigreen",
|
|
||||||
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: "uiyellow",
|
|
||||||
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: "uiorange",
|
|
||||||
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: "uiblue",
|
|
||||||
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: "uired",
|
|
||||||
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: "uiyellow",
|
|
||||||
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 := layouts.StaticPage(
|
|
||||||
layouts.StaticPageConfig{
|
|
||||||
MainTitle: "ClustVirt",
|
|
||||||
SubTitle: "Libvirt, clustered and managed",
|
|
||||||
},
|
|
||||||
components.FlexRow(
|
|
||||||
true,
|
|
||||||
ibWhatIsThis,
|
|
||||||
ibWhy,
|
|
||||||
),
|
|
||||||
components.FlexRow(
|
|
||||||
true,
|
|
||||||
ibProjectGoals,
|
|
||||||
ibStretchGoals,
|
|
||||||
),
|
|
||||||
components.FlexRow(
|
|
||||||
true,
|
|
||||||
ibRedditRequested,
|
|
||||||
ibNeverHappening,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
idx.Render(context.Background(), w)
|
|
||||||
}
|
|
@ -1,166 +0,0 @@
|
|||||||
{{ define "content" }}
|
|
||||||
<div class="m-2 px-4 pt-2 flex-col shadow-md
|
|
||||||
rounded-2xl border-8 border-double divide-solid divide-y-2
|
|
||||||
bg-dracula-900 text-dracula-100 shadow-dracula-900
|
|
||||||
divide-dracula-800 border-dracula-800">
|
|
||||||
<h3 class="text-xl font-semibold">What is this?</h3>
|
|
||||||
<p>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.</p>
|
|
||||||
</div>
|
|
||||||
<div class="m-2 px-4 pt-2 flex-col shadow-md
|
|
||||||
rounded-2xl border-8 border-double divide-solid divide-y-2
|
|
||||||
bg-blade-900 text-blade-100 shadow-blade-900
|
|
||||||
divide-blade-800 border-blade-800">
|
|
||||||
<h3 class="text-xl font-semibold">Project Goals</h4>
|
|
||||||
<ul class="leading-relaxed list-image-accepted list-inside">
|
|
||||||
<li class="accepted">Open source, currently on the MIT license</li>
|
|
||||||
<li class="notimpl">Base OS Agnostic. If it can run libvirtd, this should be
|
|
||||||
able to control it on some level</li>
|
|
||||||
<li class="notimpl">Control the Virtual Machine life cycle
|
|
||||||
on one or more libvirtd hosts</li>
|
|
||||||
<li class="notimpl">Add clusting capabilities to libvirtd host,
|
|
||||||
including;</li>
|
|
||||||
<li class="notimpl">Migration of VMs</li>
|
|
||||||
<li class="notimpl">Syncronizing secrets</li>
|
|
||||||
<li class="notimpl">Syncronizing VLANs, bridges, host only
|
|
||||||
networking</li>
|
|
||||||
<li class="notimpl">Sharing HA storage availability</li>
|
|
||||||
<li class="notimpl">Locking shared resources like disks</li>
|
|
||||||
<li class="notimpl">Starting VMs marked for HA on another host
|
|
||||||
when one goes down</li>
|
|
||||||
<li class="notimpl">Manage a library of Cloud-init resources
|
|
||||||
and templates to build new VMs quickly</li>
|
|
||||||
<li class="notimpl">Local Storage management, including local
|
|
||||||
directory, lvm, zfs (if installed)</li>
|
|
||||||
<li class="notimpl">Advanced Storage management, such as Ceph,
|
|
||||||
glusterfs, drbd, iscsi, nfs</li>
|
|
||||||
<li class="notimpl">Storage syncronization of local disks
|
|
||||||
between hosts (zfs snapshots, lvm snapshots, rsync)</li>
|
|
||||||
<li class="notimpl">Backup scheduling, creation, restoration</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="m-2 px-4 pt-2 flex-col shadow-md
|
|
||||||
rounded-2xl border-8 border-double divide-solid divide-y-2
|
|
||||||
bg-cullen-900 text-cullen-100 shadow-cullen-900
|
|
||||||
divide-cullen-800 border-cullen-800">
|
|
||||||
<h3 class="text-xl font-semibold">Stretch Goals</h3>
|
|
||||||
<ul class="leading-relaxed list-image-possible list-inside">
|
|
||||||
<li>Install the OS which libvirtd is running on</li>
|
|
||||||
<li>Install/provision libvirtd on a host that does not have
|
|
||||||
it installed</li>
|
|
||||||
<li>Tools to move from one vendor to clustvirt/libvirtd</li>
|
|
||||||
<li>VM templates for common aspects of VM creation and management,
|
|
||||||
like appliances</li>
|
|
||||||
<li>External tool access that can be used to manage things that
|
|
||||||
are not managed here (cephadm dashboard, for instance)</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="m-2 px-4 pt-2 flex-col shadow-md
|
|
||||||
rounded-2xl border-8 border-double divide-solid divide-y-2
|
|
||||||
bg-morbius-900 text-morbius-100 shadow-morbius-900
|
|
||||||
divide-morbius-800 border-morbius-800">
|
|
||||||
<h3 class="text-xl font-semibold">Reddit Requested Features</h3>
|
|
||||||
<ul class="list-image-possible list-inside leading-relaxed">
|
|
||||||
<li>Search/Filter on hosts/vms - @Lopsided_Speaker_553</li>
|
|
||||||
<li>Balance on resource usage per host/Automattically migrate to
|
|
||||||
least used host - @Lopsided_Speaker_553</li>
|
|
||||||
<li>Support inter-vm only commmunication (VxLAN style)
|
|
||||||
- @Lopsided_Speaker_553</li>
|
|
||||||
<li>Deploy VMs using only API - @Lopsided_Speaker_553</li>
|
|
||||||
<li>Well documented, first class API - @kasperlitheater</li>
|
|
||||||
<li>Bootstrap service to configure a new server - @phatpappa_</li>
|
|
||||||
<li>For the love of kitten, don't use XML as configuration files
|
|
||||||
- @pascalbrax</li>
|
|
||||||
<li>Expose the Cluster Manager functionalities as API - @raven2611</li>
|
|
||||||
<li>CPU architecture awareness for migrations - @raven2611</li>
|
|
||||||
<li>Inter VM Communications via VXLAN/EVPN - @raven2611</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="m-2 px-4 pt-2 flex-col shadow-md
|
|
||||||
rounded-2xl border-8 border-double divide-solid divide-y-2
|
|
||||||
bg-marcelin-900 text-marcelin-100 shadow-marcelin-900
|
|
||||||
divide-marcelin-800 border-marcelin-800">
|
|
||||||
<h3 class="text-xl font-semibold">Never Going to Happen</h3>
|
|
||||||
<ul class="list-image-never list-inside leading-relaxed">
|
|
||||||
<li>Kubernetes</li>
|
|
||||||
<li>Application container management (docker, podman, etc)</li>
|
|
||||||
<li>Become an OS</li>
|
|
||||||
<li>Have a paywall</li>
|
|
||||||
<li>Vendor lock-in</li>
|
|
||||||
<li>Become a commercial entity (even indirectly)</li>
|
|
||||||
<li>Anything that does not have an Open Source standard behind it</li>
|
|
||||||
<li>Directly control a guest Operating System</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="m-2 px-4 pt-2 flex-col shadow-md
|
|
||||||
rounded-2xl border-8 border-double divide-solid divide-y-2
|
|
||||||
bg-dracula-900 text-dracula-100 shadow-dracula-900
|
|
||||||
divide-dracula-800 border-dracula-800">
|
|
||||||
<h3 class="text-xl font-semibold">Why?</h3>
|
|
||||||
<ul class="list-image-informational list-inside leading-relaxed">
|
|
||||||
<li>Broadcom buying VMWare, and VMWare losing a free teir for
|
|
||||||
homelabbers pissed me off</li>
|
|
||||||
<li>Vendor lock-in pisses me off</li>
|
|
||||||
<li>Even good open source Hyperconverged systems (Proxmox, as
|
|
||||||
an example) exhibit a form of vendor lock-in</li>
|
|
||||||
<li>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</li>
|
|
||||||
<li>Its fun to build things that solve a need</li>
|
|
||||||
<li>I really want to do it</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="m-2 px-4 pt-2 flex-col shadow-md
|
|
||||||
rounded-2xl border-8 border-double
|
|
||||||
bg-voncount-900 text-voncount-100 shadow-voncount-900
|
|
||||||
divide-voncount-800 border-voncount-800">
|
|
||||||
<h3 class="text-xl font-semibold border-b-2 border-voncount-800">Other notes</h3>
|
|
||||||
<p>I recently created a <a href="http://redd.it/1bct15z"
|
|
||||||
class="after:content-link after:w-3 after:h-3 after:inline-block
|
|
||||||
after:invert text-base text-morbius-100">post</a>
|
|
||||||
on reddit announcing that I was building this, and while the majority
|
|
||||||
of responses were supportive, even offering features that may enhance
|
|
||||||
what I originally set out to do, many responded with
|
|
||||||
"Why do we need another one??"</p>
|
|
||||||
|
|
||||||
<p>Besides the list above about why this exists, I wanted to clarify
|
|
||||||
a few things those individuals did not seeem to get: This is not
|
|
||||||
a rebuild of Proxmox, Cloudstack, VMWare, Harvester or any of
|
|
||||||
the other "Hyper-converged/Single-solution/turnkey/Operating System"
|
|
||||||
offerings out there. This will not take over your base operating system
|
|
||||||
on your machine, just act as a cluster manager and interface to access
|
|
||||||
the existing libvirtd instances on those machines, nor will it prescribe
|
|
||||||
a set of requirements that make it hard to move your own infrastructure
|
|
||||||
around.</p>
|
|
||||||
|
|
||||||
<p>At the heart of this project is that I hate the enshitifiation of
|
|
||||||
Open Source that has been going on, where its just another way to make
|
|
||||||
money and control the eco system. RedHat tried to do it by locking
|
|
||||||
down their source code, Proxmox does it by making sure anything you
|
|
||||||
do on Proxmox is tied to Proxmox (no offense to Proxmox), and even
|
|
||||||
Hashicorp, who I loved so dearly, changed from a pure Open Source
|
|
||||||
licensing model to one that protects the business over the community.</p>
|
|
||||||
|
|
||||||
<p>I will not let that happen here.</p>
|
|
||||||
|
|
||||||
<p>This project will seek to use the Unix philosophy, of building off
|
|
||||||
of existing standards, combining tools, and having one tool do one
|
|
||||||
job well. This does not mean there will be one application for each
|
|
||||||
aspect of the job, but that this application stack will manage Libvirtd
|
|
||||||
well, and have individual and configurable paths to manage each sub-aspect
|
|
||||||
of the libvirt stack. This stack will not create a Ceph cluster for you,
|
|
||||||
it leaves you to do that. It will not even talk to a ceph cluster.
|
|
||||||
It will, however, let you add that cluster via configuration options to
|
|
||||||
define it as a storage pool that libvirt can use.</p>
|
|
||||||
|
|
||||||
<p>If you want something that will allow you to use a single interface
|
|
||||||
to create all sub aspects that can be used by libvirt
|
|
||||||
(managing all firewall rules, creating a ceph cluster, etc.),
|
|
||||||
use something like Proxmox which includes that builtin
|
|
||||||
functionality. This isn't the stack for you.<p>
|
|
||||||
</div>
|
|
||||||
{{ end }}
|
|
249
view/static/home.templ
Normal file
249
view/static/home.templ
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
package static
|
||||||
|
|
||||||
|
import (
|
||||||
|
"git.staur.ca/stobbsm/clustvirt/view/layouts"
|
||||||
|
"git.staur.ca/stobbsm/clustvirt/view/components"
|
||||||
|
)
|
||||||
|
|
||||||
|
templ Home() {
|
||||||
|
@layouts.StaticPage("ClustVirt", "Libvirt, clustered and managed") {
|
||||||
|
@components.FlexRow(true) {
|
||||||
|
<div class={ "basis-1/3" }>
|
||||||
|
@components.InfoBox("What is This?", "uiorange") {
|
||||||
|
@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.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div class={ "basis-2/3" }>
|
||||||
|
@components.InfoBox("Why?", "uiblue") {
|
||||||
|
@components.List("informational") {
|
||||||
|
@components.ListItem() {
|
||||||
|
Broadcom buying VMWare, and VMWare losing a free
|
||||||
|
teir for homelabbers pissed me off
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Vendor lock-in pisses me off
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Even good open source Hyperconverged systems
|
||||||
|
(Proxmox, as an example) exhibit a form of vendor lock-in
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Its fun to build things that solve a need
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
I really want to do it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@components.FlexRow(true) {
|
||||||
|
<div class={ "basis-7/12" }>
|
||||||
|
@components.InfoBox("Project Goals", "uigreen") {
|
||||||
|
@components.List("accepted") {
|
||||||
|
@components.ListItem() {
|
||||||
|
Open source, currently on the MIT license
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Base OS Agnostic. If it can run libvirtd, this should be able to control it on some level
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Control the Virtual Machine life cycle on one or more libvirtd hosts
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Add clusting capabilities to libvirtd host, including;
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Migration of VMs
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Syncronizing secrets
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Syncronizing VLANs, bridges, host only networking
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Sharing HA storage availability
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Locking shared resources like disks
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Starting VMs marked for HA on another host when one goes down
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Manage a library of Cloud-init resources and templates to build new VMs quickly
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Local Storage management, including local directory, lvm, zfs (if installed)
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Advanced Storage management, such as Ceph, glusterfs, drbd, iscsi, nfs
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Storage syncronization of local disks between hosts (zfs snapshots, lvm snapshots, rsync)
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Backup scheduling, creation, restoration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div class={ "basis-5/12" }>
|
||||||
|
@components.InfoBox("Stretch Goals", "uipurple") {
|
||||||
|
@components.List("possible") {
|
||||||
|
@components.ListItem() {
|
||||||
|
Install the OS which libvirtd is running on
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Install/provision libvirtd on a host that does not have it installed
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Tools to move from one vendor to clustvirt/libvirtd
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
VM templates for common aspects of VM creation and management,
|
||||||
|
like appliances
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
External tool access that can be used to manage things that are not
|
||||||
|
managed here (cephadm dashboard, for instance)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@components.FlexRow(true) {
|
||||||
|
<div class={ "basis-8/12" }>
|
||||||
|
@components.InfoBox("Reddit Requested Feature", "uiyellow") {
|
||||||
|
@components.List("possible") {
|
||||||
|
@components.ListItem() {
|
||||||
|
Search/Filter on hosts/vms - @Lopsided_Speaker_553
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Balance on resource usage per host/Automattically migrate to least
|
||||||
|
used host - @Lopsided_Speaker_553
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Support inter-vm only commmunication (VxLAN style) - @Lopsided_Speaker_553
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Deploy VMs using only API - @Lopsided_Speaker_553
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Well documented, first class API - @kasperlitheater
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Bootstrap service to configure a new server - @phatpappa_
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
For the love of kitten, don't use XML as configuration files - @pascalbrax
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Expose the Cluster Manager functionalities as API - @raven2611
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
CPU architecture awareness for migrations - @raven2611
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Inter VM Communications via VXLAN/EVPN - @raven2611
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div class={ "basis-4/12" }>
|
||||||
|
@components.InfoBox("Never Going to Happen", "uired") {
|
||||||
|
@components.List("never") {
|
||||||
|
@components.ListItem() {
|
||||||
|
Kubernetes
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Application container management (docker, podman, etc)
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Become an OS
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Have a paywall
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Vendor lock-in
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Become a commercial entity (even indirectly)
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Anything that does not have an Open Source standard behind it
|
||||||
|
}
|
||||||
|
@components.ListItem() {
|
||||||
|
Directly control a guest Operating System
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@components.InfoBox("Other things to note", "uipink") {
|
||||||
|
@components.ContentP() {
|
||||||
|
I recently created a <span>@components.ANewTab("http://redd.it/1bct15z", "post")
|
||||||
|
</span>
|
||||||
|
on reddit announcing that I was building this, and while the majority
|
||||||
|
of responses were supportive, even offering features that may enhance
|
||||||
|
what I originally set out to do, many responded with
|
||||||
|
"Why do we need another one??"
|
||||||
|
}
|
||||||
|
@components.ContentP() {
|
||||||
|
Besides the list above about why this exists, I wanted to clarify
|
||||||
|
a few things those individuals did not seeem to get: This is not
|
||||||
|
a rebuild of Proxmox, Cloudstack, VMWare, Harvester or any of
|
||||||
|
the other "Hyper-converged/Single-solution/turnkey/Operating System"
|
||||||
|
offerings out there. This will not take over your base operating system
|
||||||
|
on your machine, just act as a cluster manager and interface to access
|
||||||
|
the existing libvirtd instances on those machines, nor will it prescribe
|
||||||
|
a set of requirements that make it hard to move your own infrastructure
|
||||||
|
around.
|
||||||
|
}
|
||||||
|
@components.ContentP() {
|
||||||
|
At the heart of this project is that I hate the enshitifiation of
|
||||||
|
Open Source that has been going on, where its just another way to make
|
||||||
|
money and control the eco system. RedHat tried to do it by locking
|
||||||
|
down their source code, Proxmox does it by making sure anything you
|
||||||
|
do on Proxmox is tied to Proxmox (no offense to Proxmox), and even
|
||||||
|
Hashicorp, who I loved so dearly, changed from a pure Open Source
|
||||||
|
licensing model to one that protects the business over the community
|
||||||
|
}
|
||||||
|
@components.ContentP() {
|
||||||
|
I will not let that happen here.
|
||||||
|
}
|
||||||
|
@components.ContentP() {
|
||||||
|
This project will seek to use the Unix philosophy, of building off
|
||||||
|
of existing standards, combining tools, and having one tool do one
|
||||||
|
job well. This does not mean there will be one application for each
|
||||||
|
aspect of the job, but that this application stack will manage Libvirtd
|
||||||
|
well, and have individual and configurable paths to manage each sub-aspect
|
||||||
|
of the libvirt stack. This stack will not create a Ceph cluster for you,
|
||||||
|
it leaves you to do that. It will not even talk to a ceph cluster.
|
||||||
|
It will, however, let you add that cluster via configuration options to
|
||||||
|
define it as a storage pool that libvirt can use.
|
||||||
|
}
|
||||||
|
@components.ContentP() {
|
||||||
|
If you want something that will allow you to use a single interface
|
||||||
|
to create all sub aspects that can be used by libvirt
|
||||||
|
(managing all firewall rules, creating a ceph cluster, etc.),
|
||||||
|
use something like Proxmox which includes that builtin
|
||||||
|
functionality. This isn't the stack for you.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1567
view/static/home_templ.go
Normal file
1567
view/static/home_templ.go
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user