Automatic actions allow 'Uncategorized' and 'Unassigned'. Resolves #5.

This commit is contained in:
kiswa 2014-10-20 18:23:44 -04:00
parent 0f3c215a42
commit 8e893b22aa
5 changed files with 111 additions and 78 deletions

12
VERSION
View File

@ -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)

View File

@ -1,5 +1,4 @@
<?php <?php
// Patch for when using nginx instead of apache, source: http://php.net/manual/en/function.getallheaders.php#84262 // Patch for when using nginx instead of apache, source: http://php.net/manual/en/function.getallheaders.php#84262
if (!function_exists('getallheaders')) { if (!function_exists('getallheaders')) {
function getallheaders() { function getallheaders() {
@ -7,7 +6,9 @@ if (!function_exists('getallheaders')) {
foreach ($_SERVER as $name => $value) { foreach ($_SERVER as $name => $value) {
if (substr($name, 0, 5) == 'HTTP_') { if (substr($name, 0, 5) == 'HTTP_') {
$headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value; $headers[str_replace(' ', '-', ucwords(strtolower(
str_replace('_', ' ', substr($name, 5))
)))] = $value;
} }
} }
@ -344,12 +345,14 @@ function runAutoActions(&$item) {
} }
break; break;
case 1: // Item assigned to user 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); updateItemFromAction($item, $action);
} }
break; break;
case 2: // Item assigned to category 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); updateItemFromAction($item, $action);
} }
break; break;

View File

