Skip to content

Commit

Permalink
Issue 80: On "Active Sprints" board show icon for Milestone or Projec…
Browse files Browse the repository at this point in the history
…t depending on how the Sprint is populated

The crafted icons are added any each reasonable location, helping improve usability via the icon as hints.
This includes icons for all known ServiceTypes.

This also fixes the management board, thereby allowing for the remote project management icons being displayed in this case as well.
  • Loading branch information
kaladay committed Oct 1, 2020
1 parent 2f8330e commit 3a75c4e
Show file tree
Hide file tree
Showing 18 changed files with 196 additions and 16 deletions.
22 changes: 22 additions & 0 deletions app/controllers/productController.js
Expand Up @@ -123,6 +123,28 @@ app.controller('ProductController', function ($controller, $scope, ApiResponseAc
$scope.otherUrlsChanged = true;
};

$scope.distinctRemoteProjectManagers = function (remoteProjectInfo) {
var list = [];
var matched = false;

for (var i in remoteProjectInfo) {
matched = false;

for (var j in list) {
if (remoteProjectInfo[i].remoteProjectManager.id === list[j].remoteProjectManager.id) {
matched = true;
break;
}
}

if (!matched) {
list.push(remoteProjectInfo[i]);
}
}

return list;
};

if ($scope.isManager() || $scope.isAdmin()) {
$scope.remoteProjectManagers = RemoteProjectManagerRepo.getAll();

Expand Down
34 changes: 34 additions & 0 deletions app/directives/remoteProjectsIconDirective.js
@@ -0,0 +1,34 @@
app.directive('remoteProjectsIcon', function ($controller) {
return {
templateUrl: 'views/directives/remoteProjectsIcon.html',
restrict: 'E',
scope: {
type: '@',
width: '@',
height: '@'
},
link: function ($scope, element, attr) {
$scope.typeIcon = false;
$scope.tooltip = "";

if ($scope.type === 'GITHUB_MILESTONE') {
$scope.typeIcon = 'github-milestone.png';
$scope.tooltip = "Github Milestone";
} else if ($scope.type === 'GITHUB_PROJECT') {
$scope.typeIcon = 'github-project.png';
$scope.tooltip = "Github Project";
} else if ($scope.type === 'VERSION_ONE') {
$scope.typeIcon = 'versionone.png';
$scope.tooltip = "Versione One";
}

if (angular.isUndefined($scope.width)) {
$scope.width = "16";
}

if (angular.isUndefined($scope.height)) {
$scope.height = "16";
}
}
};
});
1 change: 1 addition & 0 deletions app/index.html
Expand Up @@ -193,6 +193,7 @@

<!-- Directives -->
<script src="directives/customHeaderDirective.js"></script>
<script src="directives/remoteProjectsIconDirective.js"></script>

<!-- Services -->
<script src="services/activeSprintsService.js"></script>
Expand Down
Binary file added app/resources/images/github-milestone.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/resources/images/github-project.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/resources/images/versionone.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion app/resources/styles/sass/directives/_all.scss
@@ -1,2 +1,3 @@
@import "header";
@import "footer";
@import "footer";
@import "remoteProjectsIcon";
5 changes: 5 additions & 0 deletions app/resources/styles/sass/directives/_remoteProjectsIcon.scss
@@ -0,0 +1,5 @@
.remote-product-icon {
display: inline-block;
position: relative;
top: 0px;
}
21 changes: 20 additions & 1 deletion app/resources/styles/sass/management/_products.scss
Expand Up @@ -2,6 +2,20 @@
cursor: pointer;
}

.management-table {
.product-table {
.product-rpm-row {
clear: both;
}
}
}

.product-rpm-icons {
.remote-product-icon {
padding: 0px 3px;
}
}

.remote-product-panel {
margin-top: 20px;

Expand All @@ -20,4 +34,9 @@
ul {
margin-bottom: 0;
}
}

.remote-product-icon {
top: -4px;
padding-right: 6px;
}
}
3 changes: 3 additions & 0 deletions app/views/directives/remoteProjectsIcon.html
@@ -0,0 +1,3 @@
<span ng-if="typeIcon" class="remote-product-icon">
<img src="resources/images/{{typeIcon}}" title="{{tooltip}}" width="{{width}}" height="{{height}}" aria-hidden="true">
</span>
12 changes: 10 additions & 2 deletions app/views/home.html
Expand Up @@ -34,7 +34,10 @@
<tr ng-repeat="sprint in activeSprints" ng-click="select($index)" class="toggle-href" ng-class="{'info': sprint.id === getSelectedSprint().id}">
<td>{{sprint.id}}</td>
<td>{{sprint.name}}</td>
<td>{{sprint.product}}</td>
<td>
<remote-projects-icon type="{{sprint.type}}" class="pull-right"></remote-projects-icon>
<span>{{sprint.product}}</span>
</td>
<td>{{sprint.cards.length}}</td>
<td>{{getSprintEstimateTotal(sprint)}}</td>
</tr>
Expand Down Expand Up @@ -102,7 +105,12 @@
<th>Internal Count</th>
</tr>
<tr ng-repeat="product in products | orderBy: '-stats.backlogItemCount'">
<td title="'Product'">{{product.name}}</td>
<td title="'Product'">
<span ng-repeat="rpi in distinctRemoteProjectManagers(product.remoteProjectInfo)" class="product-rpm-icons">
<remote-projects-icon type="{{rpi.remoteProjectManager.type}}" class="pull-right"></remote-projects-icon>
</span>
<span>{{product.name}}</span>
</td>
<td title="'Total Backlog Items'">{{product.stats.backlogItemCount}}</td>
<td title="'Feature Count'">{{product.stats.featureCount}}</td>
<td title="'Defect Count'">{{product.stats.defectCount}}</td>
Expand Down
19 changes: 16 additions & 3 deletions app/views/management/products.html
Expand Up @@ -15,9 +15,22 @@
</tr>
<tr ng-repeat="product in products | orderBy: 'name'">
<td title="'Product'">{{product.name}}</td>
<td title="'Remote Project Manager'">{{product.remoteProjectManager.name}}</td>
<td title="'Remote Project'">{{product.remoteProject.name}}</td>
<td title="'Scope Id'">{{product.scopeId}}</td>
<td title="'Remote Project Manager'">
<div ng-repeat="rpi in distinctRemoteProjectManagers(product.remoteProjectInfo)" class="product-rpm-row">
<remote-projects-icon type="{{rpi.remoteProjectManager.type}}" class="pull-right"></remote-projects-icon>
<span>{{rpi.remoteProjectManager.name}}</span>
</div>
</td>
<td title="'Remote Project'">
<div ng-repeat="rpi in distinctRemoteProjectManagers(product.remoteProjectInfo)" class="product-rpm-row">
<div>{{getRemoteProjectByRemoteProjectInfo(rpi).name}}</div>
</div>
</td>
<td title="'Scope Id'">
<div ng-repeat="rpi in distinctRemoteProjectManagers(product.remoteProjectInfo)">
<div>{{rpi.scopeId}}</div>
</div>
</td>
<td class="actions-column text-center" title="'Actions'">
<span class="glyphicon glyphicon-pencil" title="edit" ng-click="editProduct(product)"></span>
<span class="glyphicon glyphicon-trash" title="delete" ng-click="confirmDeleteProduct(product)"></span>
Expand Down
5 changes: 4 additions & 1 deletion app/views/management/remoteProjectManager.html
Expand Up @@ -10,7 +10,10 @@
<th class="actions-column text-center">Actions</th>
</tr>
<tr ng-repeat="remoteProjectManager in remoteProjectManagers">
<td title="'Remote Project Manager'">{{remoteProjectManager.name}}</td>
<td title="'Remote Project Manager'">
<remote-projects-icon type="{{remoteProjectManager.type}}" class="pull-right"></remote-projects-icon>
<span>{{remoteProjectManager.name}}</span>
</td>
<td title="'URL'">{{remoteProjectManager.url}}</td>
<td class="actions-column text-center" title="'Actions'">
<span class="glyphicon glyphicon-pencil" title="edit" ng-click="editRemoteProjectManager(remoteProjectManager)"></span>
Expand Down
8 changes: 6 additions & 2 deletions app/views/modals/addProductModal.html
Expand Up @@ -38,8 +38,12 @@ <h4 class="modal-title">Create Product</h4>
</div>
<div class="panel-body">
<ul class="list-group">
<li class="list-group-item" ng-repeat="remoteProject in productToCreate.remoteProjectInfo track by remoteProject.scopeId" ng-model="productToCreate.remoteProjectInfo">{{getRemoteProjectByRemoteProjectInfo(remoteProject).name}}
<span class="glyphicon glyphicon-trash clickable pull-right" title="Remote Remote Project" ng-click="removeRemoteProjectInfo(productToCreate.remoteProjectInfo, remoteProject)"></span>
<li class="list-group-item" ng-repeat="remoteProject in productToCreate.remoteProjectInfo track by remoteProject.scopeId" ng-model="productToCreate.remoteProjectInfo">
<span>{{getRemoteProjectByRemoteProjectInfo(remoteProject).name}}</span>
<span class="product-rpm-icons pull-right">
<remote-projects-icon type="{{remoteProject.remoteProjectManager.type}}" width="14" height="14"></remote-projects-icon>
<span class="glyphicon glyphicon-trash clickable pull-right" title="delete" ng-click="removeRemoteProjectInfo(productToCreate.remoteProjectInfo, remoteProject)"></span>
</span>
</li>
</ul>
</div>
Expand Down
8 changes: 6 additions & 2 deletions app/views/modals/editProductModal.html
Expand Up @@ -39,8 +39,12 @@ <h4 class="modal-title">Edit Product</h4>
</div>
<div class="panel-body">
<ul class="list-group">
<li class="list-group-item" ng-repeat="remoteProject in productToEdit.remoteProjectInfo track by remoteProject.scopeId" ng-model="productToEdit.remoteProjectInfo">{{getRemoteProjectByRemoteProjectInfo(remoteProject).name}}
<span class="glyphicon glyphicon-trash clickable pull-right" title="Remote Remote Project" ng-click="removeRemoteProjectInfo(productToEdit.remoteProjectInfo, remoteProject)"></span>
<li class="list-group-item" ng-repeat="remoteProject in productToEdit.remoteProjectInfo track by remoteProject.scopeId" ng-model="productToEdit.remoteProjectInfo">
<span>{{getRemoteProjectByRemoteProjectInfo(remoteProject).name}}</span>
<span class="product-rpm-icons pull-right">
<remote-projects-icon type="{{remoteProject.remoteProjectManager.type}}" width="14" height="14"></remote-projects-icon>
<span class="glyphicon glyphicon-trash clickable pull-right" title="delete" ng-click="removeRemoteProjectInfo(productToEdit.remoteProjectInfo, remoteProject)"></span>
</span>
</li>
</ul>
</div>
Expand Down
8 changes: 4 additions & 4 deletions tests/mock/model/mockProduct.js
Expand Up @@ -5,7 +5,7 @@ var dataProduct1 = {
remoteProjectManager: {
id: 1,
name: "Remote Project Manager 1",
type: "VERSION_ONE",
type: "GITHUB_MILESTONE",
url: "url1",
token: "username1:password1"
},
Expand All @@ -18,8 +18,8 @@ var dataProduct2 = {
name: "Product 2",
remoteProjectInfo: [{
remoteProjectManager: {
id: 1,
name: "Remote Project Manager 1",
id: 2,
name: "Remote Project Manager 2",
type: "VERSION_ONE",
url: "url2",
token: "username2:password2"
Expand All @@ -35,7 +35,7 @@ var dataProduct3 = {
remoteProjectManager: {
id: 1,
name: "Remote Project Manager 1",
type: "VERSION_ONE",
type: "GITHUB_MILESTONE",
url: "url1",
token: "username1:password1"
},
Expand Down
23 changes: 23 additions & 0 deletions tests/unit/controllers/productControllerTest.js
Expand Up @@ -99,6 +99,7 @@ describe("controller: ProductController", function () {
"confirmDeleteProduct",
"createProduct",
"deleteProduct",
"distinctRemoteProjectManagers",
"editProduct",
"getRemoteProjectByRemoteProjectInfo",
"getRemoteProjectManagerRemoteProjects",
Expand Down Expand Up @@ -208,6 +209,28 @@ describe("controller: ProductController", function () {
expect($scope.cancelDeleteProduct).toHaveBeenCalled();
});

it("distinctRemoteProjectManagers should return a distinct list", function () {
var response;
var rpis = [
{
scopeId: "0010",
remoteProjectManager: dataRemoteProjectManager1
},
{
scopeId: "0020",
remoteProjectManager: dataRemoteProjectManager2
},
{
scopeId: "0030",
remoteProjectManager: dataRemoteProjectManager1
}
]

response = $scope.distinctRemoteProjectManagers(rpis);

expect(response.length).toEqual(2);
});

it("editProduct set the productToEdit and open the modal", function () {
spyOn($scope, "openModal");

Expand Down
40 changes: 40 additions & 0 deletions tests/unit/directives/remoteProjectsIconDirective.js
@@ -0,0 +1,40 @@
describe("directive: remoteProjectsIcon", function () {
var $compile, $q, $scope, directive, element;

var initializeVariables = function () {
inject(function (_$q_, _$compile_) {
$q = _$q_;
$compile = _$compile_;
});
};

var initializeDirective = function (settings) {
inject(function (_$rootScope_) {
$scope = _$rootScope_.$new();

var attr = settings && settings.attr ? settings.attr : "type=\"GITHUB_MILESTONE\"";
var body = settings && settings.body ? settings.body : "";

element = angular.element("<remote-projects-icon " + attr + ">" + body + "</remote-projects-icon>");
directive = $compile(element)($scope);

$scope.$digest();
});
};

beforeEach(function () {
module("core");
module("app");
module("templates");

installPromiseMatchers();
initializeVariables();
});

describe("Is the directive", function () {
it("defined", function () {
initializeDirective();
expect(directive).toBeDefined();
});
});
});

0 comments on commit 3a75c4e

Please sign in to comment.