bastion 0.1.9 → 0.1.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/assets/javascripts/bastion/components/nutupane.factory.js +42 -0
- data/app/assets/javascripts/bastion/components/typeahead-empty.directive.js +42 -0
- data/app/assets/javascripts/bastion/components/views/autocomplete-scoped-search.html +10 -0
- data/app/assets/javascripts/bastion/layouts/details-nutupane.html +6 -1
- data/app/assets/javascripts/bastion/layouts/nutupane.html +5 -1
- data/app/assets/stylesheets/bastion/nutupane.less +4 -1
- data/lib/bastion/engine.rb +2 -6
- data/lib/bastion/version.rb +1 -1
- data/lib/bastion.rb +1 -1
- data/test/components/nutupane.factory.test.js +33 -0
- data/test/components/typeahead-empty.directive.test.js +62 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b8ffeee982685674e514ec036fb70f5c46267247
|
4
|
+
data.tar.gz: 1c2513f3cf4b6d764000c11c89654259b09f580e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bb30797fdee0fc1ec84de971713c901d4c5dbde02563ae66cdf5d4fbd6c8253163aa2063b3bcb0fe9e385b5e9350d8e519933efbfa80f060108918d63736915b
|
7
|
+
data.tar.gz: fdef65e2a62df3d92ed7467da02022e4ad072a5280a2aa1b954096eda3f18db413e469de4e27866ec38c1215cc28ad29990e459815f8b3ce0933932e3b0b02b7
|
@@ -115,6 +115,48 @@ angular.module('Bastion.components').factory('Nutupane',
|
|
115
115
|
return params;
|
116
116
|
};
|
117
117
|
|
118
|
+
self.table.autocomplete = function (term) {
|
119
|
+
var data, promise, params;
|
120
|
+
if (resource.autocomplete) {
|
121
|
+
params = self.getParams();
|
122
|
+
params.search = term;
|
123
|
+
data = resource.autocomplete(params);
|
124
|
+
} else {
|
125
|
+
data = self.table.fetchAutocomplete(term);
|
126
|
+
}
|
127
|
+
|
128
|
+
promise = data.$promise;
|
129
|
+
if (promise) {
|
130
|
+
return promise.then(function (data) {
|
131
|
+
return self.table.transformScopedSearch(data);
|
132
|
+
});
|
133
|
+
}
|
134
|
+
else {
|
135
|
+
return data;
|
136
|
+
}
|
137
|
+
};
|
138
|
+
|
139
|
+
self.table.transformScopedSearch = function (results) {
|
140
|
+
var rows = [],
|
141
|
+
categoriesFound = [];
|
142
|
+
angular.forEach(results, function (row) {
|
143
|
+
if (row.category && row.category.length > 0) {
|
144
|
+
if (categoriesFound.indexOf(row.category) === -1) {
|
145
|
+
categoriesFound.push(row.category);
|
146
|
+
rows.push({category: row.category, isCategory: true});
|
147
|
+
}
|
148
|
+
}
|
149
|
+
rows.push(row);
|
150
|
+
});
|
151
|
+
|
152
|
+
return rows;
|
153
|
+
};
|
154
|
+
|
155
|
+
//Overridable by real controllers, but default to nothing
|
156
|
+
self.table.fetchAutocomplete = function () {
|
157
|
+
return [];
|
158
|
+
};
|
159
|
+
|
118
160
|
self.enableSelectAllResults = function () {
|
119
161
|
self.table.selectAllResultsEnabled = true;
|
120
162
|
self.table.allResultsSelected = false;
|
@@ -0,0 +1,42 @@
|
|
1
|
+
/**
|
2
|
+
Copyright 2014 Red Hat, Inc.
|
3
|
+
|
4
|
+
This software is licensed to you under the GNU General Public
|
5
|
+
License as published by the Free Software Foundation; either version
|
6
|
+
2 of the License (GPLv2) or (at your option) any later version.
|
7
|
+
There is NO WARRANTY for this software, express or implied,
|
8
|
+
including the implied warranties of MERCHANTABILITY,
|
9
|
+
NON-INFRINGEMENT, or FITNESS FOR A PARTICULAR PURPOSE. You should
|
10
|
+
have received a copy of GPLv2 along with this software; if not, see
|
11
|
+
http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
|
12
|
+
**/
|
13
|
+
|
14
|
+
/**
|
15
|
+
* @ngdoc directive
|
16
|
+
* @name Bastion.components.directive:typeaheadEmpty
|
17
|
+
*
|
18
|
+
*
|
19
|
+
* @description
|
20
|
+
* Used to support autocompletion on focus, not just after the user types a single character
|
21
|
+
*
|
22
|
+
* @example
|
23
|
+
<input
|
24
|
+
typeahead="item as item.label for item in table.autocomplete($viewValue)"
|
25
|
+
typeahead-empty />
|
26
|
+
*/
|
27
|
+
|
28
|
+
angular.module('Bastion.components').directive('typeaheadEmpty', function () {
|
29
|
+
return {
|
30
|
+
require: 'ngModel',
|
31
|
+
link: function (scope, element, attrs, modelCtrl) {
|
32
|
+
element.bind('focus', function () {
|
33
|
+
if (modelCtrl.$viewValue === undefined || modelCtrl.$viewValue === '') {
|
34
|
+
modelCtrl.$setViewValue(' ');
|
35
|
+
}
|
36
|
+
else {
|
37
|
+
modelCtrl.$setViewValue(modelCtrl.$viewValue);
|
38
|
+
}
|
39
|
+
});
|
40
|
+
}
|
41
|
+
};
|
42
|
+
});
|
@@ -20,7 +20,12 @@
|
|
20
20
|
class="form-control"
|
21
21
|
placeholder="{{ 'Search...' | translate }}"
|
22
22
|
ng-model="detailsTable.searchTerm"
|
23
|
-
bst-on-enter="detailsTable.search(detailsTable.searchTerm)"
|
23
|
+
bst-on-enter="detailsTable.search(detailsTable.searchTerm)"
|
24
|
+
ng-trim="false"
|
25
|
+
typeahead="item.label for item in detailsTable.autocomplete($viewValue)"
|
26
|
+
typeahead-empty
|
27
|
+
typeahead-template-url="widgets/views/autocomplete-scoped-search.html"/>
|
28
|
+
|
24
29
|
<span class="input-group-btn">
|
25
30
|
<button ng-click="detailsTable.search(detailsTable.searchTerm)" class="btn btn-default" type="button"><i class="icon-search"></i></button>
|
26
31
|
</span>
|
@@ -16,8 +16,12 @@
|
|
16
16
|
<input type="text"
|
17
17
|
class="form-control"
|
18
18
|
placeholder="{{ 'Search...' | translate }}"
|
19
|
+
bst-on-enter="table.search(table.searchTerm)"
|
19
20
|
ng-model="table.searchTerm"
|
20
|
-
|
21
|
+
ng-trim="false"
|
22
|
+
typeahead="item.label for item in table.autocomplete($viewValue)"
|
23
|
+
typeahead-empty
|
24
|
+
typeahead-template-url="components/views/autocomplete-scoped-search.html"/>
|
21
25
|
<span class="input-group-btn">
|
22
26
|
<button ng-click="table.search(table.searchTerm)" class="btn btn-default" type="button"><i class="icon-search"></i></button>
|
23
27
|
</span>
|
@@ -112,7 +112,6 @@ td.row-select {
|
|
112
112
|
background: rgb(250, 250, 250);
|
113
113
|
padding: 10px 15px 10px 0;
|
114
114
|
border-bottom: 1px solid rgb(230, 230, 230);
|
115
|
-
overflow: auto;
|
116
115
|
|
117
116
|
h2 { margin: 5px 0 0 0; }
|
118
117
|
|
@@ -124,6 +123,10 @@ td.row-select {
|
|
124
123
|
margin-bottom: 0;
|
125
124
|
}
|
126
125
|
}
|
126
|
+
|
127
|
+
.dropdown-menu {
|
128
|
+
width: 100%;
|
129
|
+
}
|
127
130
|
}
|
128
131
|
|
129
132
|
.nutupane-details-bar {
|
data/lib/bastion/engine.rb
CHANGED
@@ -14,12 +14,8 @@ module Bastion
|
|
14
14
|
app.routes_reloader.paths.unshift("#{Bastion::Engine.root}/config/routes.rb")
|
15
15
|
end
|
16
16
|
|
17
|
-
initializer "bastion.
|
18
|
-
|
19
|
-
app.config.less.paths << "#{Bastion::Engine.root}/app/assets/stylesheets/bastion"
|
20
|
-
app.config.less.paths << "#{Bastion::Engine.root}/vendor/assets/stylesheets/bastion"
|
21
|
-
end
|
22
|
-
|
17
|
+
initializer "bastion.plugin", :group => :all do |app|
|
18
|
+
app.config.assets.paths << "#{Bastion::Engine.root}/vendor/assets/stylesheets/bastion"
|
23
19
|
app.middleware.use ::ActionDispatch::Static, "#{Bastion::Engine.root}/app/assets/javascripts/bastion"
|
24
20
|
|
25
21
|
SETTINGS[:bastion] = {:assets => {}} if SETTINGS[:bastion].nil?
|
data/lib/bastion/version.rb
CHANGED
data/lib/bastion.rb
CHANGED
@@ -3,7 +3,7 @@ require 'rails'
|
|
3
3
|
lib_foreman = File.expand_path('lib/foreman', Rails.root)
|
4
4
|
require lib_foreman unless !Dir.exist?(lib_foreman)
|
5
5
|
|
6
|
-
require 'less-rails'
|
6
|
+
require 'less-rails' unless Rails.env.production?
|
7
7
|
require 'angular-rails-templates'
|
8
8
|
|
9
9
|
require File.expand_path('bastion/engine', File.dirname(__FILE__))
|
@@ -233,6 +233,39 @@ describe('Factory: Nutupane', function() {
|
|
233
233
|
expect(results.included.search).toBe("FOO");
|
234
234
|
});
|
235
235
|
|
236
|
+
it("provides a way to translate scoped search queries", function() {
|
237
|
+
var translated,
|
238
|
+
data = [{label: 'bar', category: 'foo'},
|
239
|
+
{label: 'bar2', category: 'foo'}];
|
240
|
+
|
241
|
+
translated = nutupane.table.transformScopedSearch(data);
|
242
|
+
expect(translated.length).toBe(3);
|
243
|
+
expect(translated[0].isCategory).toBeTruthy();
|
244
|
+
expect(translated[0].category).toBe('foo');
|
245
|
+
expect(translated[1]).toBe(data[0]);
|
246
|
+
expect(translated[2]).toBe(data[1]);
|
247
|
+
});
|
248
|
+
|
249
|
+
it("autocompletes using the original resource if possible", function() {
|
250
|
+
var data;
|
251
|
+
Resource.autocomplete = function() {return ["foo"]};
|
252
|
+
spyOn(Resource, 'autocomplete').andCallThrough();
|
253
|
+
|
254
|
+
data = nutupane.table.autocomplete();
|
255
|
+
expect(Resource.autocomplete).toHaveBeenCalled();
|
256
|
+
expect(data[0]).toBe("foo");
|
257
|
+
});
|
258
|
+
|
259
|
+
it("autocompletes using fetchAutocomplete if resource doesn't support autocomplete", function() {
|
260
|
+
var data;
|
261
|
+
nutupane.table.fetchAutocomplete = function() {return ['bar']};
|
262
|
+
spyOn(nutupane.table, 'fetchAutocomplete').andCallThrough();
|
263
|
+
|
264
|
+
data = nutupane.table.autocomplete();
|
265
|
+
expect(nutupane.table.fetchAutocomplete).toHaveBeenCalled();
|
266
|
+
expect(data[0]).toBe("bar");
|
267
|
+
});
|
268
|
+
|
236
269
|
describe("provides a way to sort the table", function() {
|
237
270
|
it ("defaults the sort to ascending if the previous sort does not match the new sort.", function() {
|
238
271
|
var expectedParams = {sort_by: 'name', sort_order: 'ASC', search: '', page: 1};
|
@@ -0,0 +1,62 @@
|
|
1
|
+
/**
|
2
|
+
* Copyright 2014 Red Hat, Inc.
|
3
|
+
*
|
4
|
+
* This software is licensed to you under the GNU General Public
|
5
|
+
* License as published by the Free Software Foundation; either version
|
6
|
+
* 2 of the License (GPLv2) or (at your option) any later version.
|
7
|
+
* There is NO WARRANTY for this software, express or implied,
|
8
|
+
* including the implied warranties of MERCHANTABILITY,
|
9
|
+
* NON-INFRINGEMENT, or FITNESS FOR A PARTICULAR PURPOSE. You should
|
10
|
+
* have received a copy of GPLv2 along with this software; if not, see
|
11
|
+
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
|
12
|
+
*/
|
13
|
+
|
14
|
+
describe('Directive: typeahead-empty', function() {
|
15
|
+
var scope,
|
16
|
+
compile,
|
17
|
+
element,
|
18
|
+
elementScope;
|
19
|
+
|
20
|
+
|
21
|
+
beforeEach(module(
|
22
|
+
'Bastion.components'
|
23
|
+
));
|
24
|
+
|
25
|
+
beforeEach(inject(function(_$compile_, _$rootScope_) {
|
26
|
+
compile = _$compile_;
|
27
|
+
scope = _$rootScope_;
|
28
|
+
}));
|
29
|
+
|
30
|
+
beforeEach(function() {
|
31
|
+
element = angular.element('<input ng-model="myInput" type="text" typeahead-empty />');
|
32
|
+
|
33
|
+
compile(element)(scope);
|
34
|
+
scope.$digest();
|
35
|
+
|
36
|
+
elementScope = element.isolateScope();
|
37
|
+
});
|
38
|
+
|
39
|
+
it("should adjust empty string", function() {
|
40
|
+
scope.myInput = '';
|
41
|
+
scope.$digest();
|
42
|
+
element.triggerHandler('focus');
|
43
|
+
|
44
|
+
expect(scope.myInput).toBe(' ');
|
45
|
+
});
|
46
|
+
|
47
|
+
it("should adjust undefined", function() {
|
48
|
+
scope.myInput = undefined;
|
49
|
+
scope.$digest();
|
50
|
+
element.triggerHandler('focus');
|
51
|
+
|
52
|
+
expect(scope.myInput).toBe(' ');
|
53
|
+
});
|
54
|
+
|
55
|
+
it("should not adjust otherss", function() {
|
56
|
+
scope.myInput = 'foo';
|
57
|
+
scope.$digest();
|
58
|
+
element.triggerHandler('focus');
|
59
|
+
|
60
|
+
expect(scope.myInput).toBe('foo');
|
61
|
+
});
|
62
|
+
});
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bastion
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Katello
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-12-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: angular-rails-templates
|
@@ -96,6 +96,8 @@ files:
|
|
96
96
|
- app/assets/javascripts/bastion/components/page-title.directive.js
|
97
97
|
- app/assets/javascripts/bastion/components/page-title.service.js
|
98
98
|
- app/assets/javascripts/bastion/components/path-selector.directive.js
|
99
|
+
- app/assets/javascripts/bastion/components/typeahead-empty.directive.js
|
100
|
+
- app/assets/javascripts/bastion/components/views/autocomplete-scoped-search.html
|
99
101
|
- app/assets/javascripts/bastion/components/views/bst-alert.html
|
100
102
|
- app/assets/javascripts/bastion/components/views/bst-dropdown.html
|
101
103
|
- app/assets/javascripts/bastion/components/views/bst-edit-add-item.html
|
@@ -181,6 +183,7 @@ files:
|
|
181
183
|
- test/components/page-title.directive.test.js
|
182
184
|
- test/components/page-title.service.test.js
|
183
185
|
- test/components/path-selector.directive.test.js
|
186
|
+
- test/components/typeahead-empty.directive.test.js
|
184
187
|
- test/i18n/translate.service.test.js
|
185
188
|
- test/menu/menu-expander.service.test.js
|
186
189
|
- test/test-mocks.module.js
|
@@ -370,6 +373,7 @@ test_files:
|
|
370
373
|
- test/components/bst-menu.directive.test.js
|
371
374
|
- test/components/bst-edit.directive.test.js
|
372
375
|
- test/components/path-selector.directive.test.js
|
376
|
+
- test/components/typeahead-empty.directive.test.js
|
373
377
|
- test/components/bst-form-buttons.directive.test.js
|
374
378
|
- test/components/page-title.service.test.js
|
375
379
|
- test/bastion/test-constants.js
|