@ -4,6 +4,10 @@ function ($scope, $interval, BoardService) {
$scope.loadingActions = true; $scope.loadingActions = true;
$scope.actions = []; $scope.actions = [];
$scope.secondarySelection = [];
$scope.boardCategories = [{ id: 0, name: 'Uncategorized' }];
$scope.userList = [{ id: 0, name: 'Unassigned', username: 'Unassigned' }];
$scope.actionData = { $scope.actionData = {
isSaving: false, isSaving: false,
board: null, board: null,
@ -17,35 +21,25 @@ function ($scope, $interval, BoardService) {
}; };
$scope.actionDeleting = []; $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 = { $scope.actionOptions = {
triggers: [ triggers: [
{ {
id: 0, id: 0,
trigger: 'Item moves to lane', 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' }
]
}, },
{ {
id: 1, id: 1,
trigger: 'Item assigned to user', 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' }
]
}, },
{ {
id: 2, id: 2,
trigger: 'Item set to category', 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' }
]
} }
] ]
}; };
@ -66,9 +60,33 @@ function ($scope, $interval, BoardService) {
return boardData; return boardData;
}, },
getCategories = function(boardData) {
var categories = [{ id: '0', name: 'Uncategorized' }];
if (boardData) {
boardData.ownCategory.forEach(function(category) {
categories.push(category);
});
}
return categories;
},
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) { getSecondaryText = function(action) {
var text = ': ', var text = ': ',
actionBoard = getBoardData(action.board_id); actionBoard = getBoardData(action.board_id),
boardCategories = getBoardData(actionBoard),
userList = getUsers(actionBoard);
switch(parseInt(action.trigger_id)) { switch(parseInt(action.trigger_id)) {
case 0: // Lane case 0: // Lane
@ -79,14 +97,14 @@ function ($scope, $interval, BoardService) {
}); });
break; break;
case 1: // User case 1: // User
actionBoard.sharedUser.forEach(function(user) { userList.forEach(function(user) {
if (user.id === action.secondary_id) { if (user.id === action.secondary_id) {
text += user.username; text += user.name;
} }
}); });
break; break;
case 2: // Category case 2: // Category
actionBoard.ownCategory.forEach(function(category) { boardCategories.forEach(function(category) {
if (category.id === action.secondary_id) { if (category.id === action.secondary_id) {
text += category.name; text += category.name;
} }
@ -98,41 +116,44 @@ function ($scope, $interval, BoardService) {
getActionText = function(action) { getActionText = function(action) {
var text = '', var text = '',
actionBoard = getBoardData(action.board_id); actionBoard = getBoardData(action.board_id),
boardCategories = getCategories(actionBoard),
userList = getUsers(actionBoard);
switch(parseInt(action.action_id)) { switch(parseInt(action.action_id)) {
case 0: // Color case 0: // Color
text = ': ' + action.color; text = ': ' + action.color;
break; break;
case 1: // Category case 1: // Category
actionBoard.ownCategory.forEach(function(category) { boardCategories.forEach(function(category) {
if (category.id === action.category_id) { if (category.id === action.category_id) {
text = ': ' + category.name; text = ': ' + category.name;
} }
}); });
break; break;
case 2: // Assignee case 2: // Assignee
actionBoard.sharedUser.forEach(function(user) { userList.forEach(function(user) {
if (user.id === action.assignee_id) { if (user.id === action.assignee_id) {
text = ': ' + user.username; text = ': ' + user.name;
} }
}); });
break; break;
} }
return text; return text;
}; },
$scope.updateAutoActions = function(actions) { updateAutoActions = function(actions) {
if (!actions) { if (!actions) {
return; return;
} }
var mappedActions = [];
var mappedActions = [];
actions.forEach(function(action) { actions.forEach(function(action) {
mappedActions.push({ mappedActions.push({
id: action.id, id: action.id,
board: $scope.boardLookup[action.board_id], board: $scope.boardLookup[action.board_id],
trigger: $scope.actionOptions.triggers[action.trigger_id].trigger + getSecondaryText(action), 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() { $scope.loadActions = function() {
BoardService.getAutoActions() BoardService.getAutoActions()
.success(function(data) { .success(function(data) {
$scope.updateAutoActions(data.data); updateAutoActions(data.data);
$scope.loadingActions = false; $scope.loadingActions = false;
$scope.loadActions();
}); });
}; };
@ -157,8 +179,12 @@ function ($scope, $interval, BoardService) {
$scope.addAction = function() { $scope.addAction = function() {
if ($scope.actionData.secondary === null || if ($scope.actionData.secondary === null ||
($scope.actionData.action !== 3 && ($scope.actionData.action !== 3 &&
($scope.actionData.color === null && $scope.actionData.category === null && $scope.actionData.assignee === null))) { ($scope.actionData.color === null && $scope.actionData.category === null &&
$scope.alerts.showAlert({ type: 'error', text: 'One or more required fields are not entered. Automatic Action not added.' }); $scope.actionData.assignee === null))) {
$scope.alerts.showAlert({
type: 'error',
text: 'One or more required fields are not entered. Automatic Action not added.'
});
return; return;
} }
@ -183,17 +209,14 @@ function ($scope, $interval, BoardService) {
}); });
}; };
$scope.secondarySelection = [];
$scope.updateSecondary = function() { $scope.updateSecondary = function() {
$scope.secondarySelection = []; $scope.secondarySelection = [];
$scope.actionData.secondary = null; $scope.actionData.secondary = null;
$scope.actionData.action = 0; $scope.actionData.action = 0;
var boardData = getBoardData($scope.actionData.board); var boardData = getBoardData($scope.actionData.board);
if (boardData) { $scope.boardCategories = getCategories(boardData);
$scope.boardCategories = boardData.ownCategory; $scope.userList = getUsers(boardData);
$scope.userList = boardData.sharedUser;
}
if (boardData) { if (boardData) {
switch($scope.actionData.trigger) { switch($scope.actionData.trigger) {
@ -201,13 +224,10 @@ function ($scope, $interval, BoardService) {
$scope.secondarySelection = boardData.ownLane; $scope.secondarySelection = boardData.ownLane;
break; break;
case 1: case 1:
$scope.secondarySelection = boardData.sharedUser; $scope.secondarySelection = $scope.userList;
$scope.secondarySelection.forEach(function(user) {
user.name = user.username;
});
break; break;
case 2: case 2:
$scope.secondarySelection = boardData.ownCategory; $scope.secondarySelection = $scope.boardCategories;
break; break;
} }
} }

View File

@ -60,7 +60,7 @@
<div class="form-group col-md-4"> <div class="form-group col-md-4">
<label for="triggerSelect">Select Action:</label> <label for="triggerSelect">Select Action:</label>
<select class="form-control" id="triggerSelect" data-ng-model="actionData.action" <select class="form-control" id="triggerSelect" data-ng-model="actionData.action"
data-ng-options="action.id as action.action for action in actionOptions.triggers[actionData.trigger].actions" data-ng-options="action.id as action.action for action in actionTypes"
data-ng-disabled="null === actionData.board" data-ng-disabled="null === actionData.board"
data-ng-change="resetActionSecondary()"> data-ng-change="resetActionSecondary()">
</select> </select>
@ -83,7 +83,7 @@
<option value="">Select Category</option> <option value="">Select Category</option>
</select> </select>
<select class="form-control" data-ng-model="actionData.assignee" <select class="form-control" data-ng-model="actionData.assignee"
data-ng-options="user.id as user.username for user in userList" data-ng-options="user.id as user.name for user in userList"
data-ng-disabled="null === actionData.board" data-ng-disabled="null === actionData.board"
data-ng-if="actionData.action === 2"> data-ng-if="actionData.action === 2">
<option value="">Select Assignee</option> <option value="">Select Assignee</option>

View File

@ -97,11 +97,11 @@ Count was done from parent directory of TaskBoard as `./cloc-1.62.pl TaskBoard -
Language | Files | Blank Lines | Comments | Code Language | Files | Blank Lines | Comments | Code
-------------------|-------:|-------------:|---------:|---------: -------------------|-------:|-------------:|---------:|---------:
Javascript | 22 | 181 | 34 | 1840 Javascript | 22 | 187 | 34 | 1853
HTML | 17 | 7 | 8 | 936 HTML | 17 | 7 | 8 | 936
PHP | 6 | 143 | 55 | 834 PHP | 6 | 150 | 57 | 849
CSS | 1 | 12 | 33 | 609 CSS | 1 | 12 | 33 | 609
Bourne Again Shell | 4 | 10 | 0 | 53 Bourne Again Shell | 4 | 10 | 0 | 53
__SUM:__ | __50__ | __353__ | __130__ | __4272__ __SUM:__ | __50__ | __366__ | __132__ | __4300__
Counts Last Updated: Oct. 18, 2014 Counts Last Updated: Oct. 18, 2014