MVP Storyboard Client
This patch constitutes the work discussed in Brussels for the MVP webclient. Changes made, as follows: 1- Updated header to contain Overview, Projects, Stories, and a "New Story" button, including mobile treatment. 2- Updated navigation header to use selection styling for mobile and regular. 3- Application index contains new-story button. 4- Main application container now has a minheight. 5- Removed old controllers (code cleanup) before reimplementation. 6- Wired project views (require API support). 7- Wired story views (require API support). 8- Wired new story modal (require API support). 9- New task form (requires API support). 10- Wired up new functional tests and fixed a few issues in existing unit tests. 11- Switched LESS compiler from recess to less, since recess can no longer compile the most recent version of bootstrap. Change-Id: Iddd5b29dd899d92f05ad7a9a63814d8599e167d4
This commit is contained in:
parent
e31dce1163
commit
062836f2dd
25
Gruntfile.js
25
Gruntfile.js
@ -101,7 +101,6 @@ module.exports = function (grunt) {
|
|||||||
concat: {
|
concat: {
|
||||||
dist: {
|
dist: {
|
||||||
src: [
|
src: [
|
||||||
dir.source + '/app/storyboard.js',
|
|
||||||
dir.source + '/app/**/module.js',
|
dir.source + '/app/**/module.js',
|
||||||
dir.source + '/app/**/*.js'
|
dir.source + '/app/**/*.js'
|
||||||
],
|
],
|
||||||
@ -119,19 +118,20 @@ module.exports = function (grunt) {
|
|||||||
* Note: We're using LessCSS here because SASS requires ruby-compass,
|
* Note: We're using LessCSS here because SASS requires ruby-compass,
|
||||||
* and cannot be easily installed with npm.
|
* and cannot be easily installed with npm.
|
||||||
*/
|
*/
|
||||||
recess: {
|
less: {
|
||||||
options: {
|
options: {
|
||||||
includePath: [
|
paths: [
|
||||||
dir.bower + '/bootstrap/less/',
|
dir.bower + '/bootstrap/less',
|
||||||
dir.bower + '/font-awesome/less/'
|
dir.bower + '/font-awesome/less/'
|
||||||
],
|
],
|
||||||
compile: true
|
cleancss: true,
|
||||||
|
strictMath: true,
|
||||||
|
strictUnits: true
|
||||||
},
|
},
|
||||||
theme: {
|
theme: {
|
||||||
src: [
|
files: {
|
||||||
dir.source + '/styles/main.less'
|
'dist/styles/main.css': dir.source + '/styles/main.less'
|
||||||
],
|
}
|
||||||
dest: dir.output + '/styles/main.css'
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -346,17 +346,16 @@ module.exports = function (grunt) {
|
|||||||
watch: {
|
watch: {
|
||||||
concat: {
|
concat: {
|
||||||
files: [
|
files: [
|
||||||
dir.source + '/app/storyboard.js',
|
|
||||||
dir.source + '/app/**/module.js',
|
dir.source + '/app/**/module.js',
|
||||||
dir.source + '/app/**/*.js'
|
dir.source + '/app/**/*.js'
|
||||||
],
|
],
|
||||||
tasks: ['concat']
|
tasks: ['concat']
|
||||||
},
|
},
|
||||||
recess: {
|
less: {
|
||||||
files: [
|
files: [
|
||||||
dir.source + '/styles/**/*.less'
|
dir.source + '/styles/**/*.less'
|
||||||
],
|
],
|
||||||
tasks: ['recess:theme']
|
tasks: ['less:theme']
|
||||||
},
|
},
|
||||||
copy: {
|
copy: {
|
||||||
files: [
|
files: [
|
||||||
@ -505,7 +504,7 @@ module.exports = function (grunt) {
|
|||||||
'jshint',
|
'jshint',
|
||||||
'useminPrepare',
|
'useminPrepare',
|
||||||
'concat',
|
'concat',
|
||||||
'recess',
|
'less',
|
||||||
'imagemin',
|
'imagemin',
|
||||||
'html2js',
|
'html2js',
|
||||||
'copy',
|
'copy',
|
||||||
|
40
bower.json
40
bower.json
@ -1,22 +1,22 @@
|
|||||||
{
|
{
|
||||||
"name": "storyboard-webclient",
|
"name": "storyboard-webclient",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"jquery": "2.0.3",
|
"jquery": "2.0.3",
|
||||||
"font-awesome": "4.0",
|
"font-awesome": "4.0",
|
||||||
"angular": "1.2.9",
|
"angular": "1.2.13",
|
||||||
"angular-resource": "1.2.9",
|
"angular-resource": "1.2.13",
|
||||||
"angular-cookies": "1.2.9",
|
"angular-cookies": "1.2.13",
|
||||||
"angular-sanitize": "1.2.9",
|
"angular-sanitize": "1.2.13",
|
||||||
"bootstrap": "3.0.0",
|
"bootstrap": "3.1.0",
|
||||||
"angular-ui-router": "0.2.7",
|
"angular-ui-router": "0.2.8-bowratic-tedium",
|
||||||
"angular-translate": "1.1.1"
|
"angular-bootstrap": "0.10.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"angular-mocks": "1.2.9",
|
"angular-mocks": "1.2.13",
|
||||||
"angular-scenario": "1.2.9"
|
"angular-scenario": "1.2.13"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
"angular": "1.2.9"
|
"angular": "1.2.13"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
10
package.json
10
package.json
@ -26,13 +26,13 @@
|
|||||||
"grunt-usemin": "2.0.2",
|
"grunt-usemin": "2.0.2",
|
||||||
"grunt-contrib-htmlmin": "0.1.3",
|
"grunt-contrib-htmlmin": "0.1.3",
|
||||||
"grunt-contrib-cssmin": "0.7.0",
|
"grunt-contrib-cssmin": "0.7.0",
|
||||||
|
"grunt-contrib-less": "0.9.0",
|
||||||
"grunt-karma": "0.6.2",
|
"grunt-karma": "0.6.2",
|
||||||
"grunt-contrib-connect": "0.5.0",
|
"grunt-contrib-connect": "0.5.0",
|
||||||
"grunt-contrib-watch": "0.5.3",
|
"grunt-contrib-watch": "0.5.3",
|
||||||
"grunt-contrib-jshint": "0.7.2",
|
"grunt-contrib-jshint": "0.7.2",
|
||||||
"grunt-contrib-uglify": "0.2.7",
|
"grunt-contrib-uglify": "0.2.7",
|
||||||
"grunt-contrib-imagemin": "0.4.0",
|
"grunt-contrib-imagemin": "0.4.0",
|
||||||
"grunt-recess": "0.5.0",
|
|
||||||
"grunt": "0.4.2",
|
"grunt": "0.4.2",
|
||||||
"grunt-cli": "0.1.11",
|
"grunt-cli": "0.1.11",
|
||||||
"matchdep": "0.1.2",
|
"matchdep": "0.1.2",
|
||||||
@ -49,10 +49,10 @@
|
|||||||
"grunt-shell": "0.6.1",
|
"grunt-shell": "0.6.1",
|
||||||
"karma-coverage": "0.1.4",
|
"karma-coverage": "0.1.4",
|
||||||
"grunt-env": "0.4.1",
|
"grunt-env": "0.4.1",
|
||||||
"protractor": "0.15.0",
|
"protractor": "0.19.0",
|
||||||
"grunt-protractor-runner": "0.2.0",
|
"grunt-protractor-runner": "0.2.3",
|
||||||
"selenium-standalone": "2.39.0-2.7.0",
|
"selenium-standalone": "2.39.0-2.7.0",
|
||||||
"karma-html-reporter": "~0.1.1",
|
"karma-html-reporter": "0.1.1",
|
||||||
"grunt-connect-proxy": "~0.1.7"
|
"grunt-connect-proxy": "0.1.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,54 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* View controller for the new project group form. Includes an intermediary
|
|
||||||
* 'saving' flag as well as room for an error response (though until we get
|
|
||||||
* a real API that'll be a bit tricky to test).
|
|
||||||
*/
|
|
||||||
angular.module('sb.project_groups').controller('ProjectGroupNewController',
|
|
||||||
function ($scope, $state, ProjectGroup) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
// View parameters.
|
|
||||||
$scope.newProjectGroup = new ProjectGroup();
|
|
||||||
$scope.isCreating = false;
|
|
||||||
$scope.error = {};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Submits the newly created project. If an error response is received,
|
|
||||||
* assigns it to the view and unsets various flags. The template
|
|
||||||
* should know how to handle it.
|
|
||||||
*/
|
|
||||||
$scope.createProjectGroup = function () {
|
|
||||||
|
|
||||||
// Clear everything and set the progress flag...
|
|
||||||
$scope.isCreating = true;
|
|
||||||
$scope.error = {};
|
|
||||||
|
|
||||||
$scope.newProjectGroup.$create(
|
|
||||||
function () {
|
|
||||||
// Success!
|
|
||||||
$state.go('project_groups.list');
|
|
||||||
},
|
|
||||||
function (error) {
|
|
||||||
// Error received. Ho hum.
|
|
||||||
$scope.isCreating = false;
|
|
||||||
$scope.error = error;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
});
|
|
@ -1,55 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Storyboard project_group submodule handles most activity surrounding the
|
|
||||||
* creation and management of project_groups.
|
|
||||||
*/
|
|
||||||
angular.module('sb.project_groups', ['ui.router', 'sb.services', 'sb.util'])
|
|
||||||
.config(function ($stateProvider, $urlRouterProvider) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
// URL Defaults.
|
|
||||||
$urlRouterProvider.when('/project_groups', '/project_groups/list');
|
|
||||||
|
|
||||||
// Set our page routes.
|
|
||||||
$stateProvider
|
|
||||||
.state('project_groups', {
|
|
||||||
abstract: true,
|
|
||||||
url: '/project_groups',
|
|
||||||
template: '<div ui-view></div>'
|
|
||||||
})
|
|
||||||
.state('project_groups.list', {
|
|
||||||
url: '/list',
|
|
||||||
templateUrl: 'app/templates/project_groups/list.html',
|
|
||||||
controller: 'ProjectGroupListController'
|
|
||||||
})
|
|
||||||
.state('project_groups.edit', {
|
|
||||||
url: '/{id:[0-9]+}/edit',
|
|
||||||
templateUrl: 'app/templates/project_groups/edit.html',
|
|
||||||
controller: 'ProjectGroupDetailController'
|
|
||||||
})
|
|
||||||
.state('project_groups.detail', {
|
|
||||||
url: '/{id:[0-9]+}',
|
|
||||||
templateUrl: 'app/templates/project_groups/detail.html',
|
|
||||||
controller: 'ProjectGroupDetailController'
|
|
||||||
})
|
|
||||||
.state('project_groups.new', {
|
|
||||||
url: '/new',
|
|
||||||
templateUrl: 'app/templates/project_groups/new.html',
|
|
||||||
controller: 'ProjectGroupNewController'
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
|
* Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
* 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
|
* not use this file except in compliance with the License. You may obtain
|
||||||
* a copy of the License at
|
* a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
@ -28,7 +28,7 @@
|
|||||||
* seconds. 3 is preferable.
|
* seconds. 3 is preferable.
|
||||||
*/
|
*/
|
||||||
angular.module('sb.projects').controller('ProjectDetailController',
|
angular.module('sb.projects').controller('ProjectDetailController',
|
||||||
function ($scope, $state, $stateParams, Project) {
|
function ($scope, $state, $stateParams, Project, Story) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// Parse the ID
|
// Parse the ID
|
||||||
@ -43,6 +43,15 @@ angular.module('sb.projects').controller('ProjectDetailController',
|
|||||||
*/
|
*/
|
||||||
$scope.project = {};
|
$scope.project = {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The count of stories for this project.
|
||||||
|
*
|
||||||
|
* TODO(krotscheck): Once we have proper paging requests working,
|
||||||
|
* this should become a count-only request, so we can delegate project
|
||||||
|
* story searches to the ProjectStoryListController.
|
||||||
|
*/
|
||||||
|
$scope.projectStoryCount = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UI flag for when we're initially loading the view.
|
* UI flag for when we're initially loading the view.
|
||||||
*
|
*
|
||||||
@ -98,6 +107,15 @@ angular.module('sb.projects').controller('ProjectDetailController',
|
|||||||
},
|
},
|
||||||
handleServiceError
|
handleServiceError
|
||||||
);
|
);
|
||||||
|
// Load the count of stories while we're at it...
|
||||||
|
Story.query({project: id},
|
||||||
|
function (result, headers) {
|
||||||
|
// Only extract the total header...
|
||||||
|
$scope.projectStoryCount =
|
||||||
|
headers('X-List-Total') || result.length;
|
||||||
|
},
|
||||||
|
handleServiceError
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -118,25 +136,4 @@ angular.module('sb.projects').controller('ProjectDetailController',
|
|||||||
handleServiceError
|
handleServiceError
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Scope method, invoke this when you'd like to delete this project.
|
|
||||||
*/
|
|
||||||
$scope.remove = function () {
|
|
||||||
// Set our progress flags and clear previous error conditions.
|
|
||||||
$scope.isUpdating = true;
|
|
||||||
$scope.error = {};
|
|
||||||
|
|
||||||
// Try to delete.
|
|
||||||
$scope.project.$delete(
|
|
||||||
function () {
|
|
||||||
// The deletion was successful, so head back to the list
|
|
||||||
// view.
|
|
||||||
$scope.isUpdating = false;
|
|
||||||
$state.go('project.list');
|
|
||||||
},
|
|
||||||
handleServiceError
|
|
||||||
);
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
|
* Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
* 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
|
* not use this file except in compliance with the License. You may obtain
|
||||||
* a copy of the License at
|
* a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
@ -24,7 +24,15 @@ angular.module('sb.projects').controller('ProjectListController',
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// Variables and methods available to the template...
|
// Variables and methods available to the template...
|
||||||
$scope.projects = [];
|
|
||||||
|
function resetScope() {
|
||||||
|
$scope.projectCount = 0;
|
||||||
|
$scope.projectOffset = 0;
|
||||||
|
$scope.projectLimit = 10;
|
||||||
|
$scope.projects = [];
|
||||||
|
$scope.error = {};
|
||||||
|
}
|
||||||
|
|
||||||
$scope.searchQuery = '';
|
$scope.searchQuery = '';
|
||||||
$scope.isSearching = false;
|
$scope.isSearching = false;
|
||||||
|
|
||||||
@ -33,18 +41,25 @@ angular.module('sb.projects').controller('ProjectListController',
|
|||||||
*/
|
*/
|
||||||
$scope.search = function () {
|
$scope.search = function () {
|
||||||
// Clear the scope and set the progress flag.
|
// Clear the scope and set the progress flag.
|
||||||
$scope.error = {};
|
resetScope();
|
||||||
$scope.isSearching = true;
|
$scope.isSearching = true;
|
||||||
$scope.projects = [];
|
|
||||||
|
|
||||||
// Execute the project query.
|
// Execute the project query.
|
||||||
Project.search(
|
Project.query(
|
||||||
// Enable this once the API's there, mocks don't support
|
// Enable this once the API accepts search queries.
|
||||||
// searches yet
|
{ /*q: $scope.searchQuery || ''*/},
|
||||||
{/* q: $scope.searchQuery || '' */},
|
function (result, headers) {
|
||||||
function (result) {
|
|
||||||
|
// Extract metadata from returned headers.
|
||||||
|
var projectCount = headers('X-List-Total') || result.length;
|
||||||
|
var projectOffset = headers('X-List-Offset') || 0;
|
||||||
|
var projectLimit = headers('X-List-Limit') || result.length;
|
||||||
|
|
||||||
// Successful search results, apply the results to the
|
// Successful search results, apply the results to the
|
||||||
// scope and unset our progress flag.
|
// scope and unset our progress flag.
|
||||||
|
$scope.projectCount = projectCount;
|
||||||
|
$scope.projectOffset = projectOffset;
|
||||||
|
$scope.projectLimit = projectLimit;
|
||||||
$scope.projects = result;
|
$scope.projects = result;
|
||||||
$scope.isSearching = false;
|
$scope.isSearching = false;
|
||||||
},
|
},
|
||||||
@ -58,5 +73,6 @@ angular.module('sb.projects').controller('ProjectListController',
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Initialize the view with a default search.
|
// Initialize the view with a default search.
|
||||||
|
resetScope();
|
||||||
$scope.search();
|
$scope.search();
|
||||||
});
|
});
|
||||||
|
@ -15,16 +15,33 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The projectGroup list controller handles discovery for all projectGroups,
|
* This controller manages stories within the scope of a particular project.
|
||||||
* including search. Note that it is assumed that we implemented a search
|
|
||||||
* (inclusive), rather than a browse (exclusive) approach.
|
|
||||||
*/
|
*/
|
||||||
angular.module('sb.project_groups').controller('ProjectGroupListController',
|
angular.module('sb.projects').controller('ProjectStoryListController',
|
||||||
function ($scope, ProjectGroup) {
|
function ($scope, $state, $stateParams, Story, NewStoryService) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
// Parse the ID. Since we're in a nested state, we don't really need
|
||||||
|
// to sanity check here, but in case of a future refactor we'll
|
||||||
|
// go ahead and do so anyway.
|
||||||
|
var id = $stateParams.hasOwnProperty('id') ?
|
||||||
|
parseInt($stateParams.id, 10) :
|
||||||
|
null;
|
||||||
|
|
||||||
|
if (id === null) {
|
||||||
|
$state.go('index');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Variables and methods available to the template...
|
// Variables and methods available to the template...
|
||||||
$scope.projectGroups = [];
|
function resetScope() {
|
||||||
|
$scope.storyCount = 0;
|
||||||
|
$scope.storyOffset = 0;
|
||||||
|
$scope.storyLimit = 10;
|
||||||
|
$scope.stories = [];
|
||||||
|
$scope.error = {};
|
||||||
|
}
|
||||||
|
|
||||||
$scope.searchQuery = '';
|
$scope.searchQuery = '';
|
||||||
$scope.isSearching = false;
|
$scope.isSearching = false;
|
||||||
|
|
||||||
@ -33,19 +50,25 @@ angular.module('sb.project_groups').controller('ProjectGroupListController',
|
|||||||
*/
|
*/
|
||||||
$scope.search = function () {
|
$scope.search = function () {
|
||||||
// Clear the scope and set the progress flag.
|
// Clear the scope and set the progress flag.
|
||||||
$scope.error = {};
|
resetScope();
|
||||||
$scope.isSearching = true;
|
$scope.isSearching = true;
|
||||||
$scope.projectGroups = [];
|
|
||||||
|
|
||||||
// Execute the projectGroup query.
|
// Execute the story query.
|
||||||
ProjectGroup.search(
|
Story.query(
|
||||||
// Enable this once the API's there, mocks don't support
|
{project: id},
|
||||||
// searches yet
|
function (result, headers) {
|
||||||
{/* q: $scope.searchQuery || '' */},
|
|
||||||
function (result) {
|
// Extract metadata from returned headers.
|
||||||
|
var storyCount = headers('X-List-Total') || result.length;
|
||||||
|
var storyOffset = headers('X-List-Offset') || 0;
|
||||||
|
var storyLimit = headers('X-List-Limit') || result.length;
|
||||||
|
|
||||||
// Successful search results, apply the results to the
|
// Successful search results, apply the results to the
|
||||||
// scope and unset our progress flag.
|
// scope and unset our progress flag.
|
||||||
$scope.projectGroups = result;
|
$scope.storyCount = storyCount;
|
||||||
|
$scope.storyOffset = storyOffset;
|
||||||
|
$scope.storyLimit = storyLimit;
|
||||||
|
$scope.stories = result;
|
||||||
$scope.isSearching = false;
|
$scope.isSearching = false;
|
||||||
},
|
},
|
||||||
function (error) {
|
function (error) {
|
||||||
@ -57,6 +80,11 @@ angular.module('sb.project_groups').controller('ProjectGroupListController',
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.newStory = function () {
|
||||||
|
NewStoryService.showNewStoryModal(id);
|
||||||
|
};
|
||||||
|
|
||||||
// Initialize the view with a default search.
|
// Initialize the view with a default search.
|
||||||
|
resetScope();
|
||||||
$scope.search();
|
$scope.search();
|
||||||
});
|
});
|
@ -22,8 +22,12 @@ angular.module('sb.projects', ['ui.router', 'sb.services', 'sb.util'])
|
|||||||
.config(function ($stateProvider, $urlRouterProvider) {
|
.config(function ($stateProvider, $urlRouterProvider) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// URL Defaults.
|
// Routing Defaults.
|
||||||
$urlRouterProvider.when('/project', '/project/list');
|
$urlRouterProvider.when('/project', '/project/list');
|
||||||
|
$urlRouterProvider.when('/project/{id:[0-9]+}',
|
||||||
|
function ($match) {
|
||||||
|
return '/project/' + $match.id + '/overview';
|
||||||
|
});
|
||||||
|
|
||||||
// Set our page routes.
|
// Set our page routes.
|
||||||
$stateProvider
|
$stateProvider
|
||||||
@ -37,16 +41,29 @@ angular.module('sb.projects', ['ui.router', 'sb.services', 'sb.util'])
|
|||||||
templateUrl: 'app/templates/project/list.html',
|
templateUrl: 'app/templates/project/list.html',
|
||||||
controller: 'ProjectListController'
|
controller: 'ProjectListController'
|
||||||
})
|
})
|
||||||
.state('project.edit', {
|
|
||||||
url: '/{id:[0-9]+}/edit',
|
|
||||||
templateUrl: 'app/templates/project/edit.html',
|
|
||||||
controller: 'ProjectDetailController'
|
|
||||||
})
|
|
||||||
.state('project.detail', {
|
.state('project.detail', {
|
||||||
|
abstract: true,
|
||||||
url: '/{id:[0-9]+}',
|
url: '/{id:[0-9]+}',
|
||||||
templateUrl: 'app/templates/project/detail.html',
|
templateUrl: 'app/templates/project/detail.html',
|
||||||
controller: 'ProjectDetailController'
|
controller: 'ProjectDetailController'
|
||||||
})
|
})
|
||||||
|
.state('project.detail.overview', {
|
||||||
|
url: '/overview',
|
||||||
|
templateUrl: 'app/templates/project/overview.html'
|
||||||
|
})
|
||||||
|
.state('project.detail.edit', {
|
||||||
|
url: '/edit',
|
||||||
|
templateUrl: 'app/templates/project/edit.html'
|
||||||
|
})
|
||||||
|
.state('project.detail.delete', {
|
||||||
|
url: '/delete',
|
||||||
|
templateUrl: 'app/templates/project/delete.html'
|
||||||
|
})
|
||||||
|
.state('project.detail.stories', {
|
||||||
|
url: '/stories',
|
||||||
|
templateUrl: 'app/templates/project/stories.html',
|
||||||
|
controller: 'ProjectStoryListController'
|
||||||
|
})
|
||||||
.state('project.new', {
|
.state('project.new', {
|
||||||
url: '/new',
|
url: '/new',
|
||||||
templateUrl: 'app/templates/project/new.html',
|
templateUrl: 'app/templates/project/new.html',
|
||||||
|
@ -38,9 +38,10 @@ angular.module('sb.services')
|
|||||||
'delete': {
|
'delete': {
|
||||||
method: 'DELETE'
|
method: 'DELETE'
|
||||||
},
|
},
|
||||||
'search': {
|
'query': {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
isArray: true
|
isArray: true,
|
||||||
|
responseType: 'json'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
29
src/app/services/resource/story.js
Normal file
29
src/app/services/resource/story.js
Normal file
@ -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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The angular resource abstraction that allows us to access stories.
|
||||||
|
*
|
||||||
|
* @see storyboardApiSignature
|
||||||
|
*/
|
||||||
|
angular.module('sb.services').factory('Story',
|
||||||
|
function ($resource, storyboardApiBase, storyboardApiSignature) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
return $resource(storyboardApiBase + '/stories/:id',
|
||||||
|
{id: '@id'},
|
||||||
|
storyboardApiSignature);
|
||||||
|
});
|
@ -13,36 +13,25 @@
|
|||||||
* License for the specific language governing permissions and limitations
|
* License for the specific language governing permissions and limitations
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Project group detail & manipulation controller. Usable for any view that
|
* Story detail & manipulation controller.
|
||||||
* wants to view, edit, or delete a project group, though views don't have to
|
|
||||||
* use all the functions therein. Includes flags for busy time, error responses
|
|
||||||
* and more.
|
|
||||||
*
|
|
||||||
* This controller assumes that the $stateParams object is both injectable and
|
|
||||||
* contains an ":id" property that indicates which project should be loaded. At
|
|
||||||
* the moment it will only set a 'isLoading' flag to indicate that data is
|
|
||||||
* loading. If loading the data is anticipated to take longer than 3 seconds,
|
|
||||||
* this will need to be updated to display a sane progress.
|
|
||||||
*
|
|
||||||
* Do not allow loading of this (or any) controller to take longer than 10
|
|
||||||
* seconds. 3 is preferable.
|
|
||||||
*/
|
*/
|
||||||
angular.module('sb.project_groups').controller('ProjectGroupDetailController',
|
angular.module('sb.story').controller('StoryDetailController',
|
||||||
function ($scope, $state, $stateParams, ProjectGroup) {
|
function ($scope, $state, $stateParams, Story, Task) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// Parse the ID
|
// Parse the ID
|
||||||
var id = $stateParams.hasOwnProperty('id') ?
|
var id = $stateParams.hasOwnProperty('storyId') ?
|
||||||
parseInt($stateParams.id, 10) :
|
parseInt($stateParams.storyId, 10) :
|
||||||
null;
|
null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The project group we're manipulating right now.
|
* The story we're manipulating right now.
|
||||||
*
|
|
||||||
* @type ProjectGroup
|
|
||||||
*/
|
*/
|
||||||
$scope.projectGroup = {};
|
$scope.story = {};
|
||||||
|
$scope.tasks = [];
|
||||||
|
$scope.newTask = new Task();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* UI flag for when we're initially loading the view.
|
* UI flag for when we're initially loading the view.
|
||||||
@ -76,6 +65,20 @@ angular.module('sb.project_groups').controller('ProjectGroupDetailController',
|
|||||||
$scope.isUpdating = false;
|
$scope.isUpdating = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the tasks for this story
|
||||||
|
*/
|
||||||
|
function loadTasks() {
|
||||||
|
$scope.tasks = [];
|
||||||
|
|
||||||
|
Task.query(
|
||||||
|
{story: id},
|
||||||
|
function (result) {
|
||||||
|
$scope.tasks = result;
|
||||||
|
},
|
||||||
|
handleServiceError
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Sanity check, do we actually have an ID? (zero is falsy)
|
// Sanity check, do we actually have an ID? (zero is falsy)
|
||||||
if (!id && id !== 0) {
|
if (!id && id !== 0) {
|
||||||
@ -89,18 +92,32 @@ angular.module('sb.project_groups').controller('ProjectGroupDetailController',
|
|||||||
$scope.isLoading = false;
|
$scope.isLoading = false;
|
||||||
} else {
|
} else {
|
||||||
// We've got an ID, so let's load it...
|
// We've got an ID, so let's load it...
|
||||||
ProjectGroup.read(
|
Story.read(
|
||||||
{'id': id},
|
{'id': id},
|
||||||
function (result) {
|
function (result) {
|
||||||
// We've got a result, assign it to the view and unset our
|
// We've got a result, assign it to the view and unset our
|
||||||
// loading flag.
|
// loading flag.
|
||||||
$scope.projectGroup = result;
|
$scope.story = result;
|
||||||
$scope.isLoading = false;
|
$scope.isLoading = false;
|
||||||
},
|
},
|
||||||
handleServiceError
|
handleServiceError
|
||||||
);
|
);
|
||||||
|
|
||||||
|
loadTasks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a task.
|
||||||
|
*/
|
||||||
|
$scope.addTask = function () {
|
||||||
|
$scope.newTask.story_id = id;
|
||||||
|
$scope.newTask.$save(function () {
|
||||||
|
loadTasks();
|
||||||
|
$scope.newTask = new Task();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scope method, invoke this when you want to update the project.
|
* Scope method, invoke this when you want to update the project.
|
||||||
*/
|
*/
|
||||||
@ -110,34 +127,11 @@ angular.module('sb.project_groups').controller('ProjectGroupDetailController',
|
|||||||
$scope.error = {};
|
$scope.error = {};
|
||||||
|
|
||||||
// Invoke the save method and wait for results.
|
// Invoke the save method and wait for results.
|
||||||
$scope.projectGroup.$update(
|
$scope.story.$update(
|
||||||
function () {
|
function (result) {
|
||||||
// Unset our loading flag and navigate to the detail view.
|
// Unset our loading flag and navigate to the detail view.
|
||||||
$scope.isUpdating = false;
|
$scope.isUpdating = false;
|
||||||
$state.go('project_groups.detail', {
|
$state.go('story.detail.overview', {storyId: result.id});
|
||||||
id: $scope.projectGroup.id
|
|
||||||
});
|
|
||||||
},
|
|
||||||
handleServiceError
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Scope method, invoke this when you'd like to delete this project.
|
|
||||||
*/
|
|
||||||
$scope.remove = function () {
|
|
||||||
// Set our progress flags and clear previous error conditions.
|
|
||||||
$scope.isUpdating = true;
|
|
||||||
$scope.error = {};
|
|
||||||
|
|
||||||
// Try to delete.
|
|
||||||
$scope.projectGroup.$delete(
|
|
||||||
function () {
|
|
||||||
// The deletion was successful, so head back to the list
|
|
||||||
// view.
|
|
||||||
$scope.isUpdating = false;
|
|
||||||
$state.go('project_groups.list');
|
|
||||||
},
|
},
|
||||||
handleServiceError
|
handleServiceError
|
||||||
);
|
);
|
@ -15,16 +15,26 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The team list controller handles discovery for all teams, including
|
* Controller for our story list.
|
||||||
* search. Note that it is assumed that we implemented a search (inclusive),
|
|
||||||
* rather than a browse (exclusive) approach.
|
|
||||||
*/
|
*/
|
||||||
angular.module('sb.teams').controller('TeamsListController',
|
angular.module('sb.story').controller('StoryListController',
|
||||||
function ($scope, Team) {
|
function ($scope, $modal, NewStoryService, Story) {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
$scope.newStory = function () {
|
||||||
|
NewStoryService.showNewStoryModal();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// Variables and methods available to the template...
|
// Variables and methods available to the template...
|
||||||
$scope.teams = [];
|
function resetScope() {
|
||||||
|
$scope.storyCount = 0;
|
||||||
|
$scope.storyOffset = 0;
|
||||||
|
$scope.storyLimit = 10;
|
||||||
|
$scope.stories = [];
|
||||||
|
$scope.error = {};
|
||||||
|
}
|
||||||
|
|
||||||
$scope.searchQuery = '';
|
$scope.searchQuery = '';
|
||||||
$scope.isSearching = false;
|
$scope.isSearching = false;
|
||||||
|
|
||||||
@ -33,19 +43,26 @@ angular.module('sb.teams').controller('TeamsListController',
|
|||||||
*/
|
*/
|
||||||
$scope.search = function () {
|
$scope.search = function () {
|
||||||
// Clear the scope and set the progress flag.
|
// Clear the scope and set the progress flag.
|
||||||
$scope.error = {};
|
resetScope();
|
||||||
$scope.isSearching = true;
|
$scope.isSearching = true;
|
||||||
$scope.teams = [];
|
|
||||||
|
|
||||||
// Execute the team search.
|
// Execute the story query.
|
||||||
Team.search(
|
Story.query(
|
||||||
// Enable this once the API's there, mocks don't support
|
// Enable this once the API accepts search queries.
|
||||||
// searches yet
|
{},
|
||||||
{/* q: $scope.searchQuery || '' */},
|
function (result, headers) {
|
||||||
function (result) {
|
|
||||||
|
// Extract metadata from returned headers.
|
||||||
|
var storyCount = headers('X-List-Total') || result.length;
|
||||||
|
var storyOffset = headers('X-List-Offset') || 0;
|
||||||
|
var storyLimit = headers('X-List-Limit') || result.length;
|
||||||
|
|
||||||
// Successful search results, apply the results to the
|
// Successful search results, apply the results to the
|
||||||
// scope and unset our progress flag.
|
// scope and unset our progress flag.
|
||||||
$scope.teams = result;
|
$scope.storyCount = storyCount;
|
||||||
|
$scope.storyOffset = storyOffset;
|
||||||
|
$scope.storyLimit = storyLimit;
|
||||||
|
$scope.stories = result;
|
||||||
$scope.isSearching = false;
|
$scope.isSearching = false;
|
||||||
},
|
},
|
||||||
function (error) {
|
function (error) {
|
||||||
@ -58,5 +75,6 @@ angular.module('sb.teams').controller('TeamsListController',
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Initialize the view with a default search.
|
// Initialize the view with a default search.
|
||||||
|
resetScope();
|
||||||
$scope.search();
|
$scope.search();
|
||||||
});
|
});
|
47
src/app/stories/controllers/story_modal_controller.js
Normal file
47
src/app/stories/controllers/story_modal_controller.js
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* 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 "new story" modal popup.
|
||||||
|
*/
|
||||||
|
angular.module('sb.story').controller('StoryModalController',
|
||||||
|
function ($scope, $modalInstance, params, Project, Story) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
$scope.story = new Story();
|
||||||
|
$scope.projects = Project.query({},
|
||||||
|
function (results) {
|
||||||
|
if (params.projectId !== null) {
|
||||||
|
for (var i = 0; i < results.length; i++) {
|
||||||
|
var project = results[i];
|
||||||
|
if (project.id === params.projectId) {
|
||||||
|
$scope.project = project;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.save = function () {
|
||||||
|
$scope.story.$create(function () {
|
||||||
|
$modalInstance.dismiss('success');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.close = function () {
|
||||||
|
$modalInstance.dismiss('cancel');
|
||||||
|
};
|
||||||
|
});
|
71
src/app/stories/module.js
Normal file
71
src/app/stories/module.js
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* 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 story submodule handles most activity surrounding the
|
||||||
|
* creation and management of stories, their tasks, and comments.
|
||||||
|
*/
|
||||||
|
angular.module('sb.story', ['ui.router', 'sb.services', 'sb.util'])
|
||||||
|
.config(function ($stateProvider, $urlRouterProvider) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
// URL Defaults.
|
||||||
|
$urlRouterProvider.when('/story', '/story/list');
|
||||||
|
$urlRouterProvider.when('/story/{id:[0-9]+}',
|
||||||
|
function ($match) {
|
||||||
|
return '/story/' + $match.id + '/overview';
|
||||||
|
});
|
||||||
|
$urlRouterProvider.when('/story/{storyId:[0-9]+}/task',
|
||||||
|
function ($match) {
|
||||||
|
return '/story/' + $match.storyId + '/overview';
|
||||||
|
});
|
||||||
|
$urlRouterProvider.when('/story/{storyId:[0-9]+}/task/{taskId:[0-9]+}',
|
||||||
|
function ($match) {
|
||||||
|
return '/story/' + $match.storyId +
|
||||||
|
'/task/' + $match.taskId;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set our page routes.
|
||||||
|
$stateProvider
|
||||||
|
.state('story', {
|
||||||
|
abstract: true,
|
||||||
|
url: '/story',
|
||||||
|
template: '<div ui-view></div>'
|
||||||
|
})
|
||||||
|
.state('story.list', {
|
||||||
|
url: '/list',
|
||||||
|
templateUrl: 'app/templates/story/list.html',
|
||||||
|
controller: 'StoryListController'
|
||||||
|
})
|
||||||
|
.state('story.detail', {
|
||||||
|
url: '/{storyId:[0-9]+}',
|
||||||
|
abstract: true,
|
||||||
|
templateUrl: 'app/templates/story/detail.html',
|
||||||
|
controller: 'StoryDetailController'
|
||||||
|
})
|
||||||
|
.state('story.detail.overview', {
|
||||||
|
url: '/overview',
|
||||||
|
templateUrl: 'app/templates/story/overview.html'
|
||||||
|
})
|
||||||
|
.state('story.detail.edit', {
|
||||||
|
url: '/edit',
|
||||||
|
templateUrl: 'app/templates/story/edit.html'
|
||||||
|
})
|
||||||
|
.state('story.detail.delete', {
|
||||||
|
url: '/delete',
|
||||||
|
templateUrl: 'app/templates/story/delete.html'
|
||||||
|
});
|
||||||
|
});
|
47
src/app/stories/services/new_story_service.js
Normal file
47
src/app/stories/services/new_story_service.js
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
angular.module('sb.story')
|
||||||
|
.factory('NewStoryService', function ($modal, $log) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
return {
|
||||||
|
showNewStoryModal: function (projectId) {
|
||||||
|
|
||||||
|
var modalInstance = $modal.open(
|
||||||
|
{
|
||||||
|
templateUrl: 'app/templates/story/new.html',
|
||||||
|
controller: 'StoryModalController',
|
||||||
|
resolve: {
|
||||||
|
params: function () {
|
||||||
|
return {
|
||||||
|
projectId: projectId || null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
modalInstance.result.then(function () {
|
||||||
|
// Do nothing.
|
||||||
|
}, function () {
|
||||||
|
$log.info('Modal dismissed at: ' + new Date());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
27
src/app/storyboard/controllers/header_controller.js
Normal file
27
src/app/storyboard/controllers/header_controller.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* 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 our application header.
|
||||||
|
*/
|
||||||
|
angular.module('storyboard').controller('HeaderController',
|
||||||
|
function ($scope, $modal, NewStoryService) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
$scope.newStory = function () {
|
||||||
|
NewStoryService.showNewStoryModal();
|
||||||
|
};
|
||||||
|
});
|
27
src/app/storyboard/controllers/home_controller.js
Normal file
27
src/app/storyboard/controllers/home_controller.js
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* 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 our home(index) page, currently just a placeholder.
|
||||||
|
*/
|
||||||
|
angular.module('storyboard').controller('HomeController',
|
||||||
|
function ($scope, $modal, NewStoryService) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
$scope.newStory = function () {
|
||||||
|
NewStoryService.showNewStoryModal();
|
||||||
|
};
|
||||||
|
});
|
@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
|
* Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
* 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
|
* not use this file except in compliance with the License. You may obtain
|
||||||
* a copy of the License at
|
* a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
@ -24,7 +24,7 @@
|
|||||||
*/
|
*/
|
||||||
angular.module('storyboard',
|
angular.module('storyboard',
|
||||||
[ 'sb.services', 'sb.templates', 'sb.pages', 'sb.projects', 'sb.auth',
|
[ 'sb.services', 'sb.templates', 'sb.pages', 'sb.projects', 'sb.auth',
|
||||||
'sb.teams', 'sb.project_groups', 'ui.router']
|
'sb.story', 'ui.router', 'ui.bootstrap']
|
||||||
)
|
)
|
||||||
.config(function ($provide, $stateProvider, $urlRouterProvider,
|
.config(function ($provide, $stateProvider, $urlRouterProvider,
|
||||||
$locationProvider, $httpProvider) {
|
$locationProvider, $httpProvider) {
|
||||||
@ -40,7 +40,8 @@ angular.module('storyboard',
|
|||||||
$stateProvider
|
$stateProvider
|
||||||
.state('index', {
|
.state('index', {
|
||||||
url: '/',
|
url: '/',
|
||||||
templateUrl: 'app/templates/index.html'
|
templateUrl: 'app/templates/index.html',
|
||||||
|
controller: 'HomeController'
|
||||||
});
|
});
|
||||||
|
|
||||||
// Attach common request headers out of courtesy to the API
|
// Attach common request headers out of courtesy to the API
|
@ -1,40 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Storyboard team submodule handles most activity surrounding the
|
|
||||||
* creation and management of project teams.
|
|
||||||
*/
|
|
||||||
angular.module('sb.teams', ['ui.router', 'sb.services', 'sb.util'])
|
|
||||||
.config(function ($stateProvider, $urlRouterProvider) {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
// URL Defaults.
|
|
||||||
$urlRouterProvider.when('/teams', '/teams/list');
|
|
||||||
|
|
||||||
// Set our page routes.
|
|
||||||
$stateProvider
|
|
||||||
.state('teams', {
|
|
||||||
abstract: true,
|
|
||||||
url: '/teams',
|
|
||||||
template: '<div ui-view></div>'
|
|
||||||
})
|
|
||||||
.state('teams.list', {
|
|
||||||
url: '/list',
|
|
||||||
templateUrl: 'app/templates/teams/list.html',
|
|
||||||
controller: 'TeamsListController'
|
|
||||||
});
|
|
||||||
});
|
|
@ -21,15 +21,17 @@
|
|||||||
<a href="#!/page/about">About</a>
|
<a href="#!/page/about">About</a>
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6">
|
<div class="col-sm-6 text-right hidden-xs">
|
||||||
<small class="text-right hidden-xs">
|
<small>
|
||||||
Licensed under the
|
Licensed under the
|
||||||
<a href="http://www.apache.org/licenses/LICENSE-2.0"
|
<a href="http://www.apache.org/licenses/LICENSE-2.0"
|
||||||
target="_blank">
|
target="_blank">
|
||||||
Apache License, Version 2.0
|
Apache License, Version 2.0
|
||||||
</a>
|
</a>
|
||||||
</small>
|
</small>
|
||||||
<small class="visible-xs">
|
</div>
|
||||||
|
<div class="col-xs-12 visible-xs">
|
||||||
|
<small>
|
||||||
Licensed under the
|
Licensed under the
|
||||||
<a href="http://www.apache.org/licenses/LICENSE-2.0"
|
<a href="http://www.apache.org/licenses/LICENSE-2.0"
|
||||||
target="_blank">
|
target="_blank">
|
||||||
|
@ -14,48 +14,95 @@
|
|||||||
~ under the License.
|
~ under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<div class="container">
|
<div class="container" ng-controller="HeaderController">
|
||||||
<div class="navbar-header">
|
<div class="navbar-header">
|
||||||
|
<!-- Expand menu button, only visible in mobile view. -->
|
||||||
<button class="navbar-toggle" type="button" data-toggle="collapse"
|
<button class="navbar-toggle" type="button" data-toggle="collapse"
|
||||||
data-target=".sb-navbar-collapse">
|
data-target=".sb-navbar-collapse">
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
<span class="icon-bar"></span>
|
<span class="icon-bar"></span>
|
||||||
</button>
|
</button>
|
||||||
<a href="#!/" class="navbar-brand">
|
|
||||||
<i class="icon icon_openstack"></i> Storyboard
|
<!-- New story button for the mobile view -->
|
||||||
</a>
|
<button type="button"
|
||||||
|
ng-click="newStory()"
|
||||||
|
class="visible-xs new-story-button btn btn-primary btn-sm navbar-btn pull-right"
|
||||||
|
>
|
||||||
|
<i class="fa fa-plus"></i>
|
||||||
|
New Story
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- Brand logo -->
|
||||||
|
<div class="navbar-brand">
|
||||||
|
<a href="#!/">
|
||||||
|
<i class="icon icon_openstack"></i> Storyboard
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<nav class="collapse navbar-collapse sb-navbar-collapse" role="navigation">
|
<ul class="nav navbar-nav collapse navbar-collapse sb-navbar-collapse">
|
||||||
<ul class="nav navbar-nav">
|
|
||||||
<li>
|
<!-- User name, visible in XS only -->
|
||||||
<a href="#!/project_groups">Project Groups</a>
|
<li class="visible-xs">
|
||||||
</li>
|
<p class="navbar-text" ng-show="isLoggedIn">
|
||||||
<li>
|
<i class="fa fa-user"></i>
|
||||||
<a href="#!/project">Projects</a>
|
{{currentUser.firstName}}
|
||||||
</li>
|
{{currentUser.lastName}}
|
||||||
<li>
|
</p>
|
||||||
<a href="#!/teams">Teams</a>
|
</li>
|
||||||
</li>
|
|
||||||
<li>
|
<li>
|
||||||
<a href="#!/stories">Stories</a>
|
<a href="#!/" active-path="^\/$">Overview</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#!/page/about">About</a>
|
<a href="#!/project" active-path="^\/project\/*">Projects</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
<li>
|
||||||
<ul class="nav navbar-nav navbar-right">
|
<a href="#!/story" active-path="^\/story.*">Stories</a>
|
||||||
<li ng-show="isLoggedIn">
|
</li>
|
||||||
<a href="#!/profile">{{currentUser.firstName}}
|
|
||||||
{{currentUser.lastName}} <i class="fa fa-cog"></i></a>
|
<!-- Divider, XS only -->
|
||||||
</li>
|
<li class="visible-xs">
|
||||||
<li ng-show="isLoggedIn">
|
<hr/>
|
||||||
<a href="#!/logout">Log out</a>
|
</li>
|
||||||
</li>
|
<!-- Login/Logout button, XS only. -->
|
||||||
<li ng-hide="isLoggedIn">
|
<li class="visible-xs">
|
||||||
<a href="#!/auth">Log in</a>
|
<a href="#!/auth/login" ng-hide="isLoggedIn">
|
||||||
</li>
|
Log in
|
||||||
</li>
|
</a>
|
||||||
</ul>
|
<a href="#!/auth/logout" ng-show="isLoggedIn">
|
||||||
</nav>
|
Log out
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<!-- User dropdown menu for non-mobile views -->
|
||||||
|
<ul class="nav navbar-nav navbar-right hidden-xs">
|
||||||
|
<li>
|
||||||
|
<button type="button"
|
||||||
|
ng-click="newStory()"
|
||||||
|
class="hidden-xs btn btn-primary btn-sm navbar-btn">
|
||||||
|
<i class="fa fa-plus"></i>
|
||||||
|
New Story
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<!-- Username and logout, non-XS only. -->
|
||||||
|
<li ng-show="isLoggedIn">
|
||||||
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||||
|
<i class="fa fa-user"></i>
|
||||||
|
{{currentUser.firstName}}
|
||||||
|
{{currentUser.lastName}}
|
||||||
|
<i class="fa fa-caret-down"></i>
|
||||||
|
</a>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li>
|
||||||
|
<a href="#!/auth/logout">Logout</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<!-- Login, non-XS only. -->
|
||||||
|
<li ng-hide="isLoggedIn">
|
||||||
|
<a href="#!/auth">Log in</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,19 +1,3 @@
|
|||||||
<!--
|
|
||||||
~ 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="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-12">
|
||||||
@ -22,9 +6,11 @@
|
|||||||
<p class="lead">A task tracking system for inter-related
|
<p class="lead">A task tracking system for inter-related
|
||||||
projects.</p>
|
projects.</p>
|
||||||
|
|
||||||
<p>This page intentionally left blank. It is tentatively slated to
|
<button type="button" class="btn btn-primary"
|
||||||
be replaced by a high-level overview of projects managed
|
ng-click="newStory()">
|
||||||
by storyboard.</p>
|
<i class="fa fa-plus"></i>
|
||||||
|
New Story
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
34
src/app/templates/project/delete.html
Normal file
34
src/app/templates/project/delete.html
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<!--
|
||||||
|
~ 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="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?
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p class="text-center lead">
|
||||||
|
This will set the project to a "deleted" state, and any stories and
|
||||||
|
tasks will no longer be visible.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="text-center">
|
||||||
|
<a href="" class="btn btn-danger btn-disabled">
|
||||||
|
Feature not yet available
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -14,25 +14,44 @@
|
|||||||
~ under the License.
|
~ under the License.
|
||||||
-->
|
-->
|
||||||
<div class="container" ng-show="isLoading">
|
<div class="container" ng-show="isLoading">
|
||||||
<div class="col-xs-12">
|
<div class="row">
|
||||||
<p class="text-center">
|
<p class="text-center">
|
||||||
<i class="fa fa-refresh fa-spin"></i>
|
<i class="fa fa-refresh fa-spin fa-lg"></i>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="container" ng-hide="isLoading">
|
<div class="container" ng-hide="isLoading">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-12">
|
<h1 class="no-border no-margin-bottom">Project detail:
|
||||||
<h1>{{project.name}}</h1>
|
{{project.name}}
|
||||||
|
</h1>
|
||||||
<p>{{project.description}}</p>
|
<ul class="nav nav-tabs nav-tabs-down nav-thick">
|
||||||
<hr/>
|
<li active-path="^\/project\/[0-9]+\/overview.*">
|
||||||
</div>
|
<a href="#!/project/1/overview">
|
||||||
</div>
|
Overview
|
||||||
<div class="row">
|
</a>
|
||||||
<div class="col-xs-12">
|
</li>
|
||||||
Project Detail List TBD.
|
<li active-path="^\/project\/[0-9]+\/stories.*">
|
||||||
</div>
|
<a href="#!/project/1/stories">
|
||||||
|
Stories
|
||||||
|
<span ng-show="!!projectStoryCount">
|
||||||
|
({{projectStoryCount}})
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li active-path="^\/project\/[0-9]+\/edit.*">
|
||||||
|
<a href="#!/project/1/edit">
|
||||||
|
Edit
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li active-path="^\/project\/[0-9]+\/delete.*">
|
||||||
|
<a href="#!/project/1/delete">
|
||||||
|
Delete
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<br/>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row" ui-view></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -13,72 +13,52 @@
|
|||||||
~ License for the specific language governing permissions and limitations
|
~ License for the specific language governing permissions and limitations
|
||||||
~ under the License.
|
~ under the License.
|
||||||
-->
|
-->
|
||||||
<div class="container" ng-show="isLoading">
|
<div class="row">
|
||||||
<div class="col-xs-12">
|
<div class="col-xs-12">
|
||||||
<p class="text-center">
|
<form class="form-horizontal" role="form" name="projectForm">
|
||||||
<i class="fa fa-refresh fa-2x fa-spin"></i>
|
<div class="form-group">
|
||||||
</p>
|
<label for="name" class="col-sm-2 control-label">
|
||||||
</div>
|
Project Name:
|
||||||
</div>
|
</label>
|
||||||
|
|
||||||
<div class="container" ng-hide="isLoading">
|
<div class="col-sm-10">
|
||||||
<div class="row">
|
<input id="name"
|
||||||
<div class="col-xs-12">
|
type="text"
|
||||||
<h1>Project: {{project.name}}</h1>
|
class="form-control"
|
||||||
<hr/>
|
ng-model="project.name"
|
||||||
</div>
|
required
|
||||||
</div>
|
placeholder="Project Name">
|
||||||
<div class="row">
|
</div>
|
||||||
<div class="col-xs-12">
|
</div>
|
||||||
<form class="form-horizontal" role="form" name="projectForm">
|
<div class="form-group">
|
||||||
<div class="form-group">
|
<label for="description"
|
||||||
<label for="name" class="col-sm-2 control-label">
|
class="col-sm-2 control-label">
|
||||||
Project Name:
|
Project Description
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<input id="name"
|
<textarea id="description"
|
||||||
type="text"
|
class="form-control"
|
||||||
class="form-control"
|
ng-model="project.description"
|
||||||
ng-model="project.name"
|
required
|
||||||
required
|
placeholder="A brief project description">
|
||||||
placeholder="Project Name">
|
</textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="description"
|
<div class="col-sm-offset-2 col-sm-10">
|
||||||
class="col-sm-2 control-label">
|
<button type="button"
|
||||||
Project Description
|
ng-click="update()"
|
||||||
</label>
|
class="btn btn-primary"
|
||||||
|
ng-disabled="!projectForm.$valid">
|
||||||
<div class="col-sm-10">
|
Save Changes
|
||||||
<textarea id="description"
|
</button>
|
||||||
class="form-control"
|
<a href="#!/project/list"
|
||||||
ng-model="project.description"
|
class="btn btn-default">
|
||||||
required
|
Cancel
|
||||||
placeholder="A brief project description">
|
</a>
|
||||||
</textarea>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</form>
|
||||||
<div class="form-group">
|
|
||||||
<div class="col-sm-offset-2 col-sm-10">
|
|
||||||
<button type="button"
|
|
||||||
ng-click="update()"
|
|
||||||
class="btn btn-primary"
|
|
||||||
ng-disabled="!projectForm.$valid">
|
|
||||||
Save Changes
|
|
||||||
</button>
|
|
||||||
<button ng-click="remove()"
|
|
||||||
class="btn btn-danger">
|
|
||||||
Delete Project
|
|
||||||
</button>
|
|
||||||
<a href="#!/project/list"
|
|
||||||
class="btn btn-default">
|
|
||||||
Cancel
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
~ Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
|
~ Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
|
||||||
~
|
~
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License"); you may
|
~ 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
|
~ not use this file except in compliance with the License. You may obtain
|
||||||
@ -13,41 +13,35 @@
|
|||||||
~ License for the specific language governing permissions and limitations
|
~ License for the specific language governing permissions and limitations
|
||||||
~ under the License.
|
~ under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-8 col-md-9">
|
<div class="col-xs-12">
|
||||||
<h3 class="no-margin">
|
<h1>{{projectCount}} Projects</h1>
|
||||||
<a href="#!/project/new" class="btn btn-default">
|
|
||||||
<i class="fa fa-plus"></i>
|
|
||||||
</a>
|
|
||||||
Projects
|
|
||||||
</h3>
|
|
||||||
<br class="visible-xs"/>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-4 col-md-3">
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control"
|
|
||||||
placeholder="Search Projects"
|
|
||||||
ng-disabled="isSearching"
|
|
||||||
ng-enter="search()"
|
|
||||||
ng-model="searchQuery"/>
|
|
||||||
<span class="input-group-btn">
|
|
||||||
<button type="button" ng-click="search()"
|
|
||||||
ng-disabled="isSearching"
|
|
||||||
class="btn btn-default">
|
|
||||||
<i class="fa fa-refresh fa-spin"
|
|
||||||
ng-show="isSearching"></i>
|
|
||||||
<i class="fa fa-search"
|
|
||||||
ng-hide="isSearching"></i>
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-12">
|
<div class="col-sm-3 col-xs-10">
|
||||||
<hr/>
|
<div class="btn-group btn-group-justified">
|
||||||
|
<div class="form-group has-feedback has-feedback-no-label">
|
||||||
|
<input type="text"
|
||||||
|
class="form-control input-sm"
|
||||||
|
placeholder="Search Projects"
|
||||||
|
ng-disabled="isSearching"
|
||||||
|
ng-enter="search()"
|
||||||
|
ng-model="searchQuery"/>
|
||||||
|
<span class="fa fa-search form-control-feedback"
|
||||||
|
ng-hide="isSearching"></span>
|
||||||
|
<span class="fa fa-refresh fa-spin form-control-feedback"
|
||||||
|
ng-show="isSearching"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-9 col-xs-2">
|
||||||
|
<a href="#!/project/new"
|
||||||
|
class="pull-right btn btn-default btn-sm">
|
||||||
|
<i class="fa fa-plus"></i>
|
||||||
|
<span class="hidden-xs">New Project</span>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@ -59,29 +53,47 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<table class="table table-striped table-hover table-responsive"
|
<p ng-show="!isSearching && projects.length == 0"
|
||||||
ng-hide="isSearching">
|
class="text-center text-warning">
|
||||||
|
<em> We were unable to find any projects.
|
||||||
|
Perhaps you would like to create one?</em>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<table class="table table-striped"
|
||||||
|
ng-hide="isSearching || projects.length == 0">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="col-sm-10">
|
||||||
|
<small>Project Name</small>
|
||||||
|
</th>
|
||||||
|
<th class="col-sm-2 text-right">
|
||||||
|
<small>
|
||||||
|
<strong>Stories</strong><br/>
|
||||||
|
Opened / Total
|
||||||
|
</small>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr ng-repeat="project in projects">
|
<tr ng-repeat="project in projects">
|
||||||
<td>
|
<td>
|
||||||
<div class="pull-right">
|
<p><strong>
|
||||||
<a href="#!/project/{{project.id}}/edit">
|
<a href="#!/project/{{project.id}}">
|
||||||
<i class="fa fa-edit"></i>
|
{{project.name}}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</strong></p>
|
||||||
<a href="#!/project/{{project.id}}">
|
<small class="text-muted">
|
||||||
<strong>{{project.name}}</strong>
|
{{project.description}}
|
||||||
</a>
|
</small>
|
||||||
<br/>
|
</td>
|
||||||
|
<td class="text-right">
|
||||||
{{project.description}}
|
<p class="text-muted">
|
||||||
|
{{project.openStories}} / {{project.totalStories}}
|
||||||
|
</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -17,8 +17,7 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xs-12">
|
<div class="col-xs-12">
|
||||||
<h1>Create a new project</h1>
|
<h1>New Project</h1>
|
||||||
<hr/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@ -14,26 +14,13 @@
|
|||||||
~ under the License.
|
~ under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<div class="container" ng-show="isLoading">
|
<div class="row">
|
||||||
<div class="col-xs-12">
|
<div class="col-xs-12">
|
||||||
<p class="text-center">
|
<p ng-show="project.description">{{project.description}}</p>
|
||||||
<i class="fa fa-refresh fa-spin"></i>
|
|
||||||
|
<p ng-hide="project.description"
|
||||||
|
class="text-muted text-center">
|
||||||
|
No description available.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="container" ng-hide="isLoading">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-xs-12">
|
|
||||||
<h1>{{projectGroup.name}}</h1>
|
|
||||||
|
|
||||||
<p>{{projectGroup.title}}</p>
|
|
||||||
<hr/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-xs-12">
|
|
||||||
Project List TBD.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
97
src/app/templates/project/stories.html
Normal file
97
src/app/templates/project/stories.html
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
<!--
|
||||||
|
~ 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="col-sm-3 col-xs-10">
|
||||||
|
<div class="btn-group btn-group-justified">
|
||||||
|
<div class="form-group has-feedback has-feedback-no-label">
|
||||||
|
<input type="text"
|
||||||
|
class="form-control input-sm"
|
||||||
|
placeholder="Search Stories"
|
||||||
|
ng-disabled="isSearching"
|
||||||
|
ng-enter="search()"
|
||||||
|
ng-model="searchQuery"/>
|
||||||
|
<span class="fa fa-search form-control-feedback"
|
||||||
|
ng-hide="isSearching"></span>
|
||||||
|
<span class="fa fa-refresh fa-spin form-control-feedback"
|
||||||
|
ng-show="isSearching"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-sm-9 col-xs-2">
|
||||||
|
<a href=""
|
||||||
|
ng-click="newStory()"
|
||||||
|
class="pull-right btn btn-default btn-sm">
|
||||||
|
<i class="fa fa-plus"></i>
|
||||||
|
<span class="hidden-xs">New Story</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div ng-show="!isSearching && stories.length == 0"
|
||||||
|
class="col-sm-12 text-center text-warning">
|
||||||
|
<hr/>
|
||||||
|
<p> We were unable to find any stories in this project.
|
||||||
|
Perhaps you would like to create one?</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<div ng-show="isSearching">
|
||||||
|
<hr/>
|
||||||
|
<p class="text-center">
|
||||||
|
<i class="fa fa-refresh fa-spin fa-lg"></i>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="table table-striped"
|
||||||
|
ng-hide="isSearching || stories.length == 0">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="col-sm-1">
|
||||||
|
<small>ID</small>
|
||||||
|
</th>
|
||||||
|
<th class="col-sm-7">
|
||||||
|
<small>Story Name</small>
|
||||||
|
</th>
|
||||||
|
<th class="col-sm-2 text-right">
|
||||||
|
<small>
|
||||||
|
<strong>Tasks</strong><br/>
|
||||||
|
Opened / Total
|
||||||
|
</small>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr ng-repeat="story in stories">
|
||||||
|
<td>
|
||||||
|
<p><strong>
|
||||||
|
<a href="#!/story/{{story.id}}">{{story.id}}</a>
|
||||||
|
</strong></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><strong>
|
||||||
|
<a href="#!/story/{{story.id}}">{{story.title}}</a>
|
||||||
|
</strong></p>
|
||||||
|
<small class="text-muted">{{story.description}}</small>
|
||||||
|
</td>
|
||||||
|
<td class="text-right">
|
||||||
|
<p class="text-muted">
|
||||||
|
{{story.openTasks}} / {{story.totalTasks}}
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
@ -1,85 +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" ng-show="isLoading">
|
|
||||||
<div class="col-xs-12">
|
|
||||||
<p class="text-center">
|
|
||||||
<i class="fa fa-refresh fa-2x fa-spin"></i>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container" ng-hide="isLoading">
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-xs-12">
|
|
||||||
<h1>Project Group: {{projectGroup.title}}</h1>
|
|
||||||
<hr/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-xs-12">
|
|
||||||
<form class="form-horizontal" role="form" name="projectForm">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="name" class="col-sm-2 control-label">
|
|
||||||
Group Name:
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<div class="col-sm-10">
|
|
||||||
<input id="name"
|
|
||||||
type="text"
|
|
||||||
class="form-control"
|
|
||||||
ng-model="projectGroup.name"
|
|
||||||
required
|
|
||||||
placeholder="Group Name">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="title"
|
|
||||||
class="col-sm-2 control-label">
|
|
||||||
Group Title
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<div class="col-sm-10">
|
|
||||||
<input id="title"
|
|
||||||
type="text"
|
|
||||||
class="form-control"
|
|
||||||
ng-model="projectGroup.title"
|
|
||||||
required
|
|
||||||
placeholder="Group Title">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="col-sm-offset-2 col-sm-10">
|
|
||||||
<button type="button"
|
|
||||||
ng-click="update()"
|
|
||||||
class="btn btn-primary"
|
|
||||||
ng-disabled="!projectForm.$valid">
|
|
||||||
Save Changes
|
|
||||||
</button>
|
|
||||||
<button ng-click="remove()"
|
|
||||||
class="btn btn-danger">
|
|
||||||
Delete Group
|
|
||||||
</button>
|
|
||||||
<a href="#!/project_groups/list"
|
|
||||||
class="btn btn-default">
|
|
||||||
Cancel
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -1,87 +0,0 @@
|
|||||||
<!--
|
|
||||||
~ Copyright (c) 2013 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-sm-8 col-md-9">
|
|
||||||
<h3 class="no-margin">
|
|
||||||
<a href="#!/project_groups/new" class="btn btn-default">
|
|
||||||
<i class="fa fa-plus"></i>
|
|
||||||
</a>
|
|
||||||
Project Groups
|
|
||||||
</h3>
|
|
||||||
<br class="visible-xs"/>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-4 col-md-3">
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control"
|
|
||||||
placeholder="Search Project Groups"
|
|
||||||
ng-disabled="isSearching"
|
|
||||||
ng-enter="search()"
|
|
||||||
ng-model="searchQuery"/>
|
|
||||||
<span class="input-group-btn">
|
|
||||||
<button type="button" ng-click="search()"
|
|
||||||
ng-disabled="isSearching"
|
|
||||||
class="btn btn-default">
|
|
||||||
<i class="fa fa-refresh fa-spin"
|
|
||||||
ng-show="isSearching"></i>
|
|
||||||
<i class="fa fa-search"
|
|
||||||
ng-hide="isSearching"></i>
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-12">
|
|
||||||
<hr/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-12">
|
|
||||||
<div ng-show="isSearching">
|
|
||||||
<hr/>
|
|
||||||
<p class="text-center">
|
|
||||||
<i class="fa fa-refresh fa-spin fa-lg"></i>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<table class="table table-striped table-hover table-responsive"
|
|
||||||
ng-hide="isSearching">
|
|
||||||
<tbody>
|
|
||||||
<tr ng-repeat="projectGroup in projectGroups">
|
|
||||||
<td>
|
|
||||||
<div class="pull-right">
|
|
||||||
<a href="#!/project_groups/{{projectGroup.id}}/edit">
|
|
||||||
<i class="fa fa-edit"></i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<a href="#!/project_groups/{{projectGroup.id}}">
|
|
||||||
<strong>{{projectGroup.name}}</strong>
|
|
||||||
</a>
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
{{projectGroup.title}}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -1,74 +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>Create a new project group</h1>
|
|
||||||
<hr/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-xs-12">
|
|
||||||
<form class="form-horizontal" role="form" name="projectGroupForm">
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="name" class="col-sm-2 control-label">
|
|
||||||
Group Name:
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<div class="col-sm-10">
|
|
||||||
<input id="name"
|
|
||||||
type="text"
|
|
||||||
class="form-control"
|
|
||||||
ng-model="newProjectGroup.name"
|
|
||||||
required
|
|
||||||
placeholder="Group Name">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="title"
|
|
||||||
class="col-sm-2 control-label">
|
|
||||||
Group Title:
|
|
||||||
</label>
|
|
||||||
|
|
||||||
<div class="col-sm-10">
|
|
||||||
<input id="title"
|
|
||||||
type="text"
|
|
||||||
class="form-control"
|
|
||||||
ng-model="newProjectGroup.title"
|
|
||||||
required
|
|
||||||
placeholder="Group Title">
|
|
||||||
</textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="col-sm-offset-2 col-sm-10">
|
|
||||||
<button type="button"
|
|
||||||
ng-click="createProjectGroup()"
|
|
||||||
class="btn btn-primary"
|
|
||||||
ng-disabled="!projectGroupForm.$valid">
|
|
||||||
Create project group
|
|
||||||
</button>
|
|
||||||
<a href="#!/project_groups/list"
|
|
||||||
class="btn btn-default">
|
|
||||||
Cancel
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
34
src/app/templates/story/delete.html
Normal file
34
src/app/templates/story/delete.html
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<!--
|
||||||
|
~ 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="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 story?
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p class="text-center lead">
|
||||||
|
This will set the story to a "deleted" state, and any
|
||||||
|
tasks will no longer be visible.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="text-center">
|
||||||
|
<a href="" class="btn btn-danger btn-disabled">
|
||||||
|
Feature not yet available
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
39
src/app/templates/story/detail.html
Normal file
39
src/app/templates/story/detail.html
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<!--
|
||||||
|
~ 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">
|
||||||
|
<h1 class="no-border no-margin-bottom">Story detail: {{story.title}}</h1>
|
||||||
|
<ul class="nav nav-tabs nav-tabs-down nav-thick">
|
||||||
|
<li active-path="^\/story\/[0-9]+\/overview.*">
|
||||||
|
<a href="#!/story/{{story.id}}/overview">
|
||||||
|
Overview
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li active-path="^\/story\/[0-9]+\/edit.*">
|
||||||
|
<a href="#!/story/{{story.id}}/edit">
|
||||||
|
Edit
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li active-path="^\/story\/[0-9]+\/delete.*">
|
||||||
|
<a href="#!/story/{{story.id}}/delete">
|
||||||
|
Delete
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<div ui-view></div>
|
||||||
|
</div>
|
64
src/app/templates/story/edit.html
Normal file
64
src/app/templates/story/edit.html
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.
|
||||||
|
-->
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-12">
|
||||||
|
<form class="form-horizontal" role="form" name="storyForm">
|
||||||
|
<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="story.title"
|
||||||
|
required
|
||||||
|
placeholder="Story Title">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="description"
|
||||||
|
class="col-sm-2 control-label">
|
||||||
|
Story Description
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<textarea id="description"
|
||||||
|
class="form-control"
|
||||||
|
ng-model="story.description"
|
||||||
|
required
|
||||||
|
placeholder="A brief story description">
|
||||||
|
</textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-offset-2 col-sm-10">
|
||||||
|
<button type="button"
|
||||||
|
ng-click="update()"
|
||||||
|
class="btn btn-primary"
|
||||||
|
ng-disabled="!storyForm.$valid">
|
||||||
|
Save Changes
|
||||||
|
</button>
|
||||||
|
<a href="#!/story/list"
|
||||||
|
class="btn btn-default">
|
||||||
|
Cancel
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
106
src/app/templates/story/list.html
Normal file
106
src/app/templates/story/list.html
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<!--
|
||||||
|
~ 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>{{storyCount}} Stories</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-3 col-xs-10">
|
||||||
|
<div class="btn-group btn-group-justified">
|
||||||
|
<div class="form-group has-feedback has-feedback-no-label">
|
||||||
|
<input type="text"
|
||||||
|
class="form-control input-sm"
|
||||||
|
placeholder="Search Stories"
|
||||||
|
ng-disabled="isSearching"
|
||||||
|
ng-enter="search()"
|
||||||
|
ng-model="searchQuery"/>
|
||||||
|
<span class="fa fa-search form-control-feedback"
|
||||||
|
ng-hide="isSearching"></span>
|
||||||
|
<span class="fa fa-refresh fa-spin form-control-feedback"
|
||||||
|
ng-show="isSearching"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-9 col-xs-2">
|
||||||
|
<a href=""
|
||||||
|
ng-click="newStory()"
|
||||||
|
class="pull-right btn btn-default btn-sm">
|
||||||
|
<i class="fa fa-plus"></i>
|
||||||
|
<span class="hidden-xs">New Story</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<div ng-show="isSearching">
|
||||||
|
<hr/>
|
||||||
|
<p class="text-center">
|
||||||
|
<i class="fa fa-refresh fa-spin fa-lg"></i>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p ng-show="!isSearching && stories.length == 0"
|
||||||
|
class="text-center text-warning">
|
||||||
|
<em> We were unable to find any stories.
|
||||||
|
Perhaps you would like to create one?</em>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<table class="table table-striped"
|
||||||
|
ng-hide="isSearching || stories.length == 0">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="col-sm-1">
|
||||||
|
<small>ID</small>
|
||||||
|
</th>
|
||||||
|
<th class="col-sm-7">
|
||||||
|
<small>Story Name</small>
|
||||||
|
</th>
|
||||||
|
<th class="col-sm-2 text-right">
|
||||||
|
<small>
|
||||||
|
<strong>Tasks</strong><br/>
|
||||||
|
Opened / Total
|
||||||
|
</small>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr ng-repeat="story in stories">
|
||||||
|
<td>
|
||||||
|
<p><strong>
|
||||||
|
<a href="#!/story/{{story.id}}">{{story.id}}</a>
|
||||||
|
</strong></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><strong>
|
||||||
|
<a href="#!/story/{{story.id}}">{{story.title}}</a>
|
||||||
|
</strong></p>
|
||||||
|
<small class="text-muted">{{story.description}}</small>
|
||||||
|
</td>
|
||||||
|
<td class="text-right">
|
||||||
|
<p class="text-muted">
|
||||||
|
{{story.openTasks}} / {{story.totalTasks}}
|
||||||
|
</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
72
src/app/templates/story/new.html
Normal file
72
src/app/templates/story/new.html
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<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 Story</h3>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-12">
|
||||||
|
<form class="form-horizontal" role="form" name="storyForm">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="project" class="col-sm-2 control-label">
|
||||||
|
Project:
|
||||||
|
</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<select ng-model="story.project"
|
||||||
|
id="project"
|
||||||
|
name="project"
|
||||||
|
class="form-control"
|
||||||
|
required
|
||||||
|
ng-options="p.id as p.name for p in projects"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="name" class="col-sm-2 control-label">
|
||||||
|
Title:
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input id="name"
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
ng-model="story.title"
|
||||||
|
required
|
||||||
|
placeholder="Story Title">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="description"
|
||||||
|
class="col-sm-2 control-label">
|
||||||
|
Description
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<textarea id="description"
|
||||||
|
class="form-control"
|
||||||
|
ng-model="story.description"
|
||||||
|
required
|
||||||
|
placeholder="A brief story description">
|
||||||
|
</textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-offset-2 col-sm-10">
|
||||||
|
<button type="button"
|
||||||
|
class="btn btn-primary"
|
||||||
|
ng-click="save()"
|
||||||
|
ng-disabled="!storyForm.$valid">
|
||||||
|
Save Changes
|
||||||
|
</button>
|
||||||
|
<button type="button"
|
||||||
|
ng-click="close()"
|
||||||
|
class="btn btn-default">
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
120
src/app/templates/story/overview.html
Normal file
120
src/app/templates/story/overview.html
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<!--
|
||||||
|
~ 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="row">
|
||||||
|
<div class="col-sm-9 col-xs-11">
|
||||||
|
<p ng-show="story.description">
|
||||||
|
{{story.description}}
|
||||||
|
</p>
|
||||||
|
<em ng-hide="story.description"
|
||||||
|
class="text-muted">
|
||||||
|
No description available
|
||||||
|
</em>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-3 col-xs-1">
|
||||||
|
<a href=""
|
||||||
|
ng-click="showAddTaskForm = !showAddTaskForm"
|
||||||
|
class="pull-right btn btn-default btn-sm">
|
||||||
|
<span ng-hide="showAddTaskForm">
|
||||||
|
<i class="fa fa-plus"></i>
|
||||||
|
<span class="hidden-xs">Add Task</span>
|
||||||
|
</span>
|
||||||
|
<span ng-show="showAddTaskForm">
|
||||||
|
<i class="fa fa-minus"></i>
|
||||||
|
<span class="hidden-xs">Add Task</span>
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row" ng-show="showAddTaskForm">
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<div class="well">
|
||||||
|
<form role="form" name="taskForm">
|
||||||
|
<div class="form-group row">
|
||||||
|
<label for="title" class="col-sm-2 control-label">
|
||||||
|
Task Title:
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<input id="title"
|
||||||
|
type="text"
|
||||||
|
class="form-control"
|
||||||
|
ng-model="newTask.title"
|
||||||
|
required
|
||||||
|
placeholder="Task Title">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-offset-2 col-sm-10">
|
||||||
|
<button type="submit" class="btn btn-default"
|
||||||
|
ng-click="addTask()">
|
||||||
|
Add task
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="col-sm-1">
|
||||||
|
<small>ID</small>
|
||||||
|
</th>
|
||||||
|
<th class="col-sm-6">
|
||||||
|
<small>Title</small>
|
||||||
|
</th>
|
||||||
|
<th class="col-sm-3">
|
||||||
|
<small>Project</small>
|
||||||
|
</th>
|
||||||
|
<th class="col-sm-2">
|
||||||
|
<small>Status</small>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr ng-repeat="task in tasks">
|
||||||
|
<td>
|
||||||
|
<p><strong>
|
||||||
|
<a href="">{{task.id}}</a>
|
||||||
|
</strong></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><strong>
|
||||||
|
<a href="">{{task.title}}</a>
|
||||||
|
</strong></p>
|
||||||
|
<small class="text-muted">{{task.description}}</small>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p><strong>
|
||||||
|
<a href="">Not Yet Implemented</a>
|
||||||
|
</strong></p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p class="text-success">{{task.status}}</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
@ -1,87 +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-sm-8 col-md-9">
|
|
||||||
<h3 class="no-margin">
|
|
||||||
<a href="#!/team/new" class="btn btn-default">
|
|
||||||
<i class="fa fa-plus"></i>
|
|
||||||
</a>
|
|
||||||
Teams
|
|
||||||
</h3>
|
|
||||||
<br class="visible-xs"/>
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-4 col-md-3">
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" class="form-control"
|
|
||||||
placeholder="Search Teams"
|
|
||||||
ng-disabled="isSearching"
|
|
||||||
ng-enter="search()"
|
|
||||||
ng-model="searchQuery"/>
|
|
||||||
<span class="input-group-btn">
|
|
||||||
<button type="button" ng-click="search()"
|
|
||||||
ng-disabled="isSearching"
|
|
||||||
class="btn btn-default">
|
|
||||||
<i class="fa fa-refresh fa-spin"
|
|
||||||
ng-show="isSearching"></i>
|
|
||||||
<i class="fa fa-search"
|
|
||||||
ng-hide="isSearching"></i>
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-12">
|
|
||||||
<hr/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-12">
|
|
||||||
<div ng-show="isSearching">
|
|
||||||
<hr/>
|
|
||||||
<p class="text-center">
|
|
||||||
<i class="fa fa-refresh fa-spin fa-lg"></i>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<table class="table table-striped table-hover table-responsive"
|
|
||||||
ng-hide="isSearching">
|
|
||||||
<tbody>
|
|
||||||
<tr ng-repeat="team in teams">
|
|
||||||
<td>
|
|
||||||
<div class="pull-right">
|
|
||||||
<a href="#!/team/{{team.id}}/edit">
|
|
||||||
<i class="fa fa-edit"></i>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<a href="#!/team/{{team.id}}">
|
|
||||||
<strong>{{team.name}}</strong>
|
|
||||||
</a>
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
{{team.description}}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
@ -30,13 +30,18 @@ angular.module('sb.util').directive('activePath',
|
|||||||
var activePath = attrs.activePath;
|
var activePath = attrs.activePath;
|
||||||
|
|
||||||
function setActivePath() {
|
function setActivePath() {
|
||||||
var isActive = activePath === $location.path();
|
var path = $location.path();
|
||||||
element.toggleClass('active', isActive);
|
var isMatchedPath = path.match(activePath) !== null;
|
||||||
|
|
||||||
|
element.toggleClass('active', isMatchedPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.$on('$destroy',
|
// This is angularjs magic, the return method from any $on
|
||||||
$rootScope.$on('$stateChangeSuccess', setActivePath)
|
// binding will return a function that will disconnect
|
||||||
);
|
// that binding.
|
||||||
|
var disconnectBinding =
|
||||||
|
$rootScope.$on('$stateChangeSuccess', setActivePath);
|
||||||
|
$scope.$on('$destroy', disconnectBinding);
|
||||||
|
|
||||||
// INIT
|
// INIT
|
||||||
setActivePath();
|
setActivePath();
|
||||||
|
@ -30,6 +30,8 @@
|
|||||||
<!-- build:js(bower_components) js/libs.js -->
|
<!-- build:js(bower_components) js/libs.js -->
|
||||||
<script src="jquery/jquery.js"></script>
|
<script src="jquery/jquery.js"></script>
|
||||||
<script src="angular/angular.js"></script>
|
<script src="angular/angular.js"></script>
|
||||||
|
<script src="angular-bootstrap/ui-bootstrap.js"></script>
|
||||||
|
<script src="angular-bootstrap/ui-bootstrap-tpls.js"></script>
|
||||||
<script src="angular-ui-router/release/angular-ui-router.js"></script>
|
<script src="angular-ui-router/release/angular-ui-router.js"></script>
|
||||||
<script src="angular-resource/angular-resource.js"></script>
|
<script src="angular-resource/angular-resource.js"></script>
|
||||||
<script src="angular-mocks/angular-mocks.js"></script>
|
<script src="angular-mocks/angular-mocks.js"></script>
|
||||||
@ -48,7 +50,31 @@
|
|||||||
<header class="navbar navbar-default navbar-fixed-top"
|
<header class="navbar navbar-default navbar-fixed-top"
|
||||||
ng-include src="'app/templates/header.html'">
|
ng-include src="'app/templates/header.html'">
|
||||||
</header>
|
</header>
|
||||||
<div ui-view></div>
|
<div ui-view class="main"></div>
|
||||||
|
<div class="modal fade">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<button type="button" class="close" data-dismiss="modal"
|
||||||
|
aria-hidden="true">×</button>
|
||||||
|
<h4 class="modal-title">Modal title</h4>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p>One fine body…</p>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-default"
|
||||||
|
data-dismiss="modal">Close
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-primary">Save changes
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- /.modal-content -->
|
||||||
|
</div>
|
||||||
|
<!-- /.modal-dialog -->
|
||||||
|
</div>
|
||||||
|
<!-- /.modal -->
|
||||||
<footer class="container" ng-include src="'app/templates/footer.html'">
|
<footer class="container" ng-include src="'app/templates/footer.html'">
|
||||||
</footer>
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
|
@ -16,12 +16,17 @@
|
|||||||
/**
|
/**
|
||||||
* Styles specific to the overall application.
|
* Styles specific to the overall application.
|
||||||
*/
|
*/
|
||||||
@import url(http://fonts.googleapis.com/css?family=PT+Sans:400,700,400italic,700italic&subset=latin,cyrillic-ext,latin-ext,cyrillic);
|
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin-top: 70px;
|
margin-top: 70px;
|
||||||
|
|
||||||
|
.main {
|
||||||
|
// Min height set so that the footer doesn't bounce around as much,
|
||||||
|
// but there's only so much we can do.
|
||||||
|
min-height: 500px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i.icon {
|
i.icon {
|
||||||
line-height: .5em;
|
line-height: .5em;
|
||||||
}
|
}
|
||||||
|
118
src/styles/bootstrap_addons.less
vendored
118
src/styles/bootstrap_addons.less
vendored
@ -18,16 +18,132 @@
|
|||||||
* Generic overrides and addons for bootstrap.
|
* Generic overrides and addons for bootstrap.
|
||||||
*/
|
*/
|
||||||
h1, h2, h3, h4, h5, h6 {
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
|
||||||
&.no-margin {
|
&.no-margin {
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.no-border {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.no-margin-bottom {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
padding-bottom: .3em;
|
||||||
|
border-bottom: 2px solid @gray-lighter;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar {
|
.navbar {
|
||||||
#gradient > .vertical(@white, @gray-lighter);
|
#gradient > .vertical(@white, @gray-lighter);
|
||||||
.box-shadow( 0 1px 3px rgba(0,0,0,.25))
|
.box-shadow(0 1px 3px rgba(0, 0, 0, .25));
|
||||||
|
|
||||||
|
// The new story button in the mobile view needs a little additional margin.
|
||||||
|
.new-story-button {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-nav {
|
||||||
|
li {
|
||||||
|
.active {
|
||||||
|
@media (max-width: @screen-sm) {
|
||||||
|
border-left: 5px solid @brand-primary;
|
||||||
|
color: @gray-darker;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: @screen-sm) {
|
||||||
|
border-bottom: 3px solid @brand-primary;
|
||||||
|
margin-bottom: -2px;
|
||||||
|
padding-bottom: (@navbar-padding-vertical - 2);
|
||||||
|
color: @gray-darker;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.visible-xs {
|
||||||
|
hr {
|
||||||
|
border-top: 1px solid @gray-light;
|
||||||
|
margin: 5px 10px 5px 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar-brand {
|
.navbar-brand {
|
||||||
color: @brand-primary;
|
color: @brand-primary;
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.has-feedback {
|
||||||
|
|
||||||
|
// Sibling selectors for inputs of different sizes.
|
||||||
|
.input-sm + .form-control-feedback {
|
||||||
|
line-height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.has-feedback-no-label {
|
||||||
|
.form-control-feedback {
|
||||||
|
top: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-tabs {
|
||||||
|
|
||||||
|
&.nav-tabs-down {
|
||||||
|
border-bottom: none;
|
||||||
|
border-top: 1px solid @nav-tabs-border-color;
|
||||||
|
|
||||||
|
> li {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
margin-top: -1px;
|
||||||
|
|
||||||
|
// Actual tabs (as links)
|
||||||
|
> a {
|
||||||
|
border-width: 1px;
|
||||||
|
border-radius: 0 0 @border-radius-base @border-radius-base;
|
||||||
|
&:hover {
|
||||||
|
border-bottom-color: @nav-tabs-link-hover-border-color;
|
||||||
|
border-top-color: @nav-tabs-border-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Active state, and its :hover to override normal :hover
|
||||||
|
&.active > a {
|
||||||
|
&,
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
border-bottom-color: @nav-tabs-active-link-hover-border-color;
|
||||||
|
border-top-color: transparent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.nav-thick {
|
||||||
|
border-width: 2px;
|
||||||
|
|
||||||
|
> li {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
margin-top: -2px;
|
||||||
|
> a {
|
||||||
|
border-width: 2px;
|
||||||
|
}
|
||||||
|
// Active state, and its :hover to override normal :hover
|
||||||
|
&.active > a {
|
||||||
|
&,
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
border-width: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
604
src/styles/bootstrap_variable_overrides.less
vendored
604
src/styles/bootstrap_variable_overrides.less
vendored
@ -1,604 +0,0 @@
|
|||||||
//
|
|
||||||
// A verbatim copy of the bootstrap variables file, included in our source
|
|
||||||
// so we can override colors, padding, fonts, what have you.
|
|
||||||
// --------------------------------------------------
|
|
||||||
|
|
||||||
// Global values
|
|
||||||
// --------------------------------------------------
|
|
||||||
|
|
||||||
// Grays
|
|
||||||
// -------------------------
|
|
||||||
|
|
||||||
@gray-darker: lighten(#000, 13.5%);
|
|
||||||
// #222
|
|
||||||
@gray-dark: lighten(#000, 20%);
|
|
||||||
// #333
|
|
||||||
@gray: lighten(#000, 33.5%);
|
|
||||||
// #555
|
|
||||||
@gray-light: lighten(#000, 60%);
|
|
||||||
// #999
|
|
||||||
@gray-lighter: lighten(#000, 93.5%);
|
|
||||||
// #eee
|
|
||||||
@white: #FFFFFF;
|
|
||||||
|
|
||||||
// Brand colors
|
|
||||||
// -------------------------
|
|
||||||
|
|
||||||
@brand-primary: #C43422;
|
|
||||||
@brand-success: #5cb85c;
|
|
||||||
@brand-warning: #f0ad4e;
|
|
||||||
@brand-danger: #d9534f;
|
|
||||||
@brand-info: #5bc0de;
|
|
||||||
|
|
||||||
// Scaffolding
|
|
||||||
// -------------------------
|
|
||||||
|
|
||||||
@body-bg: #fff;
|
|
||||||
@text-color: @gray-dark;
|
|
||||||
|
|
||||||
// Links
|
|
||||||
// -------------------------
|
|
||||||
|
|
||||||
@link-color: @brand-primary;
|
|
||||||
@link-hover-color: lighten(@link-color, 10%);
|
|
||||||
|
|
||||||
// Typography
|
|
||||||
// -------------------------
|
|
||||||
|
|
||||||
@font-family-title: "PT Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
||||||
@font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
|
||||||
@font-family-serif: Georgia, "Times New Roman", Times, serif;
|
|
||||||
@font-family-monospace: Monaco, Menlo, Consolas, "Courier New", monospace;
|
|
||||||
@font-family-base: @font-family-sans-serif;
|
|
||||||
|
|
||||||
@font-size-base: 14px;
|
|
||||||
@font-size-large: ceil(@font-size-base * 1.25);
|
|
||||||
// ~18px
|
|
||||||
@font-size-small: ceil(@font-size-base * 0.85);
|
|
||||||
// ~12px
|
|
||||||
|
|
||||||
@line-height-base: 1.428571429;
|
|
||||||
// 20/14
|
|
||||||
@line-height-computed: floor(@font-size-base * @line-height-base);
|
|
||||||
// ~20px
|
|
||||||
|
|
||||||
@headings-font-family: @font-family-title;
|
|
||||||
@headings-font-weight: 500;
|
|
||||||
@headings-line-height: 1.1;
|
|
||||||
|
|
||||||
// Iconography
|
|
||||||
// -------------------------
|
|
||||||
|
|
||||||
@icon-font-path: "../fonts/";
|
|
||||||
@icon-font-name: "glyphicons-halflings-regular";
|
|
||||||
|
|
||||||
// Components
|
|
||||||
// -------------------------
|
|
||||||
// Based on 14px font-size and 1.428 line-height (~20px to start)
|
|
||||||
|
|
||||||
@padding-base-vertical: 6px;
|
|
||||||
@padding-base-horizontal: 12px;
|
|
||||||
|
|
||||||
@padding-large-vertical: 10px;
|
|
||||||
@padding-large-horizontal: 16px;
|
|
||||||
|
|
||||||
@padding-small-vertical: 5px;
|
|
||||||
@padding-small-horizontal: 10px;
|
|
||||||
|
|
||||||
@line-height-large: 1.33;
|
|
||||||
@line-height-small: 1.5;
|
|
||||||
|
|
||||||
@border-radius-base: 4px;
|
|
||||||
@border-radius-large: 6px;
|
|
||||||
@border-radius-small: 3px;
|
|
||||||
|
|
||||||
@component-active-bg: @brand-primary;
|
|
||||||
|
|
||||||
@caret-width-base: 4px;
|
|
||||||
@caret-width-large: 5px;
|
|
||||||
|
|
||||||
// Tables
|
|
||||||
// -------------------------
|
|
||||||
|
|
||||||
@table-cell-padding: 8px;
|
|
||||||
@table-condensed-cell-padding: 5px;
|
|
||||||
|
|
||||||
@table-bg: transparent;
|
|
||||||
// overall background-color
|
|
||||||
@table-bg-accent: #f9f9f9;
|
|
||||||
// for striping
|
|
||||||
@table-bg-hover: #f5f5f5;
|
|
||||||
@table-bg-active: @table-bg-hover;
|
|
||||||
|
|
||||||
@table-border-color: #ddd;
|
|
||||||
// table and cell border
|
|
||||||
|
|
||||||
// Buttons
|
|
||||||
// -------------------------
|
|
||||||
|
|
||||||
@btn-font-weight: normal;
|
|
||||||
|
|
||||||
@btn-default-color: #333;
|
|
||||||
@btn-default-bg: #fff;
|
|
||||||
@btn-default-border: #ccc;
|
|
||||||
|
|
||||||
@btn-primary-color: #fff;
|
|
||||||
@btn-primary-bg: @brand-primary;
|
|
||||||
@btn-primary-border: darken(@btn-primary-bg, 5%);
|
|
||||||
|
|
||||||
@btn-success-color: #fff;
|
|
||||||
@btn-success-bg: @brand-success;
|
|
||||||
@btn-success-border: darken(@btn-success-bg, 5%);
|
|
||||||
|
|
||||||
@btn-warning-color: #fff;
|
|
||||||
@btn-warning-bg: @brand-warning;
|
|
||||||
@btn-warning-border: darken(@btn-warning-bg, 5%);
|
|
||||||
|
|
||||||
@btn-danger-color: #fff;
|
|
||||||
@btn-danger-bg: @brand-danger;
|
|
||||||
@btn-danger-border: darken(@btn-danger-bg, 5%);
|
|
||||||
|
|
||||||
@btn-info-color: #fff;
|
|
||||||
@btn-info-bg: @brand-info;
|
|
||||||
@btn-info-border: darken(@btn-info-bg, 5%);
|
|
||||||
|
|
||||||
@btn-link-disabled-color: @gray-light;
|
|
||||||
|
|
||||||
// Forms
|
|
||||||
// -------------------------
|
|
||||||
|
|
||||||
@input-bg: #fff;
|
|
||||||
@input-bg-disabled: @gray-lighter;
|
|
||||||
|
|
||||||
@input-color: @gray;
|
|
||||||
@input-border: #ccc;
|
|
||||||
@input-border-radius: @border-radius-base;
|
|
||||||
@input-border-focus: #66afe9;
|
|
||||||
|
|
||||||
@input-color-placeholder: @gray-light;
|
|
||||||
|
|
||||||
@input-height-base: (@line-height-computed + (@padding-base-vertical * 2) + 2);
|
|
||||||
@input-height-large: (floor(@font-size-large * @line-height-large) + (@padding-large-vertical * 2) + 2);
|
|
||||||
@input-height-small: (floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2);
|
|
||||||
|
|
||||||
@legend-color: @gray-dark;
|
|
||||||
@legend-border-color: #e5e5e5;
|
|
||||||
|
|
||||||
@input-group-addon-bg: @gray-lighter;
|
|
||||||
@input-group-addon-border-color: @input-border;
|
|
||||||
|
|
||||||
// Dropdowns
|
|
||||||
// -------------------------
|
|
||||||
|
|
||||||
@dropdown-bg: #fff;
|
|
||||||
@dropdown-border: rgba(0, 0, 0, .15);
|
|
||||||
@dropdown-fallback-border: #ccc;
|
|
||||||
@dropdown-divider-bg: #e5e5e5;
|
|
||||||
|
|
||||||
@dropdown-link-active-color: #fff;
|
|
||||||
@dropdown-link-active-bg: @component-active-bg;
|
|
||||||
|
|
||||||
@dropdown-link-color: @gray-dark;
|
|
||||||
@dropdown-link-hover-color: #fff;
|
|
||||||
@dropdown-link-hover-bg: @dropdown-link-active-bg;
|
|
||||||
|
|
||||||
@dropdown-link-disabled-color: @gray-light;
|
|
||||||
|
|
||||||
@dropdown-header-color: @gray-light;
|
|
||||||
|
|
||||||
@dropdown-caret-color: #000;
|
|
||||||
|
|
||||||
// COMPONENT VARIABLES
|
|
||||||
// --------------------------------------------------
|
|
||||||
|
|
||||||
// Z-index master list
|
|
||||||
// -------------------------
|
|
||||||
// Used for a bird's eye view of components dependent on the z-axis
|
|
||||||
// Try to avoid customizing these :)
|
|
||||||
|
|
||||||
@zindex-navbar: 1000;
|
|
||||||
@zindex-dropdown: 1000;
|
|
||||||
@zindex-popover: 1010;
|
|
||||||
@zindex-tooltip: 1030;
|
|
||||||
@zindex-navbar-fixed: 1030;
|
|
||||||
@zindex-modal-background: 1040;
|
|
||||||
@zindex-modal: 1050;
|
|
||||||
|
|
||||||
// Media queries breakpoints
|
|
||||||
// --------------------------------------------------
|
|
||||||
|
|
||||||
// Extra small screen / phone
|
|
||||||
@screen-xs: 480px;
|
|
||||||
@screen-phone: @screen-xs;
|
|
||||||
|
|
||||||
// Small screen / tablet
|
|
||||||
@screen-sm: 768px;
|
|
||||||
@screen-tablet: @screen-sm;
|
|
||||||
|
|
||||||
// Medium screen / desktop
|
|
||||||
@screen-md: 992px;
|
|
||||||
@screen-desktop: @screen-md;
|
|
||||||
|
|
||||||
// Large screen / wide desktop
|
|
||||||
@screen-lg: 1200px;
|
|
||||||
@screen-lg-desktop: @screen-lg;
|
|
||||||
|
|
||||||
// So media queries don't overlap when required, provide a maximum
|
|
||||||
@screen-xs-max: (@screen-sm - 1);
|
|
||||||
@screen-sm-max: (@screen-md - 1);
|
|
||||||
@screen-md-max: (@screen-lg - 1);
|
|
||||||
|
|
||||||
// Grid system
|
|
||||||
// --------------------------------------------------
|
|
||||||
|
|
||||||
// Number of columns in the grid system
|
|
||||||
@grid-columns: 12;
|
|
||||||
// Padding, to be divided by two and applied to the left and right of all columns
|
|
||||||
@grid-gutter-width: 30px;
|
|
||||||
// Point at which the navbar stops collapsing
|
|
||||||
@grid-float-breakpoint: @screen-tablet;
|
|
||||||
|
|
||||||
// Navbar
|
|
||||||
// -------------------------
|
|
||||||
|
|
||||||
// Basics of a navbar
|
|
||||||
@navbar-height: 40px;
|
|
||||||
@navbar-margin-bottom: @line-height-computed;
|
|
||||||
@navbar-default-color: #777;
|
|
||||||
@navbar-default-bg: #f8f8f8;
|
|
||||||
@navbar-default-border: @gray-lighter;
|
|
||||||
@navbar-border-radius: @border-radius-base;
|
|
||||||
@navbar-padding-horizontal: floor(@grid-gutter-width / 2);
|
|
||||||
@navbar-padding-vertical: ((@navbar-height - @line-height-computed) / 2);
|
|
||||||
|
|
||||||
// Navbar links
|
|
||||||
@navbar-default-link-color: #777;
|
|
||||||
@navbar-default-link-hover-color: #333;
|
|
||||||
@navbar-default-link-hover-bg: transparent;
|
|
||||||
@navbar-default-link-active-color: #555;
|
|
||||||
@navbar-default-link-active-bg: darken(@navbar-default-bg, 6.5%);
|
|
||||||
@navbar-default-link-disabled-color: #ccc;
|
|
||||||
@navbar-default-link-disabled-bg: transparent;
|
|
||||||
|
|
||||||
// Navbar brand label
|
|
||||||
@navbar-default-brand-color: @brand-primary;
|
|
||||||
@navbar-default-brand-hover-color: lighten(@brand-primary, 10%);
|
|
||||||
@navbar-default-brand-hover-bg: transparent;
|
|
||||||
|
|
||||||
// Navbar toggle
|
|
||||||
@navbar-default-toggle-hover-bg: #ddd;
|
|
||||||
@navbar-default-toggle-icon-bar-bg: #ccc;
|
|
||||||
@navbar-default-toggle-border-color: #ddd;
|
|
||||||
|
|
||||||
// Inverted navbar
|
|
||||||
//
|
|
||||||
// Reset inverted navbar basics
|
|
||||||
@navbar-inverse-color: @gray-light;
|
|
||||||
@navbar-inverse-bg: #222;
|
|
||||||
@navbar-inverse-border: darken(@navbar-inverse-bg, 10%);
|
|
||||||
|
|
||||||
// Inverted navbar links
|
|
||||||
@navbar-inverse-link-color: @gray-light;
|
|
||||||
@navbar-inverse-link-hover-color: #fff;
|
|
||||||
@navbar-inverse-link-hover-bg: transparent;
|
|
||||||
@navbar-inverse-link-active-color: @navbar-inverse-link-hover-color;
|
|
||||||
@navbar-inverse-link-active-bg: darken(@navbar-inverse-bg, 10%);
|
|
||||||
@navbar-inverse-link-disabled-color: #444;
|
|
||||||
@navbar-inverse-link-disabled-bg: transparent;
|
|
||||||
|
|
||||||
// Inverted navbar brand label
|
|
||||||
@navbar-inverse-brand-color: @navbar-inverse-link-color;
|
|
||||||
@navbar-inverse-brand-hover-color: #fff;
|
|
||||||
@navbar-inverse-brand-hover-bg: transparent;
|
|
||||||
|
|
||||||
// Inverted navbar search
|
|
||||||
// Normal navbar needs no special styles or vars
|
|
||||||
@navbar-inverse-search-bg: lighten(@navbar-inverse-bg, 25%);
|
|
||||||
@navbar-inverse-search-bg-focus: #fff;
|
|
||||||
@navbar-inverse-search-border: @navbar-inverse-bg;
|
|
||||||
@navbar-inverse-search-placeholder-color: #ccc;
|
|
||||||
|
|
||||||
// Inverted navbar toggle
|
|
||||||
@navbar-inverse-toggle-hover-bg: #333;
|
|
||||||
@navbar-inverse-toggle-icon-bar-bg: #fff;
|
|
||||||
@navbar-inverse-toggle-border-color: #333;
|
|
||||||
|
|
||||||
// Navs
|
|
||||||
// -------------------------
|
|
||||||
|
|
||||||
@nav-link-padding: 10px 15px;
|
|
||||||
@nav-link-hover-bg: @gray-lighter;
|
|
||||||
|
|
||||||
@nav-disabled-link-color: @gray-light;
|
|
||||||
@nav-disabled-link-hover-color: @gray-light;
|
|
||||||
|
|
||||||
@nav-open-link-hover-color: #fff;
|
|
||||||
@nav-open-caret-border-color: #fff;
|
|
||||||
|
|
||||||
// Tabs
|
|
||||||
@nav-tabs-border-color: #ddd;
|
|
||||||
|
|
||||||
@nav-tabs-link-hover-border-color: @gray-lighter;
|
|
||||||
|
|
||||||
@nav-tabs-active-link-hover-bg: @body-bg;
|
|
||||||
@nav-tabs-active-link-hover-color: @gray;
|
|
||||||
@nav-tabs-active-link-hover-border-color: #ddd;
|
|
||||||
|
|
||||||
@nav-tabs-justified-link-border-color: #ddd;
|
|
||||||
@nav-tabs-justified-active-link-border-color: @body-bg;
|
|
||||||
|
|
||||||
// Pills
|
|
||||||
@nav-pills-active-link-hover-bg: @component-active-bg;
|
|
||||||
@nav-pills-active-link-hover-color: #fff;
|
|
||||||
|
|
||||||
// Pagination
|
|
||||||
// -------------------------
|
|
||||||
|
|
||||||
@pagination-bg: #fff;
|
|
||||||
@pagination-border: #ddd;
|
|
||||||
|
|
||||||
@pagination-hover-bg: @gray-lighter;
|
|
||||||
|
|
||||||
@pagination-active-bg: @brand-primary;
|
|
||||||
@pagination-active-color: #fff;
|
|
||||||
|
|
||||||
@pagination-disabled-color: @gray-light;
|
|
||||||
|
|
||||||
// Pager
|
|
||||||
// -------------------------
|
|
||||||
|
|
||||||
@pager-border-radius: 15px;
|
|
||||||
@pager-disabled-color: @gray-light;
|
|
||||||
|
|
||||||
// Jumbotron
|
|
||||||
// -------------------------
|
|
||||||
|
|
||||||
@jumbotron-padding: 30px;
|
|
||||||
@jumbotron-color: inherit;
|
|
||||||
@jumbotron-bg: @gray-lighter;
|
|
||||||
|
|
||||||
@jumbotron-heading-color: inherit;
|
|
||||||
|
|
||||||
// Form states and alerts
|
|
||||||
// -------------------------
|
|
||||||
|
|
||||||
@state-warning-text: #c09853;
|
|
||||||
@state-warning-bg: #fcf8e3;
|
|
||||||
@state-warning-border: darken(spin(@state-warning-bg, -10), 3%);
|
|
||||||
|
|
||||||
@state-danger-text: #b94a48;
|
|
||||||
@state-danger-bg: #f2dede;
|
|
||||||
@state-danger-border: darken(spin(@state-danger-bg, -10), 3%);
|
|
||||||
|
|
||||||
@state-success-text: #468847;
|
|
||||||
@state-success-bg: #dff0d8;
|
|
||||||
@state-success-border: darken(spin(@state-success-bg, -10), 5%);
|
|
||||||
|
|
||||||
@state-info-text: #3a87ad;
|
|
||||||
@state-info-bg: #d9edf7;
|
|
||||||
@state-info-border: darken(spin(@state-info-bg, -10), 7%);
|
|
||||||
|
|
||||||
// Tooltips
|
|
||||||
// -------------------------
|
|
||||||
@tooltip-max-width: 200px;
|
|
||||||
@tooltip-color: #fff;
|
|
||||||
@tooltip-bg: #000;
|
|
||||||
|
|
||||||
@tooltip-arrow-width: 5px;
|
|
||||||
@tooltip-arrow-color: @tooltip-bg;
|
|
||||||
|
|
||||||
// Popovers
|
|
||||||
// -------------------------
|
|
||||||
@popover-bg: #fff;
|
|
||||||
@popover-max-width: 276px;
|
|
||||||
@popover-border-color: rgba(0, 0, 0, .2);
|
|
||||||
@popover-fallback-border-color: #ccc;
|
|
||||||
|
|
||||||
@popover-title-bg: darken(@popover-bg, 3%);
|
|
||||||
|
|
||||||
@popover-arrow-width: 10px;
|
|
||||||
@popover-arrow-color: #fff;
|
|
||||||
|
|
||||||
@popover-arrow-outer-width: (@popover-arrow-width + 1);
|
|
||||||
@popover-arrow-outer-color: rgba(0, 0, 0, .25);
|
|
||||||
@popover-arrow-outer-fallback-color: #999;
|
|
||||||
|
|
||||||
// Labels
|
|
||||||
// -------------------------
|
|
||||||
|
|
||||||
@label-default-bg: @gray-light;
|
|
||||||
@label-primary-bg: @brand-primary;
|
|
||||||
@label-success-bg: @brand-success;
|
|
||||||
@label-info-bg: @brand-info;
|
|
||||||
@label-warning-bg: @brand-warning;
|
|
||||||
@label-danger-bg: @brand-danger;
|
|
||||||
|
|
||||||
@label-color: #fff;
|
|
||||||
@label-link-hover-color: #fff;
|
|
||||||
|
|
||||||
// Modals
|
|
||||||
// -------------------------
|
|
||||||
@modal-inner-padding: 20px;
|
|
||||||
|
|
||||||
@modal-title-padding: 15px;
|
|
||||||
@modal-title-line-height: @line-height-base;
|
|
||||||
|
|
||||||
@modal-content-bg: #fff;
|
|
||||||
@modal-content-border-color: rgba(0, 0, 0, .2);
|
|
||||||
@modal-content-fallback-border-color: #999;
|
|
||||||
|
|
||||||
@modal-backdrop-bg: #000;
|
|
||||||
@modal-header-border-color: #e5e5e5;
|
|
||||||
@modal-footer-border-color: @modal-header-border-color;
|
|
||||||
|
|
||||||
// Alerts
|
|
||||||
// -------------------------
|
|
||||||
@alert-padding: 15px;
|
|
||||||
@alert-border-radius: @border-radius-base;
|
|
||||||
@alert-link-font-weight: bold;
|
|
||||||
|
|
||||||
@alert-success-bg: @state-success-bg;
|
|
||||||
@alert-success-text: @state-success-text;
|
|
||||||
@alert-success-border: @state-success-border;
|
|
||||||
|
|
||||||
@alert-info-bg: @state-info-bg;
|
|
||||||
@alert-info-text: @state-info-text;
|
|
||||||
@alert-info-border: @state-info-border;
|
|
||||||
|
|
||||||
@alert-warning-bg: @state-warning-bg;
|
|
||||||
@alert-warning-text: @state-warning-text;
|
|
||||||
@alert-warning-border: @state-warning-border;
|
|
||||||
|
|
||||||
@alert-danger-bg: @state-danger-bg;
|
|
||||||
@alert-danger-text: @state-danger-text;
|
|
||||||
@alert-danger-border: @state-danger-border;
|
|
||||||
|
|
||||||
// Progress bars
|
|
||||||
// -------------------------
|
|
||||||
@progress-bg: #f5f5f5;
|
|
||||||
@progress-bar-color: #fff;
|
|
||||||
|
|
||||||
@progress-bar-bg: @brand-primary;
|
|
||||||
@progress-bar-success-bg: @brand-success;
|
|
||||||
@progress-bar-warning-bg: @brand-warning;
|
|
||||||
@progress-bar-danger-bg: @brand-danger;
|
|
||||||
@progress-bar-info-bg: @brand-info;
|
|
||||||
|
|
||||||
// List group
|
|
||||||
// -------------------------
|
|
||||||
@list-group-bg: #fff;
|
|
||||||
@list-group-border: #ddd;
|
|
||||||
@list-group-border-radius: @border-radius-base;
|
|
||||||
|
|
||||||
@list-group-hover-bg: #f5f5f5;
|
|
||||||
@list-group-active-color: #fff;
|
|
||||||
@list-group-active-bg: @component-active-bg;
|
|
||||||
@list-group-active-border: @list-group-active-bg;
|
|
||||||
|
|
||||||
@list-group-link-color: #555;
|
|
||||||
@list-group-link-heading-color: #333;
|
|
||||||
|
|
||||||
// Panels
|
|
||||||
// -------------------------
|
|
||||||
@panel-bg: #fff;
|
|
||||||
@panel-inner-border: #ddd;
|
|
||||||
@panel-border-radius: @border-radius-base;
|
|
||||||
@panel-footer-bg: #f5f5f5;
|
|
||||||
|
|
||||||
@panel-default-text: @gray-dark;
|
|
||||||
@panel-default-border: #ddd;
|
|
||||||
@panel-default-heading-bg: #f5f5f5;
|
|
||||||
|
|
||||||
@panel-primary-text: #fff;
|
|
||||||
@panel-primary-border: @brand-primary;
|
|
||||||
@panel-primary-heading-bg: @brand-primary;
|
|
||||||
|
|
||||||
@panel-success-text: @state-success-text;
|
|
||||||
@panel-success-border: @state-success-border;
|
|
||||||
@panel-success-heading-bg: @state-success-bg;
|
|
||||||
|
|
||||||
@panel-warning-text: @state-warning-text;
|
|
||||||
@panel-warning-border: @state-warning-border;
|
|
||||||
@panel-warning-heading-bg: @state-warning-bg;
|
|
||||||
|
|
||||||
@panel-danger-text: @state-danger-text;
|
|
||||||
@panel-danger-border: @state-danger-border;
|
|
||||||
@panel-danger-heading-bg: @state-danger-bg;
|
|
||||||
|
|
||||||
@panel-info-text: @state-info-text;
|
|
||||||
@panel-info-border: @state-info-border;
|
|
||||||
@panel-info-heading-bg: @state-info-bg;
|
|
||||||
|
|
||||||
// Thumbnails
|
|
||||||
// -------------------------
|
|
||||||
@thumbnail-padding: 4px;
|
|
||||||
@thumbnail-bg: @body-bg;
|
|
||||||
@thumbnail-border: #ddd;
|
|
||||||
@thumbnail-border-radius: @border-radius-base;
|
|
||||||
|
|
||||||
@thumbnail-caption-color: @text-color;
|
|
||||||
@thumbnail-caption-padding: 9px;
|
|
||||||
|
|
||||||
// Wells
|
|
||||||
// -------------------------
|
|
||||||
@well-bg: #f5f5f5;
|
|
||||||
|
|
||||||
// Badges
|
|
||||||
// -------------------------
|
|
||||||
@badge-color: #fff;
|
|
||||||
@badge-link-hover-color: #fff;
|
|
||||||
@badge-bg: @gray-light;
|
|
||||||
|
|
||||||
@badge-active-color: @link-color;
|
|
||||||
@badge-active-bg: #fff;
|
|
||||||
|
|
||||||
@badge-font-weight: bold;
|
|
||||||
@badge-line-height: 1;
|
|
||||||
@badge-border-radius: 10px;
|
|
||||||
|
|
||||||
// Breadcrumbs
|
|
||||||
// -------------------------
|
|
||||||
@breadcrumb-bg: #f5f5f5;
|
|
||||||
@breadcrumb-color: #ccc;
|
|
||||||
@breadcrumb-active-color: @gray-light;
|
|
||||||
|
|
||||||
// Carousel
|
|
||||||
// ------------------------
|
|
||||||
|
|
||||||
@carousel-text-shadow: 0 1px 2px rgba(0, 0, 0, .6);
|
|
||||||
|
|
||||||
@carousel-control-color: #fff;
|
|
||||||
@carousel-control-width: 15%;
|
|
||||||
@carousel-control-opacity: .5;
|
|
||||||
@carousel-control-font-size: 20px;
|
|
||||||
|
|
||||||
@carousel-indicator-active-bg: #fff;
|
|
||||||
@carousel-indicator-border-color: #fff;
|
|
||||||
|
|
||||||
@carousel-caption-color: #fff;
|
|
||||||
|
|
||||||
// Close
|
|
||||||
// ------------------------
|
|
||||||
@close-color: #000;
|
|
||||||
@close-font-weight: bold;
|
|
||||||
@close-text-shadow: 0 1px 0 #fff;
|
|
||||||
|
|
||||||
// Code
|
|
||||||
// ------------------------
|
|
||||||
@code-color: #c7254e;
|
|
||||||
@code-bg: #f9f2f4;
|
|
||||||
|
|
||||||
@pre-bg: #f5f5f5;
|
|
||||||
@pre-color: @gray-dark;
|
|
||||||
@pre-border-color: #ccc;
|
|
||||||
@pre-scrollable-max-height: 340px;
|
|
||||||
|
|
||||||
// Type
|
|
||||||
// ------------------------
|
|
||||||
@text-muted: @gray-light;
|
|
||||||
@abbr-border-color: @gray-light;
|
|
||||||
@headings-small-color: @gray-light;
|
|
||||||
@blockquote-small-color: @gray-light;
|
|
||||||
@blockquote-border-color: @gray-lighter;
|
|
||||||
@page-header-border-color: @gray-lighter;
|
|
||||||
|
|
||||||
// Miscellaneous
|
|
||||||
// -------------------------
|
|
||||||
|
|
||||||
// Hr border color
|
|
||||||
@hr-border: @gray-lighter;
|
|
||||||
|
|
||||||
// Horizontal forms & lists
|
|
||||||
@component-offset-horizontal: 180px;
|
|
||||||
|
|
||||||
// Container sizes
|
|
||||||
// --------------------------------------------------
|
|
||||||
|
|
||||||
// Small screen / tablet
|
|
||||||
@container-tablet: ((720px + @grid-gutter-width));
|
|
||||||
|
|
||||||
// Medium screen / desktop
|
|
||||||
@container-desktop: ((940px + @grid-gutter-width));
|
|
||||||
|
|
||||||
// Large screen / wide desktop
|
|
||||||
@container-lg-desktop: ((1140px + @grid-gutter-width));
|
|
@ -23,8 +23,9 @@
|
|||||||
// Library inclusions
|
// Library inclusions
|
||||||
@import './bootstrap.less';
|
@import './bootstrap.less';
|
||||||
@import './font-awesome.less';
|
@import './font-awesome.less';
|
||||||
// Custom variable overrides
|
// Variables
|
||||||
@import './bootstrap_variable_overrides.less';
|
@import './variables.less';
|
||||||
|
// Addons to the bootstrap theme.
|
||||||
@import './bootstrap_addons.less';
|
@import './bootstrap_addons.less';
|
||||||
// Add our own custom icon font.
|
// Add our own custom icon font.
|
||||||
@import './custom_font_icons.less';
|
@import './custom_font_icons.less';
|
||||||
|
31
src/styles/variables.less
Normal file
31
src/styles/variables.less
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// A list of specific variable overrides. Since bootstrap is a fairly
|
||||||
|
// fast moving project, it is recommended we only include those variables which
|
||||||
|
// we are adding/overriding.
|
||||||
|
|
||||||
|
// ============================== Custom Variables =============================
|
||||||
|
@white: #FFFFFF;
|
||||||
|
@black: #000000;
|
||||||
|
|
||||||
|
// ============================== Bootstrap Overrides ==========================
|
||||||
|
// Brand colors
|
||||||
|
// -------------------------
|
||||||
|
@brand-primary: #C43422;
|
||||||
|
|
||||||
|
// Typography
|
||||||
|
// -------------------------
|
||||||
|
@font-family-title: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||||
|
|
||||||
|
@headings-font-family: @font-family-title;
|
||||||
|
|
||||||
|
@font-size-h1: (floor(@font-size-base * 2.15));
|
||||||
|
@font-size-h2: (floor(@font-size-base * 1.7));
|
||||||
|
@font-size-h3: (ceil(@font-size-base * 1.5));
|
||||||
|
@font-size-h4: (ceil(@font-size-base * 1.25));
|
||||||
|
@font-size-h5: (@font-size-base);
|
||||||
|
@font-size-h6: (ceil(@font-size-base * 0.85));
|
||||||
|
|
||||||
|
// Navbar
|
||||||
|
// -------------------------
|
||||||
|
|
||||||
|
// Basics of a navbar
|
||||||
|
@navbar-height: 40px;
|
@ -1,29 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2013 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
describe('Storyboard Login Routes', function () {
|
|
||||||
'use strict';
|
|
||||||
|
|
||||||
it('should redirect /auth to /auth/provider/list', function () {
|
|
||||||
browser.get('http://localhost:9000/#!/auth');
|
|
||||||
expect(browser.getCurrentUrl()).toContain('#!/auth/provider/list');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should redirect /auth/provider to /auth/provider/list', function () {
|
|
||||||
browser.get('http://localhost:9000/#!/auth/provider');
|
|
||||||
expect(browser.getCurrentUrl()).toContain('#!/auth/provider/list');
|
|
||||||
});
|
|
||||||
});
|
|
24
test/functional/projects/routes.js
Normal file
24
test/functional/projects/routes.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
describe('Storyboard Project Routes', function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
it('should redirect /project to /project/list', function () {
|
||||||
|
browser.get('http://localhost:9000/#!/project');
|
||||||
|
expect(browser.getCurrentUrl()).toContain('#!/project/list');
|
||||||
|
});
|
||||||
|
});
|
24
test/functional/stories/routes.js
Normal file
24
test/functional/stories/routes.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
describe('Storyboard Story Routes', function () {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
it('should redirect /story to /story/list', function () {
|
||||||
|
browser.get('http://localhost:9000/#!/story');
|
||||||
|
expect(browser.getCurrentUrl()).toContain('#!/story/list');
|
||||||
|
});
|
||||||
|
});
|
@ -38,9 +38,9 @@ describe('storyboardApiSignature', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should declare a search method', function () {
|
it('should declare a query method', function () {
|
||||||
inject(function (storyboardApiSignature) {
|
inject(function (storyboardApiSignature) {
|
||||||
expect(storyboardApiSignature.search).toBeTruthy();
|
expect(storyboardApiSignature.query).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -68,10 +68,10 @@ describe('storyboardApiSignature', function () {
|
|||||||
expect(storyboardApiSignature.delete.method).toEqual('DELETE');
|
expect(storyboardApiSignature.delete.method).toEqual('DELETE');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
it('should use GET to search', function () {
|
it('should use GET to query', function () {
|
||||||
inject(function (storyboardApiSignature) {
|
inject(function (storyboardApiSignature) {
|
||||||
expect(storyboardApiSignature.search).toBeTruthy();
|
expect(storyboardApiSignature.query).toBeTruthy();
|
||||||
expect(storyboardApiSignature.search.method).toEqual('GET');
|
expect(storyboardApiSignature.query.method).toEqual('GET');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ describe('storyboardApiSignature', function () {
|
|||||||
var Resource = $resource('/path/:id',
|
var Resource = $resource('/path/:id',
|
||||||
{id: '@id'},
|
{id: '@id'},
|
||||||
storyboardApiSignature);
|
storyboardApiSignature);
|
||||||
expect(Resource.search).toBeTruthy();
|
expect(Resource.query).toBeTruthy();
|
||||||
expect(Resource.read).toBeTruthy();
|
expect(Resource.read).toBeTruthy();
|
||||||
|
|
||||||
var resourceInstance = new Resource();
|
var resourceInstance = new Resource();
|
||||||
|
Loading…
Reference in New Issue
Block a user