diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2018-11-22 14:27:37 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2018-11-22 14:36:32 +0100 |
| commit | 13ab4beeefd2c49666ce771753fbb3a28c9d2f2c (patch) | |
| tree | 95591888c2e60e548c30e111bdce6e0d2e6a3963 /dashboard | |
| parent | 582e1f0d1d51b9237d2dedfcb4c1540b849da8c2 (diff) | |
syz-manager: modernize web UI
1. Use dashboard style.
2. Allow sorting of tables.
3. Show old crashes in grey.
4. Use tables instead of text output for more pages.
5. Show corpus inputs on a separate page to allow copy-pasting.
6. Use standard JS sorting instead of custom bubble sort (much faster).
7. Fix off-by one in table sorting.
Fixes #694
Diffstat (limited to 'dashboard')
| -rw-r--r-- | dashboard/app/handler.go | 87 | ||||
| -rw-r--r-- | dashboard/app/main.go | 3 | ||||
| -rw-r--r-- | dashboard/app/reporting.go | 5 | ||||
| -rw-r--r-- | dashboard/app/static/common.js | 31 | ||||
| -rw-r--r-- | dashboard/app/static/style.css | 16 |
5 files changed, 36 insertions, 106 deletions
diff --git a/dashboard/app/handler.go b/dashboard/app/handler.go index 3bde1cab5..167ca5857 100644 --- a/dashboard/app/handler.go +++ b/dashboard/app/handler.go @@ -5,12 +5,9 @@ package dash import ( "bytes" - "fmt" - "html/template" "net/http" - "time" - "github.com/google/syzkaller/dashboard/dashapi" + "github.com/google/syzkaller/pkg/html" "golang.org/x/net/context" "google.golang.org/appengine" "google.golang.org/appengine/log" @@ -90,84 +87,4 @@ func commonHeader(c context.Context, r *http.Request) *uiHeader { return h } -func formatTime(t time.Time) string { - if t.IsZero() { - return "" - } - return t.Format("2006/01/02 15:04") -} - -func formatClock(t time.Time) string { - if t.IsZero() { - return "" - } - return t.Format("15:04") -} - -func formatDuration(d time.Duration) string { - if d == 0 { - return "" - } - days := int(d / (24 * time.Hour)) - hours := int(d / time.Hour % 24) - mins := int(d / time.Minute % 60) - if days >= 10 { - return fmt.Sprintf("%vd", days) - } else if days != 0 { - return fmt.Sprintf("%vd%02vh", days, hours) - } else if hours != 0 { - return fmt.Sprintf("%vh%02vm", hours, mins) - } - return fmt.Sprintf("%vm", mins) -} - -func formatLateness(now, t time.Time) string { - if t.IsZero() { - return "never" - } - d := now.Sub(t) - if d < 5*time.Minute { - return "now" - } - return formatDuration(d) -} - -func formatReproLevel(l dashapi.ReproLevel) string { - switch l { - case ReproLevelSyz: - return "syz" - case ReproLevelC: - return "C" - default: - return "" - } -} - -func formatStat(v int64) string { - if v == 0 { - return "" - } - return fmt.Sprint(v) -} - -func formatShortHash(v string) string { - const hashLen = 8 - if len(v) <= hashLen { - return v - } - return v[:hashLen] -} - -var ( - templates = template.Must(template.New("").Funcs(templateFuncs).ParseGlob("*.html")) - - templateFuncs = template.FuncMap{ - "formatTime": formatTime, - "formatClock": formatClock, - "formatDuration": formatDuration, - "formatLateness": formatLateness, - "formatReproLevel": formatReproLevel, - "formatStat": formatStat, - "formatShortHash": formatShortHash, - } -) +var templates = html.CreateGlob("*.html") diff --git a/dashboard/app/main.go b/dashboard/app/main.go index 02dbfb8d9..525cd1c04 100644 --- a/dashboard/app/main.go +++ b/dashboard/app/main.go @@ -14,6 +14,7 @@ import ( "github.com/google/syzkaller/dashboard/dashapi" "github.com/google/syzkaller/pkg/email" + "github.com/google/syzkaller/pkg/html" "golang.org/x/net/context" "google.golang.org/appengine/datastore" "google.golang.org/appengine/log" @@ -570,7 +571,7 @@ func createUIBug(c context.Context, bug *Bug, state *ReportingState, managers [] default: status = fmt.Sprintf("unknown (%v)", bug.Status) } - status = fmt.Sprintf("%v on %v", status, formatTime(bug.Closed)) + status = fmt.Sprintf("%v on %v", status, html.FormatTime(bug.Closed)) break } } diff --git a/dashboard/app/reporting.go b/dashboard/app/reporting.go index 0fd2d7aa3..4982c8ade 100644 --- a/dashboard/app/reporting.go +++ b/dashboard/app/reporting.go @@ -14,6 +14,7 @@ import ( "github.com/google/syzkaller/dashboard/dashapi" "github.com/google/syzkaller/pkg/email" + "github.com/google/syzkaller/pkg/html" "golang.org/x/net/context" "google.golang.org/appengine/datastore" "google.golang.org/appengine/log" @@ -97,7 +98,7 @@ func needReport(c context.Context, typ string, state *ReportingState, bug *Bug) if !bugReporting.Reported.IsZero() && bugReporting.ReproLevel >= bug.ReproLevel { status = fmt.Sprintf("%v: reported%v on %v", reporting.DisplayTitle, reproStr(bugReporting.ReproLevel), - formatTime(bugReporting.Reported)) + html.FormatTime(bugReporting.Reported)) reporting, bugReporting = nil, nil return } @@ -149,7 +150,7 @@ func needReport(c context.Context, typ string, state *ReportingState, bug *Bug) status = fmt.Sprintf("%v: ready to report", reporting.DisplayTitle) if !bugReporting.Reported.IsZero() { status += fmt.Sprintf(" (reported%v on %v)", - reproStr(bugReporting.ReproLevel), formatTime(bugReporting.Reported)) + reproStr(bugReporting.ReproLevel), html.FormatTime(bugReporting.Reported)) } return } diff --git a/dashboard/app/static/common.js b/dashboard/app/static/common.js index 5a146f3bd..5c20f7df9 100644 --- a/dashboard/app/static/common.js +++ b/dashboard/app/static/common.js @@ -3,28 +3,22 @@ function sortTable(item, colName, conv, desc = false) { table = item.parentNode.parentNode.parentNode; - rows = table.getElementsByTagName("tr"); + rows = table.rows; col = findColumnByName(rows[0].getElementsByTagName("th"), colName); - values = new Array; + values = []; for (i = 1; i < rows.length; i++) - values[i] = conv(rows[i].getElementsByTagName("td")[col].textContent); + values.push([conv(rows[i].getElementsByTagName("td")[col].textContent), rows[i]]); if (desc) desc = !isSorted(values.slice().reverse()) else desc = isSorted(values); - do { - changed = false; - for (i = 1; i < values.length - 1; i++) { - v0 = values[i]; - v1 = values[i + 1]; - if (desc && v0 >= v1 || !desc && v0 <= v1) - continue; - changed = true; - values[i] = v1; - values[i + 1] = v0; - rows[i].parentNode.insertBefore(rows[i + 1], rows[i]); - } - } while (changed); + values.sort(function(a, b) { + if (a[0] == b[0]) return 0; + if (desc && a[0] > b[0] || !desc && a[0] < b[0]) return -1; + return 1; + }); + for (i = 0; i < values.length; i++) + table.appendChild(values[i][1]); return false; } @@ -37,8 +31,8 @@ function findColumnByName(headers, colName) { } function isSorted(values) { - for (i = 1; i < rows.length - 1; i++) { - if (values[i] > values[i + 1]) + for (i = 0; i < values.length - 1; i++) { + if (values[i][0] > values[i + 1][0]) return false; } return true; @@ -46,6 +40,7 @@ function isSorted(values) { function textSort(v) { return v.toLowerCase(); } function numSort(v) { return -parseInt(v); } +function floatSort(v) { return -parseFloat(v); } function reproSort(v) { return v == "C" ? 0 : v == "syz" ? 1 : 2; } function patchedSort(v) { return v == "" ? -1 : parseInt(v); } diff --git a/dashboard/app/static/style.css b/dashboard/app/static/style.css index cb9e6e378..536cd82ab 100644 --- a/dashboard/app/static/style.css +++ b/dashboard/app/static/style.css @@ -122,11 +122,27 @@ table td, table th { text-align: right; } +.list_table .stat_name { + width: 150pt; + max-width: 150pt; + font-family: monospace; +} + +.list_table .stat_value { + width: 100pt; + max-width: 100pt; + font-family: monospace; +} + .bad { color: #f00; font-weight: bold; } +.inactive { + color: #888; +} + .plain { text-decoration: none; } |
