Refactor: Album interface elements become Section
This is to make way for real the real album view.
This commit is contained in:
parent
ef8df004d5
commit
490b788fd0
@ -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());
|
||||
})
|
||||
]);
|
||||
};
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
});
|
||||
@ -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)]
|
||||
)
|
||||
]);
|
||||
}
|
||||
@ -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';
|
||||
|
||||
@ -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: {
|
||||
84
packages/gallery/src/interface/sectionView.js
Normal file
84
packages/gallery/src/interface/sectionView.js
Normal file
@ -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
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user