Add invitations
This commit is contained in:
parent
29543026ed
commit
600a6af27a
11 changed files with 465 additions and 19 deletions
80
roc_fnb/website/templates/new_invite.html
Normal file
80
roc_fnb/website/templates/new_invite.html
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
{% extends "base.html" %}
|
||||
<div></div>
|
||||
{% block content %}
|
||||
<script>
|
||||
let inviteCode
|
||||
function inviteElements() {
|
||||
return {
|
||||
doneView: document.getElementById('done-view'),
|
||||
inviteDisplay: document.getElementById('invite-code'),
|
||||
}
|
||||
}
|
||||
function copyInviteCodeToClipboard() {
|
||||
navigator.clipboard
|
||||
.writeText(inviteCode)
|
||||
.then(() => alert('invite code copied to clipboard'))
|
||||
}
|
||||
async function newInviteCode() {
|
||||
const { doneView, inviteDisplay } = inviteElements()
|
||||
const response = await fetch('/invite', {
|
||||
headers: { Accept: 'application/json' },
|
||||
})
|
||||
if (response.ok) {
|
||||
const { invite } = await response.json()
|
||||
inviteDisplay.innerText = inviteCode = invite
|
||||
doneView.style.display = 'inherit'
|
||||
} else {
|
||||
console.dir('response')
|
||||
alert('error creating new invite code')
|
||||
}
|
||||
}
|
||||
async function deleteInvite() {
|
||||
const { doneView, inviteDisplay } = inviteElements()
|
||||
const response = await fetch('/invite', {
|
||||
method: 'DELETE',
|
||||
body: JSON.stringify({ invite_code: inviteCode }),
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
})
|
||||
if (response.ok) {
|
||||
inviteCode = null
|
||||
inviteDisplay.innerText = ""
|
||||
doneView.display = 'none'
|
||||
}
|
||||
}
|
||||
document.addEventListener('readystatechange', () => {
|
||||
if (document.readyState === 'complete') {
|
||||
const doneView = inviteElements()
|
||||
doneView.style.display = 'none'
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<img
|
||||
id="biglogo"
|
||||
class="spinny"
|
||||
onclick="start_animation()"
|
||||
src="logo.png"
|
||||
alt="logo"
|
||||
/>
|
||||
<h1>Rochester Food Not Bombs!</h1>
|
||||
|
||||
<div>
|
||||
<div>
|
||||
<label for="invite-description"
|
||||
>Describe the invitation for future reference</label
|
||||
>
|
||||
</div>
|
||||
<button>Click here to generate a new invite code</button>
|
||||
</div>
|
||||
<div id="done-view">
|
||||
<p>
|
||||
Tell the new user to visit
|
||||
<a href="/new-user">https://{{app_hostname}}/new-user</a>.
|
||||
</p>
|
||||
|
||||
<p>They will need this invite code:</p>
|
||||
<pre id="invite-code"></pre>
|
||||
<button onclick="copyInviteCodeToClipboard()">Click here to copy it</button>
|
||||
<button onclick="deleteInvite()">Delete invite</button>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
91
roc_fnb/website/templates/sign-up.html
Normal file
91
roc_fnb/website/templates/sign-up.html
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
{% extends "base.html" %} {% block content %}
|
||||
|
||||
<script>
|
||||
document.addEventListener("readystatechange", () => {
|
||||
if (document.readyState === "complete") {
|
||||
/**
|
||||
* @type {HTMLInputElement}
|
||||
*/
|
||||
const nameInput = document.getElementById("input-name");
|
||||
/**
|
||||
* @type {HTMLInputElement}
|
||||
*/
|
||||
const passwordInput = document.getElementById("input-password");
|
||||
/**
|
||||
* @type {HTMLInputElement}
|
||||
*/
|
||||
const emailInput = document.getElementById("input-name");
|
||||
/**
|
||||
* @type {HTMLInputElement}
|
||||
*/
|
||||
const pwConfInput = document.getElementById("input-password");
|
||||
/**
|
||||
* @type {HTMLInputElement}
|
||||
*/
|
||||
const inviteCodeInput = document.getElementById("input-password");
|
||||
/**
|
||||
* @type {HTMLButtonElement}
|
||||
*/
|
||||
const button = document.getElementById("submit-button");
|
||||
button.addEventListener("click", async (event) => {
|
||||
const name = nameInput.value;
|
||||
const password = passwordInput.value;
|
||||
if (password !== pwConfInput.value) {
|
||||
// TODO better handle errors
|
||||
alert("passwords do not match")
|
||||
return
|
||||
}
|
||||
const invite_code = inviteCodeInput.value
|
||||
const email = emailInput.value
|
||||
const result = await fetch("/login", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ name, password, invite_code, email }),
|
||||
headers: {'Content-Type': 'application/json'}
|
||||
});
|
||||
if (result.ok) {
|
||||
window.location = '/me'
|
||||
} else {
|
||||
console.dir(result)
|
||||
// TODO handle error!
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<img
|
||||
id="biglogo"
|
||||
class="spinny"
|
||||
onclick="start_animation()"
|
||||
src="logo.png"
|
||||
alt="logo"
|
||||
/>
|
||||
<h1>Rochester Food Not Bombs!</h1>
|
||||
|
||||
<h3>Login:</h3>
|
||||
|
||||
<div>
|
||||
<label for="name">Your name</label>
|
||||
<input type="text" id="input-name" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="password">Your password</label>
|
||||
<input type="password" id="input-password" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="password">Confirm your password</label>
|
||||
<input type="password" id="input-password" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="invite_code">Invitation Code</label>
|
||||
<input type="password" id="input-invitation" />
|
||||
</div>
|
||||
<div>
|
||||
<label for="email">Entering an email makes web site administration easier</label>
|
||||
<input type="email" name="email" id="input-email" />
|
||||
</div>
|
||||
<div>
|
||||
<button id="submit-button" type="submit">Log in</button>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
Loading…
Add table
Add a link
Reference in a new issue