Merge pull request #104 from simple-login/feat/reverse-alias

Add reverse-alias screen
This commit is contained in:
Son Nguyen Kim
2021-10-04 17:31:40 +02:00
committed by GitHub
16 changed files with 981 additions and 461 deletions
+741 -410
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -49,9 +49,9 @@
"ejs": "^2.6.1",
"file-loader": "^1.1.11",
"mini-css-extract-plugin": "^0.4.4",
"node-sass": "^4.13.1",
"node-sass": "^6.0.1",
"prettier": "^2.0.5",
"sass-loader": "^7.1.0",
"sass-loader": "^10.1.1",
"vue-loader": "^15.4.2",
"vue-template-compiler": "^2.6.14",
"web-ext-types": "^2.1.0",
+29 -20
View File
@@ -38,12 +38,12 @@
step.
</p>
<br />
<button @click="goToCreateNewAccount()" class="btn btn-primary">
<a :href="url.createNewAccount" class="btn btn-primary">
Create a new account
</button>
<button @click="goToLogin()" class="btn btn-outline-primary">
</a>
<a :href="url.login" class="btn btn-outline-primary">
I already have account
</button>
</a>
</div>
<div class="content" v-if="step === 3">
@@ -67,12 +67,12 @@
<img
v-if="isChrome"
src="../images/chrome-permission-screenshot.png"
style="width: 400px"
style="width: 400px;"
/>
<img
v-else
src="../images/firefox-permission-screenshot.png"
style="width: 400px"
style="width: 400px;"
/>
<p>
@@ -84,7 +84,7 @@
<img
alt="SimpleLogin Button demo"
src="../images/sl-button-demo.png"
style="width: 400px"
style="width: 400px;"
class="mb-3"
/>
@@ -106,7 +106,7 @@
<button
@click="nextStep()"
class="btn"
style="color: #888; font-size: 0.8em"
style="color: #888; font-size: 0.8em;"
>
Skip
</button>
@@ -119,20 +119,20 @@
<img
alt="SimpleLogin"
src="../images/icon-simplelogin.png"
style="height: 1.2em"
style="height: 1.2em;"
/>
icon at the corner of your browser.
</p>
<p
v-if="isChrome"
class="alert alert-primary"
style="border-left: 5px #467fcf solid"
style="border-left: 5px #467fcf solid;"
>
Note: this icon maybe hidden under
<img
alt="Extension Menu"
src="../images/icon-puzzle.png"
style="height: 1.2em"
style="height: 1.2em;"
/>
button.
</p>
@@ -157,29 +157,38 @@ import EventManager from "../popup/EventManager";
export default {
data() {
return {
step: window.location.href.match(/#step3/) ? 3 : 1,
step: 1,
isChrome:
/Chrome/.test(navigator.userAgent) &&
/Google Inc/.test(navigator.vendor),
isAuthenticated: false,
userName: "",
url: {
createNewAccount: "",
login: "",
},
};
},
async mounted() {
// get URL for buttons
const apiUrl = await SLStorage.get(SLStorage.SETTINGS.API_URL);
this.url.createNewAccount = `${apiUrl}/auth/register?next=%2Fdashboard%2Fsetup_done`;
this.url.login = `${apiUrl}/dashboard/setup_done`;
// maybe user redirected from the setup_done page
if (this.step === 3) {
await this.tryGetUserInfo();
}
// update setup step
const self = this;
const updateStep = function () {
self.step = window.location.href.match(/#step3/) ? 3 : 1;
};
window.addEventListener("hashchange", updateStep, false);
updateStep();
},
methods: {
async goToCreateNewAccount() {
const apiUrl = await SLStorage.get(SLStorage.SETTINGS.API_URL);
window.location.href = `${apiUrl}/auth/register?next=%2Fdashboard%2Fsetup_done`;
},
async goToLogin() {
const apiUrl = await SLStorage.get(SLStorage.SETTINGS.API_URL);
window.location.href = `${apiUrl}/dashboard/setup_done`;
},
toStep(i) {
this.step = i;
},
+4
View File
@@ -29,6 +29,10 @@ const API_ROUTE = {
TOGGLE_ALIAS: { method: "POST", path: "/api/aliases/:alias_id/toggle" },
EDIT_ALIAS: { method: "PUT", path: "/api/aliases/:alias_id" },
DELETE_ALIAS: { method: "DELETE", path: "/api/aliases/:alias_id" },
CREATE_REVERSE_ALIAS: {
method: "POST",
path: "/api/aliases/:alias_id/contacts",
},
GET_API_KEY_FROM_COOKIE: { method: "POST", path: "/api/api_key" },
};
+8
View File
@@ -159,6 +159,14 @@ em {
.btn-svg {
cursor: pointer;
padding: 5px;
display: inline;
}
/* send btn*/
.btn-send {
width: 14px;
height: 14px;
color: #b02a8f;
}
/* more options */
+2
View File
@@ -18,6 +18,7 @@ import SelfHostSetting from "./components/SelfHostSetting";
import ApiKeySetting from "./components/ApiKeySetting";
import Main from "./components/Main";
import NewAliasResult from "./components/NewAliasResult";
import ReverseAlias from "./components/ReverseAlias";
import AppSettings from "./components/AppSettings";
import Utils from "./Utils";
import APIService from "./APIService";
@@ -30,6 +31,7 @@ const components = {
ApiKeySetting,
Main,
NewAliasResult,
ReverseAlias,
AppSettings,
};
+5
View File
@@ -7,6 +7,7 @@ const PATH = {
LOGIN: "/login",
API_KEY_SETTING: "/api-key-setting",
SELF_HOST_SETTING: "/self-host-setting",
REVERSE_ALIAS: "/reverse-alias",
APP_SETTINGS: "/app-settings",
};
@@ -39,6 +40,10 @@ class Navigation {
path: Navigation.PATH.NEW_ALIAS_RESULT,
component: components.NewAliasResult,
},
{
path: Navigation.PATH.REVERSE_ALIAS,
component: components.ReverseAlias,
},
{
path: Navigation.PATH.APP_SETTINGS,
component: components.AppSettings,
+3 -3
View File
@@ -29,7 +29,7 @@
<textarea-autosize
placeholder="Note, can be anything to help you remember why you created this alias. This field is optional."
class="form-control"
style="width: 100%"
style="width: 100%;"
v-model="moreOptions.note"
:disabled="loading"
></textarea-autosize>
@@ -38,7 +38,7 @@
From Name
<font-awesome-icon
v-b-tooltip.hover.top="
'This name is used when you send or reply from alias'
'This name is used when you send or reply from alias. You may need to use a pseudonym because the receiver can see it.'
"
icon="question-circle"
/>
@@ -69,7 +69,7 @@
<button
class="btn btn-sm btn-delete"
style="color: #dc3545"
style="color: #dc3545;"
v-on:click="handleClickDelete"
:disabled="loading"
>
+5 -5
View File
@@ -1,21 +1,21 @@
<template>
<div class="header">
<div class="row mt-2 pb-2 ml-3 mr-2" style="border-bottom: 1px #eee solid">
<div class="row mt-2 pb-2 ml-3 mr-2" style="border-bottom: 1px #eee solid;">
<div>
<div
v-on:click="navigateBack()"
v-bind:class="{ back: canBack }"
style="display: inline-block"
style="display: inline-block;"
>
<img
v-if="canBack"
src="/images/back-button.svg"
style="height: 20px"
style="height: 20px;"
/>
<img
class="sl-logo"
src="/images/horizontal-logo.svg"
style="height: 18px"
style="height: 18px;"
/>
</div>
<div class="beta-badge" v-if="isBeta">BETA</div>
@@ -53,7 +53,7 @@
:href="apiUrl + '/dashboard/'"
target="_blank"
class="dashboard-btn float-right"
style="padding: 0.25rem 0.5rem; font-size: 0.875rem"
style="padding: 0.25rem 0.5rem; font-size: 0.875rem;"
title="Dashboard"
v-b-tooltip.hover
:disabled="!useCompactLayout"
+3 -3
View File
@@ -1,7 +1,7 @@
<template>
<div class="content">
<!-- Login/register screen -->
<div v-if="!isShowMfa" class="p-6 container" style="min-height: 350px">
<div v-if="!isShowMfa" class="p-6 container" style="min-height: 350px;">
<h1 class="h5 mb-3">
Welcome to
<a href="https://simplelogin.io" target="_blank"
@@ -52,7 +52,7 @@
<!-- END Login/register screen -->
<!-- MFA screen -->
<div v-else class="p-6 container" style="min-height: 350px">
<div v-else class="p-6 container" style="min-height: 350px;">
<div class="p-3">
<div class="mb-2">
Your account is protected with Two Factor Authentication. <br />
@@ -63,7 +63,7 @@
<p>Please enter the 2FA code from your 2FA authenticator</p>
</div>
<div style="margin: auto">
<div style="margin: auto;">
<input
v-model="mfaCode"
v-on:keyup.enter="submitMfaCode"
+27 -14
View File
@@ -5,7 +5,7 @@
<!-- Main Page -->
<div class="container">
<div v-if="recommendation.show" class="text-center">
<div class="" style="font-size: 12px">
<div class="" style="font-size: 12px;">
You created this alias on this website before:
</div>
<div class="flex-grow-1">
@@ -27,14 +27,14 @@
<div>
<p
class="font-weight-bold mt-2 align-self-center"
style="display: inline-block"
style="display: inline-block;"
>
New Alias
</p>
<button
:disabled="loading || !canCreate"
style="margin-left: 15px"
style="margin-left: 15px;"
class="btn btn-outline-primary btn-sm"
title="Generate a totally random alias."
@click="createRandomAlias"
@@ -49,7 +49,7 @@
<div class="row mb-2">
<div
class="col align-self-start input-group-sm"
style="padding-right: 0"
style="padding-right: 0;"
>
<input
v-model="aliasPrefix"
@@ -63,7 +63,7 @@
<div
class="col align-self-start input-group-sm"
style="padding-left: 5px; padding-right: 5px"
style="padding-left: 5px; padding-right: 5px;"
>
<select
v-model="signedSuffix"
@@ -82,7 +82,7 @@
<button
:disabled="loading || !canCreate"
style="margin-right: 15px"
style="margin-right: 15px;"
class="btn btn-primary btn-sm align-self-start"
>
Create
@@ -90,7 +90,7 @@
</div>
<div
class="row text-danger"
style="font-size: 12px"
style="font-size: 12px;"
v-if="aliasPrefixError != ''"
>
<div class="col">
@@ -100,13 +100,13 @@
</form>
</div>
<div class="mb-1 text-center" v-if="aliasPrefix" style="font-size: 12px">
<div class="mb-1 text-center" v-if="aliasPrefix" style="font-size: 12px;">
You're about to create alias
<span class="text-primary">{{ aliasPrefix }}{{ signedSuffix[0] }}</span>
</div>
<div v-if="!canCreate">
<p class="text-danger" style="font-size: 14px">
<p class="text-danger" style="font-size: 14px;">
You have reached limit number of email aliases in free plan, please
<a :href="apiUrl + '/dashboard/pricing'" target="_blank">upgrade</a>
or reuse one of the existing aliases.
@@ -119,7 +119,7 @@
Or use an existing alias
</div>
<div class="mx-auto" style="max-width: 60%">
<div class="mx-auto" style="max-width: 60%;">
<input
v-model="searchString"
v-on:keyup.enter="loadAlias"
@@ -133,7 +133,7 @@
v-if="searchString"
@click="resetSearch"
class="float-right"
style="color: blue; border: none; padding: 0; background: none"
style="color: blue; border: none; padding: 0; background: none;"
>
Reset
</button>
@@ -157,7 +157,7 @@
</a>
<div class="list-item-email-fade" />
</div>
<div style="white-space: nowrap">
<div style="white-space: nowrap;">
<toggle-button
:value="alias.enabled"
color="#b02a8f"
@@ -166,6 +166,13 @@
@change="toggleAlias(alias)"
/>
<div
class="btn-svg btn-send"
@click="goToReverseAlias(alias)"
>
<font-awesome-icon icon="paper-plane" />
</div>
<img
src="/images/icon-dropdown.svg"
v-if="alias"
@@ -185,7 +192,7 @@
{{ alias.note }}
</div>
<div class="font-weight-lighter" style="font-size: 11px">
<div class="font-weight-lighter" style="font-size: 11px;">
{{ alias.nb_forward }} forwards, {{ alias.nb_reply }} replies,
{{ alias.nb_block }} blocks.
</div>
@@ -206,7 +213,7 @@
<div v-if="isFetchingAlias" class="text-secondary mx-auto text-center">
<img
src="/images/loading-three-dots.svg"
style="width: 80px; margin: 20px"
style="width: 80px; margin: 20px;"
/>
</div>
</div>
@@ -493,6 +500,12 @@ export default {
}
},
// Reverse Alias
goToReverseAlias(alias) {
SLStorage.setTemporary("alias", alias);
Navigation.navigateTo(Navigation.PATH.REVERSE_ALIAS, true);
},
// Clipboard
clipboardSuccessHandler({ value, event }) {
Utils.showSuccess(value + " copied to clipboard");
+1 -1
View File
@@ -41,7 +41,7 @@
<a
@click="doNotAskRateAgain"
class="text-secondary cursor"
style="font-size: 0.7em"
style="font-size: 0.7em;"
>
Do not ask again
</a>
+144
View File
@@ -0,0 +1,144 @@
<template>
<div class="content">
<div class="p-2 container">
<!-- Reverse-alias screen -->
<div class="m-2 p-2" v-if="!createdReverseAlias">
<p>
Send emails from
<span class="font-weight-bold">{{ alias.email }}</span>
</p>
<small>
To send an email from your alias to a contact, you need to create a
<b>reverse-alias</b>, a special email address. When you send an email
to the reverse-alias, the email will be sent from your alias to the
contact.<br /><br />
This Youtube video can also quickly walk you through the steps:
<a
href="https://www.youtube.com/watch?v=VsypF-DBaow"
target="_blank"
rel="noopener noreferrer"
>How to send emails from an alias</a
>
</small>
<br /><br />
<label>
Receiver:
<font-awesome-icon
v-b-tooltip.hover.top="'Where do you want to send the email?'"
icon="question-circle"
/>
</label>
<b-input
v-model="receiverEmail"
v-on:keyup.enter="createReverseAlias"
placeholder="First Last &lt;email@example.com&gt;"
:disabled="loading"
/>
</div>
<!-- Created screen -->
<div class="m-2 p-2" v-else>
<p class="font-weight-bold">
{{
createdReverseAlias.existed
? "You have created this reverse-alias before:"
: "Reverse-alias is created:"
}}
</p>
<p>
<a
v-clipboard="() => createdReverseAlias.reverse_alias"
v-clipboard:success="clipboardSuccessHandler"
v-clipboard:error="clipboardErrorHandler"
v-b-tooltip.hover
title="Click to Copy"
class="cursor"
>
<span class="text-success">
{{ createdReverseAlias.reverse_alias }}
</span>
</a>
</p>
<small>
You can send email from one of these mailbox(es):
<ul style="margin-bottom: 0;">
<li v-for="mailbox in alias.mailboxes" v-bind:key="mailbox.id">
{{ mailbox.email }}
</li>
</ul>
The email will be forwarded to
<b>{{ createdReverseAlias.contact }}</b
>.<br />
The receiver will see <b>{{ alias.email }}</b> as your email
address.<br />
</small>
</div>
<div class="m-2 p-2">
<button
class="btn btn-sm btn-primary"
@click="createReverseAlias"
:disabled="loading || !receiverEmail"
v-if="!createdReverseAlias"
>
Create a reverse-alias
</button>
<button class="btn btn-sm btn-primary" @click="backToMainPage" v-else>
<font-awesome-icon icon="arrow-left" />
Back
</button>
</div>
</div>
</div>
</template>
<script>
import SLStorage from "../SLStorage";
import Navigation from "../Navigation";
import Utils from "../Utils";
import { callAPI, API_ROUTE, API_ON_ERR } from "../APIService";
export default {
data() {
return {
alias: SLStorage.getTemporary("alias"),
createdReverseAlias: null,
loading: false,
receiverEmail: "",
};
},
methods: {
// Clipboard
clipboardSuccessHandler({ value, event }) {
Utils.showSuccess(value + " copied to clipboard");
},
clipboardErrorHandler({ value, event }) {
console.error("error", value);
},
// Create reverse-alias
async createReverseAlias() {
this.loading = true;
const response = await callAPI(
API_ROUTE.CREATE_REVERSE_ALIAS,
{
alias_id: this.alias.id,
},
{
contact: this.receiverEmail,
},
API_ON_ERR.TOAST
);
this.createdReverseAlias = response ? response.data : null;
this.loading = false;
},
backToMainPage() {
Navigation.navigateBack();
},
},
computed: {},
};
</script>
+1 -1
View File
@@ -7,7 +7,7 @@
</div>
<div class="mb-2">The default API URL is https://app.simplelogin.io</div>
<div style="margin: auto">
<div style="margin: auto;">
<input
v-model="apiUrl"
v-on:keyup.enter="saveApiUrl"
+1 -1
View File
@@ -1,5 +1,5 @@
<template>
<div v-if="show" style="height: 400px">
<div v-if="show" style="height: 400px;">
<div class="splash overlay">
<div class="overlay-content">
<img class="logo" src="/images/horizontal-logo.svg" /><br />
+5 -1
View File
@@ -26,6 +26,8 @@ import {
faBug,
faQuestionCircle,
faCog,
faPaperPlane,
faArrowLeft,
} from "@fortawesome/free-solid-svg-icons";
library.add(
@@ -39,7 +41,9 @@ library.add(
faSave,
faBug,
faQuestionCircle,
faCog
faCog,
faPaperPlane,
faArrowLeft
);
global.browser = require("webextension-polyfill");