From ccfd757aed71191939e2e3221fe20a05415ebdc1 Mon Sep 17 00:00:00 2001 From: Timothy Farrell Date: Wed, 27 Sep 2017 12:27:25 -0500 Subject: [PATCH] Album -> DOMVM AlbumView --- packages/gallery/src/app.js | 35 +++++++-------------- packages/gallery/src/data/image.js | 28 +++++------------ packages/gallery/src/data/indexType.js | 8 +++++ packages/gallery/src/interface/album.js | 32 +++++++++++++++++++ packages/gallery/src/interface/image.js | 10 +++--- packages/gallery/src/interface/thumbnail.js | 16 +++------- 6 files changed, 68 insertions(+), 61 deletions(-) create mode 100644 packages/gallery/src/interface/album.js diff --git a/packages/gallery/src/app.js b/packages/gallery/src/app.js index 98eb551..c8d8478 100644 --- a/packages/gallery/src/app.js +++ b/packages/gallery/src/app.js @@ -6,16 +6,19 @@ 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'; 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'); -image.removed.subscribe(refresh); // Events displaySelector.onchange = refresh; @@ -28,27 +31,6 @@ function refresh() { setTimeout(render, 100); } -async function renderAlbum(indexRow) { - const doc = indexRow.doc; - const l = document.createElement('h2'); - l.innerText = indexRow.doc.props.title; - container.appendChild(l); - - const albumContainer = document.createElement('div'); - container.appendChild(albumContainer); - - const results = await image.find(doc.members, { attachments: true }); - results.rows.filter(i => i.doc).forEach(i => { - createView(ImageView, { - imageRow: i, - imageContainer: albumContainer, - showTags: false, - remove: image.remove, - removeTag: imageTag.remove - }).mount(albumContainer); - }); -} - async function render() { container.innerHTML = ''; @@ -67,12 +49,17 @@ async function render() { } else { header.innerText = 'Albums'; const results = await index.find({ attachments: true }); - results.rows.forEach(renderAlbum); + 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).then(refresh); + b.onclick = evt => imageTag.add(prompt('Tag Name'), i.id); b.textContent = '+'; i.appendChild(b); }); diff --git a/packages/gallery/src/data/image.js b/packages/gallery/src/data/image.js index 04328e9..2dc8b9c 100644 --- a/packages/gallery/src/data/image.js +++ b/packages/gallery/src/data/image.js @@ -51,26 +51,12 @@ export async function add(imageFileList) { return docs.filter((d, i) => results[i].ok); } -export async function remove(ids, rev) { - if (!Array.isArray(ids)) { - try { - const doc = rev ? { _id: ids, _rev: rev } : await db.get(ids); - await db.remove(doc); - if (doc._id.startsWith(PREFIX)) { - removed.fire(doc); - } - return true; - } catch (e) { - if (e.status !== 404) { - error(`Error removing Image ${_id}`, e); - } - return false; - } - } - - const docs = await find(ids); - const result = await db.bulkDocs(docs.rows.map(r => Object.assign(r.doc, { _deleted: true }))); - return result.map(r => r.ok); +export async function remove(ids) { + const docs = await find(Array.isArray(ids) ? ids : [ids]); + const foundDocs = docs.rows.filter(r => !r.error); + const result = await db.bulkDocs(foundDocs.map(r => Object.assign(r.doc, { _deleted: true }))); + foundDocs.filter((_, i) => result[i].ok).map(r => removed.fire(r.doc)); + return result.reduce((a, r) => a && r.ok, true); } export async function update(id, properties) { @@ -162,6 +148,6 @@ const processImportables = backgroundTask(async function _processImportables() { imported.fire(id, _id, false); } - remove(_id, _rev); + await db.remove({ _id, _rev }); processImportables(); }); diff --git a/packages/gallery/src/data/indexType.js b/packages/gallery/src/data/indexType.js index 389210b..0482a90 100644 --- a/packages/gallery/src/data/indexType.js +++ b/packages/gallery/src/data/indexType.js @@ -1,9 +1,14 @@ import { log, error } from '../services/console.js'; import { getDatabase, getOrCreate } from '../services/db.js'; +import { Event } from '../utils/event.js'; const db = getDatabase(); const PREFIX = 'index'; +// Events +export const added = new Event('Index.added'); +export const removed = new Event('Index.removed'); + // Methods export const hashString = name => name @@ -47,6 +52,7 @@ export async function addMember(id, member) { if (doc.members.indexOf(member) === -1) { doc.members.push(member); await db.put(doc); + added.fire(doc._id, member); } return doc; @@ -61,8 +67,10 @@ export async function removeMember(id, member) { if (doc.members.length > 1) { doc.members.splice(idx, 1); await db.put(doc); + removed.fire(doc._id, member); } else { await db.remove(doc); + removed.fire(doc._id, member); } } } diff --git a/packages/gallery/src/interface/album.js b/packages/gallery/src/interface/album.js new file mode 100644 index 0000000..7e72895 --- /dev/null +++ b/packages/gallery/src/interface/album.js @@ -0,0 +1,32 @@ +import { defineView, defineElement as el } from 'domvm'; +import * as image from '../data/image.js'; +import { ImageView } from './image.js'; + +export function AlbumView(vm, model) { + const { albumRow, remove } = model; + const { props, members } = albumRow.doc; + const title = props.title; + let images = []; + + image.find(members, { attachments: true }).then(res => { + images = res.rows.filter(i => i.doc); + vm.redraw(true); + }); + + function removeImageFromAlbum(id, rev) { + remove(title, id); + } + + return function(vm, model, key, opts) { + return el('.album', [ + el('h2', [title]), + ...images.map(i => { + return defineView(ImageView, { + imageRow: i, + showTags: false, + remove: removeImageFromAlbum + }); + }) + ]); + }; +} diff --git a/packages/gallery/src/interface/image.js b/packages/gallery/src/interface/image.js index 646694b..dfaacd8 100644 --- a/packages/gallery/src/interface/image.js +++ b/packages/gallery/src/interface/image.js @@ -3,17 +3,19 @@ import { ThumbnailView } from './thumbnail.js'; export function ImageView(vm, model) { return function(vm, model, key, opts) { - const { imageRow, imageContainer, showTags, remove, removeTag } = model; - const { thumbnail } = imageRow.doc._attachments; + const { imageRow, showTags, remove, removeTag } = model; + const { doc } = imageRow; + const { thumbnail } = doc._attachments; const _showTags = showTags !== undefined ? showTags : true; if (thumbnail) { return el('div', [ defineView(ThumbnailView, { - id: imageRow.doc._id, + id: doc._id, + rev: doc._rev, name: 'thumbnail', doc: thumbnail, - tags: _showTags ? imageRow.doc.tags : [], + tags: _showTags ? doc.tags : [], remove: remove, removeTag: removeTag }) diff --git a/packages/gallery/src/interface/thumbnail.js b/packages/gallery/src/interface/thumbnail.js index f33efc5..3c61883 100644 --- a/packages/gallery/src/interface/thumbnail.js +++ b/packages/gallery/src/interface/thumbnail.js @@ -1,12 +1,10 @@ import { defineElement as el } from 'domvm'; export function ThumbnailView(vm, model) { - function onclick(evt) { - model.remove(evt.currentTarget.dataset.id); // .then(refresh); - } + const { remove, removeTag } = model; return function(vm, model, key, opts) { - const { id, name, doc, tags } = model; + const { id, rev, name, doc, tags } = model; const filteredTags = Object.entries(tags).filter(([_, visible]) => visible); return el(`figure#${id}.image`, [ @@ -14,18 +12,12 @@ export function ThumbnailView(vm, model) { src: `data:${doc.content_type};base64,${doc.data}`, title: `${id} ${name}`, 'data-id': id, - onclick + onclick: [remove, id, rev] }), filteredTags.length ? el( 'figcaption', - filteredTags.map(([title, _]) => - el( - 'span.tag', - { onclick: evt => model.removeTag(title, id) }, // .then(refresh) - [title] - ) - ) + filteredTags.map(([title, _]) => el('span.tag', { onclick: [removeTag, title, id] }, [title])) ) : null ]);