Skip to content

Commit

Permalink
Detail page in web UI
Browse files Browse the repository at this point in the history
  • Loading branch information
Philipp Heckel committed Nov 8, 2021
1 parent c01c94c commit 43c9a92
Show file tree
Hide file tree
Showing 6 changed files with 328 additions and 35 deletions.
38 changes: 34 additions & 4 deletions server/index.html → server/index.gohtml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{{- /*gotype: heckel.io/ntfy/server.indexPage*/ -}}
<!DOCTYPE html>
<html lang="en">
<head>
Expand Down Expand Up @@ -27,12 +28,16 @@
<meta property="og:description" content="ntfy is a simple HTTP-based pub-sub notification service. It allows you to send desktop notifications via scripts from any computer, entirely without signup or cost. Made with ❤ by Philipp C. Heckel, Apache License 2.0, source at https://heckel.io/ntfy." />
<meta property="og:image" content="/static/img/ntfy.png" />
<meta property="og:url" content="https://ntfy.sh" />
{{if .Topic}}
<!-- Never index topic page -->
<meta name="robots" content="noindex, nofollow" />
{{end}}
</head>
<body>
<div id="main">
<h1><img src="static/img/ntfy.png" alt="ntfy"/><br/>ntfy.sh - simple HTTP-based pub-sub</h1>
<div id="main"{{if .Topic}} style="display: none"{{end}}>
<h1><img src="static/img/ntfy.png" alt="ntfy"/><br/>ntfy.sh | simple HTTP-based pub-sub</h1>
<p>
<b>ntfy</b> (pronounce: <i>notify</i>) is a simple HTTP-based <a href="https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern">pub-sub</a> notification service.
<b>Ntfy</b> (pronounce: <i>notify</i>) is a simple HTTP-based <a href="https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern">pub-sub</a> notification service.
It allows you to send notifications <a href="https://play.google.com/store/apps/details?id=io.heckel.ntfy">to your phone</a> or desktop via scripts from any computer,
entirely <b>without signup or cost</b>. It's also <a href="https://github.com/binwiederhier/ntfy">open source</a> if you want to run your own.
</p>
Expand Down Expand Up @@ -79,7 +84,7 @@ <h3>Subscribe in this Web UI</h3>
<form id="subscribeForm">
<p>
<b>Topic:</b><br/>
<input type="text" id="topicField" autocomplete="off" placeholder="Topic name, e.g. phil_alerts" pattern="[-_A-Za-z]{1,64}" />
<input type="text" id="topicField" autocomplete="off" placeholder="Topic name, e.g. phil_alerts" maxlength="64" pattern="[-_A-Za-z0-9]{1,64}" />
<button id="subscribeButton">Subscribe</button>
</p>
<p id="topicsHeader"><b>Subscribed topics:</b></p>
Expand Down Expand Up @@ -209,6 +214,31 @@ <h2>Privacy policy</h2>

<center id="ironicCenterTagDontFreakOut"><i>Made with ❤️ by <a href="https://heckel.io">Philipp C. Heckel</a></i></center>
</div>
<div id="detail"{{if not .Topic}} style="display: none"{{end}}>
<div id="detailMain">
<button id="detailCloseButton"><img src="static/img/close_black_24dp.svg"/></button>
<h1><img src="static/img/ntfy.png" alt="ntfy"/><br/><span id="detailTitle"></span></h1>
<p class="smallMarginBottom">
<b>Ntfy</b> is a simple HTTP-based pub-sub notification service. This is a Ntfy topic.
To send notifications to it, simply PUT or POST to the topic URL. Here's an example using <tt>curl</tt>:
</p>
<code>
curl -d "Backup failed" <span id="detailTopicUrl"></span>
</code>
<p id="detailNotificationsDisallowed">
If you'd like to receive desktop notifications when new messages arrive on this topic, you have
<a href="#" onclick="return requestPermission()">grant the browser permission</a> to show notifications.
Click the link to do so.
</p>
<p class="smallMarginBottom">
<b>Recent notifications</b> (cached for {{.CacheDuration}}):
</p>
<p id="detailNoNotifications">
<i>You haven't received any notifications for this topic yet.</i>
</p>
<div id="detailEventsList"></div>
</div>
</div>
<script src="static/js/app.js"></script>
</body>
</html>
28 changes: 19 additions & 9 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
"fmt"
"google.golang.org/api/option"
"heckel.io/ntfy/config"
"heckel.io/ntfy/util"
"html/template"
"io"
"log"
"net"
Expand Down Expand Up @@ -46,20 +48,26 @@ func (e errHTTP) Error() string {
return fmt.Sprintf("http: %s", e.Status)
}

