modeling hub

This commit is contained in:
Emi Matchu 2012-08-06 21:15:31 -04:00
parent 2435c7f7e9
commit 72237f225c
10 changed files with 432 additions and 149 deletions

View file

@ -87,13 +87,18 @@ class ItemsController < ApplicationController
params[:species]
)
end
unless @pet_type
raise ActiveRecord::RecordNotFound, 'Pet type not found'
end
@items = @pet_type.needed_items.alphabetize
assign_closeted!
@pet_name = params[:name]
render :layout => 'application'
respond_to do |format|
format.html { @pet_name = params[:name] ; render :layout => 'application' }
format.json { render :json => @items }
end
end
protected

View file

@ -4,12 +4,6 @@ class PetsController < ApplicationController
rescue_from Pet::DownloadError, :with => :pet_download_error
cache_sweeper :user_sweeper
DESTINATIONS = {
'needed_items' => '?',
'root' => '#',
'wardrobe' => '#'
}
def load
if params[:name] == '!'
@ -25,15 +19,12 @@ class PetsController < ApplicationController
end
respond_to do |format|
format.html do
destination = params[:destination] || params[:origin]
destination = 'root' unless DESTINATIONS[destination]
query_joiner = DESTINATIONS[destination]
path = send("#{destination}_path") + query_joiner + @pet.wardrobe_query
path = destination + @pet.wardrobe_query
redirect_to path
end
format.json do
render :json => points
render :json => {:points => points, :query => @pet.wardrobe_query}
end
end
end
@ -41,6 +32,14 @@ class PetsController < ApplicationController
protected
def destination
case (params[:destination] || params[:origin])
when 'wardrobe' then wardrobe_path + '#'
when 'needed_items' then needed_items_path + '?'
else root_path + '#'
end
end
def pet_not_found
pet_load_error :long_message => 'Could not find any pet by that name. Did you spell it correctly?',
:short_message => 'Pet not found',
@ -73,7 +72,7 @@ class PetsController < ApplicationController
end
format.json do
render :text => options[:short_message], :status => options[:status]
render :text => options[:long_message], :status => options[:status]
end
end
end

View file

@ -51,25 +51,20 @@ module ItemsHelper
def closet_list_verb(owned)
ClosetHanger.verb(:you, owned)
end
def owned_icon
image_tag 'owned.png', :title => 'You own this', :alt => 'Own'
end
def wanted_icon
image_tag 'wanted.png', :title => 'You want this', :alt => 'Want'
end
def closeted_icons_for(item)
content = ''.html_safe
if item.owned?
content << image_tag(
'owned.png',
:title => 'You own this',
:alt => 'Own'
)
end
if item.wanted?
content << image_tag(
'wanted.png',
:title => 'You want this',
:alt => 'Want'
)
end
content << owned_icon if item.owned?
content << wanted_icon if item.wanted?
content_tag :div, content, :class => 'closeted-icons'
end
@ -77,9 +72,14 @@ module ItemsHelper
def list_zones(zones, method=:label)
zones.sort { |x,y| x.label <=> y.label }.map(&method).join(', ')
end
def nc_icon
image_tag 'nc.png', :title => 'NC Mall Item', :alt => 'NC',
:class => 'nc-icon'
end
def nc_icon_for(item)
image_tag 'nc.png', :title => 'NC Mall Item', :alt => 'NC', :class => 'nc-icon' if item.nc?
nc_icon if item.nc?
end
def neoitems_url_for(item)

View file

@ -164,7 +164,8 @@ class Item < ActiveRecord::Base
:zones_restrict => zones_restrict,
:rarity_index => rarity_index,
:owned => owned?,
:wanted => wanted?
:wanted => wanted?,
:nc => nc?
}
end

View file

@ -1,9 +1,71 @@
body.pets-bulk
text-align: center
#needed-items-form, #bulk-pets-form
text-align: center
#needed-items-form
#needed-items-pet
border-top: 1px solid $soft-border-color
display: none
margin-top: 1em
padding-top: 1em
h4
font-size: 150%
margin-bottom: .5em
#needed-items-reload
+inline-block
font-size: 12px
margin-left: 1em
vertical-align: middle
#needed-items-alert
display: none
margin-top: .5em
#needed-items-pet-thumbnail
height: 50px
width: 50px
#needed-items-pet-items
li.owned
background: $module-bg-color
border: 1px solid $module-border-color
.object-owned
color: $soft-text-color
display: block
font-size: 75%
font-style: italic
padding-bottom: .25em
&.loading-pet, &.loading-items
#needed-items-pet-name-field
background:
image: image-url("loading.gif")
position: center right
repeat: no-repeat
#needed-items-pet-items
+opacity(.50)
&.loading-pet
#needed-items-pet h4
+opacity(.50)
&.loaded
#needed-items-pet
display: block
&.failed
#needed-items-alert
display: block
#bulk-pets-form
textarea, div
+inline-block
border-top: 1px solid $module-border-color
margin-top: 12px
padding-top: 12px
textarea
+inline-block
@extend input[type=text]
@ -14,7 +76,7 @@ body.pets-bulk
resize: none
ul
list-style: none
margin-bottom: 1em
margin-top: 1em
li
+inline-block
background: #eee

