Skip to content

Commit afdfa50

Browse files
committed
app scaffolding + signup, login, logout
1 parent 0ac12aa commit afdfa50

40 files changed

+2150
-34
lines changed

App/Actions/AppActions.js

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
var Dispatcher = require('../Dispatcher');
2+
var AppConstants = require('../Constants/AppConstants');
3+
var assign = require('object-assign');
4+
5+
var AppActions = {
6+
appLaunched: function() {
7+
Dispatcher.dispatch({
8+
actionType: AppConstants.APP_LAUNCHED
9+
});
10+
},
11+
12+
reloadCurrentPath: function() {
13+
Dispatcher.dispatch({
14+
actionType: AppConstants.RELOAD_PATH
15+
});
16+
},
17+
18+
launchRoutePath: function(routePath) {
19+
console.log("Launching! " + routePath);
20+
Dispatcher.dispatch({
21+
actionType: AppConstants.LAUNCH_ROUTE_PATH,
22+
routePath: routePath
23+
});
24+
},
25+
26+
launchExternalURL: function(url) {
27+
console.log("Launching! " + url);
28+
Dispatcher.dispatch({
29+
actionType: AppConstants.OPEN_URL,
30+
url: url
31+
});
32+
},
33+
34+
launchItem: function(props) {
35+
if (props.actionType) {
36+
console.log("Action! " + props.actionType);
37+
Dispatcher.dispatch(props);
38+
}
39+
else if (props.routePath) {
40+
console.log(props.routePath);
41+
this.launchRoutePath(props.routePath);
42+
}
43+
else {
44+
console.log("Unknown launchItem");
45+
}
46+
},
47+
48+
launchRelativeItem: function(currentRoute, item) {
49+
var navItem = assign({}, item); // clone so we can mess with it
50+
51+
if(!navItem.routePath && navItem.replacePath) {
52+
var pieces = currentRoute.routePath.split("/");
53+
pieces[pieces.length-1] = navItem.replacePath;
54+
navItem.routePath = pieces.join('/');
55+
}
56+
if(!navItem.routePath && navItem.subPath) {
57+
navItem.routePath = currentRoute.routePath + "/" + navItem.subPath;
58+
}
59+
navItem.currentRoute = currentRoute;
60+
this.launchItem(navItem);
61+
},
62+
63+
launchNavItem: function(currentRoute, item) {
64+
var navItem = assign({}, item); // clone so we can mess with it
65+
navItem.targetPath = currentRoute.routePath;
66+
this.launchRelativeItem(currentRoute, navItem);
67+
},
68+
69+
goBack: function(navigator) {
70+
var current = navigator.getCurrentRoutes();
71+
var previous = current[0];
72+
if (current.length > 2) {
73+
previous = current[current.length-2];
74+
}
75+
AppActions.launchRoutePath(previous.routePath);
76+
}
77+
78+
};
79+
80+
module.exports = AppActions;

App/Actions/AuthActions.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
var Dispatcher = require('../Dispatcher');
2+
var AppConstants = require('../Constants/AppConstants');
3+
var AuthService = require('../Api/AuthService');
4+
5+
var AuthActions = {
6+
authCallback: function(callback) {
7+
return function(error, data) {
8+
if(callback) callback(error);
9+
10+
if (!error) {
11+
Dispatcher.dispatch({
12+
actionType: AppConstants.LOGIN_USER,
13+
userProps: data.userProps,
14+
token: data.token
15+
});
16+
}
17+
};
18+
},
19+
20+
submitLogin: function(email, password, callback) {
21+
AuthService.login(email, password, this.authCallback(callback));
22+
},
23+
24+
submitSignup: function(email, password, callback) {
25+
AuthService.signup(email, password, this.authCallback(callback));
26+
}
27+
};
28+
29+
module.exports = AuthActions;

App/Api/AuthService.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
var client = require('../Api/HTTPClient')
2+
3+
var UserService = {
4+
parseAccount: function(response) {
5+
if (!response) return null;
6+
7+
var data = {};
8+
data.token = response.token;
9+
data.userProps = {
10+
id: response.id,
11+
locations: []
12+
// TODO: first name, etc?
13+
};
14+
return data;
15+
},
16+
17+
accountCallback: function(callback) {
18+
return function(error, response) {
19+
var data = UserService.parseAccount(response);
20+
callback(error, data);
21+
};
22+
},
23+
24+
signup: function(username, password, callback) {
25+
client.post("api/signup", {username: username, password: password}, UserService.accountCallback(callback));
26+
},
27+
28+
login: function(username, password, callback) {
29+
client.post("api/login", {username: username, password: password}, UserService.accountCallback(callback));
30+
}
31+
};
32+
33+
module.exports = UserService;