type indexPage struct {
Topic string
CacheDuration string
}

const (
messageLimit = 512
)

var (
topicRegex = regexp.MustCompile(`^/[^/]+$`)
jsonRegex = regexp.MustCompile(`^/[^/]+/json$`)
sseRegex = regexp.MustCompile(`^/[^/]+/sse$`)
rawRegex = regexp.MustCompile(`^/[^/]+/raw$`)
topicRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}$`) // Regex must match JS & Android app!
jsonRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}/json$`)
sseRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}/sse$`)
rawRegex = regexp.MustCompile(`^/[-_A-Za-z0-9]{1,64}/raw$`)

staticRegex = regexp.MustCompile(`^/static/.+`)

//go:embed "index.html"
indexSource string
//go:embed "index.gohtml"
indexSource string
indexTemplate = template.Must(template.New("index").Parse(indexSource))

//go:embed static
webStaticFs embed.FS
Expand Down Expand Up @@ -159,7 +167,7 @@ func (s *Server) handle(w http.ResponseWriter, r *http.Request) {
}

func (s *Server) handleInternal(w http.ResponseWriter, r *http.Request) error {
if r.Method == http.MethodGet && r.URL.Path == "/" {
if r.Method == http.MethodGet && (r.URL.Path == "/" || topicRegex.MatchString(r.URL.Path)) {
return s.handleHome(w, r)
} else if r.Method == http.MethodHead && r.URL.Path == "/" {
return s.handleEmpty(w, r)
Expand All @@ -180,8 +188,10 @@ func (s *Server) handleInternal(w http.ResponseWriter, r *http.Request) error {
}

func (s *Server) handleHome(w http.ResponseWriter, r *http.Request) error {
_, err := io.WriteString(w, indexSource)
return err
return indexTemplate.Execute(w, &indexPage{
Topic: r.URL.Path[1:],
CacheDuration: util.DurationToHuman(s.config.CacheDuration),
})
}

func (s *Server) handleEmpty(w http.ResponseWriter, r *http.Request) error {
Expand Down
73 changes: 70 additions & 3 deletions server/static/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ html, body {
font-size: 1.1em;
}

html {
/* prevent scrollbar from repositioning website:
* https://www.w3docs.com/snippets/css/how-to-prevent-scrollbar-from-repositioning-web-page.html */
overflow-y: scroll;
}

a, a:visited {
color: #3a9784;
}
Expand Down Expand Up @@ -107,7 +113,7 @@ button:hover {

ul {
padding-left: 1em;
list-style-type: none;
list-style-type: circle;
padding-bottom: 0;
margin: 0;
}
Expand Down Expand Up @@ -146,7 +152,6 @@ li {

#subscribeBox ul {
margin: 0;
padding: 0;
}

#subscribeBox li {
Expand All @@ -160,6 +165,10 @@ li {
vertical-align: bottom;
}

#subscribeBox li a {
padding: 0 5px 0 0;
}

#subscribeBox button {
font-size: 0.8em;
background: #3a9784;
Expand Down Expand Up @@ -202,7 +211,6 @@ li {

#subscribeBox ul {
margin: 0;
padding: 0;
}

#subscribeBox input {
Expand All @@ -228,6 +236,10 @@ li {
vertical-align: bottom;
}

#subscribeBox li a {
padding: 0 5px 0 0;
}

#subscribeBox button {
font-size: 0.7em;
background: #3a9784;
Expand All @@ -240,7 +252,62 @@ li {
#subscribeBox button:hover {
background: #317f6f;
}
}

/** Detail view */
#detail {
display: none;
position: absolute;
z-index: 1;
left: 8px;
right: 8px;
top: 0;
bottom: 0;
background: white;
}

#detail .detailDate {
color: #888;
font-size: 0.9em;
}

#detail .detailMessage {
margin-bottom: 20px;
font-size: 1.1em;
}

#detail #detailMain {
max-width: 900px;
margin: 0 auto 50px auto;
position: relative; /* required for close button's "position: absolute" */
}

#detail #detailCloseButton {
background: #eee;
border-radius: 5px;
border: none;
padding: 5px;
position: absolute;
right: 0;
top: 10px;
display: block;
}

#detail #detailCloseButton:hover {
padding: 5px;
background: #ccc;
}

#detail #detailCloseButton img {
display: block; /* get rid of the weird bottom border */
}

#detail #detailNotificationsDisallowed {
display: none;
color: darkred;
}

#detail #events {
max-width: 900px;
margin: 0 auto 50px auto;
}
1 change: 1 addition & 0 deletions server/static/img/close_black_24dp.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 43c9a92

Please sign in to comment.