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 = {
|
var Modeling = {
|
||||||
_customizationsByPetId: {},
|
_customizationsByPetId: {},
|
||||||
_customizations: [],
|
_customizations: [],
|
||||||
_itemsById: {},
|
_itemsById: {},
|
||||||
_items: [],
|
_items: [],
|
||||||
|
_usersComponent: {setState: function() {}},
|
||||||
|
_neopetsUsernamesPresenceMap: {},
|
||||||
_addCustomization: function(customization) {
|
_addCustomization: function(customization) {
|
||||||
// Set all equipped, interesting items' statuses as success and cross
|
// Set all equipped, interesting items' statuses as success and cross
|
||||||
// them off the list.
|
// them off the list.
|
||||||
|
@ -78,7 +107,7 @@
|
||||||
});
|
});
|
||||||
this._customizationsByPetId[customization.custom_pet.name] = customization;
|
this._customizationsByPetId[customization.custom_pet.name] = customization;
|
||||||
this._customizations = this._buildCustomizations();
|
this._customizations = this._buildCustomizations();
|
||||||
this._update();
|
this._updateCustomizations();
|
||||||
},
|
},
|
||||||
_addNewCustomization: function(customization) {
|
_addNewCustomization: function(customization) {
|
||||||
customization.loadingForItemId = null;
|
customization.loadingForItemId = null;
|
||||||
|
@ -127,37 +156,42 @@
|
||||||
console.error("couldn't load user %s's customizations", neopiaUserId);
|
console.error("couldn't load user %s's customizations", neopiaUserId);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
_loadManyUsersCustomizations: function(neopiaUserIds) {
|
|
||||||
return neopiaUserIds.map(this._loadUserCustomizations.bind(this));
|
|
||||||
},
|
|
||||||
_startLoading: function(neopiaPetId, itemId) {
|
_startLoading: function(neopiaPetId, itemId) {
|
||||||
var customization = this._customizationsByPetId[neopiaPetId];
|
var customization = this._customizationsByPetId[neopiaPetId];
|
||||||
customization.loadingForItemId = itemId;
|
customization.loadingForItemId = itemId;
|
||||||
customization.statusByItemId[itemId] = "loading";
|
customization.statusByItemId[itemId] = "loading";
|
||||||
this._update();
|
this._updateCustomizations();
|
||||||
},
|
},
|
||||||
_stopLoading: function(neopiaPetId, itemId, status) {
|
_stopLoading: function(neopiaPetId, itemId, status) {
|
||||||
var customization = this._customizationsByPetId[neopiaPetId];
|
var customization = this._customizationsByPetId[neopiaPetId];
|
||||||
customization.loadingForItemId = null;
|
customization.loadingForItemId = null;
|
||||||
customization.statusByItemId[itemId] = status;
|
customization.statusByItemId[itemId] = status;
|
||||||
this._update();
|
this._updateCustomizations();
|
||||||
},
|
},
|
||||||
_update: function() {
|
_updateCustomizations: function() {
|
||||||
var customizations = this._customizations;
|
var neopetsUsernamesPresenceMap = this._neopetsUsernamesPresenceMap;
|
||||||
|
var liveCustomizations = this._customizations.filter(function(c) {
|
||||||
|
return neopetsUsernamesPresenceMap[c.custom_pet.owner];
|
||||||
|
});
|
||||||
this._items.forEach(function(item) {
|
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];
|
return item.missingBodyIdsPresenceMap[c.custom_pet.body_id];
|
||||||
});
|
});
|
||||||
item.component.setState({customizations: filteredCustomizations});
|
item.component.setState({customizations: filteredCustomizations});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
_updateUsernames: function() {
|
||||||
|
var usernames = Object.keys(this._neopetsUsernamesPresenceMap);
|
||||||
|
this._usersComponent.setState({usernames: usernames});
|
||||||
|
},
|
||||||
init: function($) {
|
init: function($) {
|
||||||
Neopia.init();
|
Neopia.init();
|
||||||
this._createItems($);
|
this._createItems($);
|
||||||
// TODO: use user prefs, silly!
|
var usersEl = $('#modeling-neopets-users');
|
||||||
var search = document.location.search;
|
this._usersComponent = React.renderComponent(<NeopetsUsernamesForm />,
|
||||||
var users = search.indexOf('=') >= 0 ? search.split('=')[1].split(',') : '';
|
usersEl.get(0));
|
||||||
this._loadManyUsersCustomizations(users);
|
var usernames = ImpressUser.getNeopetsUsernames();
|
||||||
|
usernames.forEach(this.addUsername.bind(this));
|
||||||
},
|
},
|
||||||
model: function(neopiaPetId, itemId) {
|
model: function(neopiaPetId, itemId) {
|
||||||
var oldCustomization = this._customizationsByPetId[neopiaPetId];
|
var oldCustomization = this._customizationsByPetId[neopiaPetId];
|
||||||
|
@ -181,6 +215,22 @@
|
||||||
.fail(function() {
|
.fail(function() {
|
||||||
Modeling._stopLoading(neopiaPetId, itemId, "error");
|
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}
|
item={item}
|
||||||
key={customization.custom_pet.name} />;
|
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 aName = a.custom_pet.name.toLowerCase();
|
||||||
var bName = b.custom_pet.name.toLowerCase();
|
var bName = b.custom_pet.name.toLowerCase();
|
||||||
if (aName < bName) return -1;
|
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($);
|
Modeling.init($);
|
||||||
})(jQuery);
|
})(jQuery);
|
||||||
|
|
|
@ -144,24 +144,29 @@ body.outfits-new
|
||||||
font-style: italic
|
font-style: italic
|
||||||
margin-bottom: .5em
|
margin-bottom: .5em
|
||||||
|
|
||||||
#newest-modeled-items
|
#modeling-neopets-users
|
||||||
text-align: center
|
float: right
|
||||||
|
font-size: 85%
|
||||||
|
margin-top: -5px
|
||||||
|
max-width: 55%
|
||||||
|
text-align: right
|
||||||
|
|
||||||
.object
|
ul, li, form
|
||||||
margin: 2px
|
display: inline-block
|
||||||
padding: 0
|
|
||||||
width: 80px
|
|
||||||
|
|
||||||
.name
|
li
|
||||||
display: none
|
+border-radius(6px)
|
||||||
|
border: 1px solid $soft-border-color
|
||||||
|
line-height: 1
|
||||||
|
margin: 0 4px
|
||||||
|
padding: 2px 4px 2px 8px
|
||||||
|
|
||||||
img
|
button
|
||||||
margin: 0
|
+reset-awesome-button
|
||||||
|
margin-left: 6px
|
||||||
|
|
||||||
.nc-icon
|
|
||||||
right: 0
|
|
||||||
|
|
||||||
#newest-unmodeled-items
|
#newest-unmodeled-items
|
||||||
|
clear: both
|
||||||
list-style: none
|
list-style: none
|
||||||
|
|
||||||
> li
|
> li
|
||||||
|
@ -264,7 +269,24 @@ body.outfits-new
|
||||||
.message
|
.message
|
||||||
font-style: italic
|
font-style: italic
|
||||||
font-size: 85%
|
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
|
#latest-contribution
|
||||||
+subtle-banner
|
+subtle-banner
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,8 @@ class OutfitsController < ApplicationController
|
||||||
@latest_contribution = Contribution.recent.first
|
@latest_contribution = Contribution.recent.first
|
||||||
Contribution.preload_contributeds_and_parents([@latest_contribution])
|
Contribution.preload_contributeds_and_parents([@latest_contribution])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@neopets_usernames = user_signed_in? ? current_user.neopets_usernames : []
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
|
|
@ -89,6 +89,10 @@ class User < ActiveRecord::Base
|
||||||
owned ? ClosetList::NullOwned.new(self) : ClosetList::NullWanted.new(self)
|
owned ? ClosetList::NullOwned.new(self) : ClosetList::NullWanted.new(self)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def neopets_usernames
|
||||||
|
[neopets_username]
|
||||||
|
end
|
||||||
|
|
||||||
def self.find_or_create_from_remote_auth_data(user_data)
|
def self.find_or_create_from_remote_auth_data(user_data)
|
||||||
user = find_or_initialize_by_remote_id_and_auth_server_id(
|
user = find_or_initialize_by_remote_id_and_auth_server_id(
|
||||||
user_data['id'],
|
user_data['id'],
|
||||||
|
|
|
@ -76,6 +76,7 @@
|
||||||
-# TODO: i18n all the things
|
-# TODO: i18n all the things
|
||||||
-# TODO: cache this entire block? or just request newest items every time?
|
-# TODO: cache this entire block? or just request newest items every time?
|
||||||
- if @newest_unmodeled_items.present?
|
- if @newest_unmodeled_items.present?
|
||||||
|
#modeling-neopets-users{'data-usernames' => @neopets_usernames.to_json}
|
||||||
%h3= t '.newest_items.unmodeled.header'
|
%h3= t '.newest_items.unmodeled.header'
|
||||||
%ul#newest-unmodeled-items
|
%ul#newest-unmodeled-items
|
||||||
- @newest_unmodeled_items.each do |item|
|
- @newest_unmodeled_items.each do |item|
|
||||||
|
|
Loading…
Reference in a new issue