Skip to content

Commit

Permalink
feat: Adjust copy for setup.
Browse files Browse the repository at this point in the history
  • Loading branch information
RubenVerborgh committed Sep 23, 2021
1 parent 1a3f5d6 commit 868429e
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 157 deletions.
140 changes: 75 additions & 65 deletions templates/identity/email-password/register-partial.html.ejs
@@ -1,5 +1,7 @@
<% const isBlankForm = !('prefilled' in locals); %>
<% prefilled = locals.prefilled || {}; %>
<%
const isBlankForm = !('prefilled' in locals);
prefilled = locals.prefilled || {};
%>

<fieldset>
<legend>Your WebID</legend>
Expand Down Expand Up @@ -47,37 +49,35 @@
<fieldset>
<legend>Your Pod</legend>
<p>
A Pod is a place to store your data.
<br>
If you create a new WebID, you must also create a Pod to store that WebID.
A Pod is a storage place for your data.
</p>
<ol>
<li class="checkbox">
<label>
<input type="checkbox" id="createPod" name="createPod"<%
if (isBlankForm || prefilled.createPod) { %> checked<% } %>>
Create a new Pod with my WebID as owner
Create a new Pod with my WebID as owner<% if (!locals.allowRoot) { %>.<% } %>
</label>
<ol id="createPodForm">
<li class="radio" id="rootPodOnForm">
<label>
<input type="radio" id="rootPodOn" name="rootPod" value="on"<%
if (locals.allowRoot && (isBlankForm || prefilled.rootPod)) { %> checked<% } %>>
... in the root.
</label>
</li>
<li class="radio">
<label>
<input type="radio" id="rootPodOff" name="rootPod" value=""<%
if (!locals.allowRoot || (!isBlankForm && !prefilled.rootPod)) { %> checked<% } %>>
... in its own namespace.
</label>
<ol id="podNameForm">
<li>
<label for="podName">Pod name:</label>
<input id="podName" type="text" name="podName" value="<%= prefilled.podName || '' %>">
</li>
</ol>
<% if (locals.allowRoot) { %>
<li class="radio">
<label>
<input type="radio" id="rootPodOn" name="rootPod" value="on"<%
if (isBlankForm || prefilled.rootPod) { %> checked<% } %>>
in the root.
</label>
</li>
<li class="radio">
<label>
<input type="radio" id="rootPodOff" name="rootPod" value=""<%
if (!isBlankForm && !prefilled.rootPod) { %> checked<% } %>>
in its own namespace.
</label>
</li>
<% } %>
<li id="podNameForm">
<label for="podName">Pod name:</label>
<input id="podName" type="text" name="podName" value="<%= prefilled.podName || '' %>">
</li>
</ol>
</li>
Expand Down Expand Up @@ -116,54 +116,60 @@
</div>
</fieldset>

