summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorTim Almdal <tnalmdal@shaw.ca>2009-08-16 12:36:14 -0700
committerTim Almdal <tnalmdal@shaw.ca>2009-08-16 12:36:14 -0700
commit76f320ab3d6b1f67055dd913eb5811d0d113682a (patch)
treee797e3410709068df3a947f274a010b79e6fc98a /modules
parenteeae2dc56c822a2fa32278bfe0f52bc43f665ec2 (diff)
In this patch, drag now works to the album tree, but the progress bar is not
showing. As well fixed a problem where selectable single clink no longer worked when the album was reloaded.
Diffstat (limited to 'modules')
-rw-r--r--modules/gallery/controllers/combined.php9
-rw-r--r--modules/organize/controllers/organize.php121
-rw-r--r--modules/organize/js/organize.js138
-rw-r--r--modules/organize/views/organize_dialog.html.php7
4 files changed, 208 insertions, 67 deletions
diff --git a/modules/gallery/controllers/combined.php b/modules/gallery/controllers/combined.php
index 9a790fdf..c1f42bfe 100644
--- a/modules/gallery/controllers/combined.php
+++ b/modules/gallery/controllers/combined.php
@@ -42,22 +42,23 @@ class Combined_Controller extends Controller {
private function _emit($type, $key) {
$input = Input::instance();
+ // We don't need to save the session for this request
+ Session::abort_save();
+
// Our data is immutable, so if they already have a copy then it needs no updating.
if ($input->server("HTTP_IF_MODIFIED_SINCE")) {
header('HTTP/1.0 304 Not Modified');
header("Expires: Tue, 19 Jan 2038 00:00:00 GMT");
header("Cache-Control: max-age=2678400");
header('Pragma: public');
- return;
+ Kohana::close_buffers(false);
+ return "";
}
if (empty($key)) {
Kohana::show_404();
}
- // We don't need to save the session for this request
- Session::abort_save();
-
$cache = Cache::instance();
$use_gzip = function_exists("gzencode") &&
stripos($input->server("HTTP_ACCEPT_ENCODING"), "gzip") !== false &&
diff --git a/modules/organize/controllers/organize.php b/modules/organize/controllers/organize.php
index 6f83f940..1c4a3a69 100644
--- a/modules/organize/controllers/organize.php
+++ b/modules/organize/controllers/organize.php
@@ -32,8 +32,8 @@ class Organize_Controller extends Controller {
}
$parents[$item->id] = 1;
- $v->album_tree = $this->_tree($root, $parents);
- $v->micro_thumb_grid = $this->_get_micro_thumb_grid($item, 0);
+ $v->album_tree = self::_tree($root, $parents);
+ $v->micro_thumb_grid = self::_get_micro_thumb_grid($item, 0);
print $v;
}
@@ -41,17 +41,77 @@ class Organize_Controller extends Controller {
$item = ORM::factory("item", $item_id);
access::required("view", $item);
access::required("edit", $item);
- print $this->_get_micro_thumb_grid($item, $offset);
+ print self::_get_micro_thumb_grid($item, $offset);
}
- private function _get_micro_thumb_grid($item, $offset) {
+ function move($target_id) {
+ access::verify_csrf();
+
+ $task_def = Task_Definition::factory()
+ ->callback("Organize_Controller::move_task_handler")
+ ->description(t("Move images"))
+ ->name(t("Move Images"));
+ $task = task::create($task_def, array("target_id" => $target_id,
+ "source_ids" => $this->input->post("source_ids")));
+
+ print json_encode(
+ array("result" => "started",
+ "status" => $task->status,
+ "url" => url::site("organize/run/$task->id?csrf=" . access::csrf_token())));
+ }
+
+ function rearrange($target_id, $before) {
+ access::verify_csrf();
+ $target = ORM::factory("item", $target_id);
+ $parent = $target->parent();
+ access::required("view", $parent);
+ access::required("edit", $parent);
+
+ $task_def = Task_Definition::factory()
+ ->callback("Organize_Controller::rearrange_task_handler")
+ ->description(t("Rearrange Image"))
+ ->name(t("Rearrange Images"));
+ $task = task::create($task_def, array("target_id" => $target_id, "before" => $before,
+ "current" => 0,
+ "source_ids" => $this->input->post("source_ids")));
+
+ print json_encode(
+ array("result" => "started",
+ "status" => $task->status,
+ "url" => url::site("organize/run/$task->id?csrf=" . access::csrf_token())));
+ }
+
+ private static function _get_micro_thumb_grid($item, $offset) {
$v = new View("organize_thumb_grid.html");
$v->item = $item;
$v->offset = $offset;
return $v;
}
- private function _tree($item, $parents) {
+ /**
+ * Run the task
+ */
+ function run($task_id) {
+ access::verify_csrf();
+
+ $task = ORM::factory("task", $task_id);
+ if (!$task->loaded || $task->owner_id != user::active()->id) {
+ access::forbidden();
+ }
+
+ $task = task::run($task_id);
+ $results = array("done" => $task->done, "status" => $task->status,
+ "percent_complete" => $task->percent_complete);
+ foreach (array("tree", "content") as $data) {
+ $value = $task->get($data, false);
+ if ($value !== false) {
+ $results[$data] = $value;
+ }
+ }
+ print json_encode($results);
+ }
+
+ private static function _tree($item, $parents) {
$v = new View("organize_tree.html");
$v->album = $item;
$keys = array_keys($parents);
@@ -62,7 +122,7 @@ class Organize_Controller extends Controller {
$albums = $item->children(null, 0, array("type" => "album"), array("title" => "ASC"));
foreach ($albums as $album) {
if (access::can("view", $album)) {
- $v->children[] = $this->_tree($album, $parents);
+ $v->children[] = self::_tree($album, $parents);
}
}
if (count($v->children)) {
@@ -70,4 +130,53 @@ class Organize_Controller extends Controller {
}
return $v;
}
+
+ static function move_task_handler($task) {
+ $start = microtime(true);
+ if ($task->percent_complete == 0) {
+ batch::start();
+ }
+
+ $target = ORM::factory("item", $task->get("target_id"));
+ $source_ids = $task->get("source_ids", array());
+ $idx = $task->get("current", 0);
+ $count = 0;
+ for (; $idx < count($source_ids) && microtime(true) - $start < 0.5; $idx++) {
+ item::move(ORM::factory("item", $source_ids[$idx]), $target);
+ $count++;
+ }
+ $task->set("current", $idx);
+ $task->percent_complete = ceil($idx / count($source_ids) * 100);
+ $task->status = t2("Moved one file", "Moved %count files", $count);
+ if ($task->percent_complete == 100) {
+ batch::stop();
+ $task->done = true;
+ $task->state = "success";
+ $parents = array();
+ foreach ($target->parents() as $parent) {
+ $parents[$parent->id] = 1;
+ }
+ $parents[$target->id] = 1;
+ // @TODO do we want to set a flag and then generate them in the run method so we don't
+ // potentially store large data items in the task?
+ $task->set("tree", self::_tree(ORM::factory("item", 1), $parents)->__toString());
+ $task->set("content", self::_get_micro_thumb_grid($target, 0)->__toString());
+ }
+ }
+
+ static function rearrange_task_handler($task) {
+ // @todo need to
+ // 1) reset the weights based on the current sort order
+ // 2) when they are all copied, change the sort order of the parent to "weight"
+ $task->percent_complete = 100;
+ //$start = microtime(true);
+ //$mode = $task->get("mode", "init");
+ //$start = microtime(true);
+ // if (microtime(true) - $start > 0.5) {
+ // break;
+ $task->done = true;
+ $task->state = "success";
+ $target = ORM::factory("item", $task->get("target_id"));
+ $task->set("content", self::_get_micro_thumb_grid($target, 0)->__toString());
+ }
}
diff --git a/modules/organize/js/organize.js b/modules/organize/js/organize.js
index 07c07286..2d7c99fc 100644
--- a/modules/organize/js/organize.js
+++ b/modules/organize/js/organize.js
@@ -1,32 +1,37 @@
(function($) {
$.organize = {
micro_thumb_draggable: {
+ handle: ".ui-state-selected",
distance: 10,
cursorAt: { left: -10, top: -10},
appendTo: "#gMicroThumbPanel",
helper: function(event, ui) {
- var selected = $(".ui-draggable.ui-state-selected img"),
- set = $('<div class="gDragHelper"></div>').css({zIndex: 2000, width: 80, height: Math.ceil(selected.length / 5) * 16 }),
- offset = $(this).offset(),
- click = { left: event.pageX - offset.left, top: event.pageY - offset.top };
-
- selected.each(function(i) {
- var row = parseInt(i / 5);
- var j = i - (row * 5);
-
- var o = $(this).offset();
-
- var copy = $(this).clone()
- .css({
- width: $(this).width(), height: $(this).height(), display: "block",
- margin: 0, position: 'absolute', outline: '5px solid #fff',
- left: o.left - event.pageX, top: o.top - event.pageY
- })
- .appendTo(set)
- .animate({width: 10, height: 10, outlineWidth: 1, margin: 1, left: (20 * j), top: (row * 20)}, 500);
- });
- return set;
+ var selected = $(".ui-draggable.ui-state-selected img");
+ if (selected.length) {
+ var set = $('<div class="gDragHelper"></div>').css({zIndex: 2000, width: 80, height: Math.ceil(selected.length / 5) * 16 }),
+ offset = $(this).offset(),
+ click = { left: event.pageX - offset.left, top: event.pageY - offset.top };
+
+ selected.each(function(i) {
+ var row = parseInt(i / 5);
+ var j = i - (row * 5);
+
+ var o = $(this).offset();
+
+ var copy = $(this).clone()
+ .css({
+ width: $(this).width(), height: $(this).height(), display: "block",
+ margin: 0, position: 'absolute', outline: '5px solid #fff',
+ left: o.left - event.pageX, top: o.top - event.pageY
+ })
+ .appendTo(set)
+ .animate({width: 10, height: 10, outlineWidth: 1, margin: 1, left: (20 * j), top: (row * 20)}, 500);
+ });
+ return set;
+ }
+ return null;
},
+
start: function(event, ui) {
$("#gMicroThumbPanel .ui-state-selected").hide();
},
@@ -52,9 +57,8 @@
greedy: true,
drop: function(event, ui) {
$.organize.do_drop({
- parent_id: $(".gBranchSelected").attr("ref"),
- target_id: $(".currentDropTarget").attr("ref"),
- position: $(".currentDropTarget").css("borderLeftStyle") == "solid" ? "before" : "after",
+ url: rearrange_url.replace("__TARGET_ID__", $(".currentDropTarget").attr("ref"))
+ .replace("__BEFORE__", $(".currentDropTarget").css("borderLeftStyle") == "solid"),
source: $(ui.helper).children("img")
});
}
@@ -66,40 +70,61 @@
greedy: true,
drop: function(event, ui) {
$.organize.do_drop({
- parent_id: $(event.target).attr("ref"),
- target_id: -1,
- position: "after",
+ url: move_url.replace("__TARGET_ID__", $(event.target).attr("ref")),
source: $(ui.helper).children("img")
});
}
},
- do_drop:function(drop_parms) {
- var source_ids = "";
- $(drop_parms.source).each(function(i) {
- source_ids += (source_ids.length ? "&" : "") + "source_id[" + i + "]=" + $(this).attr("ref");
+ do_drop:function(options) {
+ var source_ids = [];
+ $(options.source).each(function(i) {
+ source_ids.push($(this).attr("ref"));
});
- var url = drop_url.replace("__PARENT_ID__", drop_parms.parent_id)
- .replace("__POSITION__", drop_parms.position)
- .replace("__TARGET_ID__", drop_parms.target_id);
-
- console.group("do_drop");
- console.log("Generated url: " + url);
- console.log("Post data(ids to move): " + source_ids);
- console.groupEnd();
- // @todo do a ajax call to send the rearrange request to the server
- // organize/move/parent_id/before|after/-1|target_id
- // post parameters
- // source=[id1, id2, ...]
- // before or after not supplied then append to end
- // return: json {
- // result: success | msg,
- // tree: null | new tree,
- // content: new thumbgrid
- // }
- // do forget to reset all the stuff in init when updating the content
+
+ if (source_ids.length) {
+ $("#gOrganize .gProgressBar").progressbar().progressbar("value", 0);
+ $("#gOrganizeProgress").slideDown("fast", function() {
+ $.ajax({
+ url: options.url,
+ type: "POST",
+ async: false,
+ data: { "source_ids[]": source_ids },
+ dataType: "json",
+ success: function(data, textStatus) {
+ $("#gStatus").html(data.status);
+ $("#gOrganize .gProgressBar").progressbar("value", data.percent_complete);
+ setTimeout(function() { $.organize._run_task(data.url); }, 0);
+ }
+ });
+ });
+ }
},
+ _run_task: function(url) {
+ $.ajax({
+ url: url,
+ async: false,
+ dataType: "json",
+ success: function(data, textStatus) {
+ $("#gStatus").html(data.status);
+ $("#gOrganize .gProgressBar").progressbar("value", data.percent_complete);
+ if (data.done) {
+ $("#gProgress").slideUp();
+ // Don't forget to refresh the content pane and tree
+ if (data.tree) {
+ $("#gOrganizeAlbumTree").html(data.tree);
+ }
+ if (data.content) {
+ $("#gMicroThumbGrid").html(data.content);
+ }
+ $.organize.set_handlers();
+ } else {
+ setTimeout(function() { $.organize._run_task(url); }, 0);
+ }
+ }
+ });
+ },
mouse_move_handler: function(event) {
if ($(".gDragHelper").length) {
$(".gMicroThumbGridCell").css("borderStyle", "hidden");
@@ -121,8 +146,8 @@
$("#gDialog").dialog("option", "zIndex", 70);
$("#gDialog").bind("dialogopen", function(event, ui) {
$("#gOrganize").height($("#gDialog").innerHeight() - 20);
- $("#gMicroThumbPanel").height($("#gDialog").innerHeight() - 90);
- $("#gOrganizeAlbumTree").height($("#gDialog").innerHeight() - 59);
+ $("#gMicroThumbPanel").height($("#gDialog").innerHeight() - 120);
+ $("#gOrganizeAlbumTree").height($("#gDialog").innerHeight() - 89);
});
$("#gDialog").bind("dialogclose", function(event, ui) {
@@ -133,18 +158,18 @@
$("#gDialog").dialog("close");
});
- $("#gMicroThumbPanel").selectable({filter: ".gMicroThumbGridCell"});
- $("#gMicroThumbPanel").droppable($.organize.content_droppable);
-
$.organize.set_handlers();
},
set_handlers: function() {
+ $("#gMicroThumbPanel").selectable({filter: ".gMicroThumbGridCell"});
+ $("#gMicroThumbPanel").droppable($.organize.content_droppable);
+
$(".gMicroThumbGridCell").draggable($.organize.micro_thumb_draggable);
$(".gMicroThumbGridCell").mousemove($.organize.mouse_move_handler);
$(".gOrganizeBranch").droppable($.organize.branch_droppable);
- $(".gBranchText span").click($.organize.collapse_or_expand_tree);
$(".gBranchText").click($.organize.show_album);
+ $(".gOrganizeBranch .ui-icon").click($.organize.collapse_or_expand_tree);
},
/**
@@ -164,6 +189,7 @@
if ($(event.currentTarget).hasClass("gBranchSelected")) {
return;
}
+ $("#gMicroThumbPanel").selectable("destroy");
var id = $(event.currentTarget).attr("ref");
$(".gBranchSelected").removeClass("gBranchSelected");
$("#gOrganizeBranch-" + id).addClass("gBranchSelected");
diff --git a/modules/organize/views/organize_dialog.html.php b/modules/organize/views/organize_dialog.html.php
index 982eba9e..46f9ad9b 100644
--- a/modules/organize/views/organize_dialog.html.php
+++ b/modules/organize/views/organize_dialog.html.php
@@ -1,6 +1,7 @@
<?php defined("SYSPATH") or die("No direct script access.") ?>
<script type="text/javascript">
- var drop_url = "<?= url::site("organize/drop/__PARENT_ID__/__POSITION__/__TARGET_ID__?csrf=$csrf") ?>";
+ var move_url = "<?= url::site("organize/move/__TARGET_ID__?csrf=$csrf") ?>";
+ var rearrange_url = "<?= url::site("organize/rearrange/__TARGET_ID__/__BEFORE__?csrf=$csrf") ?>";
</script>
<div id="gOrganize" class="gDialogPanel">
<h1 style="display:none"><?= t("Organize %name", array("name" => p::purify($title))) ?></h1>
@@ -39,6 +40,10 @@
</div>
</div>
</div>
+ <div id="gOrganizeProgress" style="display: none">
+ <div class="gProgressBar"></div>
+ <div id="gStatus"></div>
+ </div>
</div>
<script type="text/javascript">