summaryrefslogtreecommitdiff
path: root/assets/js/components
diff options
context:
space:
mode:
Diffstat (limited to 'assets/js/components')
-rw-r--r--assets/js/components/autocomplete-email.js21
-rw-r--r--assets/js/components/board-task-click.js4
-rw-r--r--assets/js/components/calendar.js65
-rw-r--r--assets/js/components/external-task-view.js2
-rw-r--r--assets/js/components/file-upload.js20
-rw-r--r--assets/js/components/keyboard-shortcuts.js8
-rw-r--r--assets/js/components/select-dropdown-autocomplete.js3
-rw-r--r--assets/js/components/subtask-drag-and-drop.js44
-rw-r--r--assets/js/components/subtask-toggle-status.js35
-rw-r--r--assets/js/components/template.js11
10 files changed, 135 insertions, 78 deletions
diff --git a/assets/js/components/autocomplete-email.js b/assets/js/components/autocomplete-email.js
new file mode 100644
index 00000000..9d337e03
--- /dev/null
+++ b/assets/js/components/autocomplete-email.js
@@ -0,0 +1,21 @@
+KB.onClick('.js-autocomplete-email', function (e) {
+ var email = KB.dom(e.target).data('email');
+ var emailField = KB.find('.js-mail-form input[type="email"]');
+
+ if (email && emailField) {
+ emailField.build().value = email;
+ }
+
+ _KB.controllers.Dropdown.close();
+});
+
+KB.onClick('.js-autocomplete-subject', function (e) {
+ var subject = KB.dom(e.target).data('subject');
+ var subjectField = KB.find('.js-mail-form input[name="subject"]');
+
+ if (subject && subjectField) {
+ subjectField.build().value = subject;
+ }
+
+ _KB.controllers.Dropdown.close();
+});
diff --git a/assets/js/components/board-task-click.js b/assets/js/components/board-task-click.js
index fa530c38..a8c193ed 100644
--- a/assets/js/components/board-task-click.js
+++ b/assets/js/components/board-task-click.js
@@ -24,6 +24,6 @@
}
}
- KB.onClick('.task-board *', redirectToTaskView);
- KB.onClick('.task-board-change-assignee *', openEditTask);
+ KB.onClick('.task-board *', redirectToTaskView, true);
+ KB.onClick('.task-board-change-assignee *', openEditTask, true);
}());
diff --git a/assets/js/components/calendar.js b/assets/js/components/calendar.js
deleted file mode 100644
index ed6916b2..00000000
--- a/assets/js/components/calendar.js
+++ /dev/null
@@ -1,65 +0,0 @@
-KB.component('calendar', function (containerElement, options) {
- var modeMapping = { // Let's have bookable pretty mode names
- month: 'month',
- week: 'agendaWeek',
- day: 'agendaDay'
- };
-
- this.render = function () {
- var calendar = $(containerElement);
- var mode = 'month';
- if (window.location.hash) { // Check if hash contains mode
- var hashMode = window.location.hash.substr(1);
- mode = modeMapping[hashMode] || mode;
- }
-
- calendar.fullCalendar({
- locale: $("body").data("js-lang"),
- editable: true,
- eventLimit: true,
- defaultView: mode,
- header: {
- left: 'prev,next today',
- center: 'title',
- right: 'month,agendaWeek,agendaDay'
- },
- eventDrop: function(event) {
- $.ajax({
- cache: false,
- url: options.saveUrl,
- contentType: "application/json",
- type: "POST",
- processData: false,
- data: JSON.stringify({
- "task_id": event.id,
- "date_due": event.start.format()
- })
- });
- },
- viewRender: function(view) {
- // Map view.name back and update location.hash
- for (var id in modeMapping) {
- if (modeMapping[id] === view.name) { // Found
- window.location.hash = id;
- break;
- }
- }
- var url = options.checkUrl;
- var params = {
- "start": calendar.fullCalendar('getView').start.format(),
- "end": calendar.fullCalendar('getView').end.format()
- };
-
- for (var key in params) {
- url += "&" + key + "=" + params[key];
- }
-
- $.getJSON(url, function(events) {
- calendar.fullCalendar('removeEvents');
- calendar.fullCalendar('addEventSource', events);
- calendar.fullCalendar('rerenderEvents');
- });
- }
- });
- };
-});
diff --git a/assets/js/components/external-task-view.js b/assets/js/components/external-task-view.js
index d402640b..b5b8f77a 100644
--- a/assets/js/components/external-task-view.js
+++ b/assets/js/components/external-task-view.js
@@ -1,6 +1,8 @@
KB.component('external-task-view', function (containerElement, options) {
this.render = function () {
+ KB.dom(containerElement).html('<div id="external-task-view"><i class="fa fa-spinner fa-2x fa-pulse"></div>');
+
$.ajax({
cache: false,
url: options.url,
diff --git a/assets/js/components/file-upload.js b/assets/js/components/file-upload.js
index ccc57ad7..3786077d 100644
--- a/assets/js/components/file-upload.js
+++ b/assets/js/components/file-upload.js
@@ -62,7 +62,9 @@ KB.component('file-upload', function (containerElement, options) {
}
function onFileChange() {
- files = inputFileElement.files;
+ for (var i = 0; i < inputFileElement.files.length; i++) {
+ files.push(inputFileElement.files[i]);
+ }
showFiles();
}
@@ -81,7 +83,10 @@ KB.component('file-upload', function (containerElement, options) {
e.stopPropagation();
e.preventDefault();
- files = e.dataTransfer.files;
+ for (var i = 0; i < e.dataTransfer.files.length; i++) {
+ files.push(e.dataTransfer.files[i]);
+ }
+
showFiles();
}
@@ -157,8 +162,19 @@ KB.component('file-upload', function (containerElement, options) {
.text('(0%)')
.build();
+ var deleteElement = KB.dom('span')
+ .attr('id', 'file-delete-' + index)
+ .html('<a href="#"><i class="fa fa-trash fa-fw"></i></a>')
+ .on('click', function () {
+ files.splice(index, 1);
+ KB.find('#file-item-' + index).remove();
+ showFiles();
+ })
+ .build();
+
var itemElement = KB.dom('li')
.attr('id', 'file-item-' + index)
+ .add(deleteElement)
.add(progressElement)
.text(' ' + files[index].name + ' ')
.add(percentageElement);
diff --git a/assets/js/components/keyboard-shortcuts.js b/assets/js/components/keyboard-shortcuts.js
index cffcd790..02d62119 100644
--- a/assets/js/components/keyboard-shortcuts.js
+++ b/assets/js/components/keyboard-shortcuts.js
@@ -117,15 +117,7 @@ KB.keyboardShortcuts = function () {
goToLink('a.view-board');
});
- KB.onKey('v+c', function () {
- goToLink('a.view-calendar');
- });
-
KB.onKey('v+l', function () {
goToLink('a.view-listing');
});
-
- KB.onKey('v+g', function () {
- goToLink('a.view-gantt');
- });
};
diff --git a/assets/js/components/select-dropdown-autocomplete.js b/assets/js/components/select-dropdown-autocomplete.js
index 188dd5e9..8d1cd13d 100644
--- a/assets/js/components/select-dropdown-autocomplete.js
+++ b/assets/js/components/select-dropdown-autocomplete.js
@@ -183,6 +183,7 @@ KB.component('select-dropdown-autocomplete', function(containerElement, options)
function buildDropdownMenu() {
var itemElements = filterItems(inputElement.value, buildItems(options.items));
var componentPosition = componentElement.getBoundingClientRect();
+ var windowPosition = document.body.scrollTop || document.documentElement.scrollTop;
if (itemElements.length === 0) {
return null;
@@ -190,7 +191,7 @@ KB.component('select-dropdown-autocomplete', function(containerElement, options)
return KB.dom('ul')
.attr('id', 'select-dropdown-menu')
- .style('top', (document.body.scrollTop + componentPosition.bottom) + 'px')
+ .style('top', (windowPosition + componentPosition.bottom) + 'px')
.style('left', componentPosition.left + 'px')
.style('width', componentPosition.width + 'px')
.style('maxHeight', (window.innerHeight - componentPosition.bottom - 20) + 'px')
diff --git a/assets/js/components/subtask-drag-and-drop.js b/assets/js/components/subtask-drag-and-drop.js
new file mode 100644
index 00000000..f704376a
--- /dev/null
+++ b/assets/js/components/subtask-drag-and-drop.js
@@ -0,0 +1,44 @@
+KB.on('dom.ready', function() {
+
+ function savePosition(subtaskId, position) {
+ var url = $(".subtasks-table").data("save-position-url");
+
+ $.ajax({
+ cache: false,
+ url: url,
+ contentType: "application/json",
+ type: "POST",
+ processData: false,
+ data: JSON.stringify({
+ "subtask_id": subtaskId,
+ "position": position
+ })
+ });
+ }
+
+ $(".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");
+ savePosition(subtask.data("subtask-id"), subtask.index() + 1);
+ },
+ start: function(event, ui) {
+ ui.item.addClass("draggable-item-selected");
+ }
+ }).disableSelection();
+});
diff --git a/assets/js/components/subtask-toggle-status.js b/assets/js/components/subtask-toggle-status.js
new file mode 100644
index 00000000..3014adfa
--- /dev/null
+++ b/assets/js/components/subtask-toggle-status.js
@@ -0,0 +1,35 @@
+KB.on('dom.ready', function () {
+ $(document).on('click', '.js-subtask-toggle-status', function(e) {
+ var el = $(this);
+ var url = el.attr('href');
+
+ e.preventDefault();
+
+ $.ajax({
+ cache: false,
+ url: url,
+ success: function(data) {
+ if (url.indexOf('fragment=table') != -1) {
+ $('.subtasks-table').replaceWith(data);
+ } else if (url.indexOf('fragment=rows') != -1) {
+ $(el).closest('.task-list-subtasks').replaceWith(data);
+ } else {
+ $(el).closest('.subtask-title').replaceWith(data);
+ }
+ }
+ });
+ });
+
+ $(document).on('click', '.js-subtask-toggle-timer', function(e) {
+ var el = $(this);
+ e.preventDefault();
+
+ $.ajax({
+ cache: false,
+ url: el.attr('href'),
+ success: function(data) {
+ $(el).closest('.subtask-time-tracking').replaceWith(data);
+ }
+ });
+ });
+});
diff --git a/assets/js/components/template.js b/assets/js/components/template.js
new file mode 100644
index 00000000..c9ca9ab6
--- /dev/null
+++ b/assets/js/components/template.js
@@ -0,0 +1,11 @@
+KB.onClick('.js-template', function (e) {
+ var template = KB.dom(e.target).data('template');
+ var target = KB.dom(e.target).data('templateTarget');
+ var targetField = KB.find(target);
+
+ if (targetField) {
+ targetField.build().value = template;
+ }
+
+ _KB.controllers.Dropdown.close();
+}); \ No newline at end of file