aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Hanley <felix@userspace.com.au>2020-03-31 04:53:01 +0000
committerFelix Hanley <felix@userspace.com.au>2020-03-31 04:53:01 +0000
commit7a5dc7b8b58d869fe7f0fb57c1c7b8462afb4e81 (patch)
tree07d015f4791acd91cb876828a72bbd186d431c4d
parent74b027ce3b2c66ced134ca364cfbc249f02373ff (diff)
downloadsws-7a5dc7b8b58d869fe7f0fb57c1c7b8462afb4e81.tar.gz
sws-7a5dc7b8b58d869fe7f0fb57c1c7b8462afb4e81.tar.bz2
Filter updates and styling
-rw-r--r--.gitignore1
-rw-r--r--charts.go2
-rw-r--r--cmd/server/routes.go47
-rw-r--r--sass/main.scss39
-rw-r--r--tmpl/filter.tmpl153
-rw-r--r--tmpl/hitView.tmpl10
-rw-r--r--tmpl/layout.tmpl2
-rw-r--r--tmpl/navbar.tmpl2
-rw-r--r--tmpl/site.tmpl25
-rw-r--r--tmpl/sites.tmpl25
10 files changed, 183 insertions, 123 deletions
diff --git a/.gitignore b/.gitignore
index 10e3d7e..0c40485 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,4 +7,5 @@ counter/sws.min.js
cmd/server/migrations.go
cmd/server/counter.go
cmd/server/templates.go
+static/default.css
*.db
diff --git a/charts.go b/charts.go
index fe90bb1..c02bbd2 100644
--- a/charts.go
+++ b/charts.go
@@ -95,7 +95,7 @@ func SparklineSVG(w io.Writer, data *HitSet, d time.Duration) error {
hits.XValues, hits.YValues = xVals, yVals
graph := gochart.Chart{
- Width: 300,
+ Width: 600,
Height: 50,
Series: []gochart.Series{hits},
// Background: gochart.Style{
diff --git a/cmd/server/routes.go b/cmd/server/routes.go
index ae018b6..cd89739 100644
--- a/cmd/server/routes.go
+++ b/cmd/server/routes.go
@@ -87,27 +87,6 @@ func createRouter(db sws.Store, mmdbPath string) (chi.Router, error) {
r.Post(loginURL, handleLogin(db, rndr))
- // Static files
- r.Get("/*", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- p := strings.TrimPrefix(r.URL.Path, "/")
- debug("loading", p)
- if b, err := loadTemplate(p); err == nil {
- name := filepath.Base(p)
- etag := fmt.Sprintf(`"%x"`, sha1.Sum(b))
-
- if match := r.Header.Get("If-None-Match"); match != "" {
- if strings.Contains(match, etag) {
- w.WriteHeader(http.StatusNotModified)
- return
- }
- }
-
- w.Header().Set("Etag", etag)
- w.Header().Set("Cache-Control", "no-cache")
- http.ServeContent(w, r, name, time.Now(), bytes.NewReader(b))
- }
- }))
-
// Authed routes
r.Group(func(r chi.Router) {
// Ensure we have a user in context
@@ -155,6 +134,32 @@ func createRouter(db sws.Store, mmdbPath string) (chi.Router, error) {
})
})
})
+
+ // Static files
+ r.Get("/*", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
+ p := strings.TrimPrefix(r.URL.Path, "/")
+ debug("loading static", p)
+ b, err := loadTemplate(p)
+ if err == nil {
+ name := filepath.Base(p)
+ etag := fmt.Sprintf(`"%x"`, sha1.Sum(b))
+
+ if match := r.Header.Get("If-None-Match"); match != "" {
+ if strings.Contains(match, etag) {
+ w.WriteHeader(http.StatusNotModified)
+ return
+ }
+ }
+
+ w.Header().Set("Etag", etag)
+ w.Header().Set("Cache-Control", "no-cache")
+ http.ServeContent(w, r, name, time.Now(), bytes.NewReader(b))
+ }
+ debug("no template found, trying files")
+ fs := http.FileServer(http.Dir("public"))
+ fs.ServeHTTP(w, r)
+ //log("file not found:", p, err)
+ }))
})
r.NotFound(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
diff --git a/sass/main.scss b/sass/main.scss
index 78f3064..bbcf415 100644
--- a/sass/main.scss
+++ b/sass/main.scss
@@ -22,31 +22,54 @@ $card-header-shadow: 0;
@import "../node_modules/bulma/sass/components/menu";
@import "../node_modules/bulma/sass/components/card";
+$gutter: 1rem;
+$header-height: 3.25rem;
+
.navbar {
position: fixed;
width: 100%;
}
.page {
display: flex;
- flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
- margin-left: 24px;
- margin-right: 24px;
+ margin-left: $gutter;
+ margin-right: $gutter;
}
-.header {
- width: 100%;
+.page--sites {
+ flex-direction: column;
}
-.level {
+.page--site {
+ flex-direction: row;
+ padding-top: $navbar-height + $header-height + $gutter;
+}
+.header--site {
+ display: flex;
+ position: fixed;
+ top: $header-height;
+ left: $gutter;
+ right: $gutter;
+ z-index: 100;
+ background-color: white;
+ padding: .5em;
+}
+.header__title {
+ flex: 1;
+}
+.filter {
+ flex: 1;
+}
+.site__summary {
width: 100%;
}
.card {
- // background-color: #fff;
border: 1px solid #e6e9ed;
- flex: 1 1 400px;
margin: .5em;
padding: .5em;
}
+.card--narrow {
+ flex: 1 1 400px;
+}
.card--wide {
flex: 1 1 100%;
}
diff --git a/tmpl/filter.tmpl b/tmpl/filter.tmpl
index ce9ff95..e039281 100644
--- a/tmpl/filter.tmpl
+++ b/tmpl/filter.tmpl
@@ -1,73 +1,96 @@
{{ define "filter" }}
- <div class="timerange">
- <!--
- <form>
- <input type="date" name="bdate" value="{{ .Begin|dateRFC }}" />
- <input type="time" name="btime" value="{{ .Begin|timeRFC }}" />
- <input type="date" name="edate" value="{{ .End|dateRFC }}" />
- <input type="time" name="etime" value="{{ .End|timeRFC }}" />
- <select name="timezone">
- <option value="-39600">-1100</option>
- <option value="-36000">-1000</option>
- <option value="-32400">-0900</option>
- <option value="-28800">-0800</option>
- <option value="-25200">-0700</option>
- <option value="-21600">-0600</option>
- <option value="-18000">-0500</option>
- <option value="-14400">-0400</option>
- <option value="-10800">-0300</option>
- <option value="-7200">-0200</option>
- <option value="-3600">-0100</option>
- <option value="0">UTC</option>
- <option value="3600">+0100</option>
- <option value="7200">+0200</option>
- <option value="10800">+0300</option>
- <option value="14400">+0400</option>
- <option value="18000">+0500</option>
- <option value="21600">+0600</option>
- <option value="25200">+0700</option>
- <option value="28800">+0800</option>
- <option value="32400">+0900</option>
- <option value="36000">+1000</option>
- <option value="39600">+1100</option>
- </select>
- </form>
- -->
- <a href="?{{ datetimeRelative "-24h" | .QuerySetEncode "begin" }}">last day</a>
- <a href="?{{ datetimeRelative "-168h" | .QuerySetEncode "begin" }}">last 7 days</a>
- <a href="?{{ datetimeRelative "-720h" | .QuerySetEncode "begin" }}">last 30 days</a>
- <a href="?{{ .QuerySetEncode "bots" "0" }}">without bots</a>
- <a href="?{{ .QuerySetEncode "bots" "1" }}">only bots</a>
- </div>
- <div class="field is-grouped is-grouped-multiline">
- <div class="control">
- {{ if .QuerySetContains "bots" }}
- {{ $bots := .Query.Get "bots" }}
- {{ if eq $bots "0" }}
- <div class="tags has-addons">
- <a class="tag is-link">No bots</a>
- <a class="tag is-delete" href="?{{ .QuerySetEncode "bots" "" }}"></a>
- </div>
- {{ end }}
- {{ if eq $bots "1" }}
- <div class="tags has-addons">
- <a class="tag is-link">Only bots</a>
+ <div class="filter tags field is-grouped">
+ <span>Filters:</span>
+ {{ if .QuerySetContains "bots" }}
+ {{ $bots := .Query.Get "bots" }}
+ {{ if eq $bots "0" }}
+ <div class="control">
+ <span class="tags has-addons">
+ <a class="tag is-danger" href="?{{ .QuerySetEncode "bots" "" }}">no bots</a>
<a class="tag is-delete" href="?{{ .QuerySetEncode "bots" "" }}"></a>
- </div>
- {{ end }}
- {{ end }}
- {{ if .QuerySetContains "country" }}
- <div class="tags has-addons">
- <a class="tag is-link">Country {{ .Query.Get "country" }}</a>
- <a class="tag is-delete" href="?{{ .QuerySetEncode "country" "" }}"></a>
+ </span>
</div>
{{ end }}
- {{ if .QuerySetContains "begin" }}
- <div class="tags has-addons">
- <a class="tag is-link">Time filter</a>
- <a class="tag is-delete" href="?{{ .QuerySetEncode "begin" "" }}"></a>
+ {{ if eq $bots "1" }}
+ <div class="control">
+ <span class="tags has-addons">
+ <a class="tag is-danger" href="?{{ .QuerySetEncode "bots" "" }}">only bots</a>
+ <a class="tag is-delete" href="?{{ .QuerySetEncode "bots" "" }}"></a>
+ </span>
</div>
{{ end }}
- </div>
+ {{ else }}
+ <div class="control">
+ <span class="tags has-addons">
+ <a class="tag is-info" href="?{{ .QuerySetEncode "bots" "0" }}">bots</a>
+ <a class="tag is-light" href="?{{ .QuerySetEncode "bots" "0" }}">without</a>
+ </span>
+ </div>
+ <div class="control">
+ <span class="tags has-addons">
+ <a class="tag is-info" href="?{{ .QuerySetEncode "bots" "1" }}">bots</a>
+ <a class="tag is-light" href="?{{ .QuerySetEncode "bots" "1" }}">only</a>
+ </span>
+ </div>
+ {{ end }}
+ {{ if .QuerySetContains "country" }}
+ <div class="control">
+ <span class="tags has-addons">
+ <a class="tag is-danger" href="?{{ .QuerySetEncode "country" "" }}">country {{ .Query.Get "country" }}</a>
+ <a class="tag is-delete" href="?{{ .QuerySetEncode "country" "" }}"></a>
+ </span>
+ </div>
+ {{ end }}
+ {{ if .QuerySetContains "path" }}
+ <div class="control">
+ <span class="tags has-addons">
+ <a class="tag is-danger" href="?{{ .QuerySetEncode "path" "" }}">path</a>
+ <a class="tag is-delete" href="?{{ .QuerySetEncode "path" "" }}"></a>
+ </span>
+ </div>
+ {{ end }}
+ {{ if .QuerySetContains "browser" }}
+ <div class="control">
+ <span class="tags has-addons">
+ <a class="tag is-danger" href="?{{ .QuerySetEncode "browser" "" }}">browser</a>
+ <a class="tag is-delete" href="?{{ .QuerySetEncode "browser" "" }}"></a>
+ </span>
+ </div>
+ {{ end }}
+ {{ if .QuerySetContains "referrer" }}
+ <div class="control">
+ <span class="tags has-addons">
+ <a class="tag is-danger" href="?{{ .QuerySetEncode "referrer" "" }}">referrer</a>
+ <a class="tag is-delete" href="?{{ .QuerySetEncode "referrer" "" }}"></a>
+ </span>
+ </div>
+ {{ end }}
+ {{ if .QuerySetContains "begin" }}
+ <div class="control">
+ <span class="tags has-addons">
+ <a class="tag is-danger" href="?{{ .QuerySetEncode "begin" "" }}">time</a>
+ <a class="tag is-delete" href="?{{ .QuerySetEncode "begin" "" }}"></a>
+ </span>
+ </div>
+ {{ else }}
+ <div class="control">
+ <span class="tags has-addons">
+ <a class="tag is-info" href="?{{ datetimeRelative "-24h" | .QuerySetEncode "begin" }}">days</a>
+ <a class="tag is-light" href="?{{ datetimeRelative "-24h" | .QuerySetEncode "begin" }}">1</a>
+ </span>
+ </div>
+ <div class="control">
+ <span class="tags has-addons">
+ <a class="tag is-info" href="?{{ datetimeRelative "-168h" | .QuerySetEncode "begin" }}">days</a>
+ <a class="tag is-light" href="?{{ datetimeRelative "-168h" | .QuerySetEncode "begin" }}">7</a>
+ </span>
+ </div>
+ <div class="control">
+ <span class="tags has-addons">
+ <a class="tag is-info" href="?{{ datetimeRelative "-720h" | .QuerySetEncode "begin" }}">days</a>
+ <a class="tag is-light" href="?{{ datetimeRelative "-720h" | .QuerySetEncode "begin" }}">30</a>
+ </span>
+ </div>
+ {{ end }}
</div>
{{ end }}
diff --git a/tmpl/hitView.tmpl b/tmpl/hitView.tmpl
index 3deb96b..f7d4dcb 100644
--- a/tmpl/hitView.tmpl
+++ b/tmpl/hitView.tmpl
@@ -17,7 +17,7 @@
</section>
{{ if .PageSet }}
- <section id="pages" class="card">
+ <section id="pages" class="card card--narrow">
<header class="card-header">
<h3 class="card-header-title">Top 10 pages</h3>
</header>
@@ -47,7 +47,7 @@
</section>
{{ end }}
- <section id="countries" class="card">
+ <section id="countries" class="card card--narrow">
<header class="card-header">
<h3 class="card-header-title">Countries</h3>
</header>
@@ -73,7 +73,7 @@
</div>
</section>
- <section id="referrers" class="card">
+ <section id="referrers" class="card card--narrow">
<header class="card-header">
<h3 class="card-header-title">Referrers</h3>
</header>
@@ -97,7 +97,7 @@
</div>
</section>
- <section id="useragents" class="card">
+ <section id="useragents" class="card card--narrow">
<header class="card-header">
<h3 class="card-header-title">User agents</h3>
</header>
@@ -125,7 +125,7 @@
{{ end }}
{{ define "siteSummary" }}
- <section class="level">
+ <section class="site__summary level">
{{ with .Hits }}
<div class="level-item has-text-centered">
<div>
diff --git a/tmpl/layout.tmpl b/tmpl/layout.tmpl
index 4ab0db0..056ce60 100644
--- a/tmpl/layout.tmpl
+++ b/tmpl/layout.tmpl
@@ -7,7 +7,7 @@
</head>
<body class="has-navbar-fixed-top">
{{ template "navbar" . }}
- <main class="page">
+ <main class="page{{ if .Sites }} page--sites{{ end }}{{ if .Site }} page--site{{ end }}">
{{ template "flash" . }}
{{ template "content" . }}
</main>
diff --git a/tmpl/navbar.tmpl b/tmpl/navbar.tmpl
index f49ae6f..b7a1cd7 100644
--- a/tmpl/navbar.tmpl
+++ b/tmpl/navbar.tmpl
@@ -2,7 +2,7 @@
<nav class="navbar is-black is-fixed-top" role="navigation" aria-label="main navigation">
<div class="navbar-brand">
<a class="navbar-item" href="//{{ .Domain }}">
- <img src="//{{ .Domain }}/logo.png" width="112" height="28">
+ <img src="//{{ .Domain }}/favicon64.png" height="28">
</a>
<a role="button" class="navbar-burger burger" aria-label="menu" aria-expanded="false" data-target="navbarMain">
diff --git a/tmpl/site.tmpl b/tmpl/site.tmpl
index 4f4ffc3..c44f8f0 100644
--- a/tmpl/site.tmpl
+++ b/tmpl/site.tmpl
@@ -1,20 +1,23 @@
{{ define "content" }}
- <header class="header header--site">
- {{ if .Site.ID }}
- {{ with .Site }}
- <h1 class="title title--site">Hits for {{ .Name }}</h1>
- <span class="subtitle">{{ .Description }}</span>
+ {{ if .Site.ID }}
+ <header class="header header--site">
+ <div class="header__title">
+ {{ with .Site }}
+ <h1 class="title title--site">{{ .Name }}</h1>
+ {{ end }}
+ </div>
+ {{ if .Site.ID }}
+ {{ template "filter" . }}
{{ end }}
- {{ else }}
+ </header>
+ {{ else }}
+ <header class="header header--site">
<h1 class="title--site">New Site</h1>
- {{ end }}
- </header>
+ </header>
+ {{ end }}
{{ template "siteSummary" . }}
- {{ if .Site.ID }}
- {{ template "filter" . }}
- {{ end }}
{{ if .Hits }}
{{ template "hitView" . }}
{{ else }}
diff --git a/tmpl/sites.tmpl b/tmpl/sites.tmpl
index 044e595..9d449f6 100644
--- a/tmpl/sites.tmpl
+++ b/tmpl/sites.tmpl
@@ -2,17 +2,22 @@
<header>
<h1 class="title">Sites</h1>
</header>
- <ul class="sites">
- {{ range .Sites }}
- {{ template "siteForList" . }}
- {{ end }}
- </ul>
+ {{ range .Sites }}
+ {{ template "siteForList" . }}
+ {{ end }}
{{ end }}
{{ define "siteForList" }}
- <li>
- <a href="/sites/{{ .ID }}/">{{ .Name }}</a>
- <span>{{ .Description }}</span>
- <img src="{{ sparkline .ID }}" />
- </li>
+ <a class="site card" href="/sites/{{ .ID }}/">
+ <div class="card-header">
+ <object data="/favicon64.png" type="image/png">
+ <img class="card-header-icon" src="//{{ .Name }}/favicon.ico" alt="{{ .Name }} favicon" />
+ </object>
+ <span class="card-header-title">{{ .Name }}</span>
+ <img src="{{ sparkline .ID }}" />
+ </div>
+ <div class="card-content">
+ {{ .Description }}
+ </div>
+ </a>
{{ end }}