Add support for nested folders

pull/46/head
Romain Prieto 8 years ago
parent 5553ab0c9b
commit f69d2e3d48

@ -14,6 +14,12 @@ var SORT_MEDIA_BY = {
date: function(file) { return file.date; }
};
var PREVIEW_MISSING = {
urls: {
thumb: 'public/missing.png'
}
};
function Album(opts) {
if (typeof opts === 'string') opts = { title: opts };
this.title = opts.title || ('Album ' + index++);
@ -33,13 +39,15 @@ Album.prototype.finalize = function(options) {
});
// is this the top-level album?
this.home = this.depth === 0;
// lock all nested albums first (recursive)
// finalize all nested albums first (recursive)
// and set a nested filename
for (var i = 0; i < this.albums.length; ++i) {
this.albums[i].filename = this.filename + '-' + this.albums[i].filename;
this.albums[i].depth = this.depth + 1;
this.albums[i].finalize();
}
// perform stats & other calculations
// once the nested albums have been finalized too
this.calculateStats();
this.calculateSummary();
this.sort(options);
@ -86,12 +94,17 @@ Album.prototype.sort = function(options) {
};
Album.prototype.pickPreviews = function() {
this.previews = this.files.slice(0, PREVIEW_COUNT);
// also consider previews from nested albums
var nestedPicks = _.flatten(_.map(this.albums, 'previews')).filter(function(file) {
return file !== PREVIEW_MISSING;
});
// then pick the top 4 overall
var potentialPicks = _.concat(this.files, nestedPicks);
this.previews = potentialPicks.slice(0, PREVIEW_COUNT);
// and fill the gap with a placeholder
var missing = PREVIEW_COUNT - this.previews.length;
for (var i = 0; i < missing; ++i) {
this.previews.push({
urls: { thumb: 'public/missing.png' }
});
this.previews.push(PREVIEW_MISSING);
}
};

@ -6,19 +6,33 @@ var Album = require('./album');
// 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 folders = {};
var albumsByFullPath = {};
// put all files in the right album
collection.files.forEach(function(file) {
var dir = path.dirname(file.filepath);
if (!folders.hasOwnProperty(dir)) {
folders[dir] = [];
}
folders[dir].push(file);
var fullDir = path.dirname(file.filepath);
createAlbumHierarchy(albumsByFullPath, fullDir);
albumsByFullPath[fullDir].files.push(file);
});
// only return top-level albums
var topLevel = _.keys(albumsByFullPath).filter(function(dir) {
return path.dirname(dir) === '.';
});
var albums = _.map(folders, function(val, key) {
return new Album({
title: key,
files: folders[key]
});
})
return albums;
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]);
}
}
}

@ -164,6 +164,10 @@ h1 {
border-right: 1px solid @borders;
}
#sidebar ul:not(:first-child) {
margin-left: 1.5em;
}
#sidebar i.fa {
margin-right: 0.3em;
}

@ -139,6 +139,28 @@ describe('Album', function() {
should(a.previews[3].urls.thumb).eql('public/missing.png');
});
it('uses files from nested albums too', function() {
var a = new Album({
title: 'a',
albums: [
new Album({
title: 'b',
files: [fixtures.photo(), fixtures.photo()]
}),
new Album({
title: 'c',
files: [fixtures.photo(), fixtures.photo()]
})
]
});
a.finalize();
should(a.previews).have.length(4);
console.log('-----\n', a.previews)
for (var i = 0; i < 4; ++i) {
should(a.previews[i].urls.thumb).not.eql('public/missing.png');
}
});
});
});

@ -27,4 +27,37 @@ describe('ByFolder', function() {
]);
});
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 = {files: [photo1, photo2]};
var albums = byfolder.albums(collection, {});
console.log(albums);
// assert on the result
should(albums).eql([
new Album({
title: 'a',
files: [],
albums: [
new Album({
title: 'b',
files: [],
albums: [
new Album({
title: 'c',
files: [photo1]
})
]
}),
new Album({
title: 'd',
files: [photo2]
})
]
})
]);
});
});

Loading…
Cancel
Save