From c553bb64715f40d1755bb84c277442df88e3a925 Mon Sep 17 00:00:00 2001 From: Florian Pritz Date: Tue, 6 Sep 2016 14:02:31 +0200 Subject: Add multipaste queue Signed-off-by: Florian Pritz --- application/config/routes.php | 1 + application/controllers/file/multipaste.php | 113 ++++++++++++++++++++++++++++ application/service/multipaste_queue.php | 85 +++++++++++++++++++++ application/views/file/multipaste/queue.php | 32 ++++++++ public_html/data/css/style.css | 32 ++++++++ public_html/data/js/application.js | 3 + public_html/data/js/multipaste.js | 86 +++++++++++++++++++++ 7 files changed, 352 insertions(+) create mode 100644 application/controllers/file/multipaste.php create mode 100644 application/service/multipaste_queue.php create mode 100644 application/views/file/multipaste/queue.php create mode 100644 public_html/data/js/multipaste.js diff --git a/application/config/routes.php b/application/config/routes.php index 9583ff37c..f44f283f0 100644 --- a/application/config/routes.php +++ b/application/config/routes.php @@ -40,6 +40,7 @@ $route['default_controller'] = "file/file_default"; $route['user/(:any)'] = "user/$1"; +$route['file/multipaste/(:any)'] = "file/multipaste/$1"; $route['file/(:any)'] = "file/file_default/$1"; $route['tools/(:any)'] = "tools/$1"; $route['api/(:any)'] = "api/route/$1"; diff --git a/application/controllers/file/multipaste.php b/application/controllers/file/multipaste.php new file mode 100644 index 000000000..00efb2403 --- /dev/null +++ b/application/controllers/file/multipaste.php @@ -0,0 +1,113 @@ + + * + * Licensed under AGPLv3 + * (see COPYING for full license text) + * + */ + +class Multipaste extends MY_Controller { + + function __construct() { + parent::__construct(); + + $this->load->model('mfile'); + $this->load->model('mmultipaste'); + } + + public function append_multipaste_queue() { + $this->muser->require_access("basic"); + + $ids = $this->input->post("ids"); + if ($ids === false) { + $ids = []; + } + + $m = new \service\multipaste_queue(); + $m->append($ids); + + redirect("file/multipaste/queue"); + } + + public function review_multipaste() { + $this->muser->require_access("basic"); + + $this->load->view('header', $this->data); + $this->load->view('file/review_multipaste', $this->data); + $this->load->view('footer', $this->data); + } + + public function queue() { + $this->muser->require_access("basic"); + + $m = new \service\multipaste_queue(); + $ids = $m->get(); + + $this->data['ids'] = $ids; + $this->data['items'] = array_map(function($id) {return $this->_get_multipaste_item($id);}, $ids); + + $this->load->view('header', $this->data); + $this->load->view('file/multipaste/queue', $this->data); + $this->load->view('footer', $this->data); + } + + public function form_submit() { + $this->muser->require_access("basic"); + + $ids = $this->input->post('ids'); + $process = $this->input->post('process'); + + if ($ids === false) { + $ids = []; + } + + $m = new \service\multipaste_queue(); + $m->set($ids); + + $dispatcher = [ + 'save' => function() use ($ids, $m) { + redirect("file/multipaste/queue"); + }, + 'create' => function() use ($ids, $m) { + $userid = $this->muser->get_userid(); + $limits = $this->muser->get_upload_id_limits(); + $ret = \service\files::create_multipaste($ids, $userid, $limits); + $m->set([]); + redirect($ret['url_id']); + }, + ]; + + if (isset($dispatcher[$process])) { + $dispatcher[$process](); + } else { + throw new \exceptions\UserInputException("file/multipaste/form_submit/invalid-process-value", "Value in process field not found in dispatch table"); + } + } + + public function ajax_submit() { + $this->muser->require_access("basic"); + $ids = $this->input->post('ids'); + + if ($ids === false) { + $ids = []; + } + + $m = new \service\multipaste_queue(); + $m->set($ids); + } + + private function _get_multipaste_item($id) { + $filedata = $this->mfile->get_filedata($id); + $item = []; + $item['id'] = $filedata['id']; + $item['tooltip'] = \service\files::tooltip($filedata); + $item['title'] = $filedata['filename']; + if (\libraries\Image::type_supported($filedata["mimetype"])) { + $item['thumbnail'] = site_url("file/thumbnail/".$filedata['id']); + } + + return $item; + } + +} diff --git a/application/service/multipaste_queue.php b/application/service/multipaste_queue.php new file mode 100644 index 000000000..1836eeacb --- /dev/null +++ b/application/service/multipaste_queue.php @@ -0,0 +1,85 @@ + + * + * Licensed under AGPLv3 + * (see COPYING for full license text) + * + */ + +namespace service; + +class multipaste_queue { + + public function __construct() { + $CI =& get_instance(); + $CI->load->model("mfile"); + $CI->load->model("mmultipaste"); + $this->session = $CI->session; + $this->mfile = $CI->mfile; + $this->mmultipaste = $CI->mmultipaste; + } + + /** + * Append ids to the queue + * + * @param array ids + * @return void + */ + public function append(array $ids) { + $old_ids = $this->get(); + + $old_ids = $this->get(); + + # replace multipaste ids with their corresponding paste ids + $ids = array_map(function($id) {return array_values($this->resolve_multipaste($id));}, $ids); + $ids = array_reduce($ids, function($a, $b) {return array_merge($a, $b);}, []); + + $ids = array_unique(array_merge($old_ids, $ids)); + $this->set($ids); + } + + /** + * Return array of ids in a multipaste if the argument id is a multipaste. + * Otherwise return an array containing just the argument id. + * + * @param id + * @return array of ids + */ + private function resolve_multipaste($id) { + if (strpos($id, "m-") === 0) { + if ($this->mmultipaste->valid_id($id)) { + return array_map(function($filedata) {return $filedata['id'];}, $this->mmultipaste->get_files($id)); + } + } + return [$id]; + } + + /** + * Get the queue + * + * @return array of ids + */ + public function get() { + $ids = $this->session->userdata("multipaste_queue"); + if ($ids === false) { + $ids = []; + } + + assert(is_array($ids)); + return $ids; + } + + /** + * Set the queue to $ids + * + * @param array ids + * @return void + */ + public function set(array $ids) { + $ids = array_filter($ids, function($id) {return $this->mfile->valid_id($id);}); + + $this->session->set_userdata("multipaste_queue", $ids); + } + +} diff --git a/application/views/file/multipaste/queue.php b/application/views/file/multipaste/queue.php new file mode 100644 index 000000000..3f42b3cdf --- /dev/null +++ b/application/views/file/multipaste/queue.php @@ -0,0 +1,32 @@ +
+ site_url("file/multipaste/ajax_submit")]); ?> +
+ +
+ + + +
+
+ +
+ +
+ +
+ + + +
diff --git a/public_html/data/css/style.css b/public_html/data/css/style.css index 57366d3d6..8868c5995 100644 --- a/public_html/data/css/style.css +++ b/public_html/data/css/style.css @@ -42,6 +42,38 @@ height: 50px; } +.multipasteQueue .items>div { + height: 190px; + display: inline-block; + width: 150px; + vertical-align: top; + margin: 0 1px 20px 1px; +} + +.multipasteQueue .items .item { + height: 160px; +} + +.ajaxFeedback { + display: inline-block; +} + +/* Source: http://stackoverflow.com/a/26283602 */ +.glyphicon.spinning { + animation: spin 1s infinite linear; + -webkit-animation: spin2 1s infinite linear; +} + +@keyframes spin { + from { transform: scale(1) rotate(0deg); } + to { transform: scale(1) rotate(360deg); } +} + +@-webkit-keyframes spin2 { + from { -webkit-transform: rotate(0deg); } + to { -webkit-transform: rotate(360deg); } +} + @media (max-width: 768px) { .dont-float { float: left; diff --git a/public_html/data/js/application.js b/public_html/data/js/application.js index 674f68008..d212ce04c 100644 --- a/public_html/data/js/application.js +++ b/public_html/data/js/application.js @@ -7,6 +7,7 @@ define( 'lexer-input', 'tabwidth-input', 'thumbnail-view', + 'multipaste', 'uploader', 'tablesorter', 'jquery', @@ -20,6 +21,7 @@ define( LexerInput, TabwidthInput, ThumbnailView, + Multipaste, Uploader, TableSorter, $ @@ -44,6 +46,7 @@ define( TabwidthInput.initialize(); LexerInput.initialize(); ThumbnailView.initialize(); + Multipaste.initialize(); Uploader.initialize(); TableSorter.initialize(); this.configureTooltips(); diff --git a/public_html/data/js/multipaste.js b/public_html/data/js/multipaste.js new file mode 100644 index 000000000..21434ab0d --- /dev/null +++ b/public_html/data/js/multipaste.js @@ -0,0 +1,86 @@ +(function () { +'use strict'; +define(['underscore', 'util', 'jquery', 'jquery-ui'], function (_, Util, $) { + var ui = { + itemsContainer: ".multipasteQueue .items", + queueDeleteButton: ".multipaste_queue_delete", + submitButton: ".multipasteQueue button[type=submit]", + itemImages: ".multipasteQueue .items img", + form: ".multipasteQueue form", + csrfToken: "form input[name=csrf_test_name]", + ajaxFeedback: "form .ajaxFeedback", + }; + + var timer = 0; + + var PrivateFunctions = { + setupQueueDeleteButtons: function() { + $(ui.queueDeleteButton).on('click', function(event) { + event.stopImmediatePropagation(); + var id = $(event.target).data('id'); + $(event.target).parent().remove(); + PrivateFunctions.saveQueue(); + }); + }, + setupTooltips: function() { + $(ui.itemImages).popover({ + trigger: 'hover', + placement: 'auto bottom', + html: true + }); + }, + setupButtons: function() { + this.setupQueueDeleteButtons(); + }, + setupSortable: function() { + $(ui.itemsContainer).sortable({ + revert: 100, + placeholder: "ui-state-highlight", + tolerance: "pointer", + stop: function(e, u) { + u.item.find("img").first().popover("show"); + }, + start: function(e, u) { + u.item.find("img").first().popover("show"); + }, + update: function(e, u) { + PrivateFunctions.saveQueue(); + }, + }); + + $(ui.itemsContainer).disableSelection(); + }, + saveQueue: function() { + var queue = $(ui.itemsContainer).sortable("toArray", {attribute: "data-id"}); + console.log("queue changed ", queue); + clearTimeout(timer); + timer = setTimeout(function() { + var url = $(ui.form).data("ajax_url"); + var csrf_token = $(ui.csrfToken).attr("value"); + $(ui.ajaxFeedback).show(); + $.ajax({ + method: "POST", + url: url, + data: { + csrf_test_name: csrf_token, + ids: queue + }, + complete: function() { + $(ui.ajaxFeedback).hide(); + }, + }); + }, 2000); + }, + }; + + var Multipaste = { + initialize: function () { + PrivateFunctions.setupButtons(); + PrivateFunctions.setupSortable(); + PrivateFunctions.setupTooltips(); + }, + }; + + return Multipaste; +}); +})(); -- cgit v1.2.3-24-g4f1b From c9fa3ed37fd1371ef24f6c3330995025295d7baf Mon Sep 17 00:00:00 2001 From: Florian Pritz Date: Tue, 6 Sep 2016 14:11:39 +0200 Subject: Allow creation of multipastes from upload history Signed-off-by: Florian Pritz --- application/controllers/file/file_default.php | 34 +++++++++++++++++++++++++++ application/views/file/upload_history.php | 8 +++++-- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/application/controllers/file/file_default.php b/application/controllers/file/file_default.php index 2b77866a0..3b5eb0ee4 100644 --- a/application/controllers/file/file_default.php +++ b/application/controllers/file/file_default.php @@ -683,6 +683,40 @@ class File_default extends MY_Controller { $this->load->view('footer', $this->data); } + public function handle_history_submit() + { + $this->muser->require_access("apikey"); + + $process = $this->input->post("process"); + + $dispatcher = [ + "delete" => function() { + return $this->do_delete(); + }, + "multipaste" => function() { + return $this->_append_multipaste_queue(); + }, + ]; + + if (isset($dispatcher[$process])) { + $dispatcher[$process](); + } else { + throw new \exceptions\UserInputException("file/handle_history_submit/invalid-process-value", "Value in process field not found in dispatch table"); + } + } + + private function _append_multipaste_queue() + { + $ids = $this->input->post("ids"); + if ($ids === false) { + $ids = []; + } + + $m = new \service\multipaste_queue(); + $m->append($ids); + redirect("file/multipaste/queue"); + } + function upload_history() { $this->muser->require_access("apikey"); diff --git a/application/views/file/upload_history.php b/application/views/file/upload_history.php index 253c0aa9e..54324d5b3 100644 --- a/application/views/file/upload_history.php +++ b/application/views/file/upload_history.php @@ -1,7 +1,10 @@ - + @@ -32,6 +35,7 @@ +

Total sum of your distinct uploads: .

-- cgit v1.2.3-24-g4f1b From b78773f3fb954654515d551bef9cb8e68cd4b05a Mon Sep 17 00:00:00 2001 From: Florian Pritz Date: Tue, 6 Sep 2016 14:40:31 +0200 Subject: Support creation of multipaste from upload thumbnail history Signed-off-by: Florian Pritz --- .../views/file/upload_history_thumbnails.php | 7 ++-- public_html/data/js/thumbnail-view.js | 42 +++++++++++----------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/application/views/file/upload_history_thumbnails.php b/application/views/file/upload_history_thumbnails.php index 9fb9c5450..7d4fc6298 100644 --- a/application/views/file/upload_history_thumbnails.php +++ b/application/views/file/upload_history_thumbnails.php @@ -1,10 +1,11 @@ - +

Total sum of your distinct uploads: .

-- cgit v1.2.3-24-g4f1b From c3d5786689bbc4a7f499f07cf1390afd800dc69a Mon Sep 17 00:00:00 2001 From: Florian Pritz Date: Tue, 1 Nov 2016 14:26:44 +0100 Subject: upload_history: Drop duplicate buttons from bottom Signed-off-by: Florian Pritz --- application/views/file/upload_history.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/application/views/file/upload_history.php b/application/views/file/upload_history.php index 694b44fbc..c6cbe7946 100644 --- a/application/views/file/upload_history.php +++ b/application/views/file/upload_history.php @@ -34,8 +34,6 @@ - -

Total sum of your distinct uploads: .

-- cgit v1.2.3-24-g4f1b