added crud functionality

This commit is contained in:
gurkenhabicht 2025-01-08 17:59:04 +01:00
parent 2131f370ee
commit cb8d779a57
5 changed files with 265 additions and 34 deletions

178
main.go
View File

@ -37,17 +37,38 @@ const (
dbName = "gomatic"
)
// type Agent struct {
// agentId int
// agentName string
// initialContact string
// lastContact string
// }
type Agent struct {
agentId int
agentName string
initialContact string
lastContact string
AgentID int `json:"agentId"`
AgentName string `json:"agentName"`
InitialContact string `json:"initialContact"`
LastContact string `json:"lastContact"`
}
func init() {
tmpl, _ = template.ParseGlob("templates/*.html")
}
func renderTemplate(w http.ResponseWriter, tmpl string, data interface{}) {
t, err := template.ParseFiles(tmpl)
if err != nil {
log.Printf("Failed to load template %s: %v", tmpl, err)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
if err := t.Execute(w, data); err != nil {
log.Printf("Failed to render template %s: %v", tmpl, err)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
return
}
}
func initDB () {
var err error
dbOpen := fmt.Sprintf("%s:%s@(%s:%d)/%s?parseTime=true", dbUser,dbPassword, dbHost, dbPort, dbName)
@ -82,7 +103,7 @@ func getAgents(dbPointer *sql.DB) ([]Agent, error) {
for rows.Next() {
var agent Agent
rowErr := rows.Scan(&agent.agentId, &agent.agentName, &agent.initialContact, &agent.lastContact)
rowErr := rows.Scan(&agent.AgentID, &agent.AgentName, &agent.InitialContact, &agent.LastContact)
if rowErr != nil {
return nil, err
}
@ -141,6 +162,140 @@ func getHomepage(w http.ResponseWriter, r *http.Request) {
tmpl.ExecuteTemplate(w, "index.html", nil)
}
func agentsHandler(w http.ResponseWriter, r *http.Request) {
// if r.URL.Path == "/agents" {
// if r.Method == http.MethodGet{
// agents, err := getAgentsFromDB()
// if err != nil {
// http.Error(w, "Failed to fetch agents", http.StatusInternalServerError)
// return
// }
// renderTemplate(w, "templates/partials/agent_list.html", agents)
// } else {
// http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
// }
// return
// }
parts := strings.Split(strings.TrimPrefix(r.URL.Path, "/agents/"), "/")
agentId := ""
if len(parts) > 0 && parts[0] != "" {
agentId = parts[0]
}
// if len (parts) < 1 || parts[0] == "" {
// http.Error(w, "Agent ID required", http.StatusBadRequest)
// return
// }
// agentId := parts[0]
switch r.Method {
case http.MethodDelete:
deleteAgent(w, r, agentId)
case http.MethodGet:
if agentId == "" {
listAgents(w, r)
} else {
getAgent(w, r, agentId)
}
case http.MethodPost:
createAgent(w, r)
case http.MethodPut:
updateAgent(w, r, agentId)
default:
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
}
}
func listAgents(w http.ResponseWriter, r *http.Request) {
agents, err := getAgentsFromDB()
if err != nil {
http.Error(w, "Failed to fetch agents", http.StatusInternalServerError)
return
}
renderTemplate(w, "templates/partials/agent_list.html", agents)
}
func deleteAgent(w http.ResponseWriter, r *http.Request, agentID string) {
query := "DELETE FROM agents WHERE agentId = ?"
_, err := db.Exec(query, agentID)
if err != nil {
http.Error(w, "Failed to delete agent", http.StatusInternalServerError)
return
}
agents, err := getAgentsFromDB()
if err != nil {
http.Error(w, "Failed to fetch agents", http.StatusInternalServerError)
return
}
renderTemplate(w, "templates/partials/agent_list.html", agents)
}
func createAgent(w http.ResponseWriter, r * http.Request) {
err := r.ParseForm()
if err != nil {
http.Error(w, "Invalid form data", http.StatusBadRequest)
}
agentName := r.FormValue("agentName")
agentId := 42
// initalContact := r.FormValue("initialContact")
// lastContact := r.FormValue("lastContact")
query := "INSERT INTO agents (agentId, agentName, initialContact, lastContact) VALUES (?, ?, NOW(), NOW())"
_, err = db.Exec(query, agentId, agentName)
if err != nil {
http.Error(w, "Failed to create agent", http.StatusInternalServerError)
return
}
listAgents(w, r)
}
func updateAgent(w http.ResponseWriter, r *http.Request, agentId string) {
err := r.ParseForm()
if err != nil {
http.Error(w, "Invalid form data", http.StatusBadRequest)
return
}
agentName := r.FormValue("agentName")
lastContact := r.FormValue("lastContact")
query := "UPDATE agents SET agentName = ?, lastContact = ? where agentId = ?"
_, err = db.Exec(query, agentName, lastContact, agentId)
if err != nil {
http.Error(w, "Failed to update agent", http.StatusInternalServerError)
return
}
listAgents(w, r,)
}
func getAgentsFromDB() ([]Agent, error) {
query := "SELECT agentId, agentName, initialContact, lastContact FROM agents"
rows, err := db.Query(query)
if err != nil {
return nil, err
}
defer rows.Close()
var agents []Agent
for rows.Next() {
var agent Agent
err := rows.Scan(&agent.AgentID, &agent.AgentName, &agent.InitialContact, &agent.LastContact)
if err != nil {
return nil, err
}
agents = append(agents, agent)
}
return agents, rows.Err()
}
func agentHandler(w http.ResponseWriter, r *http.Request) {
parts := strings.Split(strings.TrimPrefix(r.URL.Path, "/agents/"), "/")
if len (parts) < 1 || parts[0] == "" {
@ -171,7 +326,7 @@ type webSocketHandler struct {
func getAgent(w http.ResponseWriter, r *http.Request, agentId string) {
query := "Select agentId, agentName, initialContact, lastContact from agents where agentId = ?"
var agent Agent
err := db.QueryRow(query, agentId).Scan(&agentId, &agent.agentName, &agent.initialContact, &agent.lastContact)
err := db.QueryRow(query, agentId).Scan(&agent.AgentID, &agent.AgentName, &agent.InitialContact, &agent.LastContact)
if err == sql.ErrNoRows {
http.Error(w, "Agent not found", http.StatusNotFound)
return
@ -181,6 +336,8 @@ func getAgent(w http.ResponseWriter, r *http.Request, agentId string) {
}
// return agent, nil
// TODO: Add agent_detail.html
renderTemplate(w, "templates/partials/agent_detail.html", agent)
}
@ -226,12 +383,13 @@ func main() {
webMux := http.NewServeMux()
webMux.HandleFunc("/", getHomepage)
webMux.HandleFunc("/index", getRoot)
webMux.HandleFunc("/hello", getHello)
webMux.HandleFunc("/agents", fetchAgents)
// webMux.HandleFunc("/index", getRoot)
// webMux.HandleFunc("/hello", getHello)
// webMux.HandleFunc("/agents", fetchAgents)
webMux.HandleFunc("/agents", agentsHandler)
// webMux.HandleFunc("/newagentform", getAgentForm)
// webMux.HandleFunc("/getagentupdateform/{agentId}", getAgentUpdateForm)
webMux.HandleFunc("/agents/{agentId}", agentHandler)
webMux.HandleFunc("/agents/{agentId}", agentsHandler)
// webMux.HandleFunc

View File

@ -1,14 +1,21 @@
{{define "agentList"}}
<ul>
{{range .}}
<li>
<span {{if .Done}} style="text-decoration:line-through" {{end}}>{{.Agents}}</span>
<!-- [<a href="#" hx-get="/gettaskupdateform/{{.Id}}" hx-target="#addTaskForm" hx-swap="innerHTML">Edit</a>] | -->
<a href="#" hx-delete="/agents/{{.agentId}}"
hx-confirm="Are you sure you want to Delete this Task?"
hx-target="#agentList">[Delete]</a>
</li>
{{end}}
</ul>
{{end}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Agent List</title>
<script src="https://unpkg.com/htmx.org"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css">
</head>
<body>
<div class="container mt-5">
<h1>Agent List</h1>
<div id="agent-list">
<!-- Agents will be dynamically loaded here -->
<button class="btn btn-primary mb-3" hx-get="/agents" hx-target="#agent-list" hx-swap="innerHTML">
Load Agents
</button>
</div>
</div>
</body>
</html>

View File

@ -5,23 +5,55 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://unpkg.com/htmx.org@1.9.12"></script>
<title>To Do App</title>
<!-- <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script> -->
<title>g2: gommand & gontrol</title>
<script>
document.body.addEventListener('htmx:afterRequest', (evt) => {
console.log(evt.detail.xhr.responseText);
});
document.body.addEventListener('htmx:responseError', (evt) => {
console.error(evt.detail.xhr.responseText);
});
</script>
</head>
<body>
<div class="container">
<div class="row">
<div class="col">
<h2>Agents</h2>
<div class="row">
<div class="col">
<h2>Tasks</h2>
<div id="agentList" hx-get="/agents" hx-trigger="load" hx-swap="innerHTML">
<!-- Agent List -->
<div id="agentList" hx-get="/agents" hx-trigger="load" hx-swap="innerHTML"></div>
<!-- Add Agent Form -->
<button class="btn btn-primary mt-3" data-bs-toggle="collapse" data-bs-target="#addAgentForm">Add Agent</button>
<div id="addAgentForm" class="collapse mt-2">
<form hx-post="/agents" hx-target="#agentList" hx-swap="innerHTML">
<div class="mb-3">
<label for="agentName" class="form-label">Agent Name</label>
<input type="text" class="form-control" id="agentName" name="agentName" required>
</div>
<div class="mb-3">
<label for="initialContact" class="form-label">Initial Contact</label>
<input type="datetime-local" class="form-control" id="initialContact" name="initialContact" required>
</div>
<div class="mb-3">
<label for="lastContact" class="form-label">Last Contact</label>
<input type="datetime-local" class="form-control" id="lastContact" name="lastContact" required>
</div>
<button type="submit" class="btn btn-success">Add Agent</button>
</form>
</div>
</div>
<!-- Agent Details -->
<div class="col" id="agentDetails">
<h3>Details</h3>
<p>Select an agent to view details.</p>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,8 @@
<div id="agent-detail">
<h2>Agent Details</h2>
<p>ID: {{.AgentID}}</p>
<p>Name: {{.AgentName}}</p>
<p>Initial Contact: {{.InitialContact}}</p>
<p>Last Contact: {{.LastContact}}</p>
<button hx-get="/agents" hx-target="#agentList" hx-swap="innerHTML">Back to List</button>
</div>

View File

@ -0,0 +1,26 @@
<table class="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Initial Contact</th>
<th>Last Contact</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{{range .}}
<tr>
<td>{{.AgentID}}</td>
<td>{{.AgentName}}</td>
<td>{{.InitialContact}}</td>
<td>{{.LastContact}}</td>
<td>
<button hx-get="/agents/{{.AgentID}}" hx-target="#agentDetails" hx-swap="innerHTML">View</button>
<button class="btn btn-danger" hx-delete="/agents/{{.AgentID}}" hx-target="#agentList" hx-swap="innerHTML">Delete</button>
</td>
</tr>
{{end}}
</tbody>
</table>