diff --git a/frontend/src/ketr-photos/ketr-photos.html b/frontend/src/ketr-photos/ketr-photos.html
index 8ad37e9..1092da1 100755
--- a/frontend/src/ketr-photos/ketr-photos.html
+++ b/frontend/src/ketr-photos/ketr-photos.html
@@ -335,8 +335,14 @@
Duplicate names
@@ -1421,6 +1427,22 @@
}.bind(this, thumbnail), {}, "PUT");
},
+ purgeTrashAction: function() {
+ var query = "";
+ if (this.mode == "trash") {
+ console.log("TODO: Prompt user 'Are you sure?' ?");
+ query = "?permanent=1";
+ }
+ window.fetch("api/v1/photos/" + query, function(error) {
+ if (error) {
+ console.log("Unable to take action on photo: " + error);
+ return;
+ }
+
+ this.resetPhotos();
+ }.bind(this), {}, "DELETE");
+ },
+
deleteAction: function(thumbnail) {
thumbnail.disabled = true;
var query = "";
diff --git a/server/routes/photos.js b/server/routes/photos.js
index 0e9df0b..beedec3 100755
--- a/server/routes/photos.js
+++ b/server/routes/photos.js
@@ -5,7 +5,8 @@ const express = require("express"),
config = require("config"),
moment = require("moment"),
crypto = require("crypto"),
- util = require("util");
+ util = require("util"),
+ Promise = require("bluebird");
const execFile = util.promisify(require("child_process").execFile);
@@ -314,32 +315,45 @@ const getPhoto = function(id) {
});
}
-router.delete("/:id", function(req, res/*, next*/) {
+router.delete("/:id?", function(req, res/*, next*/) {
if (!req.user.maintainer) {
return res.status(401).send("Unauthorized to delete photos.");
}
const replacements = {
- id: req.params.id
+ id: req.params.id || "*"
};
+ if (!req.params.id && !req.query.permanent) {
+ return res.status(400).send("Trash can only be emptied if permanent.");
+ }
+
+ let where = "";
+ if (req.params.id) {
+ where = "photos.id=:id";
+ if (req.query.permanent) {
+ where += " AND photos.deleted=1";
+ }
+ } else {
+ where = "photos.deleted=1";
+ }
+
console.log("DELETE /" + replacements.id, req.query);
return photoDB.sequelize.query("SELECT " +
"photos.*,albums.path AS path,photohashes.hash,(albums.path || photos.filename) AS filepath FROM photos " +
"LEFT JOIN albums ON albums.id=photos.albumId " +
"LEFT JOIN photohashes ON photohashes.photoId=photos.id " +
- "WHERE photos.id=:id", {
+ "WHERE " + where, {
replacements: replacements,
type: photoDB.Sequelize.QueryTypes.SELECT,
raw: true
}).then(function(photos) {
if (photos.length == 0) {
- res.status(404).send("Unable to find photo " + req.params.id);
+ res.status(404).send("Unable to find photo " + replacements.id);
return true;
}
- const photo = photos[0];
if (!req.query.permanent) {
return photoDB.sequelize.query("UPDATE photos SET deleted=1,updated=CURRENT_TIMESTAMP WHERE id=:id", {
replacements: replacements
@@ -348,82 +362,83 @@ router.delete("/:id", function(req, res/*, next*/) {
});
}
- /* Delete the asset from disk and the DB
- * 1. Look if there are duplicates.
- * 2. Update all other duplicates to be duplicates of the first image that remains
- * 3. If no duplicates, DELETE the entry from photohashes
- * 4. If there are duplicates, update the HASH entry to point to the first image that remains
- * 5. Delete the entry from photos
- * 6. Delete the scaled, thumb, and original from disk
- */
- return photoDB.sequelize.transaction(function(transaction) {
- return photoDB.sequelize.query("SELECT id FROM photos WHERE duplicate=:id", {
- replacements: photo,
- type: photoDB.Sequelize.QueryTypes.SELECT,
- raw: true
- }).then(function(duplicates) {
- if (!duplicates.length) {
- return null;
- }
+ /**
+ * Delete the asset from disk and the DB
+ * 1. Look if there are duplicates.
+ * 2. Update all other duplicates to be duplicates of the first image that remains
+ * 3. If no duplicates, DELETE the entry from photohashes
+ * 4. If there are duplicates, update the HASH entry to point to the first image that remains
+ * 5. Delete the entry from photos
+ * 6. Delete the scaled, thumb, and original from disk
+ */
+ return Promise.mapSeries(photos, function(photo) {
+ return photoDB.sequelize.transaction(function(transaction) {
+ return photoDB.sequelize.query("SELECT id FROM photos WHERE duplicate=:id", {
+ replacements: photo,
+ type: photoDB.Sequelize.QueryTypes.SELECT,
+ raw: true
+ }).then(function(duplicates) {
+ if (!duplicates.length) {
+ return null;
+ }
- let first = duplicates.shift();
- let needsUpdate = [];
- duplicates.forEach(function(duplicate) {
- needsUpdate.push(duplicate.id);
- });
-
- if (!needsUpdate.length) {
- return first;
- }
+ let first = duplicates.shift();
+ let needsUpdate = [];
+ duplicates.forEach(function(duplicate) {
+ needsUpdate.push(duplicate.id);
+ });
+
+ if (!needsUpdate.length) {
+ return first;
+ }
- // 2. Update all other duplicates to be duplicates of the first image that remains
- console.log("Updating " + needsUpdate + " to point to " + first.id);
- return photoDB.sequelize.query(
- "UPDATE photos SET duplicate=:first WHERE id IN (:needsUpdate)", {
- replacements: {
- first: first.id,
- needsUpdate: needsUpdate
- },
- transaction: transaction
- }).then(function() {
- return first;
- });
- }).then(function(first) {
- if (!first) {
- console.log("Deleting "+ photo.id + " from photohash.");
- // 3. If no duplicates, DELETE the entry from photohashes
+ // 2. Update all other duplicates to be duplicates of the first image that remains
+ console.log("Updating " + needsUpdate + " to point to " + first.id);
return photoDB.sequelize.query(
- "DELETE FROM photohashes WHERE photoId=:photo", {
+ "UPDATE photos SET duplicate=:first WHERE id IN (:needsUpdate)", {
replacements: {
+ first: first.id,
+ needsUpdate: needsUpdate
+ },
+ transaction: transaction
+ }).then(function() {
+ return first;
+ });
+ }).then(function(first) {
+ if (!first) {
+ console.log("Deleting "+ photo.id + " from photohash.");
+ // 3. If no duplicates, DELETE the entry from photohashes
+ return photoDB.sequelize.query(
+ "DELETE FROM photohashes WHERE photoId=:id", {
+ replacements: photo,
+ transaction: transaction
+ });
+ }
+ console.log("Updating photohash for " + photo.id + " to point to " + first.id);
+ // 4. If there are duplicates, update the HASH entry to point to the first image that remains
+ return photoDB.sequelize.query(
+ "UPDATE photohashes SET photoId=:first WHERE photoId=:photo", {
+ replacements: {
+ first: first.id,
photo: photo.id
},
transaction: transaction
});
- }
- console.log("Updating photohash for " + photo.id + " to point to " + first.id);
- // 4. If there are duplicates, update the HASH entry to point to the first image that remains
- return photoDB.sequelize.query(
- "UPDATE photohashes SET photoId=:first WHERE photoId=:photo", {
- replacements: {
- first: first.id,
- photo: photo.id
- },
- transaction: transaction
- });
- }).then(function() {
- console.log("Deleting " + photo.path + photo.filename + " from DB.");
- // 5. Delete the entry from photos
- return photoDB.sequelize.query("DELETE FROM photos WHERE id=:id", {
- replacements: replacements,
- transaction: transaction
- });
- }).then(function() {
- // 6. Delete the scaled, thumb, and original from disk
- console.log("Deleting " + photo.path + photo.filename + " from disk.");
- return unlink(photo.path + "thumbs/scaled/" + photo.filename).catch(function() {}).then(function() {
- return unlink(photo.path + "thumbs/" + photo.filename).catch(function() {}).then(function() {
- return unlink(photo.path + photo.filename).catch(function(error) {
- console.log("Error removing file: " + error);
+ }).then(function() {
+ console.log("Deleting " + photo.path + photo.filename + " from DB.");
+ // 5. Delete the entry from photos
+ return photoDB.sequelize.query("DELETE FROM photos WHERE id=:id", {
+ replacements: photo,
+ transaction: transaction
+ });
+ }).then(function() {
+ // 6. Delete the scaled, thumb, and original from disk
+ console.log("Deleting " + photo.path + photo.filename + " from disk.");
+ return unlink(photo.path + "thumbs/scaled/" + photo.filename).catch(function() {}).then(function() {
+ return unlink(photo.path + "thumbs/" + photo.filename).catch(function() {}).then(function() {
+ return unlink(photo.path + photo.filename).catch(function(error) {
+ console.log("Error removing file: " + error);
+ });
});
});
});
@@ -565,7 +580,7 @@ router.get("/trash", function(req, res/*, next*/) {
return photoDB.sequelize.query(
"SELECT photos.*,albums.path AS path,(albums.path || photos.filename) AS filepath FROM photos " +
"LEFT JOIN albums ON albums.id=photos.albumId " +
- "WHERE deleted=1 ORDER BY photos.updated", {
+ "WHERE deleted=1 ORDER BY photos.updated DESC", {
type: photoDB.Sequelize.QueryTypes.SELECT,
raw: true
}).then(function(photos) {