Skip to content

Commit 691823e

Browse files
0xmadmichiosw
authored andcommitted
feat(web): add mock create server method
1 parent 9c3ef91 commit 691823e

File tree

9 files changed

+107
-29
lines changed

9 files changed

+107
-29
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ This project uses Go modules and follows a standard Go project layout:
8383

8484
This will compile the application into the `out/` directory and start the server (defaulting to `localhost:8080`).
8585

86-
2. **Access the UI (Placeholder):** Open your browser to `http://localhost:8080/ui`.
86+
2. **Access the UI (Placeholder):** Open your browser to `http://localhost:8080`.
8787

8888
## API Documentation
8989

internal/web/handlers/ui.go

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
package handlers
33

44
import (
5+
"fmt"
56
"net/http"
67

78
"github.com/co-browser/agent-browser/internal/log"
@@ -19,8 +20,9 @@ func NewUIHandler(logger log.Logger) http.Handler {
1920
h := &UIHandler{log: logger}
2021
mux := http.NewServeMux()
2122

22-
mux.HandleFunc("/ui", h.serveIndex)
23-
mux.HandleFunc("/ui/add", h.serveAddPage)
23+
mux.HandleFunc("/", h.serveIndex)
24+
mux.HandleFunc("/add", h.serveAddPage)
25+
mux.HandleFunc("/success", h.serveSuccessPage)
2426

2527
return mux
2628
}
@@ -43,10 +45,34 @@ func (h *UIHandler) serveIndex(w http.ResponseWriter, r *http.Request) {
4345
},
4446
},
4547
}).Render(r.Context(), w)
48+
4649
if err != nil {
4750
// Use the injected logger
4851
h.log.Error().Err(err).Msg("failed to render index page template")
4952
http.Error(w, "failed to render page", http.StatusInternalServerError)
5053
// Removed old comment: // Consider logging the error as well: log.Printf(\"Error rendering template: %v\", err)
5154
}
5255
}
56+
57+
func (h *UIHandler) serveAddPage(w http.ResponseWriter, r *http.Request) {
58+
err := templates.AddPage(templates.AddPageProps{}).Render(r.Context(), w)
59+
60+
if err != nil {
61+
h.log.Error().Err(err).Msg("failed to render add page template")
62+
http.Error(w, "failed to render page", http.StatusInternalServerError)
63+
}
64+
}
65+
66+
func (h *UIHandler) serveSuccessPage(w http.ResponseWriter, r *http.Request) {
67+
name := r.URL.Query().Get("name")
68+
ip := r.URL.Query().Get("ip")
69+
70+
text := fmt.Sprintf("Successfully added server '%s' with IP %s.", name, ip)
71+
72+
err := templates.SuccessPage(templates.SuccessPageProps{Text: text}).Render(r.Context(), w)
73+
74+
if err != nil {
75+
h.log.Error().Err(err).Msg("failed to render success page template")
76+
http.Error(w, "failed to render page", http.StatusInternalServerError)
77+
}
78+
}
Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,2 @@
11
// Package middleware provides HTTP middleware components for the web server.
22
package middleware
3-
4-
import "net/http"
5-
6-
func StripTrailingSlash(next http.Handler) http.Handler {
7-
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
8-
if len(r.URL.Path) > 1 && r.URL.Path[len(r.URL.Path)-1] == '/' {
9-
http.Redirect(w, r, r.URL.Path[:len(r.URL.Path)-1], http.StatusMovedPermanently)
10-
return
11-
}
12-
13-
next.ServeHTTP(w, r)
14-
})
15-
}

internal/web/server.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,27 @@ import (
1212
)
1313

