added crud functionality
This commit is contained in:
parent
2131f370ee
commit
cb8d779a57
178
main.go
178
main.go
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
Loading…
Reference in New Issue