Rotation now works
Signed-off-by: James Ketrenos <james_git@ketrenos.com>
This commit is contained in:
parent
82e5875e52
commit
2f6f0ccfa5
@ -81,6 +81,10 @@
|
||||
Polymer({
|
||||
is: "photo-thumbnail",
|
||||
properties: {
|
||||
"unique": {
|
||||
type: String,
|
||||
value: ""
|
||||
},
|
||||
"disabled": {
|
||||
reflectToAttribute: true
|
||||
},
|
||||
@ -89,7 +93,7 @@
|
||||
},
|
||||
"thumbpath": {
|
||||
type: String,
|
||||
computed: "safeItemThumbFilepath(item, base)"
|
||||
computed: "safeItemThumbFilepath(item, base, unique)"
|
||||
},
|
||||
"width": {
|
||||
type: Number
|
||||
@ -130,11 +134,11 @@
|
||||
this.style.height = width + "px";
|
||||
},
|
||||
|
||||
safeItemThumbFilepath: function(item, base) {
|
||||
safeItemThumbFilepath: function(item, base, unique) {
|
||||
if (item === undefined|| base === undefined || item.path === undefined) {
|
||||
return "";
|
||||
}
|
||||
return base + item.path + "thumbs/" + item.filename;
|
||||
return base + item.path + "thumbs/" + item.filename + (this.unique ? ("?" + this.unique) : "");
|
||||
},
|
||||
|
||||
date: function(item) {
|
||||
@ -154,6 +158,10 @@
|
||||
event.preventDefault();
|
||||
},
|
||||
|
||||
reload: function() {
|
||||
this.unique = parseInt(this.unique || 0) + 1;
|
||||
},
|
||||
|
||||
attached: function() {
|
||||
var base = document.querySelector("base");
|
||||
if (base) {
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
<link rel="import" href="../../bower_components/iron-icon/iron-icon.html">
|
||||
<link rel="import" href="../../bower_components/iron-icons/iron-icons.html">
|
||||
<link rel="import" href="../../bower_components/iron-icons/image-icons.html">
|
||||
<link rel="import" href="../../bower_components/iron-iconset/iron-iconset.html">
|
||||
<link rel="import" href="../../bower_components/iron-pages/iron-pages.html">
|
||||
<link rel="import" href="../../bower_components/iron-resizable-behavior/iron-resizable-behavior.html">
|
||||
@ -1221,9 +1222,11 @@
|
||||
let actions = [ "delete" ];
|
||||
if (this.mode == "duplicates") {
|
||||
actions.unshift("text-format");
|
||||
}
|
||||
if (this.mode == "trash") {
|
||||
} else if (this.mode == "trash") {
|
||||
actions.unshift("undo");
|
||||
} else {
|
||||
actions.unshift("image:rotate-right");
|
||||
actions.unshift("image:rotate-left");
|
||||
}
|
||||
thumbnail.actions = actions;
|
||||
thumbnail.addEventListener("action", this._imageAction.bind(this));
|
||||
@ -1293,49 +1296,65 @@
|
||||
}.bind(this, thumbnail), 250);
|
||||
},
|
||||
|
||||
_imageAction: function(event) {
|
||||
switch (event.detail) {
|
||||
case "undo": /* Undelete an image */
|
||||
var thumbnail = event.currentTarget, params = {};
|
||||
undoAction: function(thumbnail) {
|
||||
var params = {};
|
||||
thumbnail.disabled = true;
|
||||
|
||||
params.undelete = 1;
|
||||
|
||||
var query = "";
|
||||
for (var key in params) {
|
||||
if (!query) {
|
||||
query = "?";
|
||||
} else {
|
||||
query += "&";
|
||||
}
|
||||
query += encodeURIComponent(key) + "=" + encodeURIComponent(params[key]);
|
||||
}
|
||||
window.fetch("api/v1/photos/" + thumbnail.item.id + query,
|
||||
window.fetch("api/v1/photos/" + thumbnail.item.id + "?a=undelete",
|
||||
this._removeImageAfterFetch.bind(this, thumbnail), {}, "PUT");
|
||||
break;
|
||||
},
|
||||
|
||||
case "delete": /* Delete image */
|
||||
deleteAction: function(photo) {
|
||||
var thumbnail = event.currentTarget, params = {};
|
||||
thumbnail.disabled = true;
|
||||
var query = "";
|
||||
if (this.mode == "trash") {
|
||||
console.log("TODO: Prompt user 'Are you sure?' ?");
|
||||
params.permanent = 1;
|
||||
}
|
||||
|
||||
var query = "";
|
||||
for (var key in params) {
|
||||
if (!query) {
|
||||
query = "?";
|
||||
} else {
|
||||
query += "&";
|
||||
}
|
||||
query += encodeURIComponent(key) + "=" + encodeURIComponent(params[key]);
|
||||
query += "?permanent=1";
|
||||
}
|
||||
window.fetch("api/v1/photos/" + thumbnail.item.id + query,
|
||||
this._removeImageAfterFetch.bind(this, thumbnail), {}, "DELETE");
|
||||
},
|
||||
|
||||
renameAction: function(thumbnail) {
|
||||
return;
|
||||
},
|
||||
|
||||
rotateAction: function(thumbnail, direction) {
|
||||
thumbnail.disabled = true;
|
||||
window.fetch("api/v1/photos/" + thumbnail.item.id + "?a=rotate&direction=" + direction,
|
||||
function(thumbnail, error, xhr) {
|
||||
|
||||
thumbnail.disabled = false;
|
||||
|
||||
if (error) {
|
||||
console.log("Unable to take action on photo: " + error);
|
||||
return;
|
||||
}
|
||||
|
||||
thumbnail.reload();
|
||||
}.bind(this, thumbnail), {}, "PUT");
|
||||
},
|
||||
|
||||
_imageAction: function(event) {
|
||||
switch (event.detail) {
|
||||
case "undo": /* Undelete an image */
|
||||
this.undoAction(event.currentTarget);
|
||||
break;
|
||||
|
||||
case "delete": /* Delete image */
|
||||
this.deleteAction(event.currentTarget);
|
||||
break;
|
||||
|
||||
case "image:rotate-left":
|
||||
this.rotateAction(event.currentTarget, "left");
|
||||
break;
|
||||
|
||||
case "image:rotate-right":
|
||||
this.rotateAction(event.currentTarget, "right");
|
||||
break;
|
||||
|
||||
case "text-format": /* Rename this image */
|
||||
this.renameAction(event.currentTarget);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
@ -32,39 +32,144 @@ const unlink = function (_path) {
|
||||
});
|
||||
}
|
||||
|
||||
const rename = function (_src, _dst) {
|
||||
if (_src.indexOf(picturesPath.replace(/\/$/, "")) == 0) {
|
||||
_src = _src.substring(picturesPath.length);
|
||||
}
|
||||
if (_dst.indexOf(picturesPath.replace(/\/$/, "")) == 0) {
|
||||
_dst = _dst.substring(picturesPath.length);
|
||||
}
|
||||
|
||||
let src = picturesPath + _src,
|
||||
dst = picturesPath + _dst;
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
fs.rename(src, dst, function (error, stats) {
|
||||
if (error) {
|
||||
return reject(error);
|
||||
}
|
||||
return resolve(stats);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
const stat = function (_path) {
|
||||
if (_path.indexOf(picturesPath.replace(/\/$/, "")) == 0) {
|
||||
_path = _path.substring(picturesPath.length);
|
||||
}
|
||||
|
||||
let path = picturesPath + _path;
|
||||
|
||||
return new Promise(function (resolve, reject) {
|
||||
fs.stat(path, function (error, stats) {
|
||||
if (error) {
|
||||
return reject(error);
|
||||
}
|
||||
return resolve(stats);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const sharp = require("sharp"), exif = require("exif-reader");
|
||||
|
||||
router.put("/:id", function(req, res/*, next*/) {
|
||||
if (!req.user.maintainer) {
|
||||
return res.status(401).send("Unauthorized to delete photos.");
|
||||
return res.status(401).send("Unauthorized to modify photos.");
|
||||
}
|
||||
|
||||
const replacements = {
|
||||
id: req.params.id
|
||||
};
|
||||
|
||||
let query = "";
|
||||
|
||||
console.log("PUT /" + replacements.id, req.query);
|
||||
for (let key in req.query) {
|
||||
switch (key) {
|
||||
switch (req.query.a) {
|
||||
case "undelete":
|
||||
console.log("Undeleting " + req.params.id);
|
||||
query = "UPDATE photos SET deleted=0 WHERE id=:id";
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!query) {
|
||||
return res.status(400).send("Invalid request");
|
||||
}
|
||||
|
||||
return photoDB.sequelize.query(query, {
|
||||
return photoDB.sequelize.query("UPDATE photos SET deleted=0 WHERE id=:id", {
|
||||
replacements: replacements
|
||||
}).then(function() {
|
||||
return res.status(200).send(req.params.id + " updated.");
|
||||
});
|
||||
|
||||
case "rotate":
|
||||
let direction = req.query.direction || "right";
|
||||
if (direction == "right") {
|
||||
direction = 90;
|
||||
} else {
|
||||
direction = -90;
|
||||
}
|
||||
return getPhoto(req.params.id).then(function(asset) {
|
||||
if (!asset) {
|
||||
return res.status(404).send(req.params.id + " not found.");
|
||||
}
|
||||
|
||||
let original = picturesPath + asset.path + asset.filename,
|
||||
target = picturesPath + asset.path + ".tmp." + asset.filename,
|
||||
thumb = picturesPath + asset.path + "thumbs/" + asset.filename,
|
||||
scaled = picturesPath + asset.path + "thumbs/scaled/" + asset.filename;
|
||||
|
||||
let tmp = asset.width;
|
||||
asset.width = asset.height;
|
||||
asset.height = tmp;
|
||||
|
||||
asset.image = sharp(original);
|
||||
return asset.image.rotate(direction).withMetadata().toFile(target).then(function() {
|
||||
/*...*/
|
||||
}).then(function() {
|
||||
return asset.image.rotate(direction).resize(256, 256).withMetadata().toFile(thumb);
|
||||
}).then(function() {
|
||||
return asset.image.resize(Math.min(1024, asset.width)).withMetadata().toFile(scaled);
|
||||
}).then(function() {
|
||||
return stat(target).then(function(stats) {
|
||||
if (!stats) {
|
||||
throw "Unable to find original file after attempting to rotate!";
|
||||
}
|
||||
asset.size = stats.size;
|
||||
return photoDB.sequelize.query("UPDATE photos SET " +
|
||||
"modified=CURRENT_TIMESTAMP,width=:width,height=:height,size=:size,scanned=CURRENT_TIMESTAMP " +
|
||||
"WHERE id=:id", {
|
||||
replacements: asset
|
||||
}).then(function() {
|
||||
return unlink(original).then(function() {
|
||||
return rename(target, original);
|
||||
});
|
||||
});
|
||||
});
|
||||
}).then(function() {
|
||||
sharp.cache(false);
|
||||
sharp.cache(true);
|
||||
return res.status(200).send(asset);
|
||||
});
|
||||
}).catch(function(error) {
|
||||
console.log(error);
|
||||
return res.status(500).send(error);
|
||||
});
|
||||
}
|
||||
|
||||
return res.status(400).send("Invalid request");
|
||||
});
|
||||
|
||||
const getPhoto = function(id) {
|
||||
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", {
|
||||
replacements: {
|
||||
id: id
|
||||
},
|
||||
type: photoDB.Sequelize.QueryTypes.SELECT,
|
||||
raw: true
|
||||
}).then(function(photos) {
|
||||
if (photos.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return photos[0];
|
||||
});
|
||||
}
|
||||
|
||||
router.delete("/:id", function(req, res/*, next*/) {
|
||||
if (!req.user.maintainer) {
|
||||
return res.status(401).send("Unauthorized to delete photos.");
|
||||
|
@ -333,7 +333,7 @@ function processBlock(items) {
|
||||
return;
|
||||
}
|
||||
|
||||
return image.resize(256, 256).toFile(dst).catch(function(error) {
|
||||
return image.resize(256, 256).withMetadata().toFile(dst).catch(function(error) {
|
||||
setStatus("Error resizing image: " + dst + "\n" + error, "error");
|
||||
throw error;
|
||||
});
|
||||
@ -344,7 +344,7 @@ function processBlock(items) {
|
||||
return;
|
||||
}
|
||||
|
||||
return image.resize(Math.min(1024, metadata.width)).toFile(dst).catch(function(error) {
|
||||
return image.resize(Math.min(1024, metadata.width)).withMetadata().toFile(dst).catch(function(error) {
|
||||
setStatus("Error resizing image: " + dst + "\n" + error, "error");
|
||||
throw error;
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user