diff --git a/VERSION b/VERSION index 1474d00f..4f969668 100644 --- a/VERSION +++ b/VERSION @@ -1 +1,11 @@ -v0.2.0 +v0.2.1 + +Changelog + + * Supports nginx (@alex3305) + * Supports use in Docker (Ubuntu Trusty & nginx - @alex3305) + * Build scripts executable by default (@niedzielski) + * Automatic Actions now allow "Unassigned" and "Uncategorized" for changing assignee or category (Issue #5) + * Links in item descriptions open in new tab (Issue #18) + * Lanes are now Columns to match common Kanban terminology (Issue #4) + * Any exception in API is handled and returns a 503 (inspired by @amalfra) diff --git a/api/helpers.php b/api/helpers.php index 55f0f036..30a27d04 100644 --- a/api/helpers.php +++ b/api/helpers.php @@ -1,19 +1,20 @@ $value) { - if (substr($name, 0, 5) == 'HTTP_') { - $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value; - } - } - - return $headers; - } -} +if (!function_exists('getallheaders')) { + function getallheaders() { + $headers = ''; + + foreach ($_SERVER as $name => $value) { + if (substr($name, 0, 5) == 'HTTP_') { + $headers[str_replace(' ', '-', ucwords(strtolower( + str_replace('_', ' ', substr($name, 5)) + )))] = $value; + } + } + + return $headers; + } +} // Log an action. If $itemId is set, it is an item action. function logAction($comment, $oldValue, $newValue, $itemId=null) { @@ -344,12 +345,14 @@ function runAutoActions(&$item) { } break; case 1: // Item assigned to user - if ($item->assignee == $action->secondaryId) { + if ($item->assignee == $action->secondaryId || + ($action->secondaryId == 0 && $item->assignee == null)) { updateItemFromAction($item, $action); } break; case 2: // Item assigned to category - if ($item->category == $action->secondaryId) { + if ($item->category == $action->secondaryId || + ($action->secondaryId == 0 && $item->category == null)) { updateItemFromAction($item, $action); } break; diff --git a/js/controllers/settingsAutoActions.js b/js/controllers/settingsAutoActions.js index 33b3cd3b..db7a1674 100644 --- a/js/controllers/settingsAutoActions.js +++ b/js/controllers/settingsAutoActions.js @@ -4,6 +4,10 @@ function ($scope, $interval, BoardService) { $scope.loadingActions = true; $scope.actions = []; + $scope.secondarySelection = []; + $scope.boardCategories = [{ id: 0, name: 'Uncategorized' }]; + $scope.userList = [{ id: 0, name: 'Unassigned', username: 'Unassigned' }]; + $scope.actionData = { isSaving: false, board: null, @@ -17,58 +21,72 @@ function ($scope, $interval, BoardService) { }; $scope.actionDeleting = []; + $scope.actionTypes = [ + { id: 0, action: 'Set item color' }, + { id: 1, action: 'Set item category'}, + { id: 2, action: 'Set item assignee' }, + { id: 3, action: 'Clear item due date' } + ]; $scope.actionOptions = { triggers: [ { id: 0, - trigger: 'Item moves to lane', - actions: [ - { id: 0, action: 'Set item color' }, - { id: 1, action: 'Set item category'}, - { id: 2, action: 'Set item assignee' }, - { id: 3, action: 'Clear item due date' } - ] + trigger: 'Item moves to lane' }, { id: 1, - trigger: 'Item assigned to user', - actions: [ - { id: 0, action: 'Set item color' }, - { id: 1, action: 'Set item category'}, - { id: 3, action: 'Clear item due date' } - ] + trigger: 'Item assigned to user' }, { id: 2, - trigger: 'Item set to category', - actions: [ - { id: 0, action: 'Set item color' }, - { id: 2, action: 'Set item assignee' }, - { id: 3, action: 'Clear item due date' } - ] + trigger: 'Item set to category' } ] }; var getBoardData = function(boardId) { - if (null === boardId || undefined === boardId) - { - return; - } + if (null === boardId || undefined === boardId) + { + return; + } + + var boardData; + $scope.boards.forEach(function(board) { + if (board.id === boardId) { + boardData = board; + } + }); + + return boardData; + }, + + getCategories = function(boardData) { + var categories = [{ id: '0', name: 'Uncategorized' }]; - var boardData; - $scope.boards.forEach(function(board) { - if (board.id === boardId) { - boardData = board; + if (boardData) { + boardData.ownCategory.forEach(function(category) { + categories.push(category); + }); } - }); + return categories; + }, - return boardData; - }, + getUsers = function(boardData) { + var userList = [{ id: '0', name: 'Unassigned', username: 'Unassigned' }]; + + if (boardData) { + boardData.sharedUser.forEach(function(user) { + userList.push({ id: user.id, name: user.username }); + }); + } + return userList; + }, getSecondaryText = function(action) { var text = ': ', - actionBoard = getBoardData(action.board_id); + actionBoard = getBoardData(action.board_id), + boardCategories = getBoardData(actionBoard), + userList = getUsers(actionBoard); switch(parseInt(action.trigger_id)) { case 0: // Lane @@ -79,14 +97,14 @@ function ($scope, $interval, BoardService) { }); break; case 1: // User - actionBoard.sharedUser.forEach(function(user) { + userList.forEach(function(user) { if (user.id === action.secondary_id) { - text += user.username; + text += user.name; } }); break; case 2: // Category - actionBoard.ownCategory.forEach(function(category) { + boardCategories.forEach(function(category) { if (category.id === action.secondary_id) { text += category.name; } @@ -98,41 +116,44 @@ function ($scope, $interval, BoardService) { getActionText = function(action) { var text = '', - actionBoard = getBoardData(action.board_id); + actionBoard = getBoardData(action.board_id), + boardCategories = getCategories(actionBoard), + userList = getUsers(actionBoard); + switch(parseInt(action.action_id)) { case 0: // Color text = ': ' + action.color; break; case 1: // Category - actionBoard.ownCategory.forEach(function(category) { + boardCategories.forEach(function(category) { if (category.id === action.category_id) { text = ': ' + category.name; } }); break; case 2: // Assignee - actionBoard.sharedUser.forEach(function(user) { + userList.forEach(function(user) { if (user.id === action.assignee_id) { - text = ': ' + user.username; + text = ': ' + user.name; } }); break; } return text; - }; + }, - $scope.updateAutoActions = function(actions) { + updateAutoActions = function(actions) { if (!actions) { return; } - var mappedActions = []; + var mappedActions = []; actions.forEach(function(action) { mappedActions.push({ id: action.id, board: $scope.boardLookup[action.board_id], trigger: $scope.actionOptions.triggers[action.trigger_id].trigger + getSecondaryText(action), - action: $scope.actionOptions.triggers[0].actions[action.action_id].action + getActionText(action) + action: $scope.actionTypes[action.action_id].action + getActionText(action) }); }); @@ -142,8 +163,9 @@ function ($scope, $interval, BoardService) { $scope.loadActions = function() { BoardService.getAutoActions() .success(function(data) { - $scope.updateAutoActions(data.data); + updateAutoActions(data.data); $scope.loadingActions = false; + $scope.loadActions(); }); }; @@ -157,8 +179,12 @@ function ($scope, $interval, BoardService) { $scope.addAction = function() { if ($scope.actionData.secondary === null || ($scope.actionData.action !== 3 && - ($scope.actionData.color === null && $scope.actionData.category === null && $scope.actionData.assignee === null))) { - $scope.alerts.showAlert({ type: 'error', text: 'One or more required fields are not entered. Automatic Action not added.' }); + ($scope.actionData.color === null && $scope.actionData.category === null && + $scope.actionData.assignee === null))) { + $scope.alerts.showAlert({ + type: 'error', + text: 'One or more required fields are not entered. Automatic Action not added.' + }); return; } @@ -183,17 +209,14 @@ function ($scope, $interval, BoardService) { }); }; - $scope.secondarySelection = []; $scope.updateSecondary = function() { $scope.secondarySelection = []; $scope.actionData.secondary = null; $scope.actionData.action = 0; var boardData = getBoardData($scope.actionData.board); - if (boardData) { - $scope.boardCategories = boardData.ownCategory; - $scope.userList = boardData.sharedUser; - } + $scope.boardCategories = getCategories(boardData); + $scope.userList = getUsers(boardData); if (boardData) { switch($scope.actionData.trigger) { @@ -201,13 +224,10 @@ function ($scope, $interval, BoardService) { $scope.secondarySelection = boardData.ownLane; break; case 1: - $scope.secondarySelection = boardData.sharedUser; - $scope.secondarySelection.forEach(function(user) { - user.name = user.username; - }); + $scope.secondarySelection = $scope.userList; break; case 2: - $scope.secondarySelection = boardData.ownCategory; + $scope.secondarySelection = $scope.boardCategories; break; } } diff --git a/partials/settingsAutoActions.html b/partials/settingsAutoActions.html index 35ab81a9..ff6b37eb 100644 --- a/partials/settingsAutoActions.html +++ b/partials/settingsAutoActions.html @@ -60,7 +60,7 @@