diff --git a/app/Controller/Task.php b/app/Controller/Task.php index d94c5908f..1296204a0 100644 --- a/app/Controller/Task.php +++ b/app/Controller/Task.php @@ -75,6 +75,7 @@ class Task extends Base 'links' => $this->taskLink->getLinks($task['id']), 'task' => $task, 'values' => $values, + 'link_label_list' => $this->link->getList(0, false), 'columns_list' => $this->board->getColumnsList($task['project_id']), 'colors_list' => $this->color->getList(), 'date_format' => $this->config->get('application_date_format'), diff --git a/app/Controller/Tasklink.php b/app/Controller/Tasklink.php index 61b7fab82..59ce04332 100644 --- a/app/Controller/Tasklink.php +++ b/app/Controller/Tasklink.php @@ -36,6 +36,7 @@ class Tasklink extends Base public function create(array $values = array(), array $errors = array()) { $task = $this->getTask(); + $ajax = $this->request->isAjax() || $this->request->getIntegerParam('ajax'); if (empty($values)) { $values = array( @@ -43,6 +44,17 @@ class Tasklink extends Base ); } + if ($ajax) { + $this->response->html($this->template->render('tasklink/create', array( + 'values' => $values, + 'errors' => $errors, + 'task' => $task, + 'labels' => $this->link->getList(0, false), + 'title' => t('Add a new link'), + 'ajax' => $ajax, + ))); + } + $this->response->html($this->taskLayout('tasklink/create', array( 'values' => $values, 'errors' => $errors, @@ -61,6 +73,7 @@ class Tasklink extends Base { $task = $this->getTask(); $values = $this->request->getValues(); + $ajax = $this->request->isAjax() || $this->request->getIntegerParam('ajax'); list($valid, $errors) = $this->taskLink->validateCreation($values); @@ -68,6 +81,9 @@ class Tasklink extends Base if ($this->taskLink->create($values['task_id'], $values['opposite_task_id'], $values['link_id'])) { $this->session->flash(t('Link added successfully.')); + if ($ajax) { + $this->response->redirect($this->helper->url('board', 'show', array('project_id' => $task['project_id']))); + } $this->response->redirect($this->helper->url('task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])).'#links'); } else { diff --git a/app/Model/TaskLink.php b/app/Model/TaskLink.php index f8e9f99e3..623913710 100644 --- a/app/Model/TaskLink.php +++ b/app/Model/TaskLink.php @@ -4,6 +4,7 @@ namespace Model; use SimpleValidator\Validator; use SimpleValidator\Validators; +use PicoDb\Table; /** * TaskLink model @@ -57,6 +58,7 @@ class TaskLink extends Base ->join(Link::TABLE, 'id', 'link_id') ->join(Task::TABLE, 'id', 'opposite_task_id') ->join(Board::TABLE, 'id', 'column_id', Task::TABLE) + ->orderBy(Link::TABLE.'.id ASC, '.Board::TABLE.'.position ASC, '.Task::TABLE.'.is_active DESC, '.Task::TABLE.'.id', Table::SORT_ASC) ->findAll(); } diff --git a/app/Template/board/task_menu.php b/app/Template/board/task_menu.php index bbf12291e..35104b664 100644 --- a/app/Template/board/task_menu.php +++ b/app/Template/board/task_menu.php @@ -6,6 +6,7 @@
  • a(t('Change category'), 'board', 'changeCategory', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?>
  • a(t('Change description'), 'task', 'description', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?>
  • a(t('Add a comment'), 'comment', 'create', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?>
  • +
  • a(t('Add a link'), 'tasklink', 'create', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?>
  • a(t('Edit this task'), 'task', 'edit', array('task_id' => $task['id'], 'project_id' => $task['project_id']), false, 'task-board-popover') ?>
  • a(t('Close this task'), 'task', 'close', array('task_id' => $task['id'], 'project_id' => $task['project_id'], 'redirect' => 'board'), false, 'task-board-popover') ?>
  • diff --git a/app/Template/task/show.php b/app/Template/task/show.php index ec9307158..50316c9ff 100644 --- a/app/Template/task/show.php +++ b/app/Template/task/show.php @@ -1,7 +1,7 @@ render('task/details', array('task' => $task, 'project' => $project)) ?> render('task/time', array('task' => $task, 'values' => $values, 'date_format' => $date_format, 'date_formats' => $date_formats)) ?> render('task/show_description', array('task' => $task)) ?> -render('tasklink/show', array('task' => $task, 'links' => $links)) ?> +render('tasklink/show', array('task' => $task, 'links' => $links, 'link_label_list' => $link_label_list)) ?> render('subtask/show', array('task' => $task, 'subtasks' => $subtasks, 'project' => $project)) ?> render('task/timesheet', array('task' => $task)) ?> render('file/show', array('task' => $task, 'files' => $files, 'images' => $images)) ?> diff --git a/app/Template/tasklink/create.php b/app/Template/tasklink/create.php index fb438cd86..acf9d6d1c 100644 --- a/app/Template/tasklink/create.php +++ b/app/Template/tasklink/create.php @@ -2,7 +2,7 @@

    -
    + formCsrf() ?> formHidden('task_id', $values) ?> @@ -22,6 +22,10 @@
    - a(t('cancel'), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?> + + a(t('cancel'), 'board', 'show', array('project_id' => $task['project_id']), false, 'close-popover') ?> + + a(t('cancel'), 'task', 'show', array('task_id' => $task['id'], 'project_id' => $task['project_id'])) ?> +
    \ No newline at end of file diff --git a/app/Template/tasklink/show.php b/app/Template/tasklink/show.php index a36f89dd3..75e3c3763 100644 --- a/app/Template/tasklink/show.php +++ b/app/Template/tasklink/show.php @@ -41,4 +41,24 @@ - \ No newline at end of file + + +
    + + formCsrf() ?> + formHidden('task_id', array('task_id' => $task['id'])) ?> + formHidden('opposite_task_id', array()) ?> + + formSelect('link_id', $link_label_list, array(), array()) ?> + + formText( + 'title', + array(), + array(), + array('required', 'data-dst-field="opposite_task_id"', 'data-search-url="'.$this->u('app', 'autocomplete', array('exclude_task_id' => $task['id'])).'"'), + 'task-autocomplete') ?> + + +
    + + diff --git a/assets/css/app.css b/assets/css/app.css index 9705b64f9..aa846737d 100644 --- a/assets/css/app.css +++ b/assets/css/app.css @@ -1077,6 +1077,41 @@ span.task-board-date-overdue { .task-link-closed { text-decoration: line-through; } +.task-show-images { + list-style-type: none; +} +.task-show-images li img { + width: 100%; +} +.task-show-images li .img_container { + width: 250px; + height: 100px; + overflow: hidden; +} +.task-show-images li { + padding: 10px; + overflow: auto; + width: 250px; + min-height: 120px; + display: inline-block; + vertical-align: top; +} +.task-show-images li p{ + padding: 5px; + font-weight: bold; +} +.task-show-images li:hover { + background: #eee; +} +.task-show-image-actions { + margin-left: 5px; +} +.task-show-images li .img_container:hover { + height: 100%; +} +.task-show-file-table { + width: auto; +} /* comments */ .comment { margin-bottom: 20px; @@ -1556,38 +1591,3 @@ td li.dropit-trigger { .task-board .dropit-submenu a:hover { text-decoration: none; } -.task-show-images { - list-style-type: none; -} -.task-show-images li img { - width: 100%; -} -.task-show-images li .img_container { - width: 250px; - height: 100px; - overflow: hidden; -} -.task-show-images li { - padding: 10px; - overflow: auto; - width: 250px; - min-height: 120px; - display: inline-block; - vertical-align: top; -} -.task-show-images li p{ - padding: 5px; - font-weight: bold; -} -.task-show-images li:hover { - background: #eee; -} -.task-show-image-actions { - margin-left: 5px; -} -.task-show-images li .img_container:hover { - height: 100%; -} -.task-show-file-table { - width: auto; -} \ No newline at end of file diff --git a/assets/css/src/task.css b/assets/css/src/task.css index 39cda76a0..946d18d49 100644 --- a/assets/css/src/task.css +++ b/assets/css/src/task.css @@ -253,7 +253,7 @@ span.task-board-date-overdue { } .task-show-images li .img_container { width: 250px; - height: 100px; + height: 100px; overflow: hidden; } .task-show-images li { diff --git a/assets/js/app.js b/assets/js/app.js index 7a3a6c967..d5733ed9b 100644 --- a/assets/js/app.js +++ b/assets/js/app.js @@ -142,7 +142,8 @@ return""!=a?"visible"==document[a]:!0},SetStorageItem:function(a,c){"undefined"! c.parent().addClass("form-tab-selected");e.find(".markdown").html(a);e.css("height",f.css("height"));e.css("width",f.css("width"));d.hide();e.show()})},MarkdownWriter:function(a){a.preventDefault();$(this).closest("ul").find("li").removeClass("form-tab-selected");$(this).parent().addClass("form-tab-selected");$(".write-area").show();$(".preview-area").hide()},CheckSession:function(){$(".form-login").length||$.ajax({cache:!1,url:$("body").data("status-url"),statusCode:{401:function(){window.location= $("body").data("login-url")}}})},Init:function(){$("#board-selector").chosen({width:180,no_results_text:$("#board-selector").data("notfound")});$("#board-selector").change(function(){window.location=$(this).attr("data-board-url").replace(/PROJECT_ID/g,$(this).val())});window.setInterval(Kanboard.CheckSession,6E4);Mousetrap.bindGlobal("mod+enter",function(){$("form").submit()});Mousetrap.bind("b",function(a){a.preventDefault();$("#board-selector").trigger("chosen:open")});$(".column-tooltip").tooltip({content:function(){return'
    '+ $(this).attr("title")+"
    "},position:{my:"left-20 top",at:"center bottom+9",using:function(a,c){$(this).css(a);var b=c.target.left+c.target.width/2-c.element.left-20;$("
    ").addClass("tooltip-arrow").addClass(c.vertical).addClass(0==b?"align-left":"align-right").appendTo(this)}}});$.datepicker.setDefaults($.datepicker.regional[$("body").data("js-lang")]);Kanboard.InitAfterAjax()},InitAfterAjax:function(){$(document).on("click",".popover",Kanboard.Popover);$(".form-date").datepicker({showOtherMonths:!0, -selectOtherMonths:!0,dateFormat:"yy-mm-dd",constrainInput:!1});$("#markdown-preview").click(Kanboard.MarkdownPreview);$("#markdown-write").click(Kanboard.MarkdownWriter);$(".auto-select").focus(function(){$(this).select()});$(".dropit-submenu").hide();$(".dropdown").not(".dropit").dropit({triggerParentEl:"span"})}}}(); +selectOtherMonths:!0,dateFormat:"yy-mm-dd",constrainInput:!1});$("#markdown-preview").click(Kanboard.MarkdownPreview);$("#markdown-write").click(Kanboard.MarkdownWriter);$(".auto-select").focus(function(){$(this).select()});$(".dropit-submenu").hide();$(".dropdown").not(".dropit").dropit({triggerParentEl:"span"});$(".task-autocomplete").length&&($(".task-autocomplete").parent().find("input[type=submit]").attr("disabled","disabled"),$(".task-autocomplete").autocomplete({source:$(".task-autocomplete").data("search-url"), +minLength:2,select:function(a,c){var b=$(".task-autocomplete").data("dst-field");$("input[name="+b+"]").val(c.item.id);$(".task-autocomplete").parent().find("input[type=submit]").removeAttr("disabled")}}))}}}(); Kanboard.Board=function(){function a(a){a.preventDefault();a.stopPropagation();Kanboard.Popover(a,Kanboard.InitAfterAjax)}function c(){Mousetrap.bind("n",function(){Kanboard.OpenPopover($("#board").data("task-creation-url"),Kanboard.InitAfterAjax)});Mousetrap.bind("s",function(){"expanded"===(Kanboard.GetStorageItem(d())||"expanded")?(e(),Kanboard.SetStorageItem(d(),"collapsed")):(f(),Kanboard.SetStorageItem(d(),"expanded"))});Mousetrap.bind("c",function(){p()})}function b(){$(".filter-expand-link").click(function(a){a.preventDefault(); f();Kanboard.SetStorageItem(d(),"expanded")});$(".filter-collapse-link").click(function(a){a.preventDefault();e();Kanboard.SetStorageItem(d(),"collapsed")});g()}function d(){return"board_stacking_"+$("#board").data("project-id")}function e(){$(".filter-collapse").hide();$(".task-board-collapsed").show();$(".filter-expand").show();$(".task-board-expanded").hide()}function f(){$(".filter-collapse").show();$(".task-board-collapsed").hide();$(".filter-expand").hide();$(".task-board-expanded").show()} function g(){"expanded"===(Kanboard.GetStorageItem(d())||"expanded")?f():e()}function k(){$(".column").sortable({delay:300,distance:5,connectWith:".column",placeholder:"draggable-placeholder",stop:function(a,b){q(b.item.attr("data-task-id"),b.item.parent().attr("data-column-id"),b.item.index()+1,b.item.parent().attr("data-swimlane-id"))}});$("#board").on("click",".task-board-popover",a);$("#board").on("click",".task-board",function(){window.location=$(this).data("task-url")});$(".task-board-tooltip").tooltip({track:!1, @@ -163,7 +164,6 @@ Kanboard.Analytic=function(){jQuery(document).ready(function(){Kanboard.Exists(" Kanboard.Analytic.CFD=function(){return{Init:function(){jQuery.getJSON($("#chart").attr("data-url"),function(a){var c=a.labels,b=a.columns,d=a.metrics;a=[];for(var e=0;e