summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/organize/controllers/organize.php157
-rw-r--r--modules/organize/helpers/organize_task.php71
-rw-r--r--modules/organize/js/organize.js142
-rw-r--r--modules/organize/views/organize.html.php5
-rw-r--r--modules/organize/views/organize_button_pane.html.php11
5 files changed, 219 insertions, 167 deletions
diff --git a/modules/organize/controllers/organize.php b/modules/organize/controllers/organize.php
index 62a23444..a46b3a02 100644
--- a/modules/organize/controllers/organize.php
+++ b/modules/organize/controllers/organize.php
@@ -84,6 +84,35 @@ class Organize_Controller extends Controller {
return $v->__toString();
}
+ function startTask($operation, $id) {
+ access::verify_csrf();
+ $items = $this->input->post("item");
+
+ $item = ORM::factory("item", $id);
+
+ $definition = $this->_getOperationDefinition($item, $operation);
+
+ $task_def = Task_Definition::factory()
+ ->callback("organize_task::run")
+ ->description($definition["description"])
+ ->name($definition["name"]);
+ $task = task::create($task_def, array("items" => $items, "position" => 0, "target" => $id,
+ "type" => $definition["type"],
+ "batch" => ceil(count($items) * .1)));
+ // @todo If there is only one item then call task_run($task->id); Maybe even change js so
+ // we can call finish as well.
+ batch::start();
+ print json_encode(array("result" => "started",
+ "runningMsg" => $definition["runningMsg"],
+ "pauseMsg" => "<div class=\"gWarning\">{$definition['pauseMsg']}</div>",
+ "resumeMsg" => "<div class=\"gWarning\">{$definition['resumeMsg']}</div>",
+ "task" => array("id" => $task->id,
+ "percent_complete" => $task->percent_complete,
+ "type" => $task->get("type"),
+ "status" => $task->status,
+ "state" => $task->state,
+ "done" => $task->done)));
+ }
function runTask($task_id) {
access::verify_csrf();
@@ -91,12 +120,13 @@ class Organize_Controller extends Controller {
$task = task::run($task_id);
print json_encode(array("result" => $task->done ? $task->state : "in_progress",
- "task" => array(
- "id" => $task->id,
- "percent_complete" => $task->percent_complete,
- "status" => $task->status,
- "state" => $task->state,
- "done" => $task->done)));
+ "task" => array("id" => $task->id,
+ "percent_complete" => $task->percent_complete,
+ "type" => $task->get("type"),
+ "reload" => $task->get("refresh"),
+ "status" => $task->status,
+ "state" => $task->state,
+ "done" => $task->done)));
}
function finishTask($task_id) {
@@ -107,9 +137,11 @@ class Organize_Controller extends Controller {
if ($task->done) {
$item = ORM::factory("item", (int)$task->get("target"));
$type = $task->get("type");
- if ($type == "moveTo") {
+ switch ($type) {
+ case "move":
$task->status = t("Move to '%album' completed", array("album" => $item->title));
- } else if ($type == "rearrange") {
+ break;
+ case "rearrange":
try {
$item->sort_column = "weight";
$item->save();
@@ -118,6 +150,11 @@ class Organize_Controller extends Controller {
$task->state = "error";
$task->status = $e->getMessage();
}
+ break;
+ case "rotateCcw":
+ case "rotateCw":
+ $task->status = t("Rotation completed");
+ break;
}
$task->save();
}
@@ -141,10 +178,16 @@ class Organize_Controller extends Controller {
$task->done = 1;
$task->state = "cancelled";
$type = $task->get("type");
- if ($type == "moveTo") {
+ switch ($type) {
+ case "move":
$task->status = t("Move to album was cancelled prior to completion");
- } else if ($type == "rearrange") {
- $task->status = t("Rearrange album was cancelled prior to completion");
+ break;
+ case "rearrange":
+ $task->status = t("Rearrange album was cancelled prior to completion");
+ case "rotateCcw":
+ case "rotateCw":
+ $task->status = t("Rotation was cancelled prior to completion");
+ break;
}
$task->save();
}
@@ -159,51 +202,51 @@ class Organize_Controller extends Controller {
"done" => $task->done)));
}
- function moveStart($id) {
- access::verify_csrf();
- $items = $this->input->post("item");
-
- $item = ORM::factory("item", $id);
-
- $task_def = Task_Definition::factory()
- ->callback("organize_task::move")
- ->description(t("Move albums and photos to '%name'", array("name" => $item->title)))
- ->name(t("Move to '%name'", array("name" => $item->title)));
- $task = task::create($task_def, array("items" => $items, "position" => 0, "target" => $id,
- "type" => "moveTo",
- "batch" => ceil(count($items) * .1)));
-
- batch::start();
- print json_encode(array("result" => "started",
- "task" => array(
- "id" => $task->id,
- "percent_complete" => $task->percent_complete,
- "status" => $task->status,
- "state" => $task->state,
- "done" => $task->done)));
- }
-
- function rearrangeStart($id) {
- access::verify_csrf();
- $items = $this->input->post("item");
-
- $item = ORM::factory("item", $id);
-
- $task_def = Task_Definition::factory()
- ->callback("organize_task::rearrange")
- ->description(t("Rearrange the order of albums and photos"))
- ->name(t("Rearrange: %name", array("name" => $item->title)));
- $task = task::create($task_def, array("items" => $items, "position" => 0, "target" => $id,
- "type" => "rearrange",
- "batch" => ceil(count($items) * .1)));
-
- batch::start();
- print json_encode(array("result" => "started",
- "task" => array(
- "id" => $task->id,
- "percent_complete" => $task->percent_complete,
- "status" => $task->status,
- "state" => $task->state,
- "done" => $task->done)));
+ private function _getOperationDefinition($item, $operation) {
+ switch ($operation) {
+ case "move":
+ return array("description" =>
+ t("Move albums and photos to '%name'", array("name" => $item->title)),
+ "name" => t("Move to '%name'", array("name" => $item->title)),
+ "type" => "move",
+ "runningMsg" => t("Move in progress"),
+ "pauseMsg" => t("The move operation was paused"),
+ "resumeMsg" => t("The move operation was resumed"));
+ break;
+ case "rearrange":
+ return array("description" => t("Rearrange the order of albums and photos"),
+ "name" => t("Rearrange: %name", array("name" => $item->title)),
+ "type" => "rearrange",
+ "runningMsg" => t("Rearrange in progress"),
+ "pauseMsg" => t("The rearrange operation was paused"),
+ "resumeMsg" => t("The rearrange operation was resumed"));
+ break;
+ case "rotateCcw":
+ return array("description" => t("Rotate the selected photos counter clockwise"),
+ "name" => t("Rotate images in %name", array("name" => $item->title)),
+ "type" => "rotateCcw",
+ "runningMsg" => t("Rotate Counter Clockwise in progress"),
+ "pauseMsg" => t("The rotate operation was paused"),
+ "resumeMsg" => t("The rotate operation was resumed"));
+ break;
+ case "rotateCw":
+ return array("description" => t("Rotate the selected photos clockwise"),
+ "name" => t("Rotate images in %name", array("name" => $item->title)),
+ "type" => "rotateCw",
+ "runningMsg" => t("Rotate Clockwise in progress"),
+ "pauseMsg" => t("The rotate operation was paused"),
+ "resumeMsg" => t("The rotate operation was resumed"));
+ break;
+ case "delete":
+ return array("description" => t("Delete selected photos and albums"),
+ "name" => t("`Delete images in %name", array("name" => $item->title)),
+ "type" => "delete",
+ "runningMsg" => t("Delete images in progress"),
+ "pauseMsg" => t("The delete operation was paused"),
+ "resumeMsg" => t("The delete operation was resumed"));
+ break;
+ default:
+ throw new Exception("Operation '$operation' is not implmented");
+ }
}
} \ No newline at end of file
diff --git a/modules/organize/helpers/organize_task.php b/modules/organize/helpers/organize_task.php
index bb6321fa..1344796a 100644
--- a/modules/organize/helpers/organize_task.php
+++ b/modules/organize/helpers/organize_task.php
@@ -23,17 +23,37 @@ class organize_task_Core {
return array();
}
- static function rearrange($task) {
+ static function run($task) {
$context = unserialize($task->context);
+ $taskType = $context["type"];
try {
+ $target = ORM::factory("item", $context["target"]);
$total = count($context["items"]);
$stop = min($total - $context["position"], $context["batch"]);
+ $context["refresh"] = null;
for ($offset = 0; $offset < $stop; $offset++) {
$current_id = $context["position"] + $offset;
$id = $context["items"][$current_id];
- Database::instance()
- ->query("Update {items} set weight = {$context["position"]} where id=$id;");
+ switch ($taskType) {
+ case "move":
+ $source = ORM::factory("item", $id);
+ core::move_item($source, $target);
+ break;
+ case "rearrange":
+ Database::instance()
+ ->query("Update {items} set weight = {$context["position"]} where id=$id;");
+ break;
+ case "rotateCcw":
+ case "rotateCw":
+ $item = ORM::factory("item", $id);
+ if ($item->is_photo()) {
+ $context["refresh"] = self:: _do_rotation($item, $taskType == "rotateCcw" ? -90 : 90);
+ }
+ break;
+ default:
+ throw new Exception("Task '$taskType' is not implmented");
+ }
}
$context["position"] += $stop;
$task->state = "success";
@@ -49,29 +69,30 @@ class organize_task_Core {
$task->done = $context["position"] == $total || $task->state == "error";
}
- static function move($task) {
- $context = unserialize($task->context);
+ private static function _do_rotation($item, $degrees) {
+ // This code is copied from Quick_Controller::rotate
+ graphics::rotate($item->file_path(), $item->file_path(), array("degrees" => $degrees));
- try {
- $target = ORM::factory("item", $context["target"]);
- $total = count($context["items"]);
- $stop = min($total - $context["position"], $context["batch"]);
- for ($offset = 0; $offset < $stop; $offset++) {
- $current_id = $context["position"] + $offset;
- $source = ORM::factory("item", $context["items"][$current_id]);
- core::move_item($source, $target);
- }
- $context["position"] += $stop;
- $task->state = "success";
- } catch(Exception $e) {
- $task->status = $e->getMessage();
- $task->state = "error";
- $task->save();
- throw $e;
+ list($item->width, $item->height) = getimagesize($item->file_path());
+ $item->resize_dirty= 1;
+ $item->thumb_dirty= 1;
+ $item->save();
+
+ graphics::generate($item);
+
+ $parent = $item->parent();
+ if ($parent->album_cover_item_id == $item->id) {
+ copy($item->thumb_path(), $parent->thumb_path());
+ $parent->thumb_width = $item->thumb_width;
+ $parent->thumb_height = $item->thumb_height;
+ $parent->save();
}
- $task->context = serialize($context);
- $total = count($context["items"]);
- $task->percent_complete = $context["position"] / (float)$total * 100;
- $task->done = $context["position"] == $total || $task->state == "error";
+ list ($height, $width) = $item->adjust_thumb_size(90);
+ $margin_top = (90 - $height) / 20;
+
+ return array("src" => $item->thumb_url() . "?rnd=" . rand(),
+ "id" => $item->id, "marginTop" => "{$margin_top}em",
+ "width" => $width, "height" => $height);
+
}
} \ No newline at end of file
diff --git a/modules/organize/js/organize.js b/modules/organize/js/organize.js
index 66ca0b33..e11c32c4 100644
--- a/modules/organize/js/organize.js
+++ b/modules/organize/js/organize.js
@@ -17,7 +17,6 @@ var draggable = {
revert: true,
zindex: 2000,
helper: function(event, ui) {
- console.dir(ui);
$("#gMicroThumbPanel").append("<div id=\"gDragHelper\"><ul></ul></div>");
var beginTop = event.pageY;
var beginLeft = event.pageX;
@@ -95,9 +94,9 @@ var thumbDroppable = {
$.ajax({
data: newOrder,
dataType: "json",
- success: startRearrangeCallback,
+ success: operationCallback,
type: "POST",
- url: get_url("organize/rearrangeStart", {item_id: item_id})
+ url: get_url("organize/startTask/rearrange", {item_id: item_id})
});
}
};
@@ -109,16 +108,15 @@ var treeDroppable = {
hoverClass: "gBranchDroppable",
drop: function(event, ui) {
$("#gDragHelper").hide();
- var moveItems = "";
var targetItemId = $(this).attr("ref");
if ($(this).hasClass("gBranchSelected")) {
$("#gOrganizeStatus").empty().append(INVALID_DROP_TARGET);
ui.draggable.trigger("stop", event);
return false;
}
+ var postData = serializeItemIds("#gDragHelper li");
var okToMove = true;
$("#gDragHelper li").each(function(i) {
- moveItems += "&item[]=" + $(this).attr("ref");
okToMove &= targetItemId != $(this).attr("ref");
});
if (!okToMove) {
@@ -130,35 +128,26 @@ var treeDroppable = {
$("#thumb_" + $(this).attr("ref")).remove();
});
$.ajax({
- data: moveItems,
+ data: postData,
dataType: "json",
- success: startMoveCallback,
+ success: operationCallback,
type: "POST",
- url: get_url("organize/moveStart", {item_id: targetItemId})
+ url: get_url("organize/startTask/move", {item_id: targetItemId})
});
}
};
// Selectable
var selectable = {
- count: 0,
filter: ".gMicroThumbContainer",
selected: function(event, ui) {
- /*
- * Count the number of selected items if it is greater than 1,
- * then click won't be called so we need to remove the gSelecting
- * class in the stop event.
- */
- var count = $("#gMicroThumbGrid").selectable("option", "count") + 1;
- $("#gMicroThumbGrid").selectable("option", "count", count);
$(ui.selected).addClass("gSelecting");
+ setDrawerButtonState();
+ },
+ unselected: function(event, ui) {
+ setDrawerButtonState();
},
stop: function(event) {
- var count = $("#gMicroThumbGrid").selectable("option", "count");
- if (count > 1) {
- $(".gMicroThumbContainer.gSelecting").removeClass("gSelecting");
- }
- $("#gMicroThumbGrid").selectable("option", "count", 0);
}
};
@@ -166,11 +155,12 @@ var selectable = {
// Event Handlers
// MicroThumbContainer click
var onMicroThumbContainerClick = function(event) {
- if ($(this).hasClass("gSelecting")) {
- $(this).removeClass("gSelecting");
- } else {
+ if (!$(this).hasClass("gSelecting") && $(this).hasClass("ui-selected")) {
$(this).removeClass("ui-selected");
}
+ $(this).removeClass("gSelecting");
+
+ setDrawerButtonState();
};
// MicroThumbContainer mousemove
@@ -216,7 +206,15 @@ function drawerHandleButtonsClick(event) {
$("#gDialog").dialog("close");
break;
default:
- console.log(operation);
+ var postData = serializeItemIds("#gMicroThumbPanel li.ui-selected");
+ $.ajax({
+ data: postData,
+ dataType: "json",
+ success: operationCallback,
+ type: "POST",
+ url: get_url("organize/startTask/" + operation, {item_id: item_id})
+ });
+ break;
}
}
};
@@ -234,64 +232,29 @@ var getMicroThumbsCallback = function(json, textStatus) {
}
};
-// @todo see if we can combine the next two callbacks into an object
-// as they are basically the same.
-var startMoveCallback = function (data, textStatus) {
- if (!paused) {
- createProgressDialog(OPERATION_RUNNING);
- task = data.task;
- task.pauseMsg = MOVE_PAUSED;
- task.resumeMSg = MOVE_RESUMED;
- }
- $(".gMicroThumbContainer").draggable("disable");
+var operationCallback = function (data, textStatus) {
var done = false;
- paused = false;
- while (!done && !paused) {
- $.ajax({async: false,
- success: function(data, textStatus) {
- $(".gProgressBar").progressbar("value", data.task.percent_complete);
- done = data.task.done;
- },
- error: function(XMLHttpRequest, textStatus, errorThrown) {
- paused = true;
- displayAjaxError(XMLHttpRequest.responseText);
- },
- dataType: "json",
- type: "POST",
- url: get_url("organize/runTask", {task_id: task.id})
- });
- }
- if (!paused) {
- $("#gOrganizeProgressDialog").dialog("destroy").remove();
- $.ajax({async: false,
- success: function(data, textStatus) {
- task = null;
- transitItems = [];
- $("#gOrganizeStatus").empty().append("<div class='gSuccess'>" + data.task.status + "</div>");
- },
- dataType: "json",
- type: "POST",
- url: get_url("organize/finishTask", {task_id: task.id})
- });
- }
- $(".gMicroThumbContainer").draggable("enable");
-};
-
-var startRearrangeCallback = function (data, textStatus) {
if (!paused) {
- createProgressDialog(OPERATION_RUNNING);
+ createProgressDialog(data.runningMsg);
task = data.task;
- task.pauseMsg = REARRANGE_PAUSED;
- task.resumeMsg = REARRANGE_RESUMED;
+ task.pauseMsg = data.pauseMsg;
+ task.resumeMsg = data.resumeMsg;
+ done = data.task.done;
}
$(".gMicroThumbContainer").draggable("disable");
- var done = false;
paused = false;
while (!done && !paused) {
$.ajax({async: false,
success: function(data, textStatus) {
$(".gProgressBar").progressbar("value", data.task.percent_complete);
- done = data.task.done;
+ done = data.task.done;
+ if (data.task.reload) {
+ var selector = "#gMicroThumb-" + data.task.reload.id + " img";
+ $(selector).attr("height", data.task.reload.height);
+ $(selector).attr("width", data.task.reload.width);
+ $(selector).attr("src", data.task.reload.src);
+ $(selector).css("margin-top", data.task.reload.marginTop);
+ }
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
paused = true;
@@ -306,6 +269,7 @@ var startRearrangeCallback = function (data, textStatus) {
$("#gOrganizeProgressDialog").dialog("destroy").remove();
$.ajax({async: false,
success: function(data, textStatus) {
+ setDrawerButtonState();
task = null;
$("#gOrganizeStatus").empty().append("<div class='gSuccess'>" + data.task.status + "</div>");
},
@@ -413,6 +377,35 @@ function get_url(uri, parms) {
return url;
}
+/**
+ * Set the enabled/disabled state of the buttons. The album cover is only enabled if
+ * there is only 1 image selected
+ */
+function setDrawerButtonState() {
+ switch ($("#gMicroThumbGrid li.ui-selected").length) {
+ case 0:
+ $("#gOrganizeEditHandleButtonsLeft a").attr("disabled", true);
+ $("#gOrganizeEditHandleButtonsLeft a").addClass("ui-state-disabled");
+ break;
+ case 1:
+ $("#gOrganizeEditHandleButtonsLeft a").removeAttr("disabled");
+ $("#gOrganizeEditHandleButtonsLeft a").removeClass("ui-state-disabled");
+ break;
+ default:
+ $("#gOrganizeEditHandleButtonsLeft a[ref='albumCover']").attr("disabled", true);
+ $("#gOrganizeEditHandleButtonsLeft a[ref='albumCover']").addClass("ui-state-disabled");
+ }
+}
+
+function serializeItemIds(selector) {
+ var postData = "";
+ $(selector).each(function(i) {
+ postData += "&item[]=" + $(this).attr("ref");
+ });
+
+ return postData;
+}
+
function createProgressDialog(title) {
$("body").append("<div id='gOrganizeProgressDialog'>" +
"<div class='gProgressBar'></div>" +
@@ -441,7 +434,8 @@ function createProgressDialog(title) {
$("#gOrganizeTaskResume").hide();
$("#gOrganizeTaskCancel").hide();
$("#gOrganizeStatus").empty().append(task.resumeMsg);
- startRearrangeCallback();
+ operationCallback();
+ //startRearrangeCallback();
});
$("#gOrganizeTaskCancel").click(function(event) {
$("#gOrganizeTaskPause").show();
diff --git a/modules/organize/views/organize.html.php b/modules/organize/views/organize.html.php
index c423f5a1..1b4a130a 100644
--- a/modules/organize/views/organize.html.php
+++ b/modules/organize/views/organize.html.php
@@ -5,12 +5,7 @@
var PAUSE_BUTTON = "<?= t("Pause") ?>";
var RESUME_BUTTON = "<?= t("Resume") ?>";
var CANCEL_BUTTON = "<?= t("Cancel") ?>";
- var OPERATION_RUNNING = "<?= t("Operation in Progress") ?>";
var INVALID_DROP_TARGET = "<div class=\"gError\"><?= t("Drop cancelled as it would result in a recursive move") ?></div>";
- var MOVE_PAUSED = "<div class=\"gWarning\"><?= t("The move operation was paused") ?></div>";
- var MOVE_RESUMED = "<div class=\"gWarning\"><?= t("The move operation was resumed") ?></div>";
- var REARRANGE_PAUSED = "<div class=\"gWarning\"><?= t("The rearrange operation was paused") ?></div>";
- var REARRANGE_RESUMED = "<div class=\"gWarning\"><?= t("The rearrange operation was resumed") ?></div>";
var item_id = <?= $item->id ?>;
diff --git a/modules/organize/views/organize_button_pane.html.php b/modules/organize/views/organize_button_pane.html.php
index a39c643c..9902eafb 100644
--- a/modules/organize/views/organize_button_pane.html.php
+++ b/modules/organize/views/organize_button_pane.html.php
@@ -1,7 +1,6 @@
<?php defined("SYSPATH") or die("No direct script access.") ?>
-
-<a class="gButtonLink ui-corner-all ui-state-default" href="#" ref="edit"
+<a class="gButtonLink ui-corner-all ui-state-default ui-state-disabled" href="#" ref="edit"
disabled="1" title="<?= t("Edit Selection") ?>">
<span class="ui-icon ui-icon-pencil">
<?= t("Edit Selection") ?>
@@ -9,14 +8,14 @@
</a>
<? if (graphics::can("rotate")): ?>
-<a class="gButtonLink ui-corner-all ui-state-default" href="#" ref="rotate_ccw"
+<a class="gButtonLink ui-corner-all ui-state-default ui-state-disabled" href="#" ref="rotateCcw"
disabled="1" title="<?= t("Rotate 90 degrees counter clockwise") ?>">
<span class="ui-icon ui-icon-rotate-ccw">
<?= t("Rotate 90 degrees counter clockwise") ?>
</span>
</a>
-<a class="gButtonLink ui-corner-all ui-state-default" href="#" ref="rotate_cw"
+<a class="gButtonLink ui-corner-all ui-state-default ui-state-disabled" href="#" ref="rotateCw"
disabled="1" title="<?= t("Rotate 90 degrees clockwise") ?>">
<span class="ui-icon ui-icon-rotate-cw">
<?= t("Rotate 90 degrees clockwise") ?>
@@ -24,14 +23,14 @@
</a>
<? endif ?>
-<a class="gButtonLink ui-corner-all ui-state-default" href="#" ref="album_cover"
+<a class="gButtonLink ui-corner-all ui-state-default ui-state-disabled" href="#" ref="albumCover"
disabled="1" title="<?= t("Choose this photo as the album cover") ?>">
<span class="ui-icon ui-icon-star">
<?= t("Choose this photo as the album cover") ?>
</span>
</a>
-<a class="gButtonLink ui-corner-all ui-state-default" href="#" ref="delete"
+<a class="gButtonLink ui-corner-all ui-state-default ui-state-disabled" href="#" ref="delete"
disabled="1" title="<?= t("Delete selection") ?>">
<span class="ui-icon ui-icon-trash">
<?= t("Delete selection") ?>