bastion 3.3.4 → 3.3.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/bastion/bastion.module.js +1 -0
- data/app/assets/javascripts/bastion/components/bst-alert.directive.js +23 -3
- data/app/assets/javascripts/bastion/components/nutupane.factory.js +5 -0
- data/app/assets/javascripts/bastion/components/views/bst-alert.html +1 -1
- data/app/assets/javascripts/bastion/layouts/404.html +14 -0
- data/app/assets/javascripts/bastion/layouts/details-nutupane.html +27 -18
- data/app/assets/javascripts/bastion/layouts/nutupane.html +29 -23
- data/app/assets/javascripts/bastion/routing.module.js +8 -4
- data/app/assets/stylesheets/bastion/nutupane.scss +0 -4
- data/bower.json +1 -1
- data/grunt/karma.js +3 -1
- data/lib/bastion/version.rb +1 -1
- data/package.json +1 -1
- data/test/components/bst-alert.directive.test.js +96 -17
- data/test/components/nutupane.factory.test.js +9 -0
- data/test/routing.module.test.js +5 -6
- data/vendor/assets/javascripts/bastion/angular-ui-router/angular-ui-router.js +2250 -897
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 05ff44d4550c21ed07abe4397f2cb266157a3bb7
|
4
|
+
data.tar.gz: bc8c1e7414eb123f406dc781543933ba2a695c8f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fd455b12ca5b6a5dc8489328af7920e7bdd77b105447d9c87e1898143298ecb096d165f1ff0474c9e899267b51fbf5a6596dde3a2a36094aa0e5239e424def2a
|
7
|
+
data.tar.gz: 385d580c66ec06868fc5538d8acdb7551c8554245abdbe042acc638ccdc8cf692892f15dcc6308541124aa4ec72b06f521be2c9287429a8e3bd213289f725f09
|
@@ -83,6 +83,7 @@ angular.module('Bastion').run(['$rootScope', '$state', '$stateParams', 'gettextC
|
|
83
83
|
$rootScope.$state = $state;
|
84
84
|
$rootScope.$stateParams = $stateParams;
|
85
85
|
$rootScope.transitionTo = $state.transitionTo;
|
86
|
+
$rootScope.$location = $location;
|
86
87
|
|
87
88
|
$rootScope.isState = function (stateName) {
|
88
89
|
return $state.is(stateName);
|
@@ -24,13 +24,33 @@ angular.module('Bastion.components').directive('bstAlert', ['$animate', '$timeou
|
|
24
24
|
close: '&'
|
25
25
|
},
|
26
26
|
link: function (scope, element, attrs) {
|
27
|
+
var fadeOutAnimation;
|
28
|
+
|
29
|
+
scope.fadePrevented = true;
|
27
30
|
scope.closeable = 'close' in attrs;
|
28
31
|
|
29
|
-
|
30
|
-
if (scope.type === 'success') {
|
32
|
+
scope.startFade = function () {
|
31
33
|
$timeout(function () {
|
32
|
-
|
34
|
+
if (!scope.fadePrevented) {
|
35
|
+
fadeOutAnimation = $animate.leave(element.find('.alert'));
|
36
|
+
fadeOutAnimation.then(function () {
|
37
|
+
scope.close();
|
38
|
+
});
|
39
|
+
}
|
33
40
|
}, SUCCESS_FADEOUT);
|
41
|
+
};
|
42
|
+
|
43
|
+
scope.cancelFade = function () {
|
44
|
+
scope.fadePrevented = true;
|
45
|
+
if (fadeOutAnimation) {
|
46
|
+
$animate.cancel(fadeOutAnimation);
|
47
|
+
}
|
48
|
+
};
|
49
|
+
|
50
|
+
// Automatically fade out success alerts
|
51
|
+
if (scope.type === 'success') {
|
52
|
+
scope.fadePrevented = false;
|
53
|
+
scope.startFade();
|
34
54
|
}
|
35
55
|
}
|
36
56
|
};
|
@@ -269,6 +269,11 @@ angular.module('Bastion.components').factory('Nutupane',
|
|
269
269
|
}
|
270
270
|
};
|
271
271
|
|
272
|
+
self.table.clearSearch = function () {
|
273
|
+
self.table.search(null);
|
274
|
+
self.table.searchCompleted = true;
|
275
|
+
};
|
276
|
+
|
272
277
|
// Must be overridden
|
273
278
|
self.table.closeItem = function () {
|
274
279
|
if (!self.masterOnly) {
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<div class="alert" ng-class='"alert-" + (type || "warning")'>
|
1
|
+
<div class="alert" ng-class='"alert-" + (type || "warning")' ng-mouseover="cancelFade()">
|
2
2
|
<button ng-show="closeable" type="button" class="close" aria-hidden="true" ng-click="close()">
|
3
3
|
<span class="pficon pficon-close"></span>
|
4
4
|
</button>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<span page-title>{{ '404 - Page Not Found' | translate }}</span>
|
2
|
+
|
3
|
+
<section class="col-sm-12">
|
4
|
+
<h1 translate>404 - Page Not Found</h1>
|
5
|
+
<p translate>
|
6
|
+
The requested URL <strong>{{ $location.path() }}</strong> was not found.
|
7
|
+
</p>
|
8
|
+
<p translate>
|
9
|
+
You may have mistyped the address or the page may have moved.
|
10
|
+
</p>
|
11
|
+
<p translate>
|
12
|
+
If you are the application owner check the logs for more information.
|
13
|
+
</p>
|
14
|
+
</section>
|
@@ -12,24 +12,33 @@
|
|
12
12
|
<div class="row nutupane-details-bar">
|
13
13
|
<div class="col-sm-4">
|
14
14
|
<div data-block="search">
|
15
|
-
<
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
15
|
+
<form role="form" class="search-pf has-button">
|
16
|
+
<div class="form-group has-clear">
|
17
|
+
<div class="search-pf-input-group">
|
18
|
+
<span data-block="search-filter"></span>
|
19
|
+
|
20
|
+
<input type="text"
|
21
|
+
class="form-control"
|
22
|
+
placeholder="{{ 'Search...' | translate }}"
|
23
|
+
ng-model="detailsTable.searchTerm"
|
24
|
+
bst-on-enter="detailsTable.search(detailsTable.searchTerm)"
|
25
|
+
ng-trim="false"
|
26
|
+
typeahead="item.label for item in detailsTable.autocomplete($viewValue)"
|
27
|
+
typeahead-empty
|
28
|
+
typeahead-template-url="components/views/autocomplete-scoped-search.html"/>
|
29
|
+
|
30
|
+
<button type="button" class="clear" aria-hidden="true" ng-show="detailsTable.searchTerm" ng-click='detailsTable.clearSearch()'>
|
31
|
+
<span class="pficon pficon-close"></span>
|
32
|
+
</button>
|
33
|
+
</div>
|
34
|
+
</div>
|
35
|
+
|
36
|
+
<div class="form-group">
|
37
|
+
<button class="btn btn-default" type="button" ng-click="detailsTable.search(detailsTable.searchTerm)" >
|
38
|
+
<span class="fa fa-search"></span>
|
39
|
+
</button>
|
40
|
+
</div>
|
41
|
+
</form>
|
33
42
|
</div>
|
34
43
|
</div>
|
35
44
|
|
@@ -18,35 +18,41 @@
|
|
18
18
|
</div>
|
19
19
|
</div>
|
20
20
|
|
21
|
-
|
22
21
|
<div class="col-sm-3 nutupane-info">
|
23
|
-
<
|
24
|
-
<
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
22
|
+
<form role="form" class="search-pf has-button">
|
23
|
+
<div class="form-group has-clear">
|
24
|
+
<div class="search-pf-input-group">
|
25
|
+
<label for="table-search" class="sr-only" translate>Search</label>
|
26
|
+
|
27
|
+
<input id="table-search"
|
28
|
+
type="search"
|
29
|
+
class="form-control"
|
30
|
+
placeholder="{{ 'Search...' | translate }}"
|
31
|
+
bst-on-enter="table.search(table.searchTerm)"
|
32
|
+
ng-model="table.searchTerm"
|
33
|
+
ng-trim="false"
|
34
|
+
typeahead="item.label for item in table.autocomplete($viewValue)"
|
35
|
+
typeahead-empty
|
36
|
+
typeahead-template-url="components/views/autocomplete-scoped-search.html"/>
|
37
|
+
|
38
|
+
<button type="button" class="clear" aria-hidden="true" ng-show="table.searchTerm" ng-click='table.clearSearch()'>
|
39
|
+
<span class="pficon pficon-close"></span>
|
40
|
+
</button>
|
41
|
+
</div>
|
42
|
+
</div>
|
43
|
+
|
44
|
+
<div class="form-group">
|
45
|
+
<button class="btn btn-default" type="button" ng-click="table.search(table.searchTerm)" >
|
46
|
+
<span class="fa fa-search"></span>
|
43
47
|
</button>
|
48
|
+
</div>
|
49
|
+
<div class="form-group">
|
44
50
|
<button class="btn btn-default dropdown-toggle" data-toggle="dropdown">
|
45
51
|
<i class="fa fa-caret-down"></i>
|
46
52
|
</button>
|
47
53
|
<ul bst-bookmark controller-name="controllerName" query="table.searchTerm" class="dropdown-menu pull-right"></ul>
|
48
|
-
</
|
49
|
-
</
|
54
|
+
</div>
|
55
|
+
</form>
|
50
56
|
</div>
|
51
57
|
|
52
58
|
<div class="col-sm-3 nutupane-info">
|
@@ -13,7 +13,7 @@ angular.module('Bastion.routing', ['ui.router']);
|
|
13
13
|
* @description
|
14
14
|
* Routing configuration for Bastion.
|
15
15
|
*/
|
16
|
-
function bastionRouting($urlRouterProvider, $locationProvider) {
|
16
|
+
function bastionRouting($stateProvider, $urlRouterProvider, $locationProvider) {
|
17
17
|
var oldBrowserBastionPath = '/bastion#', getRootPath;
|
18
18
|
|
19
19
|
getRootPath = function (path) {
|
@@ -25,6 +25,11 @@ angular.module('Bastion.routing', ['ui.router']);
|
|
25
25
|
return rootPath;
|
26
26
|
};
|
27
27
|
|
28
|
+
$stateProvider.state('404', {
|
29
|
+
permission: null,
|
30
|
+
templateUrl: 'layouts/404.html'
|
31
|
+
});
|
32
|
+
|
28
33
|
$urlRouterProvider.rule(function ($injector, $location) {
|
29
34
|
var $sniffer = $injector.get('$sniffer'),
|
30
35
|
$window = $injector.get('$window'),
|
@@ -65,7 +70,7 @@ angular.module('Bastion.routing', ['ui.router']);
|
|
65
70
|
}
|
66
71
|
|
67
72
|
if (foundParentState) {
|
68
|
-
$
|
73
|
+
$state.go('404');
|
69
74
|
} else {
|
70
75
|
$window.location.href = url;
|
71
76
|
}
|
@@ -73,9 +78,8 @@ angular.module('Bastion.routing', ['ui.router']);
|
|
73
78
|
});
|
74
79
|
|
75
80
|
$locationProvider.html5Mode({enabled: true, requireBase: false});
|
76
|
-
|
77
81
|
}
|
78
82
|
|
79
83
|
angular.module('Bastion.routing').config(bastionRouting);
|
80
|
-
bastionRouting.$inject = ['$urlRouterProvider', '$locationProvider'];
|
84
|
+
bastionRouting.$inject = ['$stateProvider', '$urlRouterProvider', '$locationProvider'];
|
81
85
|
})();
|
data/bower.json
CHANGED
data/grunt/karma.js
CHANGED
@@ -13,6 +13,9 @@ module.exports = {
|
|
13
13
|
preprocessors: {
|
14
14
|
'app/assets/javascripts/**/*.html': ['ng-html2js']
|
15
15
|
},
|
16
|
+
exclude: [
|
17
|
+
basePath + 'app/assets/javascripts/bastion/bastion-bootstrap.js'
|
18
|
+
],
|
16
19
|
files: [
|
17
20
|
basePath + '.tmp/bower_components/jquery/jquery.js',
|
18
21
|
basePath + 'vendor/assets/javascripts/bastion/underscore/underscore.js',
|
@@ -31,7 +34,6 @@ module.exports = {
|
|
31
34
|
basePath + 'vendor/assets/javascripts/bastion/ngInfiniteScroll/ng-infinite-scroll.js',
|
32
35
|
basePath + '.tmp/bower_components/angular-mocks/angular-mocks.js',
|
33
36
|
|
34
|
-
basePath + 'app/assets/javascripts/bastion/bastion-bootstrap.js',
|
35
37
|
basePath + 'app/assets/javascripts/bastion/bastion.module.js',
|
36
38
|
basePath + 'app/assets/javascripts/bastion/routing.module.js',
|
37
39
|
basePath + 'app/assets/javascripts/bastion/i18n/i18n.module.js',
|
data/lib/bastion/version.rb
CHANGED
data/package.json
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
"generator-bastion": "~0.1.2",
|
8
8
|
"grunt": "~0.4.5",
|
9
9
|
"grunt-angular-gettext": "~0.2.15",
|
10
|
-
"grunt-bower-task": "
|
10
|
+
"grunt-bower-task": "yatskevich/grunt-bower-task#v0.5.0",
|
11
11
|
"grunt-concurrent": "~1.0.0",
|
12
12
|
"grunt-eslint": "~6.0.0",
|
13
13
|
"grunt-htmlhint": "~0.4.1",
|
@@ -1,39 +1,118 @@
|
|
1
1
|
describe('Directive: bstAlert', function() {
|
2
|
-
var scope,
|
3
|
-
|
4
|
-
|
5
|
-
|
2
|
+
var $animate, $timeout, scope, compile, element, elementScope;
|
3
|
+
|
4
|
+
function createDirective (providedElement) {
|
5
|
+
element = angular.element('<div bst-alert="info"></div>');
|
6
|
+
|
7
|
+
if (providedElement) {
|
8
|
+
element = providedElement;
|
9
|
+
}
|
10
|
+
|
11
|
+
compile(element)(scope);
|
12
|
+
scope.$digest();
|
13
|
+
elementScope = element.isolateScope();
|
14
|
+
}
|
6
15
|
|
7
16
|
beforeEach(module('Bastion.components', 'components/views/bst-alert.html'));
|
8
17
|
|
18
|
+
beforeEach(module(function ($provide) {
|
19
|
+
$animate = {
|
20
|
+
addClass: function () {},
|
21
|
+
removeClass: function () {},
|
22
|
+
cancel: function () {},
|
23
|
+
leave: function () {
|
24
|
+
return {
|
25
|
+
then: function (callback) {
|
26
|
+
callback();
|
27
|
+
}
|
28
|
+
}
|
29
|
+
}
|
30
|
+
};
|
31
|
+
|
32
|
+
$timeout = function (callback) {
|
33
|
+
callback();
|
34
|
+
};
|
35
|
+
|
36
|
+
$provide.value('$animate', $animate);
|
37
|
+
$provide.value('$timeout', $timeout);
|
38
|
+
}));
|
39
|
+
|
9
40
|
beforeEach(inject(function(_$compile_, _$rootScope_) {
|
10
41
|
compile = _$compile_;
|
11
42
|
scope = _$rootScope_;
|
12
43
|
}));
|
13
44
|
|
14
45
|
beforeEach(function() {
|
15
|
-
|
16
|
-
|
17
|
-
compile(element)(scope);
|
18
|
-
scope.$digest();
|
19
|
-
|
20
|
-
elementScope = element.isolateScope();
|
46
|
+
createDirective();
|
21
47
|
});
|
22
48
|
|
23
49
|
it("should display an alert", function() {
|
24
|
-
scope.successMessages = ['hello'];
|
25
|
-
scope.$digest();
|
26
|
-
|
27
50
|
expect(element.find('.alert').length).toBe(1);
|
28
51
|
});
|
29
52
|
|
30
53
|
it("should display a close icon if a close function is provided", function () {
|
31
54
|
element = angular.element('<div bst-alert="info" close="close()"></div>');
|
55
|
+
createDirective(element);
|
56
|
+
expect(elementScope.closeable).toBe(true);
|
57
|
+
});
|
32
58
|
|
33
|
-
|
34
|
-
|
35
|
-
|
59
|
+
describe("can start the fade", function () {
|
60
|
+
beforeEach(function () {
|
61
|
+
spyOn($animate, 'leave').and.callThrough();
|
62
|
+
spyOn(elementScope, 'close');
|
63
|
+
});
|
36
64
|
|
37
|
-
|
65
|
+
it("and fades if the fade is not prevented", function () {
|
66
|
+
elementScope.fadePrevented = false;
|
67
|
+
elementScope.startFade();
|
68
|
+
|
69
|
+
expect($animate.leave).toHaveBeenCalled();
|
70
|
+
expect(elementScope.close).toHaveBeenCalled();
|
71
|
+
});
|
72
|
+
|
73
|
+
it("but does not fade if the fade is prevented", function () {
|
74
|
+
elementScope.fadePrevented = true;
|
75
|
+
elementScope.startFade();
|
76
|
+
|
77
|
+
expect($animate.leave).not.toHaveBeenCalled();
|
78
|
+
expect(elementScope.close).not.toHaveBeenCalled();
|
79
|
+
});
|
80
|
+
});
|
81
|
+
|
82
|
+
describe("can cancel the fade", function () {
|
83
|
+
beforeEach(function () {
|
84
|
+
element = angular.element('<div bst-alert="success"></div>');
|
85
|
+
createDirective(element);
|
86
|
+
});
|
87
|
+
|
88
|
+
it("by setting fadePrevented", function () {
|
89
|
+
elementScope.cancelFade();
|
90
|
+
expect(elementScope.fadePrevented).toBe(true);
|
91
|
+
});
|
92
|
+
|
93
|
+
it("by calling $animate.cancel() if the animation is in progress", function () {
|
94
|
+
spyOn($animate, 'cancel');
|
95
|
+
elementScope.cancelFade();
|
96
|
+
expect($animate.cancel).toHaveBeenCalled();
|
97
|
+
});
|
98
|
+
});
|
99
|
+
|
100
|
+
describe("automatically starts the fade", function () {
|
101
|
+
beforeEach(function () {
|
102
|
+
spyOn($animate, 'leave').and.callThrough();
|
103
|
+
});
|
104
|
+
|
105
|
+
it("for success alerts", function () {
|
106
|
+
element = angular.element('<div bst-alert="success"></div>');
|
107
|
+
createDirective(element);
|
108
|
+
expect(elementScope.fadePrevented).toBe(false);
|
109
|
+
expect($animate.leave).toHaveBeenCalled();
|
110
|
+
});
|
111
|
+
|
112
|
+
it("but not for non-success alerts", function () {
|
113
|
+
createDirective();
|
114
|
+
expect(elementScope.fadePrevented).toBe(true);
|
115
|
+
expect($animate.leave).not.toHaveBeenCalled();
|
116
|
+
});
|
38
117
|
});
|
39
118
|
});
|
@@ -101,6 +101,15 @@ describe('Factory: Nutupane', function() {
|
|
101
101
|
expect($location.search().search).toEqual("Find Me");
|
102
102
|
});
|
103
103
|
|
104
|
+
it("can clear the search", function () {
|
105
|
+
spyOn(nutupane.table, 'search');
|
106
|
+
|
107
|
+
nutupane.table.clearSearch();
|
108
|
+
|
109
|
+
expect(nutupane.table.search).toHaveBeenCalledWith(null);
|
110
|
+
expect(nutupane.table.searchCompleted).toBe(true);
|
111
|
+
});
|
112
|
+
|
104
113
|
it("enforcing the user of this factory to define a closeItem function", function() {
|
105
114
|
expect(nutupane.table.closeItem).toThrow();
|
106
115
|
});
|
data/test/routing.module.test.js
CHANGED
@@ -6,7 +6,7 @@ describe('config: Bastion.routing', function () {
|
|
6
6
|
$rootScope.$digest();
|
7
7
|
}
|
8
8
|
|
9
|
-
beforeEach(module('Bastion.routing'));
|
9
|
+
beforeEach(module('Bastion.routing', 'layouts/404.html'));
|
10
10
|
|
11
11
|
beforeEach(module(function ($provide) {
|
12
12
|
$sniffer = {
|
@@ -50,14 +50,13 @@ describe('config: Bastion.routing', function () {
|
|
50
50
|
});
|
51
51
|
|
52
52
|
describe("handles undefined states by", function () {
|
53
|
-
beforeEach(function () {
|
54
|
-
|
55
|
-
});
|
56
|
-
|
57
53
|
it("redirecting to a 404 page if the parent state is found", function () {
|
58
54
|
spyOn($state, 'get').and.returnValue([{url: '/found-state'}]);
|
55
|
+
spyOn($state, 'go');
|
56
|
+
|
59
57
|
goTo('/found_state/does_not_exist');
|
60
|
-
|
58
|
+
|
59
|
+
expect($state.go).toHaveBeenCalledWith('404');
|
61
60
|
});
|
62
61
|
|
63
62
|
it("redirecting to the url if no parent state is found", function () {
|