Rework the task list layout
This commit reworks the task list layout so that tasks are arranged by project and branch. The rows in the list are also modified to make space for the addition of new fields in future. One effect of this is that task notes can now be viewed and edited inline. Change-Id: I8694c906c0a5f3567331574ec3a516dec586414a
This commit is contained in:
parent
275780922d
commit
cfc3211185
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Codethink Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The angular resource abstraction that allows us to access branches and their
|
||||
* details.
|
||||
*
|
||||
* @see ResourceFactory
|
||||
* @author Adam Coldrick
|
||||
*/
|
||||
angular.module('sb.services').factory('Branch',
|
||||
function (ResourceFactory) {
|
||||
'use strict';
|
||||
|
||||
var resource = ResourceFactory.build(
|
||||
'/branches/:id',
|
||||
'/branches/search',
|
||||
{id: '@id'}
|
||||
);
|
||||
|
||||
ResourceFactory.applySearch(
|
||||
'Branch',
|
||||
resource,
|
||||
'name',
|
||||
{Text: 'q'}
|
||||
);
|
||||
|
||||
return resource;
|
||||
});
|
|
@ -20,9 +20,9 @@
|
|||
angular.module('sb.story').controller('StoryDetailController',
|
||||
function ($log, $rootScope, $scope, $state, $stateParams, $modal, Session,
|
||||
Preference, TimelineEvent, Comment, TimelineEventTypes, story,
|
||||
Story, creator, tasks, Task, DSCacheFactory, User, $q,
|
||||
storyboardApiBase, SessionModalService, moment, $document,
|
||||
$anchorScroll, $timeout, $location, currentUser,
|
||||
Story, Project, Branch, creator, tasks, Task, DSCacheFactory,
|
||||
User, $q, storyboardApiBase, SessionModalService, moment,
|
||||
$document, $anchorScroll, $timeout, $location, currentUser,
|
||||
enableEditableComments, Tags) {
|
||||
'use strict';
|
||||
|
||||
|
@ -55,8 +55,48 @@ angular.module('sb.story').controller('StoryDetailController',
|
|||
*
|
||||
* @type {[Task]}
|
||||
*/
|
||||
$scope.projectNames = [];
|
||||
$scope.projects = {};
|
||||
$scope.tasks = tasks;
|
||||
|
||||
function mapTaskToProject(task) {
|
||||
Project.get({id: task.project_id}).$promise.then(function(project) {
|
||||
var idx = $scope.projectNames.indexOf(project.name);
|
||||
if (idx < 0) {
|
||||
$scope.projectNames.push(project.name);
|
||||
$scope.projects[project.name] = project;
|
||||
$scope.projects[project.name].branchNames = [];
|
||||
$scope.projects[project.name].branches = {};
|
||||
}
|
||||
Branch.get({id: task.branch_id}).$promise.then(
|
||||
function(branch) {
|
||||
var branchIdx = $scope.projects[project.name]
|
||||
.branchNames.indexOf(branch.name);
|
||||
if (branchIdx > -1) {
|
||||
$scope.projects[project.name].branches[branch.name]
|
||||
.tasks.push(task);
|
||||
} else {
|
||||
$scope.projects[project.name]
|
||||
.branches[branch.name] = branch;
|
||||
$scope.projects[project.name]
|
||||
.branches[branch.name].tasks = [task];
|
||||
$scope.projects[project.name]
|
||||
.branches[branch.name].newTask = new Task({
|
||||
story_id: $scope.story.id,
|
||||
branch_id: branch.id,
|
||||
project_id: project.id,
|
||||
status: 'todo',
|
||||
priority: 'medium'
|
||||
});
|
||||
$scope.projects[project.name]
|
||||
.branchNames.push(branch.name);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
angular.forEach(tasks, mapTaskToProject);
|
||||
|
||||
// Load the preference for each display event.
|
||||
function reloadPagePreferences() {
|
||||
TimelineEventTypes.forEach(function (type) {
|
||||
|
@ -498,20 +538,57 @@ angular.module('sb.story').controller('StoryDetailController',
|
|||
/**
|
||||
* Adds a task.
|
||||
*/
|
||||
$scope.createTask = function () {
|
||||
$scope.createTask = function (task, branch) {
|
||||
// Make a copy to save, so that the next task retains the
|
||||
// old information (for easier continuous editing).
|
||||
var savingTask = new Task(angular.copy($scope.newTask));
|
||||
var savingTask = new Task(angular.copy(task));
|
||||
savingTask.$save(function (savedTask) {
|
||||
$scope.tasks.push(savedTask);
|
||||
if (branch) {
|
||||
branch.tasks.push(savedTask);
|
||||
} else {
|
||||
mapTaskToProject(savedTask);
|
||||
}
|
||||
$scope.loadEvents();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Cleans up the project/branch/task tree.
|
||||
*
|
||||
* If there are no tasks remaining in the given branch in the given
|
||||
* project, then remove that branch from the project's list of
|
||||
* branches to display tasks for.
|
||||
*
|
||||
* If there are then no branches left in the project, remove the
|
||||
* project from the list of projects to display tasks for.
|
||||
*/
|
||||
function cleanBranchAndProject(projectName, branchName) {
|
||||
var project = $scope.projects[projectName];
|
||||
var branch = project.branches[branchName];
|
||||
var nameIdx = -1;
|
||||
|
||||
if (branch.tasks.length === 0) {
|
||||
nameIdx = project.branchNames.indexOf(branchName);
|
||||
if (nameIdx > -1) {
|
||||
project.branchNames.splice(nameIdx, 1);
|
||||
}
|
||||
delete project.branches[branchName];
|
||||
}
|
||||
if (project.branchNames.length === 0) {
|
||||
nameIdx = $scope.projectNames.indexOf(projectName);
|
||||
if (nameIdx > -1) {
|
||||
$scope.projectNames.splice(nameIdx, 1);
|
||||
}
|
||||
delete $scope.projects[projectName];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the task list.
|
||||
*/
|
||||
$scope.updateTask = function (task, fieldName, value) {
|
||||
$scope.updateTask = function (task, fieldName, value, projectName,
|
||||
branchName) {
|
||||
var params = {id: task.id};
|
||||
params[fieldName] = value;
|
||||
task[fieldName] = value;
|
||||
|
@ -519,33 +596,37 @@ angular.module('sb.story').controller('StoryDetailController',
|
|||
Task.update(params, function() {
|
||||
$scope.showTaskEditForm = false;
|
||||
$scope.loadEvents();
|
||||
}).$promise.then(function(updated) {
|
||||
if (fieldName === 'project_id') {
|
||||
var project = $scope.projects[projectName];
|
||||
var branch = project.branches[branchName];
|
||||
|
||||
var branchTaskIndex = branch.tasks.indexOf(task);
|
||||
if (branchTaskIndex > -1) {
|
||||
branch.tasks.splice(branchTaskIndex, 1);
|
||||
}
|
||||
|
||||
cleanBranchAndProject(projectName, branchName);
|
||||
mapTaskToProject(updated);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds link/comment to task
|
||||
*/
|
||||
$scope.showTaskNotes = function(task) {
|
||||
var modalInstance = $modal.open({
|
||||
templateUrl: 'app/stories/template/task_notes.html',
|
||||
controller: 'StoryTaskNotesController',
|
||||
resolve: {
|
||||
task: function() {
|
||||
return task;
|
||||
}
|
||||
}
|
||||
});
|
||||
$scope.editNotes = function(task) {
|
||||
task.tempNotes = task.link;
|
||||
task.editing = true;
|
||||
};
|
||||
|
||||
modalInstance.result.finally(function() {
|
||||
$scope.loadEvents();
|
||||
});
|
||||
$scope.cancelEditNotes = function(task) {
|
||||
task.tempNotes = '';
|
||||
task.editing = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Removes this task
|
||||
*/
|
||||
$scope.removeTask = function (task) {
|
||||
$scope.removeTask = function (task, projectName, branchName) {
|
||||
var modalInstance = $modal.open({
|
||||
templateUrl: 'app/stories/template/delete_task.html',
|
||||
controller: 'StoryTaskDeleteController',
|
||||
|
@ -567,6 +648,14 @@ angular.module('sb.story').controller('StoryDetailController',
|
|||
if (taskIndex > -1) {
|
||||
$scope.tasks.splice(taskIndex, 1);
|
||||
}
|
||||
|
||||
var project = $scope.projects[projectName];
|
||||
var branch = project.branches[branchName];
|
||||
var branchTaskIndex = branch.tasks.indexOf(task);
|
||||
if (branchTaskIndex > -1) {
|
||||
branch.tasks.splice(branchTaskIndex, 1);
|
||||
}
|
||||
cleanBranchAndProject(projectName, branchName);
|
||||
$scope.loadEvents();
|
||||
}
|
||||
);
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Codethink Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the 'License'); you may
|
||||
* not use this file except in compliance with the License. You may obtain
|
||||
* a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an 'AS IS' BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Controller for adding notes to tasks
|
||||
*/
|
||||
|
||||
angular.module('sb.story').controller('StoryTaskNotesController',
|
||||
function ($log, $scope, $state, task, $modalInstance, Task) {
|
||||
'use strict';
|
||||
|
||||
$scope.task = angular.copy(task);
|
||||
|
||||
/**
|
||||
* Generic service error handler. Assigns errors to the view's scope,
|
||||
* and unsets our flags.
|
||||
*/
|
||||
function handleServiceError(error) {
|
||||
// We've encountered an error.
|
||||
$scope.error = error;
|
||||
$scope.isLoading = false;
|
||||
$scope.isUpdating = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets our loading flags.
|
||||
*/
|
||||
function handleServiceSuccess() {
|
||||
$scope.isLoading = false;
|
||||
$scope.isUpdating = false;
|
||||
task.link = $scope.task.link;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resets any changes and toggles the form back.
|
||||
*/
|
||||
$scope.cancel = function () {
|
||||
$scope.editing = false;
|
||||
$scope.task = angular.copy(task);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Scope method, invoke this when you want to update the task.
|
||||
*/
|
||||
$scope.update = function () {
|
||||
// Set our progress flags and clear previous error conditions.
|
||||
$scope.isUpdating = true;
|
||||
$scope.error = {};
|
||||
|
||||
// Invoke the save method and wait for results.
|
||||
var params = {
|
||||
id: task.id,
|
||||
link: $scope.task.link
|
||||
};
|
||||
Task.update(params, function () {
|
||||
$modalInstance.close('save');
|
||||
handleServiceSuccess();
|
||||
},
|
||||
handleServiceError
|
||||
);
|
||||
};
|
||||
|
||||
// Set our progress flags and clear previous error conditions.
|
||||
|
||||
$scope.close = function () {
|
||||
$modalInstance.close('closed');
|
||||
};
|
||||
});
|
|
@ -31,6 +31,7 @@
|
|||
src="'/inline/story_detail_form.html'"
|
||||
ng-show="showEditForm">
|
||||
</div>
|
||||
<hr/>
|
||||
<div ng-include src="'/inline/task_list.html'"></div>
|
||||
<hr/>
|
||||
<div ng-include src="'/inline/tags.html'"></div>
|
||||
|
@ -296,54 +297,379 @@
|
|||
<i class="fa fa-plus"></i>
|
||||
</span>
|
||||
</h4>
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<!-- Template for the task list -->
|
||||
<script type="text/ng-template" id="/inline/task_list.html">
|
||||
<table class="table table-striped table-supercondensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<td colspan="8"><strong>Tasks</strong></td>
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="task in tasks | orderBy:'-status'"
|
||||
ng-include
|
||||
src="'/inline/task_list_item.html'">
|
||||
</tr>
|
||||
<tr ng-if="tasks.length == 0 && !showAddTaskForm">
|
||||
<td colspan="8">
|
||||
<p class="text-muted text-center">
|
||||
<em>This story has no tasks.</em>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="showAddTaskForm"
|
||||
ng-include
|
||||
src="'/inline/task_edit_form.html'">
|
||||
</tr>
|
||||
<hr />
|
||||
<tr>
|
||||
<td colspan="8" class="text-left">
|
||||
<button class="btn btn-default" type="button"
|
||||
ng-click="showAddTaskForm = !showAddTaskForm"
|
||||
ng-show="isLoggedIn">
|
||||
<i class="fa fa-plus" ng-if="!showAddTaskForm"></i>
|
||||
<i class="fa fa-minus" ng-if="showAddTaskForm"></i>
|
||||
<strong> Add task </strong>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3>Tasks</h3>
|
||||
<div ng-repeat="name in projectNames">
|
||||
<h4>
|
||||
<i class="fa fa-sb-project text-muted"></i>
|
||||
<a href="#!/project/{{ projects[name].id }}">{{ name }}</a>
|
||||
</h4>
|
||||
<div ng-repeat="branchName in projects[name].branchNames">
|
||||
<div class="row" ng-if="branchName != 'master'">
|
||||
<div class="col-xs-3">
|
||||
<strong>
|
||||
  {{ branchName }}
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" ng-if="branchName == 'master'">
|
||||
<div class="col-xs-12" ng-include src="'/inline/task_table.html'"></div>
|
||||
</div>
|
||||
<div class="row" ng-if="branchName != 'master'">
|
||||
<div class="col-xs-11 col-xs-offset-1"
|
||||
ng-include src="'/inline/task_table.html'">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-show="newTask.show" ng-include src="'/inline/new_task.html'"></div>
|
||||
<button class="btn btn-default"
|
||||
ng-show="!newTask.show"
|
||||
ng-click="newTask.show = !newTask.show">
|
||||
<i class="fa fa-plus-circle"></i>
|
||||
Affects other project
|
||||
</button>
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<!-- Template for the task list -->
|
||||
<!-- Template for a table of tasks -->
|
||||
<script type="text/ng-template" id="/inline/task_table.html">
|
||||
<table class="table table-striped table-supercondensed">
|
||||
<tr ng-repeat="task in projects[name].branches[branchName].tasks | orderBy: '-status'"
|
||||
ng-include src="'/inline/task_list_item.html'">
|
||||
</tr>
|
||||
<tr ng-show="isLoggedIn && !projects[name].branches[branchName].showAddTask">
|
||||
<td class="text-center">
|
||||
<a href
|
||||
ng-click="projects[name].branches[branchName].showAddTask =
|
||||
!projects[name].branches[branchName].showAddTask">
|
||||
<i class="fa fa-plus-circle"></i>
|
||||
Add task affecting this project
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-show="projects[name].branches[branchName].showAddTask"
|
||||
ng-include src="'/inline/task_edit_form.html'">
|
||||
</tr>
|
||||
</table>
|
||||
</script>
|
||||
|
||||
<!-- Template for an item in the task list -->
|
||||
<script type="text/ng-template" id="/inline/task_list_item.html">
|
||||
<td>
|
||||
<div class="row">
|
||||
<div class="col-xs-4 task-title">
|
||||
<div>
|
||||
<a href ng-click="showDetail = !showDetail">
|
||||
<i class="fa fa-caret-down" ng-show="showDetail"></i>
|
||||
<i class="fa fa-caret-right" ng-show="!showDetail"></i>
|
||||
</a>
|
||||
<strong>{{ task.id }}</strong>
|
||||
|
||||
</div>
|
||||
<div class="title">
|
||||
<input-inline
|
||||
ng-model="task.title"
|
||||
enabled="isLoggedIn"
|
||||
on-change="updateTask(task, 'title', task.title)"
|
||||
empty-prompt="Click to set title."
|
||||
empty-disabled-prompt="No title."
|
||||
maxlength="255"
|
||||
as-inline="true"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<user-typeahead
|
||||
ng-model="task.assignee_id"
|
||||
enabled="isLoggedIn"
|
||||
on-change="updateTask(task, 'assignee_id', task.assignee_id)"
|
||||
empty-prompt="Click to assign."
|
||||
empty-disabled-prompt="Not assigned."
|
||||
as-inline="true"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<task-status-dropdown
|
||||
editable="{{isLoggedIn}}"
|
||||
on-change="updateTask(task, 'status', status)"
|
||||
status="{{ task.status }}"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<task-priority-dropdown
|
||||
editable="{{isLoggedIn}}"
|
||||
on-change="updateTask(task, 'priority', priority)"
|
||||
priority="{{newTask.priority}}"
|
||||
/>
|
||||
</div>
|
||||
<!-- Review link should go here once implemented in the API -->
|
||||
</div>
|
||||
<div class="row button-row" ng-show="showDetail">
|
||||
<div class="col-xs-1"></div>
|
||||
<div class="col-xs-10">
|
||||
<project-typeahead
|
||||
auto-focus="false"
|
||||
ng-model="task.project_id"
|
||||
ng-show="changingProject"
|
||||
enabled="isLoggedIn"
|
||||
on-change="updateTask(task, 'project_id', task.project_id, name, branchName);
|
||||
changingProject = false"
|
||||
empty-prompt="Click to set a project"
|
||||
empty-disabled-prompt="No project set."
|
||||
as-inline="false"
|
||||
placeholder="Enter project name">
|
||||
</project-typeahead>
|
||||
<button class="btn btn-xs btn-default"
|
||||
ng-click="changingProject = !changingProject">
|
||||
{{ changingProject ? 'Cancel' : 'Change project' }}
|
||||
</button>
|
||||
<button class="btn btn-xs btn-default"
|
||||
ng-show="tasks.length > 1"
|
||||
ng-click="removeTask(task, name, branchName)">
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" ng-show="showDetail">
|
||||
<div class="col-xs-10 col-xs-offset-1">
|
||||
<insert-markdown content="task.link" ng-show="!task.editing"></insert-markdown>
|
||||
<insert-markdown content="task.tempNotes" ng-show="task.editing && notesPreview"></insert-markdown>
|
||||
<form name="taskNotesForm" ng-show="task.editing">
|
||||
<div class="form-group">
|
||||
<textarea placeholder="Enter task notes here"
|
||||
class="form-control context-edit"
|
||||
msd-elastic
|
||||
rows="3"
|
||||
ng-show="isLoggedIn"
|
||||
ng-disabled="isUpdating"
|
||||
ng-model="task.tempNotes">
|
||||
</textarea>
|
||||
</div>
|
||||
|
||||
<div class="clearfix">
|
||||
<button type="button" ng-show="isLoggedIn"
|
||||
class="btn btn-default" ng-click="notesPreview = !notesPreview">
|
||||
Toggle Preview
|
||||
</button>
|
||||
<div class="pull-right">
|
||||
<div class="btn" ng-show="isUpdating">
|
||||
<i class="fa fa-spinner fa-lg fa-spin"></i>
|
||||
</div>
|
||||
<button type="button" ng-show="isLoggedIn"
|
||||
class="btn btn-primary"
|
||||
ng-click="updateTask(task, 'link', task.tempNotes);
|
||||
cancelEditNotes(task)"
|
||||
ng-disabled="!taskNotesForm.$valid">
|
||||
Save
|
||||
</button>
|
||||
<button type="button" ng-show="isLoggedIn"
|
||||
class="btn btn-default"
|
||||
ng-click="cancelEditNotes(task)">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="row text-center" ng-show="!task.editing && !task.link">
|
||||
<button class="btn btn-primary btn-xs"
|
||||
ng-click="editNotes(task)">
|
||||
<i class="fa fa-pencil"></i> Add notes
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-1" ng-show="!task.editing && task.link">
|
||||
<button class="btn btn-primary btn-xs"
|
||||
ng-click="editNotes(task)">
|
||||
<i class="fa fa-pencil"></i> Edit
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</script>
|
||||
|
||||
<!-- Template for the task add form. -->
|
||||
<script type="text/ng-template" id="/inline/task_edit_form.html">
|
||||
<td>
|
||||
<div class="row">
|
||||
<div class="col-xs-4 task-title">
|
||||
<div>
|
||||
<a href ng-click="showDetail = !showDetail">
|
||||
<i class="fa fa-caret-down" ng-show="showDetail"></i>
|
||||
<i class="fa fa-caret-right" ng-show="!showDetail"></i>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<input-inline
|
||||
auto-focus="true"
|
||||
ng-model="projects[name].branches[branchName].newTask.title"
|
||||
enabled="isLoggedIn"
|
||||
on-change="updateTaskInline()"
|
||||
empty-prompt="Click to assign."
|
||||
empty-disabled-prompt="Not assigned."
|
||||
maxlength="255"
|
||||
as-inline="false"
|
||||
placeholder="Enter task name"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<user-typeahead
|
||||
auto-focus="false"
|
||||
ng-model="projects[name].branches[branchName].newTask.assignee_id"
|
||||
enabled="isLoggedIn"
|
||||
on-change="updateTaskInline()"
|
||||
empty-prompt="Click to assign."
|
||||
empty-disabled-prompt="Not assigned."
|
||||
as-inline="false"
|
||||
placeholder="Assign user to task"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<task-status-dropdown
|
||||
editable="{{isLoggedIn}}"
|
||||
on-change="updateTask(projects[name].branches[branchName].newTask, 'status', status)"
|
||||
status="{{projects[name].branches[branchName].newTask.status}}"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<task-priority-dropdown
|
||||
editable="{{isLoggedIn}}"
|
||||
on-change="updateTask(projects[name].branches[branchName].newTask, 'priority', priority)"
|
||||
priority="{{projects[name].branches[branchName].newTask.priority}}"
|
||||
/>
|
||||
</div>
|
||||
<!-- Review link should go here once implemented in the API -->
|
||||
<div class="col-xs-2 text-right">
|
||||
<button ng-click="createTask(projects[name].branches[branchName].newTask,
|
||||
projects[name].branches[branchName])"
|
||||
class="btn btn-primary">
|
||||
Save
|
||||
</button>
|
||||
<button ng-click="projects[name].branches[branchName].showAddTask =
|
||||
!projects[name].branches[branchName].showAddTask"
|
||||
class="btn btn-default">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" ng-show="showDetail">
|
||||
<div class="col-xs-10 col-xs-offset-1">
|
||||
<textarea ng-model="projects[name].branches[branchName].newTask.link"
|
||||
class="form-control context-edit"
|
||||
msd-elastic
|
||||
rows="3"
|
||||
ng-show="isLoggedIn"
|
||||
placeholder="Task notes">
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</script>
|
||||
|
||||
<!-- Template for creating a task in an as-yet unrelated project -->
|
||||
<script type="text/ng-template" id="/inline/new_task.html">
|
||||
<div>
|
||||
<h4>
|
||||
<i class="fa fa-sb-project text-muted"></i>
|
||||
<project-typeahead
|
||||
auto-focus="false"
|
||||
ng-model="newTask.project_id"
|
||||
enabled="isLoggedIn"
|
||||
on-change="updateTaskInline()"
|
||||
empty-prompt="Click to set a project"
|
||||
empty-disabled-prompt="No project set."
|
||||
as-inline="false"
|
||||
placeholder="Enter project name">
|
||||
</project-typeahead>
|
||||
</h4>
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<table class="table table-supercondensed">
|
||||
<tr>
|
||||
<td>
|
||||
<div class="row">
|
||||
<div class="col-xs-4 task-title">
|
||||
<div>
|
||||
<a href ng-click="showDetail = !showDetail">
|
||||
<i class="fa fa-caret-down" ng-show="showDetail"></i>
|
||||
<i class="fa fa-caret-right" ng-show="!showDetail"></i>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
<input-inline
|
||||
auto-focus="true"
|
||||
ng-model="newTask.title"
|
||||
enabled="isLoggedIn"
|
||||
on-change="updateTaskInline()"
|
||||
empty-prompt="Click to assign."
|
||||
empty-disabled-prompt="Not assigned."
|
||||
maxlength="255"
|
||||
as-inline="false"
|
||||
placeholder="Enter task name"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<user-typeahead
|
||||
auto-focus="false"
|
||||
ng-model="newTask.assignee_id"
|
||||
enabled="isLoggedIn"
|
||||
on-change="updateTaskInline()"
|
||||
empty-prompt="Click to assign."
|
||||
empty-disabled-prompt="Not assigned."
|
||||
as-inline="false"
|
||||
placeholder="Assign user to task"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-xs-2">
|
||||
<task-status-dropdown
|
||||
editable="{{isLoggedIn}}"
|
||||
on-change="updateTask(newTask, 'status', status)"
|
||||
status="{{newTask.status}}"
|
||||
/>
|
||||
</div>
|
||||
<!-- Review link should go here once implemented in the API -->
|
||||
<div class="col-xs-2">
|
||||
<task-priority-dropdown
|
||||
editable="{{isLoggedIn}}"
|
||||
on-change="updateTask(newTask, 'priority', priority)"
|
||||
priority="{{newTask.priority}}"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-xs-2 text-right">
|
||||
<button ng-click="createTask(newTask)"
|
||||
class="btn btn-primary">
|
||||
Save
|
||||
</button>
|
||||
<button ng-click="newTask.show = !newTask.show"
|
||||
class="btn btn-default">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" ng-show="showDetail">
|
||||
<div class="col-xs-10 col-xs-offset-1">
|
||||
<textarea ng-model="newTask.link"
|
||||
class="form-control context-edit"
|
||||
msd-elastic
|
||||
rows="3"
|
||||
ng-show="isLoggedIn"
|
||||
placeholder="Task notes">
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<!-- Template for the events stream -->
|
||||
<script type="text/ng-template" id="/inline/discussion.html">
|
||||
<div>
|
||||
<div class="clearfix">
|
||||
|
@ -429,135 +755,3 @@
|
|||
<hr />
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<!-- Template for an item in the task list -->
|
||||
<script type="text/ng-template" id="/inline/task_list_item.html">
|
||||
<td class="col-xs-1 center-vertical">{{task.id}}:</td>
|
||||
<td class="col-xs-3 center-vertical">
|
||||
<input-inline
|
||||
ng-model="task.title"
|
||||
enabled="isLoggedIn"
|
||||
on-change="updateTask(task, 'title', task.title)"
|
||||
empty-prompt="Click to assign."
|
||||
empty-disabled-prompt="Not assigned."
|
||||
maxlength="255"
|
||||
as-inline="true"
|
||||
/>
|
||||
</td>
|
||||
<td class="col-xs-1 center-vertical">
|
||||
<button class="btn btn-xs btn-task-notes"
|
||||
ng-class="{'btn-default': !task.link,
|
||||
'btn-primary': task.link}"
|
||||
ng-click="showTaskNotes(task)"
|
||||
title="Task notes">
|
||||
<i class="fa"
|
||||
ng-class="{'fa-sticky-note-o': !task.link,
|
||||
'fa-sticky-note': task.link}"></i>
|
||||
</button>
|
||||
</td>
|
||||
<td class="col-xs-3 center-vertical">
|
||||
<project-typeahead
|
||||
ng-model="task.project_id"
|
||||
enabled="isLoggedIn"
|
||||
on-change="updateTask(task, 'project_id', task.project_id)"
|
||||
empty-prompt="Click to assign."
|
||||
empty-disabled-prompt="Not assigned."
|
||||
as-inline="true"
|
||||
/>
|
||||
</td>
|
||||
<td class="col-xs-2 center-vertical">
|
||||
<user-typeahead
|
||||
ng-model="task.assignee_id"
|
||||
enabled="isLoggedIn"
|
||||
on-change="updateTask(task, 'assignee_id', task.assignee_id)"
|
||||
empty-prompt="Click to assign."
|
||||
empty-disabled-prompt="Not assigned."
|
||||
as-inline="true"
|
||||
/>
|
||||
</td>
|
||||
<td class="text-center col-xs-1 center-vertical">
|
||||
<task-priority-dropdown
|
||||
editable="{{isLoggedIn}}"
|
||||
on-change="updateTask(task, 'priority', priority)"
|
||||
priority="{{task.priority}}"
|
||||
/>
|
||||
</td>
|
||||
<td class="text-center col-xs-1 center-vertical">
|
||||
<task-status-dropdown
|
||||
editable="{{isLoggedIn}}"
|
||||
on-change="updateTask(task, 'status', status)"
|
||||
status="{{task.status}}"
|
||||
/>
|
||||
</td>
|
||||
<td class="text-right col-xs-1 center-vertical">
|
||||
<a ng-show="isLoggedIn"
|
||||
ng-click="removeTask(task)">
|
||||
<i class="fa fa-times fa-lg"></i>
|
||||
</a>
|
||||
</td>
|
||||
</script>
|
||||
|
||||
<!-- Template for the task add form. -->
|
||||
<script type="text/ng-template" id="/inline/task_edit_form.html">
|
||||
<td class="col-xs-1"></td>
|
||||
<td class="col-xs-3">
|
||||
<input-inline
|
||||
auto-focus="true"
|
||||
ng-model="newTask.title"
|
||||
enabled="isLoggedIn"
|
||||
on-change="updateTaskInline()"
|
||||
empty-prompt="Click to assign."
|
||||
empty-disabled-prompt="Not assigned."
|
||||
maxlength="255"
|
||||
as-inline="false"
|
||||
placeholder="Enter task name"
|
||||
/>
|
||||
</td>
|
||||
<td class="col-xs-1">
|
||||
</td>
|
||||
|
||||
<td class="col-xs-3">
|
||||
<project-typeahead
|
||||
auto-focus="false"
|
||||
ng-model="newTask.project_id"
|
||||
enabled="isLoggedIn"
|
||||
on-change="updateTaskInline()"
|
||||
empty-prompt="Click to assign."
|
||||
empty-disabled-prompt="Not assigned."
|
||||
as-inline="false"
|
||||
placeholder="Enter project name"
|
||||
/>
|
||||
</td>
|
||||
<td class="col-xs-2">
|
||||
<user-typeahead
|
||||
auto-focus="false"
|
||||
ng-model="newTask.assignee_id"
|
||||
enabled="isLoggedIn"
|
||||
on-change="updateTaskInline()"
|
||||
empty-prompt="Click to assign."
|
||||
empty-disabled-prompt="Not assigned."
|
||||
as-inline="false"
|
||||
placeholder="Assign user to task"
|
||||
/>
|
||||
</td>
|
||||
<td class="text-center col-xs-1">
|
||||
<task-priority-dropdown
|
||||
editable="{{isLoggedIn}}"
|
||||
on-change="updateTask(newTask, 'priority', priority)"
|
||||
priority="{{newTask.priority}}"
|
||||
/>
|
||||
</td>
|
||||
<td class="text-center col-xs-1">
|
||||
<task-status-dropdown
|
||||
editable="{{isLoggedIn}}"
|
||||
on-change="updateTask(newTask, 'status', status)"
|
||||
status="{{newTask.status}}"
|
||||
/>
|
||||
</td>
|
||||
<td class="text-right col-xs-1">
|
||||
<button ng-click="createTask()"
|
||||
class="btn btn-primary">
|
||||
Save
|
||||
</button>
|
||||
</td>
|
||||
</script>
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
<!--
|
||||
~ Copyright (c) 2016 Codethink Limited
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
~ not use this file except in compliance with the License. You may obtain
|
||||
~ a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
~ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
~ License for the specific language governing permissions and limitations
|
||||
~ under the License.
|
||||
-->
|
||||
<div class="panel panel-default card-modal">
|
||||
<div class="panel-heading clearfix">
|
||||
<button type="button" class="close" aria-hidden="true"
|
||||
ng-click="close()">×
|
||||
</button>
|
||||
<h3 class="panel-title">Notes on {{task.title}}</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div ng-show="!isLoggedIn || !editing || preview">
|
||||
<insert-markdown content="task.link"></insert-markdown>
|
||||
</div>
|
||||
<button type="button" ng-show="isLoggedIn && !editing"
|
||||
class="btn btn-primary pull-right"
|
||||
ng-click="editing = !editing">
|
||||
<i class="fa fa-pencil"></i> Edit
|
||||
</button>
|
||||
<form name="taskNotesForm" ng-show="editing">
|
||||
<div class="form-group">
|
||||
<textarea placeholder="Enter task notes here"
|
||||
class="form-control context-edit"
|
||||
msd-elastic
|
||||
rows="3"
|
||||
ng-show="isLoggedIn"
|
||||
ng-disabled="isUpdating"
|
||||
ng-model="task.link">
|
||||
</textarea>
|
||||
</div>
|
||||
|
||||
<div class="clearfix">
|
||||
<button type="button" ng-show="isLoggedIn"
|
||||
class="btn btn-default" ng-click="preview = !preview">
|
||||
Toggle Preview
|
||||
</button>
|
||||
<div class="pull-right">
|
||||
<div class="btn" ng-show="isUpdating">
|
||||
<i class="fa fa-spinner fa-lg fa-spin"></i>
|
||||
</div>
|
||||
<button type="button" ng-show="isLoggedIn"
|
||||
class="btn btn-primary"
|
||||
ng-click="update()"
|
||||
ng-disabled="!taskNotesForm.$valid">
|
||||
Save
|
||||
</button>
|
||||
<button type="button" ng-show="isLoggedIn"
|
||||
class="btn btn-default"
|
||||
ng-click="cancel()">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div>
|
||||
</div>
|
|
@ -2,17 +2,19 @@
|
|||
<div class="form-group"
|
||||
ng-if="!enabled || !showForm">
|
||||
<p class="form-control-static">
|
||||
{{ inputText }}
|
||||
|
||||
|
||||
<a href=""
|
||||
ng-focus="toggleForm()"
|
||||
ng-click="toggleForm()"
|
||||
ng-if="!showForm && enabled">
|
||||
<span ng-if="inputText">
|
||||
{{inputText}}
|
||||
<i class="fa fa-edit"></i>
|
||||
<i class="fa fa-pencil"></i>
|
||||
</span>
|
||||
<em ng-if="!inputText" class="text-muted">
|
||||
{{emptyPrompt}}
|
||||
<i class="fa fa-edit"></i>
|
||||
<i class="fa fa-pencil"></i>
|
||||
</em>
|
||||
</a>
|
||||
|
||||
|
|
|
@ -8,21 +8,19 @@
|
|||
ng-if="project && !project.$resolved"></i>
|
||||
|
||||
|
||||
<a
|
||||
href="#!/project/{{project.id}}">
|
||||
{{project.name}}
|
||||
</a>
|
||||
<a href="#!/project/{{project.id}}">{{project.name}}</a>
|
||||
|
||||
|
||||
<a href=""
|
||||
ng-focus="toggleForm()"
|
||||
ng-click="toggleForm()"
|
||||
ng-if="!showForm && enabled">
|
||||
<span ng-if="project">
|
||||
<i class="fa fa-edit"></i>
|
||||
<i class="fa fa-pencil"></i>
|
||||
</span>
|
||||
<em ng-if="!project" class="text-muted">
|
||||
{{emptyPrompt}}
|
||||
<i class="fa fa-edit"></i>
|
||||
<i class="fa fa-pencil"></i>
|
||||
</em>
|
||||
</a>
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<span class="label label-{{style}}" ng-hide="editable">
|
||||
{{priority | taskPriorityLabel}}
|
||||
</span>
|
||||
<div class="dropdown" ng-show="editable" dropdown>
|
||||
<div class="dropdown form-control-static" ng-show="editable" dropdown>
|
||||
<a class="btn btn-{{style}} btn-xs dropdown-toggle" dropdown-toggle>
|
||||
{{priority | taskPriorityLabel}}
|
||||
<i class="fa fa-caret-down"></i>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<span class="label label-{{style}}" ng-hide="editable">
|
||||
{{statusName}}
|
||||
</span>
|
||||
<div class="dropdown" ng-show="editable" dropdown>
|
||||
<div class="dropdown form-control-static" ng-show="editable" dropdown>
|
||||
<a class="btn btn-{{style}} btn-xs dropdown-toggle" dropdown-toggle>
|
||||
{{ statusName }}
|
||||
<i class="fa fa-caret-down"></i>
|
||||
|
|
|
@ -8,17 +8,19 @@
|
|||
ng-if="user && !user.$resolved"></i>
|
||||
|
||||
|
||||
<span ng-if="user && enabled">{{user.full_name}}</span>
|
||||
|
||||
|
||||
<a href=""
|
||||
ng-focus="toggleForm()"
|
||||
ng-click="toggleForm()"
|
||||
ng-if="!showForm && enabled">
|
||||
<span ng-if="user">
|
||||
{{user.full_name}}
|
||||
<i class="fa fa-edit"></i>
|
||||
<i class="fa fa-pencil"></i>
|
||||
</span>
|
||||
<em ng-if="!user" class="text-muted">
|
||||
{{emptyPrompt}}
|
||||
<i class="fa fa-edit"></i>
|
||||
<i class="fa fa-pencil"></i>
|
||||
</em>
|
||||
</a>
|
||||
|
||||
|
|
|
@ -226,7 +226,3 @@ div .container-fluid {
|
|||
.modal-checkbox {
|
||||
margin-left: 0px !important;
|
||||
}
|
||||
|
||||
.btn-task-notes i {
|
||||
color: @black !important;
|
||||
}
|
||||
|
|
|
@ -11,3 +11,38 @@
|
|||
left: 150px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.task-title {
|
||||
& > div {
|
||||
vertical-align: top;
|
||||
display: inline-block;
|
||||
padding-top: 7px;
|
||||
padding-bottom: 7px;
|
||||
}
|
||||
|
||||
& .title {
|
||||
max-width: 75%;
|
||||
}
|
||||
|
||||
& .form-control-static {
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
input-inline, project-typeahead, user-typeahead, task-status-dropdown {
|
||||
display: inline-block;
|
||||
|
||||
& .form-group {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.noselect {
|
||||
user-select: none;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue