features/templ-components #3

Merged
jtom38 merged 17 commits from features/templ-components into main 2024-07-13 10:40:28 -07:00
33 changed files with 261 additions and 93 deletions
Showing only changes of commit 574695bfb0 - Show all commits

View File

@ -1,21 +1,18 @@
package bulma package bulma
templ Button(color string, isLight, isDark bool) { // This creates a button that accepts children under it.
if isLight { templ Button() {
<button type="button" class={ "button", "is-light", color }> <button type="button" class={ "button" }>
{ children... } { children... }
</button> </button>
} }
if isDark {
<button type="button" class={ "button", "is-dark", color }> // Used to create a button and lets you define the color.
{ children... } // Accepts children.
</button> templ ButtonColor(color string) {
}
if !isLight && !isDark {
<button type="button" class={ "button", color }> <button type="button" class={ "button", color }>
{ children... } { children... }
</button> </button>
}
} }
templ ButtonNewTab(url, text string) { templ ButtonNewTab(url, text string) {
@ -24,7 +21,6 @@ templ ButtonNewTab(url, text string) {
</button> </button>
} }
templ ALink(url, title string) { templ ALink(url, title string) {
<a href={ templ.SafeURL(url) }>{ title }</a> <a href={ templ.SafeURL(url) }>{ title }</a>
} }

View File

@ -0,0 +1,15 @@
package form
templ TextInput(color, id, fieldType, placeholder string) {
if color == "" {
<input class={ "input" } name={ id } id={ id } type={ fieldType } placeholder={ placeholder }/>
} else {
<input class={ "input", color } name={ id } id={ id } type={ fieldType } placeholder={ placeholder }/>
}
}
templ Checkbox(text, id string) {
<label class="checkbox">
<input type="checkbox" id={ id }/> { text }
</label>
}

View File

@ -0,0 +1,13 @@
package form
type NewParam struct {
HxPost string
}
templ New(param NewParam) {
if param.HxPost != "" {
<form hx-post={ param.HxPost }>
{ children... }
</form>
}
}

View File

@ -0,0 +1,33 @@
package form
templ SelectOne(color string, isRound bool) {
if isRound {
<div class="select is-round">
<select>
{ children... }
</select>
</div>
} else {
<div class="select">
<select>
{ children... }
</select>
</div>
}
}
templ SelectOneItem(name string) {
<option>{ name }</option>
}
templ SelectMany(howManySelectable int, color string, isRound bool) {
<div class="select is-multiple">
<select multiple size="{ howManySelectable }">
{ children... }
</select>
</div>
}
templ SelectManyItem(name string) {
<option value={ name }>{ name }</option>
}

View File

@ -0,0 +1,5 @@
package form
templ TextArea(id, placeholder, color string) {
<textarea class={ "textarea", color } id={ id } placeholder={ placeholder }/>
}

View File

@ -0,0 +1,8 @@
package form
const (
InputTypeText = "text"
InputTypePassword = "password"
InputTypeEmail = "email"
InputTypePhoneNumber = "tel"
)

View File

@ -0,0 +1,7 @@
package bulma
templ Notification(message, color string) {
<div class={ "notification", color }>
{ message }
</div>
}

View File

@ -0,0 +1,13 @@
package bulma
templ Tag(message string) {
<span class={ "tag" }>{ message }</span>
}
templ TagColor(message, color string) {
<span class={ "tag", color }>{ message }</span>
}
templ TagColorSize(message, color, size string) {
<span class={ "tag", color, size }>{ message }</span>
}

View File

@ -0,0 +1,49 @@
package bulma
templ Title(message string) {
<h1 class="title">{ message }</h1>
}
templ Subitle(message string) {
<h2 class="subtitle">{ message }</h2>
}
templ H1(message string, isSubtitle bool) {
if isSubtitle {
<h1 class="subtitle is-1">{ message }</h1>
} else {
<h1 class="title is-1">{ message }</h1>
}
}
templ H2(message string, isSubtitle bool) {
if isSubtitle {
<h2 class="subtitle is-2">{ message }</h2>
} else {
<h2 class="title is-2">{ message }</h2>
}
}
templ H3(message string, isSubtitle bool) {
if isSubtitle {
<h3 class="subtitle is-3">{ message }</h3>
} else {
<h3 class="title is-3">{ message }</h3>
}
}
templ H4(message string, isSubtitle bool) {
if isSubtitle {
<h4 class="subtitle is-4">{ message }</h4>
} else {
<h4 class="title is-4">{ message }</h4>
}
}
templ H5(message string, isSubtitle bool) {
if isSubtitle {
<h5 class="subtitle is-5">{ message }</h5>
} else {
<h5 class="title is-5">{ message }</h5>
}
}

View File

@ -7,4 +7,8 @@ const (
ColorWarning = "is-warning" ColorWarning = "is-warning"
ColorSuccess = "is-success" ColorSuccess = "is-success"
ColorError = "is-error" ColorError = "is-error"
SizeNormal = "is-normal"
SizeMedium = "is-medium"
SizeLarge = "is-large"
) )

