From 77332428e6ed397853dd0ed4794711104d525a81 Mon Sep 17 00:00:00 2001 From: James Ketrenos Date: Sun, 7 Oct 2018 16:26:42 -0700 Subject: [PATCH] Started implementing maintainer action buttons Signed-off-by: James Ketrenos --- frontend/elements/photo-thumbnail.html | 31 +++++- frontend/src/ketr-photos/ketr-photos.html | 34 ++++++ server/scanner.js | 128 +++++++++++++--------- 3 files changed, 136 insertions(+), 57 deletions(-) diff --git a/frontend/elements/photo-thumbnail.html b/frontend/elements/photo-thumbnail.html index 4a3b8d3..df7510f 100755 --- a/frontend/elements/photo-thumbnail.html +++ b/frontend/elements/photo-thumbnail.html @@ -2,6 +2,7 @@ + @@ -28,7 +29,7 @@ @apply --photo-thumbnail; } - :host > div { + #info { position: absolute; padding: 0.5em; background-color: rgba(0, 0, 0, 0.5); @@ -37,15 +38,29 @@ left: 0px; right: 0px; font-size: 0.6em; - } + } - :host(:hover) > div { + #actions { + padding: 0.5em; + background-color: rgba(0, 0, 0, 0.5); + opacity: 0; + font-size: 0.6em; + } + + :host(:hover) #info, + :host(:hover) #actions { opacity: 1; - } + } -
+
+ +
+ +
[[item.name]] ([[item.id]])
[[item.taken]]
[[item.path]]
@@ -82,6 +97,12 @@ "thumbChanged(thumbpath, visible)" ], + _fireAction: function(event) { + event.stopPropagation(); + event.preventDefault(); + this.fire("action", event.model.item); + }, + thumbChanged: function(thumbpath, visible) { if (visible) { this.style.backgroundImage = "url(" + diff --git a/frontend/src/ketr-photos/ketr-photos.html b/frontend/src/ketr-photos/ketr-photos.html index 6d78ac3..cab5b80 100755 --- a/frontend/src/ketr-photos/ketr-photos.html +++ b/frontend/src/ketr-photos/ketr-photos.html @@ -221,6 +221,7 @@ } photo-thumbnail { + transition: opacity 0.25s ease-in-out; --photo-thumbnail: { border: 3px solid white; }; @@ -1212,6 +1213,14 @@ var thumbnail = document.createElement("photo-thumbnail"); thumbnail.item = photo; + if (this.user.maintainer) { + let actions = [ "delete" ]; + if (this.mode == "duplicates") { + actions.unshift("text-format"); + } + thumbnail.actions = actions; + thumbnail.addEventListener("action", this._imageAction.bind(this)); + } thumbnail.addEventListener("load-image", this._imageTap.bind(this)); thumbnail.addEventListener("load-album", this.loadAlbum.bind(this)); @@ -1226,6 +1235,31 @@ this.processing = false; }, + _imageAction: function(event) { + console.log(event.detail); + switch (event.detail) { + case "delete": /* Delete image */ + var thumbnail = event.currentTarget; + thumbnail.style.opacity = 0; + thumbnail.style.pointerEvents = "none"; + + this.async(function(thumbnail) { + thumbnail.parentElement.removeChild(thumbnail); + for (var i = 0; i < this.thumbnails.length; i++) { + if (this.thumbnails[i] == thumbnail) { + console.log("Found thumbnail"); + this.thumbnails.splice(i, 1); + this.notifyPath("thumbnails.length"); + break; + } + } + }.bind(this, thumbnail), 250); + break; + case "text-format": /* Rename this image */ + break; + } + }, + pathTapped: function(event) { this.path = event.currentTarget.path; Polymer.dom(this.$.thumbnails).innerHTML = ""; diff --git a/server/scanner.js b/server/scanner.js index 095c6ae..bc34019 100755 --- a/server/scanner.js +++ b/server/scanner.js @@ -27,10 +27,10 @@ function removeNewerFile(path, fileA, fileB) { return; } if (statsA.mtime > statsB.mtime) { - console.log("Removing file by moving to 'corrupt':" + fileA); + setStatus("Removing file by moving to 'corrupt':" + fileA); moveCorrupt(path, fileA); } else { - console.log("Removing file by moving to 'corrupt':" + fileB); + setStatus("Removing file by moving to 'corrupt':" + fileB); moveCorrupt(path, fileB); } }); @@ -101,14 +101,14 @@ const exists = function(path) { } function convertRawToJpg(path, file) { - console.log("Converting " + path + file); + setStatus("Converting " + path + file); path = picturesPath + path; return new Promise(function(resolve, reject) { return exists(path + file.replace(rawExtension, ".jpg")).then(function(exist) { if (exist) { - console.log("Skipping already converted file: " + file); + setStatus("Skipping already converted file: " + file); return; } @@ -133,25 +133,25 @@ function convertRawToJpg(path, file) { ufraw.on('exit', function(stderr, code, signal) { if (signal || code != 0) { let error = "UFRAW for " + path + file + " returned an error: " + code + "\n" + signal + "\n" + stderr.join("\n") + "\n"; - console.error(error); + setStatus(error, "error"); return moveCorrupt(path, file).then(function() { - console.warn("ufraw failed"); + setStatus("ufraw failed", "warn"); return reject(error); }).catch(function(error) { - console.warn("moveCorrupt failed"); + setStatus("moveCorrupt failed", "warn"); return reject(error); }); } return mkdir(path + "raw").then(function() { fs.rename(path + file, path + "raw/" + file, function(err) { if (err) { - console.error("Unable to move RAW file: " + path + file); + setStatus("Unable to move RAW file: " + path + file, "error"); return reject(err); } return resolve(); }); }).catch(function(error) { - console.warn("mkdir failed"); + setStatus("mkdir failed", "warn"); return reject(error); }); }.bind(this, ufraw)); @@ -165,13 +165,13 @@ function moveCorrupt(path, file) { path = picturesPath + path; } - console.warn("Moving corrupt file '" + file + "' to " + path + "corrupt"); + setStatus("Moving corrupt file '" + file + "' to " + path + "corrupt", "warn"); return mkdir(path + "corrupt").then(function() { return new Promise(function(resolve, reject) { fs.rename(path + file, path + "corrupt/" + file, function(err) { if (err) { - console.error("Unable to move corrupt file: " + path + file); + setStatus("Unable to move corrupt file: " + path + file, "error"); return reject(err); } return resolve(); @@ -202,7 +202,7 @@ function processBlock(items) { }); let toProcess = processing.length, lastMessage = moment(); - console.log("Items to be processed: " + toProcess); + setStatus("Items to be processed: " + toProcess); return Promise.mapSeries(processing, function(asset) { return computeHash(picturesPath + asset.album.path + asset.filename).then(function(hash) { asset.hash = hash; @@ -222,7 +222,7 @@ function processBlock(items) { } else if (results[0].hash != asset.hash) { query = "UPDATE photohashes SET hash=:hash WHERE photoId=:id"; } else if (results[0].photoId != asset.id) { - console.log("Duplicate asset: " + + setStatus("Duplicate asset: " + "'" + asset.album.path + asset.filename + "' is a copy of " + "'" + results[0].path + results[0].filename + "'"); duplicates.push(asset); @@ -293,7 +293,7 @@ function processBlock(items) { asset.modified = moment(metadata.exif.exif.DateTimeOriginal).format(); if (asset.taken == "Invalid date" || asset.taken.replace(/T.*/, "") == "1899-11-30") { - console.log("Invalid EXIF date information for " + asset.album.path + asset.filename); + setStatus("Invalid EXIF date information for " + asset.album.path + asset.filename); asset.taken = asset.modified = moment(created).format(); } } else { @@ -332,7 +332,7 @@ function processBlock(items) { } return image.resize(256, 256).toFile(dst).catch(function(error) { - console.error("Error resizing image: " + dst, error); + setStatus("Error resizing image: " + dst + "\n" + error, "error"); throw error; }); }).then(function() { @@ -343,7 +343,7 @@ function processBlock(items) { } return image.resize(Math.min(1024, metadata.width)).toFile(dst).catch(function(error) { - console.error("Error resizing image: " + dst, error); + setStatus("Error resizing image: " + dst + "\n" + error, "error"); throw error; }); }); @@ -355,7 +355,7 @@ function processBlock(items) { }); }); }).catch(function(error) { - console.error("Error reading image " + src + ": ", error); + setStatus("Error reading image " + src + ":\n" + error, "error"); return moveCorrupt(path, file).then(function() { /* If the original file was not a NEF/ORF, we are done... */ @@ -369,31 +369,31 @@ function processBlock(items) { /* Move the NEF/ORF to /corrupt as well so it isn't re-checked again and again... */ // return moveCorrupt(path, asset.filename); - console.error("Already attempted to convert NEF/ORF to JPG: " + path + file); + setStatus("Already attempted to convert NEF/ORF to JPG: " + path + file, "error"); return; } } - console.warn("Adding " + path + file + " back onto processing queue."); + setStatus("Adding " + path + file + " back onto processing queue.", "error"); triedClean.push(path + file); processBlock([ path, file, created, albumId ]); }); }); }).catch(function() { - console.warn("Continuing file processing."); + setStatus("Continuing file processing.", "warn"); }); }).then(function() { toProcess--; if (moment().add(-5, 'seconds') > lastMessage) { - console.log("Items to be processed: " + toProcess); + setStatus("Items to be processed: " + toProcess); lastMessage = moment(); } }); }).catch(function(error) { - console.log("Error processing file. Continuing."); + setStatus("Error processing file. Continuing."); throw error; }).then(function() { - console.log("Completed processing queue. Marking " + duplicates.length + " duplicates."); + setStatus("Completed processing queue. Marking " + duplicates.length + " duplicates."); let dups = []; duplicates.forEach(function(asset) { /* If not already marked as a duplicate, mark it. */ @@ -412,7 +412,7 @@ function processBlock(items) { } }); }).then(function() { - console.log("Looking for removed assets"); + setStatus("Looking for removed assets"); return photoDB.sequelize.query("SELECT photos.scanned,photos.id,photos.filename,albums.path FROM photos " + "LEFT JOIN albums ON (albums.id=photos.albumId) " + "WHERE photos.deleted=0 AND DATETIME(photos.scanned) lastMessage) { - console.log("Albums to be created in DB: " + toProcess); + setStatus("Albums to be created in DB: " + toProcess); lastMessage = moment(); } }); }); }).then(function() { - console.log("Processed " + albums.length + " album DB entries in " + + setStatus("Processed " + albums.length + " album DB entries in " + ((Date.now() - now) / 1000) + "s"); now = Date.now(); - console.log(assets.length + " assets remaining to be verified/updated. ETA N/A"); + setStatus(assets.length + " assets remaining to be verified/updated. ETA N/A"); let processed = 0, start = Date.now(), last = 0, updateScanned = [], newEntries = 0; return photoDB.sequelize.transaction(function(transaction) { @@ -721,7 +744,7 @@ function doScan() { } let remaining = assets.length - processed, eta = Math.ceil((elapsed / 1000) * remaining / (processed - last)); - console.log(remaining + " assets remaining be verified/updated " + + setStatus(remaining + " assets remaining be verified/updated " + "(" + newEntries + " new entries, " + (processed - newEntries) + " up-to-date so far). ETA " + eta + "s"); last = processed; start = Date.now(); @@ -736,23 +759,23 @@ function doScan() { ids: updateScanned } }).then(function() { - console.log("Updated scan date of " + updateScanned.length + " assets"); + setStatus("Updated scan date of " + updateScanned.length + " assets"); updateScanned = []; }); } }).then(function() { - console.log(newEntries + " assets are new. " + (needsProcessing.length - newEntries) + " assets have been modified."); - console.log(needsProcessing.length + " assets need HASH computed. " + (assets.length - needsProcessing.length) + " need no update.");; + setStatus(newEntries + " assets are new. " + (needsProcessing.length - newEntries) + " assets have been modified.\n" + + needsProcessing.length + " assets need HASH computed. " + (assets.length - needsProcessing.length) + " need no update.");; processBlock(needsProcessing); needsProcessing = []; }).then(function() { - console.log("Scanned " + assets.length + " asset DB entries in " + + setStatus("Scanned " + assets.length + " asset DB entries in " + ((Date.now() - now) / 1000) + "s"); assets = []; }); }); }).then(function() { - console.log("Total time to initialize DB and all scans: " + ((Date.now() - initialized) / 1000) + "s"); + setStatus("Total time to initialize DB and all scans: " + ((Date.now() - initialized) / 1000) + "s"); return photoDB.sequelize.query("SELECT max(scanned) AS scanned FROM photos", { type: photoDB.sequelize.QueryTypes.SELECT }).then(function(results) { @@ -761,11 +784,14 @@ function doScan() { } else { lastScan = new Date(results[0].scanned); } - console.log("Updating any asset newer than " + moment(lastScan).format()); + setStatus("Updating any asset newer than " + moment(lastScan).format()); }); }).then(function() { - scanning = false; + setStatus("idle"); return "scan complete"; + }).catch(function(error) { + setStatus(error); + throw error; }); } @@ -773,8 +799,6 @@ module.exports = { init: function(db) { photoDB = db; }, - scan: function () { - return doScan(); - } + scan: doScan };