WIP: Web UI improvements
This commit is contained in:
parent
5948f39a53
commit
644ffa1420
6 changed files with 129 additions and 22 deletions
|
@ -33,10 +33,9 @@
|
||||||
<h1><img src="static/img/ntfy.png" alt="ntfy"/><br/>ntfy.sh - simple HTTP-based pub-sub</h1>
|
<h1><img src="static/img/ntfy.png" alt="ntfy"/><br/>ntfy.sh - simple HTTP-based pub-sub</h1>
|
||||||
<p>
|
<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 <b>notifications to your phone or desktop via scripts from any computer</b>, entirely <b>without signup or cost</b>.
|
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,
|
||||||
It's also <a href="https://github.com/binwiederhier/ntfy">open source</a> if you want to run your own.
|
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>
|
</p>
|
||||||
<p id="error"></p>
|
|
||||||
|
|
||||||
<h2>Publishing messages</h2>
|
<h2>Publishing messages</h2>
|
||||||
<p>
|
<p>
|
||||||
|
@ -65,21 +64,24 @@
|
||||||
<a href="https://developer.mozilla.org/en-US/docs/Web/API/EventSource">EventSource</a>, a JSON feed, or raw feed.
|
<a href="https://developer.mozilla.org/en-US/docs/Web/API/EventSource">EventSource</a>, a JSON feed, or raw feed.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h3>Subscribe via web</h3>
|
<div id="subscribeBox">
|
||||||
<p>
|
|
||||||
If you subscribe to a topic via this web UI in the field below, messages published to any subscribed topic
|
|
||||||
will show up as <b>desktop notification</b>.
|
|
||||||
</p>
|
|
||||||
<form id="subscribeForm">
|
<form id="subscribeForm">
|
||||||
|
<h3>Subscribe via web</h3>
|
||||||
|
<p id="error"></p>
|
||||||
<p>
|
<p>
|
||||||
<label for="topicField">Subscribe to topic:</label>
|
Messages published to topics subscribed here will show up as <b>desktop notification</b>.
|
||||||
<input type="text" id="topicField" placeholder="Letters, numbers, _ and -" pattern="[-_A-Za-z]{1,64}" />
|
Topics are not password-protected, so choose a name that's not easy to guess. Once subscribed, you can
|
||||||
<input type="submit" id="subscribeButton" value="Subscribe" />
|
publish messages via PUT/POST.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<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>
|
||||||
</form>
|
</form>
|
||||||
<p id="topicsHeader">Topics:</p>
|
<p id="topicsHeader"><b>Subscribed topics:</b></p>
|
||||||
<ul id="topicsList"></ul>
|
<ul id="topicsList"></ul>
|
||||||
<audio id="notifySound" src="static/sound/mixkit-message-pop-alert-2354.mp3"></audio>
|
<audio id="notifySound" src="static/sound/mixkit-message-pop-alert-2354.mp3"></audio>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h3>Subscribe via phone</h3>
|
<h3>Subscribe via phone</h3>
|
||||||
<p>
|
<p>
|
||||||
|
|
|
@ -60,6 +60,7 @@ code {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Lato font (OFL), https://fonts.google.com/specimen/Lato#about,
|
/* 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 */
|
embedded with the help of https://google-webfonts-helper.herokuapp.com/fonts/lato?subsets=latin */
|
||||||
|
|
||||||
|
@ -87,3 +88,104 @@ code {
|
||||||
#ironicCenterTagDontFreakOut {
|
#ironicCenterTagDontFreakOut {
|
||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Subscribe box */
|
||||||
|
|
||||||
|
button {
|
||||||
|
background: #3a9784;
|
||||||
|
border: none;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 3px 5px;
|
||||||
|
color: white;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:hover {
|
||||||
|
background: #317f6f;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
padding-left: 1em;
|
||||||
|
list-style-type: none;
|
||||||
|
padding-bottom: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
li {
|
||||||
|
padding: 4px 0;
|
||||||
|
margin: 4px 0;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (min-width: 1600px) {
|
||||||
|
#subscribeBox {
|
||||||
|
position: fixed;
|
||||||
|
top: 180px;
|
||||||
|
right: 10px;
|
||||||
|
width: 300px;
|
||||||
|
border-left: 4px solid #3a9784;
|
||||||
|
padding: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#subscribeBox h3 {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-size: 1.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#subscribeBox #topicsHeader {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#subscribeBox p {
|
||||||
|
font-size: 0.9em;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#subscribeBox ul {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#subscribeBox input {
|
||||||
|
height: 18px;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: none;
|
||||||
|
border-bottom: 1px solid #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
#subscribeBox input:focus {
|
||||||
|
border-bottom: 2px solid #3a9784;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#subscribeBox li {
|
||||||
|
margin: 3px 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#subscribeBox li img {
|
||||||
|
width: 15px;
|
||||||
|
height: 15px;
|
||||||
|
vertical-align: bottom;
|
||||||
|
}
|
||||||
|
|
||||||
|
#subscribeBox button {
|
||||||
|
font-size: 0.7em;
|
||||||
|
background: #3a9784;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 3px 5px;
|
||||||
|
color: white;
|
||||||
|
cursor: pointer;
|
||||||
|
border-top: solid transparent 2px;
|
||||||
|
border-bottom: solid transparent 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#subscribeBox button:hover {
|
||||||
|
background: #317f6f;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
1
server/static/img/clear_black_24dp.svg
Normal file
1
server/static/img/clear_black_24dp.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#FFFFFF"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41z"/></svg>
|
After Width: | Height: | Size: 269 B |
1
server/static/img/delete_black_24dp.svg
Normal file
1
server/static/img/delete_black_24dp.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<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>
|
After Width: | Height: | Size: 235 B |
1
server/static/img/send_black_24dp.svg
Normal file
1
server/static/img/send_black_24dp.svg
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<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="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/></svg>
|
After Width: | Height: | Size: 195 B |
|
@ -40,7 +40,7 @@ const subscribeInternal = (topic, delaySec) => {
|
||||||
if (!topicEntry) {
|
if (!topicEntry) {
|
||||||
topicEntry = document.createElement('li');
|
topicEntry = document.createElement('li');
|
||||||
topicEntry.id = `topic-${topic}`;
|
topicEntry.id = `topic-${topic}`;
|
||||||
topicEntry.innerHTML = `${topic} <button onclick="test('${topic}')">Test</button> <button onclick="unsubscribe('${topic}')">Unsubscribe</button>`;
|
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>`;
|
||||||
topicsList.appendChild(topicEntry);
|
topicsList.appendChild(topicEntry);
|
||||||
}
|
}
|
||||||
topicsHeader.style.display = '';
|
topicsHeader.style.display = '';
|
||||||
|
@ -48,7 +48,7 @@ const subscribeInternal = (topic, delaySec) => {
|
||||||
// Open event source
|
// Open event source
|
||||||
let eventSource = new EventSource(`${topic}/sse`);
|
let eventSource = new EventSource(`${topic}/sse`);
|
||||||
eventSource.onopen = () => {
|
eventSource.onopen = () => {
|
||||||
topicEntry.innerHTML = `${topic} <button onclick="test('${topic}')">Test</button> <button onclick="unsubscribe('${topic}')">Unsubscribe</button>`;
|
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>`;
|
||||||
delaySec = 0; // Reset on successful connection
|
delaySec = 0; // Reset on successful connection
|
||||||
};
|
};
|
||||||
eventSource.onerror = (e) => {
|
eventSource.onerror = (e) => {
|
||||||
|
@ -83,7 +83,7 @@ const unsubscribe = (topic) => {
|
||||||
const test = (topic) => {
|
const test = (topic) => {
|
||||||
fetch(`/${topic}`, {
|
fetch(`/${topic}`, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
body: `This is a test notification`
|
body: `This is a test notification sent from the Ntfy Web UI. It was sent at ${new Date().toString()}.`
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ const showNotificationDeniedError = () => {
|
||||||
showError("You have blocked desktop notifications for this website. Please unblock them and refresh to use the web-based desktop notifications.");
|
showError("You have blocked desktop notifications for this website. Please unblock them and refresh to use the web-based desktop notifications.");
|
||||||
};
|
};
|
||||||
|
|
||||||
subscribeForm.onsubmit = function () {
|
subscribeButton.onclick = function () {
|
||||||
if (!topicField.value) {
|
if (!topicField.value) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue