added password to upload form

This commit is contained in:
Danny Coates 2018-10-29 19:06:15 -07:00
parent 0e5202c470
commit 12e6eb1666
No known key found for this signature in database
GPG Key ID: 4C442633C62E00CB
7 changed files with 153 additions and 17 deletions

View File

@ -67,6 +67,63 @@ progress::-webkit-progress-value {
box-shadow: 0 0 5rem 5rem white; box-shadow: 0 0 5rem 5rem white;
} }
.checkbox {
@apply leading-normal;
@apply select-none;
}
.checkbox > input[type='checkbox'] {
@apply absolute;
@apply opacity-0;
}
.checkbox > label {
@apply cursor-pointer;
}
.checkbox > label::before {
@apply bg-blue-lightest;
@apply border;
@apply rounded-sm;
content: '';
height: 1.5rem;
width: 1.5rem;
margin-right: 0.5rem;
float: left;
}
.checkbox > label:hover::before {
@apply border-blue;
}
.checkbox > input:focus + label::before {
@apply border-blue;
}
.checkbox > input:checked + label::before {
background-image: url('../assets/lock.svg');
background-position: center;
background-size: 1.25rem;
background-repeat: no-repeat;
}
.checkbox > input:disabled + label {
cursor: auto;
}
.checkbox > input:disabled + label::before {
background-image: url('../assets/lock.svg');
background-position: center;
background-size: 1.25rem;
background-repeat: no-repeat;
cursor: auto;
}
#password-msg::after {
content: '\200b';
}
@screen md { @screen md {
.main { .main {
@apply flex-1; @apply flex-1;

View File

@ -7,6 +7,7 @@ function getString(item) {
export default function(state, emitter) { export default function(state, emitter) {
window.addEventListener('paste', async event => { window.addEventListener('paste', async event => {
if (state.route !== '/' || state.uploading) return; if (state.route !== '/' || state.uploading) return;
if (event.target.type === 'password') return;
const items = Array.from(event.clipboardData.items); const items = Array.from(event.clipboardData.items);
const transferFiles = items.filter(item => item.kind === 'file'); const transferFiles = items.filter(item => item.kind === 'file');

View File

@ -1,21 +1,7 @@
const html = require('choo/html'); const html = require('choo/html');
const assets = require('../../common/assets');
const { list } = require('../utils'); const { list } = require('../utils');
const archiveTile = require('./archiveTile'); const archiveTile = require('./archiveTile');
const intro = require('./intro');
function intro(state) {
return html`
<article class="flex flex-col items-center justify-center bg-white border border-grey-light p-2">
<p class="text-center">
<div class="font-semibold">${state.translate('uploadPageHeader')}</div>
<div class="italic">${state.translate('pageHeaderCredits')}</div>
</p>
<img src="${assets.get('illustration_download.svg')}"/>
<p class="m-4 max-w-sm text-sm font-light">${state.translate(
'uploadPageExplainer'
)}</p>
</article>`;
}
module.exports = function(state, emit) { module.exports = function(state, emit) {
const archives = state.storage.files.map(archive => const archives = state.storage.files.map(archive =>

View File

@ -16,6 +16,81 @@ function expiryInfo(translate, archive) {
); );
} }
function password(state) {
const MAX_LENGTH = 32;
return html`
<div class="my-2">
<div class="checkbox">
<input
id="add-password"
type="checkbox"
${state.password ? 'checked' : ''}
autocomplete="off"
onchange=${togglePasswordInput}/>
<label for="add-password">
${state.translate('addPasswordMessage')}
</label>
</div>
<input
id="password-input"
class="${
state.password ? '' : 'invisible'
} border rounded-sm focus:border-blue leading-normal mt-2"
autocomplete="off"
maxlength="${MAX_LENGTH}"
type="password"
oninput=${inputChanged}
onfocus=${focused}
placeholder="${state.translate('unlockInputPlaceholder')}"
value="${state.password || ''}"
>
<label
id="password-msg"
for="password-input"
class="block text-xs text-grey-darker mt-1"></label>
</div>`;
function togglePasswordInput(event) {
event.stopPropagation();
const checked = event.target.checked;
const input = document.getElementById('password-input');
if (checked) {
input.classList.remove('invisible');
input.focus();
} else {
input.classList.add('invisible');
input.value = '';
document.getElementById('password-msg').textContent = '';
state.password = null;
}
}
function inputChanged() {
const passwordInput = document.getElementById('password-input');
const pwdmsg = document.getElementById('password-msg');
const password = passwordInput.value;
const length = password.length;
if (length === MAX_LENGTH) {
pwdmsg.textContent = state.translate('maxPasswordLength', {
length: MAX_LENGTH
});
} else {
pwdmsg.textContent = '';
}
state.password = password;
}
function focused(event) {
event.preventDefault();
const el = document.getElementById('password-input');
if (el.placeholder !== state.translate('unlockInputPlaceholder')) {
el.placeholder = '';
}
}
}
function fileInfo(file, action) { function fileInfo(file, action) {
return html` return html`
<article class="flex flex-row items-start p-3"> <article class="flex flex-row items-start p-3">
@ -104,6 +179,7 @@ module.exports.wip = function(state, emit) {
</label> </label>
</div> </div>
${expiryOptions(state, emit)} ${expiryOptions(state, emit)}
${password(state, emit)}
<button <button
class="flex-none border rounded bg-blue text-white mt-2 py-2 px-6" class="flex-none border rounded bg-blue text-white mt-2 py-2 px-6"
title="${state.translate('uploadFilesButton')}" title="${state.translate('uploadFilesButton')}"

View File

@ -95,7 +95,7 @@ module.exports = function(state, emit) {
content = password(state, emit); content = password(state, emit);
} }
return html` return html`
<main class="main"> <main class="main container">
<section class="relative h-full w-full my-4 px-6"> <section class="relative h-full w-full my-4 px-6">
${content} ${content}
</section> </section>

16
app/ui/intro.js Normal file
View File

@ -0,0 +1,16 @@
const html = require('choo/html');
const assets = require('../../common/assets');
module.exports = function intro(state) {
return html`
<article class="flex flex-col items-center justify-center bg-white border border-grey-light p-2">
<p class="text-center">
<div class="font-semibold">${state.translate('uploadPageHeader')}</div>
<div class="italic">${state.translate('pageHeaderCredits')}</div>
</p>
<img src="${assets.get('illustration_download.svg')}"/>
<p class="m-4 max-w-sm text-sm font-light">${state.translate(
'uploadPageExplainer'
)}</p>
</article>`;
};

View File

@ -4,7 +4,7 @@ module.exports = function(selected, options, translate, changed) {
let x = selected; let x = selected;
return html` return html`
<select class="appearance-none cursor-pointer border rounded-sm bg-blue-lightest p-1" onchange=${choose}> <select class="appearance-none cursor-pointer border rounded-sm bg-blue-lightest hover:border-blue focus:border-blue p-1" onchange=${choose}>
${options.map( ${options.map(
i => i =>
html`<option value="${i}" ${ html`<option value="${i}" ${