View file

@ -62,7 +62,7 @@
= image_tag 'http://images.neopets.com/items/mall_ac_garland_spotlight.gif'
%h3
%a{:href => bulk_pets_path}
Modeling
Modeling Hub
%div
%h4 Found something?
%p

View file

@ -1,33 +1,74 @@
- unless user_signed_in?
%p.warning
= link_to 'You are not logged in!', login_path(:return_to => bulk_pets_path)
We award points for each new contribution to our database, and we don't want
you to miss out, since our users have made the Dress to Impress database
what it is today. Thanks for all your hard work!
%p.noscript
Note that submitting pets in bulk requires Javascript.
%p.script-only
We like to make it as easy as possible for you to contribute, so we thought
this might help!
%strong
Type a pet's name in the box below, and we'll
start loading it the moment you press enter!
If you're a power-user,
you can even submit a whole list at once &mdash; just put one pet per line, and
copy-paste it into the box. We do the rest!
%p
%strong
Thanks for all your hard work!
= form_tag load_pet_path, :id => 'bulk-pets-form' do
= origin_tag bulk_pets_path
%span.noscript
%input{:name => "name", :type => "text"}/
%input{:type => "submit", :value => "Load pet"}/
%span.script-only
%ul
%textarea
%button#bulk-pets-form-add{:type => "button"} Add
%button#bulk-pets-form-clear{:type => "button"} Clear
- title 'Modeling Hub'
- cache do
= form_tag load_pet_path, :id => 'needed-items-form' do
%h3 Looking for ways to contribute?
%p
Enter your pet's name below and we'll tell you what items you can help us
model. Thanks for your help!
= origin_tag bulk_pets_path
= destination_tag 'needed_items'
%input#needed-items-pet-name-field{:type => "text", :name => "name"}/
%input{:type => "submit", :value => "Submit"}/
#needed-items-alert.alert
#needed-items-pet.script-only
%h4
%img#needed-items-pet-thumbnail.inline-image
Items
%span#needed-items-pet-name
can model
%button#needed-items-reload Reload
%ul#needed-items-pet-items
= form_tag load_pet_path, :id => 'bulk-pets-form' do
%h3 Model pets in bulk
%p
Got a lot of pets to model? Just keep typing them into the box below, or
even paste in a whole list of names, one name per line. Thanks for your
help!
= origin_tag bulk_pets_path
%div.noscript
%input{:name => "name", :type => "text"}/
%input{:type => "submit", :value => "Load pet"}/
%div.script-only
%textarea
%button#bulk-pets-form-add{:type => "button"} Add
%button#bulk-pets-form-clear{:type => "button"} Clear
%ul
%script#item-template{:type => 'text/x-jquery-tmpl'}
%li{:class => 'object{{if owned}} owned{{/if}}'}
= link_to item_path(':id').sub(':id', '${id}') do
%img{:src => '${thumbnail_url}', :alt => '${description}', :title => '${description}'}
%span.name ${name}
{{if nc}}
= nc_icon
{{/if}}
.closeted-icons
{{if owned}}
= owned_icon
{{/if}}
{{if wanted}}
= wanted_icon
{{/if}}
{{if owned}}
%span.object-owned You own this item
{{/if}}
- content_for :javascripts do
= include_javascript_libraries :jquery
= include_javascript_libraries :jquery, :jquery_tmpl
= include_javascripts :bulk_pets_package

View file

@ -44,7 +44,7 @@ OpenneoImpressItems::Application.routes.draw do |map|
match '/users/current-user/outfits' => 'outfits#index', :as => :current_user_outfits
match '/pets/load' => 'pets#load', :method => :post, :as => :load_pet
match '/pets/bulk' => 'pets#bulk', :as => :bulk_pets
match '/modeling' => 'pets#bulk', :as => :bulk_pets
match '/login' => 'sessions#new', :as => :login
match '/logout' => 'sessions#destroy', :as => :logout

View file

