Replace file uploads with dropzone

This commit is contained in:
Timothy Farrell 2017-11-22 21:25:36 -06:00
parent 549d5be3f6
commit c83066082c
5 changed files with 148 additions and 38 deletions

View File

@ -10,7 +10,7 @@ import { EventEmitter } from 'events';
EventEmitter.defaultMaxListeners = 1000; // https://github.com/pouchdb/pouchdb/issues/6123
// Attach our root view to the DOM
createView(GalleryView, {}).mount(document.querySelector('#app'));
createView(GalleryView, {}).mount(document.body);
// Start the router
router.start('home');

View File

@ -5,7 +5,6 @@
<link rel="stylesheet" href="/assets/app.css">
</head>
<body>
<div id='app'></div>
<script src="/assets/app.bundle.js"></script>
</body>
</html>

View File

@ -0,0 +1,75 @@
import { prop, computed } from 'frptools';
import { injectStyle, el } from '../services/style';
const CSS_DROPZONE = {
width: '200px',
height: '200px',
border: '2px #666 dashed',
borderRadius: '5px'
};
const CSS_DROPZONE_ACTIVE = {
borderStyle: 'solid',
backgroundColor: '#eee'
};
export function Dropzone(vm, model) {
const { ondrop, ondragenter, ondragleave } = model;
const enterCounter = prop(0);
enterCounter.subscribe(() => vm.redraw());
function onDragOver(evt) {
// allows the browser to accept drops.
evt.preventDefault();
}
function onDragEnter() {
enterCounter(enterCounter() + 1);
if (ondragenter) {
ondragenter();
}
}
function onDragLeave() {
enterCounter(enterCounter() - 1);
if (ondragleave) {
ondragleave();
}
}
function onDrop(evt) {
evt.preventDefault();
enterCounter(0);
if (ondrop) {
ondrop(evt.dataTransfer.files);
}
}
return function render(vm, model) {
const { className, activeClassName, class: _class, children } = model;
const class_ = Object.assign(
{
[className || injectStyle(CSS_DROPZONE)]: true,
[activeClassName || injectStyle(CSS_DROPZONE_ACTIVE)]: enterCounter() > 0
},
_class || {}
);
return el(
'div',
{
class: class_,
ondragenter: onDragEnter,
ondragover: onDragOver,
ondragleave: onDragLeave,
ondrop: onDrop
},
...children
);
};
}

View File

@ -3,8 +3,9 @@ import { ImageType } from '../data/image.js';
import { AlbumType } from '../data/album.js';
import { ThumbnailView } from './thumbnail.js';
import { AlbumView } from './album.js';
import { Dropzone } from './dropzone.js';
import { router, routeChanged } from '../services/router.js';
import { styled, el } from '../services/style.js';
import { injectStyle, styled, el } from '../services/style.js';
export function GalleryView(vm, model) {
const { db } = model;
@ -28,8 +29,8 @@ export function GalleryView(vm, model) {
let laCleanup = null;
let title = '';
function uploadImages(evt) {
Array.from(evt.currentTarget.files).forEach(ImageType.upload);
function uploadImages(files) {
Array.from(files).forEach(ImageType.upload);
}
function deleteImage(i) {
@ -64,21 +65,8 @@ export function GalleryView(vm, model) {
});
});
return function(vm, model, key, opts) {
return el('.gallery', [
header([
el('div', { css: { fontSize: '20pt' } }, 'Gallery'),
el('button', { onclick: addAlbum }, 'Add Album'),
el('input#fInput', {
type: 'file',
multiple: true,
accept: 'image/jpeg',
onchange: uploadImages
})
]),
...(!data || !data.ready()
? [el('h1', 'Loading...')]
: [
function renderDropzone() {
return [
el('a', { href: router.href('images') }, 'Images'),
el('a', { href: router.href('albums') }, 'Albums'),
el('h1', title),
@ -91,14 +79,46 @@ export function GalleryView(vm, model) {
showTags: true,
remove: deleteImage
},
i._id + i._rev
i._hash()
);
})
: data().map(a => {
return vw(AlbumView, a, a._id + a._rev);
return vw(AlbumView, a, a._hash());
}))
])
]);
];
}
return function render(vm, params, key, opts) {
if (!data || !data.ready()) {
return el('h1', 'Loading...');
}
return el(
'.gallery',
{ class: slate },
header([
el('div', { css: { fontSize: '20pt' } }, 'Gallery'),
headerRight(
{
css: { visibility: /* selectMode */ true ? 'visible' : 'hidden' }
},
[el('button', { onclick: addAlbum }, 'Add Album')]
)
]),
vw(
Dropzone,
{
className: slate,
activeClassName: 'dropHover',
ondrop: uploadImages,
type: 'file',
multiple: true, // FIXME - these don't carry through to the input tag
accept: 'image/jpeg',
children: renderDropzone()
},
'dz'
)
);
};
}
@ -109,3 +129,15 @@ const header = styled({
display: 'flex',
alignItems: 'center'
});
const headerRight = styled({
display: 'flex',
alignItems: 'center'
});
const slate = injectStyle({
display: 'flex',
flex: 1,
flexDirection: 'column'
// overflow: 'hidden',
});

View File

@ -7,7 +7,7 @@ import find from 'pouchdb-find';
import { log, warn } from './console.js';
import { isObject } from '../utils/comparators.js';
import { LiveArray } from '../utils/livearray.js';
import { deepAssign } from '../utils/conversion.js';
import { deepAssign, pouchDocHash } from '../utils/conversion.js';
export const PouchDB = core
.plugin(idb)
@ -43,6 +43,10 @@ export class TypeSpec {
return doc;
}
_hash() {
return pouchDocHash(this);
}
async delete() {
return await this.update({ _deleted: true });
}