View File

@ -0,0 +1,5 @@
package templhtml
templ Br(){
<br/>
}

View File

@ -0,0 +1,9 @@
package templhtml
templ ALink(url, title string) {
<a href={ templ.SafeURL(url) }>{ title }</a>
}
templ ANewTab(url, text string) {
<a href={ templ.SafeURL(url) } target="_blank" rel="noopener noreferrer">{ text }</a>
}

View File

@ -1,17 +1,16 @@
package articles package articles
import ( import (
"git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout" "git.jamestombleson.com/jtom38/newsbot-portal/components/bulma"
"git.jamestombleson.com/jtom38/newsbot-portal/internal/models" "git.jamestombleson.com/jtom38/newsbot-portal/internal/models"
"git.jamestombleson.com/jtom38/newsbot-portal/internal/views/bulma" "git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout"
) )
templ List(model models.ListArticlesViewModel) { templ List(model models.ListArticlesViewModel) {
@layout.WithTemplate() { @layout.WithTemplate() {
@filterBar() @filterBar()
for _, item := range model.Items { for _, item := range model.Items {
@bulma.ArticleCardWithThumbnail(item.Article.Title, item.Article.Thumbnail, item.Article.Url, item.Article.PubDate.String(), item.Source.DisplayName ) @bulma.ArticleCardWithThumbnail(item.Article.Title, item.Article.Thumbnail, item.Article.Url, item.Article.PubDate.String(), item.Source.DisplayName)
} }
} }
} }

View File

@ -1,9 +0,0 @@
package form
templ Input(color, id, fieldType string) {
if color == "" {
<input class={ "input" } id={ id } type={ fieldType }/>
} else {
<input class={ "input", color } id={ id } type={ fieldType }/>
}
}

View File

@ -1,7 +0,0 @@
package form
templ New(postUrl string) {
<form hx-post={ postUrl }>
{ children... }
</form>
}

View File

@ -1,6 +0,0 @@
package form
const (
InputTypeText = "text"
InputTypePassword = "password"
)

View File

