forked from OpenNeo/impress
username form, backed by localstorage for guests; not yet backed by db for logged-in users
This commit is contained in:
parent
72b7ce1ac6
commit
8288b8a10d
5 changed files with 145 additions and 28 deletions
|
@ -54,11 +54,40 @@
|
|||
}
|
||||
};
|
||||
|
||||
var ImpressUser = (function() {
|
||||
var userSignedIn = ($('meta[name=user-signed-in]').attr('content') === 'true');
|
||||
if (userSignedIn) {
|
||||
return {
|
||||
// TODO
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
_key: "guestNeopetsUsernames",
|
||||
_setNeopetsUsernames: function(usernames) {
|
||||
localStorage.setItem(this._key, JSON.stringify(usernames));
|
||||
},
|
||||
addNeopetsUsername: function(username) {
|
||||
this._setNeopetsUsernames(this.getNeopetsUsernames().concat([username]));
|
||||
},
|
||||
removeNeopetsUsername: function(username) {
|
||||
this._setNeopetsUsernames(this.getNeopetsUsernames().filter(function(u) {
|
||||
return u !== username;
|
||||
}));
|
||||
},
|
||||
getNeopetsUsernames: function() {
|
||||
return JSON.parse(localStorage.getItem(this._key)) || [];
|
||||
}
|
||||
};
|
||||
}
|
||||
})();
|
||||
|
||||
var Modeling = {
|
||||
_customizationsByPetId: {},
|
||||
_customizations: [],
|
||||
_itemsById: {},
|
||||
_items: [],
|
||||
_usersComponent: {setState: function() {}},
|
||||
_neopetsUsernamesPresenceMap: {},
|
||||
_addCustomization: function(customization) {
|
||||
// Set all equipped, interesting items' statuses as success and cross
|
||||
// them off the list.
|
||||
|
@ -78,7 +107,7 @@
|
|||
});
|
||||
this._customizationsByPetId[customization.custom_pet.name] = customization;
|
||||
this._customizations = this._buildCustomizations();
|
||||
this._update();
|
||||
this._updateCustomizations();
|
||||
},
|
||||
_addNewCustomization: function(customization) {
|
||||
customization.loadingForItemId = null;
|
||||
|
@ -127,37 +156,42 @@
|
|||
console.error("couldn't load user %s's customizations", neopiaUserId);
|
||||
});
|
||||
},
|
||||
_loadManyUsersCustomizations: function(neopiaUserIds) {
|
||||
return neopiaUserIds.map(this._loadUserCustomizations.bind(this));
|
||||
},
|
||||
_startLoading: function(neopiaPetId, itemId) {
|
||||
var customization = this._customizationsByPetId[neopiaPetId];
|
||||
customization.loadingForItemId = itemId;
|
||||
customization.statusByItemId[itemId] = "loading";
|
||||
this._update();
|
||||
this._updateCustomizations();
|
||||
},
|
||||
_stopLoading: function(neopiaPetId, itemId, status) {
|
||||
var customization = this._customizationsByPetId[neopiaPetId];
|
||||
customization.loadingForItemId = null;
|
||||
customization.statusByItemId[itemId] = status;
|
||||
this._update();
|
||||
this._updateCustomizations();
|
||||
},
|
||||
_update: function() {
|
||||
var customizations = this._customizations;
|
||||
_updateCustomizations: function() {
|
||||
var neopetsUsernamesPresenceMap = this._neopetsUsernamesPresenceMap;
|
||||
var liveCustomizations = this._customizations.filter(function(c) {
|
||||
return neopetsUsernamesPresenceMap[c.custom_pet.owner];
|
||||
});
|
||||
this._items.forEach(function(item) {
|
||||
var filteredCustomizations = customizations.filter(function(c) {
|
||||
var filteredCustomizations = liveCustomizations.filter(function(c) {
|
||||
return item.missingBodyIdsPresenceMap[c.custom_pet.body_id];
|
||||
});
|
||||
item.component.setState({customizations: filteredCustomizations});
|
||||
});
|
||||
},
|
||||
_updateUsernames: function() {
|
||||
var usernames = Object.keys(this._neopetsUsernamesPresenceMap);
|
||||
this._usersComponent.setState({usernames: usernames});
|
||||
},
|
||||
init: function($) {
|
||||
Neopia.init();
|
||||
this._createItems($);
|
||||
// TODO: use user prefs, silly!
|
||||
var search = document.location.search;
|
||||
var users = search.indexOf('=') >= 0 ? search.split('=')[1].split(',') : '';
|
||||
this._loadManyUsersCustomizations(users);
|
||||
var usersEl = $('#modeling-neopets-users');
|
||||
this._usersComponent = React.renderComponent(<NeopetsUsernamesForm />,
|
||||
usersEl.get(0));
|
||||
var usernames = ImpressUser.getNeopetsUsernames();
|
||||
usernames.forEach(this.addUsername.bind(this));
|
||||
},
|
||||
model: function(neopiaPetId, itemId) {
|
||||
var oldCustomization = this._customizationsByPetId[neopiaPetId];
|
||||
|
@ -181,6 +215,22 @@
|
|||
.fail(function() {
|
||||
Modeling._stopLoading(neopiaPetId, itemId, "error");
|
||||
});
|
||||
},
|
||||
addUsername: function(username) {
|
||||
if (typeof this._neopetsUsernamesPresenceMap[username] === 'undefined') {
|
||||
this._neopetsUsernamesPresenceMap[username] = true;
|
||||
ImpressUser.addNeopetsUsername(username);
|
||||
this._loadUserCustomizations(username);
|
||||
this._updateUsernames();
|
||||
}
|
||||
},
|
||||
removeUsername: function(username) {
|
||||
if (this._neopetsUsernamesPresenceMap[username]) {
|
||||
delete this._neopetsUsernamesPresenceMap[username];
|
||||
ImpressUser.removeNeopetsUsername(username);
|
||||
this._updateCustomizations();
|
||||
this._updateUsernames();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -195,7 +245,7 @@
|
|||
item={item}
|
||||
key={customization.custom_pet.name} />;
|
||||
}
|
||||
var sortedCustomizations = this.state.customizations.sort(function(a, b) {
|
||||
var sortedCustomizations = this.state.customizations.slice(0).sort(function(a, b) {
|
||||
var aName = a.custom_pet.name.toLowerCase();
|
||||
var bName = b.custom_pet.name.toLowerCase();
|
||||
if (aName < bName) return -1;
|
||||
|
@ -243,5 +293,43 @@
|
|||
}
|
||||
});
|
||||
|
||||
var NeopetsUsernamesForm = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {usernames: [], newUsername: ""};
|
||||
},
|
||||
render: function() {
|
||||
function buildUsernameItem(username) {
|
||||
return <NeopetsUsernameItem username={username} key={username} />;
|
||||
}
|
||||
return <div>
|
||||
<ul>{this.state.usernames.slice(0).sort().map(buildUsernameItem)}</ul>
|
||||
<form onSubmit={this.handleSubmit}>
|
||||
<input type="text" placeholder="neopets username"
|
||||
onChange={this.handleChange}
|
||||
value={this.state.newUsername} />
|
||||
<button type="submit">add</button></form></div>;
|
||||
},
|
||||
handleChange: function(e) {
|
||||
this.setState({newUsername: e.target.value});
|
||||
},
|
||||
handleSubmit: function(e) {
|
||||
e.preventDefault();
|
||||
this.state.newUsername = $.trim(this.state.newUsername);
|
||||
if (this.state.newUsername.length) {
|
||||
Modeling.addUsername(this.state.newUsername);
|
||||
this.setState({newUsername: ""});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var NeopetsUsernameItem = React.createClass({
|
||||
render: function() {
|
||||
return <li>{this.props.username} <button onClick={this.handleClick}>×</button></li>
|
||||
},
|
||||
handleClick: function(e) {
|
||||
Modeling.removeUsername(this.props.username);
|
||||
}
|
||||
});
|
||||
|
||||
Modeling.init($);
|
||||
})(jQuery);
|
||||
|
|
|
@ -144,24 +144,29 @@ body.outfits-new
|
|||
font-style: italic
|
||||
margin-bottom: .5em
|
||||
|
||||
#newest-modeled-items
|
||||
text-align: center
|
||||
#modeling-neopets-users
|
||||
float: right
|
||||
font-size: 85%
|
||||
margin-top: -5px
|
||||
max-width: 55%
|
||||
text-align: right
|
||||
|
||||
.object
|
||||
margin: 2px
|
||||
padding: 0
|
||||
width: 80px
|
||||
ul, li, form
|
||||
display: inline-block
|
||||
|
||||
.name
|
||||
display: none
|
||||
li
|
||||
+border-radius(6px)
|
||||
border: 1px solid $soft-border-color
|
||||
line-height: 1
|
||||
margin: 0 4px
|
||||
padding: 2px 4px 2px 8px
|
||||
|
||||
img
|
||||
margin: 0
|
||||
button
|
||||
+reset-awesome-button
|
||||
margin-left: 6px
|
||||
|
||||
.nc-icon
|
||||
right: 0
|
||||
|
||||
#newest-unmodeled-items
|
||||
clear: both
|
||||
list-style: none
|
||||
|
||||
> li
|
||||
|
@ -264,7 +269,24 @@ body.outfits-new
|
|||
.message
|
||||
font-style: italic
|
||||
font-size: 85%
|
||||
|
||||
|
||||
#newest-modeled-items
|
||||
text-align: center
|
||||
|
||||
.object
|
||||
margin: 2px
|
||||
padding: 0
|
||||
width: 80px
|
||||
|
||||
.name
|
||||
display: none
|
||||
|
||||
img
|
||||
margin: 0
|
||||
|
||||
.nc-icon
|
||||
right: 0
|
||||
|
||||
#latest-contribution
|
||||
+subtle-banner
|
||||
|
||||
|
|
|
@ -75,6 +75,8 @@ class OutfitsController < ApplicationController
|
|||
@latest_contribution = Contribution.recent.first
|
||||
Contribution.preload_contributeds_and_parents([@latest_contribution])
|
||||
end
|
||||
|
||||
@neopets_usernames = user_signed_in? ? current_user.neopets_usernames : []
|
||||
end
|
||||
|
||||
def show
|
||||
|
|
|
@ -89,6 +89,10 @@ class User < ActiveRecord::Base
|
|||
owned ? ClosetList::NullOwned.new(self) : ClosetList::NullWanted.new(self)
|
||||
end
|
||||
|
||||
def neopets_usernames
|
||||
[neopets_username]
|
||||
end
|
||||
|
||||
def self.find_or_create_from_remote_auth_data(user_data)
|
||||
user = find_or_initialize_by_remote_id_and_auth_server_id(
|
||||
user_data['id'],
|
||||
|
|
|
@ -76,6 +76,7 @@
|
|||
-# TODO: i18n all the things
|
||||
-# TODO: cache this entire block? or just request newest items every time?
|
||||
- if @newest_unmodeled_items.present?
|
||||
#modeling-neopets-users{'data-usernames' => @neopets_usernames.to_json}
|
||||
%h3= t '.newest_items.unmodeled.header'
|
||||
%ul#newest-unmodeled-items
|
||||
- @newest_unmodeled_items.each do |item|
|
||||
|
|
Loading…
Reference in a new issue