@ -1,74 +1,177 @@
var form = $('#bulk-pets-form'),
queue_el = form.find('ul'),
names_el = form.find('textarea'),
add_el = $('#bulk-pets-form-add'),
clear_el = $('#bulk-pets-form-clear'),
bulk_load_queue;
var DEBUG = (document.location.search == '?debug');
$(document.body).addClass('js');
bulk_load_queue = new (function BulkLoadQueue() {
var pets = [],
standard_pet_el = $('<li/>'),
url = form.attr('action') + '.json';
standard_pet_el.append('<img/>').append($('<span/>', {'class': 'name'}))
.append($('<span/>', {'class': 'response', text: 'Waiting...'}));
/* Needed items form */
(function () {
var UI = {};
UI.form = $('#needed-items-form');
UI.alert = $('#needed-items-alert');
UI.pet_name_field = $('#needed-items-pet-name-field');
UI.pet_thumbnail = $('#needed-items-pet-thumbnail');
UI.pet_name = $('#needed-items-pet-name');
UI.reload = $('#needed-items-reload');
UI.pet_items = $('#needed-items-pet-items');
UI.item_template = $('#item-template');
function Pet(name) {
var el = standard_pet_el.clone()
.children('img').attr('src', petImage('cpn/' + name, 1)).end()
.children('span.name').text(name).end();
el.appendTo(queue_el);
var current_request = { abort: function () {} };
function sendRequest(options) {
current_request = $.ajax(options);
}
function cancelRequest() {
if(DEBUG) console.log("Canceling request", current_request);
current_request.abort();
}
/* Pet */
function loadPet(pet_name) {
// If there is a request in progress, kill it. Our new pet request takes
// priority, and, if I submit a name while the previous name is loading, I
// don't want to process both responses.
cancelRequest();
this.load = function () {
var response_el = el.children('span.response').text('Loading...');
$.ajax({
complete: function (data) {
pets.shift();
if(pets.length) {
pets[0].load();
}
},
data: {name: name},
dataType: 'json',
error: function (xhr) {
el.addClass('failed');
response_el.text(xhr.responseText);
},
success: function (data) {
var response = data === true ? 'Thanks!' : data + ' points';
el.addClass('loaded');
response_el.text(response);
},
type: 'post',
url: url
});
}
sendRequest({
url: UI.form.attr('action') + '.json',
dataType: 'json',
data: {name: pet_name},
error: petError,
success: function (data) { petSuccess(data, pet_name) },
complete: petComplete
});
UI.form.removeClass('failed').addClass('loading-pet');
}
this.add = function (name) {
name = name.replace(/^\s+|\s+$/g, '');
if(name.length) {
var pet = new Pet(name);
pets.push(pet);
if(pets.length == 1) pet.load();
}
function petComplete() {
UI.form.removeClass('loading-pet');
}
function petError(xhr) {
UI.alert.text(xhr.responseText);
UI.form.addClass('failed');
}
function petSuccess(data, pet_name) {
UI.pet_thumbnail.attr('src', petThumbnailUrl(pet_name));
UI.pet_name.text(pet_name);
loadItems(data.query);
}
function petThumbnailUrl(pet_name) {
return 'http://pets.neopets.com/cpn/' + pet_name + '/1/1.png';
}
/* Items */
function loadItems(query) {
UI.form.addClass('loading-items');
sendRequest({
url: '/items/needed.json',
dataType: 'json',
data: query,
success: itemsSuccess
});
}
function itemsSuccess(items) {
if(DEBUG) {
// The dev server is missing lots of data, so sends me 2000+ needed
// items. We don't need that many for styling, so limit it to 100 to make
// my browser happier.
items = items.slice(0, 100);
}
UI.pet_items.empty();
UI.item_template.tmpl(items).appendTo(UI.pet_items);
UI.form.removeClass('loading-items').addClass('loaded');
}
UI.form.submit(function (e) {
e.preventDefault();
loadPet(UI.pet_name_field.val());
});
UI.reload.click(function () {
loadPet(UI.pet_name.text());
});
})();
names_el.keyup(function () {
var names = this.value.split('\n'), x = names.length - 1, i, name;
for(i = 0; i < x; i++) {
bulk_load_queue.add(names[i]);
}
this.value = (x >= 0) ? names[x] : '';
});
/* Bulk pets form */
(function () {
var form = $('#bulk-pets-form'),
queue_el = form.find('ul'),
names_el = form.find('textarea'),
add_el = $('#bulk-pets-form-add'),
clear_el = $('#bulk-pets-form-clear'),
bulk_load_queue;
add_el.click(function () {
bulk_load_queue.add(names_el.val());
names_el.val('');
});
$(document.body).addClass('js');
clear_el.click(function () {
queue_el.children('li.loaded, li.failed').remove();
});
bulk_load_queue = new (function BulkLoadQueue() {
var pets = [],
standard_pet_el = $('<li/>'),
url = form.attr('action') + '.json';
standard_pet_el.append('<img/>').append($('<span/>', {'class': 'name'}))
.append($('<span/>', {'class': 'response', text: 'Waiting...'}));
function Pet(name) {
var el = standard_pet_el.clone()
.children('img').attr('src', petImage('cpn/' + name, 1)).end()
.children('span.name').text(name).end();
el.appendTo(queue_el);
this.load = function () {
var response_el = el.children('span.response').text('Loading...');
$.ajax({
complete: function (data) {
pets.shift();
if(pets.length) {
pets[0].load();
}
},
data: {name: name},
dataType: 'json',
error: function (xhr) {
el.addClass('failed');
response_el.text(xhr.responseText);
},
success: function (data) {
var points = data.points;
var response = (points === true) ? 'Thanks!' : points + ' points';
el.addClass('loaded');
response_el.text(response);
},
type: 'post',
url: url
});
}
}
this.add = function (name) {
name = name.replace(/^\s+|\s+$/g, '');
if(name.length) {
var pet = new Pet(name);
pets.push(pet);
if(pets.length == 1) pet.load();
}
}
})();
names_el.keyup(function () {
var names = this.value.split('\n'), x = names.length - 1, i, name;
for(i = 0; i < x; i++) {
bulk_load_queue.add(names[i]);
}
this.value = (x >= 0) ? names[x] : '';
});
add_el.click(function () {
bulk_load_queue.add(names_el.val());
names_el.val('');
});
clear_el.click(function () {
queue_el.children('li.loaded, li.failed').remove();
});
})();

View file

@ -4041,23 +4041,95 @@ body.outfits-show #outfit-items {
text-align: center;
}
/* line 1, ../../../app/stylesheets/pets/_bulk.sass */
body.pets-bulk {
/* line 2, ../../../app/stylesheets/pets/_bulk.sass */
body.pets-bulk #needed-items-form, body.pets-bulk #bulk-pets-form {
text-align: center;
}
/* line 5, ../../../app/stylesheets/pets/_bulk.sass */
body.pets-bulk #bulk-pets-form textarea, body.pets-bulk #bulk-pets-form div {
/* line 6, ../../../app/stylesheets/pets/_bulk.sass */
body.pets-bulk #needed-items-form #needed-items-pet {
border-top: 1px solid #aaddaa;
display: none;
margin-top: 1em;
padding-top: 1em;
}
/* line 12, ../../../app/stylesheets/pets/_bulk.sass */
body.pets-bulk #needed-items-form #needed-items-pet h4 {
font-size: 150%;
margin-bottom: 0.5em;
}
/* line 16, ../../../app/stylesheets/pets/_bulk.sass */
body.pets-bulk #needed-items-form #needed-items-pet #needed-items-reload {
display: -moz-inline-box;
-moz-box-orient: vertical;
display: inline-block;
vertical-align: middle;
*vertical-align: auto;
font-size: 12px;
margin-left: 1em;
vertical-align: middle;
}
/* line 7, ../../../../../../.rvm/gems/ruby-1.9.2-p290/gems/compass-0.10.6/frameworks/compass/stylesheets/compass/css3/_inline-block.scss */
body.pets-bulk #bulk-pets-form textarea, body.pets-bulk #bulk-pets-form div {
body.pets-bulk #needed-items-form #needed-items-pet #needed-items-reload {
*display: inline;
}
/* line 7, ../../../app/stylesheets/pets/_bulk.sass */
/* line 22, ../../../app/stylesheets/pets/_bulk.sass */
body.pets-bulk #needed-items-form #needed-items-alert {
display: none;
margin-top: 0.5em;
}
/* line 26, ../../../app/stylesheets/pets/_bulk.sass */
body.pets-bulk #needed-items-form #needed-items-pet-thumbnail {
height: 50px;
width: 50px;
}
/* line 31, ../../../app/stylesheets/pets/_bulk.sass */
body.pets-bulk #needed-items-form #needed-items-pet-items li.owned {
background: #eeffee;
border: 1px solid #006600;
}
/* line 35, ../../../app/stylesheets/pets/_bulk.sass */
body.pets-bulk #needed-items-form .object-owned {
color: #448844;
display: block;
font-size: 75%;
font-style: italic;
padding-bottom: 0.25em;
}
/* line 43, ../../../app/stylesheets/pets/_bulk.sass */
body.pets-bulk #needed-items-form.loading-pet #needed-items-pet-name-field, body.pets-bulk #needed-items-form.loading-items #needed-items-pet-name-field {
background-image: url('/images/loading.gif?1315327995');
background-position: center right;
background-repeat: no-repeat;
}
/* line 49, ../../../app/stylesheets/pets/_bulk.sass */
body.pets-bulk #needed-items-form.loading-pet #needed-items-pet-items, body.pets-bulk #needed-items-form.loading-items #needed-items-pet-items {
-moz-opacity: 0.5;
-webkit-opacity: 0.5;
-o-opacity: 0.5;
-khtml-opacity: 0.5;
}
/* line 53, ../../../app/stylesheets/pets/_bulk.sass */
body.pets-bulk #needed-items-form.loading-pet #needed-items-pet h4 {
-moz-opacity: 0.5;
-webkit-opacity: 0.5;
-o-opacity: 0.5;
-khtml-opacity: 0.5;
}
/* line 57, ../../../app/stylesheets/pets/_bulk.sass */
body.pets-bulk #needed-items-form.loaded #needed-items-pet {
display: block;
}
/* line 61, ../../../app/stylesheets/pets/_bulk.sass */
body.pets-bulk #needed-items-form.failed #needed-items-alert {
display: block;
}
/* line 64, ../../../app/stylesheets/pets/_bulk.sass */
body.pets-bulk #bulk-pets-form {
border-top: 1px solid #006600;
margin-top: 12px;
padding-top: 12px;
}
/* line 69, ../../../app/stylesheets/pets/_bulk.sass */
body.pets-bulk #bulk-pets-form textarea {
display: -moz-inline-box;
-moz-box-orient: vertical;
@ -4074,12 +4146,12 @@ body.pets-bulk #bulk-pets-form textarea {
body.pets-bulk #bulk-pets-form textarea {
*display: inline;
}
/* line 15, ../../../app/stylesheets/pets/_bulk.sass */
/* line 77, ../../../app/stylesheets/pets/_bulk.sass */
body.pets-bulk #bulk-pets-form ul {
list-style: none;
margin-bottom: 1em;
margin-top: 1em;
}
/* line 18, ../../../app/stylesheets/pets/_bulk.sass */
/* line 80, ../../../app/stylesheets/pets/_bulk.sass */
body.pets-bulk #bulk-pets-form ul li {
display: -moz-inline-box;
-moz-box-orient: vertical;
@ -4095,39 +4167,39 @@ body.pets-bulk #bulk-pets-form ul li {
body.pets-bulk #bulk-pets-form ul li {
*display: inline;
}
/* line 24, ../../../app/stylesheets/pets/_bulk.sass */
/* line 86, ../../../app/stylesheets/pets/_bulk.sass */
body.pets-bulk #bulk-pets-form ul li.loaded {
background: #e6efc2;
}
/* line 26, ../../../app/stylesheets/pets/_bulk.sass */
/* line 88, ../../../app/stylesheets/pets/_bulk.sass */
body.pets-bulk #bulk-pets-form ul li.failed {
background: #fbe3e4;
}
/* line 28, ../../../app/stylesheets/pets/_bulk.sass */
/* line 90, ../../../app/stylesheets/pets/_bulk.sass */
body.pets-bulk #bulk-pets-form ul img {
float: left;
height: 50px;
width: 50px;
}
/* line 33, ../../../app/stylesheets/pets/_bulk.sass */
/* line 95, ../../../app/stylesheets/pets/_bulk.sass */
body.pets-bulk #bulk-pets-form ul span {
display: block;
}
/* line 35, ../../../app/stylesheets/pets/_bulk.sass */
/* line 97, ../../../app/stylesheets/pets/_bulk.sass */
body.pets-bulk #bulk-pets-form ul .response {
font-size: 75%;
font-style: italic;
margin-left: 75px;
}
/* line 42, ../../../app/stylesheets/pets/_bulk.sass */
/* line 104, ../../../app/stylesheets/pets/_bulk.sass */
body.pets-bulk.js .noscript {
display: none;
}
/* line 44, ../../../app/stylesheets/pets/_bulk.sass */
/* line 106, ../../../app/stylesheets/pets/_bulk.sass */
body.pets-bulk.js .script-only {
display: block;
}
/* line 47, ../../../app/stylesheets/pets/_bulk.sass */
/* line 109, ../../../app/stylesheets/pets/_bulk.sass */
body.pets-bulk .script-only {
display: none;
}