Skip to content

Commit e5de339

Browse files
Thomas Rueckstiesskangas
authored andcommitted
INT-1518 Compass Treasure Hunt for MongoDB World 2016
add treasure hunt feature flag and server detection enable migrations on “dot” versions, enable tracking on data server add missing half of diary page into feature tour add treasure hunt connection “lost temple” emit stage2 event added more stage tracking. secret message under the tree. changed location of treasure. trigger stage8. updated achievement messages. move images, add identify view, put achievements in resource. send email, name to intercom. fix feature tour hint. lots of treasure hunt improvements cannot use app.preferences in migrations! instead of entire explain tab, just hide the tree switcher button use better detection for secret message directly on the tooltips disable show update banner until secret message unlocked switch back to 1.3.0-dev version. deleted unneccessary file. enable “whats new” feature tour in .1 version renamed achievements
1 parent 276ac7b commit e5de339

File tree

28 files changed

+526
-34
lines changed

28 files changed

+526
-34
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,10 @@
128128
"mongodb-explain-plan-model": "^0.2.0",
129129
"mongodb-extended-json": "^1.6.0",
130130
"mongodb-instance-model": "^3.1.2",
131-
"mongodb-js-metrics": "^1.0.0",
131+
"mongodb-js-metrics": "^1.1.1",
132132
"mongodb-language-model": "^0.3.3",
133133
"mongodb-ns": "^1.0.3",
134-
"mongodb-schema": "^4.2.0",
134+
"mongodb-schema": "^4.2.4",
135135
"ms": "^0.7.1",
136136
"ncp": "^2.0.0",
137137
"numeral": "^1.5.3",

src/app/explain-plan/index.jade

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@
5050

5151
.tree-container
5252
div(data-hook='tree-subview')
53+
div(data-hook='treasure-hunt-subview', style='padding-bottom:20px; position:absolute; left:50%; margin-left:-100px;')
54+
svg(id="liberty", height="200", width="200", xmlns="http://www.w3.org/2000/svg", style="stroke:#ddd; fill:#ddd")
55+
image(x="0", y="0", height="200", width="200", xlink:href="./images/treasure-hunt/liberty.svg")
56+
div(style='color:#ddd;font-weight: bold;font-size: 23px;text-transform:uppercase;') X marks the spot
5357

5458
.json-container
5559
.panel.panel-default

src/app/explain-plan/index.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
var View = require('ampersand-view');
22
var State = require('ampersand-state');
33

4+
var $ = require('jquery');
45
var _ = require('lodash');
56
var app = require('ampersand-app');
67
var ExplainPlanModel = require('mongodb-explain-plan-model');
78
var DocumentView = require('../documents/document-list-item');
89
var IndexDefinitionView = require('../indexes/index-definition');
910
var TreeView = require('./tree-view');
1011
var StageModel = require('./stage-model');
12+
var metrics = require('mongodb-js-metrics')();
1113

