Add album view

This commit is contained in:
Timothy Farrell 2017-04-18 09:06:26 -05:00
parent 9c465cd405
commit ccd0fafd9e
5 changed files with 119 additions and 52 deletions

View File

@ -1,28 +1,29 @@
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 './context/generateThumbnails.js';
document.querySelector('#fInput').onchange = async evt => {
image.add(evt.currentTarget.files);
};
window.__DEV__ = true;
window.db = getDatabase();
image.imported.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);
};
// To test the output:
function refresh() {
setTimeout(() => history.go(0), 100);
setTimeout(render, 100);
}
db.allDocs({ include_docs: true, attachments: true }).then(async results => {
results.rows.forEach(r => {
const doc = r.doc;
});
function renderThumbnail(id, name, doc, tags) {
const c = document.createElement('div');
const e = document.createElement('img');
@ -47,16 +48,47 @@ db.allDocs({ include_docs: true, attachments: true }).then(async results => {
return c;
}
results.rows.forEach(r => {
for (let aName in r.doc._attachments) {
function renderImage(imageRow, imageContainer, showTags = true) {
for (let aName in imageRow.doc._attachments) {
if (aName !== 'thumbnail') {
continue;
}
document.body.appendChild(
renderThumbnail(r.doc._id, aName, r.doc._attachments[aName], r.doc.tags)
imageContainer.appendChild(
renderThumbnail(
imageRow.doc._id,
aName,
imageRow.doc._attachments[aName],
showTags ? imageRow.doc.tags : []
)
);
}
});
}
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 => renderImage(i, albumContainer, false));
}
async function render() {
container.innerHTML = '';
if (displaySelector.value === 'i') {
header.innerText = 'Images';
const results = await image.find({ attachments: true });
results.rows.forEach(i => renderImage(i, container));
} else {
header.innerText = 'Albums';
const results = await index.find({ attachments: true });
results.rows.forEach(renderAlbum);
}
Array.from(document.querySelectorAll('.image')).forEach(i => {
const b = document.createElement('button');
@ -64,4 +96,6 @@ db.allDocs({ include_docs: true, attachments: true }).then(async results => {
b.textContent = '+';
i.appendChild(b);
});
});
}
render();

View File

@ -3,7 +3,7 @@ import * as index from '../data/indexType.js';
export async function add(title, imageId, visible = true) {
const trimmedTitle = title.trim();
await index.add(trimmedTitle, [imageId]);
await index.add(trimmedTitle, { title: trimmedTitle }, [imageId]);
return image.update(imageId, {
tags: { [trimmedTitle]: visible }
});
@ -14,3 +14,7 @@ export async function remove(title, imageId) {
await image.update(imageId, { tags: { [title]: undefined } });
await index.removeMember(title, imageId);
}
image.removed.subscribe(image => {
Object.keys(image.tags).forEach(t => index.removeMember(t, image._id));
});

View File

@ -8,13 +8,26 @@ import { Event, backgroundTask } from '../utils/event.js';
const db = getDatabase();
const PROCESS_PREFIX = 'importing';
const PREFIX = 'image';
// Events
export const imported = new Event('Image.imported');
export const removed = new Event('Image.removed');
// Methods
const getId = id => (id.startsWith(PREFIX) ? id : `${PREFIX}_${id}`);
export async function find(keys, options = {}) {
return await db.allDocs(Object.assign({ include_docs: true }, options, { keys }));
let opts = { include_docs: true };
if (Array.isArray(keys)) {
Object.assign(opts, options);
opts.keys = keys.map(getId);
} else {
Object.assign(opts, keys);
opts.startkey = `${PREFIX}_0`;
opts.endkey = `${PREFIX}_\ufff0`;
}
return await db.allDocs(opts);
}
export async function add(imageFileList) {
@ -45,6 +58,9 @@ export async function remove(ids, rev) {
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) {
@ -76,8 +92,8 @@ export async function addAttachment(doc, key, blob) {
// Internal Functions
const processImportables = backgroundTask(async function _processImportables() {
const result = await db.allDocs({
startkey: `${PROCESS_PREFIX}_0`,
endkey: `${PROCESS_PREFIX}_z`,
startkey: `${PROCESS_PREFIX}_`,
endkey: `${PROCESS_PREFIX}_\ufff0`,
include_docs: true,
attachments: true,
binary: true,
@ -97,7 +113,7 @@ const processImportables = backgroundTask(async function _processImportables() {
tags.DateTimeOriginal ? new Date(tags.DateTimeOriginal * 1000).toISOString() : doc.modifiedDate
);
const { _id, _rev } = doc;
const id = `image_${originalDate.getTime().toString(36)}_${digest.substr(0, 6)}`;
const id = `${PREFIX}_${originalDate.getTime().toString(36)}_${digest.substr(0, 6)}`;
let continueProcessing = true;
try {

View File

@ -13,13 +13,23 @@ export const hashString = name =>
const getId = id => (id.startsWith(PREFIX) ? id : `${PREFIX}_${hashString(id)}`);
export async function find(keys, options = {}) {
return await db.allDocs(Object.assign({ include_docs: true }, options, { keys: keys.map(getId) }));
let opts = { include_docs: true };
if (Array.isArray(keys)) {
Object.assign(opts, options);
opts.keys = keys.map(getId);
} else {
Object.assign(opts, keys);
opts.startkey = `${PREFIX}_`;
opts.endkey = `${PREFIX}_\ufff0`;
}
return await db.allDocs(opts);
}
export async function add(id, members = []) {
export async function add(id, props = {}, members = []) {
const _id = getId(id);
const [results, created] = await getOrCreate({
_id,
props,
members: []
});

View File

@ -1,8 +1,11 @@
<body>
<div>
Images
<input id='fInput' type="file" multiple accept="image/jpeg"/>
</div>
<select id='display' value='i'>
<option value='i'>Images</option>
<option value='a'>Albums</option>
</select>
<h1></h1>
<div id='app'></div>
</body>
<script src="/assets/app.bundle.js"></script>