|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 199 B |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
@@ -0,0 +1,10 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="170" height="32" viewBox="0 0 170 32">
|
||||
<title>EagleCast</title>
|
||||
<g>
|
||||
<circle cx="16" cy="16" r="15" fill="#1b3a5b"/>
|
||||
<path d="M9.2 13.2 C9.2 9.2 12.6 6.6 16.4 6.6 C20.2 6.6 23.3 8.9 24.4 11.9 L30.4 14.2 L24.7 15.9 C24.8 16.5 24.3 17.1 23.4 17.1 L21.7 17.1 C22.5 21.6 20.4 25.1 16.7 26.1 C14.7 26.6 13.1 25.7 12.3 23.9 C10.5 21.0 9.5 17.3 9.2 13.2 Z" fill="#ffffff"/>
|
||||
<path d="M24.4 11.9 L30.4 14.2 L24.7 15.9 C25.0 14.5 24.8 13.1 24.4 11.9 Z" fill="#eaa221"/>
|
||||
<circle cx="19.8" cy="11.9" r="1.5" fill="#1b3a5b"/>
|
||||
</g>
|
||||
<text x="38" y="22.5" font-family="Inter, 'Helvetica Neue', Arial, sans-serif" font-size="18" font-weight="700" fill="#1b3a5b">Eagle<tspan fill="#eaa221">Cast</tspan></text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 769 B |
@@ -0,0 +1,5 @@
|
||||
User-agent: *
|
||||
Allow: /subscription/form
|
||||
Disallow: /subscription/
|
||||
Disallow: /campaign/
|
||||
Disallow: /link/
|
||||
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414"><path fill="#FFA500" d="M12.8 16C12.8 8.978 7.022 3.2 0 3.2V0c8.777 0 16 7.223 16 16h-3.2zM2.194 11.61c1.21 0 2.195.985 2.195 2.196 0 1.21-.99 2.194-2.2 2.194C.98 16 0 15.017 0 13.806c0-1.21.983-2.195 2.194-2.195zM10.606 16h-3.11c0-4.113-3.383-7.497-7.496-7.497v-3.11c5.818 0 10.606 4.79 10.606 10.607z"/></svg>
|
||||
|
After Width: | Height: | Size: 462 B |
@@ -0,0 +1,230 @@
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
html, body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
min-width: 320px;
|
||||
}
|
||||
body {
|
||||
background: #f9f9f9;
|
||||
font-family: "Inter", "Open Sans", "Helvetica Neue", sans-serif;
|
||||
font-size: 16px;
|
||||
line-height: 26px;
|
||||
color: #111;
|
||||
}
|
||||
a {
|
||||
color: #1b3a5b;
|
||||
text-decoration-color: #abcbfb;
|
||||
}
|
||||
a:hover {
|
||||
color: #111;
|
||||
}
|
||||
label {
|
||||
cursor: pointer;
|
||||
color: #444;
|
||||
}
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
h4 {
|
||||
font-weight: 400;
|
||||
}
|
||||
.section {
|
||||
margin-bottom: 45px;
|
||||
}
|
||||
|
||||
input[type="text"], input[type="email"], input[type="password"], select {
|
||||
padding: 10px 15px;
|
||||
border: 1px solid #888;
|
||||
border-radius: 3px;
|
||||
width: 100%;
|
||||
box-shadow: 2px 2px 0 #f3f3f3;
|
||||
border: 1px solid #ddd;
|
||||
font-size: 1em;
|
||||
}
|
||||
input:focus {
|
||||
border-color: #1b3a5b;
|
||||
}
|
||||
|
||||
input:focus::placeholder {
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
input[disabled] {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.center {
|
||||
text-align: center;
|
||||
}
|
||||
.right {
|
||||
text-align: right;
|
||||
}
|
||||
.small {
|
||||
font-size: 0.875em;
|
||||
}
|
||||
.error {
|
||||
color: #FF5722;
|
||||
}
|
||||
.button {
|
||||
background: #1b3a5b;
|
||||
padding: 15px 30px;
|
||||
border-radius: 3px;
|
||||
border: 0;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
color: #ffff;
|
||||
display: inline-block;
|
||||
min-width: 150px;
|
||||
font-size: 1.1em;
|
||||
text-align: center;
|
||||
}
|
||||
.button:hover {
|
||||
background: #333;
|
||||
color: #fff;
|
||||
}
|
||||
.button.button-outline {
|
||||
background: #fff;
|
||||
border: 1px solid #1b3a5b;
|
||||
color: #1b3a5b;
|
||||
}
|
||||
.button.button-outline:hover {
|
||||
border-color: #333;
|
||||
background-color: #333;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.container {
|
||||
margin: 60px auto 15px auto;
|
||||
max-width: 550px;
|
||||
}
|
||||
|
||||
.wrap {
|
||||
background: #fff;
|
||||
padding: 40px;
|
||||
box-shadow: 2px 2px 0 #f3f3f3;
|
||||
border: 1px solid #eee;
|
||||
}
|
||||
|
||||
.header {
|
||||
border-bottom: 1px solid #eee;
|
||||
padding-bottom: 15px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
.header .logo img {
|
||||
width: auto;
|
||||
max-width: 150px;
|
||||
}
|
||||
|
||||
.unsub-all {
|
||||
margin-top: 30px;
|
||||
padding-top: 30px;
|
||||
border-top: 1px solid #eee;
|
||||
}
|
||||
|
||||
.row {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.lists {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
.lists li {
|
||||
margin: 0 0 5px 0;
|
||||
}
|
||||
.lists .description {
|
||||
margin: 0 0 15px 0;
|
||||
font-size: 0.875em;
|
||||
line-height: 1.3rem;
|
||||
color: #888;
|
||||
margin-left: 25px;
|
||||
}
|
||||
.form .nonce {
|
||||
display: none;
|
||||
}
|
||||
.form .captcha {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.archive {
|
||||
list-style-type: none;
|
||||
margin: 25px 0 0 0;
|
||||
padding: 0;
|
||||
}
|
||||
.archive .date {
|
||||
display: block;
|
||||
color: #666;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
.archive li {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.feed {
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
.home-options {
|
||||
margin-top: 30px;
|
||||
}
|
||||
.home-options a {
|
||||
margin: 0 7px;
|
||||
}
|
||||
|
||||
.pagination {
|
||||
margin-top: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
.pg-page {
|
||||
display: inline-block;
|
||||
padding: 0 10px;
|
||||
text-decoration: none;
|
||||
}
|
||||
.pg-page.pg-selected {
|
||||
text-decoration: underline;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.login .submit {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.login button {
|
||||
width: 100%;
|
||||
vertical-align: middle;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.login button img {
|
||||
max-width: 24px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.login input[name=totp_code] {
|
||||
font-size: 2em;
|
||||
letter-spacing: 5px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
footer.container {
|
||||
margin-top: 15px;
|
||||
text-align: center;
|
||||
color: #aaa;
|
||||
font-size: 0.775em;
|
||||
margin-top: 30px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
footer a {
|
||||
color: #aaa;
|
||||
text-decoration: none;
|
||||
}
|
||||
footer a:hover {
|
||||
color: #111;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 650px) {
|
||||
.wrap {
|
||||
margin: 0;
|
||||
padding: 30px;
|
||||
max-width: none;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
{{ define "archive" }}
|
||||
{{ template "header" .}}
|
||||
<section>
|
||||
<h2>{{ L.T "public.archiveTitle" }}</h2>
|
||||
|
||||
<ul class="archive">
|
||||
{{ range $c := .Data.Campaigns }}
|
||||
<li>
|
||||
<a href="{{ $c.URL }}">{{ $c.Subject }}</a>
|
||||
<span class="date">
|
||||
{{ if $c.SendAt.Valid }}
|
||||
{{ $c.SendAt.Time.Format "Mon, 02 Jan 2006" }}
|
||||
{{ else }}
|
||||
{{ $c.CreatedAt.Time.Format "Mon, 02 Jan 2006" }}
|
||||
{{ end }}
|
||||
</span>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
|
||||
{{ if not .Data.Campaigns }}
|
||||
{{ L.T "public.archiveEmpty" }}
|
||||
{{ end }}
|
||||
|
||||
{{ if .EnablePublicSubPage }}
|
||||
<div class="right">
|
||||
<a href="{{ .RootURL }}/archive.xml">
|
||||
<img src="{{ .RootURL }}/public/static/rss.svg" alt="RSS" class="feed"
|
||||
width="16" height="16" />
|
||||
</a>
|
||||
<a href="{{ .RootURL }}/subscription/form">{{ L.T "public.sub" }}</a>
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ if gt .Data.TotalPages 1 }}
|
||||
<div class="pagination">{{ .Data.Pagination }}</div>
|
||||
{{ end }}
|
||||
</section>
|
||||
|
||||
{{ template "footer" .}}
|
||||
{{ end }}
|
||||
@@ -0,0 +1,23 @@
|
||||
{{ define "admin-forgot-password" }}
|
||||
{{ template "header" .}}
|
||||
|
||||
<section class="login">
|
||||
<h2>{{ .L.T "users.forgotPassword"}}</h2>
|
||||
|
||||
<form method="post" action="/admin/forgot" class="form">
|
||||
<div>
|
||||
<p>
|
||||
<label for="email">{{ .L.T "subscribers.email" }}</label>
|
||||
<input id="email" type="email" name="email" autofocus required />
|
||||
</p>
|
||||
|
||||
{{ if .Data.Error }}<p class="error">{{ .Data.Error }}</p>{{ end }}
|
||||
|
||||
<p><button class="button" type="submit">{{ .L.T "globals.buttons.continue" }}</button></p>
|
||||
<p class="small"><a href="{{ .RootURL }}/admin/login">← {{ .L.T "users.login" }}</a></p>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
{{ template "footer" .}}
|
||||
{{ end }}
|
||||
@@ -0,0 +1,18 @@
|
||||
{{ define "home" }}
|
||||
{{ template "header" .}}
|
||||
|
||||
<section class="center">
|
||||
<a href="admin" class="button">{{ L.T "users.login" }}</a>
|
||||
|
||||
<div class="home-options">
|
||||
{{ if .EnablePublicSubPage }}
|
||||
<a href="{{ .RootURL }}/subscription/form">{{ L.T "public.sub" }}</a>
|
||||
{{ end }}
|
||||
{{ if .EnablePublicArchive }}
|
||||
<a href="{{ .RootURL }}/archive">{{ L.T "public.archiveTitle" }}</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{{ template "footer" .}}
|
||||
{{ end }}
|
||||
@@ -0,0 +1,48 @@
|
||||
{{ define "header" }}
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<title>{{ .Data.Title }} - {{ .SiteName }}</title>
|
||||
<meta name="description" content="{{ .Data.Description }}" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
|
||||
|
||||
{{ if .EnablePublicArchive }}
|
||||
<link rel="alternate" type="application/rss+xml" title="{{ L.T "public.archiveTitle" }} - {{ .SiteName }}"
|
||||
href="{{ .RootURL }}/archive.xml" />
|
||||
{{ end }}
|
||||
|
||||
<link href="/public/static/style.css?v={{ .AssetVersion }}" rel="stylesheet" type="text/css" />
|
||||
<link href="/public/custom.css?v={{ .AssetVersion }}" rel="stylesheet" type="text/css">
|
||||
<script src="/public/custom.js?v={{ .AssetVersion }}" async defer></script>
|
||||
|
||||
{{ if ne .FaviconURL "" }}
|
||||
<link rel="icon" href="{{ .FaviconURL }}" type="image/x-icon" />
|
||||
{{ else }}
|
||||
<link rel="icon" href="/public/static/favicon.png?v={{ .AssetVersion }}" type="image/png" />
|
||||
{{ end }}
|
||||
</head>
|
||||
<body>
|
||||
<div class="container wrap">
|
||||
<header class="header">
|
||||
<div class="logo">
|
||||
<a href="{{ if .EnablePublicSubPage }}{{ .RootURL}}/subscription/form{{ end }}">
|
||||
{{ if ne .LogoURL "" }}
|
||||
<img src="{{ .LogoURL }}" alt="{{ .Data.Title }}" />
|
||||
{{ else }}
|
||||
<img src="/public/static/logo.svg?v={{ .AssetVersion }}" alt="{{ .Data.Title }}" />
|
||||
{{ end }}
|
||||
</a>
|
||||
</div>
|
||||
</header>
|
||||
{{ end }}
|
||||
|
||||
{{ define "footer" }}
|
||||
</div>
|
||||
|
||||
<footer class="container">
|
||||
{{ L.T "public.poweredBy" }} <a href="https://source.offmarket.win/aleagle/EagleCast" target="_blank" rel="noopener noreferrer">EagleCast</a>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
{{ end }}
|
||||
@@ -0,0 +1,37 @@
|
||||
{{ define "admin-login-setup" }}
|
||||
{{ template "header" .}}
|
||||
|
||||
<section class="login">
|
||||
<h2>{{ .L.T "users.newUser"}}</h2>
|
||||
<p> {{ .L.T "users.firstTime" }}</p>
|
||||
|
||||
<form method="post" action="" class="form">
|
||||
<div>
|
||||
<input type="hidden" name="nonce" value="{{ .Data.Nonce }}" />
|
||||
<input type="hidden" name="next" value="{{ .Data.NextURI }}" />
|
||||
<p>
|
||||
<label for="email">{{ .L.T "subscribers.email" }}</label>
|
||||
<input id="email" type="email" name="email" autofocus required minlength="3" />
|
||||
</p>
|
||||
<p>
|
||||
<label for="username">{{ .L.T "users.username" }}</label>
|
||||
<input id="username" type="text" name="username" required minlength="3" />
|
||||
</p>
|
||||
<p>
|
||||
<label for="password">{{ .L.T "users.password" }}</label>
|
||||
<input id="password" type="password" name="password" required minlength="8" />
|
||||
</p>
|
||||
<p>
|
||||
<label for="password2">{{ .L.T "users.passwordRepeat" }}</label>
|
||||
<input id="password2" type="password" name="password2" required minlength="8" />
|
||||
</p>
|
||||
|
||||
{{ if .Data.Error }}<p><span class="error">{{ .Data.Error }}</span></p>{{ end }}
|
||||
|
||||
<p class="submit"><button class="button" type="submit">{{ .L.T "globals.buttons.continue" }}</button></p>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
{{ template "footer" .}}
|
||||
{{ end }}
|
||||
@@ -0,0 +1,45 @@
|
||||
{{ define "admin-login" }}
|
||||
{{ template "header" .}}
|
||||
|
||||
<section class="login">
|
||||
<h2>{{ .L.T "users.login"}}</h2>
|
||||
{{ if .Data.PasswordEnabled }}
|
||||
<form method="post" action="/admin/login" class="form">
|
||||
<div>
|
||||
<input type="hidden" name="nonce" value="{{ .Data.Nonce }}" />
|
||||
<input type="hidden" name="next" value="{{ .Data.NextURI }}" />
|
||||
<p>
|
||||
<label for="username">{{ .L.T "users.username" }}</label>
|
||||
<input id="username" type="text" name="username" autofocus required minlength="3" />
|
||||
</p>
|
||||
<p>
|
||||
<label for="password">{{ .L.T "users.password" }}</label>
|
||||
<input id="password" type="password" name="password" required minlength="8" />
|
||||
</p>
|
||||
|
||||
{{ if .Data.Error }}<p><span class="error">{{ .Data.Error }}</span></p>{{ end }}
|
||||
|
||||
<p class="submit"><button class="button" type="submit">{{ .L.T "users.login" }}</button></p>
|
||||
</div>
|
||||
</form>
|
||||
{{ end }}
|
||||
|
||||
{{ if .Data.OIDCProvider }}
|
||||
<form method="post" action="/auth/oidc">
|
||||
<div>
|
||||
<input type="hidden" name="nonce" value="{{ .Data.Nonce }}" />
|
||||
<input type="hidden" name="next" value="{{ .Data.NextURI }}" />
|
||||
<p><button class="button button-outline" type="submit">
|
||||
<img src="{{ .RootURL }}/public/static/auth/{{ .Data.OIDCProviderLogo }}" alt="" />
|
||||
{{ .L.Ts "users.loginOIDC" "name" .Data.OIDCProvider }}
|
||||
</button></p>
|
||||
</div>
|
||||
</form>
|
||||
{{ end }}
|
||||
|
||||
<p class="center small"><a href="{{ .RootURL }}/admin/forgot">{{ .L.T "users.forgotPassword" }}</a></p>
|
||||
|
||||
</section>
|
||||
|
||||
{{ template "footer" .}}
|
||||
{{ end }}
|
||||
@@ -0,0 +1,10 @@
|
||||
{{ define "message" }}
|
||||
{{ template "header" .}}
|
||||
|
||||
<h2>{{ .Data.Title }}</h2>
|
||||
<div>
|
||||
{{ .Data.Message }}
|
||||
</div>
|
||||
|
||||
{{ template "footer" .}}
|
||||
{{ end }}
|
||||
@@ -0,0 +1,30 @@
|
||||
{{ define "optin" }}
|
||||
{{ template "header" .}}
|
||||
<section>
|
||||
<h2>{{ L.T "public.confirmSubTitle" }}</h2>
|
||||
<p>
|
||||
{{ L.T "public.confirmSubInfo" }}
|
||||
</p>
|
||||
|
||||
<form method="post" class="optin-form">
|
||||
<ul>
|
||||
{{ range $i, $l := .Data.Lists }}
|
||||
<input type="hidden" name="l" value="{{ $l.UUID }}" />
|
||||
{{ if eq $l.Type "public" }}
|
||||
<li>{{ $l.Name }}</li>
|
||||
{{ else }}
|
||||
<li>{{ L.Ts "public.subPrivateList" }}</li>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</ul>
|
||||
<p>
|
||||
<input type="hidden" name="confirm" value="true" />
|
||||
<button type="submit" class="button" id="btn-unsub">
|
||||
{{ L.Ts "public.confirmSub" }}
|
||||
</button>
|
||||
</p>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
{{ template "footer" .}}
|
||||
{{ end }}
|
||||
@@ -0,0 +1,26 @@
|
||||
{{ define "admin-reset-password" }}
|
||||
{{ template "header" .}}
|
||||
|
||||
<section class="login">
|
||||
<h2>{{ .L.T "users.resetPassword"}}</h2>
|
||||
|
||||
<form method="post" action="/admin/reset?token={{ .Data.Token }}&email={{ .Data.Email }}" class="form">
|
||||
<div>
|
||||
<p>
|
||||
<label for="password">{{ .L.T "users.newPassword" }}</label>
|
||||
<input id="password" type="password" name="password" autofocus required minlength="8" />
|
||||
</p>
|
||||
<p>
|
||||
<label for="password2">{{ .L.T "users.passwordRepeat" }}</label>
|
||||
<input id="password2" type="password" name="password2" required minlength="8" />
|
||||
</p>
|
||||
|
||||
{{ if .Data.Error }}<p><span class="error">{{ .Data.Error }}</span></p>{{ end }}
|
||||
|
||||
<p class="submit"><button class="button" type="submit">{{ .L.T "users.resetPassword" }}</button></p>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
{{ template "footer" .}}
|
||||
{{ end }}
|
||||
@@ -0,0 +1,57 @@
|
||||
{{ define "subscription-form" }}
|
||||
{{ template "header" . }}
|
||||
<section>
|
||||
<h2>{{ L.T "public.subTitle" }}</h2>
|
||||
|
||||
<form method="post" action="" class="form">
|
||||
<div>
|
||||
<p>
|
||||
<label for="email">{{ L.T "subscribers.email" }}</label>
|
||||
<input id="email" name="email" required="true" type="email" placeholder="{{ L.T "subscribers.email" }}" autofocus="true" >
|
||||
|
||||
<input name="nonce" class="nonce" value="" />
|
||||
</p>
|
||||
<p>
|
||||
<label for="name">{{ L.T "public.subName" }}</label>
|
||||
<input id="name" name="name" type="text" placeholder="{{ L.T "public.subName" }}" >
|
||||
</p>
|
||||
|
||||
<ul class="lists">
|
||||
<h2>{{ L.T "globals.terms.lists" }}</h2>
|
||||
{{ range $i, $l := .Data.Lists }}
|
||||
<li>
|
||||
<input checked="true" id="l-{{ $l.UUID}}" type="checkbox" name="l" value="{{ $l.UUID }}" >
|
||||
<label for="l-{{ $l.UUID}}">{{ $l.Name }}</label>
|
||||
{{ if ne $l.Description "" }}
|
||||
<p class="description">{{ $l.Description }}</p>
|
||||
{{ end }}
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
|
||||
{{ if .Data.Captcha.Enabled }}
|
||||
<div class="captcha">
|
||||
{{ if eq .Data.Captcha.Provider "hcaptcha" }}
|
||||
<div class="h-captcha" data-sitekey="{{ .Data.Captcha.Key }}"></div>
|
||||
<script src="https://js.hcaptcha.com/1/api.js" async defer></script>
|
||||
{{ else if eq .Data.Captcha.Provider "altcha" }}
|
||||
<altcha-widget challengeurl="{{ .RootURL }}/api/public/captcha/altcha"></altcha-widget>
|
||||
<script type="module" src="{{ .RootURL }}/public/static/altcha.umd.js" async defer></script>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
<p>
|
||||
<button type="submit" class="button">{{ L.T "public.sub" }}</button>
|
||||
|
||||
{{ if .EnablePublicArchive }}
|
||||
<p class="right">
|
||||
<a href="{{ .RootURL }}/archive">{{ L.T "public.archiveTitle" }}</a>
|
||||
</p>
|
||||
{{ end }}
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
{{ template "footer" .}}
|
||||
{{ end }}
|
||||
@@ -0,0 +1,123 @@
|
||||
{{ define "subscription" }}
|
||||
{{ template "header" .}}
|
||||
<section class="section">
|
||||
{{ if not .Data.ShowManage }}
|
||||
<h2>{{ L.T "public.unsubTitle" }}</h2>
|
||||
<form method="post" class="unsub-form">
|
||||
<div>
|
||||
{{ if .Data.AllowBlocklist }}
|
||||
<p>{{ L.T "public.unsubHelp" }}</p>
|
||||
<p>
|
||||
<input id="privacy-blocklist" type="checkbox" name="blocklist" value="true" />
|
||||
<label for="privacy-blocklist">{{ L.T "public.unsubFull" }}</label>
|
||||
</p>
|
||||
{{ end }}
|
||||
|
||||
<p>
|
||||
<button type="submit" class="button" id="btn-unsub">{{ L.T "public.unsub" }}</button>
|
||||
</p>
|
||||
|
||||
{{ if .Data.AllowPreferences }}
|
||||
<a href="?manage=true">{{ L.T "public.managePrefs" }}</a>
|
||||
{{ end }}
|
||||
</div>
|
||||
</form>
|
||||
{{ else }}
|
||||
<form method="post" class="manage-form">
|
||||
<div>
|
||||
<input type="hidden" name="manage" value="true" />
|
||||
|
||||
<h2>{{ L.T "public.managePrefs" }}</h2>
|
||||
<label>{{ L.T "globals.fields.name" }}</label>
|
||||
<input type="text" name="name" value="{{ .Data.Subscriber.Name }}" maxlength="256" required />
|
||||
|
||||
{{ if .Data.Subscriptions }}
|
||||
<br /><br />
|
||||
<h3>{{ L.T "public.managePrefsUnsub" }}</h3>
|
||||
<ul class="lists">
|
||||
{{ range $i, $l := .Data.Subscriptions }}
|
||||
{{ if ne $l.SubscriptionStatus.Value "unsubscribed" }}
|
||||
<li>
|
||||
<input id="l-{{ $l.UUID}}" type="checkbox" name="l" value="{{ $l.UUID }}" checked />
|
||||
<label for="l-{{ $l.UUID}}">{{ $l.Name }}</label>
|
||||
</li>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</ul>
|
||||
{{ end }}
|
||||
|
||||
{{ if .Data.AllowBlocklist }}
|
||||
<p>
|
||||
<input id="privacy-blocklist" type="checkbox" name="blocklist" value="true" onchange="unsubAll(event)" />
|
||||
<label for="privacy-blocklist">{{ L.T "public.unsubFull" }}</label>
|
||||
</p>
|
||||
{{ end }}
|
||||
|
||||
<p>
|
||||
<button type="submit" class="button" id="btn-unsub">{{ L.T "globals.buttons.save" }}</button>
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
{{ end }}
|
||||
</section>
|
||||
|
||||
{{ if or .Data.AllowExport .Data.AllowWipe }}
|
||||
<form id="data-form" class="data-form" method="post" action="" onsubmit="return handleData()">
|
||||
<section>
|
||||
<h2>{{ L.T "public.privacyTitle" }}</h2>
|
||||
{{ if .Data.AllowExport }}
|
||||
<div class="row">
|
||||
<input id="privacy-export" type="radio" name="data-action" value="export" required />
|
||||
<label for="privacy-export"><strong>{{ L.T "public.privacyExport" }}</strong></label>
|
||||
<br />
|
||||
{{ L.T "public.privacyExportHelp" }}
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
{{ if .Data.AllowWipe }}
|
||||
<div class="row">
|
||||
<input id="privacy-wipe" type="radio" name="data-action" value="wipe" required />
|
||||
<label for="privacy-wipe"><strong>{{ L.T "public.privacyWipe" }}</strong></label>
|
||||
<br />
|
||||
{{ L.T "public.privacyWipeHelp" }}
|
||||
</div>
|
||||
{{ end }}
|
||||
<p>
|
||||
<input type="submit" value="{{ L.T "globals.buttons.continue" }}" class="button button-outline" />
|
||||
</p>
|
||||
</section>
|
||||
</form>
|
||||
<script>
|
||||
function handleData() {
|
||||
var a = document.querySelector('input[name="data-action"]:checked').value,
|
||||
f = document.querySelector("#data-form");
|
||||
if (a == "export") {
|
||||
f.action = "/subscription/export/{{ .Data.SubUUID }}";
|
||||
return true;
|
||||
} else if (confirm("{{ L.T "public.privacyConfirmWipe" }}")) {
|
||||
f.action = "/subscription/wipe/{{ .Data.SubUUID }}";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function unsubAll(e) {
|
||||
if (e.target.checked) {
|
||||
document.querySelector("input[name=name]").disabled = "disabled";
|
||||
} else {
|
||||
document.querySelector("input[name=name]").removeAttribute("disabled");
|
||||
}
|
||||
|
||||
document.querySelectorAll('input[type=checkbox][name=l]').forEach(function(l) {
|
||||
if (e.target.checked) {
|
||||
l.disabled = "disabled";
|
||||
} else {
|
||||
l.removeAttribute("disabled");
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{{ end }}
|
||||
|
||||
{{ template "footer" .}}
|
||||
{{ end }}
|
||||
@@ -0,0 +1,25 @@
|
||||
{{ define "admin-twofa" }}
|
||||
{{ template "header" .}}
|
||||
|
||||
<section class="login">
|
||||
<h2>{{ .L.T "users.twoFA"}}</h2>
|
||||
<p>{{ .L.T "users.totpCodeHelp" }}</p>
|
||||
|
||||
<form method="post" action="/admin/login/twofa" class="form">
|
||||
<div>
|
||||
<input type="hidden" name="token" value="{{ .Data.Token }}" />
|
||||
<input type="hidden" name="next" value="{{ .Data.NextURI }}" />
|
||||
<p>
|
||||
<input id="totp_code" type="text" name="totp_code" autofocus required
|
||||
pattern="[0-9]{6}" maxlength="6" placeholder="• • • • • •" aria-label="{{ .L.T "users.totpCode" }}" />
|
||||
</p>
|
||||
|
||||
{{ if .Data.Error }}<p><span class="error">{{ .Data.Error }}</span></p>{{ end }}
|
||||
|
||||
<p class="submit"><button class="button" type="submit">{{ .L.T "globals.buttons.continue" }}</button></p>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
{{ template "footer" .}}
|
||||
{{ end }}
|
||||