@ -1,7 +1,7 @@
package home package home
import "git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout" import "git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout"
import "git.jamestombleson.com/jtom38/newsbot-portal/internal/views/bulma" import "git.jamestombleson.com/jtom38/newsbot-portal/components/bulma"
templ Index() { templ Index() {
@layout.WithTemplate() { @layout.WithTemplate() {

View File

@ -1,18 +1,25 @@
package sources package sources
import ( import (
"git.jamestombleson.com/jtom38/newsbot-portal/components/bulma"
"git.jamestombleson.com/jtom38/newsbot-portal/components/bulma/form"
"git.jamestombleson.com/jtom38/newsbot-portal/internal/models" "git.jamestombleson.com/jtom38/newsbot-portal/internal/models"
"git.jamestombleson.com/jtom38/newsbot-portal/internal/views/bulma"
"git.jamestombleson.com/jtom38/newsbot-portal/internal/views/bulma/form"
"git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout" "git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout"
) )
var (
p = form.NewParam{
HxPost: "/sources/add",
}
)
templ Add(model models.AddSourcePayloadModel) { templ Add(model models.AddSourcePayloadModel) {
@layout.WithTemplate() { @layout.WithTemplate() {
<h2>New Source</h2> @bulma.H2("New Source", false)
<p>At this time only direct RSS links are allowed to be provided</p> <p>At this time only direct RSS links are allowed to be provided.</p>
@form.New("/sources/add") { @form.New(p) {
@form.Input("", "url", "text") @form.TextInput("", "name", form.InputTypeText, "Name of the site")
@form.TextInput("", "url", form.InputTypeText, "RSS URL")
@form.Submit("Submit", bulma.ColorPrimary) @form.Submit("Submit", bulma.ColorPrimary)
} }
} }

View File

@ -0,0 +1,11 @@
package sources
import "git.jamestombleson.com/jtom38/newsbot-portal/components/bulma"
templ AddAfter(message string, isError bool) {
if isError {
@bulma.Notification(message, bulma.ColorError)
} else {
@bulma.Notification("The requested source was added to the server", bulma.ColorSuccess)
}
}

View File

@ -1,15 +1,21 @@
package sources package sources
import ( import (
"git.jamestombleson.com/jtom38/newsbot-portal/components/bulma"
templhtml "git.jamestombleson.com/jtom38/newsbot-portal/components/templ-html"
"git.jamestombleson.com/jtom38/newsbot-portal/internal/models" "git.jamestombleson.com/jtom38/newsbot-portal/internal/models"
"git.jamestombleson.com/jtom38/newsbot-portal/internal/views/bulma"
"git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout" "git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout"
) )
templ ListAll(model models.ListAllSourcesViewModel) { templ ListAll(model models.ListAllSourcesViewModel) {
@layout.WithTemplate() { @layout.WithTemplate() {
@bulma.Button() {
@templhtml.ALink("/sources/add", "New Source")
}
@templhtml.Br()
@templhtml.Br()
for _, item := range model.Items { for _, item := range model.Items {
@bulma.Button(bulma.ColorPrimary, false, false) { @bulma.ButtonColor(bulma.ColorPrimary) {
@bulma.ANewTab(item.Url, item.DisplayName) @bulma.ANewTab(item.Url, item.DisplayName)
} }
<br/> <br/>

View File

@ -1,17 +1,16 @@
package users package users
import "git.jamestombleson.com/jtom38/newsbot-portal/internal/models" import (
"git.jamestombleson.com/jtom38/newsbot-portal/components/bulma"
"git.jamestombleson.com/jtom38/newsbot-portal/internal/models"
)
// This is returned after the user logs into the application. // This is returned after the user logs into the application.
// It just returns a partial view because it will overlap with the existing template. // It just returns a partial view because it will overlap with the existing template.
templ AfterLogin(vm models.AfterLoginViewModel) { templ AfterLogin(vm models.AfterLoginViewModel) {
if vm.Success { if vm.Success {
<div class="notification is-success"> @bulma.Notification(vm.Message, bulma.ColorSuccess)
{ vm.Message }
</div>
} else { } else {
<div class="notification is-error"> @bulma.Notification(vm.Message, bulma.ColorError)
{ vm.Message }
</div>
} }
} }

View File

@ -1,15 +1,13 @@
package users package users
import "git.jamestombleson.com/jtom38/newsbot-portal/components/bulma"
// This is returned after the user creates an account. // This is returned after the user creates an account.
// It just returns a partial view because it will overlap with the existing template. // It just returns a partial view because it will overlap with the existing template.
templ AfterSignUp(message string, success bool) { templ AfterSignUp(message string, success bool) {
if success { if success {
<div class="notification is-success"> @bulma.Notification(message, bulma.ColorSuccess)
{ message }
</div>
} else { } else {
<div class="notification is-error"> @bulma.Notification(message, bulma.ColorError)
{ message }
</div>
} }
} }

View File

@ -1,23 +1,29 @@
package users package users
import ( import (
"git.jamestombleson.com/jtom38/newsbot-portal/internal/views/bulma/form" "git.jamestombleson.com/jtom38/newsbot-portal/components/bulma/form"
"git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout" "git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout"
) )
var (
p = form.NewParam{
HxPost: "/users/login",
}
)
templ LoginNew() { templ LoginNew() {
@layout.WithTemplate() { @layout.WithTemplate() {
@form.New("/users/login") { @form.New(p) {
@form.Field() { @form.Field() {
@form.Label("Username") @form.Label("Username")
@form.Control() { @form.Control() {
@form.Input("", "username", "text") @form.TextInput("", "username", "text", "email address")
} }
} }
@form.Field(){ @form.Field() {
@form.Label("Password") @form.Label("Password")
@form.Control(){ @form.Control() {
@form.Input("", "password", form.InputTypePassword) @form.TextInput("", "password", form.InputTypePassword, "")
} }
} }
@form.Submit("Submit", "is-primary") @form.Submit("Submit", "is-primary")

View File

@ -1,7 +1,7 @@
package users package users
import "git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout" import "git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout"
import "git.jamestombleson.com/jtom38/newsbot-portal/internal/views/bulma" import "git.jamestombleson.com/jtom38/newsbot-portal/components/bulma"
templ Logout() { templ Logout() {
@layout.WithTemplate(){ @layout.WithTemplate(){

View File

@ -1,15 +1,19 @@
package users package users
import "git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout" import (
import "git.jamestombleson.com/jtom38/newsbot-portal/internal/views/bulma" "git.jamestombleson.com/jtom38/newsbot-portal/components/bulma"
templhtml "git.jamestombleson.com/jtom38/newsbot-portal/components/templ-html"
"git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout"
)
templ Profile() { templ Profile() {
@layout.WithTemplate() { @layout.WithTemplate() {
@bulma.Hero("Profile", "Here you can update your profile 😀") @bulma.Hero("Profile", "Here you can update your profile 😀")
<button type="button" class="button"> @bulma.H2("Sessions", false)
<a href="/users/forcelogout">Logout Everywhere</a> @bulma.Button() {
Logout Everywhere</button> @templhtml.ALink("/users/forcelogout", "Terminate all active sessions")
<p class="subtitle">This will force all active sessions to stop working and require a new login.</p> }
@bulma.Subitle("This will force you to login again as the application will give you a new session value.")
} }
} }

View File

@ -1,23 +1,26 @@
package users package users
import "git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout" import (
"git.jamestombleson.com/jtom38/newsbot-portal/components/bulma/form"
"git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout"
)
templ SignUp() { templ SignUp() {
@layout.WithTemplate() { @layout.WithTemplate() {
<form hx-post="/users/signup"> @form.New(form.NewParam{HxPost: "/users/signup"}) {
<div class="field"> @form.Field(){
<label class="label">Username</label> @form.Label("Username")
<div class="control"> @form.Control() {
<input class="input" type="text" name="username" id="username"/> @form.TextInput("", "username", form.InputTypeText, "username or email address")
</div> }
</div> }
<div class="field"> @form.Field() {
<label class="label">Password</label> @form.Label("Password")
<div class="control"> @form.Control() {
<input class="input" type="password" name="password" id="exampleInputPassword1"/> @form.TextInput("", "password", form.InputTypePassword, "Nice strong password, like Ox!")
</div> }
</div> }
<button type="submit" class="button is-primary">Submit</button> @form.Submit("Submit", "")
</form> }
} }
} }