mirror of https://github.com/thumbsup/thumbsup
Refactor album mapping code to be much simpler based on (media) => string
parent
07ec7702cd
commit
7e73e6a10b
@ -1,42 +0,0 @@
|
||||
var _ = require('lodash')
|
||||
var path = require('path')
|
||||
var moment = require('moment')
|
||||
var Album = require('./album')
|
||||
|
||||
// creates nested albums based on the media date, e.g. "{year}/{month}"
|
||||
// opts = {format}, where format is a valid <moment> format
|
||||
// e.g. "YYYY-MM" or "YYYY/MMMM" for nested albums
|
||||
exports.albums = function (collection, opts) {
|
||||
opts = _.defaults(opts, {
|
||||
grouping: opts.albumsDateFormat || 'YYYY-MMMM'
|
||||
})
|
||||
var groups = {}
|
||||
// put all files in the right albums
|
||||
collection.forEach(function (media) {
|
||||
var groupName = moment(media.date).format(opts.grouping)
|
||||
createAlbumHierarchy(groups, groupName)
|
||||
groups[groupName].files.push(media)
|
||||
})
|
||||
// only return top-level albums
|
||||
var topLevel = _.keys(groups).filter(function (dir) {
|
||||
return path.dirname(dir) === '.'
|
||||
})
|
||||
return _.values(_.pick(groups, topLevel))
|
||||
}
|
||||
|
||||
function createAlbumHierarchy (albumsByFullDate, dateSegment) {
|
||||
if (!albumsByFullDate.hasOwnProperty(dateSegment)) {
|
||||
// create parent albums first
|
||||
var parentDate = path.dirname(dateSegment)
|
||||
if (parentDate !== '.') {
|
||||
createAlbumHierarchy(albumsByFullDate, parentDate)
|
||||
}
|
||||
// then create album if it doesn't exist
|
||||
var lastDateSegment = path.basename(dateSegment)
|
||||
albumsByFullDate[dateSegment] = new Album({title: lastDateSegment})
|
||||
// then attach to parent
|
||||
if (parentDate !== '.') {
|
||||
albumsByFullDate[parentDate].albums.push(albumsByFullDate[dateSegment])
|
||||
}
|
||||
}
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
var _ = require('lodash')
|
||||
var path = require('path')
|
||||
var Album = require('./album')
|
||||
|
||||
// for now only 1 level of folders,
|
||||
// e.g. an album might be called "holidays/newyork" or "holidays/tokyo"n
|
||||
// eventually we could return nested albums as an option
|
||||
exports.albums = function (collection, opts) {
|
||||
var albumsByFullPath = {}
|
||||
// put all files in the right album
|
||||
collection.forEach(function (media) {
|
||||
var fullDir = path.dirname(media.file.path)
|
||||
createAlbumHierarchy(albumsByFullPath, fullDir)
|
||||
albumsByFullPath[fullDir].files.push(media)
|
||||
})
|
||||
// only return top-level albums
|
||||
var topLevel = _.keys(albumsByFullPath).filter(function (dir) {
|
||||
return path.dirname(dir) === '.'
|
||||
})
|
||||
return _.values(_.pick(albumsByFullPath, topLevel))
|
||||
}
|
||||
|
||||
function createAlbumHierarchy (albumsByFullPath, fullDir) {
|
||||
if (!albumsByFullPath.hasOwnProperty(fullDir)) {
|
||||
// create parent albums first
|
||||
var parentDir = path.dirname(fullDir)
|
||||
if (parentDir !== '.') {
|
||||
createAlbumHierarchy(albumsByFullPath, parentDir)
|
||||
}
|
||||
// then create album if it doesn't exist
|
||||
var dirname = path.basename(fullDir)
|
||||
albumsByFullPath[fullDir] = new Album({title: dirname})
|
||||
// then attach to parent
|
||||
if (parentDir !== '.') {
|
||||
albumsByFullPath[parentDir].albums.push(albumsByFullPath[fullDir])
|
||||
}
|
||||
}
|
||||
}
|
@ -1,22 +1,45 @@
|
||||
var Album = require('./album')
|
||||
var byFolder = require('./by-folder')
|
||||
var byDate = require('./by-date')
|
||||
const _ = require('lodash')
|
||||
const path = require('path')
|
||||
const Album = require('./album')
|
||||
|
||||
exports.createAlbums = function (collection, opts) {
|
||||
// top-level album for the home page
|
||||
exports.createAlbums = function (collection, mapper, opts) {
|
||||
// returns a top-level album for the home page
|
||||
// under which all files are grouped into sub-albums
|
||||
// and finalised recursively (calculate stats, etc...)
|
||||
var home = new Album('Home')
|
||||
home.filename = opts.index || 'index'
|
||||
|
||||
// create albums
|
||||
if (opts.albumsFrom === 'folders') {
|
||||
home.albums = byFolder.albums(collection, opts)
|
||||
} else if (opts.albumsFrom === 'date') {
|
||||
home.albums = byDate.albums(collection, opts)
|
||||
} else {
|
||||
throw new Error('Invalid <albumsFrom> option')
|
||||
}
|
||||
|
||||
// finalize all albums recursively (calculate stats, etc...)
|
||||
home.albums = group(collection, mapper)
|
||||
home.finalize(opts)
|
||||
return home
|
||||
}
|
||||
|
||||
function group (collection, mapper) {
|
||||
var groups = {}
|
||||
// put all files in the right albums
|
||||
collection.forEach(function (media) {
|
||||
var groupName = mapper(media)
|
||||
createAlbumHierarchy(groups, groupName)
|
||||
groups[groupName].files.push(media)
|
||||
})
|
||||
// only return top-level albums
|
||||
var topLevel = _.keys(groups).filter(function (dir) {
|
||||
return path.dirname(dir) === '.'
|
||||
})
|
||||
return _.values(_.pick(groups, topLevel))
|
||||
}
|
||||
|
||||
function createAlbumHierarchy (allGroupNames, segment) {
|
||||
if (!allGroupNames.hasOwnProperty(segment)) {
|
||||
// create parent albums first
|
||||
var parent = path.dirname(segment)
|
||||
if (parent !== '.') {
|
||||
createAlbumHierarchy(allGroupNames, parent)
|
||||
}
|
||||
// then create album if it doesn't exist
|
||||
var lastSegment = path.basename(segment)
|
||||
allGroupNames[segment] = new Album({title: lastSegment})
|
||||
// then attach to parent
|
||||
if (parent !== '.') {
|
||||
allGroupNames[parent].albums.push(allGroupNames[segment])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,15 @@
|
||||
const moment = require('moment')
|
||||
const path = require('path')
|
||||
|
||||
exports.create = function (opts) {
|
||||
var mapper = null
|
||||
if (opts.albumsFrom === 'folders') {
|
||||
mapper = (media) => path.dirname(media.file.path)
|
||||
} else if (opts.albumsFrom === 'date') {
|
||||
var dateFormat = opts.albumsDateFormat || 'YYYY MMMM'
|
||||
mapper = (media) => moment(media.date).format(dateFormat)
|
||||
} else {
|
||||
throw new Error('Invalid <albumsFrom> option')
|
||||
}
|
||||
return mapper
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
/* eslint-disable camelcase */
|
||||
|
||||
var should = require('should/as-function')
|
||||
var Album = require('../../src/model/album.js')
|
||||
var bydate = require('../../src/model/by-date.js')
|
||||
var fixtures = require('../fixtures')
|
||||
|
||||
describe('ByDate', function () {
|
||||
beforeEach(function () {
|
||||
Album.resetIds()
|
||||
})
|
||||
|
||||
it('creates top-level albums grouped by month', function () {
|
||||
// create files from different dates
|
||||
var a_2016_06 = fixtures.photo({date: fixtures.date('2016-06-01')})
|
||||
var b_2016_06 = fixtures.photo({date: fixtures.date('2016-06-10')})
|
||||
var c_2016_07 = fixtures.photo({date: fixtures.date('2016-07-23')})
|
||||
var d_2016_07 = fixtures.video({date: fixtures.date('2016-07-18')})
|
||||
// group them per month
|
||||
var collection = [a_2016_06, b_2016_06, c_2016_07, d_2016_07]
|
||||
var albums = bydate.albums(collection, {
|
||||
grouping: 'YYYY-MM'
|
||||
})
|
||||
// assert on the result
|
||||
should(albums).eql([
|
||||
new Album({
|
||||
id: 1,
|
||||
'title': '2016-06',
|
||||
files: [a_2016_06, b_2016_06]
|
||||
}),
|
||||
new Album({
|
||||
id: 2,
|
||||
title: '2016-07',
|
||||
files: [c_2016_07, d_2016_07]
|
||||
})
|
||||
])
|
||||
})
|
||||
|
||||
it('creates albums using a date hierarchy', function () {
|
||||
// create files from different dates
|
||||
var a_2015_06 = fixtures.photo({date: fixtures.date('2015-06-01')})
|
||||
var b_2015_06 = fixtures.photo({date: fixtures.date('2015-06-10')})
|
||||
var c_2016_07 = fixtures.photo({date: fixtures.date('2016-07-23')})
|
||||
var d_2016_08 = fixtures.video({date: fixtures.date('2016-08-18')})
|
||||
// group them per year, and nested month
|
||||
var collection = [a_2015_06, b_2015_06, c_2016_07, d_2016_08]
|
||||
var albums = bydate.albums(collection, {
|
||||
grouping: 'YYYY/MM'
|
||||
})
|
||||
// assert on the result
|
||||
should(albums).eql([
|
||||
new Album({
|
||||
id: 1,
|
||||
'title': '2015',
|
||||
files: [],
|
||||
albums: [
|
||||
new Album({
|
||||
id: 2,
|
||||
title: '06',
|
||||
files: [a_2015_06, b_2015_06]
|
||||
})
|
||||
]
|
||||
}),
|
||||
new Album({
|
||||
id: 3,
|
||||
title: '2016',
|
||||
files: [],
|
||||
albums: [
|
||||
new Album({
|
||||
id: 4,
|
||||
title: '07',
|
||||
files: [c_2016_07]
|
||||
}),
|
||||
new Album({
|
||||
id: 5,
|
||||
title: '08',
|
||||
files: [d_2016_08]
|
||||
})
|
||||
]
|
||||
})
|
||||
])
|
||||
})
|
||||
})
|
@ -1,70 +0,0 @@
|
||||
var should = require('should/as-function')
|
||||
var Album = require('../../src/model/album.js')
|
||||
var byfolder = require('../../src/model/by-folder.js')
|
||||
var fixtures = require('../fixtures')
|
||||
|
||||
describe('ByFolder', function () {
|
||||
beforeEach(function () {
|
||||
Album.resetIds()
|
||||
})
|
||||
|
||||
it('creates albums by folders', function () {
|
||||
// create files in different folders
|
||||
var london1 = fixtures.photo({path: 'london/IMG_000001.jpg'})
|
||||
var london2 = fixtures.photo({path: 'london/IMG_000002.jpg'})
|
||||
var newyork1 = fixtures.photo({path: 'newyork/IMG_000003.jpg'})
|
||||
var newyork2 = fixtures.video({path: 'newyork/IMG_000004.mp4'})
|
||||
// group them per folder
|
||||
var collection = [london1, london2, newyork1, newyork2]
|
||||
var albums = byfolder.albums(collection, {})
|
||||
// assert on the result
|
||||
should(albums).eql([
|
||||
new Album({
|
||||
id: 1,
|
||||
title: 'london',
|
||||
files: [london1, london2]
|
||||
}),
|
||||
new Album({
|
||||
id: 2,
|
||||
title: 'newyork',
|
||||
files: [newyork1, newyork2]
|
||||
})
|
||||
])
|
||||
})
|
||||
|
||||
it('creates nested albums for nested folders', function () {
|
||||
// create files in nested folders
|
||||
var photo1 = fixtures.photo({path: 'a/b/c/IMG_000001.jpg'})
|
||||
var photo2 = fixtures.photo({path: 'a/d/IMG_000002.jpg'})
|
||||
// group them per folder
|
||||
var collection = [photo1, photo2]
|
||||
var albums = byfolder.albums(collection, {})
|
||||
// assert on the result
|
||||
should(albums).eql([
|
||||
new Album({
|
||||
id: 1,
|
||||
title: 'a',
|
||||
files: [],
|
||||
albums: [
|
||||
new Album({
|
||||
id: 2,
|
||||
title: 'b',
|
||||
files: [],
|
||||
albums: [
|
||||
new Album({
|
||||
id: 3,
|
||||
title: 'c',
|
||||
files: [photo1]
|
||||
})
|
||||
]
|
||||
}),
|
||||
new Album({
|
||||
id: 4,
|
||||
title: 'd',
|
||||
files: [photo2]
|
||||
})
|
||||
]
|
||||
})
|
||||
])
|
||||
})
|
||||
})
|
@ -0,0 +1,90 @@
|
||||
const path = require('path')
|
||||
const should = require('should/as-function')
|
||||
const hierarchy = require('../../src/model/hierarchy.js')
|
||||
const Album = require('../../src/model/album.js')
|
||||
const fixtures = require('../fixtures')
|
||||
|
||||
describe('hierarchy', function () {
|
||||
beforeEach(function () {
|
||||
Album.resetIds()
|
||||
})
|
||||
|
||||
describe('root album', function () {
|
||||
it('creates a root album (homepage) to put all sub-albums', function () {
|
||||
const mapper = (media) => 'all'
|
||||
const home = hierarchy.createAlbums([], mapper, {})
|
||||
should(home.title).eql('Home')
|
||||
})
|
||||
|
||||
it('defaults the homepage to index.html', function () {
|
||||
const mapper = (media) => 'all'
|
||||
const home = hierarchy.createAlbums([], mapper, {})
|
||||
should(home.path).eql('index.html')
|
||||
should(home.url).eql('index.html')
|
||||
})
|
||||
|
||||
it('can configure the homepage path', function () {
|
||||
const mapper = (media) => 'all'
|
||||
const home = hierarchy.createAlbums([], mapper, {index: 'default.html'})
|
||||
should(home.path).eql('default.html')
|
||||
should(home.url).eql('default.html')
|
||||
})
|
||||
})
|
||||
|
||||
describe('nested albums', function () {
|
||||
it('can group media into a single folder', function () {
|
||||
const media = [
|
||||
fixtures.photo({path: 'IMG_000001.jpg'}),
|
||||
fixtures.photo({path: 'IMG_000002.jpg'})
|
||||
]
|
||||
const mapper = (media) => 'all'
|
||||
const home = hierarchy.createAlbums(media, mapper)
|
||||
should(home.albums.length).eql(1)
|
||||
should(home.albums[0].title).eql('all')
|
||||
should(home.albums[0].files).eql([media[0], media[1]])
|
||||
})
|
||||
|
||||
it('can group media into several folders', function () {
|
||||
const media = [
|
||||
fixtures.photo({path: 'one/IMG_000001.jpg'}),
|
||||
fixtures.photo({path: 'two/IMG_000002.jpg'})
|
||||
]
|
||||
const mapper = (media) => path.dirname(media.file.path)
|
||||
const home = hierarchy.createAlbums(media, mapper)
|
||||
should(home.albums.length).eql(2)
|
||||
should(home.albums[0].title).eql('one')
|
||||
should(home.albums[0].files).eql([media[0]])
|
||||
should(home.albums[1].title).eql('two')
|
||||
should(home.albums[1].files).eql([media[1]])
|
||||
})
|
||||
|
||||
it('can group media into one nested folder', function () {
|
||||
const media = [
|
||||
fixtures.photo({path: 'IMG_000001.jpg'}),
|
||||
fixtures.photo({path: 'IMG_000002.jpg'})
|
||||
]
|
||||
const mapper = (media) => 'one/two'
|
||||
const home = hierarchy.createAlbums(media, mapper)
|
||||
should(home.albums.length).eql(1)
|
||||
should(home.albums[0].title).eql('one')
|
||||
should(home.albums[0].albums.length).eql(1)
|
||||
should(home.albums[0].albums[0].title).eql('two')
|
||||
should(home.albums[0].albums[0].files).eql([media[0], media[1]])
|
||||
})
|
||||
|
||||
it('can group media at different levels', function () {
|
||||
const media = [
|
||||
fixtures.photo({path: 'one/IMG_000001.jpg'}),
|
||||
fixtures.photo({path: 'one/two/IMG_000002.jpg'})
|
||||
]
|
||||
const mapper = (media) => path.dirname(media.file.path)
|
||||
const home = hierarchy.createAlbums(media, mapper)
|
||||
should(home.albums.length).eql(1)
|
||||
should(home.albums[0].title).eql('one')
|
||||
should(home.albums[0].files).eql([media[0]])
|
||||
should(home.albums[0].albums.length).eql(1)
|
||||
should(home.albums[0].albums[0].title).eql('two')
|
||||
should(home.albums[0].albums[0].files).eql([media[1]])
|
||||
})
|
||||
})
|
||||
})
|
@ -0,0 +1,32 @@
|
||||
var should = require('should/as-function')
|
||||
var mapper = require('../../src/model/mapper.js')
|
||||
var fixtures = require('../fixtures.js')
|
||||
|
||||
describe('mapper', function () {
|
||||
it('can create a path mapper', function () {
|
||||
const map = mapper.create({albumsFrom: 'folders'})
|
||||
const media = fixtures.photo({
|
||||
path: 'holidays/canada/IMG_0001.jpg'
|
||||
})
|
||||
should(map(media)).eql('holidays/canada')
|
||||
})
|
||||
it('can create a default date mapper', function () {
|
||||
const map = mapper.create({albumsFrom: 'date'})
|
||||
const media = fixtures.photo({
|
||||
path: 'holidays/canada/IMG_0001.jpg',
|
||||
date: '2016-07-14 12:07:41'
|
||||
})
|
||||
should(map(media)).eql('2016 July')
|
||||
})
|
||||
it('can create a custom date mapper', function () {
|
||||
const map = mapper.create({
|
||||
albumsFrom: 'date',
|
||||
albumsDateFormat: 'YYYY/MM'
|
||||
})
|
||||
const media = fixtures.photo({
|
||||
path: 'holidays/canada/IMG_0001.jpg',
|
||||
date: '2016-07-14 12:07:41'
|
||||
})
|
||||
should(map(media)).eql('2016/07')
|
||||
})
|
||||
})
|
Loading…
Reference in New Issue