Initial commit
Contents were based on WriteFreely 0.13.1 release tarballs, might write an script to automate this. Signed-off-by: Andrei Jiroh Eugenio Halili <ajhalili2006@gmail.com>
|
@ -0,0 +1,3 @@
|
|||
writefreely
|
||||
*.swp
|
||||
*.save
|
|
@ -0,0 +1,7 @@
|
|||
{{define "head"}}<title>Page not found — {{.SiteName}}</title>{{end}}
|
||||
{{define "content"}}
|
||||
<div class="error-page">
|
||||
<p class="msg">This page is missing.</p>
|
||||
<p>Are you sure it was ever here?</p>
|
||||
</div>
|
||||
{{end}}
|
|
@ -0,0 +1,10 @@
|
|||
{{define "head"}}<title>Post not found — {{.SiteName}}</title>{{end}}
|
||||
{{define "content"}}
|
||||
<div class="error-page" style="max-width:30em">
|
||||
<p class="msg">Post not found.</p>
|
||||
{{if and (not .SingleUser) .OpenRegistration}}
|
||||
<p class="commentary" style="margin-top:2.5em">Why not share a thought of your own?</p>
|
||||
<p><a href="/">Start a blog</a> and spread your ideas on <strong>{{.SiteName}}</strong>, a simple{{if .Federation}}, federated{{end}} blogging community.</p>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
|
@ -0,0 +1,7 @@
|
|||
{{define "head"}}<title>Unpublished — {{.SiteName}}</title>{{end}}
|
||||
{{define "content"}}
|
||||
<div class="error-page">
|
||||
<p class="msg">{{if .Content}}{{.Content}}{{else}}Post was unpublished by the author.{{end}}</p>
|
||||
<p class="commentary">It might be back some day.</p>
|
||||
</div>
|
||||
{{end}}
|
|
@ -0,0 +1,10 @@
|
|||
{{define "head"}}<title>Server error — {{.SiteName}}</title>{{end}}
|
||||
{{define "content"}}
|
||||
<div class="content-container tight">
|
||||
<h1>Server error 😵</h1>
|
||||
<p>Please <a href="https://github.com/writefreely/writefreely/issues/new">contact the human authors</a> of this software and remind them of their many shortcomings.</p>
|
||||
<p>Be gentle, though. They are fragile mortal beings.</p>
|
||||
<p style="margin-top:2em">Also, unlike the AI that will soon replace them, you will need to include an error log from the server in your report. (Utterly <em>primitive</em>, we know.)</p>
|
||||
<p>– {{.SiteName}} 🤖</p>
|
||||
</div>
|
||||
{{end}}
|
|
@ -0,0 +1,7 @@
|
|||
{{define "head"}}<title>Temporarily Unavailable — {{.SiteMetaName}}</title>{{end}}
|
||||
{{define "content"}}
|
||||
<div class="error-page">
|
||||
<p class="msg">The words aren't coming to me. 🗅</p>
|
||||
<p>We couldn't serve this page due to high server load. This should only be temporary.</p>
|
||||
</div>
|
||||
{{end}}
|
|
@ -0,0 +1,29 @@
|
|||
{{define "head"}}<title>{{.ContentTitle}} — {{.SiteName}}</title>
|
||||
<meta name="description" content="{{.PlainContent}}">
|
||||
{{end}}
|
||||
{{define "content"}}
|
||||
<div class="content-container snug">
|
||||
<h1>{{.ContentTitle}}</h1>
|
||||
|
||||
{{.Content}}
|
||||
|
||||
{{if .PublicStats}}
|
||||
<hr style="margin:1.5em 0;" />
|
||||
<p><em>{{.SiteName}}</em> is home to <strong>{{largeNumFmt .AboutStats.NumPosts}}</strong> {{pluralize "article" "articles" .AboutStats.NumPosts}} across <strong>{{largeNumFmt .AboutStats.NumBlogs}}</strong> {{pluralize "blog" "blogs" .AboutStats.NumBlogs}}.</p>
|
||||
{{end}}
|
||||
|
||||
{{if not .WFModesty}}
|
||||
<h2 style="margin-top:2em">About WriteFreely</h2>
|
||||
<p><a href="https://writefreely.org">WriteFreely</a> is a self-hosted, decentralized blogging platform for publishing beautiful, simple blogs.</p>
|
||||
<p>It lets you publish a single blog, or host a community of writers who can create multiple blogs under one account. You can also enable federation, which allows people in the fediverse to follow your blog, bookmark your posts, and share them with others.</p>
|
||||
<div class="clearfix blurbs" style="font-size: 1.3em;text-align:center">
|
||||
<div class="half big">
|
||||
<p><a href="https://writefreely.org/start">Start an instance</a></p>
|
||||
</div>
|
||||
<div class="half big">
|
||||
<p><a href="https://writefreely.org">WriteFreely</a></p>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
|
@ -0,0 +1,2 @@
|
|||
{{define "head"}}<title>{{.Title}} — {{.SiteName}}</title>{{end}}
|
||||
{{define "content"}}<div class="content-container">{{.Content}}</div>{{end}}
|
|
@ -0,0 +1,203 @@
|
|||
{{define "head"}}
|
||||
<title>{{.SiteName}}</title>
|
||||
|
||||
<style type="text/css">
|
||||
h2 {
|
||||
font-weight: normal;
|
||||
}
|
||||
#pricing.content-container div.form-container #payment-form {
|
||||
display: block !important;
|
||||
}
|
||||
#pricing #signup-form table {
|
||||
max-width: inherit !important;
|
||||
width: 100%;
|
||||
}
|
||||
#pricing #payment-form table {
|
||||
margin-top: 0 !important;
|
||||
max-width: inherit !important;
|
||||
width: 100%;
|
||||
}
|
||||
tr.subscription {
|
||||
border-spacing: 0;
|
||||
}
|
||||
#pricing.content-container tr.subscription button {
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
width: 100%;
|
||||
}
|
||||
#pricing tr.subscription td {
|
||||
padding: 0 0.5em;
|
||||
}
|
||||
#pricing table.billing > tbody > tr > td:first-child {
|
||||
vertical-align: middle !important;
|
||||
}
|
||||
.billing-section {
|
||||
display: none;
|
||||
}
|
||||
.billing-section.bill-me {
|
||||
display: table-row;
|
||||
}
|
||||
#btn-create {
|
||||
color: white !important;
|
||||
}
|
||||
#total-price {
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
#alias-site.demo {
|
||||
color: #999;
|
||||
}
|
||||
#alias-site {
|
||||
text-align: left;
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
form dd {
|
||||
margin: 0;
|
||||
}
|
||||
.banner-container {
|
||||
text-align: left;
|
||||
}
|
||||
.banner-container h1 {
|
||||
margin-top: 0;
|
||||
max-width: 8em;
|
||||
}
|
||||
.or {
|
||||
margin-bottom: 2.5em !important;
|
||||
}
|
||||
</style>
|
||||
{{end}}
|
||||
{{define "content"}}
|
||||
<div id="pricing" class="content-container wide-form">
|
||||
|
||||
<div class="row">
|
||||
<div class="banner-container">
|
||||
{{.Banner}}
|
||||
<p><a href="{{if .Content}}#more{{else}}/about{{end}}">Learn more...</a></p>
|
||||
</div>
|
||||
|
||||
<div{{if not .OpenRegistration}} style="padding: 2em 0;"{{end}}>
|
||||
{{ if .OpenRegistration }}
|
||||
{{template "oauth-buttons" .}}
|
||||
{{if not .DisablePasswordAuth}}
|
||||
{{if .Flashes}}<ul class="errors">
|
||||
{{range .Flashes}}<li class="urgent">{{.}}</li>{{end}}
|
||||
</ul>{{end}}
|
||||
|
||||
<div id="billing">
|
||||
<form action="/auth/signup" method="POST" id="signup-form" onsubmit="return signup()">
|
||||
<dl class="billing">
|
||||
<label>
|
||||
<dt>Username</dt>
|
||||
<dd>
|
||||
<input type="text" id="alias" name="alias" style="width: 100%; box-sizing: border-box;" tabindex="1" autofocus {{if .ForcedLanding}}disabled{{end}} />
|
||||
{{if .Federation}}<p id="alias-site" class="demo">@<strong>your-username</strong>@{{.FriendlyHost}}</p>{{else}}<p id="alias-site" class="demo">{{.FriendlyHost}}/<strong>your-username</strong></p>{{end}}
|
||||
</dd>
|
||||
</label>
|
||||
<label>
|
||||
<dt>Password</dt>
|
||||
<dd><input type="password" id="password" name="pass" autocomplete="new-password" placeholder="" tabindex="2" style="width: 100%; box-sizing: border-box;" {{if .ForcedLanding}}disabled{{end}} /></dd>
|
||||
</label>
|
||||
<label>
|
||||
<dt>Email (optional)</dt>
|
||||
<dd><input type="email" name="email" id="email" style="letter-spacing: 1px; width: 100%; box-sizing: border-box;" placeholder="me@example.com" tabindex="3" {{if .ForcedLanding}}disabled{{end}} /></dd>
|
||||
</label>
|
||||
<dt>
|
||||
<button id="btn-create" type="submit" style="margin-top: 0" {{if .ForcedLanding}}disabled{{end}}>Create blog</button>
|
||||
</dt>
|
||||
</dl>
|
||||
</form>
|
||||
</div>
|
||||
{{end}}
|
||||
{{ else }}
|
||||
<p style="font-size: 1.3em; margin: 1rem 0;">Registration is currently closed.</p>
|
||||
<p>You can always sign up on <a href="https://writefreely.org/instances">another instance</a>.</p>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{if .Content}}
|
||||
<a name="more"></a><hr style="margin: 1em auto 3em;" />
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
{{ if .Content }}
|
||||
<div class="content-container snug">
|
||||
{{.Content}}
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
<script type="text/javascript" src="/js/h.js"></script>
|
||||
<script type="text/javascript">
|
||||
function signup() {
|
||||
var $pass = document.getElementById('password');
|
||||
|
||||
// Validate input
|
||||
if (!aliasOK) {
|
||||
var $a = $alias;
|
||||
$a.el.className = 'error';
|
||||
$a.el.focus();
|
||||
$a.el.scrollIntoView();
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($pass.value == "") {
|
||||
var $a = $pass;
|
||||
$a.className = 'error';
|
||||
$a.focus();
|
||||
$a.scrollIntoView();
|
||||
return false;
|
||||
}
|
||||
|
||||
var $btn = document.getElementById('btn-create');
|
||||
$btn.disabled = true;
|
||||
$btn.value = 'Creating...';
|
||||
return true;
|
||||
}
|
||||
|
||||
var $alias = H.getEl('alias');
|
||||
var $aliasSite = document.getElementById('alias-site');
|
||||
var aliasOK = true;
|
||||
var typingTimer;
|
||||
var doneTypingInterval = 750;
|
||||
var doneTyping = function() {
|
||||
// Check on username
|
||||
var alias = $alias.el.value;
|
||||
if (alias != "") {
|
||||
var params = {
|
||||
username: alias
|
||||
};
|
||||
var http = new XMLHttpRequest();
|
||||
http.open("POST", '/api/alias', true);
|
||||
|
||||
// Send the proper header information along with the request
|
||||
http.setRequestHeader("Content-type", "application/json");
|
||||
|
||||
http.onreadystatechange = function() {
|
||||
if (http.readyState == 4) {
|
||||
data = JSON.parse(http.responseText);
|
||||
if (http.status == 200) {
|
||||
aliasOK = true;
|
||||
$alias.removeClass('error');
|
||||
$aliasSite.className = $aliasSite.className.replace(/(?:^|\s)demo(?!\S)/g, '');
|
||||
$aliasSite.className = $aliasSite.className.replace(/(?:^|\s)error(?!\S)/g, '');
|
||||
$aliasSite.innerHTML = '{{ if .Federation }}@<strong>' + data.data + '</strong>@{{.FriendlyHost}}{{ else }}{{.FriendlyHost}}/<strong>' + data.data + '</strong>/{{ end }}';
|
||||
} else {
|
||||
aliasOK = false;
|
||||
$alias.setClass('error');
|
||||
$aliasSite.className = 'error';
|
||||
$aliasSite.textContent = data.error_msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
http.send(JSON.stringify(params));
|
||||
} else {
|
||||
$aliasSite.className += ' demo';
|
||||
$aliasSite.innerHTML = '{{ if .Federation }}@<strong>your-username</strong>@{{.FriendlyHost}}{{ else }}{{.FriendlyHost}}/<strong>your-username</strong>/{{ end }}';
|
||||
}
|
||||
};
|
||||
$alias.on('keyup input', function() {
|
||||
clearTimeout(typingTimer);
|
||||
typingTimer = setTimeout(doneTyping, doneTypingInterval);
|
||||
});
|
||||
</script>
|
||||
|
||||
{{end}}
|
|
@ -0,0 +1,36 @@
|
|||
{{define "head"}}<title>Log in — {{.SiteName}}</title>
|
||||
<meta name="description" content="Log in to {{.SiteName}}.">
|
||||
<meta itemprop="description" content="Log in to {{.SiteName}}.">
|
||||
<style>
|
||||
input{margin-bottom:0.5em;}
|
||||
</style>
|
||||
{{end}}
|
||||
{{define "content"}}
|
||||
<div class="tight content-container">
|
||||
<h1>Log in to {{.SiteName}}</h1>
|
||||
|
||||
{{if .Flashes}}<ul class="errors">
|
||||
{{range .Flashes}}<li class="urgent">{{.}}</li>{{end}}
|
||||
</ul>{{end}}
|
||||
|
||||
{{template "oauth-buttons" .}}
|
||||
|
||||
{{if not .DisablePasswordAuth}}
|
||||
<form action="/auth/login" method="post" style="text-align: center;margin-top:1em;" onsubmit="disableSubmit()">
|
||||
<input type="text" name="alias" placeholder="Username" value="{{.LoginUsername}}" {{if not .LoginUsername}}autofocus{{end}} /><br />
|
||||
<input type="password" name="pass" placeholder="Password" {{if .LoginUsername}}autofocus{{end}} /><br />
|
||||
{{if .To}}<input type="hidden" name="to" value="{{.To}}" />{{end}}
|
||||
<input type="submit" id="btn-login" value="Login" />
|
||||
</form>
|
||||
|
||||
{{if and (not .SingleUser) .OpenRegistration}}<p style="text-align:center;font-size:0.9em;margin:3em auto;max-width:26em;">{{if .Message}}{{.Message}}{{else}}<em>No account yet?</em> <a href="{{.SignupPath}}">Sign up</a> to start a blog.{{end}}</p>{{end}}
|
||||
|
||||
<script type="text/javascript">
|
||||
function disableSubmit() {
|
||||
var $btn = document.getElementById("btn-login");
|
||||
$btn.value = "Logging in...";
|
||||
$btn.disabled = true;
|
||||
}
|
||||
</script>
|
||||
{{end}}
|
||||
{{end}}
|
|
@ -0,0 +1,10 @@
|
|||
{{define "head"}}<title>{{.ContentTitle}} — {{.SiteName}}</title>
|
||||
<meta name="description" content="{{.PlainContent}}">
|
||||
{{end}}
|
||||
{{define "content"}}<div class="content-container snug">
|
||||
<h1>{{.ContentTitle}}</h1>
|
||||
<p style="font-style:italic">Last updated {{.Updated}}</p>
|
||||
|
||||
{{.Content}}
|
||||
</div>
|
||||
{{end}}
|
|
@ -0,0 +1,186 @@
|
|||
{{define "head"}}<title>Finish Creating Account — {{.SiteName}}</title>
|
||||
<style>input{margin-bottom:0.5em;}</style>
|
||||
<style type="text/css">
|
||||
h2 {
|
||||
font-weight: normal;
|
||||
}
|
||||
#pricing.content-container div.form-container #payment-form {
|
||||
display: block !important;
|
||||
}
|
||||
#pricing #signup-form table {
|
||||
max-width: inherit !important;
|
||||
width: 100%;
|
||||
}
|
||||
#pricing #payment-form table {
|
||||
margin-top: 0 !important;
|
||||
max-width: inherit !important;
|
||||
width: 100%;
|
||||
}
|
||||
tr.subscription {
|
||||
border-spacing: 0;
|
||||
}
|
||||
#pricing.content-container tr.subscription button {
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
width: 100%;
|
||||
}
|
||||
#pricing tr.subscription td {
|
||||
padding: 0 0.5em;
|
||||
}
|
||||
#pricing table.billing > tbody > tr > td:first-child {
|
||||
vertical-align: middle !important;
|
||||
}
|
||||
.billing-section {
|
||||
display: none;
|
||||
}
|
||||
.billing-section.bill-me {
|
||||
display: table-row;
|
||||
}
|
||||
#btn-create {
|
||||
color: white !important;
|
||||
}
|
||||
#total-price {
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
#alias-site.demo {
|
||||
color: #999;
|
||||
}
|
||||
#alias-site {
|
||||
text-align: left;
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
form dd {
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
{{end}}
|
||||
{{define "content"}}
|
||||
<div id="pricing" class="tight content-container">
|
||||
<h1>Finish creating account</h1>
|
||||
|
||||
{{if .Flashes}}<ul class="errors">
|
||||
{{range .Flashes}}<li class="urgent">{{.}}</li>{{end}}
|
||||
</ul>{{end}}
|
||||
|
||||
<div id="billing">
|
||||
<form action="/oauth/signup" method="post" style="text-align: center;margin-top:1em;" onsubmit="return disableSubmit()">
|
||||
<input type="hidden" name="access_token" value="{{ .AccessToken }}" />
|
||||
<input type="hidden" name="token_username" value="{{ .TokenUsername }}" />
|
||||
<input type="hidden" name="token_alias" value="{{ .TokenAlias }}" />
|
||||
<input type="hidden" name="token_email" value="{{ .TokenEmail }}" />
|
||||
<input type="hidden" name="token_remote_user" value="{{ .TokenRemoteUser }}" />
|
||||
<input type="hidden" name="provider" value="{{ .Provider }}" />
|
||||
<input type="hidden" name="client_id" value="{{ .ClientID }}" />
|
||||
<input type="hidden" name="signature" value="{{ .TokenHash }}" />
|
||||
{{if .InviteCode}}<input type="hidden" name="invite_code" value="{{ .InviteCode }}" />{{end}}
|
||||
|
||||
<dl class="billing">
|
||||
<label>
|
||||
<dt>Display Name</dt>
|
||||
<dd>
|
||||
<input type="text" style="width: 100%; box-sizing: border-box;" name="alias" placeholder="Name"{{ if .Alias }} value="{{.Alias}}"{{ end }} />
|
||||
</dd>
|
||||
</label>
|
||||
<label>
|
||||
<dt>Username</dt>
|
||||
<dd>
|
||||
<input type="text" id="username" name="username" style="width: 100%; box-sizing: border-box;" placeholder="Username" value="{{.LoginUsername}}" /><br />
|
||||
{{if .Federation}}<p id="alias-site" class="demo">@<strong>your-username</strong>@{{.FriendlyHost}}</p>{{else}}<p id="alias-site" class="demo">{{.FriendlyHost}}/<strong>your-username</strong></p>{{end}}
|
||||
</dd>
|
||||
</label>
|
||||
<label>
|
||||
<dt>Email</dt>
|
||||
<dd>
|
||||
<input type="text" name="email" style="width: 100%; box-sizing: border-box;" placeholder="Email"{{ if .Email }} value="{{.Email}}"{{ end }} />
|
||||
</dd>
|
||||
</label>
|
||||
<dt>
|
||||
<input type="submit" id="btn-login" value="Next" />
|
||||
</dt>
|
||||
</dl>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="/js/h.js"></script>
|
||||
<script type="text/javascript">
|
||||
// Copied from signup.tmpl
|
||||
// NOTE: this element is named "alias" on signup.tmpl and "username" here
|
||||
var $alias = H.getEl('username');
|
||||
|
||||
function disableSubmit() {
|
||||
// Validate input
|
||||
if (!aliasOK) {
|
||||
var $a = $alias;
|
||||
$a.el.className = 'error';
|
||||
$a.el.focus();
|
||||
$a.el.scrollIntoView();
|
||||
return false;
|
||||
}
|
||||
|
||||
var $btn = document.getElementById("btn-login");
|
||||
$btn.value = "Logging in...";
|
||||
$btn.disabled = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Copied from signup.tmpl
|
||||
var $aliasSite = document.getElementById('alias-site');
|
||||
var aliasOK = true;
|
||||
var typingTimer;
|
||||
var doneTypingInterval = 750;
|
||||
var doneTyping = function(genID) {
|
||||
// Check on username
|
||||
var alias = $alias.el.value;
|
||||
if (alias != "") {
|
||||
var params = {
|
||||
username: alias
|
||||
};
|
||||
var http = new XMLHttpRequest();
|
||||
http.open("POST", '/api/alias', true);
|
||||
|
||||
// Send the proper header information along with the request
|
||||
http.setRequestHeader("Content-type", "application/json");
|
||||
|
||||
http.onreadystatechange = function() {
|
||||
if (http.readyState == 4) {
|
||||
data = JSON.parse(http.responseText);
|
||||
if (http.status == 200) {
|
||||
aliasOK = true;
|
||||
$alias.removeClass('error');
|
||||
$aliasSite.className = $aliasSite.className.replace(/(?:^|\s)demo(?!\S)/g, '');
|
||||
$aliasSite.className = $aliasSite.className.replace(/(?:^|\s)error(?!\S)/g, '');
|
||||
$aliasSite.innerHTML = '{{ if .Federation }}@<strong>' + data.data + '</strong>@{{.FriendlyHost}}{{ else }}{{.FriendlyHost}}/<strong>' + data.data + '</strong>/{{ end }}';
|
||||
} else {
|
||||
if (genID === true) {
|
||||
$alias.el.value = alias + "-" + randStr(4);
|
||||
doneTyping();
|
||||
return;
|
||||
}
|
||||
aliasOK = false;
|
||||
$alias.setClass('error');
|
||||
$aliasSite.className = 'error';
|
||||
$aliasSite.textContent = data.error_msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
http.send(JSON.stringify(params));
|
||||
} else {
|
||||
$aliasSite.className += ' demo';
|
||||
$aliasSite.innerHTML = '{{ if .Federation }}@<strong>your-username</strong>@{{.FriendlyHost}}{{ else }}{{.FriendlyHost}}/<strong>your-username</strong>/{{ end }}';
|
||||
}
|
||||
};
|
||||
$alias.on('keyup input', function() {
|
||||
clearTimeout(typingTimer);
|
||||
typingTimer = setTimeout(doneTyping, doneTypingInterval);
|
||||
});
|
||||
function randStr(len) {
|
||||
var res = '';
|
||||
var chars = '23456789bcdfghjklmnpqrstvwxyz';
|
||||
for (var i=0; i<len; i++) {
|
||||
res += chars.charAt(Math.floor(Math.random() * chars.length));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
doneTyping(true);
|
||||
</script>
|
||||
{{end}}
|
|
@ -0,0 +1,180 @@
|
|||
{{define "head"}}
|
||||
<title>Sign up — {{.SiteName}}</title>
|
||||
|
||||
<style type="text/css">
|
||||
h2 {
|
||||
font-weight: normal;
|
||||
}
|
||||
#pricing.content-container div.form-container #payment-form {
|
||||
display: block !important;
|
||||
}
|
||||
#pricing #signup-form table {
|
||||
max-width: inherit !important;
|
||||
width: 100%;
|
||||
}
|
||||
#pricing #payment-form table {
|
||||
margin-top: 0 !important;
|
||||
max-width: inherit !important;
|
||||
width: 100%;
|
||||
}
|
||||
tr.subscription {
|
||||
border-spacing: 0;
|
||||
}
|
||||
#pricing.content-container tr.subscription button {
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 0 !important;
|
||||
width: 100%;
|
||||
}
|
||||
#pricing tr.subscription td {
|
||||
padding: 0 0.5em;
|
||||
}
|
||||
#pricing table.billing > tbody > tr > td:first-child {
|
||||
vertical-align: middle !important;
|
||||
}
|
||||
.billing-section {
|
||||
display: none;
|
||||
}
|
||||
.billing-section.bill-me {
|
||||
display: table-row;
|
||||
}
|
||||
#btn-create {
|
||||
color: white !important;
|
||||
}
|
||||
#total-price {
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
#alias-site.demo {
|
||||
color: #999;
|
||||
}
|
||||
#alias-site {
|
||||
text-align: left;
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
form dd {
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
{{end}}
|
||||
{{define "content"}}
|
||||
<div id="pricing" class="content-container wide-form">
|
||||
|
||||
<div class="row">
|
||||
<div style="margin: 0 auto; max-width: 25em;">
|
||||
<h1>Sign up</h1>
|
||||
|
||||
{{ if .Error }}
|
||||
<p style="font-style: italic">{{.Error}}</p>
|
||||
{{ else }}
|
||||
{{if .Flashes}}<ul class="errors">
|
||||
{{range .Flashes}}<li class="urgent">{{.}}</li>{{end}}
|
||||
</ul>{{end}}
|
||||
|
||||
<div id="billing">
|
||||
{{template "oauth-buttons" .}}
|
||||
|
||||
{{if not .DisablePasswordAuth}}
|
||||
<form action="/auth/signup" method="POST" id="signup-form" onsubmit="return signup()">
|
||||
<input type="hidden" name="invite_code" value="{{.Invite}}" />
|
||||
<dl class="billing">
|
||||
<label>
|
||||
<dt>Username</dt>
|
||||
<dd>
|
||||
<input type="text" id="alias" name="alias" style="width: 100%; box-sizing: border-box;" tabindex="1" autofocus />
|
||||
{{if .Federation}}<p id="alias-site" class="demo">@<strong>your-username</strong>@{{.FriendlyHost}}</p>{{else}}<p id="alias-site" class="demo">{{.FriendlyHost}}/<strong>your-username</strong></p>{{end}}
|
||||
</dd>
|
||||
</label>
|
||||
<label>
|
||||
<dt>Password</dt>
|
||||
<dd><input type="password" id="password" name="pass" autocomplete="new-password" placeholder="" tabindex="2" style="width: 100%; box-sizing: border-box;" /></dd>
|
||||
</label>
|
||||
<label>
|
||||
<dt>Email (optional)</dt>
|
||||
<dd><input type="email" name="email" id="email" style="letter-spacing: 1px; width: 100%; box-sizing: border-box;" placeholder="me@example.com" tabindex="3" /></dd>
|
||||
</label>
|
||||
<dt>
|
||||
<button id="btn-create" type="submit" style="margin-top: 0">Create blog</button>
|
||||
</dt>
|
||||
</dl>
|
||||
</form>
|
||||
{{end}}
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" src="/js/h.js"></script>
|
||||
<script type="text/javascript">
|
||||
function signup() {
|
||||
var $pass = document.getElementById('password');
|
||||
|
||||
// Validate input
|
||||
if (!aliasOK) {
|
||||
var $a = $alias;
|
||||
$a.el.className = 'error';
|
||||
$a.el.focus();
|
||||
$a.el.scrollIntoView();
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($pass.value == "") {
|
||||
var $a = $pass;
|
||||
$a.className = 'error';
|
||||
$a.focus();
|
||||
$a.scrollIntoView();
|
||||
return false;
|
||||
}
|
||||
|
||||
var $btn = document.getElementById('btn-create');
|
||||
$btn.disabled = true;
|
||||
$btn.value = 'Creating...';
|
||||
return true;
|
||||
}
|
||||
|
||||
var $alias = H.getEl('alias');
|
||||
var $aliasSite = document.getElementById('alias-site');
|
||||
var aliasOK = true;
|
||||
var typingTimer;
|
||||
var doneTypingInterval = 750;
|
||||
var doneTyping = function() {
|
||||
// Check on username
|
||||
var alias = $alias.el.value;
|
||||
if (alias != "") {
|
||||
var params = {
|
||||
username: alias
|
||||
};
|
||||
var http = new XMLHttpRequest();
|
||||
http.open("POST", '/api/alias', true);
|
||||
|
||||
// Send the proper header information along with the request
|
||||
http.setRequestHeader("Content-type", "application/json");
|
||||
|
||||
http.onreadystatechange = function() {
|
||||
if (http.readyState == 4) {
|
||||
data = JSON.parse(http.responseText);
|
||||
if (http.status == 200) {
|
||||
aliasOK = true;
|
||||
$alias.removeClass('error');
|
||||
$aliasSite.className = $aliasSite.className.replace(/(?:^|\s)demo(?!\S)/g, '');
|
||||
$aliasSite.className = $aliasSite.className.replace(/(?:^|\s)error(?!\S)/g, '');
|
||||
$aliasSite.innerHTML = '{{ if .Federation }}@<strong>' + data.data + '</strong>@{{.FriendlyHost}}{{ else }}{{.FriendlyHost}}/<strong>' + data.data + '</strong>/{{ end }}';
|
||||
} else {
|
||||
aliasOK = false;
|
||||
$alias.setClass('error');
|
||||
$aliasSite.className = 'error';
|
||||
$aliasSite.textContent = data.error_msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
http.send(JSON.stringify(params));
|
||||
} else {
|
||||
$aliasSite.className += ' demo';
|
||||
$aliasSite.innerHTML = '{{ if .Federation }}@<strong>your-username</strong>@{{.FriendlyHost}}{{ else }}{{.FriendlyHost}}/<strong>your-username</strong>/{{ end }}';
|
||||
}
|
||||
};
|
||||
$alias.on('keyup input', function() {
|
||||
clearTimeout(typingTimer);
|
||||
typingTimer = setTimeout(doneTyping, doneTypingInterval);
|
||||
});
|
||||
</script>
|
||||
|
||||
{{end}}
|
|
@ -0,0 +1 @@
|
|||
*.css
|
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 275 KiB |
After Width: | Height: | Size: 104 KiB |
After Width: | Height: | Size: 105 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 5.6 KiB |
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 7.7 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 9.2 KiB |
After Width: | Height: | Size: 17 KiB |
After Width: | Height: | Size: 16 KiB |
After Width: | Height: | Size: 6.7 KiB |
After Width: | Height: | Size: 7.2 KiB |
After Width: | Height: | Size: 5.9 KiB |
After Width: | Height: | Size: 7.1 KiB |
After Width: | Height: | Size: 6.5 KiB |
After Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 2.6 KiB |
After Width: | Height: | Size: 6.1 KiB |
After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 5.7 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 7.4 KiB |
After Width: | Height: | Size: 7.1 KiB |
After Width: | Height: | Size: 7.1 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 6.9 KiB |
After Width: | Height: | Size: 6.0 KiB |
After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 199 B |
After Width: | Height: | Size: 195 B |
After Width: | Height: | Size: 485 B |
After Width: | Height: | Size: 439 B |
After Width: | Height: | Size: 168 B |
After Width: | Height: | Size: 160 B |
After Width: | Height: | Size: 239 B |
After Width: | Height: | Size: 222 B |
After Width: | Height: | Size: 105 B |
After Width: | Height: | Size: 110 B |
After Width: | Height: | Size: 655 B |
After Width: | Height: | Size: 640 B |
After Width: | Height: | Size: 94 B |
After Width: | Height: | Size: 106 B |
After Width: | Height: | Size: 344 B |
After Width: | Height: | Size: 432 B |
After Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 1005 B |
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 2.7 KiB |
After Width: | Height: | Size: 2.8 KiB |
|
@ -0,0 +1,78 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="15mm"
|
||||
height="15mm"
|
||||
viewBox="0 0 15 15"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
sodipodi:docname="paidarticle.svg"
|
||||
inkscape:version="0.92.3 (2405546, 2018-03-11)">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="3.959798"
|
||||
inkscape:cx="32.178691"
|
||||
inkscape:cy="9.7652796"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:window-width="1280"
|
||||
inkscape:window-height="720"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="26"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-97.650089,-94.91132)">
|
||||
<circle
|
||||
style="opacity:0.83300003;fill:#72bf85;fill-opacity:1;stroke:none;stroke-width:1.14235425;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path819"
|
||||
cx="105.15009"
|
||||
cy="102.41132"
|
||||
r="7.5" />
|
||||
<g
|
||||
aria-label="$"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:10.58333302px;line-height:125%;font-family:'Open Sans';-inkscape-font-specification:'Open Sans Bold';letter-spacing:0px;word-spacing:0px;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
id="text817"
|
||||
transform="translate(0.15009808,-0.15009445)">
|
||||
<path
|
||||
d="m 107.59415,103.90759 q 0,0.82166 -0.59427,1.32292 -0.59428,0.49609 -1.66399,0.59428 v 1.05936 h -0.70796 v -1.03869 q -1.26091,-0.0258 -2.21175,-0.44442 v -1.36426 q 0.44958,0.22221 1.08003,0.39274 0.63562,0.17053 1.13172,0.20154 v -1.60197 l -0.34624,-0.13436 q -1.02319,-0.40307 -1.4521,-0.87333 -0.42375,-0.47542 -0.42375,-1.17305 0,-0.74931 0.58394,-1.229903 0.58912,-0.485759 1.63815,-0.589112 v -0.790649 h 0.70796 v 0.769979 q 1.18339,0.05168 2.13941,0.475423 l -0.48576,1.209232 q -0.80615,-0.33073 -1.65365,-0.40308 v 1.52445 q 1.00769,0.38758 1.43144,0.6718 0.42892,0.28422 0.62529,0.62528 0.20153,0.34107 0.20153,0.79582 z m -1.55546,0.0775 q 0,-0.21704 -0.1757,-0.3669 -0.1757,-0.14986 -0.5271,-0.31006 v 1.28675 q 0.7028,-0.11886 0.7028,-0.60979 z m -2.07739,-3.13675 q 0,0.22737 0.15503,0.37723 0.1602,0.1447 0.5116,0.29973 v -1.2144 q -0.66663,0.0982 -0.66663,0.53744 z"
|
||||
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-family:'Open Sans';-inkscape-font-specification:'Open Sans Bold';fill:#ffffff;fill-opacity:1;stroke-width:0.26458332px"
|
||||
id="path821"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.6 KiB |