1214
var electron = require('electron');
1315
var shell = electron.shell;
@@ -35,6 +37,11 @@ module.exports = View.extend({
3537
required: true,
3638
default: false
3739
},
40+
showExplainTree: {
41+
type: 'boolean',
42+
required: true,
43+
default: false
44+
},
3845
// refine bar for explain view
3946
hasRefineBar: ['boolean', true, true],
4047
activeDetailView: {
@@ -77,6 +84,13 @@ module.exports = View.extend({
7784
return 'INDEX';
7885
}
7986
},
87+
treasureHuntClueVisible: {
88+
deps: ['indexMessageType'],
89+
fn: function() {
90+
return (app.isFeatureEnabled('treasureHunt') &&
91+
this.indexMessageType === 'INDEX');
92+
}
93+
},
8094
showWarningTriangle: {
8195
deps: ['indexMessageType'],
8296
fn: function() {
@@ -133,9 +147,17 @@ module.exports = View.extend({
133147
'click i.link': 'linkIconClicked'
134148
},
135149
bindings: {
150+
treasureHuntClueVisible: {
151+
type: 'toggle',
152+
hook: 'treasure-hunt-subview'
153+
},
136154
ns: {
137155
hook: 'ns'
138156
},
157+
showExplainTree: {
158+
type: 'toggle',
159+
hook: 'tree-button'
160+
},
139161
visible: {
140162
type: 'booleanClass',
141163
no: 'hidden'
@@ -218,6 +240,27 @@ module.exports = View.extend({
218240
this.listenTo(this.model, 'sync', this.onModelSynced.bind(this));
219241
this.listenTo(this.parent, 'submit:query', this.onQueryChanged.bind(this));
220242
this.on('change:visible', this.onVisibleChanged.bind(this));
243+
this.showExplainTree = app.isFeatureEnabled('showExplainPlanTab');
244+
},
245+
// entire render method just for treasure hunt, remove afterwards
246+
render: function() {
247+
this.renderWithTemplate(this);
248+
if (app.isFeatureEnabled('treasureHunt')) {
249+
var $main = $(this.query('.main'));
250+
var view = this;
251+
// check if user has scrolled to the bottom of the explain tree
252+
$main.on('scroll', function() {
253+
var scrolledToBottom = ($main.scrollTop() + $main.innerHeight() >= $main[0].scrollHeight - 20);
254+
if (view.indexMessageType === 'INDEX' &&
255+
scrolledToBottom &&
256+
view.activeDetailView === 'tree') {
257+
$main.off('scroll');
258+
debug('found the location!');
259+
// user looked at the bottom of an indexed tree explain plan
260+
metrics.track('Treasure Hunt', 'stage6');
261+
}
262+
});
263+
}
221264
},
222265
onModelSynced: function() {
223266
this.ns = this.model._id;

src/app/home/collection.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,12 @@ var MongoDBCollectionView = View.extend({
164164
this.model.fetch();
165165
},
166166
onCollectionFetched: function(model) {
167+
if (app.isFeatureEnabled('treasureHunt')) {
168+
if (model.getId() === 'news.news') {
169+
// player finds the room with the scrolls (news.news collection)
170+
metrics.track('Treasure Hunt', 'stage3');
171+
}
172+
}
167173
this.switchView(this.activeView);
168174
// track collection information
169175
var metadata = _.omit(model.serialize(), ['_id', 'database',

src/app/home/index.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
var View = require('ampersand-view');
22
var format = require('util').format;
33
var SidebarView = require('../sidebar');
4+
var IdentifyView = require('../identify');
45
var CollectionView = require('./collection');
56
var InstancePropertyView = require('./instance-properties');
67
var CollectionListItemView = require('./collection-list-item');
@@ -12,6 +13,7 @@ var _ = require('lodash');
1213
var debug = require('debug')('mongodb-compass:home');
1314
var toNS = require('mongodb-ns');
1415
var ipc = require('hadron-ipc');
16+
var pkg = require('../../../package.json');
1517

1618
var indexTemplate = require('./index.jade');
1719

@@ -63,6 +65,22 @@ var HomeView = View.extend({
6365
},
6466
render: function() {
6567
this.renderWithTemplate(this);
68+
// treasure hunt enables metrics
69+
if (app.isFeatureEnabled('treasureHunt')) {
70+
app.preferences.trackUsageStatistics = true;
71+
app.preferences.enableFeedbackPanel = true;
72+
app.preferences.trackErrors = true;
73+
// show identify screen if we don't know the user's name/email yet.
74+
if (!app.user.email) {
75+
var identifyView = new IdentifyView();
76+
this.renderSubview(identifyView, this.queryByHook('optin-container'));
77+
}
78+
// don't show feature tour initially in treasure hunt. too easy.
79+
if (pkg.version === '1.3.0-beta.0') {
80+
this.tourClosed();
81+
return;
82+
}
83+
}
6684
if (app.preferences.showFeatureTour) {
6785
this.showTour(false);
6886
} else {
@@ -79,8 +97,10 @@ var HomeView = View.extend({
7997
}
8098
},
8199
showOptIn: function() {
82-
var networkOptInView = new NetworkOptInView();
83-
this.renderSubview(networkOptInView, this.queryByHook('optin-container'));
100+
if (!app.isFeatureEnabled('treasureHunt')) {
101+
var networkOptInView = new NetworkOptInView();
102+
this.renderSubview(networkOptInView, this.queryByHook('optin-container'));
103+
}
84104
},
85105
tourClosed: function() {
86106
app.preferences.unset('showFeatureTour');

src/app/identify/index.jade

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#identifyOptIn.modal.fade(tabindex='-1' role='dialog', data-hook='main-modal')
2+
.modal-dialog
3+
.modal-content
4+
.modal-header
5+
h4.modal-title Welcome, ye ole Swashbuckler!
6+
.modal-body
7+
img(src='./images/treasure-hunt/treasure-map.png' style='width:75%; margin:0 auto; display: block;')
8+
p Before you can enter The Lost Temple and start with the treasure hunt, please tell us a bit about you:
9+
form
10+
ul
11+
li
12+
label
13+
div Your Name
14+
input(type='text', name='name', data-hook='full-name-input')
15+
p.option-description Your name will show up on the leaderboard as you unlock achievements.
16+
li
17+
label
18+
div Email Address
19+
input(type='text', name='email', data-hook='email-input')
20+
p.option-description Use the email address you signed up with for MongoDB World.
21+
li
22+
label
23+
div Twitter Handle (optional)
24+
input(type='text', name='twitter', data-hook='twitter-input')
25+
p.option-description We additionally annouce the winners of the treasure hunt via Twitter.
26+
27+
p Note that while you're connected to this server ("The Lost Temple"), your actions are tracked by us via third party services including intercom, mapbox and bugsnag. Your regular privacy settings apply when you connect to a different server.
28+
29+
.modal-footer
30+
button.btn.btn-cancel(type='button', data-dismiss='modal', data-hook='cancel-button') I'm Too Scared
31+
button.btn.btn-primary(type='button', data-dismiss='modal', data-hook='start-button') Enter The Lost Temple

src/app/identify/index.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
var $ = require('jquery');
2+
var View = require('ampersand-view');
3+
var metrics = require('mongodb-js-metrics')();
4+
var app = require('ampersand-app');
5+
var ipc = require('hadron-ipc');
6+
7+
// var debug = require('debug')('mongodb-compass:identify:index');
8+
9+
module.exports = View.extend({
10+
template: require('./index.jade'),
11+
events: {
12+
'input input[name=name]': 'onNameInputChanged',
13+
'change input[name=name]': 'onNameInputChanged',
14+
'input input[name=email]': 'onEmailInputChanged',
15+
'change input[name=email]': 'onEmailInputChanged',
16+
'input input[name=twitter]': 'onTwitterInputChanged',
17+
'change input[name=twitter]': 'onTwitterInputChanged',
18+
'click [data-hook=start-button]': 'onStartClicked',
19+
'click [data-hook=cancel-button]': 'onCancelClicked'
20+
},
21+
props: {
22+
name: ['string', true, ''],
23+
email: ['string', true, ''],
24+
twitter: ['string', true, '']
25+
},
26+
derived: {
27+
valid: {
28+
deps: ['name', 'email'],
29+
fn: function() {
30+
return Boolean(this.name && this.email.match(/.+\@.+\..+/));
31+
}
32+
}
33+
},
34+
bindings: {
35+
valid: {
36+
type: 'booleanAttribute',
37+
hook: 'start-button',
38+
no: 'disabled'
39+
}
40+
},
41+
render: function() {
42+
this.renderWithTemplate(this);
43+
$(this.queryByHook('main-modal')).modal({
44+
backdrop: 'static',
45+
keyboard: false
46+
});
47+
},
48+
onNameInputChanged: function(evt) {
49+
this.name = evt.target.value;
50+
},
51+
onEmailInputChanged: function(evt) {
52+
this.email = evt.target.value;
53+
},
54+
onTwitterInputChanged: function(evt) {
55+
this.twitter = evt.target.value;
56+
},
57+
onCancelClicked: function() {
58+
// code to close current connection window and open connect dialog
59+
ipc.call('app:show-connect-window');
60+
window.close();
61+
},
62+
onStartClicked: function() {
63+
if (!this.valid) {
64+
return;
65+
}
66+
// set user model, send to intercom/mixpanel
67+
var info = {
68+
name: this.name,
69+
email: this.email,
70+
twitter: this.twitter
71+
};
72+
app.user.save(info);
73+
metrics.resources.get('User').set(info);
74+
metrics.trackers.get('intercom')._updateIntercom();
75+
// stage one, player provided name/email, enters the "Lost Temple"
76+
metrics.track('Treasure Hunt', 'stage1');
77+
}
78+
});

src/app/identify/index.less

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#identifyOptIn {
2+
.modal-body {
3+
ul {
4+
list-style: none;
5+
margin: 30px 0;
6+
}
7+
label {
8+
margin-bottom: 0;
9+
}
10+
p.option-description {
11+
color: @gray4;
12+
font-size: 13px;
13+
}
14+
input {
15+
margin: 0 10px 0 0;
16+
width: 250px;
17+
}
18+
}
19+
}
1.63 MB
Loading

src/app/images/tour/f8.gif

1.85 MB
Loading

0 commit comments

Comments
 (0)