From cfc5f0e78c4b571797eb95af27afba42438ee9fd Mon Sep 17 00:00:00 2001 From: Michael Abashian Date: Mon, 21 Dec 2015 10:38:40 -0500 Subject: [PATCH] Added angular-breadcrumb to the project --- .../client/lib/angular-breadcrumb/.bower.json | 44 +++ .../lib/angular-breadcrumb/.editorconfig | 16 + .../client/lib/angular-breadcrumb/.npmignore | 15 + .../lib/angular-breadcrumb/CHANGELOG.md | 151 +++++++ .../lib/angular-breadcrumb/CONTRIBUTING.md | 52 +++ .../lib/angular-breadcrumb/Gruntfile.js | 258 ++++++++++++ awx/ui/client/lib/angular-breadcrumb/LICENSE | 24 ++ .../client/lib/angular-breadcrumb/bower.json | 33 ++ .../dist/angular-breadcrumb.js | 369 ++++++++++++++++++ .../dist/angular-breadcrumb.min.js | 4 + .../release/angular-breadcrumb.js | 369 ++++++++++++++++++ .../release/angular-breadcrumb.min.js | 4 + awx/ui/client/src/app.js | 21 +- 13 files changed, 1350 insertions(+), 10 deletions(-) create mode 100644 awx/ui/client/lib/angular-breadcrumb/.bower.json create mode 100644 awx/ui/client/lib/angular-breadcrumb/.editorconfig create mode 100644 awx/ui/client/lib/angular-breadcrumb/.npmignore create mode 100644 awx/ui/client/lib/angular-breadcrumb/CHANGELOG.md create mode 100644 awx/ui/client/lib/angular-breadcrumb/CONTRIBUTING.md create mode 100644 awx/ui/client/lib/angular-breadcrumb/Gruntfile.js create mode 100644 awx/ui/client/lib/angular-breadcrumb/LICENSE create mode 100644 awx/ui/client/lib/angular-breadcrumb/bower.json create mode 100644 awx/ui/client/lib/angular-breadcrumb/dist/angular-breadcrumb.js create mode 100644 awx/ui/client/lib/angular-breadcrumb/dist/angular-breadcrumb.min.js create mode 100644 awx/ui/client/lib/angular-breadcrumb/release/angular-breadcrumb.js create mode 100644 awx/ui/client/lib/angular-breadcrumb/release/angular-breadcrumb.min.js diff --git a/awx/ui/client/lib/angular-breadcrumb/.bower.json b/awx/ui/client/lib/angular-breadcrumb/.bower.json new file mode 100644 index 0000000000..3895c9f0a9 --- /dev/null +++ b/awx/ui/client/lib/angular-breadcrumb/.bower.json @@ -0,0 +1,44 @@ +{ + "name": "angular-breadcrumb", + "description": "AngularJS module that generates a breadcrumb from ui-router's states", + "version": "0.4.1", + "main": "release/angular-breadcrumb.js", + "ignore": [ + "sample", + "src", + "test", + ".bowerrc", + ".coveralls.yml", + ".gitignore", + ".jshintrc", + ".travis.yml", + "gruntfile.js", + "bower.json", + "karma.conf.js", + "libpeerconnection.log", + "package.json", + "README.md" + ], + "dependencies": { + "angular": ">=1.0.8", + "angular-ui-router": ">=0.2.0" + }, + "devDependencies": { + "bootstrap": "~2.3.2", + "angular-ui-bootstrap-bower": "~0.8.0", + "underscore": "~1.5.1", + "angular-mocks": ">=1.0.8", + "angular-sanitize": ">=1.0.8" + }, + "homepage": "https://github.com/ncuillery/angular-breadcrumb", + "_release": "0.4.1", + "_resolution": { + "type": "version", + "tag": "v0.4.1", + "commit": "b291e06f4010ebebbb41ea2c14e73e236aa70930" + }, + "_source": "git://github.com/ncuillery/angular-breadcrumb.git", + "_target": "~0.4.1", + "_originalSource": "angular-breadcrumb", + "_direct": true +} \ No newline at end of file diff --git a/awx/ui/client/lib/angular-breadcrumb/.editorconfig b/awx/ui/client/lib/angular-breadcrumb/.editorconfig new file mode 100644 index 0000000000..16480f1870 --- /dev/null +++ b/awx/ui/client/lib/angular-breadcrumb/.editorconfig @@ -0,0 +1,16 @@ +# EditorConfig helps developers define and maintain consistent +# coding styles between different editors and IDEs +# editorconfig.org + +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.md] +trim_trailing_whitespace = false diff --git a/awx/ui/client/lib/angular-breadcrumb/.npmignore b/awx/ui/client/lib/angular-breadcrumb/.npmignore new file mode 100644 index 0000000000..86b98729db --- /dev/null +++ b/awx/ui/client/lib/angular-breadcrumb/.npmignore @@ -0,0 +1,15 @@ +sample +src +test +.idea +bower_components +coverage +testDependencies +.bowerrc +.coveralls.yml +.gitignore +.jshintrc +.travis.yml +gruntfile.js +karma.conf.js +libpeerconnection.log diff --git a/awx/ui/client/lib/angular-breadcrumb/CHANGELOG.md b/awx/ui/client/lib/angular-breadcrumb/CHANGELOG.md new file mode 100644 index 0000000000..6bec7b2db5 --- /dev/null +++ b/awx/ui/client/lib/angular-breadcrumb/CHANGELOG.md @@ -0,0 +1,151 @@ + +### 0.4.1 (2015-08-09) + + +#### Features + +* add the scope-based ncyBreadcrumbIgnore flag ([934c5523](http://github.com/ncuillery/angular-breadcrumb/commit/934c5523208a9615d7cfa3abcb397bbe131332ac), closes [#42](http://github.com/ncuillery/angular-breadcrumb/issues/42), [#62](http://github.com/ncuillery/angular-breadcrumb/issues/42)) + + + +### 0.4.0 (2015-05-17) + + +#### Bug Fixes + +* **$breadcrumb:** Handle parents provided by StateObject references ([f4288d37](http://github.com/ncuillery/angular-breadcrumb/commit/f4288d375fd1090ffec1d67e85c6300d74d86d37), closes [#82](http://github.com/ncuillery/angular-breadcrumb/issues/82)) +* **ncyBreadcrumb:** + * Prevent memory leak when label is a binding ([264e10f6](http://github.com/ncuillery/angular-breadcrumb/commit/264e10f680e1bbb8d1e00cf500de39cac4222cfd), closes [#88](http://github.com/ncuillery/angular-breadcrumb/issues/88)) + * Removed trailing spaces from breadcrumb items([bc276ed5](http://github.com/ncuillery/angular-breadcrumb/commit/bc276ed5351a586d4a6dc83ada0687e6ca485344), closes [#77](http://github.com/ncuillery/angular-breadcrumb/issues/77)) + +#### Features + +* Add force to ncyBreadcrumb options ([31125a38](http://github.com/ncuillery/angular-breadcrumb/commit/31125a386d706dd76df807b3b02e1fccea38fb59), closes [#77](http://github.com/ncuillery/angular-breadcrumb/issues/78)) +* **ncyBreadcrumbText:** Add ncyBreadcrumbText directive ([82b2b443](http://github.com/ncuillery/angular-breadcrumb/commit/82b2b443fab220cd9ac7d3a8c90c1edc4291e54a), closes [#71](http://github.com/ncuillery/angular-breadcrumb/issues/71), [#83](http://github.com/ncuillery/angular-breadcrumb/issues/83)) + + + +### 0.3.3 (2014-12-16) + + +#### Bug Fixes + +* **ncyBreadcrumb:** define `$$templates` with var instead of attaching it to `window` ([c35c9d25](http://github.com/ncuillery/angular-breadcrumb/commit/c35c9d255b5e2585d225a961d1efdb51d18f6a55), closes [#55](http://github.com/ncuillery/angular-breadcrumb/issues/55)) + + + +### 0.3.2 (2014-11-15) + +* **npm:** nothing, it's only a blank release due to a network problem during the last `npm publish` (f...ing npm doesn't allow a republish with the same version number [npm-registry-couchapp#148](https://github.com/npm/npm-registry-couchapp/issues/148)). + + +### 0.3.1 (2014-11-15) + + +#### Bug Fixes + +* **npm:** update package.json after (unclean) npm publish ([ab8161c2](http://github.com/ncuillery/angular-breadcrumb/commit/ab8161c25f98613f725b5e5ff8fe147acd60b365), closes [#52](http://github.com/ncuillery/angular-breadcrumb/issues/52)) +* **sample:** Send correct url params for the room link in booking view ([876de49a](http://github.com/ncuillery/angular-breadcrumb/commit/876de49a9c5d6e2d75714a606238e9041ed49baf)) + + + +## 0.3.0 (2014-10-29) + + +#### Bug Fixes + +* organize state-level options in `ncyBreadcrumb` key instead of `data` ([1ea436d3](http://github.com/ncuillery/angular-breadcrumb/commit/1ea436d3f6d5470b7ae3e71e71259dbd2422bc00), closes [#30](http://github.com/ncuillery/angular-breadcrumb/issues/30)) +* curly braces appearing on title of sample app ([855e76cb](http://github.com/ncuillery/angular-breadcrumb/commit/855e76cb33fda607fa3caa230564b77b48262c40)) + + +#### Features + +* Add a global option to include abstract states ([6f0461ea](http://github.com/ncuillery/angular-breadcrumb/commit/6f0461ea7db36d8e10c29ed10de1f1c08d215a19), closes [#35](http://github.com/ncuillery/angular-breadcrumb/issues/35), [#28](http://github.com/ncuillery/angular-breadcrumb/issues/28)) +* **$breadcrumb:** + * Support url params when using `ncyBreadcrumb.parent` property ([55730045](http://github.com/ncuillery/angular-breadcrumb/commit/55730045dcf3b4fb1048c67f1e18953505563ed4), closes [#46](http://github.com/ncuillery/angular-breadcrumb/issues/46)) + * add the customization of the parent state with a function ([ada09015](http://github.com/ncuillery/angular-breadcrumb/commit/ada09015c49f05a94349dabf078f1ed621811aaa), closes [#32](http://github.com/ncuillery/angular-breadcrumb/issues/32)) +* **ncyBreadcrumbLast:** Add a new directive rendering the last step ([1eef24fb](http://github.com/ncuillery/angular-breadcrumb/commit/1eef24fbe862a1e3308181c38f50755843cf4426), closes [#37](http://github.com/ncuillery/angular-breadcrumb/issues/37)) + + +#### Breaking Changes + +* state-level options has been moved under the custom key +`ncyBreadcrumb` in state's configuration. + +To migrate the code follow the example below: +``` +// Before +$stateProvider.state('A', { + url: '/a', + data: { + ncyBreadcrumbLabel: 'State A' + } +}); +``` + +``` +// After +$stateProvider.state('A', { + url: '/a', + ncyBreadcrumb: { + label: 'State A' + } +}); +``` +See [API reference](https://github.com/ncuillery/angular-breadcrumb/wiki/API-Reference) for more informations. + ([1ea436d3](http://github.com/ncuillery/angular-breadcrumb/commit/1ea436d3f6d5470b7ae3e71e71259dbd2422bc00)) + + + +### 0.2.3 (2014-07-26) + + +#### Bug Fixes + +* **$breadcrumb:** use `$stateParams` in case of unhierarchical states ([1c3c05e0](http://github.com/ncuillery/angular-breadcrumb/commit/1c3c05e0acac191fe2e76db2ef18da339caefaaa), closes [#29](http://github.com/ncuillery/angular-breadcrumb/issues/29)) + + + +### 0.2.2 (2014-06-23) + + +#### Bug Fixes + +* catch the `$viewContentLoaded` earlier ([bb47dd54](http://github.com/ncuillery/angular-breadcrumb/commit/bb47dd54deb5efc579ccb9b1575e686803dee1c5), closes [#14](http://github.com/ncuillery/angular-breadcrumb/issues/14)) +* **sample:** + * make the CRU(D) about rooms working ([3ca89ec7](http://github.com/ncuillery/angular-breadcrumb/commit/3ca89ec771fd20dc4ab2d733612bdcfb96ced703)) + * prevent direct URL access to a day disabled in the datepicker ([95236916](http://github.com/ncuillery/angular-breadcrumb/commit/95236916e00b19464a3dfe3584ef1b18da9ffb25), closes [#17](http://github.com/ncuillery/angular-breadcrumb/issues/17)) + * use the same variable in the datepicker and from url params for state `booking.day` ([646f7060](http://github.com/ncuillery/angular-breadcrumb/commit/646f70607e494f0e5e3c2483ed69f689684b2742), closes [#16](http://github.com/ncuillery/angular-breadcrumb/issues/16)) + + +#### Features + +* **ncyBreadcrumb:** watch every expression founded in labels ([1363515e](http://github.com/ncuillery/angular-breadcrumb/commit/1363515e20977ce2f39a1f5e5e1d701f0d7af296), closes [#20](http://github.com/ncuillery/angular-breadcrumb/issues/20)) + + + +### 0.2.1 (2014-05-16) + + +#### Bug Fixes + +* **$breadcrumb:** check if a state has a parent when looking for an inheritated property ([77e668b5](http://github.com/ncuillery/angular-breadcrumb/commit/77e668b5eb759570a64c2a885e81580953af3201), closes [#11](http://github.com/ncuillery/angular-breadcrumb/issues/11)) + + + +### 0.2.0 (2014-05-08) + + +#### Bug Fixes + +* **$breadcrumb:** remove abstract states from breadcrumb ([8a06c5ab](http://github.com/ncuillery/angular-breadcrumb/commit/8a06c5abce749027d48f7309d1aabea1e447dfd5), closes [#8](http://github.com/ncuillery/angular-breadcrumb/issues/8)) +* **ncyBreadcrumb:** display the correct breadcrumb in case of direct access ([e1f455ba](http://github.com/ncuillery/angular-breadcrumb/commit/e1f455ba4def97d3fc76b53772867b5f9daf4232), closes [#10](http://github.com/ncuillery/angular-breadcrumb/issues/10)) + + +#### Features + +* **$breadcrumb:** + * add a configuration property for skipping a state in the breadcrumb ([dd255d90](http://github.com/ncuillery/angular-breadcrumb/commit/dd255d906c4231f44b48f066d4db197a9c6b9e27), closes [#9](http://github.com/ncuillery/angular-breadcrumb/issues/9)) + * allow chain of states customization ([028e493a](http://github.com/ncuillery/angular-breadcrumb/commit/028e493a1ebcae5ae60b8a9d42b949262000d7df), closes [#7](http://github.com/ncuillery/angular-breadcrumb/issues/7)) +* **ncyBreadcrumb:** add 'Element' declaration style '' ([b51441ea](http://github.com/ncuillery/angular-breadcrumb/commit/b51441eafb1659b782fea1f8668c7f455e1d6b4d)) + diff --git a/awx/ui/client/lib/angular-breadcrumb/CONTRIBUTING.md b/awx/ui/client/lib/angular-breadcrumb/CONTRIBUTING.md new file mode 100644 index 0000000000..720c4f142a --- /dev/null +++ b/awx/ui/client/lib/angular-breadcrumb/CONTRIBUTING.md @@ -0,0 +1,52 @@ +# Contributing to angular-breadcrumb + +I am very glad to see this project living with PR from contributors who trust in it. Here is some guidelines to keep the contributions useful and efficient. + +## Development hints + +### Installation +- Checkout the repository +- Run `npm install` +- Run `bower install` + +### Test running +This module uses the classic AngularJS stack with: + +- Karma (test runner) +- Jasmine (assertion framework) +- angular-mocks (AngularJS module for testing) + +Run the test with the grunt task `grunt test`. It runs the tests with different versions of AngularJS. + +### Test developing +Tests are build around modules with a specific `$stateProvider` configuration: + +- [Basic configuration](https://github.com/ncuillery/angular-breadcrumb/blob/master/test/mock/test-modules.js#L6): Basic definitions (no template, no controller) +- [Interpolation configuration](https://github.com/ncuillery/angular-breadcrumb/blob/master/test/mock/test-modules.js#L21): States with bindings in `ncyBreadcrumbLabel` +- [HTML configuration](https://github.com/ncuillery/angular-breadcrumb/blob/master/test/mock/test-modules.js#L36): States with HTML in `ncyBreadcrumbLabel` +- [Sample configuration](https://github.com/ncuillery/angular-breadcrumb/blob/master/test/mock/test-modules.js#L41): Bridge towards the sample app configuration for using in tests +- [UI-router's configuration](https://github.com/ncuillery/angular-breadcrumb/blob/master/test/mock/test-ui-router-sample.js#L9): Clone of the UI-router sample app (complemented with breadcrumb configuration) + +Theses modules are loaded by Karma and they are available in test specifications. + +Specifications are generally related to the directive `ncyBreadcrumb` or the service `$breadcrumb`. + +### Sample +If you are not familiar with JS testing. You can run the [sample](http://ncuillery.github.io/angular-breadcrumb/#/sample) locally for testing purposes by using `grunt sample`. Sources are live-reloaded after each changes. + +## Submitting a Pull Request +- Fork the [repository](https://github.com/ncuillery/angular-breadcrumb/) +- Make your changes in a new git branch following the coding rules below. +- Run the grunt default task (by typing `grunt` or `grunt default`): it will run the tests and build the module in `dist` directory) +- Commit the changes (including the `dist` directory) by using the commit conventions explained below. +- Push and make the PR + + +## Coding rules +- When making changes on the source file, please check that your changes are covered by the tests. If not, create a new test case. + + +## Commit conventions +angular-breadcrumb uses the same strict conventions as AngularJS and UI-router. These conventions are explained [here](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#-git-commit-guidelines). + +It is very important to fit these conventions especially for types `fix` and `feature` which are used by the CHANGELOG.md generation (it uses the [grunt-conventional-changelog](https://github.com/btford/grunt-conventional-changelog)). diff --git a/awx/ui/client/lib/angular-breadcrumb/Gruntfile.js b/awx/ui/client/lib/angular-breadcrumb/Gruntfile.js new file mode 100644 index 0000000000..744af4d211 --- /dev/null +++ b/awx/ui/client/lib/angular-breadcrumb/Gruntfile.js @@ -0,0 +1,258 @@ +'use strict'; + +var LIVERELOAD_PORT = 35729; +var lrSnippet = require('connect-livereload')({ port: LIVERELOAD_PORT }); +var mountFolder = function (connect, dir) { + return connect.static(require('path').resolve(dir)); +}; + +module.exports = function (grunt) { + + // Project configuration. + grunt.initConfig({ + // Metadata. + pkg: grunt.file.readJSON('package.json'), + headerDev: '/*! <%= pkg.name %> - v<%= pkg.version %>-dev-<%= grunt.template.today("yyyy-mm-dd") %>\n', + headerRelease: '/*! <%= pkg.name %> - v<%= pkg.version %>\n', + banner: '<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' + + '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' + + ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n', + // Task configuration. + concat: { + dev: { + options: { + banner: '<%= headerDev %><%= banner %>\n(function (window, angular, undefined) {\n', + footer: '})(window, window.angular);\n', + stripBanners: true + }, + src: ['src/<%= pkg.name %>.js'], + dest: 'dist/<%= pkg.name %>.js' + }, + release: { + options: { + banner: '<%= headerRelease %><%= banner %>\n(function (window, angular, undefined) {\n', + footer: '})(window, window.angular);\n', + stripBanners: true + }, + src: ['src/<%= pkg.name %>.js'], + dest: 'release/<%= pkg.name %>.js' + } + }, + uglify: { + dev: { + options: { + banner: '<%= headerDev %><%= banner %>' + }, + src: '<%= concat.dev.dest %>', + dest: 'dist/<%= pkg.name %>.min.js' + }, + release: { + options: { + banner: '<%= headerRelease %><%= banner %>' + }, + src: '<%= concat.release.dest %>', + dest: 'release/<%= pkg.name %>.min.js' + } + }, + karma: { + unit: { + configFile: 'karma.conf.js' + } + }, + jshint: { + options: { + jshintrc: '.jshintrc' + }, + gruntfile: { + src: 'Gruntfile.js' + }, + sources: { + options: { + jshintrc: 'src/.jshintrc' + }, + src: ['src/**/*.js'] + }, + test: { + src: ['test/**/*.js'] + } + }, + watch: { + gruntfile: { + files: '<%= jshint.gruntfile.src %>', + tasks: ['jshint:gruntfile'] + }, + sources: { + files: '<%= jshint.sources.src %>', + tasks: ['jshint:sources', 'karma'] + }, + test: { + files: '<%= jshint.test.src %>', + tasks: ['jshint:test', 'karma'] + }, + sample: { + options: { + livereload: LIVERELOAD_PORT + }, + tasks: 'copy:breadcrumb', + files: [ + 'sample/*.{css,js,html}', + 'sample/controllers/*.{css,js,html}', + 'sample/views/*.{css,js,html}', + 'src/*.js' + ] + } + }, + copy: { + breadcrumb: { + files: [ + { + flatten: true, + expand: true, + src: [ + 'src/angular-breadcrumb.js' + ], + dest: 'sample/asset/' + } + ] + }, + asset: { + files: [ + { + flatten: true, + expand: true, + src: [ + 'dist/angular-breadcrumb.js', + 'bower_components/angular/angular.js', + 'bower_components/angular-ui-router/release/angular-ui-router.js', + 'bower_components/angular-ui-bootstrap-bower/ui-bootstrap-tpls.js', + 'bower_components/bootstrap/docs/assets/css/bootstrap.css', + 'bower_components/underscore/underscore.js' + ], + dest: 'sample/asset/' + } + ] + }, + img: { + files: [ + { + flatten: true, + expand: true, + src: [ + 'bower_components/bootstrap.css/img/glyphicons-halflings.png' + ], + dest: 'sample/img/' + } + ] + } + }, + connect: { + options: { + port: 9000, + hostname: 'localhost' + }, + livereload: { + options: { + middleware: function (connect) { + return [ + lrSnippet, + mountFolder(connect, 'sample') + ]; + } + } + } + }, + open: { + server: { + url: 'http://localhost:<%= connect.options.port %>/index.html' + } + }, + bump: { + options: { + files: ['package.json', 'bower.json'], + updateConfigs: ['pkg'] + } + }, + clean: { + release: ["sample/*.zip"], + test: ["testDependencies/*"] + }, + compress: { + release: { + options: { + archive: 'sample/<%= pkg.name %>-<%= pkg.version %>.zip' + }, + files: [ + {expand: true, cwd: 'release/', src: ['*.js']} + ] + } + }, + replace: { + release: { + src: ['sample/views/home.html'], + overwrite: true, + replacements: [{ + from: /angular-breadcrumb-[0-9]+\.[0-9]+\.[0-9]+\.zip/g, + to: "angular-breadcrumb-<%= pkg.version %>.zip" + }, + { + from: /\([0-9]+\.[0-9]+\.[0-9]+\)/g, + to: "(<%= pkg.version %>)" + }] + } + }, + shell: { + testMinimal: { + command: 'bower install angular#=1.0.8 angular-mocks#=1.0.8 angular-sanitize#=1.0.8 angular-ui-router#=0.2.0 --config.directory=. --config.cwd=testDependencies' + }, + test1dot2: { + command: 'bower install angular#=1.2.18 angular-mocks#=1.2.18 angular-sanitize#=1.2.18 angular-ui-router#=0.2.15 --config.directory=. --config.cwd=testDependencies' + }, + testLatest: { + command: 'bower install angular angular-mocks angular-sanitize angular-ui-router --config.directory=. --config.cwd=testDependencies' + } + } + + }); + + // These plugins provide necessary tasks. + grunt.loadNpmTasks('grunt-bump'); + grunt.loadNpmTasks('grunt-contrib-clean'); + grunt.loadNpmTasks('grunt-contrib-compress'); + grunt.loadNpmTasks('grunt-contrib-concat'); + grunt.loadNpmTasks('grunt-contrib-uglify'); + grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-contrib-watch'); + grunt.loadNpmTasks('grunt-contrib-copy'); + grunt.loadNpmTasks('grunt-contrib-connect'); + grunt.loadNpmTasks('grunt-conventional-changelog'); + grunt.loadNpmTasks('grunt-karma'); + grunt.loadNpmTasks('grunt-open'); + grunt.loadNpmTasks('grunt-shell'); + grunt.loadNpmTasks('grunt-text-replace'); + + grunt.registerTask('test', ['jshint', 'testMin', 'test1dot2', 'testLatest']); + grunt.registerTask('testMin', ['clean:test', 'shell:testMinimal', 'karma']); + grunt.registerTask('test1dot2', ['clean:test', 'shell:test1dot2', 'karma']); + grunt.registerTask('testLatest', ['clean:test', 'shell:testLatest', 'karma']); + + grunt.registerTask('default', ['test', 'concat:dev', 'uglify:dev']); + + grunt.registerTask('sample', ['concat:dev', 'copy:asset', 'copy:img', 'connect:livereload', 'open', 'watch']); + + grunt.registerTask('release-prepare', 'Update all files for a release', function(target) { + if(!target) { + target = 'patch'; + } + grunt.task.run( + 'bump-only:' + target, // Version update + 'test', // Tests + 'concat:release', // Concat with release banner + 'uglify:release', // Minify with release banner + 'changelog', // Changelog update + 'clean:release', // Delete old version download file + 'compress:release', // New version download file + 'replace:release' // Update version in download button (link & label) + ); + }); + +}; diff --git a/awx/ui/client/lib/angular-breadcrumb/LICENSE b/awx/ui/client/lib/angular-breadcrumb/LICENSE new file mode 100644 index 0000000000..f0774fcf13 --- /dev/null +++ b/awx/ui/client/lib/angular-breadcrumb/LICENSE @@ -0,0 +1,24 @@ +The MIT License + +Copyright (c) 2013 Nicolas Cuillery + +Permission is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. diff --git a/awx/ui/client/lib/angular-breadcrumb/bower.json b/awx/ui/client/lib/angular-breadcrumb/bower.json new file mode 100644 index 0000000000..3a0a2f944c --- /dev/null +++ b/awx/ui/client/lib/angular-breadcrumb/bower.json @@ -0,0 +1,33 @@ +{ + "name": "angular-breadcrumb", + "description": "AngularJS module that generates a breadcrumb from ui-router's states", + "version": "0.4.1", + "main": "release/angular-breadcrumb.js", + "ignore": [ + "sample", + "src", + "test", + ".bowerrc", + ".coveralls.yml", + ".gitignore", + ".jshintrc", + ".travis.yml", + "gruntfile.js", + "bower.json", + "karma.conf.js", + "libpeerconnection.log", + "package.json", + "README.md" + ], + "dependencies": { + "angular": ">=1.0.8", + "angular-ui-router": ">=0.2.0" + }, + "devDependencies": { + "bootstrap": "~2.3.2", + "angular-ui-bootstrap-bower": "~0.8.0", + "underscore": "~1.5.1", + "angular-mocks": ">=1.0.8", + "angular-sanitize": ">=1.0.8" + } +} diff --git a/awx/ui/client/lib/angular-breadcrumb/dist/angular-breadcrumb.js b/awx/ui/client/lib/angular-breadcrumb/dist/angular-breadcrumb.js new file mode 100644 index 0000000000..e20ca158ec --- /dev/null +++ b/awx/ui/client/lib/angular-breadcrumb/dist/angular-breadcrumb.js @@ -0,0 +1,369 @@ +/*! angular-breadcrumb - v0.4.0-dev-2015-08-07 +* http://ncuillery.github.io/angular-breadcrumb +* Copyright (c) 2015 Nicolas Cuillery; Licensed MIT */ + +(function (window, angular, undefined) { +'use strict'; + +function isAOlderThanB(scopeA, scopeB) { + if(angular.equals(scopeA.length, scopeB.length)) { + return scopeA > scopeB; + } else { + return scopeA.length > scopeB.length; + } +} + +function parseStateRef(ref) { + var parsed = ref.replace(/\n/g, " ").match(/^([^(]+?)\s*(\((.*)\))?$/); + if (!parsed || parsed.length !== 4) { throw new Error("Invalid state ref '" + ref + "'"); } + return { state: parsed[1], paramExpr: parsed[3] || null }; +} + +function $Breadcrumb() { + + var $$options = { + prefixStateName: null, + template: 'bootstrap3', + templateUrl: null, + includeAbstract : false + }; + + this.setOptions = function(options) { + angular.extend($$options, options); + }; + + this.$get = ['$state', '$stateParams', '$rootScope', function($state, $stateParams, $rootScope) { + + var $lastViewScope = $rootScope; + + // Early catch of $viewContentLoaded event + $rootScope.$on('$viewContentLoaded', function (event) { + // With nested views, the event occur several times, in "wrong" order + if(!event.targetScope.ncyBreadcrumbIgnore && + isAOlderThanB(event.targetScope.$id, $lastViewScope.$id)) { + $lastViewScope = event.targetScope; + } + }); + + // Get the parent state + var $$parentState = function(state) { + // Check if state has explicit parent OR we try guess parent from its name + var parent = state.parent || (/^(.+)\.[^.]+$/.exec(state.name) || [])[1]; + var isObjectParent = typeof parent === "object"; + // if parent is a object reference, then extract the name + return isObjectParent ? parent.name : parent; + }; + + // Add the state in the chain if not already in and if not abstract + var $$addStateInChain = function(chain, stateRef) { + var conf, + parentParams, + ref = parseStateRef(stateRef), + force = false, + skip = false; + + for(var i=0, l=chain.length; i' + + '
  • ' + + '{{step.ncyBreadcrumbLabel}}' + + '{{step.ncyBreadcrumbLabel}}' + + '/' + + '
  • ' + + '', + bootstrap3: '' + }; + + return { + restrict: 'AE', + replace: true, + scope: {}, + template: $breadcrumb.getTemplate($$templates), + templateUrl: $breadcrumb.getTemplateUrl(), + link: { + post: function postLink(scope) { + var labelWatchers = []; + + var renderBreadcrumb = function() { + deregisterWatchers(labelWatchers); + labelWatchers = []; + + var viewScope = $breadcrumb.$getLastViewScope(); + scope.steps = $breadcrumb.getStatesChain(); + angular.forEach(scope.steps, function (step) { + if (step.ncyBreadcrumb && step.ncyBreadcrumb.label) { + var parseLabel = $interpolate(step.ncyBreadcrumb.label); + step.ncyBreadcrumbLabel = parseLabel(viewScope); + // Watcher for further viewScope updates + registerWatchers(labelWatchers, parseLabel, viewScope, step); + } else { + step.ncyBreadcrumbLabel = step.name; + } + }); + }; + + $rootScope.$on('$viewContentLoaded', function (event) { + if(!event.targetScope.ncyBreadcrumbIgnore) { + renderBreadcrumb(); + } + }); + + // View(s) may be already loaded while the directive's linking + renderBreadcrumb(); + } + } + }; +} +BreadcrumbDirective.$inject = ['$interpolate', '$breadcrumb', '$rootScope']; + +function BreadcrumbLastDirective($interpolate, $breadcrumb, $rootScope) { + + return { + restrict: 'A', + scope: {}, + template: '{{ncyBreadcrumbLabel}}', + compile: function(cElement, cAttrs) { + + // Override the default template if ncyBreadcrumbLast has a value + var template = cElement.attr(cAttrs.$attr.ncyBreadcrumbLast); + if(template) { + cElement.html(template); + } + + return { + post: function postLink(scope) { + var labelWatchers = []; + + var renderLabel = function() { + deregisterWatchers(labelWatchers); + labelWatchers = []; + + var viewScope = $breadcrumb.$getLastViewScope(); + var lastStep = $breadcrumb.getLastStep(); + if(lastStep) { + scope.ncyBreadcrumbLink = lastStep.ncyBreadcrumbLink; + if (lastStep.ncyBreadcrumb && lastStep.ncyBreadcrumb.label) { + var parseLabel = $interpolate(lastStep.ncyBreadcrumb.label); + scope.ncyBreadcrumbLabel = parseLabel(viewScope); + // Watcher for further viewScope updates + // Tricky last arg: the last step is the entire scope of the directive ! + registerWatchers(labelWatchers, parseLabel, viewScope, scope); + } else { + scope.ncyBreadcrumbLabel = lastStep.name; + } + } + }; + + $rootScope.$on('$viewContentLoaded', function (event) { + if(!event.targetScope.ncyBreadcrumbIgnore) { + renderLabel(); + } + }); + + // View(s) may be already loaded while the directive's linking + renderLabel(); + } + }; + + } + }; +} +BreadcrumbLastDirective.$inject = ['$interpolate', '$breadcrumb', '$rootScope']; + +function BreadcrumbTextDirective($interpolate, $breadcrumb, $rootScope) { + + return { + restrict: 'A', + scope: {}, + template: '{{ncyBreadcrumbChain}}', + + compile: function(cElement, cAttrs) { + // Override the default template if ncyBreadcrumbText has a value + var template = cElement.attr(cAttrs.$attr.ncyBreadcrumbText); + if(template) { + cElement.html(template); + } + + var separator = cElement.attr(cAttrs.$attr.ncyBreadcrumbTextSeparator) || ' / '; + + return { + post: function postLink(scope) { + var labelWatchers = []; + + var registerWatchersText = function(labelWatcherArray, interpolationFunction, viewScope) { + angular.forEach(getExpression(interpolationFunction), function(expression) { + var watcher = viewScope.$watch(expression, function(newValue, oldValue) { + if (newValue !== oldValue) { + renderLabel(); + } + }); + labelWatcherArray.push(watcher); + }); + }; + + var renderLabel = function() { + deregisterWatchers(labelWatchers); + labelWatchers = []; + + var viewScope = $breadcrumb.$getLastViewScope(); + var steps = $breadcrumb.getStatesChain(); + var combinedLabels = []; + angular.forEach(steps, function (step) { + if (step.ncyBreadcrumb && step.ncyBreadcrumb.label) { + var parseLabel = $interpolate(step.ncyBreadcrumb.label); + combinedLabels.push(parseLabel(viewScope)); + // Watcher for further viewScope updates + registerWatchersText(labelWatchers, parseLabel, viewScope); + } else { + combinedLabels.push(step.name); + } + }); + + scope.ncyBreadcrumbChain = combinedLabels.join(separator); + }; + + $rootScope.$on('$viewContentLoaded', function (event) { + if(!event.targetScope.ncyBreadcrumbIgnore) { + renderLabel(); + } + }); + + // View(s) may be already loaded while the directive's linking + renderLabel(); + } + }; + + } + }; +} +BreadcrumbTextDirective.$inject = ['$interpolate', '$breadcrumb', '$rootScope']; + +angular.module('ncy-angular-breadcrumb', ['ui.router.state']) + .provider('$breadcrumb', $Breadcrumb) + .directive('ncyBreadcrumb', BreadcrumbDirective) + .directive('ncyBreadcrumbLast', BreadcrumbLastDirective) + .directive('ncyBreadcrumbText', BreadcrumbTextDirective); +})(window, window.angular); diff --git a/awx/ui/client/lib/angular-breadcrumb/dist/angular-breadcrumb.min.js b/awx/ui/client/lib/angular-breadcrumb/dist/angular-breadcrumb.min.js new file mode 100644 index 0000000000..1da045d879 --- /dev/null +++ b/awx/ui/client/lib/angular-breadcrumb/dist/angular-breadcrumb.min.js @@ -0,0 +1,4 @@ +/*! angular-breadcrumb - v0.4.0-dev-2015-08-07 +* http://ncuillery.github.io/angular-breadcrumb +* Copyright (c) 2015 Nicolas Cuillery; Licensed MIT */ +!function(a,b,c){"use strict";function d(a,c){return b.equals(a.length,c.length)?a>c:a.length>c.length}function e(a){var b=a.replace(/\n/g," ").match(/^([^(]+?)\s*(\((.*)\))?$/);if(!b||4!==b.length)throw new Error("Invalid state ref '"+a+"'");return{state:b[1],paramExpr:b[3]||null}}function f(){var a={prefixStateName:null,template:"bootstrap3",templateUrl:null,includeAbstract:!1};this.setOptions=function(c){b.extend(a,c)},this.$get=["$state","$stateParams","$rootScope",function(b,f,g){var h=g;g.$on("$viewContentLoaded",function(a){!a.targetScope.ncyBreadcrumbIgnore&&d(a.targetScope.$id,h.$id)&&(h=a.targetScope)});var i=function(a){var b=a.parent||(/^(.+)\.[^.]+$/.exec(a.name)||[])[1],c="object"==typeof b;return c?b.name:b},j=function(c,d){for(var g,i,j=e(d),k=!1,l=!1,m=0,n=c.length;n>m;m+=1)if(c[m].name===j.state)return;g=b.get(j.state),g.ncyBreadcrumb&&(g.ncyBreadcrumb.force&&(k=!0),g.ncyBreadcrumb.skip&&(l=!0)),g["abstract"]&&!a.includeAbstract&&!k||l||(j.paramExpr&&(i=h.$eval(j.paramExpr)),g.ncyBreadcrumbLink=b.href(j.state,i||f||{}),c.unshift(g))},k=function(a){var c=e(a),d=b.get(c.state);if(d.ncyBreadcrumb&&d.ncyBreadcrumb.parent){var f="function"==typeof d.ncyBreadcrumb.parent,g=f?d.ncyBreadcrumb.parent(h):d.ncyBreadcrumb.parent;if(g)return g}return i(d)};return{getTemplate:function(b){return a.templateUrl?null:b[a.template]?b[a.template]:a.template},getTemplateUrl:function(){return a.templateUrl},getStatesChain:function(c){for(var d=[],e=b.$current.self.name;e;e=k(e))if(j(d,e),c&&d.length)return d;return a.prefixStateName&&j(d,a.prefixStateName),d},getLastStep:function(){var a=this.getStatesChain(!0);return a.length?a[0]:c},$getLastViewScope:function(){return h}}}]}function g(a,c,d){var e={bootstrap2:'',bootstrap3:''};return{restrict:"AE",replace:!0,scope:{},template:c.getTemplate(e),templateUrl:c.getTemplateUrl(),link:{post:function(e){var f=[],g=function(){l(f),f=[];var d=c.$getLastViewScope();e.steps=c.getStatesChain(),b.forEach(e.steps,function(b){if(b.ncyBreadcrumb&&b.ncyBreadcrumb.label){var c=a(b.ncyBreadcrumb.label);b.ncyBreadcrumbLabel=c(d),k(f,c,d,b)}else b.ncyBreadcrumbLabel=b.name})};d.$on("$viewContentLoaded",function(a){a.targetScope.ncyBreadcrumbIgnore||g()}),g()}}}}function h(a,b,c){return{restrict:"A",scope:{},template:"{{ncyBreadcrumbLabel}}",compile:function(d,e){var f=d.attr(e.$attr.ncyBreadcrumbLast);return f&&d.html(f),{post:function(d){var e=[],f=function(){l(e),e=[];var c=b.$getLastViewScope(),f=b.getLastStep();if(f)if(d.ncyBreadcrumbLink=f.ncyBreadcrumbLink,f.ncyBreadcrumb&&f.ncyBreadcrumb.label){var g=a(f.ncyBreadcrumb.label);d.ncyBreadcrumbLabel=g(c),k(e,g,c,d)}else d.ncyBreadcrumbLabel=f.name};c.$on("$viewContentLoaded",function(a){a.targetScope.ncyBreadcrumbIgnore||f()}),f()}}}}}function i(a,c,d){return{restrict:"A",scope:{},template:"{{ncyBreadcrumbChain}}",compile:function(e,f){var g=e.attr(f.$attr.ncyBreadcrumbText);g&&e.html(g);var h=e.attr(f.$attr.ncyBreadcrumbTextSeparator)||" / ";return{post:function(e){var f=[],g=function(a,c,d){b.forEach(j(c),function(b){var c=d.$watch(b,function(a,b){a!==b&&i()});a.push(c)})},i=function(){l(f),f=[];var d=c.$getLastViewScope(),i=c.getStatesChain(),j=[];b.forEach(i,function(b){if(b.ncyBreadcrumb&&b.ncyBreadcrumb.label){var c=a(b.ncyBreadcrumb.label);j.push(c(d)),g(f,c,d)}else j.push(b.name)}),e.ncyBreadcrumbChain=j.join(h)};d.$on("$viewContentLoaded",function(a){a.targetScope.ncyBreadcrumbIgnore||i()}),i()}}}}}var j=function(a){if(a.expressions)return a.expressions;var c=[];return b.forEach(a.parts,function(a){b.isFunction(a)&&c.push(a.exp)}),c},k=function(a,c,d,e){b.forEach(j(c),function(b){var f=d.$watch(b,function(){e.ncyBreadcrumbLabel=c(d)});a.push(f)})},l=function(a){b.forEach(a,function(a){a()})};g.$inject=["$interpolate","$breadcrumb","$rootScope"],h.$inject=["$interpolate","$breadcrumb","$rootScope"],i.$inject=["$interpolate","$breadcrumb","$rootScope"],b.module("ncy-angular-breadcrumb",["ui.router.state"]).provider("$breadcrumb",f).directive("ncyBreadcrumb",g).directive("ncyBreadcrumbLast",h).directive("ncyBreadcrumbText",i)}(window,window.angular); \ No newline at end of file diff --git a/awx/ui/client/lib/angular-breadcrumb/release/angular-breadcrumb.js b/awx/ui/client/lib/angular-breadcrumb/release/angular-breadcrumb.js new file mode 100644 index 0000000000..ba6e5dcd39 --- /dev/null +++ b/awx/ui/client/lib/angular-breadcrumb/release/angular-breadcrumb.js @@ -0,0 +1,369 @@ +/*! angular-breadcrumb - v0.4.1 +* http://ncuillery.github.io/angular-breadcrumb +* Copyright (c) 2015 Nicolas Cuillery; Licensed MIT */ + +(function (window, angular, undefined) { +'use strict'; + +function isAOlderThanB(scopeA, scopeB) { + if(angular.equals(scopeA.length, scopeB.length)) { + return scopeA > scopeB; + } else { + return scopeA.length > scopeB.length; + } +} + +function parseStateRef(ref) { + var parsed = ref.replace(/\n/g, " ").match(/^([^(]+?)\s*(\((.*)\))?$/); + if (!parsed || parsed.length !== 4) { throw new Error("Invalid state ref '" + ref + "'"); } + return { state: parsed[1], paramExpr: parsed[3] || null }; +} + +function $Breadcrumb() { + + var $$options = { + prefixStateName: null, + template: 'bootstrap3', + templateUrl: null, + includeAbstract : false + }; + + this.setOptions = function(options) { + angular.extend($$options, options); + }; + + this.$get = ['$state', '$stateParams', '$rootScope', function($state, $stateParams, $rootScope) { + + var $lastViewScope = $rootScope; + + // Early catch of $viewContentLoaded event + $rootScope.$on('$viewContentLoaded', function (event) { + // With nested views, the event occur several times, in "wrong" order + if(!event.targetScope.ncyBreadcrumbIgnore && + isAOlderThanB(event.targetScope.$id, $lastViewScope.$id)) { + $lastViewScope = event.targetScope; + } + }); + + // Get the parent state + var $$parentState = function(state) { + // Check if state has explicit parent OR we try guess parent from its name + var parent = state.parent || (/^(.+)\.[^.]+$/.exec(state.name) || [])[1]; + var isObjectParent = typeof parent === "object"; + // if parent is a object reference, then extract the name + return isObjectParent ? parent.name : parent; + }; + + // Add the state in the chain if not already in and if not abstract + var $$addStateInChain = function(chain, stateRef) { + var conf, + parentParams, + ref = parseStateRef(stateRef), + force = false, + skip = false; + + for(var i=0, l=chain.length; i' + + '
  • ' + + '{{step.ncyBreadcrumbLabel}}' + + '{{step.ncyBreadcrumbLabel}}' + + '/' + + '
  • ' + + '', + bootstrap3: '' + }; + + return { + restrict: 'AE', + replace: true, + scope: {}, + template: $breadcrumb.getTemplate($$templates), + templateUrl: $breadcrumb.getTemplateUrl(), + link: { + post: function postLink(scope) { + var labelWatchers = []; + + var renderBreadcrumb = function() { + deregisterWatchers(labelWatchers); + labelWatchers = []; + + var viewScope = $breadcrumb.$getLastViewScope(); + scope.steps = $breadcrumb.getStatesChain(); + angular.forEach(scope.steps, function (step) { + if (step.ncyBreadcrumb && step.ncyBreadcrumb.label) { + var parseLabel = $interpolate(step.ncyBreadcrumb.label); + step.ncyBreadcrumbLabel = parseLabel(viewScope); + // Watcher for further viewScope updates + registerWatchers(labelWatchers, parseLabel, viewScope, step); + } else { + step.ncyBreadcrumbLabel = step.name; + } + }); + }; + + $rootScope.$on('$viewContentLoaded', function (event) { + if(!event.targetScope.ncyBreadcrumbIgnore) { + renderBreadcrumb(); + } + }); + + // View(s) may be already loaded while the directive's linking + renderBreadcrumb(); + } + } + }; +} +BreadcrumbDirective.$inject = ['$interpolate', '$breadcrumb', '$rootScope']; + +function BreadcrumbLastDirective($interpolate, $breadcrumb, $rootScope) { + + return { + restrict: 'A', + scope: {}, + template: '{{ncyBreadcrumbLabel}}', + compile: function(cElement, cAttrs) { + + // Override the default template if ncyBreadcrumbLast has a value + var template = cElement.attr(cAttrs.$attr.ncyBreadcrumbLast); + if(template) { + cElement.html(template); + } + + return { + post: function postLink(scope) { + var labelWatchers = []; + + var renderLabel = function() { + deregisterWatchers(labelWatchers); + labelWatchers = []; + + var viewScope = $breadcrumb.$getLastViewScope(); + var lastStep = $breadcrumb.getLastStep(); + if(lastStep) { + scope.ncyBreadcrumbLink = lastStep.ncyBreadcrumbLink; + if (lastStep.ncyBreadcrumb && lastStep.ncyBreadcrumb.label) { + var parseLabel = $interpolate(lastStep.ncyBreadcrumb.label); + scope.ncyBreadcrumbLabel = parseLabel(viewScope); + // Watcher for further viewScope updates + // Tricky last arg: the last step is the entire scope of the directive ! + registerWatchers(labelWatchers, parseLabel, viewScope, scope); + } else { + scope.ncyBreadcrumbLabel = lastStep.name; + } + } + }; + + $rootScope.$on('$viewContentLoaded', function (event) { + if(!event.targetScope.ncyBreadcrumbIgnore) { + renderLabel(); + } + }); + + // View(s) may be already loaded while the directive's linking + renderLabel(); + } + }; + + } + }; +} +BreadcrumbLastDirective.$inject = ['$interpolate', '$breadcrumb', '$rootScope']; + +function BreadcrumbTextDirective($interpolate, $breadcrumb, $rootScope) { + + return { + restrict: 'A', + scope: {}, + template: '{{ncyBreadcrumbChain}}', + + compile: function(cElement, cAttrs) { + // Override the default template if ncyBreadcrumbText has a value + var template = cElement.attr(cAttrs.$attr.ncyBreadcrumbText); + if(template) { + cElement.html(template); + } + + var separator = cElement.attr(cAttrs.$attr.ncyBreadcrumbTextSeparator) || ' / '; + + return { + post: function postLink(scope) { + var labelWatchers = []; + + var registerWatchersText = function(labelWatcherArray, interpolationFunction, viewScope) { + angular.forEach(getExpression(interpolationFunction), function(expression) { + var watcher = viewScope.$watch(expression, function(newValue, oldValue) { + if (newValue !== oldValue) { + renderLabel(); + } + }); + labelWatcherArray.push(watcher); + }); + }; + + var renderLabel = function() { + deregisterWatchers(labelWatchers); + labelWatchers = []; + + var viewScope = $breadcrumb.$getLastViewScope(); + var steps = $breadcrumb.getStatesChain(); + var combinedLabels = []; + angular.forEach(steps, function (step) { + if (step.ncyBreadcrumb && step.ncyBreadcrumb.label) { + var parseLabel = $interpolate(step.ncyBreadcrumb.label); + combinedLabels.push(parseLabel(viewScope)); + // Watcher for further viewScope updates + registerWatchersText(labelWatchers, parseLabel, viewScope); + } else { + combinedLabels.push(step.name); + } + }); + + scope.ncyBreadcrumbChain = combinedLabels.join(separator); + }; + + $rootScope.$on('$viewContentLoaded', function (event) { + if(!event.targetScope.ncyBreadcrumbIgnore) { + renderLabel(); + } + }); + + // View(s) may be already loaded while the directive's linking + renderLabel(); + } + }; + + } + }; +} +BreadcrumbTextDirective.$inject = ['$interpolate', '$breadcrumb', '$rootScope']; + +angular.module('ncy-angular-breadcrumb', ['ui.router.state']) + .provider('$breadcrumb', $Breadcrumb) + .directive('ncyBreadcrumb', BreadcrumbDirective) + .directive('ncyBreadcrumbLast', BreadcrumbLastDirective) + .directive('ncyBreadcrumbText', BreadcrumbTextDirective); +})(window, window.angular); diff --git a/awx/ui/client/lib/angular-breadcrumb/release/angular-breadcrumb.min.js b/awx/ui/client/lib/angular-breadcrumb/release/angular-breadcrumb.min.js new file mode 100644 index 0000000000..ceb49da17e --- /dev/null +++ b/awx/ui/client/lib/angular-breadcrumb/release/angular-breadcrumb.min.js @@ -0,0 +1,4 @@ +/*! angular-breadcrumb - v0.4.1 +* http://ncuillery.github.io/angular-breadcrumb +* Copyright (c) 2015 Nicolas Cuillery; Licensed MIT */ +!function(a,b,c){"use strict";function d(a,c){return b.equals(a.length,c.length)?a>c:a.length>c.length}function e(a){var b=a.replace(/\n/g," ").match(/^([^(]+?)\s*(\((.*)\))?$/);if(!b||4!==b.length)throw new Error("Invalid state ref '"+a+"'");return{state:b[1],paramExpr:b[3]||null}}function f(){var a={prefixStateName:null,template:"bootstrap3",templateUrl:null,includeAbstract:!1};this.setOptions=function(c){b.extend(a,c)},this.$get=["$state","$stateParams","$rootScope",function(b,f,g){var h=g;g.$on("$viewContentLoaded",function(a){!a.targetScope.ncyBreadcrumbIgnore&&d(a.targetScope.$id,h.$id)&&(h=a.targetScope)});var i=function(a){var b=a.parent||(/^(.+)\.[^.]+$/.exec(a.name)||[])[1],c="object"==typeof b;return c?b.name:b},j=function(c,d){for(var g,i,j=e(d),k=!1,l=!1,m=0,n=c.length;n>m;m+=1)if(c[m].name===j.state)return;g=b.get(j.state),g.ncyBreadcrumb&&(g.ncyBreadcrumb.force&&(k=!0),g.ncyBreadcrumb.skip&&(l=!0)),g["abstract"]&&!a.includeAbstract&&!k||l||(j.paramExpr&&(i=h.$eval(j.paramExpr)),g.ncyBreadcrumbLink=b.href(j.state,i||f||{}),c.unshift(g))},k=function(a){var c=e(a),d=b.get(c.state);if(d.ncyBreadcrumb&&d.ncyBreadcrumb.parent){var f="function"==typeof d.ncyBreadcrumb.parent,g=f?d.ncyBreadcrumb.parent(h):d.ncyBreadcrumb.parent;if(g)return g}return i(d)};return{getTemplate:function(b){return a.templateUrl?null:b[a.template]?b[a.template]:a.template},getTemplateUrl:function(){return a.templateUrl},getStatesChain:function(c){for(var d=[],e=b.$current.self.name;e;e=k(e))if(j(d,e),c&&d.length)return d;return a.prefixStateName&&j(d,a.prefixStateName),d},getLastStep:function(){var a=this.getStatesChain(!0);return a.length?a[0]:c},$getLastViewScope:function(){return h}}}]}function g(a,c,d){var e={bootstrap2:'',bootstrap3:''};return{restrict:"AE",replace:!0,scope:{},template:c.getTemplate(e),templateUrl:c.getTemplateUrl(),link:{post:function(e){var f=[],g=function(){l(f),f=[];var d=c.$getLastViewScope();e.steps=c.getStatesChain(),b.forEach(e.steps,function(b){if(b.ncyBreadcrumb&&b.ncyBreadcrumb.label){var c=a(b.ncyBreadcrumb.label);b.ncyBreadcrumbLabel=c(d),k(f,c,d,b)}else b.ncyBreadcrumbLabel=b.name})};d.$on("$viewContentLoaded",function(a){a.targetScope.ncyBreadcrumbIgnore||g()}),g()}}}}function h(a,b,c){return{restrict:"A",scope:{},template:"{{ncyBreadcrumbLabel}}",compile:function(d,e){var f=d.attr(e.$attr.ncyBreadcrumbLast);return f&&d.html(f),{post:function(d){var e=[],f=function(){l(e),e=[];var c=b.$getLastViewScope(),f=b.getLastStep();if(f)if(d.ncyBreadcrumbLink=f.ncyBreadcrumbLink,f.ncyBreadcrumb&&f.ncyBreadcrumb.label){var g=a(f.ncyBreadcrumb.label);d.ncyBreadcrumbLabel=g(c),k(e,g,c,d)}else d.ncyBreadcrumbLabel=f.name};c.$on("$viewContentLoaded",function(a){a.targetScope.ncyBreadcrumbIgnore||f()}),f()}}}}}function i(a,c,d){return{restrict:"A",scope:{},template:"{{ncyBreadcrumbChain}}",compile:function(e,f){var g=e.attr(f.$attr.ncyBreadcrumbText);g&&e.html(g);var h=e.attr(f.$attr.ncyBreadcrumbTextSeparator)||" / ";return{post:function(e){var f=[],g=function(a,c,d){b.forEach(j(c),function(b){var c=d.$watch(b,function(a,b){a!==b&&i()});a.push(c)})},i=function(){l(f),f=[];var d=c.$getLastViewScope(),i=c.getStatesChain(),j=[];b.forEach(i,function(b){if(b.ncyBreadcrumb&&b.ncyBreadcrumb.label){var c=a(b.ncyBreadcrumb.label);j.push(c(d)),g(f,c,d)}else j.push(b.name)}),e.ncyBreadcrumbChain=j.join(h)};d.$on("$viewContentLoaded",function(a){a.targetScope.ncyBreadcrumbIgnore||i()}),i()}}}}}var j=function(a){if(a.expressions)return a.expressions;var c=[];return b.forEach(a.parts,function(a){b.isFunction(a)&&c.push(a.exp)}),c},k=function(a,c,d,e){b.forEach(j(c),function(b){var f=d.$watch(b,function(){e.ncyBreadcrumbLabel=c(d)});a.push(f)})},l=function(a){b.forEach(a,function(a){a()})};g.$inject=["$interpolate","$breadcrumb","$rootScope"],h.$inject=["$interpolate","$breadcrumb","$rootScope"],i.$inject=["$interpolate","$breadcrumb","$rootScope"],b.module("ncy-angular-breadcrumb",["ui.router.state"]).provider("$breadcrumb",f).directive("ncyBreadcrumb",g).directive("ncyBreadcrumbLast",h).directive("ncyBreadcrumbText",i)}(window,window.angular); \ No newline at end of file diff --git a/awx/ui/client/src/app.js b/awx/ui/client/src/app.js index e3ed9e423c..896a9eb211 100644 --- a/awx/ui/client/src/app.js +++ b/awx/ui/client/src/app.js @@ -186,7 +186,8 @@ var tower = angular.module('Tower', [ 'features', 'longDateFilter', 'pendolytics', - 'ui.router' + 'ui.router', + 'ncy-angular-breadcrumb' ]) .constant('AngularScheduler.partials', urlPrefix + 'lib/angular-scheduler/lib/') @@ -773,15 +774,15 @@ var tower = angular.module('Tower', [ state('dashboard', { url: '/home', templateUrl: urlPrefix + 'partials/home.html', - controller: Home, - resolve: { - graphData: ['$q', 'jobStatusGraphData', 'FeaturesService', function($q, jobStatusGraphData, FeaturesService) { - return $q.all({ - jobStatus: jobStatusGraphData.get("month", "all"), - features: FeaturesService.get() - }); - }] - } + controller: Home + // resolve: { + // graphData: ['$q', 'jobStatusGraphData', 'FeaturesService', function($q, jobStatusGraphData, FeaturesService) { + // return $q.all({ + // jobStatus: jobStatusGraphData.get("month", "all"), + // features: FeaturesService.get() + // }); + // }] + // } }). state('dashboardGroups', {