Added project group list and detail view.
Reused several components from the existing list search, as well as other parts from project views, to create a rudimentary list of project groups. Also created a detail page that shows member projects and stories, and lastly added a quicknav option into the header quicknav. Change-Id: Ie29dacb6c6fda47c0e59fa054da9c259a9a59797
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
/**
|
||||
* Project group detail controller, for general user use of project groups.
|
||||
* From a feature standpoint this really just means viewing the group, member
|
||||
* projects, and any stories that belong under this project group.
|
||||
*/
|
||||
angular.module('sb.project_group').controller('ProjectGroupDetailController',
|
||||
function ($scope, projectGroup, projects, stories) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* The project group we're viewing right now.
|
||||
*
|
||||
* @type ProjectGroup
|
||||
*/
|
||||
$scope.projectGroup = projectGroup;
|
||||
|
||||
/**
|
||||
* The list of projects in this group
|
||||
*
|
||||
* @type [Project]
|
||||
*/
|
||||
$scope.projects = projects;
|
||||
|
||||
/**
|
||||
* The list of stories in this project group
|
||||
*
|
||||
* @type [Story]
|
||||
*/
|
||||
$scope.stories = stories;
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A Project
|
||||
*/
|
||||
angular.module('sb.project_group').controller('ProjectGroupListController',
|
||||
function ($scope) {
|
||||
'use strict';
|
||||
|
||||
// search results must be of type "ProjectGroup"
|
||||
$scope.resourceTypes = ['ProjectGroup'];
|
||||
|
||||
// Projects have no default criteria
|
||||
$scope.defaultCriteria = [];
|
||||
});
|
||||
87
src/app/project_group/module.js
Normal file
87
src/app/project_group/module.js
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||
*
|
||||
* 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 StoryBoard project group submodule handles most activity involving
|
||||
* searching for and reviewing project groups. Administration of project groups
|
||||
* lives in the admin module.
|
||||
*/
|
||||
angular.module('sb.project_group',
|
||||
['ui.router', 'sb.services', 'sb.util', 'sb.auth'])
|
||||
.config(function ($stateProvider, $urlRouterProvider, PermissionResolver) {
|
||||
'use strict';
|
||||
|
||||
// Routing Defaults.
|
||||
$urlRouterProvider.when('/project_group', '/project_group/list');
|
||||
|
||||
// Set our page routes.
|
||||
$stateProvider
|
||||
.state('project_group', {
|
||||
abstract: true,
|
||||
url: '/project_group',
|
||||
template: '<div ui-view></div>',
|
||||
resolve: {
|
||||
isSuperuser: PermissionResolver
|
||||
.resolvePermission('is_superuser', true)
|
||||
}
|
||||
})
|
||||
.state('project_group.list', {
|
||||
url: '/list',
|
||||
templateUrl: 'app/project_group/template/list.html',
|
||||
controller: 'ProjectGroupListController'
|
||||
})
|
||||
.state('project_group.detail', {
|
||||
url: '/{id:[0-9]+}',
|
||||
templateUrl: 'app/project_group/template/detail.html',
|
||||
controller: 'ProjectGroupDetailController',
|
||||
resolve: {
|
||||
projectGroup: function ($stateParams, ProjectGroup, $q) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
ProjectGroup.get({id: $stateParams.id},
|
||||
function (result) {
|
||||
deferred.resolve(result);
|
||||
}, function (error) {
|
||||
deferred.reject(error);
|
||||
});
|
||||
return deferred.promise;
|
||||
},
|
||||
projects: function($stateParams, Project, $q) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
Project.query({project_group_id: $stateParams.id},
|
||||
function (result) {
|
||||
deferred.resolve(result);
|
||||
}, function (error) {
|
||||
deferred.reject(error);
|
||||
});
|
||||
return deferred.promise;
|
||||
},
|
||||
stories: function($stateParams, Story, $q) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
Story.query({project_group_id: $stateParams.id},
|
||||
function (result) {
|
||||
deferred.resolve(result);
|
||||
}, function (error) {
|
||||
deferred.reject(error);
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
;
|
||||
63
src/app/project_group/template/detail.html
Normal file
63
src/app/project_group/template/detail.html
Normal file
@@ -0,0 +1,63 @@
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<h1>
|
||||
<i class="fa fa-sb-project-group"></i>
|
||||
{{projectGroup.name}}
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-2 text-center text-muted">
|
||||
<span class="hidden-xs">
|
||||
<i class="fa fa-3x fa-sb-project"></i>
|
||||
<br/>
|
||||
<small>Projects</small>
|
||||
</span>
|
||||
<i class="fa fa-2x fa-sb-project visible-xs"></i>
|
||||
</div>
|
||||
<div class="col-xs-10">
|
||||
<table class="table table-condensed table-striped table-clean">
|
||||
<tbody ng-if="projects.length != 0">
|
||||
<tr ng-repeat="project in projects"
|
||||
ng-include="'app/search/template/project_search_item.html'">
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<tbody ng-if=\projects.length == 0">
|
||||
<td class="text-center text-muted">
|
||||
<em>No projects found.</em>
|
||||
</td>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<hr/>
|
||||
</div>
|
||||
<div class="col-xs-2 text-center text-muted">
|
||||
<span class="hidden-xs">
|
||||
<i class="fa fa-3x fa-sb-story"></i>
|
||||
<br/>
|
||||
<small>Stories</small>
|
||||
</span>
|
||||
<i class="fa fa-2x fa-sb-story visible-xs"></i>
|
||||
</div>
|
||||
<div class="col-xs-10">
|
||||
<table class="table table-condensed table-striped table-clean">
|
||||
<tbody ng-if="stories.length != 0">
|
||||
<tr ng-repeat="story in stories"
|
||||
ng-include="'app/search/template/story_search_item.html'">
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<tbody ng-if="stories.length == 0">
|
||||
<td class="text-center text-muted">
|
||||
<em>No stories found.</em>
|
||||
</td>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
132
src/app/project_group/template/list.html
Normal file
132
src/app/project_group/template/list.html
Normal file
@@ -0,0 +1,132 @@
|
||||
<!--
|
||||
~ Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||
~
|
||||
~ 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="container"
|
||||
ng-controller="SearchCriteriaController"
|
||||
ng-init="init(resourceTypes, defaultCriteria)"
|
||||
search-results
|
||||
search-resource="ProjectGroup"
|
||||
search-criteria="criteria"
|
||||
search-without-criteria="true">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<h1><i class="fa fa-sb-project"></i> Project Groups</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-10 col-xs-12">
|
||||
<div class="form-group has-feedback has-feedback-no-label">
|
||||
<div id="search-criteria"
|
||||
tag-complete="criteria as criteria.title for criteria in searchForCriteria($viewValue)"
|
||||
tag-complete-tags="criteria"
|
||||
tag-complete-label-field="title"
|
||||
tag-complete-option-template-url="'app/search/template/typeahead_criteria_item.html'"
|
||||
tag-complete-tag-template-url="'app/search/template/criteria_tag_item.html'"
|
||||
tag-complete-loading="loadingCriteria = isLoading"
|
||||
tag-complete-on-select="addCriteria(tag)"
|
||||
placeholder="Search Project Groups">
|
||||
</div>
|
||||
<span class="form-control-feedback text-muted">
|
||||
<i class="fa fa-search"
|
||||
ng-hide="loadingCriteria"></i>
|
||||
<i class="fa fa-refresh fa-spin"
|
||||
ng-show="loadingCriteria"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-2 hidden-xs">
|
||||
<div class="form form-horizontal">
|
||||
<p class="form-control-static text-muted">
|
||||
({{searchResults.length}} found)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row"
|
||||
ng-if="!hasValidCriteria">
|
||||
<div class="col-xs-12 text-muted text-center">
|
||||
<em>What would you like to search by?</em>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row"
|
||||
ng-if="hasValidCriteria">
|
||||
<div class="col-xs-12">
|
||||
<br/>
|
||||
</div>
|
||||
<div class="col-xs-12">
|
||||
<table class="table table-condensed table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<a ng-click="toggleFilter('name')">
|
||||
Project Group
|
||||
<i class="fa fa-caret-down"
|
||||
ng-if="sortField == 'name' && sortDirection == 'desc'">
|
||||
</i>
|
||||
<i class="fa fa-caret-up"
|
||||
ng-if="sortField == 'name' && sortDirection == 'asc'">
|
||||
</i>
|
||||
</a>
|
||||
</th>
|
||||
<th class="hidden-xs">
|
||||
<a ng-click="toggleFilter('created_at')">
|
||||
Created
|
||||
<i class="fa fa-caret-down"
|
||||
ng-if="sortField == 'created_at' && sortDirection == 'desc'">
|
||||
</i>
|
||||
<i class="fa fa-caret-up"
|
||||
ng-if="sortField == 'created_at' && sortDirection == 'asc'">
|
||||
</i>
|
||||
</a>
|
||||
</th>
|
||||
<th class="hidden-xs">
|
||||
<a ng-click="toggleFilter('updated_at')">
|
||||
Updated
|
||||
<i class="fa fa-caret-down"
|
||||
ng-if="sortField == 'updated_at' && sortDirection == 'desc'">
|
||||
</i>
|
||||
<i class="fa fa-caret-up"
|
||||
ng-if="sortField == 'updated_at' && sortDirection == 'asc'">
|
||||
</i>
|
||||
</a>
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody ng-if="searchResults.length != 0">
|
||||
<tr ng-repeat="projectGroup in searchResults"
|
||||
ng-include="'app/search/template/project_group_search_item.html'">
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<tbody ng-if="searchResults.length == 0 && !isSearching">
|
||||
<td class="text-center text-muted" colspan="3">
|
||||
<em>No project groups found.</em>
|
||||
</td>
|
||||
</tbody>
|
||||
|
||||
<tbody ng-if="isSearching">
|
||||
<td colspan="3">
|
||||
<small class="fa fa-spin fa-refresh text-muted">
|
||||
</small>
|
||||
</td>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
24
src/app/search/template/project_group_search_item.html
Normal file
24
src/app/search/template/project_group_search_item.html
Normal file
@@ -0,0 +1,24 @@
|
||||
<td>
|
||||
<a href="#!/project_group/{{projectGroup.id}}">
|
||||
{{projectGroup.name | truncate: 97}}
|
||||
</a>
|
||||
</td>
|
||||
<td class="hidden-xs">
|
||||
<span time-moment eventdate="projectGroup.created_at">
|
||||
</span>
|
||||
</td>
|
||||
<td class="hidden-xs">
|
||||
<span time-moment
|
||||
ng-if="projectGroup.updated_at"
|
||||
eventdate="projectGroup.updated_at">
|
||||
</span>
|
||||
<em ng-if="!projectGroup.updated_at"
|
||||
class="text-muted">
|
||||
Not updated
|
||||
</em>
|
||||
</td>
|
||||
<td>
|
||||
<subscribe class="pull-right"
|
||||
resource="project_group"
|
||||
resource-id="projectGroup.id"></subscribe>
|
||||
</td>
|
||||
@@ -20,8 +20,8 @@
|
||||
*/
|
||||
angular.module('storyboard').controller('HeaderController',
|
||||
function ($q, $scope, $rootScope, $state, NewStoryService, Session,
|
||||
SessionState, CurrentUser, Criteria, Notification,
|
||||
Priority, Project, Story) {
|
||||
SessionState, CurrentUser, Criteria, Notification, Priority,
|
||||
Project, Story, ProjectGroup) {
|
||||
'use strict';
|
||||
|
||||
function resolveCurrentUser() {
|
||||
@@ -75,6 +75,9 @@ angular.module('storyboard').controller('HeaderController',
|
||||
case 'Text':
|
||||
$state.go('search', {q: criteria.value});
|
||||
break;
|
||||
case 'ProjectGroup':
|
||||
$state.go('project_group.detail', {id: criteria.value});
|
||||
break;
|
||||
case 'Project':
|
||||
$state.go('project.detail', {id: criteria.value});
|
||||
break;
|
||||
@@ -100,9 +103,18 @@ angular.module('storyboard').controller('HeaderController',
|
||||
var searches = [];
|
||||
|
||||
if (searchString.match(/^[0-9]+$/)) {
|
||||
var getProjectGroupDeferred = $q.defer();
|
||||
var getProjectDeferred = $q.defer();
|
||||
var getStoryDeferred = $q.defer();
|
||||
|
||||
ProjectGroup.get({id: searchString},
|
||||
function (result) {
|
||||
getProjectGroupDeferred.resolve(Criteria.create(
|
||||
'ProjectGroup', result.id, result.name
|
||||
));
|
||||
}, function () {
|
||||
getProjectGroupDeferred.resolve(null);
|
||||
});
|
||||
Project.get({id: searchString},
|
||||
function (result) {
|
||||
getProjectDeferred.resolve(Criteria.create(
|
||||
@@ -121,10 +133,12 @@ angular.module('storyboard').controller('HeaderController',
|
||||
});
|
||||
|
||||
// If the search string is entirely numeric, do a GET.
|
||||
searches.push(getProjectGroupDeferred.promise);
|
||||
searches.push(getProjectDeferred.promise);
|
||||
searches.push(getStoryDeferred.promise);
|
||||
|
||||
} else {
|
||||
searches.push(ProjectGroup.criteriaResolver(searchString, 5));
|
||||
searches.push(Project.criteriaResolver(searchString, 5));
|
||||
searches.push(Story.criteriaResolver(searchString, 5));
|
||||
}
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
angular.module('storyboard',
|
||||
[ 'sb.services', 'sb.templates', 'sb.dashboard', 'sb.pages', 'sb.projects',
|
||||
'sb.auth', 'sb.story', 'sb.profile', 'sb.notification', 'sb.search',
|
||||
'sb.admin', 'sb.subscription', 'ui.router', 'ui.bootstrap',
|
||||
'monospaced.elastic', 'angularMoment'])
|
||||
'sb.admin', 'sb.subscription', 'sb.project_group', 'ui.router',
|
||||
'ui.bootstrap', 'monospaced.elastic', 'angularMoment'])
|
||||
.constant('angularMomentConfig', {
|
||||
preprocess: 'utc',
|
||||
timezone: 'UTC'
|
||||
|
||||
@@ -35,7 +35,14 @@
|
||||
<small class="visible-lg visible-md">Dashboard</small>
|
||||
</a>
|
||||
</li>
|
||||
<li active-path="^\/project\/*">
|
||||
<li active-path="^\/project_group\/*">
|
||||
<a href="#!/project_group">
|
||||
<i class="fa fa-sb-project-group fa-lg visible-sm visible-xs"></i>
|
||||
<i class="fa fa-sb-project-group fa-3x visible-lg visible-md"></i>
|
||||
<small class="visible-lg visible-md">Project Groups</small>
|
||||
</a>
|
||||
</li>
|
||||
<li active-path="^\/project[^_]\/*">
|
||||
<a href="#!/project">
|
||||
<i class="fa fa-sb-project fa-lg visible-sm visible-xs"></i>
|
||||
<i class="fa fa-sb-project fa-3x visible-lg visible-md"></i>
|
||||
|
||||
Reference in New Issue
Block a user