1414
// NewMux creates the main HTTP ServeMux.
15-
func NewMux(uiHandler http.Handler /* add apiHandler http.Handler later */) *http.ServeMux {
15+
func NewMux(params struct {
16+
fx.In
17+
18+
UIHandler http.Handler `name:"uiHandler"`
19+
APIHandler http.Handler `name:"apiHandler"`
20+
}) *http.ServeMux {
1621
mux := http.NewServeMux()
1722
// Define routes here
18-
mux.Handle("/ui", uiHandler)
19-
// Add metrics endpoint
2023
mux.Handle("/metrics", promhttp.Handler())
21-
// TODO: Add routes for API handlers
22-
// mux.Handle("/api/", apiHandler)
24+
mux.Handle("/", params.UIHandler)
25+
mux.Handle("/api/", params.APIHandler)
26+
2327
return mux
2428
}
2529

26-
2730
// NewServer creates the main HTTP server instance.
2831
func NewServer(mux *http.ServeMux) *http.Server {
2932
// TODO: Make address configurable
3033
return &http.Server{
3134
Addr: ":8080",
32-
Handler: middleware.StripTrailingSlash(mux),
35+
Handler: mux,
3336
}
3437
}
3538

internal/web/templates/blocks/add_server_form.templ

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ css addServerFormButton() {
4343
templ AddServerForm() {
4444
<section class={ addServerForm() } data-testid="add-server-form">
4545
<h2>Add New Server</h2>
46-
<form method="POST" action="/ui/add">
46+
<form method="POST" action="/api/create">
4747
<div class={ addServerFormField() }>
4848
<label class={ addServerFormFieldLabel() } for="name">
4949
Server Name:
@@ -53,6 +53,7 @@ templ AddServerForm() {
5353
id="name"
5454
type="text"
5555
name="name"
56+
pattern="^[a-zA-Z0-9]([a-zA-Z0-9-_]{0,62}[a-zA-Z0-9])?$"
5657
placeholder="Enter server name"
5758
required
5859
/>

internal/web/templates/blocks/header.templ

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ css headerLink() {
1818

1919
templ Header(name string) {
2020
<header class={ header() } data-testid="header">
21-
<a class={ headerLink() } href="/ui"><h1 class={ headerTitle() }>{ name }</h1></a>
21+
<a class={ headerLink() } href="/"><h1 class={ headerTitle() }>{ name }</h1></a>
2222
</header>
2323
}

internal/web/templates/blocks/servers.templ

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,19 @@ css serverSectionHeader() {
5656
align-items: center;
5757
}
5858

59+
css serverListItemRemove() {
60+
background-color: #ff4d4d;
61+
color: #fff;
62+
padding: 5px 10px;
63+
border: none;
64+
border-radius: 4px;
65+
}
66+
5967
templ Servers(servers []domain.ServerItem) {
6068
<section class={ serverSection() }>
6169
<div class={ serverSectionHeader() }>
6270
<h2 class={ serverTitle() }>MCP servers</h2>
63-
@components.Link("Add server", "/ui/add")
71+
@components.Link(components.LinkProps{ Name: "Add server", Href: "/add" })
6472
</div>
6573
<ul class={ serverList() } data-testid="servers">
6674
for _, item := range servers {
@@ -76,6 +84,6 @@ templ Server(server domain.ServerItem) {
7684
<strong class={ serverListItemName() }>{ server.Name }</strong>
7785
<div class={ serverListItemIP() }>{ server.IP }</div>
7886
</div>
79-
@components.Button(components.ButtonProps{Label: "Remove", Type: "button"})
87+
@components.Button(components.ButtonProps{Label: "Remove", Type: "button", Class: serverListItemRemove()})
8088
</li>
8189
}

internal/web/templates/components/link.templ

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
package components
22

3+
type LinkProps struct {
4+
Name string
5+
Href templ.SafeURL
6+
Class templ.CSSClass
7+
}
8+
39
css link() {
410
text-decoration: none;
511
text-transform: none;
@@ -11,6 +17,6 @@ css link() {
1117
display: block;
1218
}
1319

14-
templ Link(name string, href templ.SafeURL) {
15-
<a class={ link() } href={ href }>{ name }</a>
20+
templ Link(props LinkProps) {
21+
<a class={ link(), props.Class } href={ props.Href }>{ props.Name }</a>
1622
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package templates
2+
3+
import (
4+
"github.com/co-browser/agent-browser/internal/web/templates/blocks"
5+
"github.com/co-browser/agent-browser/internal/web/templates/components"
6+
)
7+
8+
type SuccessPageProps struct {
9+
Text string
10+
}
11+
12+
css successContainer() {
13+
padding: 20px 16px;
14+
display: flex;
15+
flex-direction: column;
16+
align-items: center;
17+
justify-content: center;
18+
}
19+
20+
css successGoBackLink() {
21+
display: flex;
22+
align-items: center;
23+
justify-content: center;
24+
height: 40px;
25+
background-color: #007bff;
26+
color: white;
27+
border: none;
28+
border-radius: 4px;
29+
}
30+
31+
templ SuccessPageComponent(props SuccessPageProps) {
32+
<section class={ successContainer() } data-testid="success-page">
33+
<h2>Success</h2>
34+
<div>
35+
if props.Text != "" {
36+
<p>{ props.Text }</p>
37+
} else {
38+
<p>Operation completed successfully!</p>
39+
}
40+
@components.Link(components.LinkProps{Name: "Go back to home", Href: "/", Class: successGoBackLink()})
41+
</div>
42+
</section>
43+
}
44+
45+
templ SuccessPage(props SuccessPageProps) {
46+
@blocks.Main(SuccessPageComponent(props))
47+
}

0 commit comments

Comments
 (0)