forked from OpenNeo/impress
contributions viewing
This commit is contained in:
parent
db56b0d218
commit
a5b119a9bc
16 changed files with 323 additions and 1 deletions
7
app/controllers/contributions_controller.rb
Normal file
7
app/controllers/contributions_controller.rb
Normal file
|
@ -0,0 +1,7 @@
|
|||
class ContributionsController < ApplicationController
|
||||
def index
|
||||
@contributions = Contribution.recent.paginate :page => params[:page],
|
||||
:include => :user
|
||||
Contribution.preload_contributeds_and_parents @contributions
|
||||
end
|
||||
end
|
|
@ -39,4 +39,8 @@ module ApplicationHelper
|
|||
def origin_tag(value)
|
||||
hidden_field_tag 'origin', value, :id => nil
|
||||
end
|
||||
|
||||
def title(value)
|
||||
content_for :title, value
|
||||
end
|
||||
end
|
||||
|
|
40
app/helpers/contribution_helper.rb
Normal file
40
app/helpers/contribution_helper.rb
Normal file
|
@ -0,0 +1,40 @@
|
|||
module ContributionHelper
|
||||
def contributed_description(contributed)
|
||||
case contributed
|
||||
when Item
|
||||
contributed_item(contributed, 'for the first time')
|
||||
when SwfAsset
|
||||
contributed_item(contributed.item, 'on a new body type')
|
||||
when PetType
|
||||
contributed_pet_type(contributed, :after => 'for the first time')
|
||||
when PetState
|
||||
contributed_pet_type(contributed.pet_type, :before => 'a new pose for')
|
||||
end
|
||||
end
|
||||
|
||||
def contributed_item(item, adverbial)
|
||||
output do |html|
|
||||
html << 'the'
|
||||
html << link_to(item.name, item, :class => 'contributed-name')
|
||||
html << adverbial
|
||||
html << image_tag(item.thumbnail_url)
|
||||
end
|
||||
end
|
||||
|
||||
PET_TYPE_IMAGE_FORMAT = 'http://pets.neopets.com/cp/%s/1/3.png'
|
||||
def contributed_pet_type(pet_type, options)
|
||||
options[:before] ||= 'the'
|
||||
output do |html|
|
||||
html << options[:before]
|
||||
html << content_tag(:span, pet_type.human_name, :class => 'contributed-name')
|
||||
html << options[:after] if options[:after]
|
||||
html << image_tag(sprintf(PET_TYPE_IMAGE_FORMAT, pet_type.image_hash))
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def output(&block)
|
||||
raw([].tap(&block).join(' '))
|
||||
end
|
||||
end
|
84
app/models/contribution.rb
Normal file
84
app/models/contribution.rb
Normal file
|
@ -0,0 +1,84 @@
|
|||
class Contribution < ActiveRecord::Base
|
||||
POINT_VALUES = {
|
||||
'Item' => 3,
|
||||
'SwfAsset' => 2,
|
||||
'PetType' => 15,
|
||||
'PetState' => 10
|
||||
}
|
||||
|
||||
attr_accessor :contributed
|
||||
|
||||
belongs_to :user
|
||||
|
||||
scope :recent, order('id DESC')
|
||||
|
||||
cattr_reader :per_page
|
||||
@@per_page = 30
|
||||
|
||||
def point_value
|
||||
POINT_VALUES[contributed_type]
|
||||
end
|
||||
|
||||
CONTRIBUTED_RELATIONSHIPS = {
|
||||
'SwfAsset' => 'Item',
|
||||
'PetState' => 'PetType'
|
||||
}
|
||||
CONTRIBUTED_CHILDREN = CONTRIBUTED_RELATIONSHIPS.keys
|
||||
CONTRIBUTED_TYPES = CONTRIBUTED_CHILDREN + CONTRIBUTED_RELATIONSHIPS.values
|
||||
CONTRIBUTED_BASES = {}
|
||||
CONTRIBUTED_TYPES.each do |type|
|
||||
base = type == 'SwfAsset' ? SwfAsset.object_assets : type.constantize
|
||||
CONTRIBUTED_BASES[type] = base
|
||||
end
|
||||
def self.preload_contributeds_and_parents(contributions)
|
||||
# Initialize the groups we'll be using for quick access
|
||||
contributions_by_type = {}
|
||||
contributed_by_type = {}
|
||||
contributed_by_type_and_id = {}
|
||||
needed_ids_by_type = {}
|
||||
CONTRIBUTED_TYPES.each do |type|
|
||||
contributions_by_type[type] = []
|
||||
contributed_by_type[type] = []
|
||||
contributed_by_type_and_id[type] = {}
|
||||
needed_ids_by_type[type] = []
|
||||
end
|
||||
|
||||
# Go through the contributions to sort them for future contributed
|
||||
# assignment, and so we can know what immediate contributed items we'll
|
||||
# need to look up
|
||||
contributions.each do |contribution|
|
||||
type = contribution.contributed_type
|
||||
contributions_by_type[type] << contribution
|
||||
needed_ids_by_type[type] << contribution.contributed_id
|
||||
end
|
||||
|
||||
# Load contributed objects without parents, prepare them for easy access
|
||||
# for future assignment to contributions and looking up parents
|
||||
CONTRIBUTED_CHILDREN.each do |type|
|
||||
base = CONTRIBUTED_BASES[type]
|
||||
base.find(needed_ids_by_type[type]).each do |contributed|
|
||||
contributed_by_type[type] << contributed
|
||||
contributed_by_type_and_id[type][contributed.id] = contributed
|
||||
end
|
||||
end
|
||||
|
||||
# Load both parents of the children we just got, and immediately
|
||||
# contributed objects of that class. all_by_ids_or_children properly
|
||||
# assigns parents to children, as well
|
||||
CONTRIBUTED_RELATIONSHIPS.each do |child_type, type|
|
||||
base = CONTRIBUTED_BASES[type]
|
||||
ids = needed_ids_by_type[type]
|
||||
children = contributed_by_type[child_type]
|
||||
base.all_by_ids_or_children(ids, children).each do |contributed|
|
||||
contributed_by_type_and_id[type][contributed.id] = contributed
|
||||
end
|
||||
end
|
||||
|
||||
# Assign contributed objects to contributions
|
||||
contributions.each do |contribution|
|
||||
type = contribution.contributed_type
|
||||
id = contribution.contributed_id
|
||||
contribution.contributed = contributed_by_type_and_id[type][id]
|
||||
end
|
||||
end
|
||||
end
|
|
@ -149,6 +149,34 @@ class Item < ActiveRecord::Base
|
|||
@parent_swf_asset_relationships_to_update = rels
|
||||
end
|
||||
|
||||
def self.all_by_ids_or_children(ids, swf_assets)
|
||||
swf_asset_ids = []
|
||||
swf_assets_by_id = {}
|
||||
swf_assets_by_parent_id = {}
|
||||
swf_assets.each do |swf_asset|
|
||||
id = swf_asset.id
|
||||
swf_assets_by_id[id] = swf_asset
|
||||
swf_asset_ids << id
|
||||
end
|
||||
SwfAsset.select('id, parent_id').object_assets.joins(:object_asset_relationships).
|
||||
where(SwfAsset.arel_table[:id].in(swf_asset_ids)).each do |row|
|
||||
item_id = row.parent_id.to_i
|
||||
swf_assets_by_parent_id[item_id] ||= []
|
||||
swf_assets_by_parent_id[item_id] << swf_assets_by_id[row.id.to_i]
|
||||
ids << item_id
|
||||
end
|
||||
find(ids).tap do |items|
|
||||
items.each do |item|
|
||||
swf_assets = swf_assets_by_parent_id[item.id]
|
||||
if swf_assets
|
||||
swf_assets.each do |swf_asset|
|
||||
swf_asset.item = item
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.collection_from_pet_type_and_registries(pet_type, info_registry, asset_registry)
|
||||
# bear in mind that registries are arrays with many nil elements,
|
||||
# due to how the parser works
|
||||
|
|
|
@ -10,6 +10,16 @@ class PetAttribute < StaticResource
|
|||
self.name.capitalize
|
||||
end
|
||||
|
||||
def self.find(id)
|
||||
attribute = super
|
||||
unless attribute
|
||||
attribute = new
|
||||
attribute.id = id
|
||||
attribute.name = "color \##{id}"
|
||||
end
|
||||
attribute
|
||||
end
|
||||
|
||||
def self.find_by_name(name)
|
||||
@objects_by_name[name.downcase]
|
||||
end
|
||||
|
|
|
@ -64,6 +64,10 @@ class PetType < ActiveRecord::Base
|
|||
self['image_hash'] || BasicHashes[species.name][color.name]
|
||||
end
|
||||
|
||||
def human_name
|
||||
self.color.human_name + ' ' + self.species.human_name
|
||||
end
|
||||
|
||||
def add_pet_state_from_biology!(biology)
|
||||
pet_state = PetState.from_pet_type_and_biology_info(self, biology)
|
||||
self.pet_states << pet_state
|
||||
|
@ -92,4 +96,24 @@ class PetType < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.all_by_ids_or_children(ids, pet_states)
|
||||
pet_states_by_pet_type_id = {}
|
||||
pet_states.each do |pet_state|
|
||||
id = pet_state.pet_type_id
|
||||
ids << id
|
||||
pet_states_by_pet_type_id[id] ||= []
|
||||
pet_states_by_pet_type_id[id] << pet_state
|
||||
end
|
||||
find(ids).tap do |pet_types|
|
||||
pet_types.each do |pet_type|
|
||||
pet_states = pet_states_by_pet_type_id[pet_type.id]
|
||||
if pet_states
|
||||
pet_states.each do |pet_state|
|
||||
pet_state.pet_type = pet_type
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,6 +3,8 @@ class SwfAsset < ActiveRecord::Base
|
|||
LOCAL_ASSET_DIR = Rails.root.join('public', PUBLIC_ASSET_DIR)
|
||||
set_inheritance_column 'inheritance_type'
|
||||
|
||||
attr_accessor :item
|
||||
|
||||
has_many :object_asset_relationships, :class_name => 'ParentSwfAssetRelationship',
|
||||
:conditions => {:swf_asset_type => 'object'}
|
||||
|
||||
|
@ -17,6 +19,8 @@ class SwfAsset < ActiveRecord::Base
|
|||
where(arel_table[:body_id].in(BodyIdsFittingStandard))
|
||||
}
|
||||
|
||||
scope :object_assets, where(arel_table[:type].eq('object'))
|
||||
|
||||
def local_url
|
||||
'/' + File.join(PUBLIC_ASSET_DIR, local_path_within_outfit_swfs)
|
||||
end
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
class User < ActiveRecord::Base
|
||||
DefaultAuthServerId = 1
|
||||
|
||||
has_many :contributions
|
||||
|
||||
scope :top_contributors, order('points DESC')
|
||||
|
||||
def self.find_or_create_from_remote_auth_data(user_data)
|
||||
|
|
38
app/stylesheets/contributions/_index.sass
Normal file
38
app/stylesheets/contributions/_index.sass
Normal file
|
@ -0,0 +1,38 @@
|
|||
body.contributions-index
|
||||
text-align: center
|
||||
|
||||
.contributions
|
||||
li
|
||||
list-style: none
|
||||
height: 80px
|
||||
overflow: hidden
|
||||
padding: 1em 0 0 100px
|
||||
position: relative
|
||||
text-align: left
|
||||
.point-value
|
||||
+header-text
|
||||
color: #fff
|
||||
font-size: 80px
|
||||
left: 0
|
||||
line-height: 1
|
||||
position: absolute
|
||||
text-align: center
|
||||
text-shadow: 2px 2px 0 #000
|
||||
top: 0
|
||||
width: 80px
|
||||
z-index: 3
|
||||
&:hover
|
||||
+opacity(0.5)
|
||||
img
|
||||
height: 80px
|
||||
left: 0
|
||||
position: absolute
|
||||
top: 0
|
||||
width: 80px
|
||||
z-index: 2
|
||||
span
|
||||
&.username, &.contributed-name
|
||||
font-weight: bold
|
||||
&.time-ago
|
||||
display: block
|
||||
font-size: 75%
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
@import layout
|
||||
|
||||
@import contributions/index
|
||||
@import items
|
||||
@import items/index
|
||||
@import items/show
|
||||
|
|
10
app/views/contributions/_contribution.html.haml
Normal file
10
app/views/contributions/_contribution.html.haml
Normal file
|
@ -0,0 +1,10 @@
|
|||
- contributed = contribution.contributed
|
||||
= content_tag_for :li, contribution do
|
||||
%span.point-value= contribution.point_value
|
||||
%span.username
|
||||
= link_to contribution.user.name, user_contributions_path(contribution.user)
|
||||
showed us
|
||||
= contributed_description contributed
|
||||
%span.time-ago{:title => contribution.created_at.to_s}
|
||||
= time_ago_in_words(contribution.created_at)
|
||||
ago
|
9
app/views/contributions/index.html.haml
Normal file
9
app/views/contributions/index.html.haml
Normal file
|
@ -0,0 +1,9 @@
|
|||
- title 'Recent Contributions'
|
||||
%ul.buttons
|
||||
%li= link_to 'Top Contributors', top_contributors_path, :class => 'button'
|
||||
- if @contributions.empty?
|
||||
%p No contributions to see here!
|
||||
- else
|
||||
= will_paginate @contributions
|
||||
%ul.contributions= render @contributions
|
||||
= will_paginate @contributions
|
|
@ -1,11 +1,17 @@
|
|||
!!! 5
|
||||
%html
|
||||
%head
|
||||
%title Dress to Impress
|
||||
%title
|
||||
Dress to Impress
|
||||
- if content_for? :title
|
||||
—
|
||||
= yield :title
|
||||
= stylesheet_link_tag "compiled/screen"
|
||||
= javascript_include_tag "http://#{RemoteImpressHost}/assets/js/analytics.js"
|
||||
%body{:class => body_class}
|
||||
#container
|
||||
- if content_for? :title
|
||||
%h1#title= yield :title
|
||||
= yield :before_flashes
|
||||
= flashes
|
||||
|
||||
|
|
|
@ -86,3 +86,5 @@ Zombie
|
|||
Onion
|
||||
Magma
|
||||
Relic
|
||||
Woodland
|
||||
Transparent
|
||||
|
|
|
@ -367,6 +367,59 @@ dd {
|
|||
src: local("Droid Sans"), url("http://themes.googleusercontent.com/font?kit=POVDFY-UUf0WFR9DIMCU8g") format("truetype");
|
||||
}
|
||||
|
||||
/* line 1, ../../../app/stylesheets/contributions/_index.sass */
|
||||
body.contributions-index {
|
||||
text-align: center;
|
||||
}
|
||||
/* line 5, ../../../app/stylesheets/contributions/_index.sass */
|
||||
body.contributions-index .contributions li {
|
||||
list-style: none;
|
||||
height: 80px;
|
||||
overflow: hidden;
|
||||
padding: 1em 0 0 100px;
|
||||
position: relative;
|
||||
text-align: left;
|
||||
}
|
||||
/* line 12, ../../../app/stylesheets/contributions/_index.sass */
|
||||
body.contributions-index .contributions .point-value {
|
||||
font-family: Delicious, Helvetica, Arial, Verdana, sans-serif;
|
||||
color: white;
|
||||
font-size: 80px;
|
||||
left: 0;
|
||||
line-height: 1;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
text-shadow: 2px 2px 0 black;
|
||||
top: 0;
|
||||
width: 80px;
|
||||
z-index: 3;
|
||||
}
|
||||
/* line 24, ../../../app/stylesheets/contributions/_index.sass */
|
||||
body.contributions-index .contributions .point-value:hover {
|
||||
-moz-opacity: 0.5;
|
||||
-webkit-opacity: 0.5;
|
||||
-o-opacity: 0.5;
|
||||
-khtml-opacity: 0.5;
|
||||
}
|
||||
/* line 26, ../../../app/stylesheets/contributions/_index.sass */
|
||||
body.contributions-index .contributions img {
|
||||
height: 80px;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 80px;
|
||||
z-index: 2;
|
||||
}
|
||||
/* line 34, ../../../app/stylesheets/contributions/_index.sass */
|
||||
body.contributions-index .contributions span.username, body.contributions-index .contributions span.contributed-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
/* line 36, ../../../app/stylesheets/contributions/_index.sass */
|
||||
body.contributions-index .contributions span.time-ago {
|
||||
display: block;
|
||||
font-size: 75%;
|
||||
}
|
||||
|
||||
/* line 1, ../../../app/stylesheets/_items.sass */
|
||||
body.items {
|
||||
text-align: center;
|
||||
|
|
Loading…
Reference in a new issue