Skip to content

Commit 67bf6cd

Browse files
committed
Merge pull request #134 from 10gen/INT-637_connection-name-default
0.4.0 required fixes
2 parents 7fb49b5 + 9aff345 commit 67bf6cd

24 files changed

+483
-225
lines changed

package.json

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@
5454
"start": "gulp dev",
5555
"release": "gulp release",
5656
"test": "mocha",
57-
"check": "mongodb-js-precommit"
57+
"check": "mongodb-js-precommit",
58+
"fmt": "mongodb-js-fmt src/{**/*.js,*.js}"
5859
},
5960
"pre-commit": [
6061
"check",
@@ -67,10 +68,14 @@
6768
"dependencies": {
6869
"ampersand-form-view": "^5.1.1",
6970
"ampersand-input-view": "^5.0.0",
71+
"ampersand-rest-collection": "^5.0.0",
7072
"debug": "^2.2.0",
7173
"electron-squirrel-startup": "^0.1.2",
72-
"mongodb-connection-model": "0.0.2",
73-
"scout-server": "http://bin.mongodb.org/js/scout-server/v0.2.1/scout-server-0.2.1.tar.gz"
74+
"mongodb-collection-model": "^0.1.0",
75+
"mongodb-connection-model": "^0.0.3",
76+
"mongodb-instance-model": "^0.2.0",
77+
"mongodb-ns": "^1.0.0",
78+
"scout-server": "http://bin.mongodb.org/js/scout-server/v0.2.2/scout-server-0.2.2.tar.gz"
7479
},
7580
"devDependencies": {
7681
"ampersand-app": "^1.0.4",
@@ -114,7 +119,8 @@
114119
"mocha": "^2.2.5",
115120
"moment": "^2.10.3",
116121
"mongodb-extended-json": "^1.3.1",
117-
"mongodb-js-precommit": "^0.1.2",
122+
"mongodb-js-precommit": "^0.2.2",
123+
"mongodb-js-fmt": "^0.0.3",
118124
"mongodb-language-model": "^0.2.1",
119125
"mongodb-schema": "^3.3.0",
120126
"mousetrap": "^1.5.3",
@@ -130,8 +136,7 @@
130136
"raf": "^3.0.0",
131137
"run-sequence": "^1.1.2",
132138
"run-series": "^1.1.2",
133-
"scout-brain": "http://bin.mongodb.org/js/scout-brain/v0.0.2/scout-brain-0.0.2.tar.gz",
134-
"scout-client": "http://bin.mongodb.org/js/scout-client/v0.1.2/scout-client-0.1.2.tar.gz",
139+
"scout-client": "http://bin.mongodb.org/js/scout-client/v0.1.4/scout-client-0.1.4.tar.gz",
135140
"stream-combiner2": "^1.0.2",
136141
"uuid": "^2.0.1",
137142
"vinyl-buffer": "^1.0.0",

src/app.js

Lines changed: 116 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/* eslint no-console:0 */
2+
13
var pkg = require('../package.json');
24
var app = require('ampersand-app');
35
app.extend({
@@ -8,7 +10,9 @@ app.extend({
810
'App Version': pkg.version
911
}
1012
});
11-
require('./bugsnag').listen(app);
13+
14+
var bugsnag = require('./bugsnag');
15+
bugsnag.listen(app);
1216

1317
var _ = require('lodash');
1418
var domReady = require('domready');
@@ -17,6 +21,13 @@ var getOrCreateClient = require('scout-client');
1721
var ViewSwitcher = require('ampersand-view-switcher');
1822
var View = require('ampersand-view');
1923
var localLinks = require('local-links');
24+
25+
var QueryOptions = require('./models/query-options');
26+
var Connection = require('./models/connection');
27+
var MongoDBInstance = require('./models/mongodb-instance');
28+
var Router = require('./router');
29+
var Statusbar = require('./statusbar');
30+
2031
var debug = require('debug')('scout:app');
2132

2233
// Inter-process communication with main process (Electron window)
@@ -78,24 +89,62 @@ var Application = View.extend({
7889
/**
7990
* Enable/Disable features with one global switch
8091
*/
81-
features: 'object'
92+
features: 'object',
93+
clientStartedAt: 'date',
94+
clientStalledTimeout: 'number'
8295
},
8396
events: {
8497
'click a': 'onLinkClick'
8598
},
86-
/**
87-
* We have what we need, we can now start our router and show the appropriate page!
88-
*/
89-
_onDOMReady: function() {
90-
this.el = document.querySelector('#application');
91-
this.render();
99+
onClientReady: function() {
100+
debug('Client ready! Took %dms to become readable',
101+
new Date() - this.clientStartedAt);
102+
103+
debug('clearing client stall timeout...');
104+
clearTimeout(this.clientStalledTimeout);
105+
106+
debug('initializing singleton models... ');
107+
this.queryOptions = new QueryOptions();
108+
this.volatileQueryOptions = new QueryOptions();
109+
this.instance = new MongoDBInstance();
92110

111+
this.startRouter();
112+
},
113+
startRouter: function() {
114+
this.router = new Router();
115+
debug('Listening for page changes from the router...');
93116
this.listenTo(this.router, 'page', this.onPageChange);
94117

118+
debug('Starting router...');
95119
this.router.history.start({
96120
pushState: false,
97121
root: '/'
98122
});
123+
app.statusbar.hide();
124+
},
125+
onFatalError: function(id, err) {
126+
debug('clearing client stall timeout...');
127+
clearTimeout(this.clientStalledTimeout);
128+
129+
console.error('Fatal Error!: ', id, err);
130+
bugsnag.notifyException(err, 'Fatal Error: ' + id);
131+
app.statusbar.fatal(err);
132+
},
133+
// ms we'll wait for a `scout-client` instance
134+
// to become readable before giving up and showing
135+
// a fatal error message.
136+
CLIENT_STALLED_REDLINE: 5 * 1000,
137+
startClientStalledTimer: function() {
138+
this.clientStartedAt = new Date();
139+
140+
debug('Starting client stalled timer to bail in %dms...',
141+
this.CLIENT_STALLED_REDLINE);
142+
143+
this.clientStalledTimeout = setTimeout(function() {
144+
this.onFatalError('client stalled',
145+
new Error('Error connecting to MongoDB. '
146+
+ 'Please reload the page.'));
147+
}.bind(this), this.CLIENT_STALLED_REDLINE);
99148
},
100149
/**
101150
* When you want to go to a different page in the app or just save
@@ -117,15 +166,25 @@ var Application = View.extend({
117166
trigger: !options.silent
118167
});
119168
},
169+
/**
170+
* Called a soon as the DOM is ready so we can
171+
* start showing status indicators as
172+
* quickly as possible.
173+
*/
120174
render: function() {
175+
debug('Rendering app container...');
176+
177+
this.el = document.querySelector('#application');
121178
this.renderWithTemplate(this);
122179
this.pageSwitcher = new ViewSwitcher(this.queryByHook('layout-container'), {
123180
show: function() {
124181
document.scrollTop = 0;
125182
}
126183
});
127-
128-
this.statusbar.el = this.queryByHook('statusbar');
184+
debug('rendering statusbar...');
185+
this.statusbar = new Statusbar({
186+
el: this.queryByHook('statusbar')
187+
});
129188
this.statusbar.render();
130189
},
131190
onPageChange: function(view) {
@@ -153,47 +212,68 @@ var state = new Application({
153212
connection_id: connection_id
154213
});
155214

156-
var QueryOptions = require('./models/query-options');
157-
var Connection = require('./models/connection');
158-
var MongoDBInstance = require('./models/mongodb-instance');
159-
var Router = require('./router');
160-
var Statusbar = require('./statusbar');
161-
162-
function start() {
163-
state.router = new Router();
164-
domReady(state._onDOMReady.bind(state));
165-
}
215+
// @todo (imlucas): Feature flags can be overrideen
216+
// via `window.localStorage`.
217+
var FEATURES = {
218+
querybuilder: true,
219+
'Connect with SSL': false,
220+
'Connect with Kerberos': true,
221+
'Connect with LDAP': false,
222+
'Connect with X.509': false
223+
};
166224

167225
app.extend({
168226
client: null,
227+
// @note (imlucas): Backwards compat for querybuilder
228+
features: FEATURES,
229+
/**
230+
* Check whether a feature flag is currently enabled.
231+
*
232+
* @param {String} id - A key in `FEATURES`.
233+
* @return {Boolean}
234+
*/
235+
isFeatureEnabled: function(id) {
236+
return FEATURES[id] === true;
237+
},
169238
init: function() {
170-
// feature flags
171-
this.features = {
172-
querybuilder: true
173-
};
174-
state.statusbar = new Statusbar();
239+
domReady(function() {
240+
state.render();
241+
242+
if (!connection_id) {
243+
// Not serving a part of the app which uses the client,
244+
// so we can just start everything up now.
245+
state.startRouter();
246+
return;
247+
}
248+
249+
app.statusbar.show('Retrieving connection details...');
175250

176-
if (connection_id) {
177251
state.connection = new Connection({
178252
_id: connection_id
179253
});
180254

181-
182255
debug('looking up connection `%s`...', connection_id);
183256
state.connection.fetch({
184257
success: function() {
185-
debug('got connection `%j`...', state.connection.serialize());
186-
app.client = getOrCreateClient(app.endpoint, state.connection.serialize());
258+
app.statusbar.show('Connection details loaded! Initializing client...');
259+
260+
var endpoint = app.endpoint;
261+
var connection = state.connection.serialize();
262+
263+
app.client = getOrCreateClient(endpoint, connection)
264+
.on('readable', state.onClientReady.bind(state))
265+
.on('error', state.onFatalError.bind(state, 'create client'));
187266

188-
state.queryOptions = new QueryOptions();
189-
state.volatileQueryOptions = new QueryOptions();
190-
state.instance = new MongoDBInstance();
191-
start();
267+
state.startClientStalledTimer();
268+
},
269+
error: function() {
270+
// @todo (imlucas) `ampersand-sync-localforage` currently drops
271+
// the real error so for now just use a generic.
272+
state.onFatalError(state, 'fetch connection',
273+
new Error('Error retrieving connection. Please reload the page.'));
192274
}
193275
});
194-
} else {
195-
start();
196-
}
276+
});
197277
// set up ipc
198278
ipc.on('message', state.onMessageReceived.bind(this));
199279
},

src/bugsnag.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ function beforeNotify(d) {
2828
debug('redacted bugsnag report\n', JSON.stringify(d, null, 2));
2929
}
3030

31+
module.exports = bugsnag;
32+
3133
/**
3234
* Configure bugsnag's api client which attaches a handler to
3335
* `window.onerror` so any uncaught exceptions are trapped and logged

src/connect/auth-fields.js

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,6 @@ module.exports = {
6767
password,
6868
database_name
6969
],
70-
71-
'MONGODB-CR': [
72-
username,
73-
password,
74-
database_name
75-
],
76-
7770
GSSAPI: [
7871
username,
7972
service_name

src/connect/connect-form-view.js

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -18,33 +18,7 @@ var ConnectFormView = FormView.extend({
1818
*/
1919
submitCallback: function(obj) {
2020
debug('form submitted', obj);
21-
22-
var connection = new Connection(obj);
23-
24-
var existingName = this.parent.checkExistingConnection(connection);
25-
if (existingName) {
26-
this.valid = false;
27-
this.setValue('name', existingName);
28-
return;
29-
}
30-
31-
existingName = this.parent.checkExistingName(connection);
32-
if (existingName) {
33-
this.valid = false;
34-
return;
35-
}
36-
37-
app.statusbar.show();
38-
39-
debug('testing credentials are usable...');
40-
connection.test(function(err) {
41-
app.statusbar.hide();
42-
if (err) {
43-
this.parent.onConnectionError(err, connection);
44-
return;
45-
}
46-
this.parent.onConnectionAccepted(connection);
47-
}.bind(this));
21+
this.parent.onFormSubmitted(new Connection(obj));
4822
},
4923
clean: function(obj) {
5024
// clean up the form values here, e.g. conversion to numbers etc.
@@ -73,6 +47,8 @@ var ConnectFormView = FormView.extend({
7347
* These are the default form fields that are always present in the connect dialog. Auth and
7448
* SSL fields are added/removed dynamically, depending on whether the options are expanded or
7549
* collapsed.
50+
*
51+
* @return {Array<InputView>}
7652
*/
7753
fields: function() {
7854
return [
@@ -110,7 +86,7 @@ var ConnectFormView = FormView.extend({
11086
template: require('./input-saveas.jade'),
11187
el: this.parent.queryByHook('saveas-subview'),
11288
name: 'name',
113-
placeholder: 'Connection Name',
89+
placeholder: 'e.g. Shared Dev, Stats Box, PRODUCTION',
11490
required: false
11591
})
11692
];

src/connect/connection.jade

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
li.list-group-item
22
.close-icon(data-hook='close')
33
i.fa.fa-close
4-
a(data-hook='name')
4+
a()
5+
span(data-hook='name')
6+
span(style='padding-left: 4px;',
7+
data-hook='has-auth',
8+
title='This connection has authentication enabled.')
9+
i.fa.fa-lock

0 commit comments

Comments
 (0)