From db3a7cdda936fe5ebadb3ff7792c6acf8f468367 Mon Sep 17 00:00:00 2001
From: Gibheer <gibheer+git@zero-knowledge.org>
Date: Thu, 3 Jan 2019 13:44:21 +0100
Subject: monfront - add some cleanup and search

Monfront now has a basic search functionality for nodes. It also got
some nicer design to make it more useable.
---
 cmd/monfront/main.go | 80 +++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 67 insertions(+), 13 deletions(-)

(limited to 'cmd/monfront')

diff --git a/cmd/monfront/main.go b/cmd/monfront/main.go
index 10dd803..989759a 100644
--- a/cmd/monfront/main.go
+++ b/cmd/monfront/main.go
@@ -89,12 +89,11 @@ func main() {
 	Tmpl = tmpl
 
 	http.HandleFunc("/", showChecks)
+	http.HandleFunc("/check", showCheck)
 	http.HandleFunc("/checks", showChecks)
-	http.HandleFunc("/hosts", showHosts)
 	http.HandleFunc("/groups", showGroups)
 	http.HandleFunc("/action", checkAction)
 	http.HandleFunc("/unhandled/checks", showChecks)
-	http.HandleFunc("/unhandled/hosts", showHosts)
 	http.HandleFunc("/unhandled/groups", showGroups)
 	http.ListenAndServe(config.Listen, nil)
 }
@@ -196,6 +195,17 @@ func showChecks(w http.ResponseWriter, r *http.Request) {
 	}
 	idx := 0
 	params := []interface{}{}
+	if search, found := r.URL.Query()["search"]; found {
+		idx += 1
+		// Add the search for nodes. As hostnames or FQDNs are really weird, the
+		// string needs to be split up by some characters. The input string needs
+		// to be split up too, so all is done here.
+		// TODO move this into a proper index and add more to search.
+		where = append(where, fmt.Sprintf(
+			`to_tsvector('english', regexp_replace(n.name, '[.-/]', ' ', 'g')) @@
+			to_tsquery('english', regexp_replace($%d, '[.-/]', ' & ', 'g'))`, idx))
+		params = append(params, search[0])
+	}
 	if id, found := r.URL.Query()["node_id"]; found {
 		idx += 1
 		where = append(where, fmt.Sprintf("n.id = $%d::int", idx))
@@ -254,7 +264,8 @@ func showChecks(w http.ResponseWriter, r *http.Request) {
 	return
 }
 
-func showHosts(w http.ResponseWriter, r *http.Request) {
+// showCheck loads shows the notifications for a specific check.
+func showCheck(w http.ResponseWriter, r *http.Request) {
 }
 
 func showGroups(w http.ResponseWriter, r *http.Request) {
@@ -349,12 +360,37 @@ var (
 
 var (
 	Templates = map[string]string{
-		"header": `<doctype html>
+		"header": `<!doctype html>
 <html>
 	<head>
 		<title>{{ .Title }}</title>
 		<style type="text/css">
 			* { font-size: 100%; }
+			body { display: flex; flex-direction: column; padding: 0; margin: 0; }
+			#mainmenu { background: #3a5f78; }
+			#mainmenu ul {
+				padding: 0;
+				display: flex;
+				flex-direction: row;
+				align-items: stretch;
+				align-content: center; }
+			#mainmenu .submenu { border-left: 0.1em solid black; }
+			#mainmenu li { list-style-type: none; }
+			.submenu .header {
+				text-align: center;
+				font-weight: bold;
+				color: #ff9000;
+				padding: 0.5em 0.5em;
+				display: block; }
+			#mainmenu a, #mainmenu a:visited, #mainmenu a:active, #mainmenu a:hover {
+				color: #ff9000;
+				padding: 0.25em 0.5em;
+				display: block; }
+			#mainmenu a:hover, #mainmenu a:active { color: #eeeeee; }
+			#mainmenu ul ul a { margin-left: 0.5em; }
+			#mainmenu form * { display: block; margin: 0.25em 0.5em; }
+			#mainmenu form input { }
+			#mainmenu form button { }
 			form section {
 				display: flex;
 				flex-direction: row;
@@ -362,19 +398,20 @@ var (
 				align-items: flex-start;
 			}
 			form nav { order: 1; }
-			form content { order: 2; flex-grow: 1; }
+			form content { order: 2; flex-grow: 1; border-left: 0.15em solid #dddddd; }
 			form nav { display: flex; flex-direction: column; }
 			form nav > * { margin: 0.5em; }
-			table td, table th { padding: 0.5em; }
+			table { width: 100%; }
+			table tr:nth-child(odd) { background: #eeeeee; }
+			table tr:hover { background: #dfdfdf; }
+			table th { background: #cccccc; color: #3a5f78; }
+			table td, table th { text-align: center; }
+			table pre { font-size: 75%; }
 			{{ range $mapId, $mapping := .Mappings }}
 			{{ range $target, $val := $mapping }}
 			td.state-{{ $mapId }}-{{ $target }} { background: {{ $val.Color }}; }
 			{{ end }}
 			{{ end }}
-		 /* td.state-0 { background: green; }
-		  td.state-1 { background: orange; }
-		  td.state-2 { background: red; }
-		  td.state-99 { background: gray; } */
 		</style>
 		<script>
 			setTimeout(function() { location.reload(true) }, 30000)
@@ -384,9 +421,26 @@ var (
 		<nav id="mainmenu">
 			<ul>
 				<li><a href="/">home</a></li>
-				<li><a href="/unhandled/checks">unhandled checks</a></li>
-				<li><a href="/unhandled/hosts">unhandled hosts</a></li>
-				<li><a href="/unhandled/groups">unhandled groups</a></li>
+				<li class="submenu">
+					<span class="header">all</span>
+					<ul>
+						<li><a href="/checks">checks</a></li>
+						<li><a href="/groups">groups</a></li>
+					</ul>
+				</li>
+				<li class="submenu">
+					<span class="header">unhandled</span>
+					<ul>
+						<li><a href="/unhandled/checks">checks</a></li>
+						<li><a href="/unhandled/groups">groups</a></li>
+					</ul>
+				</li>
+				<li class="submenu">
+					<form action="/checks" method="get">
+						<input name="search" placeholder="search" />
+						<button type="submit">search</button>
+					</form>
+				</li>
 			</ul>
 		</nav>`,
 		"footer": `</body></html>`,
-- 
cgit v1.2.3-70-g09d2