<!-- Assist the user with filling out the form by hiding irrelevant fields -->
<script>
// Assist the user with filling out the form by hiding irrelevant fields
(() => {
// Wire up the UI elements
const elements = {};
// Wires up the DOM element with the specified ID
function registerElement(id) {
const element = document.getElementById(id) || document.createElement('input');
elements[id] = element;
element.addEventListener('change', synchronizeInputFields);
}
// Wire up all elements
[
'mainForm',
'createWebIdOn', 'createWebIdOff', 'createWebIdForm', 'existingWebIdForm', 'webId',
'createPod', 'createPodForm', 'rootPodOnForm', 'rootPodOn', 'rootPodOff', 'podNameForm', 'podName',
'createPod', 'createPodForm', 'rootPodOn', 'rootPodOff', 'podNameForm', 'podName',
'register', 'passwordForm', 'noPasswordForm',
].forEach(id => {
elements[id] = document.getElementById(id);
elements[id].addEventListener('change', updateUI);
});
elements.mainForm = document.getElementById('<%= formId %>');
].forEach(registerElement);
updateUI();
// Conditions under which elements should be visible
const visibilityConditions = {
createWebIdForm: () => elements.createWebIdOn.checked,
existingWebIdForm: () => elements.createWebIdOff.checked,
createPodForm: () => elements.createPod.checked,
podNameForm: () => !elements.rootPodOn.checked,
passwordForm: () => elements.createWebIdOn.checked || elements.register.checked,
noPasswordForm: () => !isVisible('passwordForm'),
};
// Updates the UI when something has changed
function updateUI({ srcElement } = {}) {
// When Pod creation is required, automatically tick the corresponding checkbox
// Ensures that the only relevant input fields are visible and enabled
function synchronizeInputFields({ srcElement } = {}) {
// The user needs a Pod if they want to create a WebID
if (elements.createWebIdOn.checked)
elements.createPod.checked = true;
elements.createPod.disabled = elements.createWebIdOn.checked;
elements.createPod.checked = true;
// Hide irrelevant fields
setVisibility('createWebIdForm', elements.createWebIdOn.checked);
setVisibility('existingWebIdForm', elements.createWebIdOff.checked);
setVisibility('createPodForm', elements.createPod.checked);
setVisibility('rootPodOnForm', <%= locals.allowRoot %>);
setVisibility('podNameForm', elements.rootPodOff.checked);
setVisibility('passwordForm', elements.createWebIdOn.checked || elements.register.checked);
setVisibility('noPasswordForm', !isVisible('passwordForm'));
for (const [id, condition] of Object.entries(visibilityConditions))
setVisibility(id, condition());
// Lock pod creation if a WebID is requested
elements.createPod.disabled = elements.createWebIdOn.checked;
// If child elements have just been activated, focus on them
if (srcElement?.checked) {
switch(document.activeElement) {
case elements.createWebIdOff:
const { webId } = elements;
webId.value = webId.value.startsWith('http') ? webId.value : 'https://';
webId.focus();
break;
case elements.createPod:
if (elements.rootPodOn.checked) {
break;
}
case elements.rootPodOff:
elements.podName.focus();
break;
case elements.createWebIdOff:
const { webId } = elements;
webId.value = webId.value.startsWith('http') ? webId.value : 'https://';
webId.focus();
break;
case elements.createPod:
case elements.rootPodOff:
elements.podName.focus();
break;
}
}
}
Expand All @@ -182,8 +188,8 @@
// Disable children of hidden elements,
// such that the browser does not expect input for them
for (const child of getDescendants(element)) {
if ('disabled' in child)
child.disabled = !visible;
if ('disabled' in child)
child.disabled = !visible;
}
}
Expand All @@ -192,12 +198,16 @@
return [...element.querySelectorAll("*")];
}
// TODO: take form id as input?
// Prepare the form when the DOM is ready
window.addEventListener('DOMContentLoaded', (event) => {
synchronizeInputFields();
elements.mainForm.classList.add('loaded');
});
// Enable all elements on form submission (otherwise their value is not submitted)
elements.mainForm.addEventListener('submit', () => {
for (const child of getDescendants(elements.mainForm))
child.disabled = false;
child.disabled = false;
});
elements.mainForm.addEventListener('formdata', updateUI);
})();
elements.mainForm.addEventListener('formdata', synchronizeInputFields);
</script>
2 changes: 1 addition & 1 deletion templates/identity/email-password/register.html.ejs
Expand Up @@ -5,7 +5,7 @@
<p class="error">Error: <%= message %></p>
<% } %>

<%- include('./register-partial.html.ejs', { allowRoot: false, formId: 'mainForm' }) %>
<%- include('./register-partial.html.ejs', { allowRoot: false }) %>

<p class="actions"><button type="submit" name="submit">Sign up</button></p>
</form>
39 changes: 8 additions & 31 deletions templates/root/prefilled/index.html
Expand Up @@ -22,22 +22,21 @@ <h1>Welcome to Solid</h1>

<h2 id="users">Getting started as a <em>user</em></h2>
<p>
<strong><a href="/idp/register/">Sign up</a> for an account</strong>
<a href="/idp/register/">Sign up for an account</a>
to get started with your own Pod and WebID.
</p>
<p>
The <em>default</em> configuration stores data only in memory,
so be sure to choose a configuration that saves data to disk.
If you are exposing this server publicly,
<a href="#public">read the guidelines below</a>.
The default configuration stores data only in memory.
If you want to keep data permanently,
choose a configuration that saves data to disk instead.
</p>

<h2 id="developers">Getting started as a <em>developer</em></h2>
<p>
The <em>default</em> server configuration includes
this <strong>ready-to-use root Pod</strong> you're looking at.
That way, you don't need to create an account
to read and write data or to test apps.
<a href="./setup">Run the setup</a> to configure your server.
<br>
The default configuration includes
the <strong>ready-to-use root Pod</strong> you're currently looking at.
</p>
<p>
You can easily choose any folder on your disk
Expand All @@ -46,28 +45,6 @@ <h2 id="developers">Getting started as a <em>developer</em></h2>
Use the <code>--help</code> switch to learn more.
</p>

<h2 id="public">Making this server public</h2>
<p>
Before making this server public,
you might want to <strong>disable certain convenience features</strong>
so they remain only accessible to you:
</p>
<ul>
<li>
Modify or delete this welcome document
at <a href="index.html"><code>index.html</code></a>.
</li>
<li>
Prevent public write and control access to the root Pod
by modifying <a href="../../../.acl"><code>.acl</code></a>.
</li>
<li>
Disable Pod registration
by <a href="https://github.com/solid/community-server/blob/main/config/identity/README.md">changing
the configuration</a>.
</li>
</ul>

<h2>Have a wonderful Solid experience</h2>
<p>
<strong>Learn more about Solid
Expand Down
96 changes: 40 additions & 56 deletions templates/setup/index.html.ejs
@@ -1,39 +1,7 @@
<h1>Welcome to Solid</h1>
<h1>Set up your Solid server</h1>
<p>
This server implements
the <a href="https://solid.github.io/specification/protocol">Solid protocol</a>
so you can create your own <a href="https://solidproject.org/about">Solid Pod</a>
and identity.
</p>

<h2 id="public">Making this server public</h2>
<p>
Before making this server public,
you might want to <strong>disable Pod registration</strong>
by <a href="https://github.com/solid/community-server/blob/main/config/identity/README.md">changing
the configuration</a>.
</p>

<h2 id="setup">Setting up the server</h2>
<p>
The <em>default</em> configuration stores data only in memory,
so be sure to choose a configuration that saves data to disk.
If you are exposing this server publicly,
<a href="#public">read the guidelines below</a>.
</p>
<p>
When using the file-based version of the server,
you can easily choose any folder on your disk to use as root.
<br>
Use the <code>--help</code> switch to learn more.
</p>
<p>
To make sure the server is set up exactly as you want it,
please fill in the form below.
</p>
<p>
In case you want to automate the server initialization and want to get rid of this setup screen,
update your config with new imports from <code>config/app/setup/</code> and possibly <code>config/app/init/</code>.
Your Solid server needs a <strong>one-time setup</strong>
so it acts exactly the way you want.
</p>

<form method="post" id="mainForm">
Expand All @@ -43,46 +11,62 @@
<p class="error"><%= message %></p>
<% } %>
<fieldset>
<legend>Choose options</legend>
<legend>Accounts on this server</legend>
<ol>
<li class="checkbox">
<label>
<input type="checkbox" id="initialize" name="initialize" checked>
Allow access to the root container.
<input type="checkbox" checked disabled>
Enable account registration.
</label>
<p>
This defaults to public access for everyone.
Disabling this makes it impossible to access the root container and add resources,
but new pods can still be created through registration,
which is ideal if you only want data to be edited in the pods.
This option is irrelevant when creating a root pod with the option below.
You can disable account registration
by <a href="https://github.com/solid/community-server/blob/main/config/identity/README.md">changing the configuration</a>.
</p>
</li>
<li class="checkbox">
<label>
<input type="checkbox" id="registration" name="registration" checked>
Provision a pod, create a WebID, and/or register an identity.
<input type="checkbox" id="registration" name="registration">
Sign me up for an account.
</label>
<p>
Any existing root Pod will be disabled.
</p>
</li>
<li class="checkbox" id="initializeForm">
<label>
<input type="checkbox" id="initialize" name="initialize">
Expose a public root Pod.
</label>
<p>
By default, the public has read and write access to the root Pod.
<br>
You typically only want to choose this
for rapid testing and development.
</p>
</li>
</ol>
</fieldset>

<fieldset id="registrationForm">
<%- include('../identity/email-password/register-partial.html.ejs', { allowRoot: true, formId: 'mainForm' }) %>
<legend>Sign up</legend>
<%-
include('../identity/email-password/register-partial.html.ejs', {
allowRoot: true,
})
%>
</fieldset>

<p class="actions"><button type="submit" name="submit">Submit</button></p>
<p class="actions"><button type="submit">Complete setup</button></p>
</form>

<!-- Show or hide the account creation form when needed -->
<script>
const registrationCheckbox = document.getElementById('registration');
registrationCheckbox.addEventListener('change', updateUI);
const registrationForm = document.getElementById('registrationForm');
function updateUI() {
const visible = registrationCheckbox.checked;
registrationForm.classList[visible ? 'remove' : 'add']('hidden');
}
[
'registration', 'registrationForm', 'initializeForm',
].forEach(registerElement);
updateUI();
Object.assign(visibilityConditions, {
registrationForm: () => elements.registration.checked,
initializeForm: () => !elements.registration.checked,
});
</script>

0 comments on commit 868429e

Please sign in to comment.