Album -> DOMVM AlbumView

This commit is contained in:
Timothy Farrell 2017-09-27 12:27:25 -05:00
parent da9e699df4
commit ccfd757aed
6 changed files with 68 additions and 61 deletions

View File

@ -6,16 +6,19 @@ import { getDatabase } from './services/db.js';
import * as imageTag from './context/manageImageTags.js'; import * as imageTag from './context/manageImageTags.js';
import generateThumbnails from './contextLoaders/generateThumbnails.js'; import generateThumbnails from './contextLoaders/generateThumbnails.js';
import { ImageView } from './interface/image.js'; import { ImageView } from './interface/image.js';
import { AlbumView } from './interface/album.js';
window.__DEV__ = true; window.__DEV__ = true;
window.db = getDatabase(); window.db = getDatabase();
image.imported.subscribe(refresh); image.imported.subscribe(refresh);
image.imported.subscribe(generateThumbnails); image.imported.subscribe(generateThumbnails);
image.removed.subscribe(refresh);
index.added.subscribe(refresh);
index.removed.subscribe(refresh);
const header = document.querySelector('h1'); const header = document.querySelector('h1');
const container = document.querySelector('#app'); const container = document.querySelector('#app');
const displaySelector = document.querySelector('#display'); const displaySelector = document.querySelector('#display');
image.removed.subscribe(refresh);
// Events // Events
displaySelector.onchange = refresh; displaySelector.onchange = refresh;
@ -28,27 +31,6 @@ function refresh() {
setTimeout(render, 100); 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() { async function render() {
container.innerHTML = ''; container.innerHTML = '';
@ -67,12 +49,17 @@ async function render() {
} else { } else {
header.innerText = 'Albums'; header.innerText = 'Albums';
const results = await index.find({ attachments: true }); 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 => { Array.from(document.querySelectorAll('.image')).forEach(i => {
const b = document.createElement('button'); 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 = '+'; b.textContent = '+';
i.appendChild(b); i.appendChild(b);
}); });

View File

@ -51,26 +51,12 @@ export async function add(imageFileList) {
return docs.filter((d, i) => results[i].ok); return docs.filter((d, i) => results[i].ok);
} }
export async function remove(ids, rev) { export async function remove(ids) {
if (!Array.isArray(ids)) { const docs = await find(Array.isArray(ids) ? ids : [ids]);
try { const foundDocs = docs.rows.filter(r => !r.error);
const doc = rev ? { _id: ids, _rev: rev } : await db.get(ids); const result = await db.bulkDocs(foundDocs.map(r => Object.assign(r.doc, { _deleted: true })));
await db.remove(doc); foundDocs.filter((_, i) => result[i].ok).map(r => removed.fire(r.doc));
if (doc._id.startsWith(PREFIX)) { return result.reduce((a, r) => a && r.ok, true);
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 update(id, properties) { export async function update(id, properties) {
@ -162,6 +148,6 @@ const processImportables = backgroundTask(async function _processImportables() {
imported.fire(id, _id, false); imported.fire(id, _id, false);
} }
remove(_id, _rev); await db.remove({ _id, _rev });
processImportables(); processImportables();
}); });

View File

@ -1,9 +1,14 @@
import { log, error } from '../services/console.js'; import { log, error } from '../services/console.js';
import { getDatabase, getOrCreate } from '../services/db.js'; import { getDatabase, getOrCreate } from '../services/db.js';
import { Event } from '../utils/event.js';
const db = getDatabase(); const db = getDatabase();
const PREFIX = 'index'; const PREFIX = 'index';
// Events
export const added = new Event('Index.added');
export const removed = new Event('Index.removed');
// Methods // Methods
export const hashString = name => export const hashString = name =>
name name
@ -47,6 +52,7 @@ export async function addMember(id, member) {
if (doc.members.indexOf(member) === -1) { if (doc.members.indexOf(member) === -1) {
doc.members.push(member); doc.members.push(member);
await db.put(doc); await db.put(doc);
added.fire(doc._id, member);
} }
return doc; return doc;
@ -61,8 +67,10 @@ export async function removeMember(id, member) {
if (doc.members.length > 1) { if (doc.members.length > 1) {
doc.members.splice(idx, 1); doc.members.splice(idx, 1);
await db.put(doc); await db.put(doc);
removed.fire(doc._id, member);
} else { } else {
await db.remove(doc); await db.remove(doc);
removed.fire(doc._id, member);
} }
} }
} }

View File

@ -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
});
})
]);
};
}

View File

@ -3,17 +3,19 @@ import { ThumbnailView } from './thumbnail.js';
export function ImageView(vm, model) { export function ImageView(vm, model) {
return function(vm, model, key, opts) { return function(vm, model, key, opts) {
const { imageRow, imageContainer, showTags, remove, removeTag } = model; const { imageRow, showTags, remove, removeTag } = model;
const { thumbnail } = imageRow.doc._attachments; const { doc } = imageRow;
const { thumbnail } = doc._attachments;
const _showTags = showTags !== undefined ? showTags : true; const _showTags = showTags !== undefined ? showTags : true;
if (thumbnail) { if (thumbnail) {
return el('div', [ return el('div', [
defineView(ThumbnailView, { defineView(ThumbnailView, {
id: imageRow.doc._id, id: doc._id,
rev: doc._rev,
name: 'thumbnail', name: 'thumbnail',
doc: thumbnail, doc: thumbnail,
tags: _showTags ? imageRow.doc.tags : [], tags: _showTags ? doc.tags : [],
remove: remove, remove: remove,
removeTag: removeTag removeTag: removeTag
}) })

View File

@ -1,12 +1,10 @@
import { defineElement as el } from 'domvm'; import { defineElement as el } from 'domvm';
export function ThumbnailView(vm, model) { export function ThumbnailView(vm, model) {
function onclick(evt) { const { remove, removeTag } = model;
model.remove(evt.currentTarget.dataset.id); // .then(refresh);
}
return function(vm, model, key, opts) { 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); const filteredTags = Object.entries(tags).filter(([_, visible]) => visible);
return el(`figure#${id}.image`, [ return el(`figure#${id}.image`, [
@ -14,18 +12,12 @@ export function ThumbnailView(vm, model) {
src: `data:${doc.content_type};base64,${doc.data}`, src: `data:${doc.content_type};base64,${doc.data}`,
title: `${id} ${name}`, title: `${id} ${name}`,
'data-id': id, 'data-id': id,
onclick onclick: [remove, id, rev]
}), }),
filteredTags.length filteredTags.length
? el( ? el(
'figcaption', 'figcaption',
filteredTags.map(([title, _]) => filteredTags.map(([title, _]) => el('span.tag', { onclick: [removeTag, title, id] }, [title]))
el(
'span.tag',
{ onclick: evt => model.removeTag(title, id) }, // .then(refresh)
[title]
)
)
) )
: null : null
]); ]);