mirror of
https://git.pleroma.social/pleroma/relay.git
synced 2024-11-10 02:17:59 +00:00
replace alerts with in-page toast messages
This commit is contained in:
parent
2be96a8ca5
commit
a966f9c1cf
|
@ -13,7 +13,9 @@
|
||||||
%meta(name="viewport" content="width=device-width, initial-scale=1")
|
%meta(name="viewport" content="width=device-width, initial-scale=1")
|
||||||
%link(rel="stylesheet" type="text/css" href="/theme/{{config.theme}}.css" nonce="{{view.request['hash']}}")
|
%link(rel="stylesheet" type="text/css" href="/theme/{{config.theme}}.css" nonce="{{view.request['hash']}}")
|
||||||
%link(rel="stylesheet" type="text/css" href="/static/style.css" nonce="{{view.request['hash']}}")
|
%link(rel="stylesheet" type="text/css" href="/static/style.css" nonce="{{view.request['hash']}}")
|
||||||
|
%link(rel="stylesheet" type="text/css" href="/static/toast.css" nonce="{{view.request['hash']}}")
|
||||||
%script(type="application/javascript" src="/static/menu.js" nonce="{{view.request['hash']}}", defer)
|
%script(type="application/javascript" src="/static/menu.js" nonce="{{view.request['hash']}}", defer)
|
||||||
|
%script(type="application/javascript" src="/static/toast.js" nonce="{{view.request['hash']}}", defer)
|
||||||
%script(type="application/javascript" src="/static/api.js" nonce="{{view.request['hash']}}", defer)
|
%script(type="application/javascript" src="/static/api.js" nonce="{{view.request['hash']}}", defer)
|
||||||
-block head
|
-block head
|
||||||
|
|
||||||
|
@ -37,6 +39,8 @@
|
||||||
-else
|
-else
|
||||||
{{menu_item("Login", "/login")}}
|
{{menu_item("Login", "/login")}}
|
||||||
|
|
||||||
|
%ul#notifications
|
||||||
|
|
||||||
#container
|
#container
|
||||||
#header.section
|
#header.section
|
||||||
%span#menu-open << ⁞
|
%span#menu-open << ⁞
|
||||||
|
|
|
@ -18,7 +18,7 @@ async function handle_config_change(event) {
|
||||||
await request("POST", "v1/config", params);
|
await request("POST", "v1/config", params);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
alert(error);
|
toast(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,8 @@ async function handle_config_change(event) {
|
||||||
document.querySelector("#header .title").innerHTML = params.value;
|
document.querySelector("#header .title").innerHTML = params.value;
|
||||||
document.querySelector("title").innerHTML = params.value;
|
document.querySelector("title").innerHTML = params.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toast("Updated config", "message");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ async function ban() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (values.domain === "") {
|
if (values.domain === "") {
|
||||||
alert("Domain is required");
|
toast("Domain is required");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ async function ban() {
|
||||||
var ban = await request("POST", "v1/domain_ban", values);
|
var ban = await request("POST", "v1/domain_ban", values);
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
alert(err);
|
toast(err);
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,8 +58,6 @@ async function ban() {
|
||||||
remove: `<a href="#" title="Unban domain">✖</a>`
|
remove: `<a href="#" title="Unban domain">✖</a>`
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(row.querySelector(".update-ban"));
|
|
||||||
console.log(row.querySelector(".remove a"));
|
|
||||||
add_row_listeners(row);
|
add_row_listeners(row);
|
||||||
|
|
||||||
elems.domain.value = null;
|
elems.domain.value = null;
|
||||||
|
@ -67,6 +65,7 @@ async function ban() {
|
||||||
elems.note.value = null;
|
elems.note.value = null;
|
||||||
|
|
||||||
document.querySelector("details.section").open = false;
|
document.querySelector("details.section").open = false;
|
||||||
|
toast("Banned domain", "message");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -88,11 +87,12 @@ async function update_ban(domain) {
|
||||||
await request("PATCH", "v1/domain_ban", values)
|
await request("PATCH", "v1/domain_ban", values)
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
alert(error);
|
toast(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
row.querySelector("details").open = false;
|
row.querySelector("details").open = false;
|
||||||
|
toast("Updated baned domain", "message");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -101,11 +101,12 @@ async function unban(domain) {
|
||||||
await request("DELETE", "v1/domain_ban", {"domain": domain});
|
await request("DELETE", "v1/domain_ban", {"domain": domain});
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
alert(error);
|
toast(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById(domain).remove();
|
document.getElementById(domain).remove();
|
||||||
|
toast("Unbanned domain", "message");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ async function add_instance() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (values.actor === "") {
|
if (values.actor === "") {
|
||||||
alert("Actor is required");
|
toast("Actor is required");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ async function add_instance() {
|
||||||
var instance = await request("POST", "v1/instance", values);
|
var instance = await request("POST", "v1/instance", values);
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
alert(err);
|
toast(err);
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,6 +62,7 @@ async function add_instance() {
|
||||||
elems.software.value = null;
|
elems.software.value = null;
|
||||||
|
|
||||||
document.querySelector("details.section").open = false;
|
document.querySelector("details.section").open = false;
|
||||||
|
toast("Added instance", "message");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -70,7 +71,7 @@ async function del_instance(domain) {
|
||||||
await request("DELETE", "v1/instance", {"domain": domain});
|
await request("DELETE", "v1/instance", {"domain": domain});
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
alert(error);
|
toast(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +89,7 @@ async function req_response(domain, accept) {
|
||||||
await request("POST", "v1/request", params);
|
await request("POST", "v1/request", params);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
alert(error);
|
toast(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,6 +116,8 @@ async function req_response(domain, accept) {
|
||||||
add_instance_listeners(row);
|
add_instance_listeners(row);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
toast("Removed instance", "message");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ async function ban() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (values.name === "") {
|
if (values.name === "") {
|
||||||
alert("Domain is required");
|
toast("Domain is required");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ async function ban() {
|
||||||
var ban = await request("POST", "v1/software_ban", values);
|
var ban = await request("POST", "v1/software_ban", values);
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
alert(err);
|
toast(err);
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,6 +64,7 @@ async function ban() {
|
||||||
elems.note.value = null;
|
elems.note.value = null;
|
||||||
|
|
||||||
document.querySelector("details.section").open = false;
|
document.querySelector("details.section").open = false;
|
||||||
|
toast("Banned software", "message");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -85,11 +86,12 @@ async function update_ban(name) {
|
||||||
await request("PATCH", "v1/software_ban", values)
|
await request("PATCH", "v1/software_ban", values)
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
alert(error);
|
toast(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
row.querySelector("details").open = false;
|
row.querySelector("details").open = false;
|
||||||
|
toast("Updated software ban", "message");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -98,11 +100,12 @@ async function unban(name) {
|
||||||
await request("DELETE", "v1/software_ban", {"name": name});
|
await request("DELETE", "v1/software_ban", {"name": name});
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
alert(error);
|
toast(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById(name).remove();
|
document.getElementById(name).remove();
|
||||||
|
toast("Unbanned software", "message");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
68
relay/frontend/static/toast.css
Normal file
68
relay/frontend/static/toast.css
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
#notifications {
|
||||||
|
position: fixed;
|
||||||
|
top: 40px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
#notifications li {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
list-style: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
padding: 5px;;
|
||||||
|
margin-bottom: var(--spacing);
|
||||||
|
animation: show_toast 0.3s ease forwards;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto max-content;
|
||||||
|
grid-gap: 5px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#notifications a {
|
||||||
|
font-size: 1.5em;
|
||||||
|
line-height: 1em;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#notifications li.hide {
|
||||||
|
animation: hide_toast 0.3s ease forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@keyframes show_toast {
|
||||||
|
0% {
|
||||||
|
transform: translateX(100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
40% {
|
||||||
|
transform: translateX(-5%);
|
||||||
|
}
|
||||||
|
|
||||||
|
80% {
|
||||||
|
transform: translateX(0%);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: translateX(-10px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@keyframes hide_toast {
|
||||||
|
0% {
|
||||||
|
transform: translateX(-10px);
|
||||||
|
}
|
||||||
|
|
||||||
|
40% {
|
||||||
|
transform: translateX(0%);
|
||||||
|
}
|
||||||
|
|
||||||
|
80% {
|
||||||
|
transform: translateX(-5%);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: translateX(calc(100% + 20px));
|
||||||
|
}
|
||||||
|
}
|
26
relay/frontend/static/toast.js
Normal file
26
relay/frontend/static/toast.js
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
const notifications = document.querySelector("#notifications")
|
||||||
|
|
||||||
|
|
||||||
|
function remove_toast(toast) {
|
||||||
|
toast.classList.add("hide");
|
||||||
|
|
||||||
|
if (toast.timeoutId) {
|
||||||
|
clearTimeout(toast.timeoutId);
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(() => toast.remove(), 300);
|
||||||
|
}
|
||||||
|
|
||||||
|
function toast(text, type="error", timeout=5) {
|
||||||
|
const toast = document.createElement("li");
|
||||||
|
toast.className = `section ${type}`
|
||||||
|
toast.innerHTML = `<span class=".text">${text}</span><a href="#">✖</span>`
|
||||||
|
|
||||||
|
toast.querySelector("a").addEventListener("click", async (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
await remove_toast(toast);
|
||||||
|
});
|
||||||
|
|
||||||
|
notifications.appendChild(toast);
|
||||||
|
toast.timeoutId = setTimeout(() => remove_toast(toast), timeout * 1000);
|
||||||
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
function add_row_listeners(row) {
|
function add_row_listeners(row) {
|
||||||
console.log(row);
|
|
||||||
row.querySelector(".remove a").addEventListener("click", async (event) => {
|
row.querySelector(".remove a").addEventListener("click", async (event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
await del_user(row.id);
|
await del_user(row.id);
|
||||||
|
@ -23,12 +22,12 @@ async function add_user() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (values.username === "" | values.password === "" | values.password2 === "") {
|
if (values.username === "" | values.password === "" | values.password2 === "") {
|
||||||
alert("Username, password, and password2 are required");
|
toast("Username, password, and password2 are required");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (values.password !== values.password2) {
|
if (values.password !== values.password2) {
|
||||||
alert("Passwords do not match");
|
toast("Passwords do not match");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +35,7 @@ async function add_user() {
|
||||||
var user = await request("POST", "v1/user", values);
|
var user = await request("POST", "v1/user", values);
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
alert(err);
|
toast(err);
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +54,7 @@ async function add_user() {
|
||||||
elems.handle.value = null;
|
elems.handle.value = null;
|
||||||
|
|
||||||
document.querySelector("details.section").open = false;
|
document.querySelector("details.section").open = false;
|
||||||
|
toast("Created user", "message");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -63,11 +63,12 @@ async function del_user(username) {
|
||||||
await request("DELETE", "v1/user", {"username": username});
|
await request("DELETE", "v1/user", {"username": username});
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
alert(error);
|
toast(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById(username).remove();
|
document.getElementById(username).remove();
|
||||||
|
toast("Deleted user", "message");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ async function add_whitelist() {
|
||||||
var domain = domain_elem.value.trim();
|
var domain = domain_elem.value.trim();
|
||||||
|
|
||||||
if (domain === "") {
|
if (domain === "") {
|
||||||
alert("Domain is required");
|
toast("Domain is required");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,8 +19,8 @@ async function add_whitelist() {
|
||||||
var item = await request("POST", "v1/whitelist", {"domain": domain});
|
var item = await request("POST", "v1/whitelist", {"domain": domain});
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
alert(err);
|
toast(err);
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var row = append_table_row(document.getElementById("whitelist"), item.domain, {
|
var row = append_table_row(document.getElementById("whitelist"), item.domain, {
|
||||||
|
@ -33,6 +33,7 @@ async function add_whitelist() {
|
||||||
|
|
||||||
domain_elem.value = null;
|
domain_elem.value = null;
|
||||||
document.querySelector("details.section").open = false;
|
document.querySelector("details.section").open = false;
|
||||||
|
toast("Added domain", "message");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,11 +42,12 @@ async function del_whitelist(domain) {
|
||||||
await request("DELETE", "v1/whitelist", {"domain": domain});
|
await request("DELETE", "v1/whitelist", {"domain": domain});
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
alert(error);
|
toast(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById(domain).remove();
|
document.getElementById(domain).remove();
|
||||||
|
toast("Removed domain", "message");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue