fix incident view
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2025-03-24 17:03:16 +11:00
parent 49e60f7843
commit 252bf0a1c8
9 changed files with 612 additions and 10 deletions

View File

@@ -0,0 +1,85 @@
package views
import (
"strconv"
"mocksnow/components/core"
tpl "github.com/a-h/templ"
)
type IncidentRow struct {
ID int64
ExternalID string
CreatedAt string
IncidentNumber string
Description string
ShortDescription string
Urgency int64
Impact int64
State int64
AllNotes string
AssignmentGroup string
AssignedTo string
Category string
Subcategory string
SysID string
}
templ IncidentsTable(rows []IncidentRow) {
<!DOCTYPE html>
<html lang="en">
@core.Header()
<body>
<main>
<div>
<h1>Incidents</h1>
<div>
<table>
<thead>
<tr>
<th>ID</th>
<th>Created At</th>
<th>Incident #</th>
<th>SysId</th>
<th>Description</th>
<th>Short Description</th>
<th>Urgency</th>
<th>Impact</th>
<th>State</th>
<th>External ID</th>
<th>Work Notes</th>
<th>Assignment Group</th>
<th>Assigned To</th>
<th>Category</th>
<th>Subcategory</th>
</tr>
</thead>
<tbody>
for _, row := range rows {
<tr>
<td>{ strconv.FormatInt(row.ID, 10) }</td>
<td>{ row.CreatedAt }</td>
<td>{ row.IncidentNumber }</td>
<td>{ row.SysID }</td>
<td>{ row.Description }</td>
<td>{ row.ShortDescription }</td>
<td>{ strconv.FormatInt(row.Urgency, 10) }</td>
<td>{ strconv.FormatInt(row.Impact, 10) }</td>
<td>{ strconv.FormatInt(row.State, 10) }</td>
<td>{ row.ExternalID }</td>
<td>@tpl.Raw(row.AllNotes)</td>
<td>{ row.AssignmentGroup }</td>
<td>{ row.AssignedTo }</td>
<td>{ row.Category }</td>
<td>{ row.Subcategory }</td>
</tr>
}
</tbody>
</table>
</div>
</div>
</main>
@core.Footer()
</body>
</html>
}

View File

@@ -0,0 +1,280 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.856
package views
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
import (
tpl "github.com/a-h/templ"
"mocksnow/components/core"
"strconv"
)
type IncidentRow struct {
ID int64
ExternalID string
CreatedAt string
IncidentNumber string
Description string
ShortDescription string
Urgency int64
Impact int64
State int64
AllNotes string
AssignmentGroup string
AssignedTo string
Category string
Subcategory string
SysID string
}
func IncidentsTable(rows []IncidentRow) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<!doctype html><html lang=\"en\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = core.Header().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<body><main><div><h1>Incidents</h1><div><table><thead><tr><th>ID</th><th>Created At</th><th>Incident #</th><th>SysId</th><th>Description</th><th>Short Description</th><th>Urgency</th><th>Impact</th><th>State</th><th>External ID</th><th>Work Notes</th><th>Assignment Group</th><th>Assigned To</th><th>Category</th><th>Subcategory</th></tr></thead> <tbody>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for _, row := range rows {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<tr><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.FormatInt(row.ID, 10))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/incidents.templ`, Line: 60, Col: 71}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var3 string
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(row.CreatedAt)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/incidents.templ`, Line: 61, Col: 55}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(row.IncidentNumber)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/incidents.templ`, Line: 62, Col: 60}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(row.SysID)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/incidents.templ`, Line: 63, Col: 51}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(row.Description)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/incidents.templ`, Line: 64, Col: 57}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(row.ShortDescription)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/incidents.templ`, Line: 65, Col: 62}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.FormatInt(row.Urgency, 10))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/incidents.templ`, Line: 66, Col: 76}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var9 string
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.FormatInt(row.Impact, 10))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/incidents.templ`, Line: 67, Col: 75}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var10 string
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(strconv.FormatInt(row.State, 10))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/incidents.templ`, Line: 68, Col: 74}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var11 string
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(row.ExternalID)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/incidents.templ`, Line: 69, Col: 56}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = tpl.Raw(row.AllNotes).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 14, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var12 string
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(row.AssignmentGroup)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/incidents.templ`, Line: 71, Col: 61}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 15, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var13 string
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(row.AssignedTo)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/incidents.templ`, Line: 72, Col: 56}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 16, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var14 string
templ_7745c5c3_Var14, templ_7745c5c3_Err = templ.JoinStringErrs(row.Category)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/incidents.templ`, Line: 73, Col: 54}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var14))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 17, "</td><td>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var15 string
templ_7745c5c3_Var15, templ_7745c5c3_Err = templ.JoinStringErrs(row.Subcategory)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/incidents.templ`, Line: 74, Col: 57}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var15))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 18, "</td></tr>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 19, "</tbody></table></div></div></main>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = core.Footer().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 20, "</body></html>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return nil
})
}
var _ = templruntime.GeneratedTemplate

View File

@@ -59,7 +59,7 @@ func IncomingTable(rows []IncomingRow) templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<body><main><div><h1>Incoming Incidents</h1><div><table><thead><tr><th>ID</th><th>Incident #</th><th>Description</th><th>Short Description</th><th>Urgency</th><th>Impact</th><th>State</th><th>External ID</th><th>Work Notes</th><th>Assignment Group</th><th>Assigned To</th><th>Category</th><th>Subcategory</th><th>Created At</th></tr></thead> <tbody>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<body><main><div><h1>Incoming API Calls</h1><div><table><thead><tr><th>ID</th><th>Incident #</th><th>Description</th><th>Short Description</th><th>Urgency</th><th>Impact</th><th>State</th><th>External ID</th><th>Work Notes</th><th>Assignment Group</th><th>Assigned To</th><th>Category</th><th>Subcategory</th><th>Created At</th></tr></thead> <tbody>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}

View File

@@ -50,6 +50,10 @@ WHERE incident_number = sqlc.arg('incidentNumber');
-- name: ListIncidents :many
SELECT * FROM incidents;
-- name: GetIncidentReport :many
SELECT incidents.*, GROUP_CONCAT(worknotes.note, '<br />') AS all_notes
FROM incidents LEFT JOIN worknotes ON incidents.incident_number = worknotes.incident_number;
-- name: CreateWorkNote :one
INSERT into worknotes (
"incident_number", "note"

View File

@@ -178,6 +178,68 @@ func (q *Queries) GetIncident(ctx context.Context, incidentnumber sql.NullString
return i, err
}
const getIncidentReport = `-- name: GetIncidentReport :many
SELECT incidents.id, incidents.external_id, incidents.created_at, incidents.incident_number, incidents.description, incidents.short_description, incidents.urgency, incidents.impact, incidents.state, incidents.assignment_group, incidents.assigned_to, incidents.category, incidents.subcategory, incidents.sys_id, GROUP_CONCAT(worknotes.note, '<br />') AS all_notes
FROM incidents LEFT JOIN worknotes ON incidents.incident_number = worknotes.incident_number
`
type GetIncidentReportRow struct {
ID int64
ExternalID string
CreatedAt sql.NullTime
IncidentNumber sql.NullString
Description sql.NullString
ShortDescription sql.NullString
Urgency sql.NullInt64
Impact sql.NullInt64
State sql.NullInt64
AssignmentGroup sql.NullString
AssignedTo sql.NullString
Category sql.NullString
Subcategory sql.NullString
SysID sql.NullString
AllNotes string
}
func (q *Queries) GetIncidentReport(ctx context.Context) ([]GetIncidentReportRow, error) {
rows, err := q.db.QueryContext(ctx, getIncidentReport)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetIncidentReportRow
for rows.Next() {
var i GetIncidentReportRow
if err := rows.Scan(
&i.ID,
&i.ExternalID,
&i.CreatedAt,
&i.IncidentNumber,
&i.Description,
&i.ShortDescription,
&i.Urgency,
&i.Impact,
&i.State,
&i.AssignmentGroup,
&i.AssignedTo,
&i.Category,
&i.Subcategory,
&i.SysID,
&i.AllNotes,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const listIncidents = `-- name: ListIncidents :many
SELECT id, external_id, created_at, incident_number, description, short_description, urgency, impact, state, assignment_group, assigned_to, category, subcategory, sys_id FROM incidents
`
@@ -263,6 +325,53 @@ func (q *Queries) ListIncoming(ctx context.Context) ([]Incoming, error) {
return items, nil
}
const updateIncident = `-- name: UpdateIncident :exec
UPDATE incidents
SET
external_id = ?,
description = ?,
short_description = ?,
urgency = ?,
impact = ?,
state = ?,
assignment_group = ?,
assigned_to = ?,
category = ?,
subcategory = ?
WHERE incident_number = ?
`
type UpdateIncidentParams struct {
ExternalID string
Description sql.NullString
ShortDescription sql.NullString
Urgency sql.NullInt64
Impact sql.NullInt64
State sql.NullInt64
AssignmentGroup sql.NullString
AssignedTo sql.NullString
Category sql.NullString
Subcategory sql.NullString
IncidentNumber sql.NullString
}
func (q *Queries) UpdateIncident(ctx context.Context, arg UpdateIncidentParams) error {
_, err := q.db.ExecContext(ctx, updateIncident,
arg.ExternalID,
arg.Description,
arg.ShortDescription,
arg.Urgency,
arg.Impact,
arg.State,
arg.AssignmentGroup,
arg.AssignedTo,
arg.Category,
arg.Subcategory,
arg.IncidentNumber,
)
return err
}
const updateIncidentNumber = `-- name: UpdateIncidentNumber :exec
UPDATE incidents
SET incident_number = ?1

View File

@@ -2,6 +2,9 @@ package utils
import (
"context"
"database/sql"
"encoding/base64"
"fmt"
"log"
"log/slog"
"net"
@@ -69,7 +72,7 @@ func SleepWithContext(ctx context.Context, d time.Duration) {
}
}
// Generic converter using reflection
// Generic converter using reflection for all sqlc/sqlite types
func ConvertStruct(src interface{}, dst interface{}) {
srcVal := reflect.ValueOf(src)
srcType := reflect.TypeOf(src)
@@ -77,30 +80,97 @@ func ConvertStruct(src interface{}, dst interface{}) {
for i := 0; i < srcVal.NumField(); i++ {
srcField := srcVal.Field(i)
srcFieldType := srcField.Type()
dstField := dstVal.FieldByName(srcType.Field(i).Name)
//slog.Info("Source field", "name", srcType.Field(i).Name)
if !dstField.IsValid() || !dstField.CanSet() {
continue
}
switch srcField.Type().Name() {
case "NullString":
switch srcFieldType {
case reflect.TypeOf(sql.NullString{}):
//slog.Info("Sourcefield is string")
if srcField.FieldByName("Valid").Bool() {
dstField.SetString(srcField.FieldByName("String").String())
} else {
dstField.SetString("")
}
case "NullTime":
case reflect.TypeOf(sql.NullInt64{}):
//slog.Info("Sourcefield is int64")
if srcField.FieldByName("Valid").Bool() {
val := srcField.FieldByName("Int64").Int()
if dstField.Kind() == reflect.String {
dstField.SetString(fmt.Sprintf("%d", val))
} else {
dstField.SetInt(val)
}
} else {
if dstField.Kind() == reflect.String {
dstField.SetString("")
} else {
dstField.SetInt(0)
}
}
case reflect.TypeOf(sql.NullFloat64{}):
if srcField.FieldByName("Valid").Bool() {
val := srcField.FieldByName("Float64").Float()
if dstField.Kind() == reflect.String {
dstField.SetString(fmt.Sprintf("%f", val))
} else {
dstField.SetFloat(val)
}
} else {
if dstField.Kind() == reflect.String {
dstField.SetString("")
} else {
dstField.SetFloat(0)
}
}
case reflect.TypeOf(sql.NullBool{}):
if srcField.FieldByName("Valid").Bool() {
val := srcField.FieldByName("Bool").Bool()
if dstField.Kind() == reflect.String {
dstField.SetString(fmt.Sprintf("%t", val))
} else {
dstField.SetBool(val)
}
} else {
if dstField.Kind() == reflect.String {
dstField.SetString("")
} else {
dstField.SetBool(false)
}
}
case reflect.TypeOf(sql.NullTime{}):
//slog.Info("Sourcefield is time")
if srcField.FieldByName("Valid").Bool() {
t := srcField.FieldByName("Time").Interface().(time.Time)
dstField.SetString(t.Format("2006-01-02 15:04:05"))
} else {
slog.Info("value is not valid")
dstField.SetString("")
}
default:
// Handle int64 -> int conversion
if srcField.Kind() == reflect.Int64 && dstField.Kind() == reflect.Int {
dstField.SetInt(srcField.Int())
// Handle []byte (often from BLOB fields)
if srcField.Kind() == reflect.Slice && srcField.Type().Elem().Kind() == reflect.Uint8 {
if !srcField.IsNil() {
encoded := base64.StdEncoding.EncodeToString(srcField.Bytes())
dstField.SetString(encoded)
} else {
dstField.SetString("")
}
}
// Fallback: copy if types are directly assignable
if srcField.Type().AssignableTo(dstField.Type()) {
dstField.Set(srcField)
}
}
}

View File

@@ -0,0 +1,53 @@
package handler
import (
"context"
"encoding/json"
"fmt"
"mocksnow/components/views"
"mocksnow/db/queries"
"mocksnow/internal/utils"
"net/http"
)
func (h *Handler) RenderIncidentTable(w http.ResponseWriter, r *http.Request) {
ctx := context.Background()
h.Logger.Debug("Querying incidents table")
results, err := h.Database.Queries().GetIncidentReport(ctx)
if err != nil {
h.Logger.Error("Unable to query incoming table", "error", err)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(map[string]string{
"status": "ERROR",
"message": fmt.Sprintf("Unable to query incoming table: '%s'", err),
})
return
}
if len(results) == 0 {
h.Logger.Error("Empty updates result")
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(map[string]string{
"status": "ERROR",
"message": fmt.Sprintf("Empty updates result"),
})
return
}
views.IncidentsTable(ConvertIncidentList(results)).Render(r.Context(), w)
}
// Converts a slice of Incoming to []IncomingRow
func ConvertIncidentList(list []queries.GetIncidentReportRow) []views.IncidentRow {
rows := make([]views.IncidentRow, 0, len(list))
for _, in := range list {
//prettyPrint(in)
var row views.IncidentRow
utils.ConvertStruct(in, &row)
rows = append(rows, row)
}
return rows
}

View File

@@ -4,16 +4,16 @@ import (
"context"
"encoding/json"
"fmt"
"net/http"
"mocksnow/components/views"
"mocksnow/db/queries"
"mocksnow/internal/utils"
"net/http"
)
func (h *Handler) RenderIncomingTable(w http.ResponseWriter, r *http.Request) {
ctx := context.Background()
h.Logger.Debug("Querying updates table")
h.Logger.Debug("Querying incoming table")
results, err := h.Database.Queries().ListIncoming(ctx)
if err != nil {
h.Logger.Error("Unable to query incoming table", "error", err)

View File

@@ -31,6 +31,7 @@ func New(logger *slog.Logger, database db.Database, buildTime string, sha1ver st
mux.HandleFunc("/api/now/import/x_dusa2_itom_inc_imp", h.NewSnow)
mux.HandleFunc("/api/now/table/incident/", h.GetIncident)
mux.HandleFunc("/api/print", h.RenderIncomingTable)
mux.HandleFunc("/api/print/incidents", h.RenderIncidentTable)
// TODO - fallback route that will just echo incoming payload
mux.HandleFunc("/", h.Fallback)