Gallery -> DOMVM GalleryView
The whole app is converted to be base in DOMVM now. But there are bugs.
This commit is contained in:
parent
ccfd757aed
commit
e1c1c0e18a
@ -21,6 +21,7 @@
|
|||||||
"pouchdb-binary-utils": "~6.1.2",
|
"pouchdb-binary-utils": "~6.1.2",
|
||||||
"pouchdb-core": "~6.1.2",
|
"pouchdb-core": "~6.1.2",
|
||||||
"pouchdb-replication": "~6.1.2",
|
"pouchdb-replication": "~6.1.2",
|
||||||
|
"router": "2.0.0",
|
||||||
"webpack": "^2.3.3"
|
"webpack": "^2.3.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@ -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 image from './data/image.js';
|
||||||
import * as index from './data/indexType.js';
|
import * as index from './data/indexType.js';
|
||||||
import { getDatabase } from './services/db.js';
|
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 { GalleryView } from './interface/gallery.js';
|
||||||
import { AlbumView } from './interface/album.js';
|
import { router, routeChanged } from './services/router.js';
|
||||||
|
|
||||||
window.__DEV__ = true;
|
|
||||||
window.db = getDatabase();
|
window.db = getDatabase();
|
||||||
|
|
||||||
image.imported.subscribe(refresh);
|
const NAV_OPTIONS = {
|
||||||
image.imported.subscribe(generateThumbnails);
|
images: {
|
||||||
image.removed.subscribe(refresh);
|
model: image,
|
||||||
index.added.subscribe(refresh);
|
title: 'Images'
|
||||||
index.removed.subscribe(refresh);
|
},
|
||||||
const header = document.querySelector('h1');
|
albums: {
|
||||||
const container = document.querySelector('#app');
|
model: index,
|
||||||
const displaySelector = document.querySelector('#display');
|
title: 'Albums'
|
||||||
|
}
|
||||||
// Events
|
|
||||||
displaySelector.onchange = refresh;
|
|
||||||
document.querySelector('#fInput').onchange = async evt => {
|
|
||||||
image.add(evt.currentTarget.files);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// To test the output:
|
async function update(route) {
|
||||||
function refresh() {
|
const o = NAV_OPTIONS[route.name];
|
||||||
setTimeout(render, 100);
|
gallery.update({
|
||||||
}
|
title: o.title,
|
||||||
|
members: (await o.model.find({ attachments: true })).rows
|
||||||
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);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
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');
|
||||||
|
|||||||
@ -5,12 +5,6 @@
|
|||||||
<link rel="stylesheet" href="">
|
<link rel="stylesheet" href="">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<input id='fInput' type="file" multiple accept="image/jpeg"/>
|
|
||||||
<select id='display' value='i'>
|
|
||||||
<option value='i'>Images</option>
|
|
||||||
<option value='a'>Albums</option>
|
|
||||||
</select>
|
|
||||||
<h1></h1>
|
|
||||||
<div id='app'></div>
|
<div id='app'></div>
|
||||||
<script src="/assets/app.bundle.js"></script>
|
<script src="/assets/app.bundle.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@ -8,9 +8,10 @@ export function AlbumView(vm, model) {
|
|||||||
const title = props.title;
|
const title = props.title;
|
||||||
let images = [];
|
let images = [];
|
||||||
|
|
||||||
|
// FIXME - If the album is updated, this does not properly refresh.
|
||||||
image.find(members, { attachments: true }).then(res => {
|
image.find(members, { attachments: true }).then(res => {
|
||||||
images = res.rows.filter(i => i.doc);
|
images = res.rows.filter(i => i.doc);
|
||||||
vm.redraw(true);
|
vm.redraw();
|
||||||
});
|
});
|
||||||
|
|
||||||
function removeImageFromAlbum(id, rev) {
|
function removeImageFromAlbum(id, rev) {
|
||||||
@ -21,11 +22,15 @@ export function AlbumView(vm, model) {
|
|||||||
return el('.album', [
|
return el('.album', [
|
||||||
el('h2', [title]),
|
el('h2', [title]),
|
||||||
...images.map(i => {
|
...images.map(i => {
|
||||||
return defineView(ImageView, {
|
return defineView(
|
||||||
|
ImageView,
|
||||||
|
{
|
||||||
imageRow: i,
|
imageRow: i,
|
||||||
showTags: false,
|
showTags: false,
|
||||||
remove: removeImageFromAlbum
|
remove: removeImageFromAlbum
|
||||||
});
|
},
|
||||||
|
i._id
|
||||||
|
);
|
||||||
})
|
})
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|||||||
53
packages/gallery/src/interface/gallery.js
Normal file
53
packages/gallery/src/interface/gallery.js
Normal file
@ -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
|
||||||
|
);
|
||||||
|
}))
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -2,8 +2,14 @@ import { defineView, defineElement as el } from 'domvm';
|
|||||||
import { ThumbnailView } from './thumbnail.js';
|
import { ThumbnailView } from './thumbnail.js';
|
||||||
|
|
||||||
export function ImageView(vm, model) {
|
export function ImageView(vm, model) {
|
||||||
|
const { addTag } = model;
|
||||||
|
|
||||||
|
function onAddTag(image_id) {
|
||||||
|
addTag(prompt('Tag Name'), image_id);
|
||||||
|
}
|
||||||
|
|
||||||
return function(vm, model, key, opts) {
|
return function(vm, model, key, opts) {
|
||||||
const { imageRow, showTags, remove, removeTag } = model;
|
const { imageRow, showTags, remove, addTag, removeTag } = model;
|
||||||
const { doc } = imageRow;
|
const { doc } = imageRow;
|
||||||
const { thumbnail } = doc._attachments;
|
const { thumbnail } = doc._attachments;
|
||||||
const _showTags = showTags !== undefined ? showTags : true;
|
const _showTags = showTags !== undefined ? showTags : true;
|
||||||
@ -18,7 +24,8 @@ export function ImageView(vm, model) {
|
|||||||
tags: _showTags ? doc.tags : [],
|
tags: _showTags ? doc.tags : [],
|
||||||
remove: remove,
|
remove: remove,
|
||||||
removeTag: removeTag
|
removeTag: removeTag
|
||||||
})
|
}),
|
||||||
|
addTag ? el('button', { onclick: [onAddTag, doc._id] }, '+') : null
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,8 @@
|
|||||||
import { defineElement as el } from 'domvm';
|
import { defineElement as el } from 'domvm';
|
||||||
|
|
||||||
export function ThumbnailView(vm, model) {
|
export function ThumbnailView(vm, model) {
|
||||||
const { remove, removeTag } = model;
|
|
||||||
|
|
||||||
return function(vm, model, key, opts) {
|
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);
|
const filteredTags = Object.entries(tags).filter(([_, visible]) => visible);
|
||||||
|
|
||||||
return el(`figure#${id}.image`, [
|
return el(`figure#${id}.image`, [
|
||||||
|
|||||||
31
packages/gallery/src/services/router.js
Normal file
31
packages/gallery/src/services/router.js
Normal file
@ -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')
|
||||||
|
}
|
||||||
|
]);
|
||||||
@ -14,5 +14,10 @@ module.exports = {
|
|||||||
devServer: {
|
devServer: {
|
||||||
contentBase: path.resolve(__dirname, './src')
|
contentBase: path.resolve(__dirname, './src')
|
||||||
},
|
},
|
||||||
|
plugins: [
|
||||||
|
new webpack.DefinePlugin({
|
||||||
|
__DEV__: true
|
||||||
|
})
|
||||||
|
],
|
||||||
devtool: 'source-map'
|
devtool: 'source-map'
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user