App/Api/HTTPClient.js

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// http://visionmedia.github.io/superagent
2+
var superagent = require('superagent');
3+
4+
var Network = require('../Api/Network');
5+
6+
var CurrentUserStore = require('../Stores/CurrentUserStore');
7+
var EnvironmentStore = require('../Stores/EnvironmentStore');
8+
9+
var HTTPClient = {
10+
wrapper: function(inner) {
11+
return function(error, response) {
12+
Network.completed();
13+
14+
if(!inner) return;
15+
// chance to wrap and call original
16+
17+
var parsed = null;
18+
if(response && response.text && response.text.length > 0) {
19+
try {
20+
parsed = JSON.parse(response.text);
21+
}
22+
catch (e) {
23+
parsed = null;
24+
// TODO: some other error?
25+
console.log("HTTPClient could not parse:\n\n" + response.text);
26+
}
27+
}
28+
29+
var errorObj = null;
30+
var valueObj = null;
31+
32+
if (error) {
33+
// error.status => 422
34+
errorObj = {};
35+
if (error.status) {
36+
errorObj.status = error.status; // 422
37+
}
38+
else {
39+
errorObj.status = 520; // Unknown error
40+
}
41+
42+
errorObj.errors = [];
43+
if (parsed && parsed.error) {
44+
errorObj.message = parsed.error
45+
}
46+
if (!errorObj.message) {
47+
errorObj.message = 'Server Error: ' + errorObj.status;
48+
}
49+
console.log("http error (" + errorObj.status + "): " + errorObj.message);
50+
}
51+
else {
52+
valueObj = parsed;
53+
}
54+
inner(errorObj, valueObj);
55+
};
56+
},
57+
58+
addHeaders: function(req) {
59+
// TODO: load version from somewhere
60+
var appVersion = "1.0";
61+
var userAgent = "Sample iPhone v" + appVersion;
62+
var locale = 'en-US';
63+
64+
req = req.accept('application/json');
65+
req = req.type('application/json');
66+
req = req.set('User-Agent', userAgent);
67+
req = req.set('X-CLIENT-VERSION', appVersion);
68+
req = req.set('X-Sample-User-Agent', userAgent);
69+
req = req.set('X-Client-Application', apiKey);
70+
req = req.set('X-LOCALE', locale);
71+
72+
var currentUser = CurrentUserStore.get();
73+
if (currentUser && currentUser.getToken()) {
74+
req = req.set('Authorization', 'Bearer ' + currentUser.getToken());
75+
}
76+
77+
// if (currentUser && currentUser.data.guid) {
78+
// req = req.set('X-GUID', currentUser.data.guid);
79+
// }
80+
// if (currentUser && currentUser.data.ab_decision_group_id) {
81+
// req = req.set('X-AB-DECISION-GROUP-ID', currentUser.data.ab_decision_group_id.toString());
82+
// }
83+
// if (currentUser && currentUser.data.ab_decision) {
84+
// req = req.set('X-AB-DECISION', currentUser.data.ab_decision);
85+
// }
86+
87+
return req;
88+
},
89+
90+
fetch: function(req, callback) {
91+
req = this.addHeaders(req);
92+
Network.started();
93+
req.end(this.wrapper(callback));
94+
},
95+
96+
url: function(path) {
97+
var host = EnvironmentStore.get().getApiHost();
98+
return host + "/" + path;
99+
},
100+
101+
post: function(path, values, callback) {
102+
var req = superagent.post(this.url(path));
103+
if (values) {
104+
req = req.send(values);
105+
}
106+
this.fetch(req, callback);
107+
},
108+
109+
put: function(path, values, callback) {
110+
var req = superagent.put(this.url(path));
111+
if (values) {
112+
req = req.send(values);
113+
}
114+
this.fetch(req, callback);
115+
},
116+
117+
118+
get: function(path, params, callback) {
119+
var req = superagent.get(this.url(path));
120+
if (params) {
121+
req = req.query(params);
122+
}
123+
this.fetch(req, callback);
124+
}
125+
};
126+
127+
module.exports = HTTPClient;

App/Api/Network.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
var Dispatcher = require('../Dispatcher');
2+
var AppConstants = require('../Constants/AppConstants');
3+
4+
var _httpCount = 0; // TODO: immutable?
5+
6+
var Network = {
7+
onThread: function(callback) {
8+
// TODO: should this be requestAnimationFrame?
9+
global.setTimeout(callback, 0);
10+
},
11+
12+
started: function() {
13+
this.onThread(function() {
14+
if (_httpCount < 0) _httpCount = 0;
15+
_httpCount++;
16+
if (_httpCount == 1) {
17+
Dispatcher.dispatch({
18+
actionType: AppConstants.NETWORK_ACTIVITY,
19+
isActive: true
20+
});
21+
}
22+
});
23+
},
24+
completed: function() {
25+
this.onThread(function() {
26+
_httpCount--;
27+
if (_httpCount < 0) _httpCount = 0;
28+
if (_httpCount === 0) {
29+
Dispatcher.dispatch({
30+
actionType: AppConstants.NETWORK_ACTIVITY,
31+
isActive: false
32+
});
33+
}
34+
});
35+
}
36+
};
37+
38+
module.exports = Network;

0 commit comments

Comments
 (0)