Admin Project Group UI
User interface for project group administration. Nothing fancy - I replaced the Projects icon with one that had a plural version (box, boxes). This patch depends on 106507. Change-Id: Ie117bbdf35f385ba016cb5a818cf05cd12ad7361
This commit is contained in:
parent
329f878568
commit
a0cc35c72f
src
app
admin
controller
project_group_admin_controller.jsproject_group_delete_controller.jsproject_group_edit_controller.jsproject_group_item_controller.jsproject_group_new_controller.js
module.jstemplate
services/resource
util/helper
theme/base
89
src/app/admin/controller/project_group_admin_controller.js
Normal file
89
src/app/admin/controller/project_group_admin_controller.js
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Administration controller for project groups.
|
||||
*/
|
||||
angular.module('sb.admin').controller('ProjectGroupAdminController',
|
||||
function ($scope, $modal, ProjectGroup) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* The project groups.
|
||||
*
|
||||
* @type {Array}
|
||||
*/
|
||||
$scope.projectGroups = [];
|
||||
|
||||
/**
|
||||
* The search filter query string.
|
||||
*
|
||||
* @type {string}
|
||||
*/
|
||||
$scope.filterQuery = '';
|
||||
|
||||
/**
|
||||
* Launches the add-project-group modal.
|
||||
*/
|
||||
$scope.addProjectGroup = function () {
|
||||
$modal.open(
|
||||
{
|
||||
templateUrl: 'app/admin/template/project_group_new.html',
|
||||
controller: 'ProjectGroupNewController'
|
||||
}).result.then(function () {
|
||||
// On success, reload the page.
|
||||
$scope.search();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Open up the delete project group modal.
|
||||
*
|
||||
* @param projectGroup
|
||||
*/
|
||||
$scope.deleteProjectGroup = function (projectGroup) {
|
||||
var modalInstance = $modal.open({
|
||||
templateUrl: 'app/admin/template/project_group_delete.html',
|
||||
controller: 'ProjectGroupDeleteController',
|
||||
resolve: {
|
||||
projectGroup: function () {
|
||||
return projectGroup;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Reset the view after successful completion.
|
||||
modalInstance.result.then(
|
||||
function () {
|
||||
$scope.search();
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Execute a search.
|
||||
*/
|
||||
$scope.search = function () {
|
||||
var searchQuery = $scope.filterQuery || '';
|
||||
|
||||
$scope.projectGroups = ProjectGroup.query({
|
||||
title: searchQuery
|
||||
});
|
||||
};
|
||||
|
||||
// Initialize
|
||||
$scope.search();
|
||||
});
|
44
src/app/admin/controller/project_group_delete_controller.js
Normal file
44
src/app/admin/controller/project_group_delete_controller.js
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Controller for the project group delete modal popup.
|
||||
*/
|
||||
angular.module('sb.profile').controller('ProjectGroupDeleteController',
|
||||
function ($scope, projectGroup, $modalInstance) {
|
||||
'use strict';
|
||||
|
||||
$scope.projectGroup = projectGroup;
|
||||
|
||||
// Set our progress flags and clear previous error conditions.
|
||||
$scope.isUpdating = true;
|
||||
$scope.error = {};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
$scope.remove = function () {
|
||||
$scope.projectGroup.$delete(
|
||||
function () {
|
||||
$modalInstance.close('success');
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
$scope.close = function () {
|
||||
$modalInstance.dismiss('cancel');
|
||||
};
|
||||
});
|
203
src/app/admin/controller/project_group_edit_controller.js
Normal file
203
src/app/admin/controller/project_group_edit_controller.js
Normal file
@ -0,0 +1,203 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* New Project Group edit controller.
|
||||
*/
|
||||
angular.module('sb.profile').controller('ProjectGroupEditController',
|
||||
function ($q, $log, $scope, $state, projectGroup, projects, Project,
|
||||
ProjectGroupItem, ArrayUtil) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* The project group we're editing. Resolved by the route.
|
||||
*/
|
||||
$scope.projectGroup = projectGroup;
|
||||
|
||||
/**
|
||||
* The list of projects in this group (Resolved by the route).
|
||||
*/
|
||||
$scope.projects = projects;
|
||||
|
||||
/**
|
||||
* A collection of all project ID's that have been loaded on
|
||||
* initialization. This list is used to determine the project member
|
||||
* diff.
|
||||
*/
|
||||
var loadedIds = [];
|
||||
$scope.projects.forEach(function (project) {
|
||||
loadedIds.push(project.id);
|
||||
});
|
||||
|
||||
/**
|
||||
* UI flag, are we saving?
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
$scope.isSaving = false;
|
||||
|
||||
/**
|
||||
* Project typeahead search method.
|
||||
*/
|
||||
$scope.searchProjects = function (value) {
|
||||
var deferred = $q.defer();
|
||||
Project.query({name: value, limit: 10},
|
||||
function (results) {
|
||||
// Dedupe the results.
|
||||
var idxList = [];
|
||||
for (var i = 0; i < $scope.projects.length; i++) {
|
||||
var project = $scope.projects[i];
|
||||
if (!!project) {
|
||||
idxList.push(project.id);
|
||||
}
|
||||
}
|
||||
|
||||
for (var j = results.length - 1; j >= 0; j--) {
|
||||
var resultId = results[j].id;
|
||||
if (idxList.indexOf(resultId) > -1) {
|
||||
results.splice(j, 1);
|
||||
}
|
||||
}
|
||||
|
||||
deferred.resolve(results);
|
||||
},
|
||||
function (error) {
|
||||
$log.error(error);
|
||||
deferred.resolve([]);
|
||||
});
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats the project name.
|
||||
*/
|
||||
$scope.formatProjectName = function (model) {
|
||||
if (!!model) {
|
||||
return model.name;
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove a project from the list
|
||||
*/
|
||||
$scope.removeProject = function (index) {
|
||||
$scope.projects.splice(index, 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Save the project and the associated groups
|
||||
*/
|
||||
$scope.save = function () {
|
||||
$scope.isSaving = true;
|
||||
|
||||
var promises = [];
|
||||
|
||||
// Get the desired ID's.
|
||||
var desiredIds = [];
|
||||
$scope.projects.forEach(function (project) {
|
||||
desiredIds.push(project.id);
|
||||
});
|
||||
|
||||
// Intersect loaded vs. current to get a list of project
|
||||
// reference to delete.
|
||||
var idsToDelete = ArrayUtil.difference(loadedIds, desiredIds);
|
||||
idsToDelete.forEach(function (id) {
|
||||
|
||||
// Get a deferred promise...
|
||||
var deferred = $q.defer();
|
||||
|
||||
// Construct the item.
|
||||
var item = new ProjectGroupItem({
|
||||
id: id,
|
||||
projectGroupId: projectGroup.id
|
||||
});
|
||||
|
||||
// Delete the item.
|
||||
item.$delete(function (result) {
|
||||
deferred.resolve(result);
|
||||
},
|
||||
function (error) {
|
||||
deferred.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
promises.push(deferred.promise);
|
||||
});
|
||||
|
||||
// Intersect current vs. loaded to get a list of project
|
||||
// reference to delete.
|
||||
var idsToAdd = ArrayUtil.difference(desiredIds, loadedIds);
|
||||
idsToAdd.forEach(function (id) {
|
||||
|
||||
// Get a deferred promise...
|
||||
var deferred = $q.defer();
|
||||
|
||||
// Construct the item.
|
||||
var item = new ProjectGroupItem({
|
||||
id: id,
|
||||
projectGroupId: projectGroup.id
|
||||
});
|
||||
|
||||
// Delete the item.
|
||||
item.$create(function (result) {
|
||||
deferred.resolve(result);
|
||||
},
|
||||
function (error) {
|
||||
deferred.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
promises.push(deferred.promise);
|
||||
});
|
||||
|
||||
|
||||
// Save the project group itself.
|
||||
var deferred = $q.defer();
|
||||
promises.push(deferred.promise);
|
||||
$scope.projectGroup.$update(function (success) {
|
||||
deferred.resolve(success);
|
||||
}, function (error) {
|
||||
$log.error(error);
|
||||
deferred.reject(error);
|
||||
});
|
||||
|
||||
// Roll all the promises into one big happy promise.
|
||||
$q.all(promises).then(
|
||||
function () {
|
||||
$state.go('admin.project_group', {});
|
||||
},
|
||||
function (error) {
|
||||
$log.error(error);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Add project.
|
||||
*/
|
||||
$scope.addProject = function () {
|
||||
$scope.projects.push({});
|
||||
};
|
||||
|
||||
/**
|
||||
* Insert item into the project list.
|
||||
*/
|
||||
$scope.selectNewProject = function (index, model) {
|
||||
// Put our model into the array
|
||||
$scope.projects[index] = model;
|
||||
};
|
||||
});
|
44
src/app/admin/controller/project_group_item_controller.js
Normal file
44
src/app/admin/controller/project_group_item_controller.js
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Controller for the project group member list.
|
||||
*/
|
||||
angular.module('sb.admin').controller('ProjectGroupItemController',
|
||||
function ($scope, $log, ProjectGroupItem) {
|
||||
'use strict';
|
||||
|
||||
$scope.projectGroupItems = [];
|
||||
$scope.loadingProjectGroupItems = false;
|
||||
|
||||
if (!$scope.projectGroup) {
|
||||
return;
|
||||
}
|
||||
|
||||
var id = $scope.projectGroup.id;
|
||||
|
||||
$scope.loadingProjectGroupItems = true;
|
||||
ProjectGroupItem.query({
|
||||
projectGroupId: id
|
||||
},
|
||||
function (results) {
|
||||
$scope.loadingProjectGroupItems = false;
|
||||
$scope.projectGroupItems = results;
|
||||
}, function (error) {
|
||||
$log.error(error);
|
||||
$scope.loadingProjectGroupItems = false;
|
||||
});
|
||||
});
|
169
src/app/admin/controller/project_group_new_controller.js
Normal file
169
src/app/admin/controller/project_group_new_controller.js
Normal file
@ -0,0 +1,169 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* New Project Group modal controller.
|
||||
*/
|
||||
angular.module('sb.profile').controller('ProjectGroupNewController',
|
||||
function ($q, $log, $scope, $modalInstance, ProjectGroup, ProjectGroupItem,
|
||||
Project) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Flag for the UI to indicate that we're saving.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
$scope.isSaving = false;
|
||||
|
||||
/**
|
||||
* The list of projects.
|
||||
*
|
||||
* @type {{}[]}
|
||||
*/
|
||||
$scope.projects = [
|
||||
{}
|
||||
];
|
||||
|
||||
/**
|
||||
* The new project group.
|
||||
*
|
||||
* @type {ProjectGroup}
|
||||
*/
|
||||
$scope.projectGroup = new ProjectGroup();
|
||||
|
||||
/**
|
||||
* Project typeahead search method.
|
||||
*/
|
||||
$scope.searchProjects = function (value) {
|
||||
var deferred = $q.defer();
|
||||
Project.query({name: value, limit: 10},
|
||||
function (results) {
|
||||
// Dedupe the results.
|
||||
var idxList = [];
|
||||
for (var i = 0; i < $scope.projects.length; i++) {
|
||||
var project = $scope.projects[i];
|
||||
if (!!project) {
|
||||
idxList.push(project.id);
|
||||
}
|
||||
}
|
||||
|
||||
for (var j = results.length - 1; j >= 0; j--) {
|
||||
var resultId = results[j].id;
|
||||
if (idxList.indexOf(resultId) > -1) {
|
||||
results.splice(j, 1);
|
||||
}
|
||||
}
|
||||
|
||||
deferred.resolve(results);
|
||||
},
|
||||
function (error) {
|
||||
$log.error(error);
|
||||
deferred.resolve([]);
|
||||
});
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats the project name.
|
||||
*/
|
||||
$scope.formatProjectName = function (model) {
|
||||
if (!!model) {
|
||||
return model.name;
|
||||
}
|
||||
return '';
|
||||
};
|
||||
|
||||
/**
|
||||
* Add project.
|
||||
*/
|
||||
$scope.addProject = function () {
|
||||
$scope.projects.push({});
|
||||
};
|
||||
|
||||
/**
|
||||
* Insert item into the project list.
|
||||
*/
|
||||
$scope.selectNewProject = function (index, model) {
|
||||
// Put our model into the array
|
||||
$scope.projects[index] = model;
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove a project from the list.
|
||||
*/
|
||||
$scope.removeProject = function (index) {
|
||||
$scope.projects.splice(index, 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* Saves the project group
|
||||
*/
|
||||
$scope.save = function () {
|
||||
$scope.isSaving = true;
|
||||
|
||||
// Create a new project group
|
||||
$scope.projectGroup.$save(function (projectGroup) {
|
||||
$modalInstance.close(projectGroup);
|
||||
|
||||
var promises = [];
|
||||
$scope.projects.forEach(
|
||||
function (project) {
|
||||
// Get a deferred promise...
|
||||
var deferred = $q.defer();
|
||||
|
||||
// Construct the item.
|
||||
var item = new ProjectGroupItem({
|
||||
id: project.id,
|
||||
projectGroupId: projectGroup.id
|
||||
});
|
||||
|
||||
// Create the item.
|
||||
item.$create(function (result) {
|
||||
deferred.resolve(result);
|
||||
},
|
||||
function (error) {
|
||||
deferred.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
promises.push(deferred.promise);
|
||||
}
|
||||
);
|
||||
|
||||
// Wait for all the promises to finish.
|
||||
$q.all(promises, function () {
|
||||
$modalInstance.close(projectGroup);
|
||||
}, function (error) {
|
||||
$log.error(error);
|
||||
$modalInstance.dismiss(error);
|
||||
});
|
||||
|
||||
|
||||
}, function (error) {
|
||||
$scope.isSaving = false;
|
||||
$log.error(error);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Close this modal without saving.
|
||||
*/
|
||||
$scope.close = function () {
|
||||
$modalInstance.dismiss('cancel');
|
||||
};
|
||||
|
||||
});
|
@ -17,12 +17,13 @@
|
||||
/**
|
||||
* The StoryBoard administration module.
|
||||
*/
|
||||
angular.module('sb.admin', [ 'sb.services', 'sb.templates', 'ui.router'])
|
||||
angular.module('sb.admin', [ 'sb.services', 'sb.templates', 'sb.util',
|
||||
'ui.router'])
|
||||
.config(function ($stateProvider, $urlRouterProvider, PermissionResolver) {
|
||||
'use strict';
|
||||
|
||||
// Routing Defaults.
|
||||
$urlRouterProvider.when('/admin', '/admin/index');
|
||||
$urlRouterProvider.when('/admin', '/admin/project_group');
|
||||
|
||||
// Declare the states for this module.
|
||||
$stateProvider
|
||||
@ -35,8 +36,24 @@ angular.module('sb.admin', [ 'sb.services', 'sb.templates', 'ui.router'])
|
||||
.requirePermission('is_superuser', true)
|
||||
}
|
||||
})
|
||||
.state('admin.index', {
|
||||
url: '/index',
|
||||
templateUrl: 'app/admin/template/index.html'
|
||||
.state('admin.project_group', {
|
||||
url: '/project_group',
|
||||
templateUrl: 'app/admin/template/project_group.html',
|
||||
controller: 'ProjectGroupAdminController'
|
||||
})
|
||||
.state('admin.project_group_edit', {
|
||||
url: '/project_group/:id',
|
||||
templateUrl: 'app/admin/template/project_group_edit.html',
|
||||
controller: 'ProjectGroupEditController',
|
||||
resolve: {
|
||||
projectGroup: function ($stateParams, ProjectGroup) {
|
||||
return ProjectGroup.get({id: $stateParams.id}).$promise;
|
||||
},
|
||||
projects: function ($stateParams, ProjectGroupItem) {
|
||||
return ProjectGroupItem.query(
|
||||
{projectGroupId: $stateParams.id}
|
||||
).$promise;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
@ -1,25 +0,0 @@
|
||||
<!--
|
||||
~ 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">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<h1>StoryBoard Administration</h1>
|
||||
|
||||
<p>No admin functions are defined yet. </p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
144
src/app/admin/template/project_group.html
Normal file
144
src/app/admin/template/project_group.html
Normal file
@ -0,0 +1,144 @@
|
||||
<!--
|
||||
~ 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">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<h1><i class="fa fa-sb-project-group"></i> Project Groups</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-3 col-sm-4 col-xs-10">
|
||||
<div class="has-feedback has-feedback-no-label">
|
||||
<input id="projectInput"
|
||||
type="text"
|
||||
class="form-control"
|
||||
ng-model="filterQuery"
|
||||
required
|
||||
ng-disabled="!projectGroups.$resolved"
|
||||
ng-enter="search()"
|
||||
placeholder="Search Project Groups">
|
||||
<span class="form-control-feedback text-muted
|
||||
form-control-feedback-sm">
|
||||
<i class="fa fa-refresh fa-spin"
|
||||
ng-hide="projectGroups.$resolved"></i>
|
||||
<i class="fa fa-search"
|
||||
ng-show="projectGroups.$resolved"></i>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-sm-5 hidden-xs">
|
||||
<div class="form form-horizontal">
|
||||
<p class="form-control-static text-muted">
|
||||
({{projectGroups.length}} found)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-3 col-xs-2">
|
||||
<button class="btn btn-primary pull-right"
|
||||
ng-click="addProjectGroup()">
|
||||
<i class="fa fa-plus"></i>
|
||||
<span class="hidden-xs">Add Project Group</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12">
|
||||
<!-- Spacer -->
|
||||
<br/>
|
||||
<table class="table table-condensed table-striped">
|
||||
|
||||
<tbody ng-if="!projectGroups.$resolved">
|
||||
<tr>
|
||||
<td>
|
||||
<span class="text-muted text-center">
|
||||
<i class="fa fa-spin fa-refresh"></i>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<tbody ng-if="projectGroups.$resolved && projectGroups.length == 0">
|
||||
<tr>
|
||||
<td class="text-center">
|
||||
<em class="text-muted">
|
||||
No project groups found.
|
||||
</em>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<tbody ng-if="projectGroups.$resolved && projectGroups.length > 0">
|
||||
<tr ng-repeat="projectGroup in projectGroups">
|
||||
<td class="col-sm-3 col-xs-4">
|
||||
<i class="fa fa-sb-project-group text-muted"></i>
|
||||
<a href="#!/admin/project_group/{{projectGroup.id}}">
|
||||
{{projectGroup.title}}
|
||||
</a>
|
||||
</td>
|
||||
<td class="col-sm-9 col-xs-8"
|
||||
ng-controller="ProjectGroupItemController">
|
||||
<div class="pull-right btn-group btn-group-xs">
|
||||
<a class="btn btn-link "
|
||||
href="#!/admin/project_group/{{projectGroup.id}}">
|
||||
<i class="fa fa-edit fa-lg"></i>
|
||||
</a>
|
||||
<a class="btn btn-link "
|
||||
href=""
|
||||
ng-click="deleteProjectGroup(projectGroup)">
|
||||
<i class="fa fa-times fa-lg"></i>
|
||||
</a>
|
||||
</div>
|
||||
<table>
|
||||
<tbody ng-if="loadingProjectGroupItems">
|
||||
<tr>
|
||||
<td>
|
||||
<span class="text-muted text-center">
|
||||
<i class="fa fa-spin fa-refresh"></i>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<tbody ng-if="projectGroupItems.length == 0 && !loadingProjectGroupItems">
|
||||
<tr>
|
||||
<td>
|
||||
<em class="text-muted">
|
||||
This group does not contain any
|
||||
projects.
|
||||
</em>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
<tbody ng-if="projectGroupItems.length > 0">
|
||||
<tr ng-repeat="project in projectGroupItems">
|
||||
<td>
|
||||
<a href="#!/project/{{project.id}}">
|
||||
<i class="fa fa-sb-project text-muted"></i>
|
||||
{{project.name}}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
41
src/app/admin/template/project_group_delete.html
Normal file
41
src/app/admin/template/project_group_delete.html
Normal file
@ -0,0 +1,41 @@
|
||||
<!--
|
||||
~ 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="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<button type="button" class="close" aria-hidden="true"
|
||||
ng-click="close()">×</button>
|
||||
<h3 class="panel-title">{{projectGroup.title}}</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
<div class="col-sm-8 col-sm-offset-2">
|
||||
<h2 class="text-danger text-center">
|
||||
Are you certain that you want to delete this project group?
|
||||
</h2>
|
||||
|
||||
<p class="text-center lead">
|
||||
This action cannot be undone.
|
||||
</p>
|
||||
|
||||
<div class="text-center">
|
||||
<a href="" class="btn btn-danger" ng-click="remove()">
|
||||
Remove this project group
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
140
src/app/admin/template/project_group_edit.html
Normal file
140
src/app/admin/template/project_group_edit.html
Normal file
@ -0,0 +1,140 @@
|
||||
<!--
|
||||
~ 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">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<h1><i class="fa fa-sb-project-group"></i> {{projectGroup.title}}
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<form class="form-horizontal"
|
||||
role="form"
|
||||
name="projectGroupForm">
|
||||
<div class="form-group">
|
||||
<label for="title" class="col-sm-2 control-label">
|
||||
Title:
|
||||
</label>
|
||||
|
||||
<div class="col-sm-10">
|
||||
<input id="title"
|
||||
type="text"
|
||||
class="form-control"
|
||||
ng-model="projectGroup.title"
|
||||
required
|
||||
ng-disabled="isSaving"
|
||||
placeholder="Project Group Title">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="name" class="col-sm-2 control-label">
|
||||
URL:
|
||||
</label>
|
||||
|
||||
<div class="col-sm-10">
|
||||
<input id="name"
|
||||
type="text"
|
||||
class="form-control"
|
||||
ng-model="projectGroup.name"
|
||||
required
|
||||
ng-disabled="isSaving"
|
||||
placeholder="URL Stub for the project group">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-2 text-right">
|
||||
<label class="control-label">
|
||||
Projects:
|
||||
</label>
|
||||
</div>
|
||||
<div class="col-sm-10">
|
||||
<form role="form" name="projectsForm">
|
||||
<table class="table table-striped table-outlined">
|
||||
<tbody>
|
||||
<tr ng-repeat="(index, project) in projects"
|
||||
ng-include
|
||||
src="'/inline/project_row.html'">
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-4 col-xs-offset-2">
|
||||
<button type="button"
|
||||
class="btn btn-default"
|
||||
ng-disabled="isSaving"
|
||||
ng-click="addProject()">
|
||||
+
|
||||
Add another project
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-xs-6 text-right">
|
||||
<button type="button"
|
||||
class="btn btn-primary"
|
||||
ng-click="save()"
|
||||
ng-disabled="!projectGroupForm.$valid || !projectsForm.$valid || isSaving">
|
||||
Save
|
||||
</button>
|
||||
<a href="#!/admin/project_group"
|
||||
ng-disabled="isSaving"
|
||||
class="btn btn-default">
|
||||
Cancel
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Template for story metadata -->
|
||||
<script type="text/ng-template" id="/inline/project_row.html">
|
||||
<td class="col-xs-11">
|
||||
<div class="has-feedback has-feedback-no-label">
|
||||
<input id="project"
|
||||
type="text"
|
||||
placeholder="Select a Project"
|
||||
required
|
||||
ng-model="project"
|
||||
typeahead-editable="false"
|
||||
typeahead="project as project.name for project
|
||||
in searchProjects($viewValue)"
|
||||
typeahead-loading="loadingProjects"
|
||||
typeahead-on-select="selectNewProject(index, $model)"
|
||||
typeahead-input-formatter="formatProjectName($model)"
|
||||
ng-disabled="isSaving"
|
||||
class="form-control input-sm"
|
||||
/>
|
||||
<span class="form-control-feedback text-muted
|
||||
form-control-feedback-sm">
|
||||
<i class="fa fa-refresh fa-spin" ng-show="loadingProjects"></i>
|
||||
<i class="fa fa-search" ng-hide="loadingProjects"></i>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<th class="col-xs-1"
|
||||
ng-show="projects.length > 1">
|
||||
<button type="button" class="close"
|
||||
ng-click="removeProject(index)">
|
||||
×
|
||||
</button>
|
||||
</th>
|
||||
</script>
|
136
src/app/admin/template/project_group_new.html
Normal file
136
src/app/admin/template/project_group_new.html
Normal file
@ -0,0 +1,136 @@
|
||||
<!--
|
||||
~ 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="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<button type="button" class="close" aria-hidden="true"
|
||||
ng-click="close()">×</button>
|
||||
<h3 class="panel-title">New Project Group</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<form class="form-horizontal"
|
||||
role="form"
|
||||
name="projectGroupForm">
|
||||
<div class="form-group">
|
||||
<label for="title" class="col-sm-2 control-label">
|
||||
Title:
|
||||
</label>
|
||||
|
||||
<div class="col-sm-10">
|
||||
<input id="title"
|
||||
type="text"
|
||||
class="form-control"
|
||||
ng-model="projectGroup.title"
|
||||
required
|
||||
ng-disabled="isSaving"
|
||||
placeholder="Project Group Title">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="name" class="col-sm-2 control-label">
|
||||
URL:
|
||||
</label>
|
||||
|
||||
<div class="col-sm-10">
|
||||
<input id="name"
|
||||
type="text"
|
||||
class="form-control"
|
||||
ng-model="projectGroup.name"
|
||||
required
|
||||
ng-disabled="isSaving"
|
||||
placeholder="URL Stub for the project group">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<form role="form" name="projectsForm">
|
||||
<table class="table table-striped table-outlined">
|
||||
<tbody>
|
||||
<tr ng-repeat="(index, project) in projects"
|
||||
ng-include
|
||||
src="'/inline/project_row.html'">
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-6">
|
||||
<button type="button"
|
||||
class="btn btn-default"
|
||||
ng-disabled="isSaving"
|
||||
ng-click="addProject()">
|
||||
+
|
||||
Add another project
|
||||
</button>
|
||||
</div>
|
||||
<div class="col-xs-6 text-right">
|
||||
<button type="button"
|
||||
class="btn btn-primary"
|
||||
ng-click="save()"
|
||||
ng-disabled="!projectGroupForm.$valid || !projectsForm.$valid || isSaving">
|
||||
Save Changes
|
||||
</button>
|
||||
<button type="button"
|
||||
ng-click="close()"
|
||||
ng-disabled="isSaving"
|
||||
class="btn btn-default">
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Template for story metadata -->
|
||||
<script type="text/ng-template" id="/inline/project_row.html">
|
||||
<td class="col-xs-11">
|
||||
<div class="has-feedback has-feedback-no-label">
|
||||
<input id="project"
|
||||
type="text"
|
||||
placeholder="Select a Project"
|
||||
required
|
||||
ng-model="project"
|
||||
typeahead-editable="false"
|
||||
typeahead="project as project.name for project
|
||||
in searchProjects($viewValue)"
|
||||
typeahead-loading="loadingProjects"
|
||||
typeahead-on-select="selectNewProject(index, $model)"
|
||||
typeahead-input-formatter="formatProjectName($model)"
|
||||
ng-disabled="isSaving"
|
||||
class="form-control input-sm"
|
||||
/>
|
||||
<span class="form-control-feedback text-muted
|
||||
form-control-feedback-sm">
|
||||
<i class="fa fa-refresh fa-spin" ng-show="loadingProjects"></i>
|
||||
<i class="fa fa-search" ng-hide="loadingProjects"></i>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<th class="col-xs-1"
|
||||
ng-show="projects.length > 1">
|
||||
<button type="button" class="close"
|
||||
ng-click="removeProject(index)">
|
||||
×
|
||||
</button>
|
||||
</th>
|
||||
</script>
|
50
src/app/services/resource/project_group_item.js
Normal file
50
src/app/services/resource/project_group_item.js
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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 angular resource abstraction that allows us to access children of
|
||||
* project groups.
|
||||
*
|
||||
* @author Michael Krotscheck
|
||||
*/
|
||||
angular.module('sb.services').factory('ProjectGroupItem',
|
||||
function ($resource, storyboardApiBase) {
|
||||
'use strict';
|
||||
return $resource(storyboardApiBase +
|
||||
'/project_groups/:projectGroupId/projects/:id',
|
||||
{
|
||||
projectGroupId: '@projectGroupId',
|
||||
id: '@id'
|
||||
},
|
||||
{
|
||||
'create': {
|
||||
method: 'PUT',
|
||||
transformRequest: function () {
|
||||
// The API endpoint takes no payload.
|
||||
return '';
|
||||
}
|
||||
},
|
||||
'delete': {
|
||||
method: 'DELETE'
|
||||
},
|
||||
'query': {
|
||||
method: 'GET',
|
||||
isArray: true,
|
||||
responseType: 'json'
|
||||
}
|
||||
}
|
||||
);
|
||||
});
|
64
src/app/util/helper/array_util.js
Normal file
64
src/app/util/helper/array_util.js
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Array utilities.
|
||||
*/
|
||||
angular.module('sb.util').factory('ArrayUtil',
|
||||
function () {
|
||||
'use strict';
|
||||
|
||||
return {
|
||||
|
||||
/**
|
||||
* Performs a logical intersection on two arrays. Given A, and B,
|
||||
* returns A∩B, the set of all objects that are in both A and B.
|
||||
*
|
||||
* @param A
|
||||
* @param B
|
||||
*/
|
||||
intersection: function (A, B) {
|
||||
var result = [];
|
||||
A.forEach(function (item) {
|
||||
if (B.indexOf(item) > -1) {
|
||||
result.push(item);
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
/**
|
||||
* Performs a logical difference operation on the two
|
||||
* arrays. Given sets U and A it will return U\A, the set of all
|
||||
* members of U that are not members of A.
|
||||
*
|
||||
* @param U
|
||||
* @param A
|
||||
*/
|
||||
difference: function (U, A) {
|
||||
var result = [];
|
||||
U.forEach(function (item) {
|
||||
if (A.indexOf(item) === -1) {
|
||||
result.push(item);
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
}
|
||||
);
|
@ -23,4 +23,5 @@
|
||||
.@{fa-css-prefix}-sb-user:before { content: @fa-var-user; }
|
||||
.@{fa-css-prefix}-sb-task:before { content: @fa-var-tag; }
|
||||
.@{fa-css-prefix}-sb-story:before { content: @fa-var-list-ul; }
|
||||
.@{fa-css-prefix}-sb-project:before { content: @fa-var-flag; }
|
||||
.@{fa-css-prefix}-sb-project:before { content: @fa-var-cube; }
|
||||
.@{fa-css-prefix}-sb-project-group:before { content: @fa-var-cubes; }
|
||||
|
Loading…
x
Reference in New Issue
Block a user