From 197d5dd2bd9e7141e68fcdf6a43d7d262ea011e1 Mon Sep 17 00:00:00 2001 From: Michael Krotscheck Date: Thu, 19 Dec 2013 07:27:10 -0800 Subject: [PATCH] Initial commit This contains the initial commit for the storyboard web client project, consisting of the basic build & testing harnesses, simple set of routes, and a list of basic dependencies necessary to run an application. It's purpose is to be reference Javascript/Angular project to test out the build images. --- .gitignore | 10 + .gitreview | 4 + .jshintrc | 65 ++ Gruntfile.js | 605 ++++++++++++++++++ LICENSE | 202 ++++++ README.md | 37 ++ bin/bootstrap.sh | 71 ++ bin/build.sh | 38 ++ bower.json | 22 + karma-integration.conf.js | 66 ++ karma-unit.conf.js | 66 ++ package.json | 57 ++ protractor.conf.js | 97 +++ .../auth/controller/auth_list_controller.js | 33 + .../auth/controller/auth_login_controller.js | 28 + src/app/auth/module.js | 62 ++ src/app/pages/module.js | 40 ++ .../controllers/project_list_controller.js | 28 + src/app/projects/module.js | 41 ++ .../services/http/http_error_broadcaster.js | 66 ++ src/app/services/module.js | 24 + .../services/provider/storyboard_api_base.js | 53 ++ .../resolver/auth_provider_resolver.js | 84 +++ src/app/services/resource/auth_provider.js | 58 ++ .../services/resource/auth_provider_mock.js | 83 +++ src/app/storyboard.js | 59 ++ src/app/templates/auth/provider/list.html | 33 + src/app/templates/auth/provider/login.html | 23 + src/app/templates/footer.html | 23 + src/app/templates/header.html | 55 ++ src/app/templates/index.html | 67 ++ src/app/templates/page/about.html | 95 +++ src/app/templates/project/list.html | 48 ++ src/app/util/directive/active_path.js | 45 ++ src/app/util/directive/enter.js | 39 ++ src/app/util/filter/debug_filter.js | 31 + src/app/util/module.js | 17 + src/favicon.ico | Bin 0 -> 115797 bytes src/fonts/custom_font_icons.eot | Bin 0 -> 5136 bytes src/fonts/custom_font_icons.ttf | Bin 0 -> 4924 bytes src/fonts/custom_font_icons.woff | Bin 0 -> 3088 bytes src/images/logo/logo_128.png | Bin 0 -> 68458 bytes src/images/logo/logo_16.png | Bin 0 -> 1626 bytes src/images/logo/logo_256.png | Bin 0 -> 16993 bytes src/images/logo/logo_32.png | Bin 0 -> 2623 bytes src/images/logo/logo_48.png | Bin 0 -> 3589 bytes src/images/logo/logo_512.png | Bin 0 -> 41291 bytes src/images/logo/logo_64.png | Bin 0 -> 4483 bytes src/index.html | 61 ++ src/robots.txt | 3 + src/styles/auth.less | 24 + src/styles/custom_font_icons.less | 24 + src/styles/main.less | 26 + test/functional/module.js | 27 + test/integration/services/module.js | 40 ++ test/unit/services/module.js | 40 ++ 56 files changed, 2720 insertions(+) create mode 100644 .gitignore create mode 100644 .gitreview create mode 100644 .jshintrc create mode 100644 Gruntfile.js create mode 100644 LICENSE create mode 100644 README.md create mode 100755 bin/bootstrap.sh create mode 100755 bin/build.sh create mode 100644 bower.json create mode 100644 karma-integration.conf.js create mode 100644 karma-unit.conf.js create mode 100644 package.json create mode 100644 protractor.conf.js create mode 100644 src/app/auth/controller/auth_list_controller.js create mode 100644 src/app/auth/controller/auth_login_controller.js create mode 100644 src/app/auth/module.js create mode 100644 src/app/pages/module.js create mode 100644 src/app/projects/controllers/project_list_controller.js create mode 100644 src/app/projects/module.js create mode 100644 src/app/services/http/http_error_broadcaster.js create mode 100644 src/app/services/module.js create mode 100644 src/app/services/provider/storyboard_api_base.js create mode 100644 src/app/services/resolver/auth_provider_resolver.js create mode 100644 src/app/services/resource/auth_provider.js create mode 100644 src/app/services/resource/auth_provider_mock.js create mode 100644 src/app/storyboard.js create mode 100644 src/app/templates/auth/provider/list.html create mode 100644 src/app/templates/auth/provider/login.html create mode 100644 src/app/templates/footer.html create mode 100644 src/app/templates/header.html create mode 100644 src/app/templates/index.html create mode 100644 src/app/templates/page/about.html create mode 100644 src/app/templates/project/list.html create mode 100644 src/app/util/directive/active_path.js create mode 100644 src/app/util/directive/enter.js create mode 100644 src/app/util/filter/debug_filter.js create mode 100644 src/app/util/module.js create mode 100644 src/favicon.ico create mode 100644 src/fonts/custom_font_icons.eot create mode 100644 src/fonts/custom_font_icons.ttf create mode 100644 src/fonts/custom_font_icons.woff create mode 100644 src/images/logo/logo_128.png create mode 100644 src/images/logo/logo_16.png create mode 100644 src/images/logo/logo_256.png create mode 100644 src/images/logo/logo_32.png create mode 100644 src/images/logo/logo_48.png create mode 100644 src/images/logo/logo_512.png create mode 100644 src/images/logo/logo_64.png create mode 100644 src/index.html create mode 100644 src/robots.txt create mode 100644 src/styles/auth.less create mode 100644 src/styles/custom_font_icons.less create mode 100644 src/styles/main.less create mode 100644 test/functional/module.js create mode 100644 test/integration/services/module.js create mode 100644 test/unit/services/module.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..564b6438 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +.build +.local +node_modules +bower_components +dist +npm-debug.log +*.iml +.idea +reports +cover \ No newline at end of file diff --git a/.gitreview b/.gitreview new file mode 100644 index 00000000..5fa3236e --- /dev/null +++ b/.gitreview @@ -0,0 +1,4 @@ +[gerrit] +host=review.openstack.org +port=29418 +project=openstack-infra/storyboard-webclient.git diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 00000000..a751de03 --- /dev/null +++ b/.jshintrc @@ -0,0 +1,65 @@ +// 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. + +/** + * This file contains JSHint configuration settings, which allow us to enforce a + * coding standard programatically using jshint. It's as close to PEP-8 as we + * can get it. + * + * @see http://www.jshint.com/ + */ +{ + "node": true, + "browser": true, + "esnext": true, + "bitwise": true, + "camelcase": true, + "curly": true, + "eqeqeq": true, + "immed": true, + "indent": 4, + "maxlen": 80, + "latedef": true, + "newcap": true, + "noarg": true, + "quotmark": "single", + "undef": true, + "unused": true, + "strict": true, + "trailing": true, + "smarttabs": true, + + // Inform JSHint that the following globals are expected. + "globals": { + // Library constants + "$": false, // JQuery + "angular": false, // AngularJS + + // Unit test constants + "after": false, + "afterEach": false, + "before": false, + "beforeEach": false, + "describe": false, + "expect": false, + "inject": false, + "it": false, + "spyOn": false, + + // functional test constants + "browser": false, + "by": false, + "element": false + } +} \ No newline at end of file diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 00000000..1c40555b --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,605 @@ +/* + * 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. + */ + +/** + * This file serves as task declaration/configuration for steps executed + * during the grunt build. It loads grunt modules declared in package.json, + * configures them, and makes them available via 'grunt PLUGIN' on the + * commandline. It also groups these tasks into individual steps helpful during + * development, such as build, package, test, and release. + * + * @author Michael Krotscheck + */ +var config = { + livereload: { + port: 35729 + } +}; + +var lrSnippet = require('connect-livereload')(config.livereload); +var mountFolder = function (connect, dir) { + 'use strict'; + return connect.static(require('path').resolve(dir)); +}; + + +module.exports = function (grunt) { + 'use strict'; + + var dir = { + source : './src', + test : './test', + output : './dist', + report : './reports', + bower: './bower_components' + }; + + // load all grunt tasks + require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks); + + grunt.initConfig({ + + /** + * grunt clean + * + * Cleans our output directories. + */ + clean: { + dist: { + files: [ + { + dot: true, + src: [ + dir.report, + './cover', + dir.output + ] + } + ] + } + }, + + /** + * grunt jshint + * + * Runs the JSHint linter against all the javascript files in our + * project, using the .jshintrc file shared with our IDE (sublime, + * eclipse, intellij, etc) + */ + jshint: { + options: { + jshintrc: '.jshintrc' + }, + all: [ + dir.source + '/**/*.js', + dir.test + '/**/*.js', + './*.js' + ] + }, + + /** + * grunt concat + * + * Creates a single file out of our javascript source in accordance + * with the concatenation priority. First the application module, then + * any dependent module declarations, and finally everything else. + */ + concat: { + dist: { + src: [ + dir.source + '/app/storyboard.js', + dir.source + '/app/**/module.js', + dir.source + '/app/**/*.js' + ], + dest: dir.output + '/js/storyboard.js' + } + }, + + /** + * grunt recess + * + * Compiles our .less CSS files into real CSS, linting as it goes. We + * do this manually during our build process so that we can inject + * our own variables into bootstrap and/or other CSS frameworks. + * + * Note: We're using LessCSS here because SASS requires ruby-compass, + * and cannot be easily installed with npm. + */ + recess: { + options: { + compile: true + }, + bootstrap: { + src: [ + dir.bower + '/bootstrap/less/bootstrap.less' + ], + dest: dir.output + '/styles/bootstrap.css' + }, + theme: { + src: [ + dir.source + '/styles/**/*.less' + ], + dest: dir.output + '/styles/theme.css' + } + }, + + /** + * grunt imagemin + * + * Runs optimizations on our images and copies them to the dist + * directory. + */ + imagemin: { + dist: { + files: [ + { + expand: true, + cwd: dir.source + '/images', + src: '**/*.{png,jpg,jpeg}', + dest: dir.output + '/images' + } + ] + } + }, + + /** + * grunt html2js + * + * A convenience method that converts all of the templates found in our + * project into a single javascript file (mostly by converting them + * into strings). This presents a tradeoff: All of the HTML layout + * is loaded up front, which could take a while, but it prevents load + * lag during application runtime. + */ + html2js: { + options: { + module: 'sb.templates', + base: dir.source + }, + main: { + src: [dir.source + '/app/templates/**/*.html'], + dest: dir.output + '/js/templates.js' + } + }, + + /** + * grunt copy + * + * Copies any as-yet-unprocessed files into the dist directory, as well + * as pulling any assets from imported libraries to their appropriate + * locations. + */ + copy: { + dist: { + files: [ + { + expand: true, + dot: true, + cwd: dir.source, + dest: dir.output, + src: [ + '**/*.{ico,txt,eot,ttf,woff}', + '*.html', + 'robots.txt' + ] + }, + { + expand: true, + dot: true, + cwd: dir.bower + '/font-awesome', + dest: dir.output, + src: [ + 'fonts/*.*' + ] + } + ] + } + }, + + /** + * @private + * + * grunt useminPrepare + * + * This task is a configuration builder, used to parse minification + * annotations in index.html. It's used in our compile step as an + * dependency concatenator, so that we can easily declare what we + * need in the index.html file and get all the pieces wrapped up + * nice and pretty by the script. + * + * It will generate configurations for the concat task (the others + * are explicitly disabled). + */ + useminPrepare: { + html: [dir.source + '/index.html'], + options: { + flow: { + steps: { + 'js': ['concat'], + 'css': ['concat'] + }, + post: [] + }, + dest: dir.output + } + }, + + /** + * grunt useminPrepare cssmin + * + * Parses all of the css references in our index.html and minifies them. + * The configuration for this task is generated by useminPrepare. + */ + cssmin: { + minify: { + expand: true, + cwd: dir.output + '/styles/', + src: ['*.css'], + dest: dir.output + '/styles/' + } + + }, + + /** + * grunt useminPrepare uglify + * + * Performs a minifcation on our concatenated javascript, making sure + * not to mangle angularjs' injector pattern. + */ + uglify: { + options: { + mangle: false + }, + dist: { + files: [ + { + expand: true, + cwd: dir.output + '/js', + src: '**/*.js', + dest: dir.output + '/js' + } + ] + } + }, + + /** + * grunt useminPrepare usemin + * + * Completes the packaging task by renaming all modified asset + * references from the previous steps in referencing documents. + */ + usemin: { + html: [ + dir.output + '/index.html' + ], + css: [ + dir.output + '/styles/**/*.css' + ], + options: { + dirs: [dir.output] + } + }, + + /** + * grunt htmlmin + * + * The final optimization step, which cleans up our html file and + * removes extraneous comments, tags, and more. + */ + htmlmin: { + dist: { + options: { + removeComments: true, + removeCommentsFromCDATA: true, + collapseWhitespace: false, + collapseBooleanAttributes: false, + removeAttributeQuotes: false, + removeRedundantAttributes: false, + useShortDoctype: false, + removeEmptyAttributes: true, + removeOptionalTags: true + }, + files: [ + { + expand: true, + cwd: dir.output, + src: ['index.html'], + dest: dir.output + } + ] + } + }, + + /** + * grunt open + * + * Opens your default web browser to the specified URL. This is mostly + * used when running server, so that the developer doesn't have to know + * what URL/port the dev box is running on. + */ + open: { + server: { + url: 'http://localhost:<%= connect.options.port %>' + } + }, + + /** + * grunt watch + * + * This task is run with grunt server, in order to automatically update + * the hosted files that are served via the devserver. The livereload + * directive will then communicate with the browser and refresh the page + * when necessary. + */ + watch: { + concat: { + files: [ + dir.source + '/app/storyboard.js', + dir.source + '/app/**/module.js', + dir.source + '/app/**/*.js' + ], + tasks: ['concat'] + }, + recess: { + files: [ + dir.source + '/styles/**/*.less' + ], + tasks: ['recess:bootstrap', 'recess:theme'] + }, + copy: { + files: [ + dir.source + '/**/*.{ico,txt,eot,ttf,woff}' + ], + tasks: ['copy'] + }, + index: { + files: [ + dir.source + '/index.html' + ], + tasks: ['compile'] + + }, + templates: { + files: [ + dir.source + '/app/templates/**/*.html' + ], + tasks: ['html2js'] + }, + jshint: { + files: [ + 'Gruntfile.js', + dir.source + '/**/*.js', + dir.test + '/**/*.js' + ], + tasks: ['jshint'] + }, + livereload: { + options: { + livereload: config.livereload.port + }, + files: [ + dir.output + '/**/*.*' + ] + } + }, + + /** + * grunt connect + * + * The connect plugin hosts a simple web server with our application, + * either under development or under test. + */ + connect: { + options: { + port: 9000, + hostname: 'localhost' + }, + livereload: { + options: { + middleware: function (connect) { + return [ + lrSnippet, + mountFolder(connect, dir.output) + ]; + } + } + }, + dist: { + options: { + keepalive: true, + middleware: function (connect) { + return [ + mountFolder(connect, dir.output) + ]; + } + } + }, + test: { + options: { + middleware: function (connect) { + return [ + mountFolder(connect, dir.output) + ]; + } + } + } + }, + + /** + * grunt karma:unit / grunt karma:integration + * + * This task runs the unit or integration suite on the compiled code. + */ + karma: { + unit: { + configFile: './karma-unit.conf.js' + }, + integration: { + configFile: './karma-integration.conf.js' + } + }, + + /** + * grunt shell:xvfbStart / grunt shell:xvfbStop + * + * Starts and stops a virtual frame buffer. + */ + shell: { + xvfbStart: { + command: 'source ./bin/xvfb.sh start' + }, + xvfbStop: { + command: 'source ./bin/xvfb.sh stop' + } + }, + + /** + * grunt protractor + * + * Protractor is an angular-provided method by which jasmine tests are + * executed via the selenium web driver. Its goal is to handle browser + * drive testing, rather than unit or integration testing. + */ + protractor: { + options: { + configFile: './protractor.conf.js', + keepAlive: true, + noColor: false, + args: { + } + }, + dist: {} + } + }); + + /** + * Compiles all of our sources. + */ + grunt.registerTask('compile', [ + 'jshint', + 'useminPrepare', + 'concat', + 'recess', + 'imagemin', + 'html2js', + 'copy', + 'usemin' + ]); + + /** + * Package built code into a release package. + */ + grunt.registerTask('package', [ + 'uglify', + 'cssmin', + 'htmlmin' + ]); + + /** + * Compile and packages our code. + */ + grunt.registerTask('build', [ + 'compile', + 'package' + ]); + + /** + * This task performs a full build of our application, and then runs that + * source in a local web server. It does no watching, it simply hosts the + * files. + */ + grunt.registerTask('server:dist', [ + 'clean', + 'compile', + 'package', + 'open', + 'connect:dist' + ]); + + /** + * Development server - runs a build and sets up concurrent watchers that + * will automatically lint, test, and refresh + * the code when a change is detected. + */ + grunt.registerTask('server', [ + 'clean', + 'compile', + 'connect:livereload', + 'open', + 'watch' + ]); + + /** + * grunt test:integration + * + * This command will create a clean build against which our unit + * tests will be run. For more information, please see + * karma-unit.conf.js + */ + grunt.registerTask('test:unit', [ + 'clean', + 'compile', + 'useminPrepare', + 'concat', + 'karma:unit' + ]); + + /** + * grunt test:integration + * + * This command will create a clean build against which our integration + * tests will be run. For more information, please see + * karma-integration.conf.js + */ + grunt.registerTask('test:integration', [ + 'clean', + 'compile', + 'useminPrepare', + 'concat', + 'karma:integration' + ]); + + /** + * grunt test:functional + * + * This command will create a clean build against which our functional + * tests will be run. For more information, please see + * karma-functional.conf.js + */ + grunt.registerTask('test:functional', [ + 'clean', + 'compile', + 'connect:test', + 'protractor' + ]); + + /** + * grunt test + * + * Run all the tests. + */ + grunt.registerTask('test', [ + 'clean', + 'compile', + 'useminPrepare', + 'concat', + 'karma:unit', + 'karma:integration', + 'package', + 'connect:test', + 'protractor' + ]); +}; diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..e06d2081 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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. + diff --git a/README.md b/README.md new file mode 100644 index 00000000..6821dddd --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +storyboard-webclient +==================== + +A PoC WebClient for the OpenStack Storyboard project. + +### Prerequisites: Quick build/CI + +* Xvfb +* GCC 4.2 or newer +* Python 2.6 or 2.7 +* GNU Make 3.81 or newer +* libexecinfo (FreeBSD and OpenBSD only) + +### Prerequisites: Dev + +* NodeJS 0.10.24 or newer +* Grunt 0.4.2 +* bower 1.2.8 + +### Command reference: + +**Bootstrap & build the CI environment** + +* `./bin/bootstrap.sh` +* `./bin/build.sh` + +**Run a local development server** + +`grunt server` + +**Run the test suite** + +`grunt test` + +**Package the distro** + +`grunt build` \ No newline at end of file diff --git a/bin/bootstrap.sh b/bin/bootstrap.sh new file mode 100755 index 00000000..517c6bfd --- /dev/null +++ b/bin/bootstrap.sh @@ -0,0 +1,71 @@ +#!/bin/bash -xe + +# This script bootstraps the current workspace with a locally compiled +# node/grunt/bower javascript toolchain. This is done because recent NodeJS +# releases (v0.10+) are not available for the images we use for builds +# (CentOS, Ubuntu 12.04 precise), and because we only need node to generate our +# static assets. +# + +node_version=0.10.24 +script_dir="$( cd "$( dirname "$0" )" && pwd )" +workspace_path="$(dirname "$script_dir")" + +node_archive_path=~/.cache/storyboard/node-v$node_version.tar.gz +node_remote_path=http://nodejs.org/dist/v$node_version/node-v$node_version.tar.gz + +# Sanity check cleanup. +rm -fr $workspace_path/.local/ +rm -fr $workspace_path/.build/ + +# Create our working directories +mkdir -p $workspace_path/.local/ +mkdir -p $workspace_path/.build/ +mkdir -p ~/.cache/storyboard + +# Download the source if we don't have it already. +if [ ! -f $node_archive_path ]; then + echo "Downloading Node v$node_version..." + cd ~/.cache/storyboard + wget $node_remote_path -O $node_archive_path + cd $workspace_path +fi + +# Compile into the workspace, so we keep things isolated. +# Note that on build nodes without ccache this will take a while. + +cd $workspace_path/.build/ +tar -xf $node_archive_path +cd $workspace_path/.build/node-v$node_version + +# Run config, exit & dump if it fails. +echo 'Configuring...' +CONFIG_OUTPUT=$(./configure --prefix=$workspace_path/.local/ 2>&1) +if [ $? != 0 ]; then + echo $CONFIG_OUTPUT + cd $workspace_path + exit 1 +fi + +# Run make +echo 'Make...' +MAKE_OUTPUT=$(make 2>&1) +if [ $? != 0 ]; then + echo $MAKE_OUTPUT + cd $workspace_path + exit 1 +fi + +# Run make install +echo 'Make Install...' +MAKE_INSTALL_OUTPUT=$(make install 2>&1) +if [ $? != 0 ]; then + echo $MAKE_INSTALL_OUTPUT + cd $workspace_path + exit 1 +fi + +# Go back home... +cd $workspace_path + +exit 0 diff --git a/bin/build.sh b/bin/build.sh new file mode 100755 index 00000000..1968f05e --- /dev/null +++ b/bin/build.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +# This script executes the build. + +VDISPLAY=99 +DIMENSIONS='1280x1024x24' +XVFB=/usr/bin/Xvfb +BIN_DIR="$( cd "$( dirname "$0" )" && pwd )" +WORKSPACE="$(dirname "$BIN_DIR")" + +# Add our new bin directory to the PATH +echo "Adding $WORKSPACE/.local/bin to PATH" +export PATH=$WORKSPACE/.local/bin:$PATH +echo "Adding $WORKSPACE/node_modules/.bin to PATH" +export PATH=$WORKSPACE/node_modules/.bin:$PATH + +cd $WORKSPACE; + +echo "Installing build dependencies" +npm prune +npm install + +echo "Installing compile dependencies" +bower prune +bower install + +echo "Launching Virtual Frame Buffer" +$XVFB :${VDISPLAY} -screen 0 ${DIMENSIONS} -ac +extension GLX +render -noreset 2>&1 > /dev/null & + +echo "Building" +set +e +DISPLAY=:${VDISPLAY} grunt clean test +result=$? + +pkill Xvfb 2>&1 > /dev/null +set -e + +exit $result \ No newline at end of file diff --git a/bower.json b/bower.json new file mode 100644 index 00000000..efdb42a3 --- /dev/null +++ b/bower.json @@ -0,0 +1,22 @@ +{ + "name": "storyboard-webclient", + "version": "0.0.1", + "dependencies": { + "jquery": "2.0.3", + "font-awesome": "4.0", + "angular": "1.2.5", + "angular-resource": "1.2.5", + "angular-cookies": "1.2.5", + "angular-sanitize": "1.2.5", + "bootstrap": "3.0.0", + "angular-ui-router": "0.2.0", + "angular-translate": "1.1.1" + }, + "devDependencies": { + "angular-mocks": "1.2.5", + "angular-scenario": "1.2.5" + }, + "resolutions": { + "angular": "1.2.5" + } +} diff --git a/karma-integration.conf.js b/karma-integration.conf.js new file mode 100644 index 00000000..4fe066f1 --- /dev/null +++ b/karma-integration.conf.js @@ -0,0 +1,66 @@ +/* + * 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. + */ + +module.exports = function (config) { + 'use strict'; + + config.set({ + + basePath: '', + + frameworks: ['jasmine'], + + plugins: [ + 'karma-coverage', + 'karma-jasmine', + 'karma-html-reporter', + 'karma-phantomjs-launcher', + 'karma-chrome-launcher', + 'karma-firefox-launcher' + ], + + files: [ + './dist/js/*.js', + './test/unit/**/*.js' + ], + + exclude: [ + ], + + singleRun: true, + + reporters: ['dots', 'progress', 'coverage', 'html'], + + colors: false, + + browsers: [ 'PhantomJS', 'Firefox' ], + + preprocessors: { + './dist/js/storyboard.js': ['coverage'] + }, + + coverageReporter: { + type: 'html', + dir: './cover/integration/' + }, + + htmlReporter: { + outputDir: './reports/integration', + templatePath: './node_modules' + + '/karma-html-reporter/jasmine_template.html' + } + }); +}; \ No newline at end of file diff --git a/karma-unit.conf.js b/karma-unit.conf.js new file mode 100644 index 00000000..164d0c82 --- /dev/null +++ b/karma-unit.conf.js @@ -0,0 +1,66 @@ +/* + * 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. + */ + +module.exports = function (config) { + 'use strict'; + + config.set({ + + basePath: '', + + frameworks: ['jasmine'], + + plugins: [ + 'karma-coverage', + 'karma-jasmine', + 'karma-html-reporter', + 'karma-phantomjs-launcher', + 'karma-chrome-launcher', + 'karma-firefox-launcher' + ], + + files: [ + './dist/js/*.js', + './test/unit/**/*.js' + ], + + exclude: [ + ], + + singleRun: true, + + reporters: ['dots', 'progress', 'coverage', 'html'], + + colors: false, + + browsers: [ 'PhantomJS', 'Firefox' ], + + preprocessors: { + './dist/js/storyboard.js': ['coverage'] + }, + + coverageReporter: { + type: 'html', + dir: './cover/unit/' + }, + + htmlReporter: { + outputDir: './reports/unit', + templatePath: './node_modules' + + '/karma-html-reporter/jasmine_template.html' + } + }); +}; \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 00000000..bf87bfda --- /dev/null +++ b/package.json @@ -0,0 +1,57 @@ +{ + "name": "storyboard-webclient", + "version": "0.0.1", + "description": "An all-javascript webclient for the Storyboard API", + "main": "index.html", + "scripts": { + "test": "grunt test" + }, + "repository": "", + "keywords": [ + "openstack", + "storyboard", + "task", + "project management" + ], + "author": "Michael Krotscheck", + "license": "Apache2", + "devDependencies": { + "connect-livereload": "0.3.1", + "karma-jasmine": "0.1.4", + "grunt-contrib-concat": "0.3.0", + "grunt-contrib-copy": "0.4.1", + "grunt-contrib-clean": "0.5.0", + "grunt-html2js": "0.2.3", + "grunt-open": "0.2.2", + "grunt-usemin": "2.0.2", + "grunt-contrib-htmlmin": "0.1.3", + "grunt-contrib-cssmin": "0.7.0", + "grunt-karma": "0.6.2", + "grunt-contrib-connect": "0.5.0", + "grunt-contrib-watch": "0.5.3", + "grunt-contrib-jshint": "0.7.2", + "grunt-contrib-uglify": "0.2.7", + "grunt-contrib-imagemin": "0.4.0", + "grunt-recess": "0.5.0", + "grunt": "0.4.2", + "grunt-cli": "0.1.11", + "matchdep": "0.1.2", + "karma-script-launcher": "0.1.0", + "karma-chrome-launcher": "0.1.1", + "karma-html2js-preprocessor": "0.1.0", + "karma-firefox-launcher": "0.1.2", + "karma-coffee-preprocessor": "0.1.1", + "requirejs": "2.1.9", + "karma-requirejs": "0.2.0", + "karma-phantomjs-launcher": "0.1.1", + "karma": "0.10.8", + "bower": "1.2.8", + "grunt-shell": "0.6.1", + "karma-coverage": "0.1.4", + "grunt-env": "0.4.1", + "protractor": "0.15.0", + "grunt-protractor-runner": "0.2.0", + "selenium-standalone": "2.39.0-2.7.0", + "karma-html-reporter": "~0.1.1" + } +} diff --git a/protractor.conf.js b/protractor.conf.js new file mode 100644 index 00000000..44e0b623 --- /dev/null +++ b/protractor.conf.js @@ -0,0 +1,97 @@ +/* + * 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. + */ + +// A reference configuration file. +exports.config = { + seleniumServerJar: './node_modules/selenium-standalone/' + + '.selenium/2.39.0/server.jar', + chromeDriver: './node_modules/selenium-standalone/' + + '.selenium/2.39.0/chromedriver', + + chromeOnly: false, + // Additional command line options to pass to selenium. For example, + // if you need to change the browser timeout, use + // seleniumArgs: ['-browserTimeout=60'], + seleniumArgs: [], + + // The timeout for each script run on the browser. This should be longer + // than the maximum time your application needs to stabilize between tasks. + allScriptsTimeout: 11000, + + // ----- What tests to run ----- + // + // Spec patterns are relative to the location of this config. + specs: [ + './test/functional/**/*.js' + ], + + // ----- Capabilities to be passed to the webdriver instance ---- + // + // For a full list of available capabilities, see + // https://code.google.com/p/selenium/wiki/DesiredCapabilities + capabilities: { + 'browserName': 'firefox' + }, + + // ----- More information for your tests ---- + // + // A base URL for your application under test. Calls to protractor.get() + // with relative paths will be prepended with this. + baseUrl: 'http://localhost:9000', + + // Selector for the element housing the angular app - this defaults to + // body, but is necessary if ng-app is on a descendant of + rootElement: 'html', + + // A callback function called once protractor is ready and available, and + // before the specs are executed + // You can specify a file containing code to run by setting onPrepare to + // the filename string. + onPrepare: function () { + // At this point, global 'protractor' object will be set up, and jasmine + // will be available. For example, you can add a Jasmine reporter with: + // jasmine.getEnv().addReporter(new jasmine.JUnitXmlReporter( + // 'outputdir/', true, true)); + }, + + // The params object will be passed directly to the protractor instance, + // and can be accessed from your test. It is an arbitrary object and can + // contain anything you may need in your test. + // This can be changed via the command line as: + // --params.login.user 'Joe' + params: { + login: { + user: 'Jane', + password: '1234' + } + }, + + // ----- Options to be passed to minijasminenode ----- + // + // See the full list at https://github.com/juliemr/minijasminenode + jasmineNodeOpts: { + // onComplete will be called just before the driver quits. + onComplete: null, + // If true, display spec names. + isVerbose: false, + // If true, print colors to the terminal. + showColors: true, + // If true, include stack traces in failures. + includeStackTrace: true, + // Default time to wait in ms before a test fails. + defaultTimeoutInterval: 30000 + } +}; diff --git a/src/app/auth/controller/auth_list_controller.js b/src/app/auth/controller/auth_list_controller.js new file mode 100644 index 00000000..a2518661 --- /dev/null +++ b/src/app/auth/controller/auth_list_controller.js @@ -0,0 +1,33 @@ +/* + * 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. + */ + +/** + * This controller handles the logic for the authorization provider list page. + * + * @author Michael Krotscheck + */ +angular.module('sb.auth').controller('AuthListController', + function ($scope, authProviders, $state) { + 'use strict'; + + // If there's only one auth provider, just use that. + if (!!authProviders && authProviders.length === 1) { + $state.go('auth.provider.id', {id: authProviders[0].id}); + } + + $scope.authProviders = authProviders; + + }); diff --git a/src/app/auth/controller/auth_login_controller.js b/src/app/auth/controller/auth_login_controller.js new file mode 100644 index 00000000..4051c63f --- /dev/null +++ b/src/app/auth/controller/auth_login_controller.js @@ -0,0 +1,28 @@ +/* + * 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. + */ + +/** + * This controller handles the logic for the authorization provider list page. + * + * @author Michael Krotscheck + */ +angular.module('sb.auth').controller('AuthLoginController', + function ($scope, authProvider) { + 'use strict'; + + $scope.authProvider = authProvider; + + }); diff --git a/src/app/auth/module.js b/src/app/auth/module.js new file mode 100644 index 00000000..e6df7717 --- /dev/null +++ b/src/app/auth/module.js @@ -0,0 +1,62 @@ +/* + * 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. + */ + +/** + * This Storyboard module contains our adaptive authentication and authorization + * logic. + * + * @author Michael Krotscheck + */ +angular.module('sb.auth', + [ 'sb.services', 'sb.templates', 'ui.router'] + ) + .config(function ($stateProvider, $urlRouterProvider, + AuthProviderResolver) { + 'use strict'; + + // Default rerouting. + $urlRouterProvider.when('/auth', '/auth/provider/list'); + $urlRouterProvider.when('/auth/provider', '/auth/provider/list'); + + // Declare the states for this module. + $stateProvider + .state('auth', { + abstract: true, + url: '/auth', + template: '
' + }) + .state('auth.provider', { + abstract: true, + url: '/provider', + template: '
' + }) + .state('auth.provider.list', { + url: '/list', + templateUrl: 'app/templates/auth/provider/list.html', + controller: 'AuthListController', + resolve: { + authProviders: AuthProviderResolver.resolveAuthProviders + } + }) + .state('auth.provider.id', { + url: '/:id', + templateUrl: 'app/templates/auth/provider/login.html', + controller: 'AuthLoginController', + resolve: { + authProvider: AuthProviderResolver.resolveAuthProvider('id') + } + }); + }); \ No newline at end of file diff --git a/src/app/pages/module.js b/src/app/pages/module.js new file mode 100644 index 00000000..5ffda99a --- /dev/null +++ b/src/app/pages/module.js @@ -0,0 +1,40 @@ +/* + * 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. + */ + +/** + * The Storyboard pages submodule contains mostly static content pages that + * require little functionality themselves. + * + * @author Michael Krotscheck + */ +angular.module('sb.pages', + [ 'sb.services', 'sb.templates', 'sb.pages', 'ui.router'] + ) + .config(function ($stateProvider) { + 'use strict'; + + // Set our page routes. + $stateProvider + .state('page', { + abstract: true, + url: '/page', + template: '
' + }) + .state('page.about', { + url: '/about', + templateUrl: 'app/templates/page/about.html' + }); + }); \ No newline at end of file diff --git a/src/app/projects/controllers/project_list_controller.js b/src/app/projects/controllers/project_list_controller.js new file mode 100644 index 00000000..1ce591ed --- /dev/null +++ b/src/app/projects/controllers/project_list_controller.js @@ -0,0 +1,28 @@ +/* + * 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. + */ + +/** + * The Storyboard project submodule handles most activity surrounding the + * creation and management of projects. + */ +angular.module('sb.projects').controller('ProjectListController', + function ($scope) { + 'use strict'; + + $scope.search = function () { + + }; + }); diff --git a/src/app/projects/module.js b/src/app/projects/module.js new file mode 100644 index 00000000..ebd4f681 --- /dev/null +++ b/src/app/projects/module.js @@ -0,0 +1,41 @@ +/* + * 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. + */ + +/** + * The Storyboard project submodule handles most activity surrounding the + * creation and management of projects. + * + * @author Michael Krotscheck + */ +angular.module('sb.projects', ['ui.router', 'sb.services']) + .config(function ($stateProvider, $urlRouterProvider) { + 'use strict'; + + // URL Defaults. + $urlRouterProvider.when('/project', '/project/list'); + + // Set our page routes. + $stateProvider + .state('project', { + abstract: true, + url: '/project', + template: '
' + }) + .state('project.list', { + url: '/list', + templateUrl: 'app/templates/project/provider.html' + }); + }); diff --git a/src/app/services/http/http_error_broadcaster.js b/src/app/services/http/http_error_broadcaster.js new file mode 100644 index 00000000..eb48628b --- /dev/null +++ b/src/app/services/http/http_error_broadcaster.js @@ -0,0 +1,66 @@ +/* + * 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. + */ + +/** + * An HTTP request interceptor that broadcasts response status codes to the + * rest of the application as events. These events are broadcast before the + * error response itself is passed back to the receiving closure, so please + * keep that in mind as you base your application logic on it. + * + * @author Michael Krotscheck + */ +angular.module('sb.services') + // Create an HTTP Error Broadcaster that intercepts requests and lets the + // rest of the application know about what happened. + .factory('httpErrorBroadcaster', function ($q, $rootScope) { + 'use strict'; + + function sendEvent(status, body) { + // Only send an event if a status is passed. + if (!!status) { + $rootScope.$broadcast('http_' + status, body || {}); + } + } + + + return { + /** + * Handle a success response. + */ + response: function (response) { + if (!!response) { + sendEvent(response.status); + } + return response; + }, + + /** + * Handle a fail response. + */ + responseError: function (response) { + if (!!response) { + sendEvent(response.status, response.body); + } + + return $q.reject(response); + } + }; + }) + // Attach the HTTP interceptor. + .config(function ($httpProvider) { + 'use strict'; + $httpProvider.interceptors.unshift('httpErrorBroadcaster'); + }); \ No newline at end of file diff --git a/src/app/services/module.js b/src/app/services/module.js new file mode 100644 index 00000000..12ca5cda --- /dev/null +++ b/src/app/services/module.js @@ -0,0 +1,24 @@ +/* + * 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. + */ + +/** + * The Storyboard Services module contains all of the necessary API resources + * used by the storyboard client. Its resources are available via injection to + * any module that declares it as a dependency. + * + * @author Michael Krotscheck + */ +angular.module('sb.services', ['ngResource', 'ngCookies', 'ngMockE2E']); \ No newline at end of file diff --git a/src/app/services/provider/storyboard_api_base.js b/src/app/services/provider/storyboard_api_base.js new file mode 100644 index 00000000..ef0d1f31 --- /dev/null +++ b/src/app/services/provider/storyboard_api_base.js @@ -0,0 +1,53 @@ +/* + * 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. + */ + +/** + * This provider attempts to discover the API URI base for storyboard, by + * checking various expected configuration parameters. + * + * @author Michael Krotscheck + */ +angular.module('sb.services') + .config(function ($provide, $injector) { + 'use strict'; + + var propertyName = 'storyboardApiBase'; + + // First to see whether something's already been injected. + if ($injector.has(propertyName)) { + // We've already got one, exit. + return; + } + + // Do we have a global ENV property with something we can use? + if (window.hasOwnProperty('ENV')) { + var ENV = window.ENV; + if (ENV !== null && ENV.hasOwnProperty(propertyName)) { + $provide.constant(propertyName, ENV[propertyName]); + return; + } + } + + // If there is a tag, then we can use that. + if ($('base').length > 0) { + $provide.constant(propertyName, ''); + return; + } + + // Neither of those work, so default to something sane on the current + // domain + $provide.constant(propertyName, '/api/v1'); + }); diff --git a/src/app/services/resolver/auth_provider_resolver.js b/src/app/services/resolver/auth_provider_resolver.js new file mode 100644 index 00000000..03f4e616 --- /dev/null +++ b/src/app/services/resolver/auth_provider_resolver.js @@ -0,0 +1,84 @@ +/* + * 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. + */ + +/** + * This collection of utility methods allow us to pre-resolve AuthProvider + * resources before a UI route switch is completed. + * + * @author Michael Krotscheck + */ +angular.module('sb.services').constant('AuthProviderResolver', { + + /** + * Resolves all available authorization providers. + */ + resolveAuthProviders: function ($q, AuthProvider, $log) { + 'use strict'; + + $log.debug('Resolving AuthProviders'); + + var deferred = $q.defer(); + + AuthProvider.query( + function (result) { + deferred.resolve(result); + }, + function (error) { + $log.warn('Route resolution rejected for AuthProviders'); + deferred.reject(error); + }); + + return deferred.promise; + }, + + /** + * Resolves an AuthProvider based on the unique ID passed via the + * stateParams. + */ + resolveAuthProvider: function (stateParamName) { + 'use strict'; + + return function ($q, AuthProvider, $stateParams, $log) { + + var deferred = $q.defer(); + + if (!$stateParams.hasOwnProperty(stateParamName)) { + $log.warn('State did not contain property of name ' + + stateParamName); + + deferred.reject({ + 'error': true + }); + } else { + var id = $stateParams[stateParamName]; + + $log.debug('Resolving AuthProvider: ' + id); + + AuthProvider.get({'id': id}, + function (result) { + deferred.resolve(result); + }, + function (error) { + $log.warn('Route resolution rejected for ' + + 'AuthProvider ' + id); + deferred.reject(error); + }); + + return deferred.promise; + } + }; + } +}); diff --git a/src/app/services/resource/auth_provider.js b/src/app/services/resource/auth_provider.js new file mode 100644 index 00000000..b6d9a29a --- /dev/null +++ b/src/app/services/resource/auth_provider.js @@ -0,0 +1,58 @@ +/* + * 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. + */ + +/** + * This resource exposes authorization providers to our angularjs environment, + * allowing us to manage & control them. It's also used during the + * authorization/login process to determine how we're going to allow users to + * log in to storyboard. + * + * @author Michael Krotscheck + */ + +angular.module('sb.services').factory('AuthProvider', + function ($resource, storyboardApiBase) { + 'use strict'; + + return $resource(storyboardApiBase + '/auth/provider/:id', + {id: '@id'}, + { + 'create': { + method: 'POST' + }, + 'get': { + method: 'GET', + cache: true + }, + 'save': { + method: 'PUT' + }, + 'delete': { + method: 'DELETE' + }, + 'query': { + method: 'GET', + isArray: true, + transformResponse: function (data) { + if (data.error) { + return data; + } else { + return data.results; + } + } + } + }); + }); \ No newline at end of file diff --git a/src/app/services/resource/auth_provider_mock.js b/src/app/services/resource/auth_provider_mock.js new file mode 100644 index 00000000..82683ca7 --- /dev/null +++ b/src/app/services/resource/auth_provider_mock.js @@ -0,0 +1,83 @@ +/* + * 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. + */ + +/** + * Mock resource responses for the AuthProvider resource. + * + * @author Michael Krotscheck + */ + +angular.module('sb.services') + .run(function ($httpBackend, $injector) { + 'use strict'; + $httpBackend = $injector.get('$httpBackend'); + + var authProviders = [ + { + 'id': 1, + 'type': 'openid', + 'title': 'OpenID', + 'url': 'https://www.google.com/prediscovered' + + '/redirection/url', + 'params': { + 'list': 'of', + 'additional': 'parameters', + 'required': 'for.this.provider' + } + }, + { + 'id': 2, + 'type': 'openid_connect', + 'title': 'OpenID Connect', + 'url': 'https://www.google.com/prediscovered' + + '/redirection/url', + 'params': { + 'list': 'of', + 'additional': 'parameters', + 'required': 'for.this.provider' + } + }, + { + 'id': 3, + 'type': 'ldap', + 'title': 'LDAP', + 'url': 'https://www.google.com/prediscovered' + + '/redirection/url', + 'params': { + 'list': 'of', + 'additional': 'parameters', + 'required': 'for.this.provider' + } + } + ]; + + $httpBackend.when('GET', '/api/v1/auth/provider') + .respond( + { + total: 1, + offset: 0, + limit: 10, + results: authProviders + } + ); + + $httpBackend.when('GET', '/api/v1/auth/provider/1') + .respond(authProviders[0]); + $httpBackend.when('GET', '/api/v1/auth/provider/2') + .respond(authProviders[1]); + $httpBackend.when('GET', '/api/v1/auth/provider/3') + .respond(authProviders[2]); + }); \ No newline at end of file diff --git a/src/app/storyboard.js b/src/app/storyboard.js new file mode 100644 index 00000000..fd58d12c --- /dev/null +++ b/src/app/storyboard.js @@ -0,0 +1,59 @@ +/* + * 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. + */ + +/** + * The Storyboard root application module. + * + * This module contains the entire, standalone application for the Storyboard + * ticket tracking web client. + * + * @author Michael Krotscheck + */ +angular.module('storyboard', + [ 'sb.services', 'sb.templates', 'sb.pages', 'sb.projects', 'sb.auth', + 'ui.router'] + ) + .config(function ($provide, $stateProvider, $urlRouterProvider, + $locationProvider, $httpProvider) { + 'use strict'; + + // Default URL hashbang route + $urlRouterProvider.otherwise('/'); + + // Override the hash prefix for Google's AJAX crawling. + $locationProvider.hashPrefix('!'); + + // Set an intial home page. + $stateProvider + .state('index', { + url: '/', + templateUrl: 'app/templates/index.html' + }); + + // Attach common request headers out of courtesy to the API + $httpProvider.defaults.headers.common['X-Client'] = 'Storyboard'; + + }) + .run(function ($log, $rootScope, $location) { + 'use strict'; + + // Listen to changes on the root scope. If it's an error in the state + // changes (i.e. a 404) take the user back to the index. + $rootScope.$on('$stateChangeError', + function () { + $location.path('/'); + }); + }); \ No newline at end of file diff --git a/src/app/templates/auth/provider/list.html b/src/app/templates/auth/provider/list.html new file mode 100644 index 00000000..198ae419 --- /dev/null +++ b/src/app/templates/auth/provider/list.html @@ -0,0 +1,33 @@ + + +
+
+
+

How would you like to log in?

+
+
+ + +
+
\ No newline at end of file diff --git a/src/app/templates/auth/provider/login.html b/src/app/templates/auth/provider/login.html new file mode 100644 index 00000000..f5967fe1 --- /dev/null +++ b/src/app/templates/auth/provider/login.html @@ -0,0 +1,23 @@ + + +
+
+
+

Login with {{authProvider.title}}

+
+
+
\ No newline at end of file diff --git a/src/app/templates/footer.html b/src/app/templates/footer.html new file mode 100644 index 00000000..06e352a4 --- /dev/null +++ b/src/app/templates/footer.html @@ -0,0 +1,23 @@ + +
+
+ + Powered by Storyboard | + About + + +
\ No newline at end of file diff --git a/src/app/templates/header.html b/src/app/templates/header.html new file mode 100644 index 00000000..4d8d535e --- /dev/null +++ b/src/app/templates/header.html @@ -0,0 +1,55 @@ + + +
+ + +
diff --git a/src/app/templates/index.html b/src/app/templates/index.html new file mode 100644 index 00000000..3fd9cbac --- /dev/null +++ b/src/app/templates/index.html @@ -0,0 +1,67 @@ + + +
+
+
+

Storyboard

+ +

A task tracking system for inter-related + projects.

+ +

StoryBoard lets you track what needs to be done across projects + and branches. + It is a proof-of-concept demo of what the ideal OpenStack task + tracker would + look like. It may or may not end up replacing Launchpad + Bugs/Blueprints for OpenStack task tracking and release + management.

+
+
+
+
+

Stories

+ +

It all begins with a story. A story is a bug + report or proposed feature. Stories are then further split into + tasks, which affect a given project and branch. + You can easily track backports of bugs to a specific branch, or + plan cross-project features.

+ Access Stories +
+
+

Projects

+ +

StoryBoard lets you efficiently track your work across a large + number of interrelated projects. Flexible project + groups lets you get the views that makes the most + sense to you.

+ Access Projects + +
+
+

But why?

+ +

The OpenStack project is now running into a number of limitations + and annoying differences in workflow with Launchpad. At the same + time, Launchpad development stalled, leaving us with little + chances to improve the tool to suit our needs. This POC reuses + key Launchpad concepts (like bug tasks) and goes beyond.

+ See project README +
+
+
\ No newline at end of file diff --git a/src/app/templates/page/about.html b/src/app/templates/page/about.html new file mode 100644 index 00000000..d58616d8 --- /dev/null +++ b/src/app/templates/page/about.html @@ -0,0 +1,95 @@ + + +
+
+
+

About Storyboard

+
+
+
+
+ +

Waxy gurn trimmed Leonine, waxy gurn 118 118 trimmed john cleese + theodore roosevelt charity donate socially mobile cigars Leonine + lando calrissian, john cleese testosterone trophy waxy gurn + musketeer lando calrissian helllloooo charming villain cigars + socially mobile 118 118 charity donate theodore roosevelt comb + Leonine trimmed. +

+ + + +

+ Old west sheriff comb soup strainer don’t panic en time-warped + cabbie, rugged et tudor philosopher comb don’t panic en + time-warped cabbie old west sheriff admiral soup strainer, + rugged et bruce forsyth clone zone shopper super mario comb old + west sheriff don’t panic en time-warped cabbie groomed country + baron admiral tudor philosopher soup strainer. +

+ +

+ Wario et sodales cum mustachioed wario hairy lipsum, holiday + waiter bruce forsyth hairy lipsum dick van dyke wario theodore + roosevelt wario leader of men horseshoe brandy sportacus + mustachioed et sodales cum, sportacus albert einstein leader of + men dick van dyke et sodales cum brandy wario theodore roosevelt + furry facial friend jolly good show bruce forsyth horseshoe + hairy lipsum holiday waiter wario mustachioed? Rock n roll star + groucho-a-like borat beefeater fox hunting, borat beefeater + groucho-a-like ian rush fox hunting toothbrush robot moustache + rock n roll star yeoman farmer groomed, robot moustache tudor + philosopher wario yeoman farmer groomed groucho-a-like borat ian + rush toothbrush beefeater rock n roll star hungarian fox + hunting? + +

+ +

Groucho marx mr frothy-top glorious facial hair mr + frothy-top albert einstein furry facial friend stiff upper lip. + Robert winston um yesbaby middle eastern despot brigadier + godlike sweat irrigator,, brigadier middle eastern despot sweat + irrigator, zap rowsdower jolly good show iron tache godlike + robert winston um yesbaby.

+ +
+ +

+
+
\ No newline at end of file diff --git a/src/app/templates/project/list.html b/src/app/templates/project/list.html new file mode 100644 index 00000000..d91f54d3 --- /dev/null +++ b/src/app/templates/project/list.html @@ -0,0 +1,48 @@ + + +
+
+
+ + + + +
+
+

Projects

+ + + + + + + + + + +
NameTitle
+ +
+ +
+
diff --git a/src/app/util/directive/active_path.js b/src/app/util/directive/active_path.js new file mode 100644 index 00000000..a5b2ab44 --- /dev/null +++ b/src/app/util/directive/active_path.js @@ -0,0 +1,45 @@ +/* + * 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. + */ + +/** + * This directive requires ui-router, as it listens for events dispatched as + * a user navigates through the application, and adds the 'active' class to + * the bound element if the user's selected path matches the one configured. + * + * @author Michael Krotscheck + */ +angular.module('sb.util').directive('activePath', + function ($location, $rootScope) { + 'use strict'; + + return { + link: function ($scope, element, attrs) { + var activePath = attrs.activePath; + + function setActivePath() { + var isActive = activePath === $location.path(); + element.toggleClass('active', isActive); + } + + $scope.$on('$destroy', + $rootScope.$on('$stateChangeSuccess', setActivePath) + ); + + // INIT + setActivePath(); + } + }; + }); \ No newline at end of file diff --git a/src/app/util/directive/enter.js b/src/app/util/directive/enter.js new file mode 100644 index 00000000..e49aa49e --- /dev/null +++ b/src/app/util/directive/enter.js @@ -0,0 +1,39 @@ +/* + * 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. + */ + +/** + * This directive adds the often sought, but never found, ng-enter directive. + * It intercepts keystrokes and will execute the bound method if that keystroke + * is the enter key. + * + * @author Michael Krotscheck + */ +angular.module('sb.util').directive('ngEnter', function () { + 'use strict'; + + return function (scope, element, attrs) { + + element.bind('keydown keypress', function (event) { + if (event.which === 13) { + scope.$apply(function () { + scope.$eval(attrs.ngEnter); + }); + + event.preventDefault(); + } + }); + }; +}); diff --git a/src/app/util/filter/debug_filter.js b/src/app/util/filter/debug_filter.js new file mode 100644 index 00000000..090ddf87 --- /dev/null +++ b/src/app/util/filter/debug_filter.js @@ -0,0 +1,31 @@ +/* + * 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. + */ + +/** + * A helpful development filter that will console.log out any value you bind + * to it in the DOM. You should probably only use this while debugging. + * + * @author Michael Krotscheck + */ +angular.module('sb.util').filter('debug', + function () { + 'use strict'; + + return function (value) { + console.warn('DEBUG', value); + return value; + }; + }); \ No newline at end of file diff --git a/src/app/util/module.js b/src/app/util/module.js new file mode 100644 index 00000000..a4b691bf --- /dev/null +++ b/src/app/util/module.js @@ -0,0 +1,17 @@ +/* + * 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. + */ + +angular.module('sb.util', ['ui.router']); \ No newline at end of file diff --git a/src/favicon.ico b/src/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..40b3ac5ddc3006f298aed7a26c24fa42c009771f GIT binary patch literal 115797 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

tlW``B zfD^f6Pap|EBEf$S{40P-5&+oc2>`izuf2Y6!>eA)^Sn{ZvU3K_RvIn()^fVrzAF(( z0+5(-{weTxs|S-N01!lA8>kaJflO5?`u#1hekIRq&CJ@fM#!$$Ta?Cdrn7}8BjLc! zrv;M$Bxac32Y!Mu?*>e!06?e`Y!f!gokysls{MX{OTAyoYqffA?OB0rrP-pemNT6; z2E}n}Pap|EVn+E>;0FmkIRhqD03eEhqIF;akzBoMzu#Z?>Q-ubtzOIQ0|v5{Mhj;Q zrz#N;!QUiBm;@j(gZ%HnPZD}@b}-2T0HIi6o3QoRydar+)uLZ)D7sp!*XJ^8&xnX! zskiVF!vUaV?{FXqKw^e?2KX7^e3Oq+B8-7Sca_5}e zSX+BV)&Gm-6DLf)UVk4V`3uKSVpMrz?JA&@fa0m&WA8vBF#)Ur>x9*|3*hU75&f%# z!SPD`{yOk%eEl6UEdl^R1TGNThaVInbFTCo>uaxw$mf=pmrcE1e{Uw5zp!`;FT&$% z*T~h=$Iy!+kVuS~g0Spmm#{?M^MrQzmk5Si?X`K8VAwsv#9b$T-^J(lg=rE1;stpL zSOiXpF~)oEHrCd^F32A)omjH}Gz01Ixgbdfq421wjQgeq%raGQLSO@>zHCG6(&>YYZOy->P8*6J{ z1wOa9yiC1bdyg2kuP!VhDDPakM6OB!I6QTmrCrDpx5E>R@)BY8{3^lFFUQC0@q1eY zLl=Tk_qYoeeB5N-Pn{)f6Wpc@_y&ZgAX1d2Ut3#!75Iaty<`Th3-yj(BoAFr z=F!Qr4Z@Y>zvcIwY8T8WNCTX)@rpUF_@PZ zmNBY4di6~@MM=kp6-j6IFF)CA5)8PS+3pft@HWAyyYaY5*m$PHa5PWc1=B155Y+w| zf+z4+pdn(^6@^<}TYDKWi_6PWuh*XxR9-rM0;itV`c+oCj`OXIj+?p=Xqve~@ZPQv zM&FAJ_l$4^Bd&Is-XMtlb&^gW7}G8Q04ufmkCCFiD1ZUggASZ;DT=xM(xBA z<|qjOgxK;6gc0c>gkyr_MOpgmtJhyb)J9L>u{k3=#X|2`={p~(^%gf(=t({|d?{XwHo>Tskmjn=T8RX3^aKEgyAE9f9tIjlq*0c|;_B+^3nF3{7Z+=J zo^KJ9Bvp;%j{x5(3a^o*`ynax_ zu0^|PGmN3Dvd}jP#{6nLR`uR*5Cq^7VU*stCXPg6KRAjWz+NcP_~HhqT~x1o?{VtM z1ePUkrGl`C1KRwWZ2A+NK767KROy(l6AAA Q0000007*qoM6N<$f`89u&j0`b literal 0 HcmV?d00001 diff --git a/src/fonts/custom_font_icons.eot b/src/fonts/custom_font_icons.eot new file mode 100644 index 0000000000000000000000000000000000000000..a2c2073a2c074451341fedb2c586ceaacefe11b2 GIT binary patch literal 5136 zcmds5TWlN06}_|M?vfNGS?}1i<&Zmf!R-zfC= zpv&d#QvSK;FaHVp2ShIK>dJcY`*YK8!}Z_M-n+V%U;Wk(U%5ln{AcKAadY(a-q9cZ zp5^cU`pX||Nw;`Ud_+1ZQ=$OtL{)xFJLxO;&ON_@5Vx+GLUNvNeMldYxOL|iMTH_{ zq~fVcl8)wr#`o@O+Xyrs&u(&)gmmKv{X@Eg5%aUL(vBu!-0e_sF;)r^pn5rR)s+8R zsc~)4%i;_&XVOEXozPqwxzeNwp-q#fiCH(0ND`Tb?gq`(r0)p#HT5+e=xef?Ubt2$ zh%>ieZ4!N)q)$&B*XL@C&)1Tr^s*kCzh_XG~f90+UHi6uiRX^nV)~^$up;BXA+ML9EyZ@?`rOB z>1=Ea4|X0E9i|xUFhjTx^zYU7!7|v^+I~a~4gi_0hN-&_4Gf0*dfVF?MgO7BFe2U~ z%mafJYe##B-XQh}ojd4zSoHPoL4RQOb+kF1_H}T}V25=eEc&g^{=ox-{oHp)TdQRn zMz;_rC&kq5H}N19MdDwUuRv5f`&~y9chGy|t z!ux2q?&=Wcgy+$I5xM;<$IvygjD z==Yp68_c?9t)6b7u(Qj*>4#R7l z-mtGP8(y>fZ75N39M1H1zc3rMW;4?4YjIXF=H|w`AG~&{`d$?aY7z}qj6+RCtJp=h_+}Nm!TDnq>$F2_tzv_kwBx*Ux%n)71$PAt96^7n zVh!agtJp;;(O<=G+9%$sVx6S;TNN9$PYY23M_it=I1c&nlQc)y@tk&!#s%2(bOrh( zSS#SH4vEnKqk&8ylTN1tio)r%rD!IVPp2bFvnBd* zhq4%go|s7~-HI#2iU)$hv=W(!a@iKfBj?NdTwHR?rjN9)AYek4WC`7sV|u7Go65`t zvM19iD~-0%Qz(l{cvjt*gEQssiYUXDJR&Wb zQzAK+8FL0Y@ ze^M%M;xSGEfE766As?MG~ohqAREWKaV z=dF#1^4pWMsmW6nV;~57i({|1%j8d-NtONn1l-4!FPv7CP+BNn_VUArhZ5~bf-5wW zDhp%=QxPvAuW;+_3R-xrh69y$enks8t!acYfx%B?kiWYrD-*R?2tA?b*d|UKC*2Jg zi=I54BIUQ@GJ}49QID^JI*P|jnR2}zR!iZ)J_O$gVnaBhcGzXXvdJ!MESv4Ji)D*l zcC&0nR#~>$WrJnAT{c;E*kupP2kf$!}@(!TL zCQuu-(zCKdmMon~ebR^-j;MoM`4sKyK$jA2F(-Ww-5c)qrY>9dJEIBPq+FHy#ww}# zV@T~kceaeNW7bf)OSEBBI3h+cf*LD>0?H0WRK$*Uj6_uQU$kQ8b6|8MdDI?~Q8~eD z3_%|+l_snSten&wVo(BWIVwb3E4;*P_(tvFpF>ebGMq0(Eh$Gz=&R>$vy4{yP;TBR zl3}SbypBd^Q?F~%B?GT(ovvN!IInCEb_n=`M{68~oj{dh6;ZgdO=*eDyro=;>^v5) zmdFNxGij^@(6Vrh?a&&}4h1aqGmg}iJ4FL*r5>`6qROff`UKW&)(>tEn z`~p@meYZ!ehvtr%2?Xv^%dYp-tO9JW;~Tx;3Z>9DPO!X->O&ut0C|0%~vc2sr3{}Cr6 zTraf*D%667QjMZ=D`OnNYQ%1~RamtU?_W6+|6Q?gc6hChSVMu}Jrfs9S4VP`L$0On z7)Kf8{PIAmqumPZVFcDzSuvZ$i=!o~Y%Gw`e`9|H`+#U|Q4w(Bw(5pRaBh;wo*c(E zUdzT9HU_Mi1d^Au@rR5NfN=o9V8Y%Mj^$AR$8wxGN73{ca~MoAhrtwc7)&$gFu>!? zVQ_*u3}%?aV3s*Y08TQ8!71i2IL#aeXP9#g;4E_(oMR4y6muA)nKKMffSXV#T3eb`VpqIEblBc364x%C&!HgSYPpcHYT1=(i_v5Q}f5-}KGqpM-b2hUtzBHM_%@F~Pvd#Aw3tbTrY(W zzA;Ipp^x_6#bSQp)>}W_BGS*GeRvTD*H6TEpnnbe{>A0;roKRJ&=rq!WwnqOWy09{ zP3XSm{N|e2@J&E}2fAFzFBhMC{_1EfxwQ)+ZeQtA zYJqOPPw$hsdHW{Cgd$|5=BZASj^={K&+dBLI5eKmZgP`^bmNBpKHbKQ`Q2J;N0Tt_ z3@9`h___OX;=0@Le~C4&4SHFeMdnO;U?L37rI9O3nh@G7X_}aG1Bn!oY3OdyTy6S} z$Y9%G+kwG0tL=qrrII*%>(w?f$O&pDy8SlRU18n5(Ap@BwVR&*g@AbHL`SotM*5ua(2{S=%&3%b9mv)ItB6)PfqnAkc8@j(lO@6Px z$-C%l(Y(U%ML7!c3o12Zm6ymc{l-Z$4F75J8~*9#D;@1OzP$dqwUsN+E(KB> zXmFsrt5pmg3P%v}9$_9Bsabovd-N8uN9a7j;DcgtU=PLvbFin&8Fa9RTSj`U0}(M~ zg@;BCj12MEJzbraX&8M%oSG3QZoPrm;h4DJ<3G`4YVUTO5Y66OuXHsdOwHpLGd>R+ z55o$BR}Xq_z1-3+9!Yv1?$cd8!kqRzJS3vGe(e~-lOCAAD)@2 zM2q<)BX2xo4qcCa{zbp%oY`VFwQC)%<~eVx*ekxkZ@=fP(d6;L>^Fxp-WIV}mmaBg zHqX9Ax~!Vs-2yTYR&Q-QfJWj&<6hb=I*#ZQ5}@ zx!imnzJjNQ1?{81)v<J^b*)B=vSr(h?48Ye7U$F=da7zrNUyqcty^vua-9oi^ala+qUJk zrShVjT3snmt*&1z%7Iv19$YM!*T(w#O0bsL8rvwvR*Gc|SD>r#P=>!{oHGso7o13W z-W#A?-6*dvU*OIcmI|vYFwHu7Swi1sD8+@PtB@Svrv*BOU_aZHL>f3bQR>GtfE4u; zKJWJiGbTSaAvq=oqW#f=}hJlQKdt*5|&hCCGzUVJe(~oJ>`$JSWYGkpi3tB?Iu*aHm`$D?eH5?6Ir5o>C$|8C6~z<4LK!$wxQ^09GQa ze5{><=7SbhK3l%-rg?r9;7BzkbFz|?stNOrswR8pOr~mz$?SgBT(mZ$%5TriWoAy- zjDaBR9ge-(u981_HdFQclW?CUg6f; z8??}^fdjR6?xKa9)-1x9#^k4S$lslmRf#$*gq~D%Yzto;C*3WWi=H}@A?3FcGKX=0 z*^FNWO_WGfa@A%%qLw3peF(l4#Fj`@?XatYWt&~qShm|$7t0R2>So!Atg`H~s|L$% zyK1uRv8x`I_t{l1%bm9JME*nHyWo2#`UK#c(zEiTmaLr3 zeAI{)j;e#(`4rviK(7*AaVLEb+#T+{O}(}pa%K~;Nx5qEja}04$B?>z;T##0$E?w6 zujs<8@QE153>vH)3MfAsRZ%PI!si@QvETKZl}>RHRsmSyGNyFjoJaW*MuEq1=2>q#{z~cppv7WnR;y zO9o!k!meG}1n+DQP6+seM{5d&okW#l7g3~kOlis7f~8!^`~o(wmdpo$b6M;J(DHDM zYzVROi0vmj@-}jE*-Bzkn6Y-Wd_AH^A{o z_|U`kc&u@RIp~;`2RlT{DGPavpa`PskP|*;rq#1UXEHH4j$@kVRX1X=yV4heb{tJ8 zv{b>WWxRHxS@o=9PEj>f_n2&?HOJosMA69nux-g0hd+h$X*?UNhD9eTdt}>;I%cc>NCivIYg<9_f6OtG9aCZWKjLJB>!p!Eg<7yssxee< zZI0vEjX2G=3#$?0XIIYje^)G=9p0=IDqi8yjTeQ|u4n91xuyDhf`*R(%jj&P@v0lT$dx8`+q|!GIl;MDkKL z{*W;aFa;nOOxs(+u{;dmSdKI2D4HH&4ucuyFgU>+2D8jL4Dcv(7@TAdgEVs(%rWN( zz$xZ1IL#aeXPCp_EOU+lJjNUb=a|DF!yE=#=8OTHXAXnMnZw`-<}i5DRs-8sbQ<4?&_N!u)sM``5qLfA0F$+26PKK4;&%&bns@850Nq2tb1g1)!+&sq6o8s{Q|i zK(H_b0Ps4bazns)u%l4A_zMI`i-9;V1S}u}z>Uq%%0k*pi0eThYRO*{bno$6srQ^sVI(&cXM_iK{?b~q#!6Bk5<&UK_a9zLY!KkFsvMW?B*2^3~8Ss zPJLq(EeSYz-P?&8w*qknD!>51#LFQV+LxYMGnNX_AN0TB;N=Xtp?bj(0D#elM|#fs zc>4zc0Ao57BMd<{*U|8ukDoJ?%SheVii*^{3`%g86Ol+H0pW5Dai1bq{3~CdxjzV4 znbKtd0M$n#5@%qJ^avEukqFmz!McDy&;Z;MP=pqs`W@8U4jomz(^oR-Jd$obp_)_M}Y+*f*sc$Ay+t%w6He%Ld^NUz3W6K=Z z=S*{Ke9o8fJb0dxC!&|;9?pwBuNFJEYk| zDB!zkZLzP@DfV8Wc(@!!khrY!j(vTE(85y;J9{U&L$$58B3gzoxI8pnA~`l?wflUa zo>6*Kn1%0fp4HrnbejEsih)F*W>LK3g~H9S#;K!#FB~!&0je!hdXEUDZ^)l;85@J! zFC%a)<6WySCI`m%wida}Ey}L?)^2FJFx%;UxE_#;2Y5xz=2t-@g)Ev9u3g>E@#TJy z^@Ck{sk)_X^ljKPIkh{!G8;F<%4&RG(tD7|E75lz22F0U3>&N#g;y0j**0Rui`@G&9HaJl&3pgOk&~ULe4JcP zImCS3PR`uBx=<9tLUy0ly)nU(oM|PX2`YL3Rs-*qSMNI7=@Uc>8V*Vp&(ciy`>$B6WE&o6Eg#EGdI9 zRW)+Zm9itvN4Sm27_j-(H~ZIy;gnRyrfjL~3dnB2&$7LO z5V+V)X5M;=2^U*H-8DSXrbKvUL^^(q90z`X%Fom+$>zpPD3b`U3_l;LTknNkAn{+p zucf4{pIS5LJH2}+?&49KpxHfnKPT;@he-XSafnpM47+wcc_t)Yc_QaW;)!GUleLO# z(7zb~0gyrgSc0=eQu>TfX`#EOgNlBPWN+3?HDsbrRypvP+on5@W4TS`^Uv%!w@35G z^f0i;WZ<6X`^jySeulexUu(X-^?Wc>_c&*bP3)Q2_a7hC`g=1$8Y$qL6AVYEe2yEf zOFux1jUmy{wXLR?Y_Z;-Iqf|0@}p``9?zS?firKsU#G%(D$YtpE#XMO@p0Gr19miS z-j0q4_mF0etAa~zq4s9RR+8kpSD6?>*Mw8%zD_Nwz4ksW)!RQpFbYz(y5f`cVd}{j z+x{HIF)Myy{j@RBwYM5Ap00JNb>_9&vDO&^&l>^pR1ccG7xd{vMYjqUv|ojj>}udo zmkh*+?uBRSGa4RhS4e~Kgk%zm$lN$^msNSJ_Bpwwxq8!ix;b>`U~uX8*RHQUN482l zwL|7k%h3qQMWO8RRz^%Q2I)G;i9XEl|7JF9n8?Mt>>qhDKH5OU&rVuZnQcE37TFvz zNHkGA6_khTq?FiiJxjRSJpsRgsTGa)g%BBc=}W zE3POuiVPtlY@sD7Xl|c`gJNNR4NDd7l>W5hE+o0IibihfxiFEs?yK28&UB$qG_l#_T{h0nl_C$;6>gXH>%=fm- zNr`I1%_^I718RYj?I}T*3fI2*?+;tqSfOX8s-s~diTgfsFAqYbwP2xC*Ax(oBoF3FpA_!qn-1zP}UE5s085(ZXSDLNHY#7$++u zTm59o`3)C08UQXY!BP5+K)0E7H3%l!km;bd*a=$&3gN3@LOwNc9Q_3|d<_E)Qlc6G r;;V(h7*p#i%^2%y1Pos-N@b03fJ#BU4Kx}-N@Nv0p_&$e4$gl7>%=DY literal 0 HcmV?d00001 diff --git a/src/images/logo/logo_128.png b/src/images/logo/logo_128.png new file mode 100644 index 0000000000000000000000000000000000000000..b52a9a136d7a1db66c1afefb67bc47f77fdb2b92 GIT binary patch literal 68458 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 literal 0 HcmV?d00001 diff --git a/src/images/logo/logo_32.png b/src/images/logo/logo_32.png new file mode 100644 index 0000000000000000000000000000000000000000..a9006d2880d250118c270a1bad70552f45b8f624 GIT binary patch literal 2623 zcmai0X;f3!7EVe*0TFN}KnMX*h9o3FASnSd$`nKlf?%y7xj-bzjY%L7;ps!Fq@rNK zDgrVDw7Q&%0)_|{kx8h?AV`o>wIEO}Vwn|u!K!`ht**Yi?!D)ny}obnZx26?A~dL zL29FkxzWTB8skGO?TLhpl}bfK3`QoCp=B;;P#lB75(tDPA2=LJi$F<|gi>}QN+_}U z=z#`EIAWei$^(UnC6DYVFkVVRYL)((f$&Vzy{P$*a|-G$&xrZFh)RA+Yz-ObgF{*mh^lt|e^4)Br7`-@BdM=p^n2G~+i z%mP9F$LKZt3yKib?RdoIFrJVL$|UwnrTw535c3iME<+3o5btY4tBEgkArQUmel#*GQFAwJAaix-8gJQf(D|;>nS_AW*VZ(jjBP$0 zX|qMfdq1;V)UmUhAIqL-SZ|eXb+s1uEE{X*a7U+oZ%Nt)ozzuEhz-lD)lM%Gss<8> zH7>n_s)7VHUj|)WpLM-UC3&8_cz+z8)^i5_>qhuZolVm(;a=A;-_dgzEj3w)msAg$L#Y zk@1`S0~AjqqS9wP%#-w$EGbG;AiMoWX=*XnIKiv5dFZPjsOQSmFR!h8wy3rrnC)a( zoqDu<(Z0+cG}PppdY|1ZHAc^L?@YRExx!mscstE^miw{e{0`*oq?JKOC)LsgebLe0|SSvNJ^vyYVez2~kN*ng9= ztxkvitj=jp%{OKDXv#WoAP>8}d>mK9_qPl1HBj4GC%p^xTW6Rp=b1vW!j#B(u0z>49tC*sipjPD%OQbDyR)H)CfE zEa(u_s<3&x*HD(D;NCe4L(HJnbDy>YVrN`G9|lyCU9z)ZMP4pDLTbXFkUFl_gcg=8 z&%Jj@B!~2$x}C3_OUQF*rsYH2@5(#kM{?(FRgd}`s|KYM<^vw~62wS$ksyndNY!oDzDcE+sbQS{6Wr(jtn^L$iSCxqWhGu%;}Y_eQXf)Fbv~# z;}{2mDJY0@4o%fvi<-(|#ML^gntnqlKxz?Ovs-%kRPafd&V6X}qex+ku-iN5$A3k} zNe0{`x zgJ@;13(LRH&V0n`=NZp0f+-sKP#^3p$`xBC+A+J~<)qxTmw(Xn^UyM2q%ZoXbo# zJU?p2U9Bn-vlMd{^eLP8p_~G*Id!4ZzqH4)>a@%J)XSr_pt|0X6SHu#u1U9fxWCT$ z)Ii(x%d_eOTi5LQc3+43UF*AmQ`TTh2Rr-1X?>ntK0LMcV&28fz?@9}4{N?;$vs*J yhMwL)*##1_Gx$zb*%js{UQF|rh3VU$t$^&$r_|4#9>XtP>HO$Hv@4W7ss90L0Al0- literal 0 HcmV?d00001 diff --git a/src/images/logo/logo_48.png b/src/images/logo/logo_48.png new file mode 100644 index 0000000000000000000000000000000000000000..ecc06156181e9605226d0c405816531e05d805ff GIT binary patch literal 3589 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 Y_KJmBmE~XzG&z8tj?tBJEquiP0ND%d{Qv*} literal 0 HcmV?d00001 diff --git a/src/images/logo/logo_64.png b/src/images/logo/logo_64.png new file mode 100644 index 0000000000000000000000000000000000000000..ad5286545035a7db9f8b0df36bc741edd65bf81e GIT binary patch literal 4483 zcmai2c{o&m+dsC9t&m+9OQbMnm|?~?W68c`WG91Rh8WCPBZX|0CCSc+vSdkwNRlkc zPKYSkiIlRJm*4a2_q^A8J=gP|>zwobe(&q^x$n=toPSQ7nTakNvj8&y0Brht+UAEV z`se{2JA9WCeWwl=eu|DY1xs?H1mgVg0LGQ%j0fv`;oR}&c${mn?;E@-0MLmMEvzZl z#zrU?l9wFr2qPEd<#Wge09B13ADoLPo&t8pyA!?D#J)B*i-C!*YGPJ!V|imAEj)p! z7vhJ0Zhd_}?M)J zXyeH)encM%k>m|N@`!UL`BT)y4we2Z1uq|C<9{4`lm9N%VaXstI3Ea9P9Earb(Gg% zXfnkd|8E)p5lyxT_Q6BU@nn*}pUYuC+{FKo4{P_|104Ym)u6OVF8*G4Z;HOQn%JR5 z&Xwqj(t;zDU~nZ(1X5EI3e{22l*cF|b>yK)3|vVO16BUR)%PY-aNaKXKV0I!xtRaT zMQQoraTJoD1&MU|Pxs6SBnpX4Ao+l`un6!OE26h6DUd9ERNB9l;{AvLc-QlOBrot^ zwLua8Py8e8I!GNIgt8_~^H9Bx0u-tY)6&wyV6>IBl;m|36*a~F=DPley#HS=xuQ%p1l!+R7W#|oIUg&CXyP~ zK%Fi%%?N#Sh1gymW;m*?kA1#=VIvIYpOagEpblH(#1wM7sIeJAg@B)tn-S6IMzjh> zKk35vR$J3&2gu2}cA*A(0 z6L>Ic;MPtFmG6bR-G&G)XblEXL~YgeVw3tV#dw9$otT8wfRY;3B0v3n28iN7<5^GD z`MD;ooQ`)?ZBm69N-=0pb3QX!DyiY>wyJQw2w2ax&V1K`PDKA2Kn^O@9i1u*c>(&w zVH4Ya7i+iC@yXxLVDv?0i>>_*(8V@IV0h;40pJOs_g*Uh&2IyZ!S3RgN$+N;4#1hm(dBmK} zw8}={bO^7c<1p52xWjLUDM<6EG%=&*;|Y-_MDu!l1u;>uJm(T0DmJUyR&MynwOOQckFllhD=rTFXdoKaas5&6jHgX@hAl?ti~`@<7&>i=krwu92H-K-*2Y zfJ7}P)?Db@FF$?Rx)nW_!WU;ABHD)PSGwq&+1(}=#~I?^7wW_We0^X6JI4!I_AoLY zw271cn!p(AkB?xbU0?%=EAm^Ed_*keC)3rG7sYhF^O$^5*FRm>C~ymotF_OkpbY7p zURX#QEnt2*MRlocAM%_hO zhvw+fdDD;G8kUq&e#WIxCf2l!&_rP&p$A&OesMCnMuody7w{;>6!OG z<{-uSjWQn+0$vxd7n;^Xo3BOn6vW#V`1O=$>AguFecEz)(^EGluxaWz;9G3uU-jFn z(LcoON=SGt$nW?Qb1nlLo^Gm9bMT(xGoN@FU%AK2Du>7{XM`OTD*{_8LrI&@XY6N7lTCU5efMlZ{GM$5zuuT9IU4#IR|5d>^N*49^k> ztz1uzrIkwz3(shEv2%-S+V16VP=@yiHW12eMC2Bv^4vyT~5lLjNoS%K}=F}|EP z3q<*p$(ni34!}p@=XO7!_TowsGYI~i%!i;5=`vEP>8%-vemmdAnW}l-Wy79bH$5Mq zf|l1i5w@&9_G7Tk@W=Apx#2t$!^X+7&}tW;u(aic0X&b#wr0fF`W(s5r{F#HvE}JX zWvzg(;5k^>kIF|@z)Oa%mI=ZBvYsyrHFVdkJr^GI#QUs1$;!I_!NTFW4zHWkQmUcV zCoP%u#DT8p#)|gwB}RHdfKorg`=mHx*R%{*7qmB z>1?MuNZ%9|>g??H>is!QdX;*OZ*5TSRRWFEL}mH&;#xZonH}j_x}iC-ZuF(ivKs>K z6qL}%B=_V#iemY!YJW4jV5Ye5xZm(bp7sF`Yws96C2EHTH>4t!{uHZA)t ztyN%3G98MfD?x$SI!w`~iuVTh`Ank5y+(;rIfN8)9nX!Z$36F~l^93YZ+P7Jeq)C~ zN9Ml3lrbJ%1Dsr}V=Lh>R-aa(N@WTC45=C1P7xebetn>$z0Ale`p#Xr5Hgwa(drxxPn47K+@ZZHVHX zy=OSv;D?x*3<O82x-t^glt=cvw46B$$&05737KSV8mGYAm?V0f6dDA)y7+*J zHA1GucMbZCg$rq$OF#Yen;9e4oVTe~(h*_VB}-w_x6=GB#C(%M~ zRoeKjts3?>HR;dME4?VYjp3sO;Rr)lHn>aX={otXf2pN%AA2G@B43lgi(*BqP7_ND zJ6^F#rav8g98G_N(c_Daz6>20zeo}4?nC8zD7QJjYigX$^vSWhM$%X=|a_ zn=>-QOb?S^x(kl#T&ERajGc?m1!|F`Uqc?8m7}h{DzE zzo)78v^JLactWO^PRtwaen3aedt$<%-(KAhRZXB>RbtM}8_FJUpV_rFvZW-fq8N{x z+s>wq3~`i3w4*!jihyR;9xT+q>sKVPMBPI0N_OvSdi~6eD{*5&rp~>8739!!u!UAk zs%YELV}6O>daK`7+-zzHD5-a_6nv%%-B1XsmEt+O7(shI=69hGU#8nz{iNfoX}``h zKk8n-5bfr{Hh6NHGtxP3!0n;;5YK~6T$Ai*uqhSE`hDa_BbQe!^VJjVX-LbWwVOHY zhLjj?HkcyJvTpA28+uFJa;r!D{6*`~bUOy&#$oxSETNoRuZx2kEh?w*S~`#XqbgkH zic%tuZR8`8xAxzceSJFW{N9$a^scCE(!X(2NIX%5w~oNb zyr}x!v|23%Bv|NcoYTRbk~X{$amV7q1zfeod^jyDkg! + + + + + + + Storyboard + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+
+ + + \ No newline at end of file diff --git a/src/robots.txt b/src/robots.txt new file mode 100644 index 00000000..94174950 --- /dev/null +++ b/src/robots.txt @@ -0,0 +1,3 @@ +# robotstxt.org + +User-agent: * diff --git a/src/styles/auth.less b/src/styles/auth.less new file mode 100644 index 00000000..4fdc35e2 --- /dev/null +++ b/src/styles/auth.less @@ -0,0 +1,24 @@ +/* + * 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. + */ + +/** + * Styles specific to the auth pages. + */ +a.auth-provider.btn { + text-align: left; + padding-left: 10px; + padding-right: 10px; +} \ No newline at end of file diff --git a/src/styles/custom_font_icons.less b/src/styles/custom_font_icons.less new file mode 100644 index 00000000..bfd25292 --- /dev/null +++ b/src/styles/custom_font_icons.less @@ -0,0 +1,24 @@ +@font-face { + font-family: custom_font_icons; + src: url(../fonts/custom_font_icons.eot); + src: url(../fonts/custom_font_icons.eot?#iefix) format("embedded-opentype"), url(../fonts/custom_font_icons.woff) format("woff"), url(../fonts/custom_font_icons.ttf) format("truetype"); + font-weight: 400; + font-style: normal +} + +.icon { + font-family: custom_font_icons; + display: inline-block; + font-weight: 400; + font-style: normal; + speak: none; + text-decoration: inherit; + text-transform: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale +} + +.icon_openstack:before { + content: "\f100" +} \ No newline at end of file diff --git a/src/styles/main.less b/src/styles/main.less new file mode 100644 index 00000000..fd0827bd --- /dev/null +++ b/src/styles/main.less @@ -0,0 +1,26 @@ +/* + * 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. + */ + +/** + * Our main SCSS layout. + */ +body { + margin-top: 70px; +} + +i.icon { + line-height: .5em; +} \ No newline at end of file diff --git a/test/functional/module.js b/test/functional/module.js new file mode 100644 index 00000000..7c9c338b --- /dev/null +++ b/test/functional/module.js @@ -0,0 +1,27 @@ +/* + * 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 Homepage', function () { + 'use strict'; + + it('should have storyboard as the title', function () { + // Load the AngularJS homepage. + browser.get('http://localhost:9000'); + + var title = element(by.tagName('title')); + expect(title.getInnerHtml()).toEqual('Storyboard'); + }); +}); diff --git a/test/integration/services/module.js b/test/integration/services/module.js new file mode 100644 index 00000000..4fa4cdd2 --- /dev/null +++ b/test/integration/services/module.js @@ -0,0 +1,40 @@ +/* + * 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('sb.services', function () { + 'use strict'; + + var module; + var dependencies = []; + + var hasModule = function (module) { + return dependencies.indexOf(module) >= 0; + }; + + beforeEach(function () { + // Get module + module = angular.module('sb.services'); + dependencies = module.requires; + }); + + it('should exist', function () { + expect(module).toBeTruthy(); + }); + + it('should load cookies module', function () { + expect(hasModule('ngCookies')).toBeTruthy(); + }); +}); diff --git a/test/unit/services/module.js b/test/unit/services/module.js new file mode 100644 index 00000000..4fa4cdd2 --- /dev/null +++ b/test/unit/services/module.js @@ -0,0 +1,40 @@ +/* + * 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('sb.services', function () { + 'use strict'; + + var module; + var dependencies = []; + + var hasModule = function (module) { + return dependencies.indexOf(module) >= 0; + }; + + beforeEach(function () { + // Get module + module = angular.module('sb.services'); + dependencies = module.requires; + }); + + it('should exist', function () { + expect(module).toBeTruthy(); + }); + + it('should load cookies module', function () { + expect(hasModule('ngCookies')).toBeTruthy(); + }); +});