From 2f7cf1830f9037128bdbf2c69e2f57c11946a4a1 Mon Sep 17 00:00:00 2001 From: Timothy Farrell Date: Sun, 31 Dec 2017 17:24:58 -0600 Subject: [PATCH] Refactor: Album interface elements become Section This is to make way for real the real album view. --- packages/gallery/src/interface/album.js | 79 ----------------- packages/gallery/src/interface/allImages.js | 31 ++++--- .../src/interface/components/albumTemplate.js | 77 ----------------- .../src/interface/components/thumbnail.js | 14 ---- packages/gallery/src/interface/gallery.js | 1 - .../albumPhotoTemplate.js => sectionPhoto.js} | 16 ++-- packages/gallery/src/interface/sectionView.js | 84 +++++++++++++++++++ 7 files changed, 111 insertions(+), 191 deletions(-) delete mode 100644 packages/gallery/src/interface/album.js delete mode 100644 packages/gallery/src/interface/components/albumTemplate.js delete mode 100644 packages/gallery/src/interface/components/thumbnail.js rename packages/gallery/src/interface/{components/albumPhotoTemplate.js => sectionPhoto.js} (87%) create mode 100644 packages/gallery/src/interface/sectionView.js diff --git a/packages/gallery/src/interface/album.js b/packages/gallery/src/interface/album.js deleted file mode 100644 index 920f5dc..0000000 --- a/packages/gallery/src/interface/album.js +++ /dev/null @@ -1,79 +0,0 @@ -import { defineView, defineElement as el } from '../utils/domvm.js'; - -import { ImageType } from '../data/image.js'; -import { FileType } from '../data/file.js'; -import { pouchDocArrayHash, pouchDocHash } from '../utils/conversion.js'; -import { ThumbnailTemplate } from './components/thumbnail.js'; -import { prop, computed } from 'frptools'; - -export function AlbumView(vm, params) { - const model = prop({}, pouchDocHash); - const images = prop([], pouchDocArrayHash); - - const id = computed(pouchDocHash, [model]); - const members = computed(d => d.members, [model]); // always update - const title = computed(d => d.title, [model]); // always update - - let laCleanup = null; - const refresh = _ => vm.redraw(); - const subscriptions = [ - images.subscribe(refresh), - model.subscribe(async album => { - if (!album.findImages) { - return; - } - const imagesLiveArray = await album.findImages(true); - - if (laCleanup) { - laCleanup(); - } - - function refresh() { - images(imagesLiveArray()); - vm.redraw(); - } - - laCleanup = imagesLiveArray.subscribe(refresh); - imagesLiveArray.ready.subscribe(refresh); - }) - ]; - - function removeImageFromAlbum(image) { - model().removeImage(image); - } - - function removeAlbum(album) { - album.delete(); - } - - function uploadImages(album, evt) { - Array.from(evt.currentTarget.files).forEach(f => album.addImageBlob(f)); - } - - function cleanup() { - if (laCleanup) { - laCleanup(); - } - subscriptions.forEach(s => s()); - } - - model(params); - - return function() { - const album = model(); - - return el('.album', [ - el('h2', title), - el('button', { onclick: [removeAlbum, album] }, 'X'), - el('input#fInput', { - type: 'file', - multiple: true, - accept: 'image/jpeg', - onchange: [uploadImages, album] - }), - ...images().map(i => { - return ThumbnailTemplate(i, removeImageFromAlbum, i._hash()); - }) - ]); - }; -} diff --git a/packages/gallery/src/interface/allImages.js b/packages/gallery/src/interface/allImages.js index 76dafbe..0a0eea5 100644 --- a/packages/gallery/src/interface/allImages.js +++ b/packages/gallery/src/interface/allImages.js @@ -5,13 +5,14 @@ import { subscribeToRender, defineView, nodeParentWithType, + defineView as vw, defineElement as el } from '../utils/domvm.js'; import { error } from '../services/console.js'; import { ImageType } from '../data/image.js'; import { pouchDocArrayHash, pouchDocHash, hashSet, extractID } from '../utils/conversion.js'; -import { AlbumTemplate } from './components/albumTemplate.js'; +import { SectionView } from './sectionView.js'; import { Icon } from './components/icon.js'; import { injectStyle, styled } from '../services/style.js'; import { CLICKABLE } from './styles.js'; @@ -24,7 +25,8 @@ export function uploadImages(evt, files) { } } -export function AllImagesView(vm, params, key, { appbar }) { +export function AllImagesView(vm, params, key, context) { + const { appbar } = context; const model = prop({}, pouchDocHash); const images = container([], pouchDocArrayHash); @@ -42,6 +44,7 @@ export function AllImagesView(vm, params, key, { appbar }) { .sort((a, b) => a[0].localeCompare(b[0])) .map(([date, _images]) => ({ title: format(date, 'MMMM D, YYYY'), + sectionId: date, images: _images })); }, @@ -165,14 +168,18 @@ export function AllImagesView(vm, params, key, { appbar }) { ); }); - function renderSection({ title, images: _images }) { - return AlbumTemplate({ - title, - id: title, - photos: _images, - selectedIds, - selectMode: selectMode() - }); + function renderSection({ title, sectionId, images: _images }) { + return vw( + SectionView, + { + title, + photos: _images, + selectedIds, + selectMode: selectMode() + }, + sectionId, + context + ); } return function() { @@ -182,8 +189,8 @@ export function AllImagesView(vm, params, key, { appbar }) { onclick: { '.photoSelect .icon svg path': toggleSelect, '.photoSelect .icon': toggleSelect, - '.albumSelectButton .icon': toggleAll, - '.albumSelectButton .icon svg path': toggleAll, + '.sectionSelectButton .icon': toggleAll, + '.sectionSelectButton .icon svg path': toggleAll, '.photoOverlay': photoClick }, onscroll: handleContentScroll diff --git a/packages/gallery/src/interface/components/albumTemplate.js b/packages/gallery/src/interface/components/albumTemplate.js deleted file mode 100644 index ab1b7ea..0000000 --- a/packages/gallery/src/interface/components/albumTemplate.js +++ /dev/null @@ -1,77 +0,0 @@ -import { - defineView as vw, - defineElement as el, - patchRefStyle, - patchNodeStyle -} from '../../utils/domvm.js'; -import { injectStyle, styled } from '../../services/style.js'; -import { DEFAULT_TRANSITION, CLICKABLE } from '../styles.js'; -import { Icon } from './icon.js'; -import { AlbumPhotoTemplate } from './albumPhotoTemplate.js'; -import { extractID } from '../../utils/conversion.js'; - -export function AlbumTemplate(params) { - const { id, title, photos, selectedIds, selectMode } = params; - const albumSelectButtonRef = `albSel${id}`; - - function photoMap(doc) { - return vw( - AlbumPhotoTemplate, - { - doc, - isSelected: selectedIds.has(doc._id), - selectMode - }, - doc._hash() - ); - } - - return Album( - { - onmouseenter: [patchRefStyle, albumSelectButtonRef, 'opacity: 0.7;'], - onmouseleave: [patchRefStyle, albumSelectButtonRef, 'opacity: 0;'], - _data: { - type: 'section', - sectionImageIds: photos.map(extractID) - } - }, - [ - albumTitle([ - title, - albumSelectButton( - { - _ref: albumSelectButtonRef, - onmouseenter: [patchNodeStyle, 'opacity: 1;'], - onmouseleave: [patchNodeStyle, 'opacity: 0.7;'], - css: { - opacity: selectMode ? 0.7 : 0 - }, - class: 'albumSelectButton' - }, - [Icon({ name: 'check_circle', size: 0.25 })] - ) - ]), - albumContent(photos.map(photoMap)) - ] - ); -} - -const Album = styled({ - margin: '10px' -}); - -const albumTitle = styled({ - display: 'flex', - alignItems: 'center' -}); - -const albumContent = styled({ - display: 'flex', - alignItems: 'flex-start', - userSelect: 'none' -}); - -const albumSelectButton = styled(DEFAULT_TRANSITION, CLICKABLE, { - paddingLeft: '0.5em', - opacity: 0 -}); diff --git a/packages/gallery/src/interface/components/thumbnail.js b/packages/gallery/src/interface/components/thumbnail.js deleted file mode 100644 index 536d203..0000000 --- a/packages/gallery/src/interface/components/thumbnail.js +++ /dev/null @@ -1,14 +0,0 @@ -import { defineView as vw, defineElement as el } from '../../utils/domvm.js'; -import { AttachmentImageView } from './attachmentImage.js'; - -export function ThumbnailTemplate(doc, remove, key) { - return el('div', [ - el( - `figure.image`, - { - onclick: { img: [remove, doc] } - }, - [AttachmentImageView(doc)] - ) - ]); -} diff --git a/packages/gallery/src/interface/gallery.js b/packages/gallery/src/interface/gallery.js index 04e15a2..5cca458 100644 --- a/packages/gallery/src/interface/gallery.js +++ b/packages/gallery/src/interface/gallery.js @@ -10,7 +10,6 @@ import { } from '../utils/domvm.js'; import { ImageType } from '../data/image.js'; import { AlbumType } from '../data/album.js'; -import { ThumbnailTemplate } from './components/thumbnail.js'; import { AllImagesView, uploadImages } from './allImages.js'; import { FocusView } from './focus.js'; import { Dropzone } from './components/dropzone.js'; diff --git a/packages/gallery/src/interface/components/albumPhotoTemplate.js b/packages/gallery/src/interface/sectionPhoto.js similarity index 87% rename from packages/gallery/src/interface/components/albumPhotoTemplate.js rename to packages/gallery/src/interface/sectionPhoto.js index 08ef4c6..53838a1 100644 --- a/packages/gallery/src/interface/components/albumPhotoTemplate.js +++ b/packages/gallery/src/interface/sectionPhoto.js @@ -6,14 +6,14 @@ import { patchRefStyleMap, patchNodeStyle, subscribeToRender -} from '../../utils/domvm.js'; -import { router } from '../../services/router.js'; -import { injectStyle, styled } from '../../services/style.js'; -import { DEFAULT_TRANSITION, CSS_FULL_SIZE, IMAGE_MARGIN, CLICKABLE } from '../styles.js'; -import { Icon } from './icon.js'; -import { AttachmentImageView } from './attachmentImage.js'; +} from '../utils/domvm.js'; +import { router } from '../services/router.js'; +import { injectStyle, styled } from '../services/style.js'; +import { DEFAULT_TRANSITION, CSS_FULL_SIZE, IMAGE_MARGIN, CLICKABLE } from './styles.js'; +import { Icon } from './components/icon.js'; +import { AttachmentImageView } from './components/attachmentImage.js'; -export function AlbumPhotoTemplate(vm, { doc }) { +export function SectionPhoto(vm, { doc }) { const photoSelectButtonRef = `pSB${doc._id}`; const photoOverlayRef = `pBkd${doc._id}`; const href = router.href('focus', { id: doc._id }); @@ -26,7 +26,7 @@ export function AlbumPhotoTemplate(vm, { doc }) { return photoContainer( { href, - class: 'albumPhoto', + class: 'sectionPhoto', onmouseenter: [hover, true], onmouseleave: [hover, false], css: { diff --git a/packages/gallery/src/interface/sectionView.js b/packages/gallery/src/interface/sectionView.js new file mode 100644 index 0000000..e3b363b --- /dev/null +++ b/packages/gallery/src/interface/sectionView.js @@ -0,0 +1,84 @@ +import { + defineView as vw, + defineElement as el, + patchRefStyle, + patchNodeStyle +} from '../utils/domvm.js'; +import { injectStyle, styled } from '../services/style.js'; +import { DEFAULT_TRANSITION, CLICKABLE } from './styles.js'; +import { Icon } from './components/icon.js'; +import { SectionPhoto } from './sectionPhoto.js'; +import { extractID } from '../utils/conversion.js'; + +export function SectionView(vm, params, key, context) { + const { appbar } = context; + const { title, photos } = params; + const sectionSelectButtonRef = `secSel${key}`; + + return function render(vm, params) { + const { selectedIds, selectMode } = params; + + function photoTemplate(doc) { + return vw( + SectionPhoto, + { + doc, + isSelected: selectedIds.has(doc._id), + selectMode + }, + doc._hash(), + context + ); + } + + return sectionContainer( + { + class: 'section', + onmouseenter: [patchRefStyle, sectionSelectButtonRef, 'opacity: 0.7;'], + onmouseleave: [patchRefStyle, sectionSelectButtonRef, 'opacity: 0;'], + _data: { + type: 'section', + sectionImageIds: photos.map(extractID) + } + }, + [ + sectionTitle([ + title, + sectionSelectButton( + { + class: 'sectionSelectButton', + _ref: sectionSelectButtonRef, + onmouseenter: [patchNodeStyle, 'opacity: 1;'], + onmouseleave: [patchNodeStyle, 'opacity: 0.7;'], + css: { + opacity: selectMode ? 0.7 : 0 + } + }, + [Icon({ name: 'check_circle', size: 0.25 })] + ) + ]), + sectionContent(photos.map(photoTemplate)) + ] + ); + }; +} + +const sectionContainer = styled({ + margin: '10px' +}); + +const sectionTitle = styled({ + display: 'flex', + alignItems: 'center' +}); + +const sectionContent = styled({ + display: 'flex', + alignItems: 'flex-start', + userSelect: 'none' +}); + +const sectionSelectButton = styled(DEFAULT_TRANSITION, CLICKABLE, { + paddingLeft: '0.5em', + opacity: 0 +});