Automatic actions allow 'Uncategorized' and 'Unassigned'. Resolves #5.
This commit is contained in:
parent
0f3c215a42
commit
8e893b22aa
12
VERSION
12
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)
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
@ -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
|
||||||
|
Reference in New Issue
Block a user