diff options
Diffstat (limited to 'assets/js/src')
-rw-r--r-- | assets/js/src/App.js | 69 | ||||
-rw-r--r-- | assets/js/src/Board.js | 74 | ||||
-rw-r--r-- | assets/js/src/Column.js | 59 | ||||
-rw-r--r-- | assets/js/src/CompareHoursColumnChart.js | 39 | ||||
-rw-r--r-- | assets/js/src/Dropdown.js | 41 | ||||
-rw-r--r-- | assets/js/src/FileUpload.js | 124 | ||||
-rw-r--r-- | assets/js/src/Gantt.js | 34 | ||||
-rw-r--r-- | assets/js/src/Popover.js | 52 | ||||
-rw-r--r-- | assets/js/src/Project.js | 28 | ||||
-rw-r--r-- | assets/js/src/Router.js | 1 | ||||
-rw-r--r-- | assets/js/src/Search.js | 9 | ||||
-rw-r--r-- | assets/js/src/Sidebar.js | 25 | ||||
-rw-r--r-- | assets/js/src/Subtask.js | 94 | ||||
-rw-r--r-- | assets/js/src/Swimlane.js | 56 | ||||
-rw-r--r-- | assets/js/src/Task.js | 43 | ||||
-rw-r--r-- | assets/js/src/Tooltip.js | 15 |
16 files changed, 633 insertions, 130 deletions
diff --git a/assets/js/src/App.js b/assets/js/src/App.js index 7651b3ec..b20a73c1 100644 --- a/assets/js/src/App.js +++ b/assets/js/src/App.js @@ -1,13 +1,16 @@ function App() { this.board = new Board(this); this.markdown = new Markdown(); - this.sidebar = new Sidebar(); this.search = new Search(this); - this.swimlane = new Swimlane(); + this.swimlane = new Swimlane(this); this.dropdown = new Dropdown(); this.tooltip = new Tooltip(this); this.popover = new Popover(this); - this.task = new Task(); + this.task = new Task(this); + this.project = new Project(); + this.subtask = new Subtask(this); + this.column = new Column(this); + this.file = new FileUpload(this); this.keyboardShortcuts(); this.chosen(); this.poll(); @@ -16,29 +19,22 @@ function App() { $(".alert-fade-out").delay(4000).fadeOut(800, function() { $(this).remove(); }); - - // Reload page when a destination project is changed - var reloading_project = false; - $("select.task-reload-project-destination").change(function() { - if (! reloading_project) { - $(".loading-icon").show(); - reloading_project = true; - window.location = $(this).data("redirect").replace(/PROJECT_ID/g, $(this).val()); - } - }); } App.prototype.listen = function() { + this.project.listen(); this.popover.listen(); this.markdown.listen(); - this.sidebar.listen(); this.tooltip.listen(); this.dropdown.listen(); this.search.listen(); this.task.listen(); this.swimlane.listen(); + this.subtask.listen(); + this.column.listen(); + this.file.listen(); this.search.focus(); - this.taskAutoComplete(); + this.autoComplete(); this.datePicker(); this.focus(); }; @@ -125,36 +121,47 @@ App.prototype.datePicker = function() { // timeFormat: 'h:mm tt', constrainInput: false }); - - $(".hasDatepicker").on("blur", function(e) { $(this).datepicker("hide"); }); }; -App.prototype.taskAutoComplete = function() { - // Task auto-completion - if ($(".task-autocomplete").length) { +App.prototype.autoComplete = function() { + $(".autocomplete").each(function() { + var input = $(this); + var field = input.data("dst-field"); + var extraField = input.data("dst-extra-field"); - if ($('.opposite_task_id').val() == '') { - $(".task-autocomplete").parent().find("input[type=submit]").attr('disabled','disabled'); + if ($('#form-' + field).val() == '') { + input.parent().find("input[type=submit]").attr('disabled','disabled'); } - $(".task-autocomplete").autocomplete({ - source: $(".task-autocomplete").data("search-url"), + input.autocomplete({ + source: input.data("search-url"), minLength: 1, select: function(event, ui) { - var field = $(".task-autocomplete").data("dst-field"); $("input[name=" + field + "]").val(ui.item.id); - $(".task-autocomplete").parent().find("input[type=submit]").removeAttr('disabled'); + if (extraField) { + $("input[name=" + extraField + "]").val(ui.item[extraField]); + } + + input.parent().find("input[type=submit]").removeAttr('disabled'); } }); - } + }); }; App.prototype.chosen = function() { - $(".chosen-select").chosen({ - width: "180px", - no_results_text: $(".chosen-select").data("notfound"), - disable_search_threshold: 10 + $(".chosen-select").each(function() { + var searchThreshold = $(this).data("search-threshold"); + + if (searchThreshold === undefined) { + searchThreshold = 10; + } + + $(this).chosen({ + width: "180px", + no_results_text: $(this).data("notfound"), + disable_search_threshold: searchThreshold + }); }); $(".select-auto-redirect").change(function() { diff --git a/assets/js/src/Board.js b/assets/js/src/Board.js index b98aa366..c99f3cd3 100644 --- a/assets/js/src/Board.js +++ b/assets/js/src/Board.js @@ -1,18 +1,19 @@ function Board(app) { this.app = app; this.checkInterval = null; + this.savingInProgress = false; } Board.prototype.execute = function() { this.app.swimlane.refresh(); this.restoreColumnViewMode(); this.compactView(); - this.columnScrolling(); this.poll(); this.keyboardShortcuts(); this.listen(); this.dragAndDrop(); + $(window).on("load", this.columnScrolling); $(window).resize(this.columnScrolling); }; @@ -42,8 +43,7 @@ Board.prototype.reloadFilters = function(search) { }; Board.prototype.check = function() { - if (this.app.isVisible()) { - + if (this.app.isVisible() && ! this.savingInProgress) { var self = this; this.app.showLoadingIcon(); @@ -59,7 +59,9 @@ Board.prototype.check = function() { }; Board.prototype.save = function(taskId, columnId, position, swimlaneId) { + var self = this; this.app.showLoadingIcon(); + this.savingInProgress = true; $.ajax({ cache: false, @@ -73,8 +75,14 @@ Board.prototype.save = function(taskId, columnId, position, swimlaneId) { "swimlane_id": swimlaneId, "position": position }), - success: this.refresh.bind(this), - error: this.app.hideLoadingIcon.bind(this) + success: function(data) { + self.refresh(data); + this.savingInProgress = false; + }, + error: function() { + self.app.hideLoadingIcon(); + this.savingInProgress = false; + } }); }; @@ -83,12 +91,12 @@ Board.prototype.refresh = function(data) { this.app.refresh(); this.app.swimlane.refresh(); - this.columnScrolling(); this.app.hideLoadingIcon(); this.listen(); this.dragAndDrop(); this.compactView(); this.restoreColumnViewMode(); + this.columnScrolling(); }; Board.prototype.dragAndDrop = function() { @@ -100,13 +108,22 @@ Board.prototype.dragAndDrop = function() { placeholder: "draggable-placeholder", items: ".draggable-item", stop: function(event, ui) { - ui.item.removeClass("draggable-item-selected"); - self.save( - ui.item.attr('data-task-id'), - ui.item.parent().attr("data-column-id"), - ui.item.index() + 1, - ui.item.parent().attr('data-swimlane-id') - ); + var task = ui.item; + var taskId = task.attr('data-task-id'); + var taskPosition = task.attr('data-position'); + var taskColumnId = task.attr('data-column-id'); + var taskSwimlaneId = task.attr('data-swimlane-id'); + + var newColumnId = task.parent().attr("data-column-id"); + var newSwimlaneId = task.parent().attr('data-swimlane-id'); + var newPosition = task.index() + 1; + + task.removeClass("draggable-item-selected"); + + if (newColumnId != taskColumnId || newSwimlaneId != taskSwimlaneId || newPosition != taskPosition) { + self.changeTaskState(taskId); + self.save(taskId, newColumnId, newPosition, newSwimlaneId); + } }, start: function(event, ui) { ui.item.addClass("draggable-item-selected"); @@ -122,6 +139,12 @@ Board.prototype.dragAndDrop = function() { $(".board-task-list").sortable(params); }; +Board.prototype.changeTaskState = function(taskId) { + var task = $("div[data-task-id=" + taskId + "]"); + task.addClass('task-board-saving-state'); + task.find('.task-board-saving-icon').show(); +}; + Board.prototype.listen = function() { var self = this; @@ -141,27 +164,40 @@ Board.prototype.listen = function() { self.toggleColumnScrolling(); }); - $(document).on("click", ".board-column-title", function() { + $(document).on("click", ".board-toggle-column-view", function() { self.toggleColumnViewMode($(this).data("column-id")); }); }; Board.prototype.toggleColumnScrolling = function() { - var scrolling = localStorage.getItem("column_scroll") || 1; + var scrolling = localStorage.getItem("column_scroll"); + + if (scrolling == undefined) { + scrolling = 1; + } + localStorage.setItem("column_scroll", scrolling == 0 ? 1 : 0); this.columnScrolling(); }; Board.prototype.columnScrolling = function() { if (localStorage.getItem("column_scroll") == 0) { + var height = 80; + $(".filter-max-height").show(); $(".filter-min-height").hide(); + $(".board-rotation-wrapper").css("min-height", ''); $(".board-task-list").each(function() { - $(this).css("min-height", 80); - $(this).css("height", ''); - $(".board-rotation-wrapper").css("min-height", ''); + var columnHeight = $(this).height(); + + if (columnHeight > height) { + height = columnHeight; + } }); + + $(".board-task-list").css("min-height", height); + $(".board-task-list").css("height", ''); } else { @@ -180,7 +216,7 @@ Board.prototype.columnScrolling = function() { }); } else { - var height = $(window).height() - 145; + var height = $(window).height() - 170; $(".board-task-list").css("height", height); $(".board-rotation-wrapper").css("min-height", height); diff --git a/assets/js/src/Column.js b/assets/js/src/Column.js new file mode 100644 index 00000000..2c8ebbd2 --- /dev/null +++ b/assets/js/src/Column.js @@ -0,0 +1,59 @@ +function Column(app) { + this.app = app; +} + +Column.prototype.listen = function() { + this.dragAndDrop(); +}; + +Column.prototype.dragAndDrop = function() { + var self = this; + + $(".draggable-row-handle").mouseenter(function() { + $(this).parent().parent().addClass("draggable-item-hover"); + }).mouseleave(function() { + $(this).parent().parent().removeClass("draggable-item-hover"); + }); + + $(".columns-table tbody").sortable({ + forcePlaceholderSize: true, + handle: "td:first i", + helper: function(e, ui) { + ui.children().each(function() { + $(this).width($(this).width()); + }); + + return ui; + }, + stop: function(event, ui) { + var column = ui.item; + column.removeClass("draggable-item-selected"); + self.savePosition(column.data("column-id"), column.index() + 1); + }, + start: function(event, ui) { + ui.item.addClass("draggable-item-selected"); + } + }).disableSelection(); +}; + +Column.prototype.savePosition = function(columnId, position) { + var url = $(".columns-table").data("save-position-url"); + var self = this; + + this.app.showLoadingIcon(); + + $.ajax({ + cache: false, + url: url, + contentType: "application/json", + type: "POST", + processData: false, + data: JSON.stringify({ + "column_id": columnId, + "position": position + }), + complete: function() { + self.app.hideLoadingIcon(); + } + }); +}; diff --git a/assets/js/src/CompareHoursColumnChart.js b/assets/js/src/CompareHoursColumnChart.js new file mode 100644 index 00000000..bed16144 --- /dev/null +++ b/assets/js/src/CompareHoursColumnChart.js @@ -0,0 +1,39 @@ +function CompareHoursColumnChart(app) { + this.app = app; +} + +CompareHoursColumnChart.prototype.execute = function() { + var metrics = $("#chart").data("metrics"); + var labelOpen = $("#chart").data("label-open"); + var labelClosed = $("#chart").data("label-closed"); + var spent = [$("#chart").data("label-spent")]; + var estimated = [$("#chart").data("label-estimated")]; + var categories = []; + + for (var status in metrics) { + spent.push(parseFloat(metrics[status].time_spent)); + estimated.push(parseFloat(metrics[status].time_estimated)); + categories.push(status == 'open' ? labelOpen : labelClosed); + } + + c3.generate({ + data: { + columns: [spent, estimated], + type: 'bar' + }, + bar: { + width: { + ratio: 0.2 + } + }, + axis: { + x: { + type: 'category', + categories: categories + } + }, + legend: { + show: true + } + }); +}; diff --git a/assets/js/src/Dropdown.js b/assets/js/src/Dropdown.js index e04603d8..61738da9 100644 --- a/assets/js/src/Dropdown.js +++ b/assets/js/src/Dropdown.js @@ -14,26 +14,53 @@ Dropdown.prototype.listen = function() { self.close(); var submenu = $(this).next('ul'); - var submenuHeight = 240; var offset = $(this).offset(); - var height = $(this).height(); // Clone the submenu outside of the column to avoid clipping issue with overflow $("body").append(jQuery("<div>", {"id": "dropdown"})); submenu.clone().appendTo("#dropdown"); var clone = $("#dropdown ul"); - clone.css('left', offset.left); + clone.addClass('dropdown-submenu-open'); + + var submenuHeight = clone.outerHeight(); + var submenuWidth = clone.outerWidth(); - if (offset.top + submenuHeight - $(window).scrollTop() > $(window).height()) { - clone.css('top', offset.top - submenuHeight - height); + if (offset.top + submenuHeight - $(window).scrollTop() < $(window).height() || $(window).scrollTop() + offset.top < submenuHeight) { + clone.css('top', offset.top + $(this).height()); } else { - clone.css('top', offset.top + height); + clone.css('top', offset.top - submenuHeight - 5); } - clone.addClass('dropdown-submenu-open'); + if (offset.left + submenuWidth > $(window).width()) { + clone.css('left', offset.left - submenuWidth + $(this).outerWidth()); + } + else { + clone.css('left', offset.left); + } }); + + $(document).on('click', '.dropdown-submenu-open li', function(e) { + if ($(e.target).is('li')) { + $(this).find('a:visible')[0].click(); // Calling native click() not the jQuery one + } + }); + + // User mention autocomplete + $('textarea[data-mention-search-url]').textcomplete([{ + match: /(^|\s)@(\w*)$/, + search: function (term, callback) { + var url = $('textarea[data-mention-search-url]').data('mention-search-url'); + $.getJSON(url, { q: term }) + .done(function (resp) { callback(resp); }) + .fail(function () { callback([]); }); + }, + replace: function (value) { + return '$1@' + value + ' '; + }, + cache: true + }], {className: "textarea-dropdown"}); }; Dropdown.prototype.close = function() { diff --git a/assets/js/src/FileUpload.js b/assets/js/src/FileUpload.js new file mode 100644 index 00000000..a8816bcd --- /dev/null +++ b/assets/js/src/FileUpload.js @@ -0,0 +1,124 @@ +function FileUpload(app) { + this.app = app; + this.files = []; + this.currentFile = 0; +} + +FileUpload.prototype.listen = function() { + var dropzone = document.getElementById("file-dropzone"); + var self = this; + + if (dropzone) { + dropzone.ondragover = dropzone.ondragenter = function(e) { + e.stopPropagation(); + e.preventDefault(); + } + + dropzone.ondrop = function(e) { + e.stopPropagation(); + e.preventDefault(); + self.files = e.dataTransfer.files; + self.show(); + $("#file-error-max-size").hide(); + } + + $(document).on("click", "#file-browser", function(e) { + e.preventDefault(); + $("#file-form-element").get(0).click(); + }); + + $(document).on("click", "#file-upload-button", function(e) { + e.preventDefault(); + self.currentFile = 0; + self.checkFiles(); + }); + + $("#file-form-element").change(function() { + self.files = document.getElementById("file-form-element").files; + self.show(); + $("#file-error-max-size").hide(); + }); + } +}; + +FileUpload.prototype.show = function() { + $("#file-list").remove(); + + if (this.files.length > 0) { + $("#file-upload-button").prop("disabled", false); + $("#file-dropzone-inner").hide(); + + var ul = jQuery("<ul>", {"id": "file-list"}); + + for (var i = 0; i < this.files.length; i++) { + var percentage = jQuery("<span>", {"id": "file-percentage-" + i}).append("(0%)"); + var progress = jQuery("<progress>", {"id": "file-progress-" + i, "value": 0}); + var li = jQuery("<li>", {"id": "file-label-" + i}) + .append(progress) + .append(" ") + .append(this.files[i].name) + .append(" ") + .append(percentage); + + ul.append(li); + } + + $("#file-dropzone").append(ul); + } else { + $("#file-dropzone-inner").show(); + } +}; + +FileUpload.prototype.checkFiles = function() { + var max = parseInt($("#file-dropzone").data("max-size")); + + for (var i = 0; i < this.files.length; i++) { + if (this.files[i].size > max) { + $("#file-error-max-size").show(); + $("#file-label-" + i).addClass("file-error"); + $("#file-upload-button").prop("disabled", true); + return; + } + } + + this.uploadFiles(); +}; + +FileUpload.prototype.uploadFiles = function() { + if (this.files.length > 0) { + this.uploadFile(this.files[this.currentFile]); + } +}; + +FileUpload.prototype.uploadFile = function(file) { + var dropzone = document.getElementById("file-dropzone"); + var url = dropzone.dataset.url; + var xhr = new XMLHttpRequest(); + var fd = new FormData(); + + xhr.upload.addEventListener("progress", this.updateProgress.bind(this)); + xhr.upload.addEventListener("load", this.transferComplete.bind(this)); + + xhr.open("POST", url, true); + fd.append('files[]', file); + xhr.send(fd); +}; + +FileUpload.prototype.updateProgress = function(e) { + if (e.lengthComputable) { + $("#file-progress-" + this.currentFile).val(e.loaded / e.total); + $("#file-percentage-" + this.currentFile).text('(' + Math.floor((e.loaded / e.total) * 100) + '%)'); + } +}; + +FileUpload.prototype.transferComplete = function() { + this.currentFile++; + + if (this.currentFile < this.files.length) { + this.uploadFile(this.files[this.currentFile]); + } else { + $("#file-upload-button").prop("disabled", true); + $("#file-upload-button").parent().hide(); + $("#file-done").show(); + } +}; diff --git a/assets/js/src/Gantt.js b/assets/js/src/Gantt.js index 380371d1..6f536552 100644 --- a/assets/js/src/Gantt.js +++ b/assets/js/src/Gantt.js @@ -185,7 +185,7 @@ Gantt.prototype.addBlocks = function(slider, start) { var block = jQuery("<div>", { "class": "ganttview-block tooltip" + (this.options.allowMoves ? " ganttview-block-movable" : ""), - "title": this.getBarTooltip(this.data[i]), + "title": this.getBarTooltip(series), "css": { "width": ((size * this.options.cellWidth) - 9) + "px", "margin-left": (offset * this.options.cellWidth) + "px" @@ -193,23 +193,25 @@ Gantt.prototype.addBlocks = function(slider, start) { }).append(text); if (size >= 2) { - text.append(this.data[i].progress); + text.append(series.progress); } - block.data("record", this.data[i]); - this.setBarColor(block, this.data[i]); - - block.append(jQuery("<div>", { - "css": { - "z-index": 0, - "position": "absolute", - "top": 0, - "bottom": 0, - "background-color": series.color.border, - "width": series.progress, - "opacity": 0.4 - } - })); + block.data("record", series); + this.setBarColor(block, series); + + if (series.progress != "0%") { + block.append(jQuery("<div>", { + "css": { + "z-index": 0, + "position": "absolute", + "top": 0, + "bottom": 0, + "background-color": series.color.border, + "width": series.progress, + "opacity": 0.4 + } + })); + } jQuery(rows[rowIdx]).append(block); rowIdx = rowIdx + 1; diff --git a/assets/js/src/Popover.js b/assets/js/src/Popover.js index 8d72dec8..5614de85 100644 --- a/assets/js/src/Popover.js +++ b/assets/js/src/Popover.js @@ -13,7 +13,7 @@ Popover.prototype.open = function(link) { self.app.dropdown.close(); $.get(link, function(content) { - $("body").append('<div id="popover-container"><div id="popover-content">' + content + '</div></div>'); + $("body").prepend('<div id="popover-container"><div id="popover-content">' + content + '</div></div>'); self.app.refresh(); self.router.dispatch(this.app); self.afterOpen(); @@ -35,10 +35,11 @@ Popover.prototype.onClick = function(e) { e.preventDefault(); e.stopPropagation(); - var link = e.target.getAttribute("href"); + var target = e.currentTarget || e.target; + var link = target.getAttribute("href"); if (! link) { - link = e.target.getAttribute("data-href"); + link = target.getAttribute("data-href"); } if (link) { @@ -55,26 +56,47 @@ Popover.prototype.listen = function() { Popover.prototype.afterOpen = function() { var self = this; - var taskForm = $("#task-form"); + var popoverForm = $("#popover-content .popover-form"); - if (taskForm) { - taskForm.on("submit", function(e) { + // Submit forms with Ajax request + if (popoverForm) { + popoverForm.on("submit", function(e) { e.preventDefault(); $.ajax({ type: "POST", - url: taskForm.attr("action"), - data: taskForm.serialize(), + url: popoverForm.attr("action"), + data: popoverForm.serialize(), success: function(data, textStatus, request) { - if (request.getResponseHeader("X-Ajax-Redirect")) { - window.location = request.getResponseHeader("X-Ajax-Redirect"); - } - else { - $("#popover-content").html(data); - self.afterOpen(); - } + self.afterSubmit(data, request, self); } }); }); } + + // Submit link with Ajax request + $(document).on("click", ".popover-link", function(e) { + e.preventDefault(); + + $.ajax({ + type: "GET", + url: $(this).attr("href"), + success: function(data, textStatus, request) { + self.afterSubmit(data, request, self); + } + }); + }); +}; + +Popover.prototype.afterSubmit = function(data, request, self) { + var redirect = request.getResponseHeader("X-Ajax-Redirect"); + + if (redirect) { + window.location = redirect === 'self' ? window.location.href.split("#")[0] : redirect; + } + else { + $("#popover-content").html(data); + $("#popover-content input[autofocus]").focus(); + self.afterOpen(); + } }; diff --git a/assets/js/src/Project.js b/assets/js/src/Project.js new file mode 100644 index 00000000..19941f03 --- /dev/null +++ b/assets/js/src/Project.js @@ -0,0 +1,28 @@ +function Project() { +} + +Project.prototype.listen = function() { + $('.project-change-role').on('change', function() { + $.ajax({ + cache: false, + url: $(this).data('url'), + contentType: "application/json", + type: "POST", + processData: false, + data: JSON.stringify({ + "id": $(this).data('id'), + "role": $(this).val() + }) + }); + }); + + $('#project-creation-form #form-src_project_id').on('change', function() { + var srcProjectId = $(this).val(); + + if (srcProjectId == 0) { + $(".project-creation-options").hide(); + } else { + $(".project-creation-options").show(); + } + }); +}; diff --git a/assets/js/src/Router.js b/assets/js/src/Router.js index 0c96262c..ab23c0fd 100644 --- a/assets/js/src/Router.js +++ b/assets/js/src/Router.js @@ -30,6 +30,7 @@ jQuery(document).ready(function() { router.addRoute('analytic-avg-time-column', AvgTimeColumnChart); router.addRoute('analytic-task-time-column', TaskTimeColumnChart); router.addRoute('analytic-lead-cycle-time', LeadCycleTimeChart); + router.addRoute('analytic-compare-hours', CompareHoursColumnChart); router.addRoute('gantt-chart', Gantt); router.dispatch(app); app.listen(); diff --git a/assets/js/src/Search.js b/assets/js/src/Search.js index de4d5959..4fbfee46 100644 --- a/assets/js/src/Search.js +++ b/assets/js/src/Search.js @@ -40,6 +40,15 @@ Search.prototype.listen = function() { Search.prototype.keyboardShortcuts = function() { var self = this; + // Switch view mode for projects: go to the overview page + Mousetrap.bind("v o", function(e) { + var link = $(".view-overview"); + + if (link.length) { + window.location = link.attr('href'); + } + }); + // Switch view mode for projects: go to the board Mousetrap.bind("v b", function(e) { var link = $(".view-board"); diff --git a/assets/js/src/Sidebar.js b/assets/js/src/Sidebar.js deleted file mode 100644 index 0794d6b3..00000000 --- a/assets/js/src/Sidebar.js +++ /dev/null @@ -1,25 +0,0 @@ -function Sidebar() { -} - -Sidebar.prototype.expand = function(e) { - e.preventDefault(); - $(".sidebar-container").removeClass("sidebar-collapsed"); - $(".sidebar-collapse").show(); - $(".sidebar h2").show(); - $(".sidebar ul").show(); - $(".sidebar-expand").hide(); -}; - -Sidebar.prototype.collapse = function(e) { - e.preventDefault(); - $(".sidebar-container").addClass("sidebar-collapsed"); - $(".sidebar-expand").show(); - $(".sidebar h2").hide(); - $(".sidebar ul").hide(); - $(".sidebar-collapse").hide(); -}; - -Sidebar.prototype.listen = function() { - $(document).on("click", ".sidebar-collapse", this.collapse); - $(document).on("click", ".sidebar-expand", this.expand); -}; diff --git a/assets/js/src/Subtask.js b/assets/js/src/Subtask.js new file mode 100644 index 00000000..7670095e --- /dev/null +++ b/assets/js/src/Subtask.js @@ -0,0 +1,94 @@ +function Subtask(app) { + this.app = app; +} + +Subtask.prototype.listen = function() { + var self = this; + + this.dragAndDrop(); + + $(document).on("click", ".subtask-toggle-status", function(e) { + e.preventDefault(); + var el = $(this); + + $.ajax({ + cache: false, + url: el.attr("href"), + success: function(data) { + if (el.hasClass("subtask-refresh-table")) { + $(".subtasks-table").replaceWith(data); + } else { + el.replaceWith(data); + } + + self.dragAndDrop(); + } + }); + }); + + $(document).on("click", ".subtask-toggle-timer", function(e) { + e.preventDefault(); + var el = $(this); + + $.ajax({ + cache: false, + url: el.attr("href"), + success: function(data) { + $(".subtasks-table").replaceWith(data); + self.dragAndDrop(); + } + }); + }); +}; + +Subtask.prototype.dragAndDrop = function() { + var self = this; + + $(".draggable-row-handle").mouseenter(function() { + $(this).parent().parent().addClass("draggable-item-hover"); + }).mouseleave(function() { + $(this).parent().parent().removeClass("draggable-item-hover"); + }); + + $(".subtasks-table tbody").sortable({ + forcePlaceholderSize: true, + handle: "td:first i", + helper: function(e, ui) { + ui.children().each(function() { + $(this).width($(this).width()); + }); + + return ui; + }, + stop: function(event, ui) { + var subtask = ui.item; + subtask.removeClass("draggable-item-selected"); + self.savePosition(subtask.data("subtask-id"), subtask.index() + 1); + }, + start: function(event, ui) { + ui.item.addClass("draggable-item-selected"); + } + }).disableSelection(); +}; + +Subtask.prototype.savePosition = function(subtaskId, position) { + var url = $(".subtasks-table").data("save-position-url"); + var self = this; + + this.app.showLoadingIcon(); + + $.ajax({ + cache: false, + url: url, + contentType: "application/json", + type: "POST", + processData: false, + data: JSON.stringify({ + "subtask_id": subtaskId, + "position": position + }), + complete: function() { + self.app.hideLoadingIcon(); + } + }); +}; diff --git a/assets/js/src/Swimlane.js b/assets/js/src/Swimlane.js index 340b40a0..60dbf41f 100644 --- a/assets/js/src/Swimlane.js +++ b/assets/js/src/Swimlane.js @@ -1,4 +1,5 @@ -function Swimlane() { +function Swimlane(app) { + this.app = app; } Swimlane.prototype.getStorageKey = function() { @@ -53,6 +54,7 @@ Swimlane.prototype.refresh = function() { Swimlane.prototype.listen = function() { var self = this; + self.dragAndDrop(); $(document).on('click', ".board-swimlane-toggle", function(e) { e.preventDefault(); @@ -67,3 +69,55 @@ Swimlane.prototype.listen = function() { } }); }; + +Swimlane.prototype.dragAndDrop = function() { + var self = this; + + $(".draggable-row-handle").mouseenter(function() { + $(this).parent().parent().addClass("draggable-item-hover"); + }).mouseleave(function() { + $(this).parent().parent().removeClass("draggable-item-hover"); + }); + + $(".swimlanes-table tbody").sortable({ + forcePlaceholderSize: true, + handle: "td:first i", + helper: function(e, ui) { + ui.children().each(function() { + $(this).width($(this).width()); + }); + + return ui; + }, + stop: function(event, ui) { + var swimlane = ui.item; + swimlane.removeClass("draggable-item-selected"); + self.savePosition(swimlane.data("swimlane-id"), swimlane.index() + 1); + }, + start: function(event, ui) { + ui.item.addClass("draggable-item-selected"); + } + }).disableSelection(); +}; + +Swimlane.prototype.savePosition = function(swimlaneId, position) { + var url = $(".swimlanes-table").data("save-position-url"); + var self = this; + + this.app.showLoadingIcon(); + + $.ajax({ + cache: false, + url: url, + contentType: "application/json", + type: "POST", + processData: false, + data: JSON.stringify({ + "swimlane_id": swimlaneId, + "position": position + }), + complete: function() { + self.app.hideLoadingIcon(); + } + }); +}; diff --git a/assets/js/src/Task.js b/assets/js/src/Task.js index b3dc1b63..955a5752 100644 --- a/assets/js/src/Task.js +++ b/assets/js/src/Task.js @@ -1,10 +1,51 @@ -function Task() { +function Task(app) { + this.app = app; } Task.prototype.listen = function() { + var self = this; + var reloadingProjectId = 0; + + // Change color $(document).on("click", ".color-square", function() { $(".color-square-selected").removeClass("color-square-selected"); $(this).addClass("color-square-selected"); $("#form-color_id").val($(this).data("color-id")); }); + + // Assign to me + $(document).on("click", ".assign-me", function(e) { + e.preventDefault(); + + var currentId = $(this).data("current-id"); + var dropdownId = "#" + $(this).data("target-id"); + + if ($(dropdownId + ' option[value=' + currentId + ']').length) { + $(dropdownId).val(currentId); + } + }); + + // Reload page when a destination project is changed + $(document).on("change", "select.task-reload-project-destination", function() { + if (reloadingProjectId > 0) { + $(this).val(reloadingProjectId); + } + else { + reloadingProjectId = $(this).val(); + var url = $(this).data("redirect").replace(/PROJECT_ID/g, reloadingProjectId); + + $(".loading-icon").show(); + + $.ajax({ + type: "GET", + url: url, + success: function(data, textStatus, request) { + reloadingProjectId = 0; + $(".loading-icon").hide(); + + self.app.popover.afterSubmit(data, request, self.app.popover); + } + }); + } + }); }; diff --git a/assets/js/src/Tooltip.js b/assets/js/src/Tooltip.js index 0ec8b268..f3ef55f9 100644 --- a/assets/js/src/Tooltip.js +++ b/assets/js/src/Tooltip.js @@ -48,21 +48,6 @@ Tooltip.prototype.listen = function() { var position = $(_this).tooltip("option", "position"); position.of = $(_this); tooltip.position(position); - - // Toggle subtasks status - $('#tooltip-subtasks a').not(".popover").click(function(e) { - - e.preventDefault(); - e.stopPropagation(); - - if ($(this).hasClass("popover-subtask-restriction")) { - self.app.popover.open($(this).attr('href')); - $(_this).tooltip('close'); - } - else { - $.get($(this).attr('href'), setTooltipContent); - } - }); }); return '<i class="fa fa-spinner fa-spin"></i>'; |