Make web ui prettier

pull/12/head
Philipp Heckel 2021-11-04 22:32:17 -04:00
parent 644ffa1420
commit c9124cb5eb
5 changed files with 81 additions and 23 deletions

View File

@ -21,7 +21,7 @@ const (
var (
defaultGlobalTopicLimit = 5000
defaultVisitorRequestLimit = rate.Every(10 * time.Second)
defaultVisitorRequestLimitBurst = 50
defaultVisitorRequestLimitBurst = 60
defaultVisitorSubscriptionLimit = 30
)

View File

@ -65,25 +65,25 @@
</p>
<div id="subscribeBox">
<h3>Subscribe in this Web UI</h3>
<p id="error"></p>
<p>
Subscribe to topics here and receive messages as <b>desktop notification</b>. Topics are not password-protected,
so choose a name that's not easy to guess. Once subscribed, you can publish messages via PUT/POST.
</p>
<form id="subscribeForm">
<h3>Subscribe via web</h3>
<p id="error"></p>
<p>
Messages published to topics subscribed here will show up as <b>desktop notification</b>.
Topics are not password-protected, so choose a name that's not easy to guess. Once subscribed, you can
publish messages via PUT/POST.
</p>
<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}" />
<button id="subscribeButton">Subscribe</button>
</p>
<p id="topicsHeader"><b>Subscribed topics:</b></p>
<ul id="topicsList"></ul>
</form>
<p id="topicsHeader"><b>Subscribed topics:</b></p>
<ul id="topicsList"></ul>
<audio id="notifySound" src="static/sound/mixkit-message-pop-alert-2354.mp3"></audio>
</div>
<h3>Subscribe via phone</h3>
<h3>Subscribe via Android App</h3>
<p>
You can use the <a href="https://play.google.com/store/apps/details?id=io.heckel.ntfy">Ntfy Android App</a>
to receive notifications directly on your phone. Just like the server, this app is also <a href="https://github.com/binwiederhier/ntfy-android">open source</a>.
@ -190,7 +190,6 @@
is the Firebase Cloud Messaging (FCM) service, which is required to provide instant Android notifications (see
FAQ for details).
</p>
<p>
The web server does not log or otherwise store request paths, remote IP addresses or even topics or messages,
aside from a short on-disk cache (up to a day) to support service restarts.

View File

@ -58,9 +58,9 @@ code {
border-radius: 3px;
margin-top: 10px;
margin-bottom: 20px;
overflow-x: scroll;
}
/* Lato font (OFL), https://fonts.google.com/specimen/Lato#about,
embedded with the help of https://google-webfonts-helper.herokuapp.com/fonts/lato?subsets=latin */
@ -118,6 +118,69 @@ li {
font-size: 0.9em;
}
/* Subscribe box SMALL SCREEN */
@media only screen and (max-width: 1599px) {
#subscribeBox #subscribeForm {
border-left: 4px solid #3a9784;
padding: 10px;
}
#subscribeBox h3 {
margin-top: 0;
margin-bottom: 0;
font-size: 1.1em;
}
#subscribeBox #topicsHeader {
margin-bottom: 0;
}
#subscribeBox input {
height: 24px;
min-width: 200px;
max-width: 300px;
border-radius: 3px;
border: none;
border-bottom: 1px solid #aaa;
font-size: 0.8em;
}
#subscribeBox input:focus {
border-bottom: 2px solid #3a9784;
outline: none;
}
#subscribeBox ul {
margin: 0;
padding: 0;
}
#subscribeBox li {
margin: 3px 0;
padding: 0;
}
#subscribeBox li img {
width: 15px;
height: 15px;
vertical-align: bottom;
}
#subscribeBox button {
font-size: 0.8em;
background: #3a9784;
border-radius: 3px;
padding: 5px;
color: white;
cursor: pointer;
}
#subscribeBox button:hover {
background: #317f6f;
}
}
/* Subscribe box BIG SCREEN */
@media only screen and (min-width: 1600px) {
#subscribeBox {
position: fixed;
@ -175,11 +238,9 @@ li {
font-size: 0.7em;
background: #3a9784;
border-radius: 3px;
padding: 3px 5px;
padding: 5px;
color: white;
cursor: pointer;
border-top: solid transparent 2px;
border-bottom: solid transparent 2px;
}
#subscribeBox button:hover {

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#FFFFFF"><path d="M0 0h24v24H0z" fill="none"/><path d="M6 19c0 1.1.9 2 2 2h8c1.1 0 2-.9 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z"/></svg>

Before

Width:  |  Height:  |  Size: 235 B

View File

@ -16,7 +16,6 @@ const topicsList = document.getElementById("topicsList");
const topicField = document.getElementById("topicField");
const notifySound = document.getElementById("notifySound");
const subscribeButton = document.getElementById("subscribeButton");
const subscribeForm = document.getElementById("subscribeForm");
const errorField = document.getElementById("error");
const subscribe = (topic) => {
@ -40,7 +39,7 @@ const subscribeInternal = (topic, delaySec) => {
if (!topicEntry) {
topicEntry = document.createElement('li');
topicEntry.id = `topic-${topic}`;
topicEntry.innerHTML = `${topic} <button onclick="test('${topic}')"> <img src="static/img/send_black_24dp.svg"> Test</button> <button onclick="unsubscribe('${topic}')"> <img src="static/img/clear_black_24dp.svg"> Unsubscribe</button>`;
topicEntry.innerHTML = `${topic} <button onclick="test('${topic}'); return false;"> <img src="static/img/send_black_24dp.svg"> Test</button> <button onclick="unsubscribe('${topic}'); return false;"> <img src="static/img/clear_black_24dp.svg"> Unsubscribe</button>`;
topicsList.appendChild(topicEntry);
}
topicsHeader.style.display = '';
@ -48,13 +47,13 @@ const subscribeInternal = (topic, delaySec) => {
// Open event source
let eventSource = new EventSource(`${topic}/sse`);
eventSource.onopen = () => {
topicEntry.innerHTML = `${topic} <button onclick="test('${topic}')"> <img src="static/img/send_black_24dp.svg"> Test</button> <button onclick="unsubscribe('${topic}')"> <img src="static/img/clear_black_24dp.svg"> Unsubscribe</button>`;
topicEntry.innerHTML = `${topic} <button onclick="test('${topic}'); return false;"> <img src="static/img/send_black_24dp.svg"> Test</button> <button onclick="unsubscribe('${topic}'); return false;"> <img src="static/img/clear_black_24dp.svg"> Unsubscribe</button>`;
delaySec = 0; // Reset on successful connection
};
eventSource.onerror = (e) => {
topicEntry.innerHTML = `${topic} <i>(Reconnecting)</i> <button disabled="disabled">Test</button> <button onclick="unsubscribe('${topic}'); return false;">Unsubscribe</button>`;
eventSource.close();
const newDelaySec = (delaySec + 5 <= 15) ? delaySec + 5 : 15;
topicEntry.innerHTML = `${topic} <i>(Reconnecting in ${newDelaySec}s ...)</i> <button disabled="disabled">Test</button> <button onclick="unsubscribe('${topic}')">Unsubscribe</button>`;
eventSource.close()
subscribeInternal(topic, newDelaySec);
};
eventSource.onmessage = (e) => {
@ -83,7 +82,7 @@ const unsubscribe = (topic) => {
const test = (topic) => {
fetch(`/${topic}`, {
method: 'PUT',
body: `This is a test notification sent from the Ntfy Web UI. It was sent at ${new Date().toString()}.`
body: `This is a test notification sent by the ntfy.sh Web UI at ${new Date().toString()}.`
})
};