app-MAIL-temp/app/dashboard/templates/dashboard/index.html

673 lines
24 KiB
HTML

{% extends 'default.html' %}
{% set active_page = "dashboard" %}
{% block head %}
<style>
.alias-activity {
font-weight: 600;
font-size: 14px;
}
.btn-group-border-left {
border-left: 1px #fbfbfb4f solid;
}
</style>
{% endblock %}
{% block title %}
Alias
{% endblock %}
{% block default_content %}
<!-- Global Stats -->
<div class="row">
<div class="col-6 col-sm-3">
<div class="card">
<div class="card-body p-3 text-center">
<div class="h1 m-0">{{ stats.nb_alias }}</div>
<div class="text-muted">Aliases</div>
</div>
</div>
</div>
<div class="col-6 col-sm-3">
<div class="card">
<div class="card-body p-3 text-center">
<div class="h1 m-0">{{ stats.nb_forward }}</div>
<div class="text-muted">Forwards</div>
</div>
</div>
</div>
<div class="col-6 col-sm-3">
<div class="card">
<div class="card-body p-3 text-center">
<div class="h1 m-0">{{ stats.nb_reply }}</div>
<div class="text-muted">Replies</div>
</div>
</div>
</div>
<div class="col-6 col-sm-3">
<div class="card">
<div class="card-body p-3 text-center">
<div class="h1 m-0">{{ stats.nb_block }}</div>
<div class="text-muted">Blocks</div>
</div>
</div>
</div>
</div>
<!-- END Global Stats -->
<div class="row mb-3">
<div class="col-lg-6 pt-1" style="max-width: 25em">
<div class="btn-group" role="group">
<form method="post">
<input type="hidden" name="form-name" value="create-custom-email">
<button data-toggle="tooltip"
title="Create a custom alias"
class="btn btn-primary mr-2"><i class="fa fa-plus"></i> New Email Alias
</button>
</form>
<div class="btn-group" role="group">
<form method="post">
<input type="hidden" name="form-name" value="create-random-email">
<button data-toggle="tooltip"
title="Create a totally random alias"
class="btn btn-success"><i class="fa fa-random"></i> Random Alias
</button>
</form>
<button id="btnGroupDrop1" type="button" class="btn btn-success dropdown-toggle btn-group-border-left"
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
</button>
<div class="dropdown-menu dropdown-menu-right border-left" aria-labelledby="btnGroupDrop1">
<div class="">
<form method="post">
<input type="hidden" name="form-name" value="create-random-email">
<input type="hidden" name="generator_scheme" value="{{ AliasGeneratorEnum.word.value }}">
<button class="dropdown-item">By Random Words</button>
</form>
</div>
<div class="">
<form method="post">
<input type="hidden" name="form-name" value="create-random-email">
<input type="hidden" name="generator_scheme" value="{{ AliasGeneratorEnum.uuid.value }}">
<button class="dropdown-item">By UUID</button>
</form>
</div>
</div>
</div>
</div>
</div>
<div id="filter-app" class="col-lg-auto pt-1 flex-grow-1">
<div class="float-right d-flex">
<!-- Filter Control -->
<div v-if="showFilter" id="filter-control">
<form method="get" class="form-inline">
<select name="sort"
onchange="this.form.submit()"
class="form-control mr-3 shadow">
<option value="" {% if sort == "" %} selected {% endif %}>
Sort by most recent activity
</option>
<option value="old2new" {% if sort == "old2new" %} selected {% endif %}>
Alias Old-Recent
</option>
<option value="old2new" {% if sort == "new2old" %} selected {% endif %}>
Alias Recent-Old
</option>
<option value="a2z" {% if sort == "a2z" %} selected {% endif %}>
Alias A-Z
</option>
<option value="z2a" {% if sort == "z2a" %} selected {% endif %}>
Alias Z-A
</option>
</select>
<select name="filter"
onchange="this.form.submit()"
class="form-control mr-3 shadow">
<option value="" {% if filter == "" %} selected {% endif %}>
All Aliases
</option>
<option value="enabled" {% if filter == "enabled" %} selected {% endif %}>
Only Enabled Aliases
</option>
<option value="disabled" {% if filter == "disabled" %} selected {% endif %}>
Only Disabled Aliases
</option>
</select>
<input type="search" name="query" placeholder="Enter to search for alias"
class="form-control shadow mr-2"
style="max-width: 15em"
value="{{ query }}">
{% if query or sort or filter %}
<a href="{{ url_for('dashboard.index') }}"
class="btn btn-light">Reset</a>
{% endif %}
</form>
</div>
<a v-if="!showFilter" @click="toggleFilter()" class="btn btn-secondary">
<i class="fe fe-chevrons-left"></i> Filters
</a>
<a v-if="showFilter" @click="toggleFilter()" class="btn btn-outline-secondary">
<i class="fe fe-chevrons-right"></i>
</a>
</div>
</div>
</div>
<div class="row">
{% for alias_info in alias_infos %}
{% set alias = alias_info.alias %}
<div class="col-12 col-lg-6">
<div class="card p-4 shadow-sm {% if alias_info.alias.id == highlight_alias_id %} highlight-row {% endif %} ">
<div class="row">
<div class="col-8">
<span class="clipboard cursor mb-0"
{% if loop.index ==1 %}
data-intro="This is an <em>alias</em>. <br><br>
<b>All</b> emails sent to an alias will be <em>forwarded</em> to your inbox. <br><br>
Alias is a great way to hide your personal email address so feel free to
use it whenever possible, for example when signing up for a newsletter or creating a new account on a suspicious website 😎"
data-step="2"
{% endif %}
{% if alias.enabled %}
data-toggle="tooltip"
title="Click to copy"
data-clipboard-text="{{ alias.email }}"
{% endif %}
>
<span class="font-weight-bold">{{ alias.email }}</span>
</span>
</div>
<div class="col text-right">
<label class="custom-switch cursor"
data-toggle="tooltip"
{% if alias.enabled %}
title="Disable alias - you will stop receiving emails sent to this alias"
{% else %}
title="Enable alias - you will start receiving emails sent to this alias"
{% endif %}
{% if loop.index ==1 %}
data-intro="By turning off an alias, emails sent to this alias will <em>not</em>
be forwarded to your inbox. <br><br>
This should be used with care as others might
not be able to reach you after ...
"
data-step="3"
{% endif %}
style="padding-left: 0px"
>
<input type="checkbox" class="custom-switch-input"
data-alias="{{ alias.id }}"
data-alias-email="{{ alias.email }}"
{{ "checked" if alias.enabled else "" }}>
<span class="custom-switch-indicator"></span>
</label>
</div>
</div>
<!-- Email Activity -->
<div class="row mb-2">
<div class="col">
<div style="font-size: 12px">
{% if alias_info.latest_email_log != None %}
{% set email_log = alias_info.latest_email_log %}
{% set contact = alias_info.latest_contact %}
{% if email_log.is_reply %}
{{ contact.website_email }}
<i class="fa fa-reply mr-2" data-toggle="tooltip" title="Email reply/sent from alias"></i>
{{ email_log.created_at | dt }}
{% elif email_log.bounced %}
<span class="text-danger">
{{ contact.website_email }}
<i class="fa fa-warning mr-2" data-toggle="tooltip"
title="Email bounced and cannot be forwarded to your mailbox"></i>
{{ email_log.created_at | dt }}
</span>
{% elif email_log.blocked %}
{{ contact.website_email }}
<i class="fa fa-ban mr-2 text-danger" data-toggle="tooltip" title="Email blocked"></i>
{{ email_log.created_at | dt }}
{% else %}
{{ contact.website_email }}
<i class="fa fa-paper-plane mr-2" data-toggle="tooltip" title="Email forwarded to alias"></i>
{{ email_log.created_at | dt }}
{% endif %}
{% else %}
No Activity. Alias created {{ alias.created_at | dt }}
{% endif %}
</div>
</div>
</div>
<!-- END Email Activity -->
<!-- Send Email && More button -->
<div class="row">
<div class="col">
<a href="{{ url_for('dashboard.alias_contact_manager', alias_id=alias.id) }}"
id="send-email-{{ alias.id }}"
{% if loop.index ==1 %}
data-intro="Not only alias can receive emails, it can <em>send</em> emails too! <br><br>
You can add a new <em>contact</em> to for your alias here. <br><br>
To send an email to your contact, SimpleLogin will create a <em>special</em> email address. <br><br>
Sending an email to this email address will <em>forward</em> the email to your contact"
data-step="4"
{% endif %}
class="btn btn-sm btn-outline-primary {% if not alias.enabled %} disabled {% endif %}"
data-toggle="tooltip"
title="Not only an alias can receive emails, it can send emails too"
>
Send Email&nbsp; &nbsp;<i class="fe fe-send"></i>
</a>
</div>
<div class="col text-right">
<a class="btn btn-sm" data-toggle="collapse" href="#alias-{{ alias.id }}" role="button"
aria-expanded="false">
More <i class="fe fe-chevron-down"></i>
</a>
</div>
</div>
<!-- END Send Email && More button -->
<!-- Collapse section -->
<div class="collapse mt-2" id="alias-{{ alias.id }}">
{% if alias_info.latest_email_log != None %}
<div style="font-size: 12px">
Alias created {{ alias.created_at | dt }}
</div>
{% endif %}
<span class="alias-activity">{{ alias_info.nb_forward }}</span> forwards,
<span class="alias-activity">{{ alias_info.nb_blocked }}</span> blocks,
<span class="alias-activity">{{ alias_info.nb_reply }}</span> replies
<a href="{{ url_for('dashboard.alias_log', alias_id=alias.id) }}"
class="btn btn-sm btn-link">
See All &nbsp;
</a>
{% if mailboxes|length > 1 %}
<div class="small-text">Current mailbox</div>
<div class="d-flex">
<div class="flex-grow-1 mr-2">
<select id="mailbox-{{ alias.id }}"
class="form-control form-control-sm" name="mailbox">
{% for mailbox in mailboxes %}
<option value="{{ mailbox.id }}" {% if mailbox.id == alias_info.mailbox.id %}
selected {% endif %}>
{{ mailbox.email }}
</option>
{% endfor %}
</select>
</div>
<div class="">
<a data-alias="{{ alias.id }}"
class="save-mailbox btn btn-sm btn-outline-info w-100">
Update
</a>
</div>
</div>
{% elif alias_info.mailbox != None and alias_info.mailbox.email != current_user.email %}
<div class="small-text">
Owned by <b>{{ alias_info.mailbox.email }}</b> mailbox
</div>
{% endif %}
<div class="small-text mt-2">Alias Note</div>
<div class="d-flex">
<div class="flex-grow-1 mr-2">
<textarea
id="note-{{ alias.id }}"
name="note"
class="form-control"
rows="2"
placeholder="e.g. where the alias is used or why is it created">{{ alias.note or "" }}</textarea>
</div>
<div class="">
<a data-alias="{{ alias.id }}"
class="save-note btn btn-sm btn-outline-success w-100">
Save
</a>
</div>
</div>
<div class="small-text mt-2" data-toogle="tooltip"
title="Alias name is used when you send or reply from alias">
Alias name
<i class="fe fe-help-circle"></i>
</div>
<div class="d-flex">
<div class="flex-grow-1 mr-2">
<input id="alias-name-{{ alias.id }}"
value="{{ alias.name or '' }}" class="form-control"
placeholder="{{ alias.custom_domain.name or "Alias name" }}">
</div>
<div class="">
<a data-alias="{{ alias.id }}"
class="save-alias-name btn btn-sm btn-outline-primary w-100">
Save
</a>
</div>
</div>
<div class="row mt-3">
<div class="col">
<form method="post">
<input type="hidden" name="form-name" value="delete-email">
<input type="hidden" name="alias-id" value="{{ alias.id }}">
<input type="hidden" name="alias" class="alias" value="{{ alias.email }}">
<span class="delete-email btn btn-link btn-sm float-right text-danger">
Delete&nbsp; &nbsp;<i class="dropdown-icon fe fe-trash-2 text-danger"></i>
</span>
</form>
</div>
</div>
</div>
<!-- END Collapse section -->
</div>
</div>
{% endfor %}
</div>
<div class="row">
<div class="col">
<nav aria-label="Alias navigation">
<ul class="pagination">
<li class="page-item {% if page == 0 %}disabled{% endif %}">
<a class="page-link"
href="{{ url_for('dashboard.index', page=page-1, query=query, sort=sort, filter=filter) }}">Previous</a>
</li>
<li class="page-item {% if last_page %}disabled{% endif %}">
<a class="page-link"
href="{{ url_for('dashboard.index', page=page+1, query=query, sort=sort, filter=filter) }}">Next</a>
</li>
</ul>
</nav>
</div>
</div>
{% if client_users %}
<div class="row">
<h3 class="page-title col"
data-intro="Here you can find the list of website/app on which
you have used the <em>Connect with SimpleLogin</em> button <br><br>
You also see what information that SimpleLogin has communicated to these website/app when you sign in."
data-step="5"
>
Apps
</h3>
</div>
<div class="row row-cards row-deck mt-4">
<div class="col-12">
<div class="card">
<div class="table-responsive">
<table class="table table-hover table-outline table-vcenter text-nowrap card-table">
<thead>
<tr>
<th>
App
</th>
<th>
Info
<i class="fe fe-help-circle" data-toggle="tooltip"
title="Info sent to this app/website"></i>
</th>
<th class="text-center">
First used
<i class="fe fe-help-circle" data-toggle="tooltip"
title="The first time you have used the SimpleLogin on this app/website"></i>
</th>
<!--<th class="text-center">Last used</th>-->
</tr>
</thead>
<tbody>
{% for client_user in client_users %}
<tr>
<td>
{{ client_user.client.name }}
</td>
<td>
{% for scope, val in client_user.get_user_info().items() %}
<div>
{% if scope == "email" %}
Email: <a href="mailto:{{ val }}">{{ val }}</a>
{% elif scope == "name" %}
Name: {{ val }}
{% endif %}
</div>
{% endfor %}
</td>
<td class="text-center">
{{ client_user.created_at | dt }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
{% endif %}
{% endblock %}
{% block script %}
<script>
{% if show_intro %}
// only show intro when screen is big enough to show "developer" tab
if (window.innerWidth >= 1024) {
introJs().start();
}
{% endif %}
$(".delete-email").on("click", function (e) {
let alias = $(this).parent().find(".alias").val();
let message = `Once <b>${alias}</b> is deleted, people/apps ` +
"who used to contact you via this alias cannot reach you any more," +
" please confirm.";
let that = $(this);
bootbox.confirm({
message: message,
buttons: {
confirm: {
label: 'Yes, delete it',
className: 'btn-danger'
},
cancel: {
label: 'Cancel',
className: 'btn-outline-primary'
}
},
callback: function (result) {
if (result) {
that.closest("form").submit();
}
}
})
});
$(".custom-switch-input").change(async function (e) {
let aliasId = $(this).data("alias");
let alias = $(this).data("alias-email");
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
var 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
var oldValue = !$(this).prop("checked");
$(this).prop("checked", oldValue);
}
})
$(".save-note").on("click", async function () {
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(`Note Saved`);
} else {
toastr.error("Sorry for the inconvenience! Could you refresh the page & retry please?", "Unknown Error");
// reset to the original value
var 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
var oldValue = !$(this).prop("checked");
$(this).prop("checked", oldValue);
}
})
$(".save-mailbox").on("click", async function () {
let aliasId = $(this).data("alias");
let mailbox_id = $(`#mailbox-${aliasId}`).val();
try {
let res = await fetch(`/api/aliases/${aliasId}`, {
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
mailbox_id: mailbox_id,
}),
});
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
var 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
var 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");
}
})
</script>
<script src="{{ url_for('static', filename='node_modules/vue/dist/vue.min.js') }}"></script>
<script>
var app = 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;
}
})
</script>
{% endblock %}