From e998747a2d2ce8dfec17f17b25035079de92c18d Mon Sep 17 00:00:00 2001 From: Timothy Farrell Date: Fri, 29 Sep 2017 16:54:08 -0500 Subject: [PATCH] Gallery -> DOMVM GalleryView The whole app is converted to be base in DOMVM now. But there are bugs. --- packages/gallery/package.json | 1 + packages/gallery/src/app.js | 90 +++++++++------------ packages/gallery/src/index.html | 6 -- packages/gallery/src/interface/album.js | 17 ++-- packages/gallery/src/interface/gallery.js | 53 ++++++++++++ packages/gallery/src/interface/image.js | 11 ++- packages/gallery/src/interface/thumbnail.js | 4 +- packages/gallery/src/services/router.js | 31 +++++++ packages/gallery/webpack.config.js | 5 ++ 9 files changed, 147 insertions(+), 71 deletions(-) create mode 100644 packages/gallery/src/interface/gallery.js create mode 100644 packages/gallery/src/services/router.js diff --git a/packages/gallery/package.json b/packages/gallery/package.json index fbd8a84..117820a 100644 --- a/packages/gallery/package.json +++ b/packages/gallery/package.json @@ -21,6 +21,7 @@ "pouchdb-binary-utils": "~6.1.2", "pouchdb-core": "~6.1.2", "pouchdb-replication": "~6.1.2", + "router": "2.0.0", "webpack": "^2.3.3" }, "devDependencies": { diff --git a/packages/gallery/src/app.js b/packages/gallery/src/app.js index c8d8478..2afa314 100644 --- a/packages/gallery/src/app.js +++ b/packages/gallery/src/app.js @@ -1,68 +1,50 @@ -import { createView } from 'domvm'; +import { createView } from 'domvm/dist/dev/domvm.dev.js'; import * as image from './data/image.js'; import * as index from './data/indexType.js'; import { getDatabase } from './services/db.js'; import * as imageTag from './context/manageImageTags.js'; import generateThumbnails from './contextLoaders/generateThumbnails.js'; -import { ImageView } from './interface/image.js'; -import { AlbumView } from './interface/album.js'; +import { GalleryView } from './interface/gallery.js'; +import { router, routeChanged } from './services/router.js'; -window.__DEV__ = true; window.db = getDatabase(); -image.imported.subscribe(refresh); -image.imported.subscribe(generateThumbnails); -image.removed.subscribe(refresh); -index.added.subscribe(refresh); -index.removed.subscribe(refresh); -const header = document.querySelector('h1'); -const container = document.querySelector('#app'); -const displaySelector = document.querySelector('#display'); - -// Events -displaySelector.onchange = refresh; -document.querySelector('#fInput').onchange = async evt => { - image.add(evt.currentTarget.files); +const NAV_OPTIONS = { + images: { + model: image, + title: 'Images' + }, + albums: { + model: index, + title: 'Albums' + } }; -// To test the output: -function refresh() { - setTimeout(render, 100); -} - -async function render() { - container.innerHTML = ''; - - if (displaySelector.value === 'i') { - header.innerText = 'Images'; - const results = await image.find({ attachments: true }); - results.rows.forEach(i => { - createView(ImageView, { - imageRow: i, - imageContainer: container, - showTags: true, - remove: image.remove, - removeTag: imageTag.remove - }).mount(container); - }); - } else { - header.innerText = 'Albums'; - const results = await index.find({ attachments: true }); - results.rows.forEach(i => { - createView(AlbumView, { - albumRow: i, - remove: imageTag.remove - }).mount(container); - }); - } - - Array.from(document.querySelectorAll('.image')).forEach(i => { - const b = document.createElement('button'); - b.onclick = evt => imageTag.add(prompt('Tag Name'), i.id); - b.textContent = '+'; - i.appendChild(b); +async function update(route) { + const o = NAV_OPTIONS[route.name]; + gallery.update({ + title: o.title, + members: (await o.model.find({ attachments: true })).rows }); } +function redraw() { + update(router.current()); +} +function onRouteChange(router, route) { + update(route); +} -render(); +image.imported.subscribe(generateThumbnails); +image.imported.subscribe(redraw); +image.removed.subscribe(redraw); +index.added.subscribe(redraw); +index.removed.subscribe(redraw); +routeChanged.subscribe(onRouteChange); + +const gallery = createView(GalleryView, { + title: '', + members: [] +}).mount(document.querySelector('#app')); + +router.start('home'); diff --git a/packages/gallery/src/index.html b/packages/gallery/src/index.html index c8f00a1..028e232 100644 --- a/packages/gallery/src/index.html +++ b/packages/gallery/src/index.html @@ -5,12 +5,6 @@ - - -

diff --git a/packages/gallery/src/interface/album.js b/packages/gallery/src/interface/album.js index 7e72895..6d51958 100644 --- a/packages/gallery/src/interface/album.js +++ b/packages/gallery/src/interface/album.js @@ -8,9 +8,10 @@ export function AlbumView(vm, model) { const title = props.title; let images = []; + // FIXME - If the album is updated, this does not properly refresh. image.find(members, { attachments: true }).then(res => { images = res.rows.filter(i => i.doc); - vm.redraw(true); + vm.redraw(); }); function removeImageFromAlbum(id, rev) { @@ -21,11 +22,15 @@ export function AlbumView(vm, model) { return el('.album', [ el('h2', [title]), ...images.map(i => { - return defineView(ImageView, { - imageRow: i, - showTags: false, - remove: removeImageFromAlbum - }); + return defineView( + ImageView, + { + imageRow: i, + showTags: false, + remove: removeImageFromAlbum + }, + i._id + ); }) ]); }; diff --git a/packages/gallery/src/interface/gallery.js b/packages/gallery/src/interface/gallery.js new file mode 100644 index 0000000..68f5cc0 --- /dev/null +++ b/packages/gallery/src/interface/gallery.js @@ -0,0 +1,53 @@ +import { defineView, defineElement as el } from 'domvm'; +import * as image from '../data/image.js'; +import * as imageTag from '../context/manageImageTags.js'; +import { ImageView } from './image.js'; +import { AlbumView } from './album.js'; +import { router } from '../services/router.js'; + +export function GalleryView(vm, model) { + function uploadImages(evt) { + image.add(evt.currentTarget.files); + } + + return function(vm, model, key, opts) { + const { title, members } = model; + + return el('.gallery', [ + el('input#fInput', { + type: 'file', + multiple: true, + accept: 'image/jpeg', + onchange: uploadImages + }), + el('a', { href: router.href('images') }, 'Images'), + el('a', { href: router.href('albums') }, 'Albums'), + el('h1', title), + ...(title === 'Images' + ? members.map(i => { + return defineView( + ImageView, + { + imageRow: i, + showTags: true, + addTag: imageTag.add, + remove: image.remove, + removeTag: imageTag.remove + }, + i._id + ); + }) + : members.map(a => { + return defineView( + AlbumView, + { + albumRow: a, + addTag: imageTag.add, + remove: imageTag.remove + }, + a._id + ); + })) + ]); + }; +} diff --git a/packages/gallery/src/interface/image.js b/packages/gallery/src/interface/image.js index dfaacd8..4bf84b2 100644 --- a/packages/gallery/src/interface/image.js +++ b/packages/gallery/src/interface/image.js @@ -2,8 +2,14 @@ import { defineView, defineElement as el } from 'domvm'; import { ThumbnailView } from './thumbnail.js'; export function ImageView(vm, model) { + const { addTag } = model; + + function onAddTag(image_id) { + addTag(prompt('Tag Name'), image_id); + } + return function(vm, model, key, opts) { - const { imageRow, showTags, remove, removeTag } = model; + const { imageRow, showTags, remove, addTag, removeTag } = model; const { doc } = imageRow; const { thumbnail } = doc._attachments; const _showTags = showTags !== undefined ? showTags : true; @@ -18,7 +24,8 @@ export function ImageView(vm, model) { tags: _showTags ? doc.tags : [], remove: remove, removeTag: removeTag - }) + }), + addTag ? el('button', { onclick: [onAddTag, doc._id] }, '+') : null ]); } diff --git a/packages/gallery/src/interface/thumbnail.js b/packages/gallery/src/interface/thumbnail.js index 3c61883..9d95c0d 100644 --- a/packages/gallery/src/interface/thumbnail.js +++ b/packages/gallery/src/interface/thumbnail.js @@ -1,10 +1,8 @@ import { defineElement as el } from 'domvm'; export function ThumbnailView(vm, model) { - const { remove, removeTag } = model; - return function(vm, model, key, opts) { - const { id, rev, name, doc, tags } = model; + const { id, rev, name, doc, tags, remove, removeTag } = model; const filteredTags = Object.entries(tags).filter(([_, visible]) => visible); return el(`figure#${id}.image`, [ diff --git a/packages/gallery/src/services/router.js b/packages/gallery/src/services/router.js new file mode 100644 index 0000000..65a4bba --- /dev/null +++ b/packages/gallery/src/services/router.js @@ -0,0 +1,31 @@ +import { Router } from 'router'; +import { Event } from '../utils/event.js'; + +export const routeChanged = new Event('Router.newRoute'); + +const fire = routeChanged.fire.bind(routeChanged); + +export const router = Router([ + { + name: 'home', + path: '/', + enter: (r, route) => { + r.goto('images'); + } + }, + { + name: 'images', + path: '/images', + enter: fire + }, + { + name: 'albums', + path: '/albums', + enter: fire + }, + { + id: '404', + path: ':vars', + enter: r => r.goto('home') + } +]); diff --git a/packages/gallery/webpack.config.js b/packages/gallery/webpack.config.js index a66f222..35141cd 100644 --- a/packages/gallery/webpack.config.js +++ b/packages/gallery/webpack.config.js @@ -14,5 +14,10 @@ module.exports = { devServer: { contentBase: path.resolve(__dirname, './src') }, + plugins: [ + new webpack.DefinePlugin({ + __DEV__: true + }) + ], devtool: 'source-map' };