Skip to content

Commit c51dbe4

Browse files
committed
Merge pull request #45 from 10gen/INT-196-filter-fields
feature(ui): INT-196 make schema fields filterable
2 parents e6c16d2 + 3e43211 commit c51dbe4

File tree

10 files changed

+119
-35
lines changed

10 files changed

+119
-35
lines changed

scout-style/sidebar.less

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,8 @@
9292
width: 218px;
9393
height: 174px;
9494
border-top: 2px solid @sidebar-border;
95-
background: url(/images/fake-sidebar-controls.png) 0 0 no-repeat;
96-
background-size: 218px 174px;
95+
// background: url(/images/fake-sidebar-controls.png) 0 0 no-repeat;
96+
// background-size: 218px 174px;
9797
}
9898
}
9999

scout-ui/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"amp-result": "^1.1.0",
4040
"ampersand-app": "^1.0.3",
4141
"ampersand-collection": "^1.4.1",
42-
"ampersand-collection-filterable": "^0.1.0",
42+
"ampersand-collection-filterable": "^0.2.0",
4343
"ampersand-collection-lodash-mixin": "^2.0.1",
4444
"ampersand-collection-rest-mixin": "^3.0.0",
4545
"ampersand-model": "^4.0.0",

scout-ui/src/field-list/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ var BasicFieldView = View.extend({
4848
render: function() {
4949
this.renderWithTemplate(this);
5050
this.viewSwitcher = new ViewSwitcher(this.queryByHook('minichart-container'));
51+
if (this.model.types.length > 0) {
52+
this.switchView(this.model.types.at(0));
53+
}
5154
},
5255
switchView: function(typeModel) {
5356
var type = typeModel.getId().toLowerCase();

scout-ui/src/home/collection.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ module.exports = AmpersandView.extend({
1515
open: {
1616
type: 'boolean',
1717
default: false
18+
},
19+
fieldListView: {
20+
type: 'view'
1821
}
1922
},
2023
derived: {
@@ -79,11 +82,12 @@ module.exports = AmpersandView.extend({
7982
waitFor: 'schema.fields',
8083
hook: 'fields-subview',
8184
prepareView: function(el) {
82-
return new FieldListView({
83-
el: el,
84-
parent: this,
85-
collection: this.schema.fields
86-
});
85+
this.fieldListView = new FieldListView({
86+
el: el,
87+
parent: this,
88+
collection: this.schema.fields
89+
});
90+
return this.fieldListView;
8791
}
8892
},
8993
refinebar: {

scout-ui/src/home/index.js

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,34 @@ module.exports = AmpersandView.extend({
1616
model: models.Instance
1717
},
1818
props: {
19+
switcher: {
20+
type: 'object',
21+
default: null
22+
},
1923
ns: {
2024
type: 'string',
2125
allowNull: true,
2226
default: null
2327
}
2428
},
29+
derived: {
30+
currentCollection: {
31+
deps: ['ns'],
32+
fn: function () {
33+
if (!this.ns) return null;
34+
return this.model.collections.find({
35+
_id: this.ns
36+
});
37+
}
38+
},
39+
currentCollectionView: {
40+
cache: false,
41+
fn: function() {
42+
return this.switcher ?
43+
this.switcher.current : null;
44+
}
45+
}
46+
},
2547
initialize: function(options) {
2648
options = options || {};
2749
this.ns = options.ns;
@@ -30,13 +52,8 @@ module.exports = AmpersandView.extend({
3052

3153
this.listenTo(this.model, 'sync', function() {
3254
if (!this.ns) return;
33-
34-
var current = this.model.collections.find({
35-
_id: this.ns
36-
});
37-
if (!current) return;
38-
39-
this.showCollection(current);
55+
if (!this.currentCollection) return;
56+
this.showCollection(this.currentCollection);
4057
});
4158

4259
this.once('change:rendered', this.onRendered);

scout-ui/src/models/index.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ var types = brain.types;
1212
var _ = require('underscore');
1313
var es = require('event-stream');
1414
var Schema = require('mongodb-schema').Schema;
15+
var FieldCollection = require('mongodb-schema').FieldCollection;
16+
var Field = require('mongodb-schema/lib/field');
1517
var QueryOptions = require('./query-options');
18+
var filterableMixin = require('ampersand-collection-filterable');
1619

1720
// Yay! Use the API from the devtools console.
1821
window.scout = client;
@@ -30,7 +33,31 @@ client.on('error', function(err) {
3033
console.error(err);
3134
});
3235

36+
/**
37+
* wrapping mongodb-schema's FieldCollection with a filterable mixin
38+
*/
39+
var FilterableFieldCollection = FieldCollection.extend(filterableMixin, {
40+
// @note, this should be in mongodb-schema FieldCollection
41+
// but FieldCollection will soon not be polymorphic anymore, so the
42+
// problem will go away and we can remove this.
43+
isModel: function (model) {
44+
return model instanceof Field;
45+
},
46+
// @note: this should not be necessary, but the mixin doesn't currently
47+
// reset its state between collections. @see
48+
// https://github.com/mongodb-js/ampersand-collection-filterable/issues/1
49+
initialize: function() {
50+
this._filtered = [];
51+
}
52+
});
53+
3354
var SampledSchema = Schema.extend({
55+
/**
56+
* Our fields need to be filterable, adding a mixin
57+
*/
58+
collections: {
59+
fields: FilterableFieldCollection
60+
},
3461
/**
3562
* Clear any data accumulated from sampling.
3663
*/
File renamed without changes.

scout-ui/src/sidebar/index.jade

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
div
22
.sidebar.panel
3-
div(data-hook='collections-filter')
4-
div(data-hook='collections')
5-
.sidebar-controls
3+
div(data-hook='collection-filter-subview')
4+
div(data-hook='collection-list-subview')
5+
div(data-hook='sidebar-control-subview')

scout-ui/src/sidebar/index.js

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,34 @@
11
var View = require('ampersand-view');
22
var debug = require('debug')('scout-ui:home');
3-
var models = require('../models');
43

5-
var ListFilter = View.extend({
4+
var CollectionFilterView = View.extend({
5+
template: require('./collection-filter.jade'),
66
props: {
77
search: 'string'
88
},
99
initialize: function() {
1010
this.listenTo(this, 'change:search', this.applyFilter);
1111
},
12-
template: require('./list-filter.jade'),
12+
events: {
13+
'input [data-hook=search]': 'handleInputChanged'
14+
},
1315
render: function() {
1416
this.renderWithTemplate(this);
15-
this.input = this.queryByHook('search');
17+
this.cacheElements({
18+
'input': '[data-hook=search]'
19+
});
1620
this.input.addEventListener('input', this.handleInputChanged.bind(this), false);
1721
},
1822
handleInputChanged: function() {
1923
this.search = this.input.value.trim();
2024
},
2125
applyFilter: function() {
22-
debug('search is now', this.search);
23-
this.parent.filter(this.search);
26+
this.parent.filterCollections(this.search);
2427
}
2528
});
2629

2730
// @todo: Keyboard nav: up/down: change active item, right: -> show collection, left: -> hide collection
28-
var CollectionsList = View.extend({
31+
var CollectionListView = View.extend({
2932
template: '<ul class="list-group" data-hook="collections"></ul>',
3033
ItemView: View.extend({
3134
bindings: {
@@ -54,34 +57,60 @@ var CollectionsList = View.extend({
5457
}
5558
});
5659

60+
61+
var SidebarControlView = CollectionFilterView.extend({
62+
template: require('./sidebar-controls.jade'),
63+
applyFilter: function() {
64+
this.parent.filterFields(this.search);
65+
}
66+
});
67+
68+
5769
module.exports = View.extend({
58-
filter: function(pattern) {
59-
var re = new RegExp((pattern || '.*'));
60-
this.collection.filter(function(model) {
61-
return re.test(model.getId());
62-
});
63-
},
6470
template: require('./index.jade'),
6571
subviews: {
6672
collections_filter: {
67-
hook: 'collections-filter',
73+
hook: 'collection-filter-subview',
6874
prepareView: function(el) {
69-
return new ListFilter({
75+
return new CollectionFilterView({
7076
el: el,
7177
parent: this
7278
});
7379
}
7480
},
7581
collections: {
76-
hook: 'collections',
82+
hook: 'collection-list-subview',
7783
prepareView: function(el) {
78-
var view = new CollectionsList({
84+
var view = new CollectionListView({
7985
el: el,
8086
parent: this,
8187
collection: this.collection
8288
});
8389
return view;
8490
}
91+
},
92+
sidebar_control: {
93+
hook: 'sidebar-control-subview',
94+
prepareView: function(el) {
95+
var view = new SidebarControlView({
96+
el: el,
97+
});
98+
return view;
99+
}
85100
}
101+
},
102+
filterCollections: function(pattern) {
103+
var re = new RegExp((pattern || '.*'));
104+
this.collection.filter(function(model) {
105+
return re.test(model.getId());
106+
});
107+
},
108+
filterFields: function(pattern) {
109+
var re = new RegExp((pattern || '.*'));
110+
// get current field list view
111+
var fieldListView = this.parent.currentCollectionView.fieldListView;
112+
fieldListView.collection.filter(function(model) {
113+
return re.test(model.getId());
114+
});
86115
}
87116
});
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.sidebar-controls
2+
.panel-heading.list-filter
3+
i.search.octicon-search
4+
input(type='search', placeholder='filter fields', data-hook='search')

0 commit comments

Comments
 (0)