bastion 0.1.9 → 0.1.10
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/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
|