Skip to content

Commit 22d745d

Browse files
authored
INT-1663: Reactify schema (#458)
* replace schema view with component adding field and type components. nested array fields working. use native-parser stream directly use schema stream ampersand model temporarily. towards react minicharts… progress on d3 component and d3 minichart fns porting d3 functions to work with react. store only runs one sampling process at a time fix bug that prevented initial rendering of d3 components sort undefined types last. make subtypes work array subtypes fully working now. detect geo coordinates (use new module) maps work, responsive minicharts. Tooltips on types working. use golden ratio for map dimensions. QueryStore, set/clear/add/remove, unique mc query builder more verbose comments for field.jsx distinct queries with few and many. correct range/single click queries on few/many. performance could be better. also try react-d3-library. move helpers to util use throttled store methods to improve performance fixed “many”. fully working for distinct queries. fixed few. re-enable brush background on “many” charts. adding setRangeValue, setOrUnsetValue bump [email protected], [email protected] make unsetIfSet an option for query actions implemented query building on ranges (numeric) fix resizing bug in distinct many charts was re-creating many() charts on every redraw… querybuilder for date/objectid and geo fix svg unique bug, full path name for query building adding internal status bar package status component and early integration progress bar for sampling. needs some work. status / progress bar fixed for schema view. remove old statusbar folder, schema model added QueryBar component, moved query store + utils query validation, query bar backwards pass. apply and reset actions hooked up with status and schema query bar: enter also applies valid queries. make all query builder actions sync, better performance clean up schema component. status subview, schema actions, maxtimems * rebased and using new hadron-app-registry * getting StatusAction from appRegistry * register QueryAction * rename schema-store.jsx to index.jsx * singular names for lib/* folders in status package * QueryAction, file renames, cleanup * handle error when stream ends. * trigger filterChanged event on apply * INT-1663: Move sampling message to query * INT-1663: Use sampling message in schema view * INT-1663: Expose Document component INT-1663: Add indexes package INT-1663: Adding initial indexes react package INT-1663: Split index column components INT-1663: Move index work to new view INT-1663: Fixing tooltips INT-1663: Allow document to not be editable Upgrade react-bootstrap * Revert "INT-1663: Expose Document component" This reverts commit 57e644c. * fix const/let bug in coordinates.js * INT-1663: Split rendering between tabs on message * INT-1663: Change sampling message based on tab * fix single vs. double quotes linting issue * adding “minicharts” for document and array. * bump [email protected] * fix edge case for empty subdocs with 0 fields. * INT-1663: Sample didn't error with 0 sampled docs * INT-1663: Ensure document list re-renders on collection change * INT-1663: Show number of loaded documents in sample bar * INT-1663: Update react-bootstrap * INT-1663: Resize minicharts on schema tab click
1 parent 3470613 commit 22d745d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+5947
-771
lines changed

package.json

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@
9898
"debug": "mongodb-js/debug#v2.2.3",
9999
"debug-menu": "^0.3.0",
100100
"electron-squirrel-startup": "^1.0.0",
101+
"detect-coordinates": "^0.1.0",
101102
"font-awesome": "https://github.com/FortAwesome/Font-Awesome/archive/v4.4.0.tar.gz",
102103
"get-object-path": "azer/get-object-path#74eb42de0cfd02c14ffdd18552f295aba723d394",
103104
"hadron-action": "^0.1.0",
@@ -124,7 +125,7 @@
124125
"mongodb-data-service": "^1.1.1",
125126
"mongodb-database-model": "^0.1.2",
126127
"mongodb-explain-plan-model": "^0.2.0",
127-
"mongodb-extended-json": "^1.6.0",
128+
"mongodb-extended-json": "^1.7.0",
128129
"mongodb-js-metrics": "^1.2.0",
129130
"mongodb-language-model": "^0.3.3",
130131
"mongodb-ns": "^1.0.3",
@@ -136,8 +137,12 @@
136137
"qs": "^5.2.0",
137138
"raf": "^3.1.0",
138139
"react": "^15.2.1",
139-
"react-bootstrap": "0.29.5",
140+
"react-bootstrap": "0.30.2",
140141
"react-dom": "^15.2.1",
142+
"react-native-listener": "^1.0.1",
143+
"react-tooltip": "^2.0.3",
144+
"reflux": "0.4.1",
145+
"reflux-state-mixin": "^0.7.0",
141146
"semver": "^5.1.0",
142147
"storage-mixin": "^0.8.0",
143148
"tunnel-ssh": "^3.2.1-beta",
@@ -147,10 +152,11 @@
147152
"uuid": "^2.0.1"
148153
},
149154
"devDependencies": {
155+
"babel-eslint": "^6.0.4",
150156
"chai": "^3.4.1",
151157
"chai-as-promised": "^5.1.0",
152158
"electron-prebuilt": "1.2.8",
153-
"eslint-config-mongodb-js": "^1.0.6",
159+
"eslint-config-mongodb-js": "^2.0.1",
154160
"eslint-plugin-react": "^4.1.0",
155161
"hadron-build": "^0.7.2",
156162
"mocha": "^2.3.4",

src/app/connect/index.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ var ConnectFormView = require('./connect-form-view');
33
var Connection = require('../models/connection');
44
var ConnectionCollection = require('../models/connection-collection');
55
var MongoDBConnection = require('mongodb-connection-model');
6-
76
var SidebarWrapperView = require('./sidebar');
87
var View = require('ampersand-view');
98

@@ -38,6 +37,9 @@ var sslMethods = require('./ssl');
3837
*/
3938
var sshTunnelMethods = require('./ssh-tunnel');
4039

40+
41+
var StatusAction = app.appRegistry.getAction('StatusAction');
42+
4143
var ConnectView = View.extend({
4244
template: indexTemplate,
4345
screenName: 'Connect',
@@ -428,7 +430,7 @@ var ConnectView = View.extend({
428430
this.dispatch('error received');
429431
return;
430432
}
431-
app.statusbar.show();
433+
StatusAction.showIndeterminateProgressBar();
432434

433435
var onSave = function() {
434436
this.connections.add(this.connection, { merge: true });
@@ -437,8 +439,8 @@ var ConnectView = View.extend({
437439
};
438440

439441
connection.test(function(err) {
440-
app.statusbar.hide();
441442
if (!err) {
443+
StatusAction.hide();
442444
// now save connection
443445
this.connection = connection;
444446
this.connection.save({ last_used: new Date() }, { success: onSave.bind(this) });
@@ -459,7 +461,7 @@ var ConnectView = View.extend({
459461
*/
460462
useConnection: function(connection) {
461463
connection = connection || this.connection;
462-
app.statusbar.hide();
464+
StatusAction.hide();
463465
metrics.track('Connection', 'used', {
464466
authentication: connection.authentication,
465467
ssl: connection.ssl,

src/app/home/collection.js

Lines changed: 53 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
var View = require('ampersand-view');
2+
var Action = require('hadron-action');
23
var CollectionStatsView = require('../collection-stats');
34
var DocumentView = require('../documents');
45
var SchemaView = require('../schema');
56
var IndexView = require('../indexes');
6-
var RefineBarView = require('../refine-view');
77
var ExplainView = require('../explain-plan');
88
var MongoDBCollection = require('../models/mongodb-collection');
9+
var React = require('react');
10+
var ReactDOM = require('react-dom');
911
var NamespaceStore = require('hadron-reflux-store').NamespaceStore;
1012
var _ = require('lodash');
1113

@@ -15,6 +17,14 @@ var debug = require('debug')('mongodb-compass:home:collection');
1517

1618
var collectionTemplate = require('./collection.jade');
1719

20+
// map tab label to correct view and switch views
21+
var tabToViewMap = {
22+
'DOCUMENTS': 'documentView',
23+
'SCHEMA': 'schemaView',
24+
'EXPLAIN PLAN': 'explainView',
25+
'INDEXES': 'indexView'
26+
};
27+
1828
var MongoDBCollectionView = View.extend({
1929
// modelType: 'Collection',
2030
template: collectionTemplate,
@@ -68,6 +78,7 @@ var MongoDBCollectionView = View.extend({
6878
},
6979
documentView: {
7080
hook: 'document-subview',
81+
waitFor: 'ns',
7182
prepareView: function(el) {
7283
return new DocumentView({
7384
el: el,
@@ -78,6 +89,7 @@ var MongoDBCollectionView = View.extend({
7889
},
7990
schemaView: {
8091
hook: 'schema-subview',
92+
waitFor: 'ns',
8193
prepareView: function(el) {
8294
return new SchemaView({
8395
el: el,
@@ -88,6 +100,7 @@ var MongoDBCollectionView = View.extend({
88100
},
89101
indexView: {
90102
hook: 'index-subview',
103+
waitFor: 'ns',
91104
prepareView: function(el) {
92105
return new IndexView({
93106
el: el,
@@ -105,63 +118,69 @@ var MongoDBCollectionView = View.extend({
105118
model: this.model
106119
});
107120
}
108-
},
109-
refineBarView: {
110-
hook: 'refine-bar-subview',
111-
prepareView: function(el) {
112-
var view = new RefineBarView({
113-
el: el,
114-
parent: this,
115-
queryOptions: app.queryOptions,
116-
volatileQueryOptions: app.volatileQueryOptions
117-
});
118-
view.on('submit', function() {
119-
this.trigger('submit:query');
120-
}.bind(this));
121-
return view;
122-
}
123121
}
122+
// refineBarView: {
123+
// hook: 'refine-bar-subview',
124+
// prepareView: function(el) {
125+
// var view = new RefineBarView({
126+
// el: el,
127+
// parent: this,
128+
// queryOptions: app.queryOptions,
129+
// volatileQueryOptions: app.volatileQueryOptions
130+
// });
131+
// view.on('submit', function() {
132+
// this.trigger('submit:query');
133+
// }.bind(this));
134+
// return view;
135+
// }
136+
// }
124137
},
125138
initialize: function() {
126139
this.model = new MongoDBCollection();
127-
this.listenToAndRun(this.parent, 'change:ns', this.onCollectionChanged.bind(this));
140+
NamespaceStore.listen( this.onCollectionChanged.bind(this) );
141+
this.schemaActions = app.appRegistry.getAction('SchemaAction');
142+
// this.listenToAndRun(this.parent, 'change:ns', this.onCollectionChanged.bind(this));
143+
},
144+
render: function() {
145+
this.renderWithTemplate(this);
146+
// render query bar here for now
147+
var queryBarComponent = app.appRegistry.getComponent('App:QueryBar');
148+
ReactDOM.render(React.createElement(queryBarComponent), this.queryByHook('refine-bar-subview'));
128149
},
129150
onTabClicked: function(e) {
130151
e.preventDefault();
131152
e.stopPropagation();
132-
133-
// map tab label to correct view and switch views
134-
var tabToViewMap = {
135-
'DOCUMENTS': 'documentView',
136-
'SCHEMA': 'schemaView',
137-
'EXPLAIN PLAN': 'explainView',
138-
'INDEXES': 'indexView'
139-
};
140153
this.switchView(tabToViewMap[e.target.innerText]);
141154
},
142155
switchView: function(viewStr) {
156+
debug('switching to', viewStr);
143157
// disable all views but the active one
144-
_.each(this._subviews, function(subview) {
145-
subview.visible = false;
146-
});
147-
if (this[viewStr]) {
148-
this[viewStr].visible = true;
149-
}
150158
this.activeView = viewStr;
159+
_.each(_.values(tabToViewMap), function(subview) {
160+
if (!this[subview]) return;
161+
if (subview === viewStr) {
162+
this[viewStr].el.classList.remove('hidden');
163+
} else {
164+
this[subview].el.classList.add('hidden');
165+
}
166+
}.bind(this));
167+
// Temporary hack to generate a resize when the schema is clicked.
168+
if (viewStr === 'schemaView') {
169+
this.schemaActions.resizeMiniCharts();
170+
}
151171
},
152172
onCollectionChanged: function() {
153-
this.ns = this.parent.ns;
173+
this.ns = NamespaceStore.ns;
154174
if (!this.ns) {
155175
this.visible = false;
156176
debug('No active collection namespace so no schema has been requested yet.');
157177
return;
158178
}
159179
this.visible = true;
160180
this.model._id = this.ns;
161-
// Need to keep the global state in sync.
162-
NamespaceStore.ns = this.ns;
163181
this.model.once('sync', this.onCollectionFetched.bind(this));
164182
this.model.fetch();
183+
Action.filterChanged(app.queryOptions.query.serialize());
165184
},
166185
onCollectionFetched: function(model) {
167186
this.switchView(this.activeView);

src/app/home/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ var IdentifyView = require('../identify');
55
var CollectionView = require('./collection');
66
var InstancePropertyView = require('./instance-properties');
77
var CollectionListItemView = require('./collection-list-item');
8+
var NamespaceStore = require('hadron-reflux-store').NamespaceStore;
89
var TourView = require('../tour');
910
var NetworkOptInView = require('../network-optin');
1011
var app = require('ampersand-app');
@@ -141,6 +142,7 @@ var HomeView = View.extend({
141142
}
142143

143144
this.ns = model.getId();
145+
NamespaceStore.ns = ns.ns;
144146
this.updateTitle(model);
145147
this.showNoCollectionsZeroState = false;
146148
this.showDefaultZeroState = false;

src/app/index.js

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,13 @@ var Preferences = require('./models/preferences');
5050
var ApplicationStore = require('hadron-reflux-store').ApplicationStore;
5151
var User = require('./models/user');
5252
var Router = require('./router');
53-
var Statusbar = require('./statusbar');
53+
// var Statusbar = require('./statusbar');
5454
var migrateApp = require('./migrations');
5555
var metricsSetup = require('./metrics');
5656
var metrics = require('mongodb-js-metrics')();
5757

58+
var React = require('react');
59+
var ReactDOM = require('react-dom');
5860
var AutoUpdate = require('../auto-update');
5961

6062
var addInspectElementMenu = require('debug-menu').install;
@@ -254,15 +256,17 @@ var Application = View.extend({
254256
pushState: false,
255257
root: '/'
256258
});
257-
app.statusbar.hide();
259+
var StatusAction = app.appRegistry.getAction('StatusAction');
260+
StatusAction.hide();
258261
},
259262
onFatalError: function(id, err) {
260263
debug('clearing client stall timeout...');
261264
clearTimeout(this.clientStalledTimeout);
262265

263266
console.error('Fatal Error!: ', id, err);
264267
metrics.error(err);
265-
app.statusbar.fatal(err);
268+
var StatusAction = app.appRegistry.getAction('StatusAction');
269+
StatusAction.setMessage(err);
266270
},
267271
// ms we'll wait for a `mongodb-scope-client` instance
268272
// to become readable before giving up and showing
@@ -317,10 +321,13 @@ var Application = View.extend({
317321
});
318322
debug('rendering statusbar...');
319323

320-
this.statusbar = new Statusbar({
321-
el: this.queryByHook('statusbar')
322-
});
323-
this.statusbar.render();
324+
// this.statusbar = new Statusbar({
325+
// el: this.queryByHook('statusbar')
326+
// });
327+
// this.statusbar.render();
328+
329+
this.statusComponent = app.appRegistry.getComponent('App:Status');
330+
ReactDOM.render(React.createElement(this.statusComponent), this.queryByHook('statusbar'));
324331

325332
this.autoUpdate = new AutoUpdate({
326333
el: this.queryByHook('auto-update')
@@ -376,10 +383,13 @@ app.extend({
376383
state.startRouter();
377384
return;
378385
}
379-
380-
app.statusbar.show({
386+
var StatusAction = app.appRegistry.getAction('StatusAction');
387+
StatusAction.configure({
388+
visible: true,
381389
message: 'Retrieving connection details...',
382-
staticSidebar: true
390+
progressbar: true,
391+
progress: 100,
392+
sidebar: true
383393
});
384394

385395
state.connection = new Connection({
@@ -392,9 +402,7 @@ app.extend({
392402
state.onFatalError('fetch connection', err);
393403
return;
394404
}
395-
app.statusbar.show({
396-
message: 'Connecting to MongoDB...'
397-
});
405+
StatusAction.setMessage('Connecting to MongoDB...');
398406

399407
var DataService = require('mongodb-data-service');
400408
app.dataService = new DataService(state.connection)
@@ -434,11 +442,11 @@ app.extend({
434442
}
435443
});
436444

437-
Object.defineProperty(app, 'statusbar', {
438-
get: function() {
439-
return state.statusbar;
440-
}
441-
});
445+
// Object.defineProperty(app, 'statusbar', {
446+
// get: function() {
447+
// return state.statusbar;
448+
// }
449+
// });
442450

443451
Object.defineProperty(app, 'autoUpdate', {
444452
get: function() {

src/app/index.less

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,7 @@
99
@import "documents/index.less";
1010
@import "schema/index.less";
1111
@import "home/index.less";
12-
@import "minicharts/index.less";
13-
@import "refine-view/index.less";
1412
@import "sampling-message/index.less";
15-
@import "statusbar/index.less";
1613
@import "tour/index.less";
1714
@import "sidebar/index.less";
1815
@import "network-optin/index.less";
@@ -25,4 +22,9 @@
2522
@import "metrics/index.less";
2623
@import "./styles/mapbox-gl.css";
2724

25+
// Packages
26+
// @todo don't hard-code these, style manager needs to handle package styles
2827
@import "../internal-packages/crud/styles/crud.less";
28+
@import "../internal-packages/status/styles/index.less";
29+
@import "../internal-packages/query/styles/index.less";
30+
@import "../internal-packages/schema/styles/index.less";

src/app/minicharts/d3fns/few.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,14 @@ var minicharts_d3fns_few = function() {
145145

146146
function chart(selection) {
147147
selection.each(function(data) {
148-
var values = _.pluck(data, 'count');
148+
var values = _.map(data, 'count');
149+
_.each(data, (d, i) => {
150+
data[i].xpos = _.sum(_(data)
151+
.slice(0, i)
152+
.map('count')
153+
.value()
154+
);
155+
});
149156
var sumValues = d3.sum(values);
150157
var maxValue = d3.max(values);
151158
var percentFormat = shared.friendlyPercentFormat(maxValue / sumValues * 100);

0 commit comments

Comments
 (0)