This commit is contained in:
2022-12-30 16:23:27 +00:00
parent 02776e8478
commit 20da343c54
1304 changed files with 870224 additions and 0 deletions

30
app/static/js/an.js Normal file
View File

@ -0,0 +1,30 @@
(function () {
// only enable on prod
if (!window.location.host.endsWith('simplelogin.io')) {
console.log("Analytics should only be enabled in prod");
return;
}
if (store.get('analytics-ignore') === 't') {
console.log("Analytics is disabled");
return;
}
console.log("init Analytics");
// Add Plausible script
// <script async defer data-domain="app.simplelogin.io,everything.simplelogin.com" src="/p.outbound.js"></script>
var plausibleScript = document.createElement('script');
plausibleScript.defer = 1;
plausibleScript.async = 1;
plausibleScript.dataset.api = "/p/api/event";
plausibleScript.dataset.domain = "app.simplelogin.io,everything.simplelogin.com";
plausibleScript.src = '/p.outbound.js';
var ins = document.getElementsByTagName('script')[0];
ins.parentNode.insertBefore(plausibleScript, ins);
// allow custom event
window.plausible = window.plausible || function() { (window.plausible.q = window.plausible.q || []).push(arguments) }
})();

273
app/static/js/index.js Normal file
View File

@ -0,0 +1,273 @@
$('.mailbox-select').multipleSelect();
function confirmDeleteAlias() {
let that = $(this);
let alias = that.data("alias-email");
let aliasDomainTrashUrl = that.data("custom-domain-trash-url");
let message = `Maybe you want to disable the alias instead? Please note once deleted, it <b>can't</b> be restored.`;
if (aliasDomainTrashUrl !== undefined) {
message = `Maybe you want to disable the alias instead? When it's deleted, it's moved to the domain
<a href="${aliasDomainTrashUrl}">trash</a>`;
}
bootbox.dialog({
title: `Delete ${alias}`,
message: message,
size: 'large',
onEscape: true,
backdrop: true,
buttons: {
disable: {
label: 'Disable it',
className: 'btn-primary',
callback: function () {
that.closest("form").find('input[name="form-name"]').val("disable-alias");
that.closest("form").submit();
}
},
delete: {
label: "Delete it, I don't need it anymore",
className: 'btn-outline-danger',
callback: function () {
that.closest("form").submit();
}
},
cancel: {
label: 'Cancel',
className: 'btn-outline-primary'
},
}
});
}
$(".enable-disable-alias").change(async function () {
let aliasId = $(this).data("alias");
let alias = $(this).data("alias-email");
await disableAlias(aliasId, alias);
});
async function disableAlias(aliasId, alias) {
let oldValue;
try {
let res = await fetch(`/api/aliases/${aliasId}/toggle`, {
method: "POST",
headers: {
"Content-Type": "application/json",
}
});
if (res.ok) {
let json = await res.json();
if (json.enabled) {
toastr.success(`${alias} is enabled`);
$(`#send-email-${aliasId}`).removeClass("disabled");
} else {
toastr.success(`${alias} is disabled`);
$(`#send-email-${aliasId}`).addClass("disabled");
}
} else {
toastr.error("Sorry for the inconvenience! Could you refresh the page & retry please?", "Unknown Error");
// reset to the original value
oldValue = !$(this).prop("checked");
$(this).prop("checked", oldValue);
}
} catch (e) {
toastr.error("Sorry for the inconvenience! Could you refresh the page & retry please?", "Unknown Error");
// reset to the original value
oldValue = !$(this).prop("checked");
$(this).prop("checked", oldValue);
}
}
$(".enable-disable-pgp").change(async function (e) {
let aliasId = $(this).data("alias");
let alias = $(this).data("alias-email");
const oldValue = !$(this).prop("checked");
let newValue = !oldValue;
try {
let res = await fetch(`/api/aliases/${aliasId}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
disable_pgp: oldValue,
}),
});
if (res.ok) {
if (newValue) {
toastr.success(`PGP is enabled for ${alias}`);
} else {
toastr.info(`PGP is disabled for ${alias}`);
}
} else {
toastr.error("Sorry for the inconvenience! Could you refresh the page & retry please?", "Unknown Error");
// reset to the original value
$(this).prop("checked", oldValue);
}
} catch (err) {
toastr.error("Sorry for the inconvenience! Could you refresh the page & retry please?", "Unknown Error");
// reset to the original value
$(this).prop("checked", oldValue);
}
});
$(".pin-alias").change(async function () {
let aliasId = $(this).data("alias");
let alias = $(this).data("alias-email");
const oldValue = !$(this).prop("checked");
let newValue = !oldValue;
try {
let res = await fetch(`/api/aliases/${aliasId}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
pinned: newValue,
}),
});
if (res.ok) {
if (newValue) {
toastr.success(`${alias} is pinned`);
} else {
toastr.info(`${alias} is unpinned`);
}
} else {
toastr.error("Sorry for the inconvenience! Could you refresh the page & retry please?", "Unknown Error");
// reset to the original value
$(this).prop("checked", oldValue);
}
} catch (e) {
toastr.error("Sorry for the inconvenience! Could you refresh the page & retry please?", "Unknown Error");
// reset to the original value
$(this).prop("checked", oldValue);
}
});
$(".save-note").on("click", async function () {
let oldValue;
let aliasId = $(this).data("alias");
let note = $(`#note-${aliasId}`).val();
try {
let res = await fetch(`/api/aliases/${aliasId}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
note: note,
}),
});
if (res.ok) {
toastr.success(`Saved`);
} else {
toastr.error("Sorry for the inconvenience! Could you refresh the page & retry please?", "Unknown Error");
// reset to the original value
oldValue = !$(this).prop("checked");
$(this).prop("checked", oldValue);
}
} catch (e) {
toastr.error("Sorry for the inconvenience! Could you refresh the page & retry please?", "Unknown Error");
// reset to the original value
oldValue = !$(this).prop("checked");
$(this).prop("checked", oldValue);
}
});
$(".save-mailbox").on("click", async function () {
let oldValue;
let aliasId = $(this).data("alias");
let mailbox_ids = $(`#mailbox-${aliasId}`).val();
if (mailbox_ids.length === 0) {
toastr.error("You must select at least a mailbox", "Error");
return;
}
try {
let res = await fetch(`/api/aliases/${aliasId}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
mailbox_ids: mailbox_ids,
}),
});
if (res.ok) {
toastr.success(`Mailbox Updated`);
} else {
toastr.error("Sorry for the inconvenience! Could you refresh the page & retry please?", "Unknown Error");
// reset to the original value
oldValue = !$(this).prop("checked");
$(this).prop("checked", oldValue);
}
} catch (e) {
toastr.error("Sorry for the inconvenience! Could you refresh the page & retry please?", "Unknown Error");
// reset to the original value
oldValue = !$(this).prop("checked");
$(this).prop("checked", oldValue);
}
});
$(".save-alias-name").on("click", async function () {
let aliasId = $(this).data("alias");
let name = $(`#alias-name-${aliasId}`).val();
try {
let res = await fetch(`/api/aliases/${aliasId}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
name: name,
}),
});
if (res.ok) {
toastr.success(`Alias Name Saved`);
} else {
toastr.error("Sorry for the inconvenience! Could you refresh the page & retry please?", "Unknown Error");
}
} catch (e) {
toastr.error("Sorry for the inconvenience! Could you refresh the page & retry please?", "Unknown Error");
}
});
new Vue({
el: '#filter-app',
delimiters: ["[[", "]]"], // necessary to avoid conflict with jinja
data: {
showFilter: false
},
methods: {
async toggleFilter() {
let that = this;
that.showFilter = !that.showFilter;
store.set('showFilter', that.showFilter);
}
},
async mounted() {
if (store.get("showFilter"))
this.showFilter = true;
}
});

40
app/static/js/theme.js Normal file
View File

@ -0,0 +1,40 @@
let setCookie = function(name, value, days) {
if (!name || !value) return false;
let expires = '';
let secure = '';
if (location.protocol === 'https:') secure = 'Secure; ';
if (days) {
let date = new Date();
date.setTime(date.getTime() + (days * 24*60*60*1000));
expires = 'Expires=' + date.toUTCString() + '; ';
}
document.cookie = name + '=' + value + '; ' +
expires +
secure +
'sameSite=Lax; ' +
'domain=' + window.location.hostname + '; ' +
'path=/';
return true;
}
let getCookie = function(name) {
let match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
if (match) return match[2];
}
$(document).ready(function() {
/** Dark mode controller */
if (getCookie('dark-mode') === "true") {
document.documentElement.setAttribute('data-theme', 'dark');
}
$('[data-toggle="dark-mode"]').on('click', function () {
if (getCookie('dark-mode') === "true") {
setCookie('dark-mode', 'false', 30);
return document.documentElement.setAttribute('data-theme', 'light')
}
setCookie('dark-mode', 'true', 30);
document.documentElement.setAttribute('data-theme', 'dark')
})
});

View File

@ -0,0 +1,28 @@
const MAX_BYTES = 10240; // 10KiB
function enableDragDropForPGPKeys(inputID) {
function drop(event) {
event.stopPropagation();
event.preventDefault();
let files = event.dataTransfer.files;
for (let i = 0; i < files.length; i++) {
let file = files[i];
if(file.type !== 'text/plain'){
toastr.warning(`File ${file.name} is not a public key file`);
continue;
}
let reader = new FileReader();
reader.onloadend = onFileLoaded;
reader.readAsBinaryString(file);
}
}
function onFileLoaded(event) {
const initialData = event.currentTarget.result.substr(0, MAX_BYTES);
$(inputID).val(initialData);
}
const dropArea = $(inputID).get(0);
dropArea.addEventListener("drop", drop, false);
}