add mark_posted

master
Joshua Herring 3 weeks ago
parent 20ff37ec43
commit 0fe34ddb61

@ -132,6 +132,8 @@ func HandleAPI(w http.ResponseWriter, r *http.Request) {
switch req.Method {
case "report_activity":
ReportActivity(w, conn, req, user)
case "mark_posted":
MarkPosted(w, conn, req, user)
default:
jsonRPCErr(w, -32601, "Method not found", req.ID)
}

@ -0,0 +1,41 @@
package api
import (
"database/sql"
"encoding/json"
"net/http"
"faculty_media_report/dbi"
)
type markPostedParams struct {
UID string `json:"uid"`
}
func MarkPosted(w http.ResponseWriter, conn *sql.Conn, req jsonRPCRequest, user dbi.User) {
if user.Status != "admin" {
jsonRPCErr(w, -32000, "Forbidden", req.ID)
return
}
var params markPostedParams
if err := json.Unmarshal(req.Params, &params); err != nil {
jsonRPCErr(w, -32602, "Invalid params", req.ID)
return
}
if params.UID == "" {
jsonRPCErr(w, -32602, "Invalid params: uid is required", req.ID)
return
}
if err := dbi.MarkPosted(conn, params.UID); err != nil {
jsonRPCErr(w, -32603, "Internal error", req.ID)
return
}
writeJSONRPC(w, jsonRPCResponse{
Jsonrpc: "2.0",
Result: true,
ID: req.ID,
})
}

@ -61,12 +61,17 @@ func handleLoginPost(w http.ResponseWriter, r *http.Request) {
}
if user.Status == "admin" {
token, err := dbi.GenJWT(user)
if err != nil {
fail()
return
}
items, err := dbi.GetReportedItems(conn)
if err != nil {
fail()
return
}
html, err := pages.DashboardPage(items)
html, err := pages.DashboardPage(token, items)
if err != nil {
fail()
return

@ -7,6 +7,11 @@ import (
"faculty_media_report/dbi"
)
type dashboardData struct {
JWT string
Items []dbi.DashboardItem
}
var dashboardTmpl = template.Must(template.New("dashboard").Parse(`<!DOCTYPE html>
<html lang="en">
<head>
@ -14,6 +19,7 @@ var dashboardTmpl = template.Must(template.New("dashboard").Parse(`<!DOCTYPE htm
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dashboard Maurer School of Law</title>
<link rel="stylesheet" href="https://unpkg.com/rivet-core@2/css/rivet.min.css">
<script>var JWT = "{{.JWT}}";</script>
</head>
<body>
<header class="rvt-header-wrapper">
@ -41,7 +47,7 @@ var dashboardTmpl = template.Must(template.New("dashboard").Parse(`<!DOCTYPE htm
<main id="main-content" class="rvt-container-xl rvt-p-top-xxl rvt-p-bottom-xxl">
<h1 class="rvt-ts-xxl rvt-m-bottom-xxl">Activity Report Dashboard</h1>
{{if .}}
{{if .Items}}
<div class="rvt-m-bottom-lg">
<button class="rvt-button rvt-button--secondary" type="button" id="download-csv">Download CSV Report</button>
</div>
@ -59,17 +65,19 @@ var dashboardTmpl = template.Must(template.New("dashboard").Parse(`<!DOCTYPE htm
<th scope="col">Description</th>
<th scope="col">Hyperlink</th>
<th scope="col" data-col="5" style="cursor:pointer;white-space:nowrap;">Type <span class="sort-ind">&#8597;</span></th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
{{range .}}
<tr>
{{range .Items}}
<tr data-uid="{{.UID}}">
<td>{{.Created}}</td>
<td>{{.LastName}}, {{.FirstName}}</td>
<td>{{.Title}}</td>
<td>{{.Description}}</td>
<td>{{if .Hyperlink}}<a href="{{.Hyperlink}}" target="_blank" rel="noopener">Link</a>{{end}}</td>
<td>{{.ItemType}}</td>
<td><button type="button" class="mark-posted-btn" aria-label="Mark as posted" style="background:none;border:none;cursor:pointer;color:#006633;padding:0;"><rvt-icon name="check"></rvt-icon></button></td>
</tr>
{{end}}
</tbody>
@ -79,6 +87,7 @@ var dashboardTmpl = template.Must(template.New("dashboard").Parse(`<!DOCTYPE htm
<p class="rvt-ts-lg">No reported items.</p>
{{end}}
</main>
<script type="module" src="https://unpkg.com/rivet-icons@3/dist/rivet-icons.js"></script>
<script>
(function() {
var table = document.getElementById('report-table');
@ -124,6 +133,31 @@ var dashboardTmpl = template.Must(template.New("dashboard").Parse(`<!DOCTYPE htm
apply();
});
});
table.addEventListener('click', function(e) {
var btn = e.target.closest('.mark-posted-btn');
if (!btn) return;
var row = btn.closest('tr');
var uid = row ? row.getAttribute('data-uid') : null;
if (!uid) return;
btn.disabled = true;
fetch('/faculty/activity/api', {
method: 'POST',
headers: {'Content-Type': 'application/json', 'Authorization': 'Bearer ' + JWT},
body: JSON.stringify({jsonrpc: '2.0', method: 'mark_posted', params: {uid: uid}, id: 1})
})
.then(function(resp) { return resp.json(); })
.then(function(data) {
if (data.error) {
btn.disabled = false;
return;
}
allRows = allRows.filter(function(r) { return r !== row; });
row.remove();
})
.catch(function() { btn.disabled = false; });
});
}
var dlBtn = document.getElementById('download-csv');
@ -150,7 +184,7 @@ var dashboardTmpl = template.Must(template.New("dashboard").Parse(`<!DOCTYPE htm
if (i === 4) {
var a = cell.querySelector('a');
fields.push(esc(a ? a.href : ''));
} else {
} else if (i < 6) {
fields.push(esc(cell.textContent.trim()));
}
});
@ -174,9 +208,9 @@ var dashboardTmpl = template.Must(template.New("dashboard").Parse(`<!DOCTYPE htm
</body>
</html>`))
func DashboardPage(items []dbi.DashboardItem) (string, error) {
func DashboardPage(jwtToken string, items []dbi.DashboardItem) (string, error) {
var buf bytes.Buffer
if err := dashboardTmpl.Execute(&buf, items); err != nil {
if err := dashboardTmpl.Execute(&buf, dashboardData{JWT: jwtToken, Items: items}); err != nil {
return "", err
}
return buf.String(), nil

Loading…
Cancel
Save