features/templ-components #3
@ -16,6 +16,7 @@ const (
|
||||
type Sources interface {
|
||||
ListAll(jwt string, page int) (domain.SourcesResponse, error)
|
||||
GetById(jwt string, id int64) (domain.SourcesResponse, error)
|
||||
NewRss(jwt, name, url, sourceType string) (domain.SourcesResponse, error)
|
||||
}
|
||||
|
||||
type sourceClient struct {
|
||||
@ -53,7 +54,7 @@ func (c sourceClient) ListAll(jwt string, page int) (domain.SourcesResponse, err
|
||||
return bind, err
|
||||
}
|
||||
|
||||
if (resp.StatusCode != 200) {
|
||||
if resp.StatusCode != 200 {
|
||||
return bind, errors.New(bind.Message)
|
||||
}
|
||||
|
||||
@ -69,9 +70,33 @@ func (c sourceClient) GetById(jwt string, id int64) (domain.SourcesResponse, err
|
||||
return bind, err
|
||||
}
|
||||
|
||||
if (statusCode != 200) {
|
||||
if statusCode != 200 {
|
||||
return bind, errors.New(bind.Message)
|
||||
}
|
||||
|
||||
return bind, nil
|
||||
}
|
||||
|
||||
func (c sourceClient) NewRss(jwt, name, url, sourceType string) (domain.SourcesResponse, error) {
|
||||
param := domain.NewSourceParamRequest{
|
||||
Name: name,
|
||||
Url: url,
|
||||
Tags: "",
|
||||
}
|
||||
bind := domain.SourcesResponse{}
|
||||
var endpoint string
|
||||
if sourceType == domain.SourceCollectorRss {
|
||||
endpoint = fmt.Sprintf("%s/%s/new/rss", c.serverAddress, SourcesBaseRoute)
|
||||
}
|
||||
|
||||
statusCode, err := PostBodyUrlAuthorized(c.client, endpoint, jwt, param, &bind)
|
||||
if err != nil {
|
||||
return bind, err
|
||||
}
|
||||
|
||||
if statusCode != 200 {
|
||||
return bind, errors.New("got the wrong status code back from the API")
|
||||
}
|
||||
|
||||
return bind, nil
|
||||
}
|
||||
|
@ -58,6 +58,35 @@ func PostUrlAuthorized(client http.Client, endpoint, jwtToken string, t any) err
|
||||
return nil
|
||||
}
|
||||
|
||||
func PostBodyUrlAuthorized(client http.Client, endpoint, jwtToken string, body any, t any) (int, error) {
|
||||
jsonBody, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
req, err := http.NewRequest(http.MethodPost, endpoint, bytes.NewBuffer(jsonBody))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
req.Header.Add(HeaderAuthorization, fmt.Sprintf("%s %s", "Bearer", jwtToken))
|
||||
req.Header.Add(HeaderContentType, ApplicationJson)
|
||||
|
||||
//response, err := http.Post(endpoint, ApplicationJson, bytes.NewBuffer(jsonBody))
|
||||
response, err := client.Do(req)
|
||||
if err != nil {
|
||||
return response.StatusCode, err
|
||||
}
|
||||
|
||||
defer response.Body.Close()
|
||||
decoder := json.NewDecoder(response.Body)
|
||||
err = decoder.Decode(&t)
|
||||
if err != nil {
|
||||
return response.StatusCode, err
|
||||
}
|
||||
|
||||
return response.StatusCode, nil
|
||||
}
|
||||
|
||||
func PostBodyUrl(client http.Client, endpoint string, body any, t any) error {
|
||||
jsonBody, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
@ -79,6 +108,22 @@ func PostBodyUrl(client http.Client, endpoint string, body any, t any) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func PostQuery(client http.Client, endpoint string, t any) (int, error) {
|
||||
response, err := http.Post(endpoint, ApplicationJson, nil)
|
||||
if err != nil {
|
||||
return response.StatusCode, err
|
||||
}
|
||||
|
||||
defer response.Body.Close()
|
||||
decoder := json.NewDecoder(response.Body)
|
||||
err = decoder.Decode(&t)
|
||||
if err != nil {
|
||||
return response.StatusCode, err
|
||||
}
|
||||
|
||||
return response.StatusCode, nil
|
||||
}
|
||||
|
||||
func Get(client http.Client, endpoint, jwt string, t any) (int, error) {
|
||||
req, err := http.NewRequest(http.MethodGet, endpoint, nil)
|
||||
if err != nil {
|
||||
|
8
components/bulma/block.templ
Normal file
8
components/bulma/block.templ
Normal file
@ -0,0 +1,8 @@
|
||||
package bulma
|
||||
|
||||
// Simple spacer that accepts children
|
||||
templ Block() {
|
||||
<div class="block">
|
||||
{ children... }
|
||||
</div>
|
||||
}
|
30
components/bulma/button.templ
Normal file
30
components/bulma/button.templ
Normal file
@ -0,0 +1,30 @@
|
||||
package bulma
|
||||
|
||||
// This creates a button that accepts children under it.
|
||||
templ Button() {
|
||||
<button type="button" class={ "button" }>
|
||||
{ children... }
|
||||
</button>
|
||||
}
|
||||
|
||||
// Used to create a button and lets you define the color.
|
||||
// Accepts children.
|
||||
templ ButtonColor(color string) {
|
||||
<button type="button" class={ "button", color }>
|
||||
{ children... }
|
||||
</button>
|
||||
}
|
||||
|
||||
templ ButtonNewTab(url, text string) {
|
||||
<button type="button" class="button">
|
||||
<a href={ templ.SafeURL(url) } target="_blank" rel="noopener noreferrer">{ text }</a>
|
||||
</button>
|
||||
}
|
||||
|
||||
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>
|
||||
}
|
19
components/bulma/example/example.templ
Normal file
19
components/bulma/example/example.templ
Normal file
@ -0,0 +1,19 @@
|
||||
package example
|
||||
|
||||
import "git.jamestombleson.com/jtom38/newsbot-portal/components/bulma"
|
||||
import "git.jamestombleson.com/jtom38/newsbot-portal/components/bulma/html"
|
||||
import "git.jamestombleson.com/jtom38/newsbot-portal/components/bulma/layout"
|
||||
|
||||
templ example() {
|
||||
@html.Doctype()
|
||||
@html.New("en"){
|
||||
@html.NewHeader(){
|
||||
@bulma.UseBulmaCdn()
|
||||
}
|
||||
@html.NewBody() {
|
||||
@layout.Container(bulma.BreakpointDefault) {
|
||||
{ children... }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1
components/bulma/example/layout.templ
Normal file
1
components/bulma/example/layout.templ
Normal file
@ -0,0 +1 @@
|
||||
package example
|
8
components/bulma/form/control.templ
Normal file
8
components/bulma/form/control.templ
Normal file
@ -0,0 +1,8 @@
|
||||
package form
|
||||
|
||||
// Div container to add a input field to.
|
||||
templ Control() {
|
||||
<div class="control">
|
||||
{ children... }
|
||||
</div>
|
||||
}
|
8
components/bulma/form/field.templ
Normal file
8
components/bulma/form/field.templ
Normal file
@ -0,0 +1,8 @@
|
||||
package form
|
||||
|
||||
// This creates a field that you can add a Label, Control or Input object.
|
||||
templ Field() {
|
||||
<div class="field">
|
||||
{ children... }
|
||||
</div>
|
||||
}
|
19
components/bulma/form/input.templ
Normal file
19
components/bulma/form/input.templ
Normal file
@ -0,0 +1,19 @@
|
||||
package form
|
||||
|
||||
templ TextInput(id, fieldType, placeholder string) {
|
||||
<input class={ "input" } name={ id } id={ id } type={ fieldType } placeholder={ placeholder }/>
|
||||
}
|
||||
|
||||
templ TextInputColor(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>
|
||||
}
|
6
components/bulma/form/label.templ
Normal file
6
components/bulma/form/label.templ
Normal file
@ -0,0 +1,6 @@
|
||||
package form
|
||||
|
||||
// This will create a small bit of text to add context to the form.
|
||||
templ Label(text string) {
|
||||
<label class="label">{ text }</label>
|
||||
}
|
13
components/bulma/form/new.templ
Normal file
13
components/bulma/form/new.templ
Normal 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>
|
||||
}
|
||||
}
|
33
components/bulma/form/select.templ
Normal file
33
components/bulma/form/select.templ
Normal 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>
|
||||
}
|
5
components/bulma/form/submit.templ
Normal file
5
components/bulma/form/submit.templ
Normal file
@ -0,0 +1,5 @@
|
||||
package form
|
||||
|
||||
templ Submit(text, color string) {
|
||||
<button type="submit" class={ "button", color }>{ text }</button>
|
||||
}
|
5
components/bulma/form/textarea.templ
Normal file
5
components/bulma/form/textarea.templ
Normal file
@ -0,0 +1,5 @@
|
||||
package form
|
||||
|
||||
templ TextArea(id, placeholder, color string) {
|
||||
<textarea class={ "textarea", color } id={ id } placeholder={ placeholder }/>
|
||||
}
|
8
components/bulma/form/util.go
Normal file
8
components/bulma/form/util.go
Normal file
@ -0,0 +1,8 @@
|
||||
package form
|
||||
|
||||
const (
|
||||
InputTypeText = "text"
|
||||
InputTypePassword = "password"
|
||||
InputTypeEmail = "email"
|
||||
InputTypePhoneNumber = "tel"
|
||||
)
|
5
components/bulma/html/br.templ
Normal file
5
components/bulma/html/br.templ
Normal file
@ -0,0 +1,5 @@
|
||||
package html
|
||||
|
||||
templ Br(){
|
||||
<br/>
|
||||
}
|
9
components/bulma/html/href.templ
Normal file
9
components/bulma/html/href.templ
Normal file
@ -0,0 +1,9 @@
|
||||
package html
|
||||
|
||||
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>
|
||||
}
|
26
components/bulma/html/html.templ
Normal file
26
components/bulma/html/html.templ
Normal file
@ -0,0 +1,26 @@
|
||||
package html
|
||||
|
||||
templ Doctype() {
|
||||
<!DOCTYPE html>
|
||||
}
|
||||
|
||||
// Creates <html> that accepts children
|
||||
templ New(lang string) {
|
||||
<html lang={ lang }>
|
||||
{ children... }
|
||||
</html>
|
||||
}
|
||||
|
||||
// Creates <head> that accepts children
|
||||
templ NewHeader() {
|
||||
<head>
|
||||
{ children... }
|
||||
</head>
|
||||
}
|
||||
|
||||
// Creates <body> that accepts children
|
||||
templ NewBody() {
|
||||
<body>
|
||||
{ children... }
|
||||
</body>
|
||||
}
|
7
components/bulma/layout/container.templ
Normal file
7
components/bulma/layout/container.templ
Normal file
@ -0,0 +1,7 @@
|
||||
package layout
|
||||
|
||||
templ Container(breakpoint string) {
|
||||
<div class={ "container", breakpoint }>
|
||||
{ children... }
|
||||
</div>
|
||||
}
|
37
components/bulma/layout/hero.templ
Normal file
37
components/bulma/layout/hero.templ
Normal file
@ -0,0 +1,37 @@
|
||||
package layout
|
||||
|
||||
templ Hero(title, subtitle string) {
|
||||
<section class="hero">
|
||||
<div class="hero-body">
|
||||
<p class="title">{ title }</p>
|
||||
<p class="subtitle">{ subtitle }</p>
|
||||
</div>
|
||||
</section>
|
||||
}
|
||||
|
||||
templ HeroSize(title, subtitle, size string) {
|
||||
<section class={ "hero", size }>
|
||||
<div class="hero-body">
|
||||
<p class="title">{ title }</p>
|
||||
<p class="subtitle">{ subtitle }</p>
|
||||
</div>
|
||||
</section>
|
||||
}
|
||||
|
||||
templ HeroColor(title, subtitle, color string) {
|
||||
<section class={ "hero", color }>
|
||||
<div class="hero-body">
|
||||
<p class="title">{ title }</p>
|
||||
<p class="subtitle">{ subtitle }</p>
|
||||
</div>
|
||||
</section>
|
||||
}
|
||||
|
||||
templ HeroColorSize(title, subtitle, color, size string) {
|
||||
<section class={ "hero", color, size }>
|
||||
<div class="hero-body">
|
||||
<p class="title">{ title }</p>
|
||||
<p class="subtitle">{ subtitle }</p>
|
||||
</div>
|
||||
</section>
|
||||
}
|
9
components/bulma/layout/section.templ
Normal file
9
components/bulma/layout/section.templ
Normal file
@ -0,0 +1,9 @@
|
||||
package bulma
|
||||
|
||||
// Creates a <section> object thats good to break up a page of content.
|
||||
templ Section(title, subtitle string) {
|
||||
<section class="section">
|
||||
<h1 class="title">{ title }</h1>
|
||||
<h2 class="subtitle">{ subtitle }</h2>
|
||||
</section>
|
||||
}
|
7
components/bulma/notification.templ
Normal file
7
components/bulma/notification.templ
Normal file
@ -0,0 +1,7 @@
|
||||
package bulma
|
||||
|
||||
templ Notification(message, color string) {
|
||||
<div class={ "notification", color }>
|
||||
{ message }
|
||||
</div>
|
||||
}
|
5
components/bulma/script.templ
Normal file
5
components/bulma/script.templ
Normal file
@ -0,0 +1,5 @@
|
||||
package bulma
|
||||
|
||||
templ UseBulmaCdn() {
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@1.0.1/css/bulma.min.css"/>
|
||||
}
|
37
components/bulma/table.templ
Normal file
37
components/bulma/table.templ
Normal file
@ -0,0 +1,37 @@
|
||||
package bulma
|
||||
|
||||
// Creates a <table> that accepts children
|
||||
templ Table(){
|
||||
<table class="table">
|
||||
{ children... }
|
||||
</table>
|
||||
}
|
||||
|
||||
// Creates a <thead> that accepts children.
|
||||
templ TableHeader() {
|
||||
<thead>{ children... }</thead>
|
||||
}
|
||||
|
||||
// Creates a <tf> that accepts children.
|
||||
templ TableRow() {
|
||||
<tr>{ children... }</tr>
|
||||
}
|
||||
|
||||
// Creates a <th> and writes the given value
|
||||
templ TableHeaderData(value string) {
|
||||
<th>{ value }</th>
|
||||
}
|
||||
|
||||
// Creates a <th> that allows you to also add a tooltip value
|
||||
templ TableHeaderDataToolTip(value, tooltip string) {
|
||||
<th><abbr title={ tooltip }>{ value }</abbr></th>
|
||||
}
|
||||
|
||||
// Creates a <td> that accepts children.
|
||||
templ TableDataChildren() {
|
||||
<td>{ children... }</td>
|
||||
}
|
||||
|
||||
templ TableData(value string) {
|
||||
<td>{ value }</td>
|
||||
}
|
13
components/bulma/tags.templ
Normal file
13
components/bulma/tags.templ
Normal 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>
|
||||
}
|
49
components/bulma/title.templ
Normal file
49
components/bulma/title.templ
Normal 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>
|
||||
}
|
||||
}
|
20
components/bulma/util.go
Normal file
20
components/bulma/util.go
Normal file
@ -0,0 +1,20 @@
|
||||
package bulma
|
||||
|
||||
const (
|
||||
ColorPrimary = "is-primary"
|
||||
ColorInfo = "is-info"
|
||||
ColorLink = "is-link"
|
||||
ColorWarning = "is-warning"
|
||||
ColorSuccess = "is-success"
|
||||
ColorError = "is-error"
|
||||
|
||||
SizeNormal = "is-normal"
|
||||
SizeMedium = "is-medium"
|
||||
SizeLarge = "is-large"
|
||||
|
||||
BreakpointDefault = ""
|
||||
BreakpointWidescreen = "is-widescreen"
|
||||
BreakpointFullHd = "is-fullhd"
|
||||
BreakpointMaxDesktop = "is-max-desktop"
|
||||
BreakpointMaxWidescreen = "is-max-widescreen"
|
||||
)
|
2
go.mod
2
go.mod
@ -3,7 +3,7 @@ module git.jamestombleson.com/jtom38/newsbot-portal
|
||||
go 1.22.1
|
||||
|
||||
require (
|
||||
git.jamestombleson.com/jtom38/newsbot-api v0.0.0-20240603002809-9237369e5a76
|
||||
git.jamestombleson.com/jtom38/newsbot-api v0.0.0-20240710142335-56199a795a2b // indirect
|
||||
github.com/a-h/templ v0.2.747
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1
|
||||
github.com/joho/godotenv v1.5.1
|
||||
|
2
go.sum
2
go.sum
@ -1,5 +1,7 @@
|
||||
git.jamestombleson.com/jtom38/newsbot-api v0.0.0-20240603002809-9237369e5a76 h1:B9t5fcfVerMjqnXXPUmYwdmUk76EoEL8x9IRehqg2c4=
|
||||
git.jamestombleson.com/jtom38/newsbot-api v0.0.0-20240603002809-9237369e5a76/go.mod h1:A3UdJyQ/IEy3utEwJiC4nbi0ohfgrUNRLTei2iZhLLA=
|
||||
git.jamestombleson.com/jtom38/newsbot-api v0.0.0-20240710142335-56199a795a2b h1:XAXD6OSFDzrJ2O1+wma/vnYfLJdcQZRD6NFjfjxjKv4=
|
||||
git.jamestombleson.com/jtom38/newsbot-api v0.0.0-20240710142335-56199a795a2b/go.mod h1:A3UdJyQ/IEy3utEwJiC4nbi0ohfgrUNRLTei2iZhLLA=
|
||||
github.com/a-h/templ v0.2.747 h1:D0dQ2lxC3W7Dxl6fxQ/1zZHBQslSkTSvl5FxP/CfdKg=
|
||||
github.com/a-h/templ v0.2.747/go.mod h1:69ObQIbrcuwPCU32ohNaWce3Cb7qM5GMiqN1K+2yop4=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
|
@ -36,5 +36,5 @@ func (h *Handler) ArticlesList(c echo.Context) error {
|
||||
|
||||
}
|
||||
|
||||
return Render(c, http.StatusOK, articles.List(vm))
|
||||
return Render(c, http.StatusOK, articles.ListArticlesTable(vm))
|
||||
}
|
||||
|
@ -65,14 +65,15 @@ func NewServer(ctx context.Context, configs config.Configs, apiClient apiclient.
|
||||
//sources.Use(ValidateJwtMiddleware(configs.JwtSecret))
|
||||
sources.GET("", s.ListAllSources)
|
||||
sources.GET("/add", s.AddSource)
|
||||
sources.POST("/add", s.AddSourceAfter)
|
||||
|
||||
users := router.Group("/users")
|
||||
users.GET("/login", s.UserLogin)
|
||||
users.POST("/login", s.UserAfterLogin)
|
||||
users.GET("/signup", s.UserSignUp)
|
||||
users.POST("/signup", s.UserAfterSignUp)
|
||||
users.Use(ValidateJwtMiddleware(configs.JwtSecret))
|
||||
users.GET("/logout", s.UsersLogout)
|
||||
users.Use(ValidateJwtMiddleware(configs.JwtSecret))
|
||||
users.GET("/profile", s.UserProfile)
|
||||
|
||||
s.Router = router
|
||||
|
@ -36,3 +36,13 @@ func (h *Handler) AddSource(c echo.Context) error {
|
||||
|
||||
return Render(c, http.StatusOK, sources.Add(models.AddSourcePayloadModel{}))
|
||||
}
|
||||
|
||||
func (h *Handler) AddSourceAfter(c echo.Context) error {
|
||||
name := c.FormValue("name")
|
||||
url := c.FormValue("url")
|
||||
resp, err := h.api.Sources.NewRss(GetJwtToken(c), name, url, "rss")
|
||||
if err != nil {
|
||||
return Render(c, http.StatusOK, sources.AddAfter(err.Error(), true))
|
||||
}
|
||||
return Render(c, http.StatusOK, sources.AddAfter(resp.Message, false))
|
||||
}
|
@ -11,7 +11,7 @@ import (
|
||||
)
|
||||
|
||||
func (h *Handler) UserLogin(c echo.Context) error {
|
||||
return Render(c, http.StatusOK, users.Login())
|
||||
return Render(c, http.StatusOK, users.LoginNew())
|
||||
}
|
||||
|
||||
func (h *Handler) UserAfterLogin(c echo.Context) error {
|
||||
|
@ -1,9 +1,9 @@
|
||||
package articles
|
||||
|
||||
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/views/bulma"
|
||||
"git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout"
|
||||
)
|
||||
|
||||
templ List(model models.ListArticlesViewModel) {
|
||||
@ -11,7 +11,6 @@ templ List(model models.ListArticlesViewModel) {
|
||||
@filterBar()
|
||||
for _, item := range model.Items {
|
||||
@bulma.ArticleCardWithThumbnail(item.Article.Title, item.Article.Thumbnail, item.Article.Url, item.Article.PubDate.String(), item.Source.DisplayName)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
32
internal/views/articles/table.templ
Normal file
32
internal/views/articles/table.templ
Normal file
@ -0,0 +1,32 @@
|
||||
package articles
|
||||
|
||||
import (
|
||||
"git.jamestombleson.com/jtom38/newsbot-portal/components/bulma"
|
||||
"git.jamestombleson.com/jtom38/newsbot-portal/internal/models"
|
||||
"git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout"
|
||||
)
|
||||
|
||||
templ ListArticlesTable(model models.ListArticlesViewModel) {
|
||||
@layout.WithTemplate() {
|
||||
@bulma.Table() {
|
||||
@bulma.TableHeader() {
|
||||
@bulma.TableRow() {
|
||||
@bulma.TableHeaderData("Title")
|
||||
@bulma.TableHeaderData("Source")
|
||||
@bulma.TableHeaderData("View")
|
||||
}
|
||||
}
|
||||
for _, item := range model.Items {
|
||||
@bulma.TableRow() {
|
||||
@bulma.TableData(item.Article.Title)
|
||||
@bulma.TableData(item.Source.DisplayName)
|
||||
@bulma.TableDataChildren() {
|
||||
@bulma.Button() {
|
||||
@bulma.ANewTab(item.Article.Url, "View")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package bulma
|
||||
|
||||
templ Hero(title, subtitle string) {
|
||||
<section class="hero">
|
||||
<div class="hero-body">
|
||||
<p class="title">{ title }</p>
|
||||
<p class="subtitle">{ subtitle }</p>
|
||||
</div>
|
||||
</section>
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
package bulma
|
||||
|
||||
templ Section(title, subtitle string) {
|
||||
<section class="section">
|
||||
<h1 class="title">Section</h1>
|
||||
<h2 class="subtitle">
|
||||
A simple container to divide your page into <strong>sections</strong>, like
|
||||
the one you're currently reading.
|
||||
</h2>
|
||||
</section>
|
||||
}
|
@ -1,15 +1,15 @@
|
||||
package home
|
||||
|
||||
import "git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout"
|
||||
import "git.jamestombleson.com/jtom38/newsbot-portal/components/bulma"
|
||||
|
||||
templ About() {
|
||||
@layout.WithTemplate(){
|
||||
<h1 class="title"> About this project</h1>
|
||||
|
||||
<section class="section">
|
||||
@bulma.Title("About this project")
|
||||
@bulma.Block() {
|
||||
Newsbot started a small project to send out notifications to discord servers.
|
||||
I wanted to be able to keep the small communitiy aware of new posts about a game we all played.
|
||||
That feature still exists because I think that keeping a communitiy aware and engaged is important and not everyone follows the same news.
|
||||
</section>
|
||||
}
|
||||
}
|
||||
}
|
@ -1,32 +1,27 @@
|
||||
package home
|
||||
|
||||
import "git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout"
|
||||
import "git.jamestombleson.com/jtom38/newsbot-portal/internal/views/bulma"
|
||||
import (
|
||||
b "git.jamestombleson.com/jtom38/newsbot-portal/components/bulma"
|
||||
bl "git.jamestombleson.com/jtom38/newsbot-portal/components/bulma/layout"
|
||||
"git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout"
|
||||
)
|
||||
|
||||
templ Index() {
|
||||
@layout.WithTemplate() {
|
||||
@bulma.Hero("Welcome to Newsbot!", "Your new home for your news.")
|
||||
|
||||
<section class="section">
|
||||
<p>
|
||||
@bl.Hero("Welcome to Newsbot!", "Your new home for your news.")
|
||||
@b.Block() {
|
||||
News bot is a self hostable solution to aggregating your news.
|
||||
You can run `Newsbot` as an API or interact with it with this site.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
|
||||
<div class="block">
|
||||
<h2 class="title">Why Newsbot</h2>
|
||||
}
|
||||
@b.H2("Why Newsbot", false)
|
||||
@b.Block() {
|
||||
I started to build this tool to help me avoid sitting on the big platform websites.
|
||||
I wanted a tool that would work for me, not them.
|
||||
|
||||
This tool started as a notification system that would let me redirect RSS posts over to Discord servers.
|
||||
It still has those roots but now its starting to scale up to a full Aggregation platform.
|
||||
|
||||
</div>
|
||||
<p>
|
||||
}
|
||||
@b.Block() {
|
||||
This project is a passion project of mine as I
|
||||
</p>
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
package layout
|
||||
|
||||
import "git.jamestombleson.com/jtom38/newsbot-portal/components/bulma"
|
||||
|
||||
templ header() {
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@1.0.0/css/bulma.min.css"/>
|
||||
@bulma.UseBulmaCdn()
|
||||
<link rel="stylesheet" href="/css/main.css"/>
|
||||
<script src="https://unpkg.com/htmx.org@1.9.11" integrity="sha384-0gxUXCCR8yv9FM2b+U3FDbsKthCI66oH5IA9fHppQq9DDMHuMauqq1ZHBpJxQ0J0" crossorigin="anonymous"></script>
|
||||
<meta charset="utf-8"/>
|
||||
|
@ -1,10 +1,29 @@
|
||||
package sources
|
||||
|
||||
import "git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout"
|
||||
import "git.jamestombleson.com/jtom38/newsbot-portal/internal/models"
|
||||
import (
|
||||
"git.jamestombleson.com/jtom38/newsbot-portal/components/bulma"
|
||||
bf "git.jamestombleson.com/jtom38/newsbot-portal/components/bulma/form"
|
||||
bl "git.jamestombleson.com/jtom38/newsbot-portal/components/bulma/layout"
|
||||
"git.jamestombleson.com/jtom38/newsbot-portal/internal/models"
|
||||
"git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout"
|
||||
)
|
||||
|
||||
var (
|
||||
p = bf.NewParam{
|
||||
HxPost: "/sources/add",
|
||||
}
|
||||
)
|
||||
|
||||
templ Add(model models.AddSourcePayloadModel) {
|
||||
@layout.WithTemplate() {
|
||||
<form hx-post="/sources/add"></form>
|
||||
@bl.Hero("New Source", "")
|
||||
@bulma.Block() {
|
||||
At this time only direct RSS links are allowed to be provided.
|
||||
}
|
||||
@bf.New(p) {
|
||||
@bf.TextInput("name", bf.InputTypeText, "Name of the site")
|
||||
@bf.TextInput("url", bf.InputTypeText, "RSS URL")
|
||||
@bf.Submit("Submit", bulma.ColorPrimary)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
11
internal/views/sources/addAfter.templ
Normal file
11
internal/views/sources/addAfter.templ
Normal 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)
|
||||
}
|
||||
}
|
@ -1,12 +1,23 @@
|
||||
package sources
|
||||
|
||||
import "git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout"
|
||||
import "git.jamestombleson.com/jtom38/newsbot-portal/internal/models"
|
||||
import (
|
||||
"git.jamestombleson.com/jtom38/newsbot-portal/components/bulma"
|
||||
bh "git.jamestombleson.com/jtom38/newsbot-portal/components/bulma/html"
|
||||
"git.jamestombleson.com/jtom38/newsbot-portal/internal/models"
|
||||
"git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout"
|
||||
)
|
||||
|
||||
templ ListAll(model models.ListAllSourcesViewModel) {
|
||||
@layout.WithTemplate() {
|
||||
@bulma.Button() {
|
||||
@bh.ALink("/sources/add", "New Source")
|
||||
}
|
||||
@bh.Br()
|
||||
@bh.Br()
|
||||
for _, item := range model.Items {
|
||||
<a href={ templ.SafeURL(item.Url) } target="_blank" rel="noopener noreferrer">{ item.DisplayName } - { item.Source } </a>
|
||||
@bulma.ButtonColor(bulma.ColorPrimary) {
|
||||
@bulma.ANewTab(item.Url, item.DisplayName)
|
||||
}
|
||||
<br/>
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,16 @@
|
||||
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.
|
||||
// It just returns a partial view because it will overlap with the existing template.
|
||||
templ AfterLogin(vm models.AfterLoginViewModel) {
|
||||
if vm.Success {
|
||||
<div class="notification is-success">
|
||||
{ vm.Message }
|
||||
</div>
|
||||
@bulma.Notification(vm.Message, bulma.ColorSuccess)
|
||||
} else {
|
||||
<div class="notification is-error">
|
||||
{ vm.Message }
|
||||
</div>
|
||||
@bulma.Notification(vm.Message, bulma.ColorError)
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,13 @@
|
||||
package users
|
||||
|
||||
import "git.jamestombleson.com/jtom38/newsbot-portal/components/bulma"
|
||||
|
||||
// This is returned after the user creates an account.
|
||||
// It just returns a partial view because it will overlap with the existing template.
|
||||
templ AfterSignUp(message string, success bool) {
|
||||
if success {
|
||||
<div class="notification is-success">
|
||||
{ message }
|
||||
</div>
|
||||
@bulma.Notification(message, bulma.ColorSuccess)
|
||||
} else {
|
||||
<div class="notification is-error">
|
||||
{ message }
|
||||
</div>
|
||||
@bulma.Notification(message, bulma.ColorError)
|
||||
}
|
||||
}
|
||||
|
32
internal/views/users/login copy.templ
Normal file
32
internal/views/users/login copy.templ
Normal file
@ -0,0 +1,32 @@
|
||||
package users
|
||||
|
||||
import (
|
||||
"git.jamestombleson.com/jtom38/newsbot-portal/components/bulma/form"
|
||||
"git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout"
|
||||
)
|
||||
|
||||
var (
|
||||
p = form.NewParam{
|
||||
HxPost: "/users/login",
|
||||
}
|
||||
)
|
||||
|
||||
templ LoginNew() {
|
||||
@layout.WithTemplate() {
|
||||
@form.New(p) {
|
||||
@form.Field() {
|
||||
@form.Label("Username")
|
||||
@form.Control() {
|
||||
@form.TextInput("username", "text", "email address")
|
||||
}
|
||||
}
|
||||
@form.Field() {
|
||||
@form.Label("Password")
|
||||
@form.Control() {
|
||||
@form.TextInput("password", form.InputTypePassword, "")
|
||||
}
|
||||
}
|
||||
@form.Submit("Submit", "is-primary")
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
package users
|
||||
|
||||
import "git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout"
|
||||
import "git.jamestombleson.com/jtom38/newsbot-portal/internal/views/bulma"
|
||||
import bl "git.jamestombleson.com/jtom38/newsbot-portal/components/bulma/layout"
|
||||
|
||||
templ Logout() {
|
||||
@layout.WithTemplate(){
|
||||
@bulma.Hero("You are out of here!", "Please login again when you are ready.")
|
||||
@bl.Hero("You are out of here!", "Please login again when you are ready.")
|
||||
}
|
||||
}
|
@ -1,15 +1,20 @@
|
||||
package users
|
||||
|
||||
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"
|
||||
bh "git.jamestombleson.com/jtom38/newsbot-portal/components/bulma/html"
|
||||
bl "git.jamestombleson.com/jtom38/newsbot-portal/components/bulma/layout"
|
||||
"git.jamestombleson.com/jtom38/newsbot-portal/internal/views/layout"
|
||||
)
|
||||
|
||||
templ Profile() {
|
||||
@layout.WithTemplate() {
|
||||
@bulma.Hero("Profile", "Here you can update your profile 😀")
|
||||
@bl.Hero("Profile", "Here you can update your profile 😀")
|
||||
|
||||
<button type="button" class="button">
|
||||
<a href="/users/forcelogout">Logout Everywhere</a>
|
||||
Logout Everywhere</button>
|
||||
<p class="subtitle">This will force all active sessions to stop working and require a new login.</p>
|
||||
@bulma.H2("Sessions", false)
|
||||
@bulma.Button() {
|
||||
@bh.ALink("/users/forcelogout", "Terminate all active sessions")
|
||||
}
|
||||
@bulma.Subitle("This will force you to login again as the application will give you a new session value.")
|
||||
}
|
||||
}
|
||||
|
@ -1,23 +1,26 @@
|
||||
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() {
|
||||
@layout.WithTemplate() {
|
||||
<form hx-post="/users/signup">
|
||||
<div class="field">
|
||||
<label class="label">Username</label>
|
||||
<div class="control">
|
||||
<input class="input" type="text" name="username" id="username"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label">Password</label>
|
||||
<div class="control">
|
||||
<input class="input" type="password" name="password" id="exampleInputPassword1"/>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" class="button is-primary">Submit</button>
|
||||
</form>
|
||||
@form.New(form.NewParam{HxPost: "/users/signup"}) {
|
||||
@form.Field(){
|
||||
@form.Label("Username")
|
||||
@form.Control() {
|
||||
@form.TextInput("username", form.InputTypeText, "username or email address")
|
||||
}
|
||||
}
|
||||
@form.Field() {
|
||||
@form.Label("Password")
|
||||
@form.Control() {
|
||||
@form.TextInput("password", form.InputTypePassword, "Nice strong password, like Ox!")
|
||||
}
|
||||
}
|
||||
@form.Submit("Submit", "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user