mirror of
https://github.com/anonaddy/anonaddy
synced 2026-04-25 17:15:29 +02:00
Added send from alias address creator
This commit is contained in:
@@ -2,6 +2,6 @@
|
||||
"printWidth": 100,
|
||||
"singleQuote": true,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5",
|
||||
"semi": false
|
||||
"semi": false,
|
||||
"arrowParens": "avoid"
|
||||
}
|
||||
596
composer.lock
generated
596
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -5,9 +5,9 @@ current:
|
||||
major: 0
|
||||
minor: 6
|
||||
patch: 1
|
||||
prerelease: ''
|
||||
prerelease: 1-g47f7ada
|
||||
buildmetadata: ''
|
||||
commit: f1d596
|
||||
commit: 47f7ad
|
||||
timestamp:
|
||||
year: 2020
|
||||
month: 10
|
||||
|
||||
2748
package-lock.json
generated
2748
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
26
package.json
26
package.json
@@ -11,17 +11,17 @@
|
||||
"format": "prettier --write 'resources/**/*.{css,js,vue}'"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^0.19",
|
||||
"cross-env": "^7.0",
|
||||
"dayjs": "^1.9.6",
|
||||
"autoprefixer": "^9.8.6",
|
||||
"axios": "^0.21.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"dayjs": "^1.9.7",
|
||||
"laravel-mix": "^5.0.9",
|
||||
"lodash": "^4.17.20",
|
||||
"portal-vue": "^2.1.7",
|
||||
"postcss-import": "^11.1.0",
|
||||
"postcss-nesting": "^5.0.0",
|
||||
"postcss": "^7.0.35",
|
||||
"resolve-url-loader": "^3.1.2",
|
||||
"tailwindcss": "^1.9.5",
|
||||
"tippy.js": "^4.3.5",
|
||||
"tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.0.2",
|
||||
"tippy.js": "^6.2.7",
|
||||
"v-clipboard": "^2.2.3",
|
||||
"vue": "^2.6.12",
|
||||
"vue-good-table": "^2.21.1",
|
||||
@@ -31,9 +31,9 @@
|
||||
"vuedraggable": "^2.24.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"husky": "^2.7.0",
|
||||
"lint-staged": "^8.2.1",
|
||||
"prettier": "1.16.4"
|
||||
"husky": "^4.3.6",
|
||||
"lint-staged": "^10.5.3",
|
||||
"prettier": "2.2.1"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
@@ -42,12 +42,10 @@
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{css,js,vue}": [
|
||||
"npm run format --",
|
||||
"git add"
|
||||
"npm run format --"
|
||||
],
|
||||
"*.php": [
|
||||
"composer format",
|
||||
"git add"
|
||||
"composer format"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
2
resources/css/app.css
vendored
2
resources/css/app.css
vendored
@@ -256,7 +256,7 @@ table.vgt-table tr.clickable:hover {
|
||||
}
|
||||
|
||||
.vgt-wrap__footer .footer__navigation__page-btn {
|
||||
@apply no-underline text-grey-500 font-bold whitespace-no-wrap;
|
||||
@apply no-underline text-grey-500 font-bold whitespace-nowrap;
|
||||
}
|
||||
|
||||
.vgt-wrap__footer .footer__navigation__page-btn:focus {
|
||||
|
||||
@@ -264,6 +264,21 @@
|
||||
<line x1="3" y1="6" x2="21" y2="6"></line>
|
||||
<line x1="3" y1="18" x2="21" y2="18"></line>
|
||||
</svg>
|
||||
<svg
|
||||
v-else-if="name === 'more'"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<circle cx="12" cy="12" r="1"></circle>
|
||||
<circle cx="12" cy="5" r="1"></circle>
|
||||
<circle cx="12" cy="19" r="1"></circle>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 50 50"
|
||||
style="enable-background:new 0 0 50 50;"
|
||||
style="enable-background: new 0 0 50 50"
|
||||
xml:space="preserve"
|
||||
>
|
||||
<path
|
||||
|
||||
@@ -79,7 +79,7 @@ export default {
|
||||
},
|
||||
watch: {
|
||||
open: {
|
||||
handler: function(newValue) {
|
||||
handler: function (newValue) {
|
||||
if (newValue) {
|
||||
this.show()
|
||||
} else {
|
||||
|
||||
65
resources/js/components/MoreOptions.vue
Normal file
65
resources/js/components/MoreOptions.vue
Normal file
@@ -0,0 +1,65 @@
|
||||
<template>
|
||||
<div class="relative flex justify-end items-center" @keydown.escape="isOpen = false">
|
||||
<button
|
||||
ref="openOptions"
|
||||
@click="isOpen = !isOpen"
|
||||
:aria-expanded="isOpen"
|
||||
id="project-options-menu-0"
|
||||
aria-has-popup="true"
|
||||
type="button"
|
||||
class="w-8 h-8 bg-white inline-flex items-center justify-center text-grey-400 rounded-full hover:text-grey-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-purple-500"
|
||||
>
|
||||
<span class="sr-only">Open options</span>
|
||||
|
||||
<icon
|
||||
name="more"
|
||||
class="block w-6 h-6 text-grey-300 fill-current cursor-pointer outline-none"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
</button>
|
||||
|
||||
<transition
|
||||
enter-active-class="transition ease-out duration-100"
|
||||
enter-class="transform opacity-0 scale-95"
|
||||
enter-to-class="transform opacity-100 scale-100"
|
||||
leave-active-class="transition ease-in duration-75"
|
||||
leave-class="transform opacity-100 scale-100"
|
||||
leave-to-class="transform opacity-0 scale-95"
|
||||
>
|
||||
<div
|
||||
v-show="isOpen"
|
||||
class="mx-3 origin-top-right absolute right-7 top-0 w-48 mt-1 rounded-md shadow-lg z-10 bg-white ring-1 ring-black ring-opacity-5 divide-y divide-grey-200"
|
||||
role="menu"
|
||||
aria-orientation="vertical"
|
||||
aria-labelledby="project-options-menu-0"
|
||||
>
|
||||
<slot></slot>
|
||||
</div>
|
||||
</transition>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
isOpen: false,
|
||||
}
|
||||
},
|
||||
created() {
|
||||
window.addEventListener('click', this.close)
|
||||
},
|
||||
|
||||
beforeDestroy() {
|
||||
window.removeEventListener('click', this.close)
|
||||
},
|
||||
|
||||
methods: {
|
||||
close(e) {
|
||||
if (!this.$refs.openOptions.contains(e.target)) {
|
||||
this.isOpen = false
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@@ -1,21 +1,44 @@
|
||||
<template>
|
||||
<span
|
||||
class="relative outline-none cursor-pointer h-6 w-12 rounded-full"
|
||||
<button
|
||||
@click="toggle"
|
||||
role="checkbox"
|
||||
:aria-checked="value.toString()"
|
||||
tabindex="0"
|
||||
@keydown.space.prevent="toggle"
|
||||
type="button"
|
||||
:aria-pressed="value.toString()"
|
||||
:class="this.value ? 'bg-cyan-500' : 'bg-grey-300'"
|
||||
class="relative inline-flex flex-shrink-0 h-6 w-11 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 focus:outline-none"
|
||||
>
|
||||
<span class="sr-only">Use setting</span>
|
||||
<span
|
||||
class="toggle-background inline-block rounded-full h-full w-full shadow-inner"
|
||||
:class="this.value ? 'bg-cyan-500' : 'bg-grey-300'"
|
||||
></span>
|
||||
<span
|
||||
class="toggle-indicator absolute bg-white rounded-full shadow w-4 h-4"
|
||||
:style="indicatorStyles"
|
||||
></span>
|
||||
</span>
|
||||
:class="this.value ? 'translate-x-5' : 'translate-x-0'"
|
||||
class="relative inline-block h-5 w-5 rounded-full bg-white shadow transform ring-0 transition ease-in-out duration-200"
|
||||
>
|
||||
<span
|
||||
:class="this.value ? 'opacity-0 ease-out duration-100' : 'opacity-100 ease-in duration-200'"
|
||||
class="absolute inset-0 h-full w-full flex items-center justify-center transition-opacity"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<svg class="h-3 w-3 text-grey-400" fill="none" viewBox="0 0 12 12">
|
||||
<path
|
||||
d="M4 8l2-2m0 0l2-2M6 6L4 4m2 2l2 2"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
<span
|
||||
:class="this.value ? 'opacity-100 ease-in duration-200' : 'opacity-0 ease-out duration-100'"
|
||||
class="absolute inset-0 h-full w-full flex items-center justify-center transition-opacity"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<svg class="h-3 w-3 text-cyan-500" fill="currentColor" viewBox="0 0 12 12">
|
||||
<path
|
||||
d="M3.707 5.293a1 1 0 00-1.414 1.414l1.414-1.414zM5 8l-.707.707a1 1 0 001.414 0L5 8zm4.707-3.293a1 1 0 00-1.414-1.414l1.414 1.414zm-7.414 2l2 2 1.414-1.414-2-2-1.414 1.414zm3.414 2l4-4-1.414-1.414-4 4 1.414 1.414z"
|
||||
/>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@@ -27,22 +50,5 @@ export default {
|
||||
this.value ? this.$emit('off') : this.$emit('on')
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
indicatorStyles() {
|
||||
return { transform: this.value ? 'translateX(1.5rem)' : 'translateX(0)' }
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.toggle-background {
|
||||
transition: background-color 0.2s ease;
|
||||
}
|
||||
|
||||
.toggle-indicator {
|
||||
top: 0.25rem;
|
||||
left: 0.25rem;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="mt-6">
|
||||
<h3 class="font-bold text-xl">
|
||||
Device Authentication (U2F)
|
||||
</h3>
|
||||
<h3 class="font-bold text-xl">Device Authentication (U2F)</h3>
|
||||
|
||||
<div class="my-4 w-24 border-b-2 border-grey-200"></div>
|
||||
|
||||
@@ -13,9 +11,7 @@
|
||||
</p>
|
||||
|
||||
<div>
|
||||
<p class="mb-0" v-if="keys.length === 0">
|
||||
You have not registered any Webauthn Keys.
|
||||
</p>
|
||||
<p class="mb-0" v-if="keys.length === 0">You have not registered any Webauthn Keys.</p>
|
||||
|
||||
<div class="table w-full text-sm md:text-base" v-if="keys.length > 0">
|
||||
<div class="table-row">
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<h3 class="font-bold text-xl">
|
||||
Information
|
||||
</h3>
|
||||
<h3 class="font-bold text-xl">Information</h3>
|
||||
|
||||
<div class="mt-4 w-24 border-b-2 border-grey-200"></div>
|
||||
|
||||
@@ -44,9 +42,7 @@
|
||||
</button>
|
||||
|
||||
<div class="mt-6">
|
||||
<h3 class="font-bold text-xl">
|
||||
Personal Access Tokens
|
||||
</h3>
|
||||
<h3 class="font-bold text-xl">Personal Access Tokens</h3>
|
||||
|
||||
<div class="my-4 w-24 border-b-2 border-grey-200"></div>
|
||||
|
||||
@@ -106,9 +102,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<label for="create-token-name" class="block text-grey-700 text-sm my-2">
|
||||
Name:
|
||||
</label>
|
||||
<label for="create-token-name" class="block text-grey-700 text-sm my-2"> Name: </label>
|
||||
<input
|
||||
v-model="form.name"
|
||||
type="text"
|
||||
|
||||
@@ -11,9 +11,7 @@
|
||||
/>
|
||||
<div class="font-bold text-xl md:text-3xl text-indigo-800">
|
||||
{{ totalActive }}
|
||||
<p class="text-grey-300 text-sm tracking-wide uppercase">
|
||||
Active
|
||||
</p>
|
||||
<p class="text-grey-300 text-sm tracking-wide uppercase">Active</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -27,9 +25,7 @@
|
||||
/>
|
||||
<div class="font-bold text-xl md:text-3xl text-indigo-800">
|
||||
{{ totalInactive }}
|
||||
<p class="text-grey-300 text-sm tracking-wide uppercase">
|
||||
Inactive
|
||||
</p>
|
||||
<p class="text-grey-300 text-sm tracking-wide uppercase">Inactive</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -43,9 +39,7 @@
|
||||
/>
|
||||
<div class="font-bold text-xl md:text-3xl text-indigo-800">
|
||||
{{ totalForwarded }}
|
||||
<p class="text-grey-300 text-sm tracking-wide uppercase">
|
||||
Emails Forwarded
|
||||
</p>
|
||||
<p class="text-grey-300 text-sm tracking-wide uppercase">Emails Forwarded</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -59,9 +53,7 @@
|
||||
/>
|
||||
<div class="font-bold text-xl md:text-3xl text-indigo-800">
|
||||
{{ totalBlocked }}
|
||||
<p class="text-grey-300 text-sm tracking-wide uppercase">
|
||||
Emails Blocked
|
||||
</p>
|
||||
<p class="text-grey-300 text-sm tracking-wide uppercase">Emails Blocked</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -75,9 +67,7 @@
|
||||
/>
|
||||
<div class="font-bold text-xl md:text-3xl text-indigo-800">
|
||||
{{ totalReplies }}
|
||||
<p class="text-grey-300 text-sm tracking-wide uppercase">
|
||||
Email Replies
|
||||
</p>
|
||||
<p class="text-grey-300 text-sm tracking-wide uppercase">Email Replies</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -122,7 +112,7 @@
|
||||
<div class="block relative mr-4">
|
||||
<select
|
||||
v-model="showAliases"
|
||||
class="block appearance-none w-full text-grey-700 bg-white p-3 pr-8 rounded shadow focus:shadow-outline"
|
||||
class="block appearance-none w-full text-grey-700 bg-white p-3 pr-8 rounded shadow focus:ring"
|
||||
required
|
||||
>
|
||||
<option value="without">Hide Deleted</option>
|
||||
@@ -148,7 +138,7 @@
|
||||
@click="generateAliasModalOpen = true"
|
||||
class="bg-cyan-400 hover:bg-cyan-300 text-cyan-900 font-bold py-3 px-4 rounded focus:outline-none ml-auto"
|
||||
>
|
||||
Generate New Alias
|
||||
Create New Alias
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -182,11 +172,23 @@
|
||||
No aliases found for that search!
|
||||
</div>
|
||||
<template slot="table-row" slot-scope="props">
|
||||
<span
|
||||
v-if="props.column.field == 'created_at'"
|
||||
class="tooltip outline-none text-sm"
|
||||
:data-tippy-content="rows[props.row.originalIndex].created_at | formatDate"
|
||||
>{{ props.row.created_at | timeAgo }}
|
||||
<span v-if="props.column.field == 'created_at'" class="flex items-center">
|
||||
<span
|
||||
:class="`bg-${getAliasStatus(props.row).colour}-100`"
|
||||
class="tooltip outline-none h-4 w-4 rounded-full flex items-center justify-center mr-2"
|
||||
:data-tippy-content="getAliasStatus(props.row).status"
|
||||
tabindex="-1"
|
||||
>
|
||||
<span
|
||||
:class="`bg-${getAliasStatus(props.row).colour}-400`"
|
||||
class="h-2 w-2 rounded-full"
|
||||
></span>
|
||||
</span>
|
||||
<span
|
||||
class="tooltip outline-none text-sm whitespace-nowrap"
|
||||
:data-tippy-content="rows[props.row.originalIndex].created_at | formatDate"
|
||||
>{{ props.row.created_at | timeAgo }}
|
||||
</span>
|
||||
</span>
|
||||
<span v-else-if="props.column.field == 'email'" class="block">
|
||||
<span
|
||||
@@ -306,18 +308,44 @@
|
||||
/>
|
||||
</span>
|
||||
<span v-else class="flex items-center justify-center outline-none" tabindex="-1">
|
||||
<icon
|
||||
v-if="props.row.deleted_at"
|
||||
name="undo"
|
||||
class="block w-6 h-6 text-grey-300 fill-current cursor-pointer outline-none"
|
||||
@click.native="openRestoreModal(props.row.id)"
|
||||
/>
|
||||
<icon
|
||||
v-else
|
||||
name="trash"
|
||||
class="block w-6 h-6 text-grey-300 fill-current cursor-pointer outline-none"
|
||||
@click.native="openDeleteModal(props.row.id)"
|
||||
/>
|
||||
<more-options>
|
||||
<div role="none">
|
||||
<span
|
||||
@click="openSendFromModal(props.row)"
|
||||
class="group cursor-pointer flex items-center px-4 py-3 text-sm text-grey-700 hover:bg-grey-100 hover:text-grey-900"
|
||||
role="menuitem"
|
||||
>
|
||||
<icon name="send" class="block mr-3 w-5 h-5 text-grey-300 outline-none" />
|
||||
Send From
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="props.row.deleted_at" role="none">
|
||||
<span
|
||||
@click="openRestoreModal(props.row.id)"
|
||||
class="group cursor-pointer flex items-center px-4 py-3 text-sm text-grey-700 hover:bg-grey-100 hover:text-grey-900"
|
||||
role="menuitem"
|
||||
>
|
||||
<icon
|
||||
name="undo"
|
||||
class="block mr-3 w-5 h-5 text-grey-300 fill-current outline-none"
|
||||
/>
|
||||
Restore
|
||||
</span>
|
||||
</div>
|
||||
<div v-else role="none">
|
||||
<span
|
||||
@click="openDeleteModal(props.row.id)"
|
||||
class="group cursor-pointer flex items-center px-4 py-3 text-sm text-grey-700 hover:bg-grey-100 hover:text-grey-900"
|
||||
role="menuitem"
|
||||
>
|
||||
<icon
|
||||
name="trash"
|
||||
class="block mr-3 w-5 h-5 text-grey-300 fill-current outline-none"
|
||||
/>
|
||||
Delete
|
||||
</span>
|
||||
</div>
|
||||
</more-options>
|
||||
</span>
|
||||
</template>
|
||||
</vue-good-table>
|
||||
@@ -328,9 +356,7 @@
|
||||
It doesn't look like you have any aliases yet!
|
||||
</h1>
|
||||
<div class="mx-auto mb-6 w-24 border-b-2 border-grey-200"></div>
|
||||
<p class="mb-4">
|
||||
There are two ways to create new aliases.
|
||||
</p>
|
||||
<p class="mb-4">There are two ways to create new aliases.</p>
|
||||
<h3 class="mb-4 text-xl text-indigo-800 font-semibold">
|
||||
Option 1: Create aliases on the fly
|
||||
</h3>
|
||||
@@ -375,28 +401,23 @@
|
||||
<h2
|
||||
class="font-semibold text-grey-900 text-2xl leading-tight border-b-2 border-grey-100 pb-4"
|
||||
>
|
||||
Generate new alias
|
||||
Create new alias
|
||||
</h2>
|
||||
<p class="mt-4 text-grey-700">
|
||||
Other aliases e.g. alias@{{ subdomain }} can also be created automatically when they
|
||||
receive their first email.
|
||||
</p>
|
||||
<label for="alias_domain" class="block text-grey-700 text-sm my-2">
|
||||
Alias Domain:
|
||||
</label>
|
||||
<label for="alias_domain" class="block text-grey-700 text-sm my-2"> Alias Domain: </label>
|
||||
<div class="block relative w-full mb-4">
|
||||
<select
|
||||
v-model="generateAliasDomain"
|
||||
id="alias_domain"
|
||||
class="block appearance-none w-full text-grey-700 bg-grey-100 p-3 pr-8 rounded shadow focus:shadow-outline"
|
||||
class="block appearance-none w-full text-grey-700 bg-grey-100 p-3 pr-8 rounded shadow focus:ring"
|
||||
required
|
||||
>
|
||||
<option
|
||||
v-for="domainOption in domainOptions"
|
||||
:key="domainOption"
|
||||
:value="domainOption"
|
||||
>{{ domainOption }}</option
|
||||
>
|
||||
<option v-for="domainOption in domainOptions" :key="domainOption" :value="domainOption">
|
||||
{{ domainOption }}
|
||||
</option>
|
||||
</select>
|
||||
<div
|
||||
class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700"
|
||||
@@ -420,15 +441,16 @@
|
||||
<select
|
||||
v-model="generateAliasFormat"
|
||||
id="alias_domain"
|
||||
class="block appearance-none w-full text-grey-700 bg-grey-100 p-3 pr-8 rounded shadow focus:shadow-outline"
|
||||
class="block appearance-none w-full text-grey-700 bg-grey-100 p-3 pr-8 rounded shadow focus:ring"
|
||||
required
|
||||
>
|
||||
<option
|
||||
v-for="formatOption in aliasFormatOptions"
|
||||
:key="formatOption.value"
|
||||
:value="formatOption.value"
|
||||
>{{ formatOption.label }}</option
|
||||
>
|
||||
{{ formatOption.label }}
|
||||
</option>
|
||||
</select>
|
||||
<div
|
||||
class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700"
|
||||
@@ -486,7 +508,7 @@
|
||||
:class="generateAliasLoading ? 'cursor-not-allowed' : ''"
|
||||
:disabled="generateAliasLoading"
|
||||
>
|
||||
Generate Alias
|
||||
Create Alias
|
||||
<loader v-if="generateAliasLoading" />
|
||||
</button>
|
||||
<button
|
||||
@@ -609,12 +631,114 @@
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
<Modal :open="sendFromAliasModalOpen" @close="closeSendFromModal">
|
||||
<div class="max-w-lg w-full bg-white rounded-lg shadow-2xl px-6 py-6">
|
||||
<h2
|
||||
class="font-semibold text-grey-900 text-2xl leading-tight border-b-2 border-grey-100 pb-4"
|
||||
>
|
||||
Send from alias
|
||||
</h2>
|
||||
<p class="mt-4 text-grey-700">
|
||||
Use this to automatically create the correct address to send an email to in order to send
|
||||
an <b>email from this alias</b>.
|
||||
</p>
|
||||
<label for="send_from_alias" class="block text-grey-700 text-sm my-2"> Alias: </label>
|
||||
<input
|
||||
v-model="aliasToSendFrom.email"
|
||||
id="send_from_alias"
|
||||
type="text"
|
||||
class="w-full appearance-none bg-grey-100 border border-transparent text-grey-700 focus:outline-none rounded p-3"
|
||||
disabled
|
||||
/>
|
||||
<label for="send_from_alias_destination" class="block text-grey-700 text-sm my-2">
|
||||
Email destination:
|
||||
</label>
|
||||
<p v-show="errors.sendFromAliasDestination" class="mb-3 text-red-500 text-sm">
|
||||
{{ errors.sendFromAliasDestination }}
|
||||
</p>
|
||||
<input
|
||||
v-model="sendFromAliasDestination"
|
||||
id="send_from_alias_destination"
|
||||
type="text"
|
||||
class="w-full appearance-none bg-grey-100 border border-transparent text-grey-700 focus:outline-none rounded p-3"
|
||||
:class="errors.sendFromAliasDestination ? 'border-red-500' : ''"
|
||||
placeholder="Enter email..."
|
||||
autofocus
|
||||
/>
|
||||
<div v-if="sendFromAliasEmailToSendTo">
|
||||
<p for="alias_domain" class="block text-grey-700 text-sm my-2">
|
||||
Send your message to this email:
|
||||
</p>
|
||||
<div
|
||||
v-clipboard="() => sendFromAliasEmailToSendTo"
|
||||
v-clipboard:success="setSendFromAliasCopied"
|
||||
class="flex items-center justify-between cursor-pointer text-xs border-t-4 rounded-sm text-green-800 border-green-600 bg-green-100 p-2 mb-3"
|
||||
role="alert"
|
||||
>
|
||||
<span>
|
||||
{{ sendFromAliasEmailToSendTo }}
|
||||
</span>
|
||||
<svg
|
||||
v-if="sendFromAliasCopied"
|
||||
viewBox="0 0 24 24"
|
||||
width="20"
|
||||
height="20"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
fill="none"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<polyline points="9 11 12 14 22 4"></polyline>
|
||||
<path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"></path>
|
||||
</svg>
|
||||
<svg
|
||||
v-else
|
||||
viewBox="0 0 24 24"
|
||||
width="20"
|
||||
height="20"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
fill="none"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
|
||||
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-6">
|
||||
<button
|
||||
type="button"
|
||||
@click="displaySendFromAddress(aliasToSendFrom)"
|
||||
class="px-4 py-3 text-cyan-900 font-semibold bg-cyan-400 hover:bg-cyan-300 border border-transparent rounded focus:outline-none"
|
||||
:class="sendFromAliasLoading ? 'cursor-not-allowed' : ''"
|
||||
:disabled="sendFromAliasLoading"
|
||||
>
|
||||
Show address
|
||||
<loader v-if="sendFromAliasLoading" />
|
||||
</button>
|
||||
<button
|
||||
@click="closeSendFromModal"
|
||||
class="ml-4 px-4 py-3 text-grey-800 font-semibold bg-white hover:bg-grey-50 border border-grey-100 rounded focus:outline-none"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Modal from './../components/Modal.vue'
|
||||
import Toggle from './../components/Toggle.vue'
|
||||
import MoreOptions from './../components/MoreOptions.vue'
|
||||
import { roundArrow } from 'tippy.js'
|
||||
import 'tippy.js/dist/svg-arrow.css'
|
||||
import 'tippy.js/dist/tippy.css'
|
||||
import tippy from 'tippy.js'
|
||||
import Multiselect from 'vue-multiselect'
|
||||
|
||||
@@ -677,9 +801,7 @@ export default {
|
||||
Modal,
|
||||
Toggle,
|
||||
Multiselect,
|
||||
},
|
||||
mounted() {
|
||||
this.addTooltips()
|
||||
MoreOptions,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -688,9 +810,15 @@ export default {
|
||||
aliasIdToEdit: '',
|
||||
aliasDescriptionToEdit: '',
|
||||
aliasIdToDelete: '',
|
||||
aliasToSendFrom: {},
|
||||
sendFromAliasDestination: '',
|
||||
sendFromAliasEmailToSendTo: '',
|
||||
sendFromAliasCopied: false,
|
||||
aliasIdToRestore: '',
|
||||
deleteAliasLoading: false,
|
||||
deleteAliasModalOpen: false,
|
||||
sendFromAliasLoading: false,
|
||||
sendFromAliasModalOpen: false,
|
||||
restoreAliasLoading: false,
|
||||
restoreAliasModalOpen: false,
|
||||
editAliasRecipientsLoading: false,
|
||||
@@ -776,16 +904,11 @@ export default {
|
||||
},
|
||||
],
|
||||
rows: this.initialAliases,
|
||||
tippyInstance: null,
|
||||
errors: {},
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
aliasIdToEdit: _.debounce(function() {
|
||||
this.addTooltips()
|
||||
}, 50),
|
||||
editAliasRecipientsModalOpen: _.debounce(function() {
|
||||
this.addTooltips()
|
||||
}, 50),
|
||||
showAliases(value) {
|
||||
this.updateAliases()
|
||||
},
|
||||
@@ -803,12 +926,16 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
addTooltips() {
|
||||
tippy('.tooltip', {
|
||||
arrow: true,
|
||||
arrowType: 'round',
|
||||
if (this.tippyInstance) {
|
||||
_.each(this.tippyInstance, instance => instance.destroy())
|
||||
}
|
||||
|
||||
this.tippyInstance = tippy('.tooltip', {
|
||||
arrow: roundArrow,
|
||||
allowHTML: true,
|
||||
})
|
||||
},
|
||||
debounceToolips: _.debounce(function() {
|
||||
debounceToolips: _.debounce(function () {
|
||||
this.addTooltips()
|
||||
}, 50),
|
||||
recipientsTooltip(recipients) {
|
||||
@@ -822,6 +949,17 @@ export default {
|
||||
this.deleteAliasModalOpen = false
|
||||
this.aliasIdToDelete = ''
|
||||
},
|
||||
openSendFromModal(alias) {
|
||||
this.sendFromAliasDestination = ''
|
||||
this.sendFromAliasEmailToSendTo = ''
|
||||
this.sendFromAliasCopied = false
|
||||
this.sendFromAliasModalOpen = true
|
||||
this.aliasToSendFrom = alias
|
||||
},
|
||||
closeSendFromModal() {
|
||||
this.sendFromAliasModalOpen = false
|
||||
this.aliasToSendFrom = {}
|
||||
},
|
||||
openRestoreModal(id) {
|
||||
this.restoreAliasModalOpen = true
|
||||
this.aliasIdToRestore = id
|
||||
@@ -1021,6 +1159,21 @@ export default {
|
||||
this.error()
|
||||
})
|
||||
},
|
||||
displaySendFromAddress(alias) {
|
||||
this.errors = {}
|
||||
|
||||
if (!this.validEmail(this.sendFromAliasDestination)) {
|
||||
this.errors.sendFromAliasDestination = 'Valid Email required'
|
||||
return
|
||||
}
|
||||
|
||||
this.sendFromAliasEmailToSendTo = `${
|
||||
alias.local_part
|
||||
}+${this.sendFromAliasDestination.replace('@', '=')}@${alias.domain}`
|
||||
},
|
||||
setSendFromAliasCopied() {
|
||||
this.sendFromAliasCopied = true
|
||||
},
|
||||
getAliasEmail(alias) {
|
||||
return alias.extension
|
||||
? `${alias.local_part}+${alias.extension}@${alias.domain}`
|
||||
@@ -1029,6 +1182,19 @@ export default {
|
||||
getAliasLocalPart(alias) {
|
||||
return alias.extension ? `${alias.local_part}+${alias.extension}` : alias.local_part
|
||||
},
|
||||
getAliasStatus(alias) {
|
||||
if (alias.deleted_at) {
|
||||
return {
|
||||
colour: 'red',
|
||||
status: 'Deleted',
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
colour: alias.active ? 'green' : 'grey',
|
||||
status: alias.active ? 'Active' : 'Inactive',
|
||||
}
|
||||
}
|
||||
},
|
||||
sortRecipients(x, y) {
|
||||
return x.length < y.length ? -1 : x.length > y.length ? 1 : 0
|
||||
},
|
||||
@@ -1039,6 +1205,10 @@ export default {
|
||||
let re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))$/
|
||||
return re.test(part)
|
||||
},
|
||||
validEmail(email) {
|
||||
let re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
|
||||
return re.test(email)
|
||||
},
|
||||
clipboardSuccess() {
|
||||
this.success('Copied to clipboard')
|
||||
},
|
||||
|
||||
@@ -186,9 +186,7 @@
|
||||
To get started all you have to do is add a TXT record to your domain to verify ownership
|
||||
and then add the domain here by clicking the button above.
|
||||
</p>
|
||||
<p class="mb-4">
|
||||
The TXT record needs to have the following values:
|
||||
</p>
|
||||
<p class="mb-4">The TXT record needs to have the following values:</p>
|
||||
<p class="mb-4">
|
||||
Type: <b>TXT</b><br />
|
||||
Host: <b>@</b><br />
|
||||
@@ -396,6 +394,9 @@
|
||||
<script>
|
||||
import Modal from './../components/Modal.vue'
|
||||
import Toggle from './../components/Toggle.vue'
|
||||
import { roundArrow } from 'tippy.js'
|
||||
import 'tippy.js/dist/svg-arrow.css'
|
||||
import 'tippy.js/dist/tippy.css'
|
||||
import tippy from 'tippy.js'
|
||||
import Multiselect from 'vue-multiselect'
|
||||
|
||||
@@ -427,9 +428,6 @@ export default {
|
||||
Toggle,
|
||||
Multiselect,
|
||||
},
|
||||
mounted() {
|
||||
this.addTooltips()
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
newDomain: '',
|
||||
@@ -499,21 +497,26 @@ export default {
|
||||
},
|
||||
],
|
||||
rows: this.initialDomains,
|
||||
tippyInstance: null,
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
domainIdToEdit: _.debounce(function() {
|
||||
domainIdToEdit: _.debounce(function () {
|
||||
this.addTooltips()
|
||||
}, 50),
|
||||
},
|
||||
methods: {
|
||||
addTooltips() {
|
||||
tippy('.tooltip', {
|
||||
arrow: true,
|
||||
arrowType: 'round',
|
||||
if (this.tippyInstance) {
|
||||
_.each(this.tippyInstance, instance => instance.destroy())
|
||||
}
|
||||
|
||||
this.tippyInstance = tippy('.tooltip', {
|
||||
arrow: roundArrow,
|
||||
allowHTML: true,
|
||||
})
|
||||
},
|
||||
debounceToolips: _.debounce(function() {
|
||||
debounceToolips: _.debounce(function () {
|
||||
this.addTooltips()
|
||||
}, 50),
|
||||
validateNewDomain(e) {
|
||||
|
||||
@@ -55,13 +55,7 @@
|
||||
Key
|
||||
<span
|
||||
class="tooltip outline-none"
|
||||
:data-tippy-content="
|
||||
`Use this to attach recipients to new aliases as they are created e.g. alias+key@${
|
||||
user.username
|
||||
}.anonaddy.com. You can attach multiple recipients by doing alias+2.3.4@${
|
||||
user.username
|
||||
}.anonaddy.com. Separating each key by a full stop.`
|
||||
"
|
||||
:data-tippy-content="`Use this to attach recipients to new aliases as they are created e.g. alias+key@${user.username}.anonaddy.com. You can attach multiple recipients by doing alias+2.3.4@${user.username}.anonaddy.com. Separating each key by a full stop.`"
|
||||
>
|
||||
<icon name="info" class="inline-block w-4 h-4 text-grey-300 fill-current" />
|
||||
</span>
|
||||
@@ -328,6 +322,9 @@
|
||||
<script>
|
||||
import Modal from './../components/Modal.vue'
|
||||
import Toggle from './../components/Toggle.vue'
|
||||
import { roundArrow } from 'tippy.js'
|
||||
import 'tippy.js/dist/svg-arrow.css'
|
||||
import 'tippy.js/dist/tippy.css'
|
||||
import tippy from 'tippy.js'
|
||||
|
||||
export default {
|
||||
@@ -361,9 +358,6 @@ export default {
|
||||
this.defaultRecipient = _.find(this.rows, ['id', this.user.default_recipient_id])
|
||||
this.defaultRecipient.aliases = this.defaultRecipient.aliases.concat(this.aliasesUsingDefault)
|
||||
},
|
||||
mounted() {
|
||||
this.addTooltips()
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
defaultRecipient: {},
|
||||
@@ -424,21 +418,26 @@ export default {
|
||||
},
|
||||
],
|
||||
rows: this.initialRecipients,
|
||||
tippyInstance: null,
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
addRecipientKeyModalOpen: _.debounce(function() {
|
||||
addRecipientKeyModalOpen: _.debounce(function () {
|
||||
this.addTooltips()
|
||||
}, 50),
|
||||
},
|
||||
methods: {
|
||||
addTooltips() {
|
||||
tippy('.tooltip', {
|
||||
arrow: true,
|
||||
arrowType: 'round',
|
||||
if (this.tippyInstance) {
|
||||
_.each(this.tippyInstance, instance => instance.destroy())
|
||||
}
|
||||
|
||||
this.tippyInstance = tippy('.tooltip', {
|
||||
arrow: roundArrow,
|
||||
allowHTML: true,
|
||||
})
|
||||
},
|
||||
debounceToolips: _.debounce(function() {
|
||||
debounceToolips: _.debounce(function () {
|
||||
this.addTooltips()
|
||||
}, 50),
|
||||
aliasesTooltip(aliases, isDefault) {
|
||||
@@ -618,9 +617,7 @@ export default {
|
||||
this.recipientKey = ''
|
||||
this.addRecipientKeyModalOpen = false
|
||||
this.success(
|
||||
`Key Successfully Added for ${
|
||||
this.recipientToAddKey.email
|
||||
}. Make sure to check the fingerprint is correct!`
|
||||
`Key Successfully Added for ${this.recipientToAddKey.email}. Make sure to check the fingerprint is correct!`
|
||||
)
|
||||
})
|
||||
.catch(error => {
|
||||
|
||||
@@ -67,9 +67,7 @@
|
||||
It doesn't look like you have any rules yet!
|
||||
</h1>
|
||||
<div class="mx-auto mb-6 w-24 border-b-2 border-grey-200"></div>
|
||||
<p class="mb-4">
|
||||
Click the button above to create a new rule.
|
||||
</p>
|
||||
<p class="mb-4">Click the button above to create a new rule.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -85,9 +83,7 @@
|
||||
actions will be added over time.
|
||||
</p>
|
||||
|
||||
<label for="rule_name" class="block text-grey-700 text-sm my-2">
|
||||
Name:
|
||||
</label>
|
||||
<label for="rule_name" class="block text-grey-700 text-sm my-2"> Name: </label>
|
||||
<p v-show="errors.ruleName" class="mb-3 text-red-500 text-sm">
|
||||
{{ errors.ruleName }}
|
||||
</p>
|
||||
@@ -112,11 +108,11 @@
|
||||
<select
|
||||
v-model="createRuleObject.operator"
|
||||
id="rule_operator"
|
||||
class="block appearance-none w-full text-grey-700 bg-white p-2 pr-6 rounded shadow focus:shadow-outline"
|
||||
class="block appearance-none w-full text-grey-700 bg-white p-2 pr-6 rounded shadow focus:ring"
|
||||
required
|
||||
>
|
||||
<option value="AND">AND </option>
|
||||
<option value="OR">OR </option>
|
||||
<option value="AND">AND</option>
|
||||
<option value="OR">OR</option>
|
||||
</select>
|
||||
<div
|
||||
class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700"
|
||||
@@ -143,14 +139,15 @@
|
||||
<select
|
||||
v-model="createRuleObject.conditions[key].type"
|
||||
id="rule_condition_types"
|
||||
class="block appearance-none w-32 text-grey-700 bg-white p-2 pr-6 rounded shadow focus:shadow-outline"
|
||||
class="block appearance-none w-32 text-grey-700 bg-white p-2 pr-6 rounded shadow focus:ring"
|
||||
required
|
||||
>
|
||||
<option
|
||||
v-for="option in conditionTypeOptions"
|
||||
:key="option.value"
|
||||
:value="option.value"
|
||||
>{{ option.label }}
|
||||
>
|
||||
{{ option.label }}
|
||||
</option>
|
||||
</select>
|
||||
<div
|
||||
@@ -177,14 +174,15 @@
|
||||
<select
|
||||
v-model="createRuleObject.conditions[key].match"
|
||||
id="rule_condition_matches"
|
||||
class="block appearance-none w-40 text-grey-700 bg-white p-2 pr-6 rounded shadow focus:shadow-outline"
|
||||
class="block appearance-none w-40 text-grey-700 bg-white p-2 pr-6 rounded shadow focus:ring"
|
||||
required
|
||||
>
|
||||
<option
|
||||
v-for="option in conditionMatchOptions(createRuleObject, key)"
|
||||
:key="option"
|
||||
:value="option"
|
||||
>{{ option }}
|
||||
>
|
||||
{{ option }}
|
||||
</option>
|
||||
</select>
|
||||
<div
|
||||
@@ -275,9 +273,7 @@
|
||||
<div v-for="(action, key) in createRuleObject.actions" :key="key">
|
||||
<!-- AND/OR operator -->
|
||||
<div v-if="key !== 0" class="flex justify-center my-2">
|
||||
<div class="relative">
|
||||
AND
|
||||
</div>
|
||||
<div class="relative">AND</div>
|
||||
</div>
|
||||
|
||||
<div class="p-2 w-full bg-grey-100">
|
||||
@@ -290,14 +286,15 @@
|
||||
v-model="createRuleObject.actions[key].type"
|
||||
@change="ruleActionChange(createRuleObject.actions[key])"
|
||||
id="rule_action_types"
|
||||
class="block appearance-none text-grey-700 bg-white p-2 pr-6 rounded shadow focus:shadow-outline"
|
||||
class="block appearance-none text-grey-700 bg-white p-2 pr-6 rounded shadow focus:ring"
|
||||
required
|
||||
>
|
||||
<option
|
||||
v-for="option in actionTypeOptions"
|
||||
:key="option.value"
|
||||
:value="option.value"
|
||||
>{{ option.label }}
|
||||
>
|
||||
{{ option.label }}
|
||||
</option>
|
||||
</select>
|
||||
<div
|
||||
@@ -319,7 +316,7 @@
|
||||
<span
|
||||
v-if="
|
||||
createRuleObject.actions[key].type === 'subject' ||
|
||||
createRuleObject.actions[key].type === 'displayFrom'
|
||||
createRuleObject.actions[key].type === 'displayFrom'
|
||||
"
|
||||
class="ml-4 flex"
|
||||
>
|
||||
@@ -343,12 +340,12 @@
|
||||
<select
|
||||
v-model="createRuleObject.actions[key].value"
|
||||
id="create_rule_action_banner"
|
||||
class="block appearance-none w-40 text-grey-700 bg-white p-2 pr-6 rounded shadow focus:shadow-outline"
|
||||
class="block appearance-none w-40 text-grey-700 bg-white p-2 pr-6 rounded shadow focus:ring"
|
||||
required
|
||||
>
|
||||
<option selected value="top">Top </option>
|
||||
<option selected value="bottom">Bottom </option>
|
||||
<option selected value="off">Off </option>
|
||||
<option selected value="top">Top</option>
|
||||
<option selected value="bottom">Bottom</option>
|
||||
<option selected value="off">Off</option>
|
||||
</select>
|
||||
<div
|
||||
class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700"
|
||||
@@ -423,9 +420,7 @@
|
||||
actions will be added over time.
|
||||
</p>
|
||||
|
||||
<label for="edit_rule_name" class="block text-grey-700 text-sm my-2">
|
||||
Name:
|
||||
</label>
|
||||
<label for="edit_rule_name" class="block text-grey-700 text-sm my-2"> Name: </label>
|
||||
<p v-show="errors.ruleName" class="mb-3 text-red-500 text-sm">
|
||||
{{ errors.ruleName }}
|
||||
</p>
|
||||
@@ -450,11 +445,11 @@
|
||||
<select
|
||||
v-model="editRuleObject.operator"
|
||||
id="edit_rule_operator"
|
||||
class="block appearance-none w-full text-grey-700 bg-white p-2 pr-6 rounded shadow focus:shadow-outline"
|
||||
class="block appearance-none w-full text-grey-700 bg-white p-2 pr-6 rounded shadow focus:ring"
|
||||
required
|
||||
>
|
||||
<option value="AND">AND </option>
|
||||
<option value="OR">OR </option>
|
||||
<option value="AND">AND</option>
|
||||
<option value="OR">OR</option>
|
||||
</select>
|
||||
<div
|
||||
class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700"
|
||||
@@ -481,14 +476,15 @@
|
||||
<select
|
||||
v-model="editRuleObject.conditions[key].type"
|
||||
id="edit_rule_condition_types"
|
||||
class="block appearance-none w-32 text-grey-700 bg-white p-2 pr-6 rounded shadow focus:shadow-outline"
|
||||
class="block appearance-none w-32 text-grey-700 bg-white p-2 pr-6 rounded shadow focus:ring"
|
||||
required
|
||||
>
|
||||
<option
|
||||
v-for="option in conditionTypeOptions"
|
||||
:key="option.value"
|
||||
:value="option.value"
|
||||
>{{ option.label }}
|
||||
>
|
||||
{{ option.label }}
|
||||
</option>
|
||||
</select>
|
||||
<div
|
||||
@@ -512,14 +508,15 @@
|
||||
<select
|
||||
v-model="editRuleObject.conditions[key].match"
|
||||
id="edit_rule_condition_matches"
|
||||
class="block appearance-none w-40 text-grey-700 bg-white p-2 pr-6 rounded shadow focus:shadow-outline"
|
||||
class="block appearance-none w-40 text-grey-700 bg-white p-2 pr-6 rounded shadow focus:ring"
|
||||
required
|
||||
>
|
||||
<option
|
||||
v-for="option in conditionMatchOptions(editRuleObject, key)"
|
||||
:key="option"
|
||||
:value="option"
|
||||
>{{ option }}
|
||||
>
|
||||
{{ option }}
|
||||
</option>
|
||||
</select>
|
||||
<div
|
||||
@@ -607,9 +604,7 @@
|
||||
<div v-for="(action, key) in editRuleObject.actions" :key="key">
|
||||
<!-- AND/OR operator -->
|
||||
<div v-if="key !== 0" class="flex justify-center my-2">
|
||||
<div class="relative">
|
||||
AND
|
||||
</div>
|
||||
<div class="relative">AND</div>
|
||||
</div>
|
||||
|
||||
<div class="p-2 w-full bg-grey-100">
|
||||
@@ -622,14 +617,15 @@
|
||||
v-model="editRuleObject.actions[key].type"
|
||||
@change="ruleActionChange(editRuleObject.actions[key])"
|
||||
id="rule_action_types"
|
||||
class="block appearance-none text-grey-700 bg-white p-2 pr-6 rounded shadow focus:shadow-outline"
|
||||
class="block appearance-none text-grey-700 bg-white p-2 pr-6 rounded shadow focus:ring"
|
||||
required
|
||||
>
|
||||
<option
|
||||
v-for="option in actionTypeOptions"
|
||||
:key="option.value"
|
||||
:value="option.value"
|
||||
>{{ option.label }}
|
||||
>
|
||||
{{ option.label }}
|
||||
</option>
|
||||
</select>
|
||||
<div
|
||||
@@ -651,7 +647,7 @@
|
||||
<span
|
||||
v-if="
|
||||
editRuleObject.actions[key].type === 'subject' ||
|
||||
editRuleObject.actions[key].type === 'displayFrom'
|
||||
editRuleObject.actions[key].type === 'displayFrom'
|
||||
"
|
||||
class="ml-4 flex"
|
||||
>
|
||||
@@ -672,12 +668,12 @@
|
||||
<select
|
||||
v-model="editRuleObject.actions[key].value"
|
||||
id="edit_rule_action_banner"
|
||||
class="block appearance-none w-40 text-grey-700 bg-white p-2 pr-6 rounded shadow focus:shadow-outline"
|
||||
class="block appearance-none w-40 text-grey-700 bg-white p-2 pr-6 rounded shadow focus:ring"
|
||||
required
|
||||
>
|
||||
<option value="top">Top </option>
|
||||
<option value="bottom">Bottom </option>
|
||||
<option value="off">Off </option>
|
||||
<option value="top">Top</option>
|
||||
<option value="bottom">Bottom</option>
|
||||
<option value="off">Off</option>
|
||||
</select>
|
||||
<div
|
||||
class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700"
|
||||
@@ -747,9 +743,7 @@
|
||||
>
|
||||
Delete rule
|
||||
</h2>
|
||||
<p class="mt-4 text-grey-700">
|
||||
Are you sure you want to delete this rule?
|
||||
</p>
|
||||
<p class="mt-4 text-grey-700">Are you sure you want to delete this rule?</p>
|
||||
<div class="mt-6">
|
||||
<button
|
||||
type="button"
|
||||
@@ -776,7 +770,6 @@
|
||||
<script>
|
||||
import Modal from './../components/Modal.vue'
|
||||
import Toggle from './../components/Toggle.vue'
|
||||
import tippy from 'tippy.js'
|
||||
import draggable from 'vuedraggable'
|
||||
|
||||
export default {
|
||||
@@ -791,9 +784,6 @@ export default {
|
||||
Toggle,
|
||||
draggable,
|
||||
},
|
||||
mounted() {
|
||||
this.addTooltips()
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
editRuleObject: {},
|
||||
@@ -869,11 +859,6 @@ export default {
|
||||
errors: {},
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
editRuleObject: _.debounce(function() {
|
||||
this.addTooltips()
|
||||
}, 50),
|
||||
},
|
||||
computed: {
|
||||
activeRules() {
|
||||
return _.filter(this.rows, rule => rule.active)
|
||||
@@ -891,15 +876,6 @@ export default {
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
addTooltips() {
|
||||
tippy('.tooltip', {
|
||||
arrow: true,
|
||||
arrowType: 'round',
|
||||
})
|
||||
},
|
||||
debounceToolips: _.debounce(function() {
|
||||
this.addTooltips()
|
||||
}, 50),
|
||||
openCreateModal() {
|
||||
this.errors = {}
|
||||
this.createRuleModalOpen = true
|
||||
|
||||
@@ -311,6 +311,9 @@
|
||||
<script>
|
||||
import Modal from './../components/Modal.vue'
|
||||
import Toggle from './../components/Toggle.vue'
|
||||
import { roundArrow } from 'tippy.js'
|
||||
import 'tippy.js/dist/svg-arrow.css'
|
||||
import 'tippy.js/dist/tippy.css'
|
||||
import tippy from 'tippy.js'
|
||||
import Multiselect from 'vue-multiselect'
|
||||
|
||||
@@ -334,9 +337,6 @@ export default {
|
||||
Toggle,
|
||||
Multiselect,
|
||||
},
|
||||
mounted() {
|
||||
this.addTooltips()
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
newUsername: '',
|
||||
@@ -399,21 +399,26 @@ export default {
|
||||
},
|
||||
],
|
||||
rows: this.initialUsernames,
|
||||
tippyInstance: null,
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
usernameIdToEdit: _.debounce(function() {
|
||||
usernameIdToEdit: _.debounce(function () {
|
||||
this.addTooltips()
|
||||
}, 50),
|
||||
},
|
||||
methods: {
|
||||
addTooltips() {
|
||||
tippy('.tooltip', {
|
||||
arrow: true,
|
||||
arrowType: 'round',
|
||||
if (this.tippyInstance) {
|
||||
_.each(this.tippyInstance, instance => instance.destroy())
|
||||
}
|
||||
|
||||
this.tippyInstance = tippy('.tooltip', {
|
||||
arrow: roundArrow,
|
||||
allowHTML: true,
|
||||
})
|
||||
},
|
||||
debounceToolips: _.debounce(function() {
|
||||
debounceToolips: _.debounce(function () {
|
||||
this.addTooltips()
|
||||
}, 50),
|
||||
validateNewUsername(e) {
|
||||
|
||||
26
resources/js/webauthn.js
vendored
26
resources/js/webauthn.js
vendored
@@ -27,7 +27,7 @@ function WebAuthn(notifyCallback = null) {
|
||||
* @param {PublicKeyCredentialCreationOptions} publicKey - see https://www.w3.org/TR/webauthn/#dictdef-publickeycredentialcreationoptions
|
||||
* @param {function(PublicKeyCredential)} callback User callback
|
||||
*/
|
||||
WebAuthn.prototype.register = function(publicKey, callback) {
|
||||
WebAuthn.prototype.register = function (publicKey, callback) {
|
||||
let publicKeyCredential = Object.assign({}, publicKey)
|
||||
publicKeyCredential.user.id = this._bufferDecode(publicKey.user.id)
|
||||
publicKeyCredential.challenge = this._bufferDecode(this._base64Decode(publicKey.challenge))
|
||||
@@ -56,7 +56,7 @@ WebAuthn.prototype.register = function(publicKey, callback) {
|
||||
* @param {PublicKeyCredential} publicKey @see https://www.w3.org/TR/webauthn/#publickeycredential
|
||||
* @param {function(PublicKeyCredential)} callback User callback
|
||||
*/
|
||||
WebAuthn.prototype._registerCallback = function(publicKey, callback) {
|
||||
WebAuthn.prototype._registerCallback = function (publicKey, callback) {
|
||||
let publicKeyCredential = {
|
||||
id: publicKey.id,
|
||||
type: publicKey.type,
|
||||
@@ -77,7 +77,7 @@ WebAuthn.prototype._registerCallback = function(publicKey, callback) {
|
||||
* @param {PublicKeyCredentialRequestOptions} publicKey - see https://www.w3.org/TR/webauthn/#dictdef-publickeycredentialrequestoptions
|
||||
* @param {function(PublicKeyCredential)} callback User callback
|
||||
*/
|
||||
WebAuthn.prototype.sign = function(publicKey, callback) {
|
||||
WebAuthn.prototype.sign = function (publicKey, callback) {
|
||||
let publicKeyCredential = Object.assign({}, publicKey)
|
||||
publicKeyCredential.challenge = this._bufferDecode(this._base64Decode(publicKey.challenge))
|
||||
if (publicKey.allowCredentials) {
|
||||
@@ -105,7 +105,7 @@ WebAuthn.prototype.sign = function(publicKey, callback) {
|
||||
* @param {PublicKeyCredential} publicKey @see https://www.w3.org/TR/webauthn/#publickeycredential
|
||||
* @param {function(PublicKeyCredential)} callback User callback
|
||||
*/
|
||||
WebAuthn.prototype._signCallback = function(publicKey, callback) {
|
||||
WebAuthn.prototype._signCallback = function (publicKey, callback) {
|
||||
let publicKeyCredential = {
|
||||
id: publicKey.id,
|
||||
type: publicKey.type,
|
||||
@@ -130,7 +130,7 @@ WebAuthn.prototype._signCallback = function(publicKey, callback) {
|
||||
* @param {ArrayBuffer} value
|
||||
* @return {string}
|
||||
*/
|
||||
WebAuthn.prototype._bufferEncode = function(value) {
|
||||
WebAuthn.prototype._bufferEncode = function (value) {
|
||||
return window.btoa(String.fromCharCode.apply(null, new Uint8Array(value)))
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ WebAuthn.prototype._bufferEncode = function(value) {
|
||||
* @param {ArrayBuffer} value
|
||||
* @return {string}
|
||||
*/
|
||||
WebAuthn.prototype._bufferDecode = function(value) {
|
||||
WebAuthn.prototype._bufferDecode = function (value) {
|
||||
var t = window.atob(value)
|
||||
return Uint8Array.from(t, c => c.charCodeAt(0))
|
||||
}
|
||||
@@ -151,7 +151,7 @@ WebAuthn.prototype._bufferDecode = function(value) {
|
||||
* @param {string} input
|
||||
* @return {string}
|
||||
*/
|
||||
WebAuthn.prototype._base64Decode = function(input) {
|
||||
WebAuthn.prototype._base64Decode = function (input) {
|
||||
// Replace non-url compatible chars with base64 standard chars
|
||||
input = input.replace(/-/g, '+').replace(/_/g, '/')
|
||||
|
||||
@@ -175,9 +175,9 @@ WebAuthn.prototype._base64Decode = function(input) {
|
||||
* @param {PublicKeyCredentialDescriptor} credentials
|
||||
* @return {PublicKeyCredentialDescriptor}
|
||||
*/
|
||||
WebAuthn.prototype._credentialDecode = function(credentials) {
|
||||
WebAuthn.prototype._credentialDecode = function (credentials) {
|
||||
var self = this
|
||||
return credentials.map(function(data) {
|
||||
return credentials.map(function (data) {
|
||||
return {
|
||||
id: self._bufferDecode(self._base64Decode(data.id)),
|
||||
type: data.type,
|
||||
@@ -191,7 +191,7 @@ WebAuthn.prototype._credentialDecode = function(credentials) {
|
||||
*
|
||||
* @return {bool}
|
||||
*/
|
||||
WebAuthn.prototype.webAuthnSupport = function() {
|
||||
WebAuthn.prototype.webAuthnSupport = function () {
|
||||
return !(
|
||||
window.PublicKeyCredential === undefined ||
|
||||
typeof window.PublicKeyCredential !== 'function' ||
|
||||
@@ -204,7 +204,7 @@ WebAuthn.prototype.webAuthnSupport = function() {
|
||||
*
|
||||
* @return {string}
|
||||
*/
|
||||
WebAuthn.prototype.notSupportedMessage = function() {
|
||||
WebAuthn.prototype.notSupportedMessage = function () {
|
||||
if (
|
||||
!window.isSecureContext &&
|
||||
window.location.hostname !== 'localhost' &&
|
||||
@@ -221,7 +221,7 @@ WebAuthn.prototype.notSupportedMessage = function() {
|
||||
* @param {string} message
|
||||
* @param {bool} isError
|
||||
*/
|
||||
WebAuthn.prototype._notify = function(message, isError) {
|
||||
WebAuthn.prototype._notify = function (message, isError) {
|
||||
if (this._notifyCallback) {
|
||||
this._notifyCallback(message, isError)
|
||||
}
|
||||
@@ -232,7 +232,7 @@ WebAuthn.prototype._notify = function(message, isError) {
|
||||
*
|
||||
* @param {function(name: string, message: string, isError: bool)} callback
|
||||
*/
|
||||
WebAuthn.prototype.setNotify = function(callback) {
|
||||
WebAuthn.prototype.setNotify = function (callback) {
|
||||
this._notifyCallback = callback
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
Backup Code:
|
||||
</label>
|
||||
|
||||
<input id="backup_code" type="text" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:shadow-outline{{ $errors->has('backup_code') ? ' border border-red-500' : '' }}" name="backup_code" required autofocus>
|
||||
<input id="backup_code" type="text" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:ring{{ $errors->has('backup_code') ? ' border border-red-500' : '' }}" name="backup_code" required autofocus>
|
||||
|
||||
@if ($errors->has('backup_code'))
|
||||
<p class="text-red-500 text-xs italic mt-4">
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
{{ __('Username') }}:
|
||||
</label>
|
||||
|
||||
<input id="username" type="text" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:shadow-outline{{ $errors->has('username') ? ' border-red-500' : '' }}" name="username" value="{{ old('username') }}" placeholder="johndoe" required autofocus>
|
||||
<input id="username" type="text" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:ring{{ $errors->has('username') ? ' border-red-500' : '' }}" name="username" value="{{ old('username') }}" placeholder="johndoe" required autofocus>
|
||||
|
||||
@if ($errors->has('username'))
|
||||
<p class="text-red-500 text-xs italic mt-4">
|
||||
@@ -44,7 +44,7 @@
|
||||
{{ __('Password') }}:
|
||||
</label>
|
||||
|
||||
<input id="password" type="password" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:shadow-outline{{ $errors->has('password') ? ' border-red-500' : '' }}" name="password" placeholder="********" required>
|
||||
<input id="password" type="password" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:ring{{ $errors->has('password') ? ' border-red-500' : '' }}" name="password" placeholder="********" required>
|
||||
|
||||
@if ($errors->has('password'))
|
||||
<p class="text-red-500 text-xs italic mt-4">
|
||||
@@ -61,7 +61,7 @@
|
||||
</label>
|
||||
</div>
|
||||
@if (Route::has('password.request'))
|
||||
<a class="whitespace-no-wrap no-underline text-sm" href="{{ route('password.request') }}">
|
||||
<a class="whitespace-nowrap no-underline text-sm" href="{{ route('password.request') }}">
|
||||
{{ __('Forgot Username/Password?') }}
|
||||
</a>
|
||||
@endif
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
{{ __('Username') }}:
|
||||
</label>
|
||||
|
||||
<input id="username" type="text" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:shadow-outline{{ $errors->has('username') ? ' border-red-500' : '' }}" name="username" value="{{ old('username') }}" placeholder="johndoe" required>
|
||||
<input id="username" type="text" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:ring{{ $errors->has('username') ? ' border-red-500' : '' }}" name="username" value="{{ old('username') }}" placeholder="johndoe" required>
|
||||
|
||||
@if ($errors->has('username'))
|
||||
<p class="text-red-500 text-xs italic mt-4">
|
||||
@@ -38,7 +38,7 @@
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<a class="whitespace-no-wrap no-underline text-sm" href="{{ route('username.reminder.show') }}">
|
||||
<a class="whitespace-nowrap no-underline text-sm" href="{{ route('username.reminder.show') }}">
|
||||
{{ __('Forgot Username?') }}
|
||||
</a>
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
{{ __('Username') }}:
|
||||
</label>
|
||||
|
||||
<input id="username" type="text" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:shadow-outline{{ $errors->has('username') ? ' border-red-500' : '' }}" name="username" value="{{ old('username') }}" placeholder="johndoe" required autofocus>
|
||||
<input id="username" type="text" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:ring{{ $errors->has('username') ? ' border-red-500' : '' }}" name="username" value="{{ old('username') }}" placeholder="johndoe" required autofocus>
|
||||
|
||||
@if ($errors->has('username'))
|
||||
<p class="text-red-500 text-xs italic mt-4">
|
||||
@@ -39,7 +39,7 @@
|
||||
{{ __('New Password') }}:
|
||||
</label>
|
||||
|
||||
<input id="password" type="password" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:shadow-outline{{ $errors->has('password') ? ' border-red-500' : '' }}" name="password" placeholder="********" required>
|
||||
<input id="password" type="password" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:ring{{ $errors->has('password') ? ' border-red-500' : '' }}" name="password" placeholder="********" required>
|
||||
|
||||
@if ($errors->has('password'))
|
||||
<p class="text-red-500 text-xs italic mt-4">
|
||||
@@ -53,7 +53,7 @@
|
||||
{{ __('Confirm New Password') }}:
|
||||
</label>
|
||||
|
||||
<input id="password-confirm" type="password" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:shadow-outline" name="password_confirmation" placeholder="********" required>
|
||||
<input id="password-confirm" type="password" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:ring" name="password_confirmation" placeholder="********" required>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
</label>
|
||||
|
||||
<div class="table w-full">
|
||||
<input id="username" type="text" class="table-cell relative appearance-none bg-grey-100 rounded-l w-full p-3 text-grey-700 focus:shadow-outline{{ $errors->has('username') ? ' border-red-500' : '' }}" name="username" value="{{ old('username') }}" placeholder="johndoe" required autofocus>
|
||||
<input id="username" type="text" class="table-cell relative appearance-none bg-grey-100 rounded-l w-full p-3 text-grey-700 focus:ring{{ $errors->has('username') ? ' border-red-500' : '' }}" name="username" value="{{ old('username') }}" placeholder="johndoe" required autofocus>
|
||||
<div class="py-3 px-2 table-cell align-middle bg-grey-200 rounded-r text-grey-600">
|
||||
.{{ config('anonaddy.domain') }}
|
||||
</div>
|
||||
@@ -45,7 +45,7 @@
|
||||
Your Real Email Address:
|
||||
</label>
|
||||
|
||||
<input id="email" type="email" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:shadow-outline{{ $errors->has('email') ? ' border-red-500' : '' }}" name="email" value="{{ old('email') }}" placeholder="johndoe@example.com" required>
|
||||
<input id="email" type="email" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:ring{{ $errors->has('email') ? ' border-red-500' : '' }}" name="email" value="{{ old('email') }}" placeholder="johndoe@example.com" required>
|
||||
|
||||
<p class="text-xs mt-1 text-grey-600">This is your recipient where emails will be forwarded</p>
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
Confirm Email Address:
|
||||
</label>
|
||||
|
||||
<input id="email-confirm" type="email" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:shadow-outline" name="email_confirmation" value="{{ old('email_confirmation') }}" placeholder="johndoe@example.com" required>
|
||||
<input id="email-confirm" type="email" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:ring" name="email_confirmation" value="{{ old('email_confirmation') }}" placeholder="johndoe@example.com" required>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap mb-6">
|
||||
@@ -69,7 +69,7 @@
|
||||
{{ __('Password') }}:
|
||||
</label>
|
||||
|
||||
<input id="password" type="password" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:shadow-outline{{ $errors->has('password') ? ' border-red-500' : '' }}" name="password" placeholder="********" required>
|
||||
<input id="password" type="password" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:ring{{ $errors->has('password') ? ' border-red-500' : '' }}" name="password" placeholder="********" required>
|
||||
|
||||
@if ($errors->has('password'))
|
||||
<p class="text-red-500 text-xs italic mt-4">
|
||||
@@ -86,7 +86,7 @@
|
||||
<div class="flex flex-grow flex-wrap">
|
||||
<img src="{{captcha_src('mini')}}" class="flex-shrink-0 h-12 w-16 mr-2 mt-2">
|
||||
|
||||
<input id="captcha" type="text" class="flex-grow mt-2 appearance-none bg-grey-100 rounded p-3 text-grey-700 focus:shadow-outline{{ $errors->has('captcha') ? ' border-red-500' : '' }}" name="captcha" placeholder="Enter the text you see" required>
|
||||
<input id="captcha" type="text" class="flex-grow mt-2 appearance-none bg-grey-100 rounded p-3 text-grey-700 focus:ring{{ $errors->has('captcha') ? ' border-red-500' : '' }}" name="captcha" placeholder="Enter the text you see" required>
|
||||
</div>
|
||||
|
||||
@if ($errors->has('captcha'))
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
{{ __('One Time Token') }}:
|
||||
</label>
|
||||
|
||||
<input id="one_time_password" type="text" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:shadow-outline{{ $errors->has('message') ? ' border border-red-500' : '' }}" name="one_time_password" placeholder="123456" required autofocus>
|
||||
<input id="one_time_password" type="text" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:ring{{ $errors->has('message') ? ' border border-red-500' : '' }}" name="one_time_password" placeholder="123456" required autofocus>
|
||||
|
||||
@if ($errors->has('message'))
|
||||
<p class="text-red-500 text-xs italic mt-4">
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
{{ __('Email') }}:
|
||||
</label>
|
||||
|
||||
<input id="email" type="text" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:shadow-outline{{ $errors->has('email') ? ' border-red-500' : '' }}" name="email" value="{{ old('email') }}" placeholder="johndoe@example.com" required>
|
||||
<input id="email" type="text" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:ring{{ $errors->has('email') ? ' border-red-500' : '' }}" name="email" value="{{ old('email') }}" placeholder="johndoe@example.com" required>
|
||||
|
||||
@if ($errors->has('email'))
|
||||
<p class="text-red-500 text-xs italic mt-4">
|
||||
@@ -39,7 +39,7 @@
|
||||
</div>
|
||||
|
||||
@if (Route::has('password.request'))
|
||||
<a class="whitespace-no-wrap no-underline text-sm" href="{{ route('password.request') }}">
|
||||
<a class="whitespace-nowrap no-underline text-sm" href="{{ route('password.request') }}">
|
||||
{{ __('Forgot Password?') }}
|
||||
</a>
|
||||
@endif
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<form method="POST" action="{{ route('verification.resend') }}" class="w-full">
|
||||
@csrf
|
||||
|
||||
<button type="submit" class="bg-cyan-400 w-full text-center hover:bg-cyan-300 text-cyan-900 font-bold py-3 px-4 rounded focus:shadow-outline no-underline mx-auto">
|
||||
<button type="submit" class="bg-cyan-400 w-full text-center hover:bg-cyan-300 text-cyan-900 font-bold py-3 px-4 rounded focus:ring no-underline mx-auto">
|
||||
{{ __('Resend verification email') }}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
</label>
|
||||
|
||||
<div class="block relative w-full">
|
||||
<select id="default-recipient" class="block appearance-none w-full text-grey-700 bg-grey-100 p-3 pr-8 rounded shadow focus:shadow-outline" name="default_recipient" required>
|
||||
<select id="default-recipient" class="block appearance-none w-full text-grey-700 bg-grey-100 p-3 pr-8 rounded shadow focus:ring" name="default_recipient" required>
|
||||
@foreach($recipientOptions as $recipient)
|
||||
<option value="{{ $recipient->id }}" {{ $user->email === $recipient->email ? 'selected' : '' }}>{{ $recipient->email }}</option>
|
||||
@endforeach
|
||||
@@ -116,7 +116,7 @@
|
||||
</label>
|
||||
|
||||
<div class="block relative w-full">
|
||||
<input id="email" type="email" class="block appearance-none w-full text-grey-700 bg-grey-100 p-3 pr-8 rounded shadow focus:shadow-outline" name="email" value="{{ old('email') ?? $user->email }}">
|
||||
<input id="email" type="email" class="block appearance-none w-full text-grey-700 bg-grey-100 p-3 pr-8 rounded shadow focus:ring" name="email" value="{{ old('email') ?? $user->email }}">
|
||||
</div>
|
||||
|
||||
@if ($errors->has('email'))
|
||||
@@ -132,7 +132,7 @@
|
||||
</label>
|
||||
|
||||
<div class="block relative w-full">
|
||||
<input id="email_confirmation" type="email" class="block appearance-none w-full text-grey-700 bg-grey-100 p-3 pr-8 rounded shadow focus:shadow-outline" name="email_confirmation">
|
||||
<input id="email_confirmation" type="email" class="block appearance-none w-full text-grey-700 bg-grey-100 p-3 pr-8 rounded shadow focus:ring" name="email_confirmation">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -165,7 +165,7 @@
|
||||
</label>
|
||||
|
||||
<div class="block relative w-full">
|
||||
<select id="default-alias-domain" class="block appearance-none w-full text-grey-700 bg-grey-100 p-3 pr-8 rounded shadow focus:shadow-outline" name="domain" required>
|
||||
<select id="default-alias-domain" class="block appearance-none w-full text-grey-700 bg-grey-100 p-3 pr-8 rounded shadow focus:ring" name="domain" required>
|
||||
@foreach($user->domainOptions() as $domainOption)
|
||||
<option value="{{ $domainOption }}" {{ $user->default_alias_domain === $domainOption ? 'selected' : '' }}>{{ $domainOption }}</option>
|
||||
@endforeach
|
||||
@@ -209,7 +209,7 @@
|
||||
</label>
|
||||
|
||||
<div class="block relative w-full">
|
||||
<select id="default-alias-format" class="block appearance-none w-full text-grey-700 bg-grey-100 p-3 pr-8 rounded shadow focus:shadow-outline" name="format" required>
|
||||
<select id="default-alias-format" class="block appearance-none w-full text-grey-700 bg-grey-100 p-3 pr-8 rounded shadow focus:ring" name="format" required>
|
||||
<option value="uuid" {{ $user->default_alias_format === 'uuid' ? 'selected' : '' }}>UUID</option>
|
||||
<option value="random_words" {{ $user->default_alias_format === 'random_words' ? 'selected' : '' }}>Random Words</option>
|
||||
<option value="custom" {{ $user->default_alias_format === 'custom' ? 'selected' : '' }}>Custom</option>
|
||||
@@ -250,7 +250,7 @@
|
||||
{{ __('Current Password') }}:
|
||||
</label>
|
||||
|
||||
<input id="current" type="password" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:shadow-outline{{ $errors->has('current') ? ' border-red-500' : '' }}" name="current" placeholder="********" required>
|
||||
<input id="current" type="password" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:ring{{ $errors->has('current') ? ' border-red-500' : '' }}" name="current" placeholder="********" required>
|
||||
|
||||
@if ($errors->has('current'))
|
||||
<p class="text-red-500 text-xs italic mt-4">
|
||||
@@ -264,7 +264,7 @@
|
||||
{{ __('New Password') }}:
|
||||
</label>
|
||||
|
||||
<input id="password" type="password" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:shadow-outline{{ $errors->has('password') ? ' border-red-500' : '' }}" name="password" placeholder="********" required>
|
||||
<input id="password" type="password" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:ring{{ $errors->has('password') ? ' border-red-500' : '' }}" name="password" placeholder="********" required>
|
||||
|
||||
@if ($errors->has('password'))
|
||||
<p class="text-red-500 text-xs italic mt-4">
|
||||
@@ -278,7 +278,7 @@
|
||||
{{ __('Confirm New Password') }}:
|
||||
</label>
|
||||
|
||||
<input id="password-confirm" type="password" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:shadow-outline" name="password_confirmation" placeholder="********" required>
|
||||
<input id="password-confirm" type="password" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:ring" name="password_confirmation" placeholder="********" required>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -336,7 +336,7 @@
|
||||
{{ __('Current Password') }}:
|
||||
</label>
|
||||
|
||||
<input id="current_password_2fa" type="password" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:shadow-outline{{ $errors->has('current_password_2fa') ? ' border-red-500' : '' }}" name="current_password_2fa" placeholder="********" required>
|
||||
<input id="current_password_2fa" type="password" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:ring{{ $errors->has('current_password_2fa') ? ' border-red-500' : '' }}" name="current_password_2fa" placeholder="********" required>
|
||||
|
||||
@if ($errors->has('current_password_2fa'))
|
||||
<p class="text-red-500 text-xs italic mt-4">
|
||||
@@ -396,7 +396,7 @@
|
||||
</label>
|
||||
|
||||
<div class="block relative w-full">
|
||||
<input id="two_factor_token" type="text" class="block appearance-none w-full text-grey-700 bg-grey-100 p-3 pr-8 rounded shadow focus:shadow-outline" name="two_factor_token" placeholder="123456" />
|
||||
<input id="two_factor_token" type="text" class="block appearance-none w-full text-grey-700 bg-grey-100 p-3 pr-8 rounded shadow focus:ring" name="two_factor_token" placeholder="123456" />
|
||||
</div>
|
||||
|
||||
@if ($errors->has('two_factor_token'))
|
||||
@@ -466,7 +466,7 @@
|
||||
</label>
|
||||
|
||||
<div class="block relative w-full">
|
||||
<select id="catch_all" class="block appearance-none w-full text-grey-700 bg-grey-100 p-3 pr-8 rounded shadow focus:shadow-outline" name="catch_all" required>
|
||||
<select id="catch_all" class="block appearance-none w-full text-grey-700 bg-grey-100 p-3 pr-8 rounded shadow focus:ring" name="catch_all" required>
|
||||
<option value="1" {{ $user->catch_all ? 'selected' : '' }}>Enabled</option>
|
||||
<option value="0" {{ ! $user->catch_all ? 'selected' : '' }}>Disabled</option>
|
||||
</select>
|
||||
@@ -509,7 +509,7 @@
|
||||
</label>
|
||||
|
||||
<div class="block relative w-full">
|
||||
<input id="from_name" type="text" class="block appearance-none w-full text-grey-700 bg-grey-100 p-3 pr-8 rounded shadow focus:shadow-outline" name="from_name" value="{{ $user->from_name }}" placeholder="John Doe" />
|
||||
<input id="from_name" type="text" class="block appearance-none w-full text-grey-700 bg-grey-100 p-3 pr-8 rounded shadow focus:ring" name="from_name" value="{{ $user->from_name }}" placeholder="John Doe" />
|
||||
</div>
|
||||
|
||||
@if ($errors->has('from_name'))
|
||||
@@ -546,7 +546,7 @@
|
||||
</label>
|
||||
|
||||
<div class="block relative w-full">
|
||||
<select id="banner_location" class="block appearance-none w-full text-grey-700 bg-grey-100 p-3 pr-8 rounded shadow focus:shadow-outline" name="banner_location" required>
|
||||
<select id="banner_location" class="block appearance-none w-full text-grey-700 bg-grey-100 p-3 pr-8 rounded shadow focus:ring" name="banner_location" required>
|
||||
<option value="top" {{ $user->banner_location === 'top' ? 'selected' : '' }}>Top</option>
|
||||
<option value="bottom" {{ $user->banner_location === 'bottom' ? 'selected' : '' }}>Bottom</option>
|
||||
<option value="off" {{ $user->banner_location === 'off' ? 'selected' : '' }}>Off</option>
|
||||
@@ -592,7 +592,7 @@
|
||||
</label>
|
||||
|
||||
<div class="block relative w-full">
|
||||
<input id="email_subject" type="text" class="block appearance-none w-full text-grey-700 bg-grey-100 p-3 pr-8 rounded shadow focus:shadow-outline" name="email_subject" value="{{ $user->email_subject }}" placeholder="The subject" />
|
||||
<input id="email_subject" type="text" class="block appearance-none w-full text-grey-700 bg-grey-100 p-3 pr-8 rounded shadow focus:ring" name="email_subject" value="{{ $user->email_subject }}" placeholder="The subject" />
|
||||
</div>
|
||||
|
||||
@if ($errors->has('email_subject'))
|
||||
@@ -677,7 +677,7 @@
|
||||
{{ __('Enter your password to continue') }}:
|
||||
</label>
|
||||
|
||||
<input id="current-password-delete" type="password" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:outline-none focus:shadow-outline{{ $errors->has('current_password_delete') ? ' border-red-500' : '' }}" name="current_password_delete" placeholder="********" required>
|
||||
<input id="current-password-delete" type="password" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:outline-none focus:ring{{ $errors->has('current_password_delete') ? ' border-red-500' : '' }}" name="current_password_delete" placeholder="********" required>
|
||||
|
||||
@if ($errors->has('current_password_delete'))
|
||||
<p class="text-red-500 text-xs italic mt-4">
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
<label for="name" class="block text-grey-700 text-sm mb-2">
|
||||
Name:
|
||||
</label>
|
||||
<input type="text" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:shadow-outline" name="name" id="name" placeholder="Yubikey" required autofocus>
|
||||
<input type="text" class="appearance-none bg-grey-100 rounded w-full p-3 text-grey-700 focus:ring" name="name" id="name" placeholder="Yubikey" required autofocus>
|
||||
|
||||
@if ($errors->has('name'))
|
||||
<p class="text-red-500 text-xs italic mt-4">
|
||||
|
||||
26
tailwind.config.js
vendored
26
tailwind.config.js
vendored
@@ -1,8 +1,4 @@
|
||||
module.exports = {
|
||||
future: {
|
||||
removeDeprecatedGapUtilities: true,
|
||||
purgeLayersByDefault: true,
|
||||
},
|
||||
purge: {
|
||||
content: [
|
||||
'app/**/*.php',
|
||||
@@ -14,7 +10,15 @@ module.exports = {
|
||||
|
||||
// These options are passed through directly to PurgeCSS
|
||||
options: {
|
||||
whitelistPatterns: [/-active$/, /-enter$/, /-leave-to$/, /show$/],
|
||||
safelist: [
|
||||
/-active$/,
|
||||
/-enter$/,
|
||||
/-leave-to$/,
|
||||
/show$/,
|
||||
'bg-green-400',
|
||||
'bg-red-400',
|
||||
'bg-grey-400',
|
||||
],
|
||||
},
|
||||
},
|
||||
theme: {
|
||||
@@ -107,6 +111,18 @@ module.exports = {
|
||||
900: '#014807',
|
||||
},
|
||||
},
|
||||
fontSize: {
|
||||
xs: '0.75rem',
|
||||
sm: '0.875rem',
|
||||
base: '1rem',
|
||||
lg: '1.125rem',
|
||||
xl: '1.25rem',
|
||||
'2xl': '1.5rem',
|
||||
'3xl': '1.875rem',
|
||||
'4xl': '2.25rem',
|
||||
'5xl': '3rem',
|
||||
'6xl': '4rem',
|
||||
},
|
||||
container: {
|
||||
center: true,
|
||||
padding: '1.5rem',
|
||||
|
||||
9
webpack.mix.js
vendored
9
webpack.mix.js
vendored
@@ -3,14 +3,7 @@ let mix = require('laravel-mix')
|
||||
mix
|
||||
.js('resources/js/app.js', 'public/js')
|
||||
.js('resources/js/webauthn.js', 'public/js')
|
||||
.postCss('resources/css/app.css', 'public/css')
|
||||
.options({
|
||||
postCss: [
|
||||
require('postcss-import')(),
|
||||
require('tailwindcss')('./tailwind.config.js'),
|
||||
require('postcss-nesting')(),
|
||||
],
|
||||
})
|
||||
.postCss('resources/css/app.css', 'public/css', [require('tailwindcss')])
|
||||
|
||||
if (mix.inProduction()) {
|
||||
mix.version()
|
||||
|
||||
Reference in New Issue
Block a user