diff --git a/app/controllers/albums_controller.rb b/app/controllers/albums_controller.rb index 2fb5ac47f41b3c52574a882f260c9fc2e9b4fbfb..fe33376f3793953e86767f422fcb5d7aa794d5bb 100644 --- a/app/controllers/albums_controller.rb +++ b/app/controllers/albums_controller.rb @@ -12,7 +12,8 @@ class AlbumsController < ApplicationController flash[:notice] = "Successfully created album." redirect_to @album else - render :action => 'new' + flash[:error] = "Successfully failed." + redirect_to albums_path end end diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index c525ad1cdde6d1612d1c38d362627ec4127c4806..c3b74a8611ea6257c286a06096beaf6a400d9232 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -16,9 +16,12 @@ class ApplicationController < ActionController::Base end def set_friends_and_status - @friends = Person.friends.all if current_user - @latest_status_message = StatusMessage.newest(current_user) if current_user - + if current_user + @groups = current_user.groups + @friends = current_user.friends + @latest_status_message = StatusMessage.newest_for(current_user.person) + @group = params[:group] ? current_user.group_by_id(params[:group]) : current_user.groups.first + end end def count_requests diff --git a/app/controllers/blogs_controller.rb b/app/controllers/blogs_controller.rb index a74b12e433e0c413a81fec0c5c2ba3037df2f9ca..4075e04edfdc58e7c35c833f37fa9519f9dbe1e8 100644 --- a/app/controllers/blogs_controller.rb +++ b/app/controllers/blogs_controller.rb @@ -24,7 +24,6 @@ class BlogsController < ApplicationController if @blog.created_at flash[:notice] = "Successfully created blog." - redirect_to @blog else render :action => 'new' end diff --git a/app/controllers/bookmarks_controller.rb b/app/controllers/bookmarks_controller.rb index 79bf76d12e1083cce4b8f9ffc6a681f90c72f21b..5d9959732f65750632a2c7f99f185ce08df6c368 100644 --- a/app/controllers/bookmarks_controller.rb +++ b/app/controllers/bookmarks_controller.rb @@ -4,11 +4,6 @@ class BookmarksController < ApplicationController def index @bookmark = Bookmark.new @bookmarks = Bookmark.paginate :page => params[:page], :order => 'created_at DESC' - - - respond_to do |format| - format.html - end end def edit @@ -34,7 +29,6 @@ class BookmarksController < ApplicationController if @bookmark.created_at flash[:notice] = "Successfully created bookmark." - redirect_to @bookmark else render :action => 'new' end diff --git a/app/controllers/dashboards_controller.rb b/app/controllers/dashboards_controller.rb deleted file mode 100644 index 438163fffe7c081961593602f1f47c00827b8c46..0000000000000000000000000000000000000000 --- a/app/controllers/dashboards_controller.rb +++ /dev/null @@ -1,9 +0,0 @@ -class DashboardsController < ApplicationController - before_filter :authenticate_user! - include ApplicationHelper - - def index - @posts = Post.paginate :page => params[:page], :order => 'created_at DESC' - end - - end diff --git a/app/controllers/dev_utilities_controller.rb b/app/controllers/dev_utilities_controller.rb index f5f96683f9f50294cab08121ce29006a570c8b53..a9711164ebac83917726431c84e34d378511ad51 100644 --- a/app/controllers/dev_utilities_controller.rb +++ b/app/controllers/dev_utilities_controller.rb @@ -1,33 +1,37 @@ class DevUtilitiesController < ApplicationController - before_filter :authenticate_user! + before_filter :authenticate_user!, :except => [:set_backer_number] include ApplicationHelper + include RequestsHelper def warzombie render :nothing => true - if User.owner.email == "tom@tom.joindiaspora.com" && StatusMessage.where(:message => "There's a bomb in the lasagna!?").first == nil - StatusMessage.create(:message => "There's a bomb in the lasagna!?", :person => User.owner) - Bookmark.create(:title => "xkcd", :link => "http://xkcd.com/743/", :person => User.owner ) - StatusMessage.create(:message => "I switched to Motoroi today, a Motorola Android-based phone, in Korea. Now, I am using Android phones in both the U.S. and Korea", :person => User.owner, :created_at => Time.now-930) - StatusMessage.create(:message => "I had 5 hours to study for it :-( GREs on Thursday. Wunderbar.", :person => User.owner, :created_at => Time.now-43990) - StatusMessage.create(:message => "Spotted in toy story 3: google maps, OSX, and windows XP. Two out of three isn't bad.", :person => User.owner, :created_at => Time.now-4390) - Bookmark.create( :title => "Reddit", :link => "http://reddit.com", :person => User.owner, :created_at => Time.now-54390) - Blog.create(:title => "I Love Rock'N'Roll - Joan Jett & The Blackhearts", :body => "<p>The loudspeakers played this song as we walked into the city pool for the first time this summer. Those loudspeakers make every song sound fresh even if I have heard it a thousand times and their effect on this song was no different. Joan sounded young and strong and ready, and for a moment I forgot where or when I was.</p> <p>also i can tell it won’t be long and also happy summer imaginary constructs -mumblelard</p>", :person => User.owner, :created_at => Time.now-3090) - StatusMessage.create(:message => "Commercials for IE make me SO MAD and my friends just don't get why.", :person => User.owner, :created_at => Time.now-30900) - Bookmark.create(:title => "Zombo.com", :link => "http://zombo.com", :person => User.owner, :created_at => Time.now-9090) - StatusMessage.create(:message => "Why do I have \"No More Heroes\" by Westlife on repeat all day?", :person => User.owner, :created_at => Time.now-590000) - StatusMessage.create(:message => "Mmm. Friday night. Acknowledged.", :person => User.owner, :created_at => Time.now-503900) - StatusMessage.create(:message => "Getting a universal remote is the epitome of laziness, I do declare.", :person => User.owner, :created_at => Time.now-4400) - StatusMessage.create(:message => "Does anyone know how to merge two Skype contact entries of the same person? (i.e. one Skype ID and one mobile number)", :person => User.owner, :created_at => Time.now-400239) - StatusMessage.create(:message => "A cool, cool morning for once.", :person => User.owner, :created_at => Time.now-150000) + if current_user.email == "tom@tom.joindiaspora.com" && StatusMessage.where(:message => "There's a bomb in the lasagna!?").first == nil + current_user.post(:status_message, :message => "There's a bomb in the lasagna!?") + current_user.post(:bookmark, :title => "xkcd", :link => "http://xkcd.com/743/" ) + current_user.post(:status_message, :message => "I switched to Motoroi today, a Motorola Android-based phone, in Korea. Now, I am using Android phones in both the U.S. and Korea", :created_at => Time.now-930) + current_user.post(:status_message, :message => "I had 5 hours to study for it :-( GREs on Thursday. Wunderbar.", :created_at => Time.now-43990) + current_user.post(:status_message, :message => "Spotted in toy story 3: google maps, OSX, and windows XP. Two out of three isn't bad.", :created_at => Time.now-4390) + current_user.post(:bookmark, :title => "Reddit", :link => "http://reddit.com", :created_at => Time.now-54390) + current_user.post(:blog, :title => "I Love Rock'N'Roll - Joan Jett & The Blackhearts", :body => "<p>The loudspeakers played this song as we walked into the city pool for the first time this summer. Those loudspeakers make every song sound fresh even if I have heard it a thousand times and their effect on this song was no different. Joan sounded young and strong and ready, and for a moment I forgot where or when I was.</p> <p>also i can tell it won’t be long and also happy summer imaginary constructs -mumblelard</p>", :created_at => Time.now-3090) + current_user.post(:status_message, :message => "Commercials for IE make me SO MAD and my friends just don't get why.", :created_at => Time.now-30900) + current_user.post(:bookmark, :title => "Zombo.com", :link => "http://zombo.com", :created_at => Time.now-9090) + current_user.post(:status_message, :message => "Why do I have \"No More Heroes\" by Westlife on repeat all day?", :created_at => Time.now-590000) + current_user.post(:status_message, :message => "Mmm. Friday night. Acknowledged.", :created_at => Time.now-503900) + current_user.post(:status_message, :message => "Getting a universal remote is the epitome of laziness, I do declare.", :created_at => Time.now-4400) + current_user.post(:status_message, :message => "Does anyone know how to merge two Skype contact entries of the same person? (i.e. one Skype ID and one mobile number)", :created_at => Time.now-400239) + current_user.post(:status_message, :message => "A cool, cool morning for once.", :created_at => Time.now-150000) end end def zombiefriends render :nothing => true - backer_info - if User.owner.email == "tom@tom.joindiaspora.com" && Person.friends.first.nil? - backer_info.each do |backer| + bkr_info = backer_info + + if current_user.email == "tom@tom.joindiaspora.com" + bkr_info.each do |backer| + backer_email = "#{backer['username']}@#{backer['username']}.joindiaspora.com" + rel_hash = relationship_flow(backer_email) logger.info "Zombefriending #{backer['given_name']} #{backer['family_name']}" - User.owner.send_friend_request_to("http://#{backer['username']}.joindiaspora.com/") + current_user.send_request(rel_hash, current_user.groups.first.id) end end end @@ -35,7 +39,7 @@ def warzombie def zombiefriendaccept render :nothing => true Request.all.each{|r| - User.owner.accept_friend_request(r.id) + current_user.accept_and_respond(r.id, current_user.groups.first.id) } end @@ -44,4 +48,11 @@ def warzombie config['servers']['backer'] end + def set_backer_number + render :nothing => true + seed_num_hash = {:seed_number => params[:number]} + file = File.new(Rails.root.join('config','backer_number.yml'),'w') + file.write(seed_num_hash.to_yaml) + file.close + end end diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb new file mode 100644 index 0000000000000000000000000000000000000000..f3da1ec8ac15b9aa4eaec57279e10f7ec5e9632b --- /dev/null +++ b/app/controllers/groups_controller.rb @@ -0,0 +1,50 @@ +class GroupsController < ApplicationController + before_filter :authenticate_user! + + def index + @posts = Post.paginate :page => params[:page], :order => 'created_at DESC' + end + + def create + @group = current_user.group(params[:group]) + + if @group.created_at + flash[:notice] = "Successfully created group." + redirect_to @group + else + render :action => 'new' + end + end + + def new + @group = Group.new + end + + def destroy + @group = Group.first(:id => params[:id]) + @group.destroy + flash[:notice] = "Successfully destroyed group." + redirect_to groups_url + end + + def show + @people_ids = @group.people.map {|p| p.id} + @posts = Post.paginate :person_id => @people_ids, :order => 'created_at DESC' + @group = Group.first(:id => params[:id]) + end + + def edit + @group = Group.first(:id => params[:id]) + end + + def update + @group = Group.first(:id => params[:id]) + if @group.update_attributes(params[:group]) + flash[:notice] = "Successfully updated group." + redirect_to @group + else + render :action => 'edit' + end + end + +end diff --git a/app/controllers/people_controller.rb b/app/controllers/people_controller.rb index ec98269679e4807b9c3e2c01309bad56d4d82b30..e161f6acded699c35bd8e51e452caac9bc0a90e3 100644 --- a/app/controllers/people_controller.rb +++ b/app/controllers/people_controller.rb @@ -3,7 +3,7 @@ class PeopleController < ApplicationController def index unless params[:q] - @people = Person.friends.paginate :page => params[:page], :order => 'created_at DESC' + @people = current_user.friends.paginate :page => params[:page], :order => 'created_at DESC' render :index else @people = Person.search_for_friends(params[:q]) @@ -12,15 +12,16 @@ class PeopleController < ApplicationController end def show - @person= Person.where(:id => params[:id]).first + @person= current_user.friend_by_id(params[:id]) + @person_profile = @person.profile @person_posts = Post.where(:person_id => @person.id).paginate :page => params[:page], :order => 'created_at DESC' - @latest_status_message = StatusMessage.newest(@person) + @latest_status_message = StatusMessage.newest_for(@person) @post_count = @person_posts.count end def destroy - current_user.unfriend(params[:id]) + current_user.unfriend(current_user.friend_by_id(params[:id])) flash[:notice] = "unfriended person." redirect_to people_url end diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb index 128115d6af62f907c256b000303e21ea1d008736..2996a23ecd8e145f3c5b9b6d288cbb2f14809ff4 100644 --- a/app/controllers/photos_controller.rb +++ b/app/controllers/photos_controller.rb @@ -7,7 +7,6 @@ class PhotosController < ApplicationController if @photo.created_at flash[:notice] = "Successfully uploaded photo." - redirect_to @photo.album else render :action => 'album#new' end @@ -25,14 +24,14 @@ class PhotosController < ApplicationController end def destroy - @photo = Photo.where(:id => params[:id]).first + @photo = Photo.first(:id => params[:id]) @photo.destroy flash[:notice] = "Successfully deleted photo." redirect_to @photo.album end def show - @photo = Photo.where(:id => params[:id]).first + @photo = Photo.first(:id => params[:id]) @album = @photo.album end diff --git a/app/controllers/publics_controller.rb b/app/controllers/publics_controller.rb index 128999d093c48b9e67f359df229f6e1e7fd00888..91edf995d9776deb4a8f96e39e429a4ae89388b8 100644 --- a/app/controllers/publics_controller.rb +++ b/app/controllers/publics_controller.rb @@ -3,23 +3,28 @@ class PublicsController < ApplicationController include Diaspora::Parser def hcard - @user = User.owner - render 'hcard' + @person = Person.first(:_id => params[:id]) + + unless @person.nil? || @person.owner.nil? + render 'hcard' + end end def host_meta - @user = User.owner render 'host_meta', :layout => false, :content_type => 'application/xrd+xml' end def webfinger - @user = Person.first(:email => params[:q].gsub('acct:', '')) - render 'webfinger', :layout => false, :content_type => 'application/xrd+xml' + @person = Person.by_webfinger(params[:q]) + unless @person.nil? || @person.owner.nil? + render 'webfinger', :layout => false, :content_type => 'application/xrd+xml' + end end def receive - puts "SOMEONE JUST SENT ME: #{params[:xml]}" - store_objects_from_xml params[:xml] + @user = Person.first(:id => params[:id]).owner + Rails.logger.debug "PublicsController has received: #{params[:xml]}" + @user.receive params[:xml] if params[:xml] render :nothing => true end diff --git a/app/controllers/requests_controller.rb b/app/controllers/requests_controller.rb index 39f9c8376e8002387f25aa45f53f33714f787d1b..f5c73660fd7277f847780a1907cf9f401414fc8f 100644 --- a/app/controllers/requests_controller.rb +++ b/app/controllers/requests_controller.rb @@ -8,10 +8,16 @@ class RequestsController < ApplicationController def destroy if params[:accept] - @friend = current_user.accept_friend_request params[:id] - - flash[:notice] = "you are now friends" - redirect_to root_url + + if params[:group_id] + @friend = current_user.accept_and_respond( params[:id], params[:group_id]) + + flash[:notice] = "you are now friends" + redirect_to root_url + else + flash[:error] = "please select a group!" + redirect_to requests_url + end else current_user.ignore_friend_request params[:id] flash[:notice] = "ignored friend request" @@ -26,8 +32,8 @@ class RequestsController < ApplicationController def create rel_hash = relationship_flow(params[:request][:destination_url]) - Rails.logger.info("Sending request: #{rel_hash}") - @request = current_user.send_request(rel_hash) + Rails.logger.debug("Sending request: #{rel_hash}") + @request = current_user.send_request(rel_hash, params[:request][:group]) if @request flash[:notice] = "a friend request was sent to #{@request.destination_url}" @@ -43,9 +49,4 @@ class RequestsController < ApplicationController end end - - - private - - end diff --git a/app/controllers/sockets_controller.rb b/app/controllers/sockets_controller.rb index e25472d52de9a5ff4e21aa51c831323acbeafedc..802aa9cb57bc292fbde0e1f5eb0806b517138f53 100644 --- a/app/controllers/sockets_controller.rb +++ b/app/controllers/sockets_controller.rb @@ -2,22 +2,14 @@ class SocketsController < ApplicationController include ApplicationHelper include SocketsHelper include Rails.application.routes.url_helpers - before_filter :authenticate_user! def incoming(msg) - puts "#{msg} connected!" + puts "Got a connection to: #{msg}" end - def new_subscriber - WebSocket.subscribe - end - - def outgoing(object) + def outgoing(uid,object) @_request = ActionDispatch::Request.new({}) - WebSocket.push_to_clients(action_hash(object)) + Diaspora::WebSocket.push_to_user(uid, action_hash(uid, object)) end - def delete_subscriber(sid) - WebSocket.unsubscribe(sid) - end end diff --git a/app/controllers/status_messages_controller.rb b/app/controllers/status_messages_controller.rb index f499492e83521bab7e577eaf5a12129bd63763b9..f941389a55d20954de3936b766a860063ea005ee 100644 --- a/app/controllers/status_messages_controller.rb +++ b/app/controllers/status_messages_controller.rb @@ -1,5 +1,5 @@ class StatusMessagesController < ApplicationController - #before_filter :authenticate_user! + before_filter :authenticate_user! def index @status_messages = StatusMessage.paginate :page => params[:page], :order => 'created_at DESC' @@ -16,7 +16,6 @@ class StatusMessagesController < ApplicationController if @status_message.created_at flash[:notice] = "Successfully created status message." - redirect_to status_messages_url else render :action => 'new' end @@ -38,7 +37,7 @@ class StatusMessagesController < ApplicationController respond_to do |format| format.html - format.xml { render :xml => Post.build_xml_for(@status_message) } + format.xml { render :xml => @status_message.build_xml_for } format.json { render :json => @status_message } end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 9b4411c7a3638c955f626e191bd389c1d2a0dfcd..12f87c481511d9289522d81abe1cf43b0f163015 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -1,12 +1,12 @@ class UsersController < ApplicationController + before_filter :authenticate_user!, :except => [:new, :create] - before_filter :authenticate_user! def index @users = User.sort(:created_at.desc).all end def show - @user= Person.first(:id => params[:id]) - @user_profile = @user.profile + @user= User.first(:id => params[:id]) + @user_profile = @user.person.profile end def edit @@ -25,4 +25,20 @@ class UsersController < ApplicationController render :action => 'edit' end end + + def create + @user = User.instantiate(params[:user]) + + if @user.created_at && @user.person.created_at + flash[:notice] = "Successfully signed up." + redirect_to root_path + else + render :action => 'new' + end + end + + def new + @user = User.new + end + end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 2e2895fbb79d92e22bb35e9e2141ca9107c22172..7f6a7bae23737ec4829d0a30adddd65253a40b60 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -8,7 +8,7 @@ module ApplicationHelper end def mine?(post) - post.person == User.owner + current_user.owns? post end def type_partial(post) @@ -31,12 +31,12 @@ module ApplicationHelper end end - def link_to_person(person) - link_to person.real_name, person_path(person) + def owner_image_tag + person_image_tag(current_user) end - def owner_image_tag - person_image_tag(User.owner) + def owner_image_link + person_image_link(current_user) end def person_image_tag(person) @@ -50,10 +50,6 @@ module ApplicationHelper link_to person_image_tag(person), object_path(person) end - def owner_image_link - person_image_link(User.owner) - end - def new_request(request_count) "new_requests" if request_count > 0 end diff --git a/app/helpers/comments_helper.rb b/app/helpers/comments_helper.rb index a94d176adc47b355a2ff18278d10307bb0cc297a..b1e4df9cdef74ea419215ae9a46f15c0e843484c 100644 --- a/app/helpers/comments_helper.rb +++ b/app/helpers/comments_helper.rb @@ -1,9 +1,3 @@ module CommentsHelper - def target - - end - - def text - params[:comment][:text] - end + end diff --git a/app/helpers/photos_helper.rb b/app/helpers/photos_helper.rb index b858aaf7e111a6720ab89d0639f1393071444eed..b9231fe948bcce634185995a02a31a21d1494cf2 100644 --- a/app/helpers/photos_helper.rb +++ b/app/helpers/photos_helper.rb @@ -5,7 +5,7 @@ module PhotosHelper end def link_to_prev(photo, album) - link_to "<< previous", photo_path(album.prev_photo(photo)), :rel => "prefetch" + link_to "<< prev", photo_path(album.prev_photo(photo)), :rel => "prefetch" end def link_to_next(photo, album) diff --git a/app/helpers/publics_helper.rb b/app/helpers/publics_helper.rb index e694adef9ed68bdaf8a01880d12a28e93fb559c9..1e8ecac8fb6b5030198a02c36382a251da0a1fb8 100644 --- a/app/helpers/publics_helper.rb +++ b/app/helpers/publics_helper.rb @@ -14,4 +14,11 @@ module PublicsHelper 400 end end -end \ No newline at end of file + + def terse_url(full_url) + terse = full_url.gsub(/https?:\/\//, '') + terse.gsub!(/www\./, '') + terse = terse.chop! if terse[-1, 1] == '/' + terse + end +end diff --git a/app/helpers/requests_helper.rb b/app/helpers/requests_helper.rb index 4404ec223044bff72a3f923c4fe44b3d9fa45789..16a50a886e8c38060ae3b96afecab32449635701 100644 --- a/app/helpers/requests_helper.rb +++ b/app/helpers/requests_helper.rb @@ -26,10 +26,16 @@ module RequestsHelper end def relationship_flow(identifier) - f = Redfinger.finger(identifier) - action = subscription_mode(f) - url = subscription_url(action, f) - + puts request.host + if identifier.include?(request.host) + person = Person.by_webfinger identifier + action = (person == current_user.person ? :none : :friend) + url = person.owner.receive_url + else + f = Redfinger.finger(identifier) + action = subscription_mode(f) + url = subscription_url(action, f) + end { action => url } end diff --git a/app/helpers/sockets_helper.rb b/app/helpers/sockets_helper.rb index f13576306475f4a346c07fc6fc9bc9cf60e59937..b357803998fd6b62227aa313ee95c5432ed551cd 100644 --- a/app/helpers/sockets_helper.rb +++ b/app/helpers/sockets_helper.rb @@ -5,17 +5,16 @@ module SocketsHelper (object.is_a? Post) ? object.id : object.post_id end - def url_options - {:host => ""} - end + #def url_options + # {:host => ""} + #end - def action_hash(object) + def action_hash(uid, object) begin - v = render_to_string(:partial => type_partial(object), :locals => {:post => object}) unless object.is_a? Retraction + user = User.first(:id => uid) + v = render_to_string(:partial => type_partial(object), :locals => {:post => object, :current_user => user}) unless object.is_a? Retraction rescue Exception => e - puts "web socket view rendering failed for some reason." + v.inspect - puts object.inspect - puts e.message + Rails.logger.error("web socket view rendering failed for object #{object.inspect}.") raise e end action_hash = {:class =>object.class.to_s.underscore.pluralize, :html => v, :post_id => obj_id(object)} @@ -24,6 +23,7 @@ module SocketsHelper action_hash[:photo_hash] = object.thumb_hash elsif object.is_a? StatusMessage action_hash[:status_message_hash] = object.latest_hash + action_hash[:status_message_hash][:mine?] = true if object.person.owner_id == uid end action_hash.to_json diff --git a/app/helpers/status_messages_helper.rb b/app/helpers/status_messages_helper.rb index 57d0f2f17d873e937f99a29cdd8fccdd815826a6..840e789a0d5fc49bcf8c7be655bda2503faa69d5 100644 --- a/app/helpers/status_messages_helper.rb +++ b/app/helpers/status_messages_helper.rb @@ -1,5 +1,4 @@ module StatusMessagesHelper - def my_latest_message unless @latest_status_message.nil? return @latest_status_message.message @@ -7,7 +6,4 @@ module StatusMessagesHelper return "No message to display." end end - - - end diff --git a/app/models/album.rb b/app/models/album.rb index 3fb8917c4cf0b1dfa031ddb0407fd36ecb9db93f..03dc5ed1a8610161a6f25bcb3405ca28068d9aec 100644 --- a/app/models/album.rb +++ b/app/models/album.rb @@ -26,9 +26,9 @@ class Album def self.mine_or_friends(friend_param, current_user) if friend_param - Album.where(:person_id.ne => current_user.id) + Album.where(:person_id => current_user.friend_ids) else - Album.where(:person_id => current_user.id) + current_user.person.albums end end diff --git a/app/models/blog.rb b/app/models/blog.rb index 0df0dd5582f491e95011004540eca98f4e1917ec..3859cfa1e65a46e2ab3f9e838cfbad37e43b920a 100644 --- a/app/models/blog.rb +++ b/app/models/blog.rb @@ -15,8 +15,8 @@ class Blog < Post <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> <title>#{self.title}</title> <content>#{self.body}</content> - <link rel="alternate" type="text/html" href="#{User.owner.url}blogs/#{self.id}"/> - <id>#{User.owner.url}blogs/#{self.id}</id> + <link rel="alternate" type="text/html" href="#{person.url}blogs/#{self.id}"/> + <id>#{person.url}blogs/#{self.id}</id> <published>#{self.created_at.xmlschema}</published> <updated>#{self.updated_at.xmlschema}</updated> </entry> diff --git a/app/models/bookmark.rb b/app/models/bookmark.rb index 8f793fd47b3c51a05e82d12cdc513964d6dbdd59..677bfa126da0104b9d2c726edb2044e45dadb653 100644 --- a/app/models/bookmark.rb +++ b/app/models/bookmark.rb @@ -12,27 +12,31 @@ class Bookmark < Post validates_format_of :link, :with => /^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?$/ix - before_validation :clean_link - def to_activity <<-XML <entry> <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> <title>#{self.title}</title> - <link rel="alternate" type="text/html" href="#{User.owner.url}bookmarks/#{self.id}"/> + <link rel="alternate" type="text/html" href="#{person.url}bookmarks/#{self.id}"/> <link rel="related" type="text/html" href="#{self.link}"/> - <id>#{User.owner.url}bookmarks/#{self.id}</id> + <id>#{person.url}bookmarks/#{self.id}</id> <published>#{self.created_at.xmlschema}</published> <updated>#{self.updated_at.xmlschema}</updated> </entry> XML end + + def self.instantiate params + params[:link] = clean_link(params[:link]) + create params + end protected - def clean_link - if self.link - self.link = 'http://' + self.link unless self.link.match('https?://') - self.link = self.link + '/' if self.link[-1,1] != '/' + def self.clean_link link + if link + link = 'http://' + link unless link.match('https?://') + link = link + '/' if link[-1,1] != '/' + link end end end diff --git a/app/models/comment.rb b/app/models/comment.rb index 1808952a8338b5ee4f2152d6386fbf16750cb178..3b574f28f12b09877c45f773cd106dcf10b08e47 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -3,11 +3,12 @@ class Comment include ROXML include Diaspora::Webhooks include Encryptable + include Diaspora::Socketable xml_accessor :text xml_accessor :person, :as => Person xml_accessor :post_id - + xml_accessor :_id key :text, String timestamps! @@ -17,19 +18,22 @@ class Comment key :person_id, ObjectId belongs_to :person, :class_name => "Person" + + validates_presence_of :text - after_save :send_people_comments_on_my_posts - after_save :send_to_view - + def push_upstream + Rails.logger.info("GOIN UPSTREAM") + push_to([post.person]) + end - def ==(other) - (self.message == other.message) && (self.person.email == other.person.email) + def push_downstream + Rails.logger.info("SWIMMIN DOWNSTREAM") + push_to(post.people_with_permissions) end - + #ENCRYPTION before_validation :sign_if_mine, :sign_if_my_post - #validates_true_for :creator_signature, :logic => lambda {self.verify_creator_signature} validates_true_for :post_creator_signature, :logic => lambda {self.verify_post_creator_signature} xml_accessor :creator_signature @@ -53,8 +57,7 @@ class Comment end def verify_post_creator_signature - unless person == User.owner - puts "verifying post creator sig from #{post.person.real_name}" + if person.owner.nil? verify_signature(post_creator_signature, post.person) else true @@ -64,19 +67,9 @@ class Comment protected def sign_if_my_post - if self.post.person == User.owner - self.post_creator_signature = sign + unless self.post.person.owner.nil? + self.post_creator_signature = sign_with_key self.post.person.encryption_key end end - - def send_people_comments_on_my_posts - if User.owner.mine?(self.post) && !(self.person.is_a? User) - self.push_to(self.post.people_with_permissions) - end - end - - - def send_to_view - SocketsController.new.outgoing(self) - end + end diff --git a/app/models/group.rb b/app/models/group.rb new file mode 100644 index 0000000000000000000000000000000000000000..6b8f1892131882d3db7e8c42e5279ff9b6304174 --- /dev/null +++ b/app/models/group.rb @@ -0,0 +1,19 @@ +class Group + include MongoMapper::Document + + key :name, String + + key :person_ids, Array + key :request_ids, Array + key :post_ids, Array + + many :people, :in => :person_ids, :class_name => 'Person' + many :requests, :in => :request_ids, :class_name => 'Request' + many :posts, :in => :post_ids, :class_name => 'Post' + + belongs_to :user, :class_name => 'User' + + timestamps! + +end + diff --git a/app/models/person.rb b/app/models/person.rb index ee7ad104f2e7ec1819631a1c470b2f697c875148..d7fa74418dda6a55c5adf1d04c9a833fcb9df226 100644 --- a/app/models/person.rb +++ b/app/models/person.rb @@ -5,32 +5,35 @@ class Person xml_accessor :_id xml_accessor :email xml_accessor :url - xml_accessor :serialized_key xml_accessor :profile, :as => Profile - key :email, String + key :email, String, :unique => true key :url, String - key :active, Boolean, :default => false key :serialized_key, String + + key :owner_id, ObjectId + key :user_refs, Integer, :default => 0 + + belongs_to :owner, :class_name => 'User' one :profile, :class_name => 'Profile' + many :posts, :class_name => 'Post', :foreign_key => :person_id many :albums, :class_name => 'Album', :foreign_key => :person_id + timestamps! before_validation :clean_url - validates_presence_of :email, :url, :serialized_key + validates_presence_of :email, :url, :profile, :serialized_key validates_format_of :url, :with => /^(https?):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*(\.[a-z]{2,5})?(:[0-9]{1,5})?(\/.*)?$/ix - validates_true_for :url, :logic => lambda { self.url_unique?} after_destroy :remove_all_traces - scope :friends, where(:_type => "Person", :active => true) def self.search_for_friends(query) Person.all('$where' => "function() { return this.profile.first_name.match(/^#{query}/i) || this.profile.last_name.match(/^#{query}/i); }") @@ -40,25 +43,84 @@ class Person "#{profile.first_name.to_s} #{profile.last_name.to_s}" end - def key + def encryption_key OpenSSL::PKey::RSA.new( serialized_key ) end - def key= new_key + def encryption_key= new_key raise TypeError unless new_key.class == OpenSSL::PKey::RSA serialized_key = new_key.export end def export_key - key.public_key.export + encryption_key.public_key.export end - protected + + ######## Posting ######## + def post(class_name, options = {}) + options[:person] = self + model_class = class_name.to_s.camelize.constantize + post = model_class.instantiate(options) + post.notify_people + post.socket_to_uid owner.id if (owner_id && post.respond_to?( :socket_to_uid)) + post + end + + ######## Commenting ######## + def comment(text, options = {}) + raise "must comment on something!" unless options[:on] + c = Comment.new(:person_id => self.id, :text => text, :post => options[:on]) + if c.save + begin + dispatch_comment c + rescue Exception => e + puts e.inspect + raise e + end + + + c.socket_to_uid owner.id if owner_id + true + else + Rails.logger.warn "this failed to save: #{c.inspect}" + end + false + end + + def dispatch_comment( c ) + if owns? c.post + c.push_downstream + elsif owns? c + c.push_upstream + end + end + ##profile + def update_profile(params) + if self.update_attributes(params) + self.profile.notify_people! + true + else + false + end + end + + def owns?(post) + self.id == post.person.id + end + + def receive_url + "#{self.url}receive/users/#{self.id}/" + end + + def self.by_webfinger( identifier ) + Person.first(:email => identifier.gsub('acct:', '')) + end - def url_unique? - same_url = Person.first(:url => self.url) - return same_url.nil? || same_url.id == self.id + def remote? + owner.nil? end + protected def clean_url self.url ||= "http://localhost:3000/" if self.class == User if self.url diff --git a/app/models/photo.rb b/app/models/photo.rb index e57e2f78d4b0535c711b8db68f9eff7d9db276fc..d93a1189a90c5603d09b662cd416a3ee87800a70 100644 --- a/app/models/photo.rb +++ b/app/models/photo.rb @@ -37,22 +37,20 @@ class Photo < Post end def remote_photo - @remote_photo ||= User.owner.url.chop + image.url + @remote_photo ||= self.person.url.chop + image.url end def remote_photo= remote_path - Rails.logger.info("Setting remote photo with id #{id}") @remote_photo = remote_path image.download! remote_path image.store! - Rails.logger.info("Setting remote photo with id #{id}") end def ensure_user_picture - user = User.owner - if user.profile.image_url == image.url(:thumb_medium) + users = Person.all('profile.image_url' => image.url(:thumb_medium) ) + users.each{ |user| user.profile.update_attributes!(:image_url => nil) - end + } end def thumb_hash diff --git a/app/models/post.rb b/app/models/post.rb index 1b4149fdcbfdad5e7547a6d10aea8b1988761b16..e35b028cde0c3fd80959f969a70f024647806052 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -5,6 +5,7 @@ class Post include ROXML include Diaspora::Webhooks include Encryptable + include Diaspora::Socketable xml_accessor :_id xml_accessor :person, :as => Person @@ -20,11 +21,8 @@ class Post timestamps! - after_save :send_to_view - after_save :notify_people - before_destroy :propagate_retraction - after_destroy :destroy_comments, :remove_from_view + after_destroy :destroy_comments def self.instantiate params self.create params @@ -35,19 +33,10 @@ class Post Post.sort(:created_at.desc).all end - def self.newest(person = nil) - return self.last if person.nil? - + def self.newest_for(person) self.first(:person_id => person.id, :order => '_id desc') end - def self.my_newest - self.newest(User.owner) - end - def self.newest_by_email(email) - self.newest(Person.first(:email => email)) - end - #ENCRYPTION before_validation :sign_if_mine validates_true_for :creator_signature, :logic => lambda {self.verify_creator_signature} @@ -69,10 +58,10 @@ class Post end def log_inspection - Rails.logger.info self.inspect + Rails.logger.debug self.inspect end def log_save_inspection - Rails.logger.info "After saving, object is:" + Rails.logger.debug "After saving, object is:" log_inspection end @@ -85,13 +74,7 @@ protected Retraction.for(self).notify_people end - def send_to_view - SocketsController.new.outgoing(self) - end - - def remove_from_view - SocketsController.new.outgoing(Retraction.for(self)) - end + end diff --git a/app/models/profile.rb b/app/models/profile.rb index bb5176eacf6c660410358a14c1431a6b6e4efefc..9b4c81005428f63d2c5161be442732a8a4f8c6e1 100644 --- a/app/models/profile.rb +++ b/app/models/profile.rb @@ -20,8 +20,7 @@ class Profile self._parent_document.id end - def to_diaspora_xml - "<post>"+ self.to_xml.to_s + "</post>" + def person + Person.first(:id => self.person_id) end - end diff --git a/app/models/request.rb b/app/models/request.rb index f39d1267fbb4fdfc238dad319ab6e98730669de0..99625ad1341013543a7fcea9dc3cc62d8ec65e30 100644 --- a/app/models/request.rb +++ b/app/models/request.rb @@ -15,6 +15,7 @@ class Request key :callback_url, String key :person_id, ObjectId key :exported_key, String + key :group_id, ObjectId belongs_to :person @@ -25,23 +26,35 @@ class Request before_validation :clean_link - scope :for_user, lambda{ |user| where(:destination_url => user.url) } - scope :from_user, lambda{ |user| where(:destination_url.ne => user.url) } + scope :for_user, lambda{ |user| where(:destination_url => user.receive_url) } + scope :from_user, lambda{ |user| where(:destination_url.ne => user.receive_url) } - def self.instantiate(options ={}) + def self.instantiate(options = {}) person = options[:from] - self.new(:destination_url => options[:to], :callback_url => person.url, :person => person, :exported_key => person.export_key) + self.new(:destination_url => options[:to], + :callback_url => person.receive_url, + :person => person, + :exported_key => person.export_key, + :group_id => options[:into]) end - - def activate_friend - p = Person.where(:url => self.person.url).first - p.active = true - p.save + + def reverse accepting_user + self.person = accepting_user.person + self.exported_key = accepting_user.export_key + self.destination_url = self.callback_url + save + end + + def set_pending_friend + p = Person.first(:id => self.person.id) + + self.person.save #save pending friend + end #ENCRYPTION - before_validation :sign_if_mine - validates_true_for :creator_signature, :logic => lambda {self.verify_creator_signature} + #before_validation :sign_if_mine + #validates_true_for :creator_signature, :logic => lambda {self.verify_creator_signature} xml_accessor :creator_signature key :creator_signature, String diff --git a/app/models/retraction.rb b/app/models/retraction.rb index 9a07de141871993c7a85783137918b001d25480d..c9cf8dd77237fa6beb292ee3f2b277b5d2bb7295 100644 --- a/app/models/retraction.rb +++ b/app/models/retraction.rb @@ -5,9 +5,15 @@ class Retraction def self.for(object) retraction = self.new - retraction.post_id= object.id + if object.is_a? User + retraction.post_id = object.person.id + retraction.type = object.person.class.to_s + else + retraction.post_id = object.id + retraction.type = object.class.to_s + end retraction.person_id = person_id_from(object) - retraction.type = object.class.to_s + retraction.send(:sign_if_mine) retraction end @@ -19,10 +25,14 @@ class Retraction attr_accessor :person_id attr_accessor :type - def perform + def perform receiving_user_id + Rails.logger.debug "Performing retraction for #{post_id}" begin - return unless signature_valid? - self.type.constantize.destroy(self.post_id) + return unless signature_valid? + Rails.logger.debug("Retracting #{self.type} id: #{self.post_id}") + target = self.type.constantize.first(self.post_id) + target.unsocket_from_uid receiving_user_id if target.respond_to? :unsocket_from_uid + target.destroy rescue NameError Rails.logger.info("Retraction for unknown type recieved.") end @@ -44,12 +54,22 @@ class Retraction object.person.id end end + + def person + Person.first(:id => self.person_id) + end #ENCRYPTION xml_reader :creator_signature def creator_signature - @creator_signature ||= sign if person_id == User.owner.id + object = self.type.constantize.first(:id => post_id) + + if object.class == Person && person_id == object.id + @creator_signature || sign_with_key(object.key) + elsif person_id == object.person.id + @creator_signature || sign_if_mine + end end def creator_signature= input diff --git a/app/models/status_message.rb b/app/models/status_message.rb index fe641bdb2e95e5be53c18a01c5f3c506252c12a5..3fb9aa39d01447d662de73edc4c4520af9b32f64 100644 --- a/app/models/status_message.rb +++ b/app/models/status_message.rb @@ -13,8 +13,8 @@ class StatusMessage < Post <entry> <activity:verb>http://activitystrea.ms/schema/1.0/post</activity:verb> <title>#{self.message}</title> - <link rel="alternate" type="text/html" href="#{User.owner.url}status_messages/#{self.id}"/> - <id>#{User.owner.url}status_messages/#{self.id}</id> + <link rel="alternate" type="text/html" href="#{person.url}status_messages/#{self.id}"/> + <id>#{person.url}status_messages/#{self.id}</id> <published>#{self.created_at.xmlschema}</published> <updated>#{self.updated_at.xmlschema}</updated> </entry> @@ -22,7 +22,7 @@ class StatusMessage < Post end def latest_hash - {:mine? => self.person == User.owner, :text => message} + { :text => message} end end diff --git a/app/models/user.rb b/app/models/user.rb index 730b2a0c87889325716f0ffa762440c694655a87..16a58862e66558dd4c358296de351e07091fc0af 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,109 +1,188 @@ -class User < Person +class User + include MongoMapper::Document devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable - + key :friend_ids, Array + key :pending_request_ids, Array + + one :person, :class_name => 'Person', :foreign_key => :owner_id + + many :friends, :in => :friend_ids, :class_name => 'Person' + many :pending_requests, :in => :pending_request_ids, :class_name => 'Request' + + many :groups, :class_name => 'Group' + before_validation_on_create :assign_key - validates_presence_of :profile - before_validation :do_bad_things - - ######## Posting ######## + ######## Making things work ######## - def post(class_name, options = {}) - options[:person] = self - model_class = class_name.to_s.camelize.constantize - post = model_class.instantiate(options) + key :email, String + + def method_missing(method, *args) + self.person.send(method, *args) end - ######## Commenting ######## - def comment(text, options = {}) - raise "must comment on something!" unless options[:on] - c = Comment.new(:person_id => self.id, :text => text, :post => options[:on]) - if c.save - if mine?(c.post) - c.push_to(c.post.people_with_permissions) # should return plucky query - else - c.push_to([c.post.person]) - end - true - end - false + + def real_name + "#{person.profile.first_name.to_s} #{person.profile.last_name.to_s}" end - ##profile - def update_profile(params) - if self.update_attributes(params) - puts self.profile.class - self.profile.notify_people! - true - else - false - end + ######### Groups ###################### + + def group( opts = {} ) + opts[:user] = self + Group.create(opts) end - ######### Friend Requesting - def send_friend_request_to(friend_url) - unless Person.where(:url => friend_url).first - p = Request.instantiate(:to => friend_url, :from => self) - if p.save - p.push_to_url friend_url + ######### Friend Requesting ########### + def send_friend_request_to(friend_url, group_id) + unless self.friends.detect{ |x| x.receive_url == friend_url} + request = Request.instantiate(:to => friend_url, :from => self.person, :into => group_id) + if request.save + self.pending_requests << request + self.save + + group = self.group_by_id(group_id) + + group.requests << request + group.save + + request.push_to_url friend_url end - p + request end end - def accept_friend_request(friend_request_id) + def accept_friend_request(friend_request_id, group_id) request = Request.where(:id => friend_request_id).first - request.activate_friend - request.person = self - request.exported_key = self.export_key - request.destination_url = request.callback_url + n = pending_requests.delete(request) + + activate_friend(request.person, group_by_id(group_id)) + + request.reverse self + request + end + + def dispatch_friend_acceptance(request) request.push_to_url(request.callback_url) - request.destroy + request.destroy unless request.callback_url.include? url + end + + def accept_and_respond(friend_request_id, group_id) + dispatch_friend_acceptance(accept_friend_request(friend_request_id, group_id)) end def ignore_friend_request(friend_request_id) request = Request.first(:id => friend_request_id) person = request.person - person.destroy unless person.active + person.user_refs -= 1 + pending_requests.delete(request) + save + (person.user_refs > 0 || person.owner.nil? == false) ? person.save : person.destroy request.destroy end def receive_friend_request(friend_request) Rails.logger.info("receiving friend request #{friend_request.to_json}") - friend_request.person.serialized_key = friend_request.exported_key - if Request.where(:callback_url => friend_request.callback_url).first - friend_request.activate_friend + if request_from_me?(friend_request) + group = self.group_by_id(friend_request.group_id) + activate_friend(friend_request.person, group) + + Rails.logger.info("#{self.real_name}'s friend request has been accepted") friend_request.destroy else + friend_request.person.user_refs += 1 friend_request.person.save + pending_requests << friend_request + save + Rails.logger.info("#{self.real_name} has received a friend request") friend_request.save end end - def unfriend(friend_id) - bad_friend = Person.first(:id => friend_id, :active => true) - if bad_friend - Retraction.for(self).push_to_url(bad_friend.url) - bad_friend.destroy - end + def unfriend(bad_friend) + Rails.logger.info("#{self.real_name} is unfriending #{bad_friend.inspect}") + Retraction.for(self).push_to_url(bad_friend.receive_url) + remove_friend(bad_friend) + end + + def remove_friend(bad_friend) + raise "Friend not deleted" unless self.friend_ids.delete( bad_friend.id ) + groups.each{|g| g.person_ids.delete( bad_friend.id )} + self.save + bad_friend.user_refs -= 1 + (bad_friend.user_refs > 0 || bad_friend.owner.nil? == false) ? bad_friend.save : bad_friend.destroy + end + + def unfriended_by(bad_friend) + Rails.logger.info("#{self.real_name} is being unfriended by #{bad_friend.inspect}") + remove_friend bad_friend end - def send_request(rel_hash) + def send_request(rel_hash, group) if rel_hash[:friend] - self.send_friend_request_to(rel_hash[:friend]) + self.send_friend_request_to(rel_hash[:friend], group) else raise "you can't do anything to that url" end end - + def activate_friend(person, group) + person.user_refs += 1 + group.people << person + friends << person + person.save + group.save + save + end + + def request_from_me?(request) + pending_requests.detect{|req| (req.callback_url == person.receive_url) && (req.destination_url == person.receive_url)} + end + + ###### Receiving ####### + def receive xml + object = Diaspora::Parser.from_xml(xml) + Rails.logger.debug("Receiving object:\n#{object.inspect}") + + if object.is_a? Retraction + if object.type == 'Person' && object.signature_valid? + + Rails.logger.info( "the person id is #{object.post_id} the friend found is #{friend_by_id(object.post_id).inspect}") + unfriended_by friend_by_id(object.post_id) + + else + object.perform self.id + end + elsif object.is_a? Request + person = Diaspora::Parser.get_or_create_person_object_from_xml( xml ) + person.serialized_key ||= object.exported_key + object.person = person + object.person.save + old_request = Request.first(:id => object.id) + object.group_id = old_request.group_id if old_request + object.save + receive_friend_request(object) + elsif object.is_a? Profile + person = Diaspora::Parser.owner_id_from_xml xml + person.profile = object + person.save + elsif object.verify_creator_signature == true + Rails.logger.debug("Saving object: #{object}") + object.save + object.socket_to_uid( id) if (object.respond_to?(:socket_to_uid) && !self.owns?(object)) + dispatch_comment object if object.is_a?(Comment) && !owns?(object) + end + end + ###Helpers############ - def mine?(post) - self == post.person + def self.instantiate( opts = {} ) + opts[:person][:email] = opts[:email] + opts[:person][:serialized_key] = generate_key + User.create( opts) end def terse_url @@ -117,18 +196,29 @@ class User < Person self.password_confirmation = self.password end - def self.owner - User.first + def friend_by_id( id ) + friends.detect{|x| x.id == ensure_bson( id ) } end - + + def group_by_id( id ) + groups.detect{|x| x.id == ensure_bson( id ) } + end + protected def assign_key - self.serialized_key ||= generate_key.export + self.person.serialized_key ||= generate_key.export end def generate_key OpenSSL::PKey::RSA::generate 1024 end + def self.generate_key + OpenSSL::PKey::RSA::generate 1024 + end + + def ensure_bson id + id.class == String ? BSON::ObjectID(id) : id + end end diff --git a/app/uploaders/image_uploader.rb b/app/uploaders/image_uploader.rb index e118e0f844453dffdd488cc93fe11b63b1f52f9f..2a55e30592e564c46ded16c6ea9b7c83f744cdc6 100644 --- a/app/uploaders/image_uploader.rb +++ b/app/uploaders/image_uploader.rb @@ -24,7 +24,7 @@ class ImageUploader < CarrierWave::Uploader::Base end version :thumb_large do - process :resize_to_fill => [300,200] + process :resize_to_fill => [300,300] end version :scaled_full do diff --git a/app/views/albums/_album.html.haml b/app/views/albums/_album.html.haml index d4a629ba0674788d9bab410007552fc15d759dfc..52cb7fe4aea4d276f43a2e4b49f0968ee01b796d 100644 --- a/app/views/albums/_album.html.haml +++ b/app/views/albums/_album.html.haml @@ -1,4 +1,4 @@ -.album{:id => post.id, :class => ("mine" if mine?(post))} +.album{:id => post.id, :class => ("mine" if current_user.owns?(post))} %div.name = link_to post.name, object_path(post) diff --git a/app/views/albums/_new_album.haml b/app/views/albums/_new_album.haml index ae83e0e99e1d40204479d020be5c7a4bc18764d9..a52f0c9ec3fb13f23f81eb3516160cb30c137dcd 100644 --- a/app/views/albums/_new_album.haml +++ b/app/views/albums/_new_album.haml @@ -1,3 +1,5 @@ +%h1 Add a new album + = form_for Album.new do |f| = f.error_messages %p diff --git a/app/views/albums/edit.html.haml b/app/views/albums/edit.html.haml index 3843685e0d6016b847c722527a2c1c59689be46c..b505cf76b626a02c3f369c54ac60d81250ec8098 100644 --- a/app/views/albums/edit.html.haml +++ b/app/views/albums/edit.html.haml @@ -1,6 +1,5 @@ +.back= link_to "⇧ #{@album.name}", @album %h1.big_text - .back - = link_to "⇧ #{@album.name}", @album = "Editing #{@album.name}" @@ -12,6 +11,10 @@ %p = a.text_field :name + %ul + - for photo in @album.photos + %li.photo_edit_block= image_tag photo.image.url(:thumb_large) + #submit_block = link_to "Cancel", root_path or diff --git a/app/views/albums/index.html.haml b/app/views/albums/index.html.haml index 8f3816f3d20f888868222ee4194bd79db9e46662..47d2f68a953c18aa657c30a487e02fa46c24ad2b 100644 --- a/app/views/albums/index.html.haml +++ b/app/views/albums/index.html.haml @@ -1,17 +1,17 @@ +.back= link_to "⇧ home", root_path %h1.big_text - .back - = link_to "⇧ home", root_path Albums - .button.right#add_album_button - = link_to 'New Album', "#" + .right + = link_to 'New Album', '#new_album_pane', {:class => "button", :id => "add_album_button"} - #add_album_box.contextual_pane +.yo{:style => "display:none;" } + #new_album_pane = render "albums/new_album" .sub_header %ul.button_set - %li.selected= friends_albums_link - %li= your_albums_link + %li{:class => ("selected" if params[:friends])}= friends_albums_link + %li{:class => ("selected" if not params[:friends])}= your_albums_link %div - for album in @albums diff --git a/app/views/albums/show.html.haml b/app/views/albums/show.html.haml index 253d94d19792b666ba909a39765d8bf6cf03c21e..b63dea9de9afff13345f3b65eaf58ec7b78f6fc6 100644 --- a/app/views/albums/show.html.haml +++ b/app/views/albums/show.html.haml @@ -1,20 +1,22 @@ +.back= link_to '⇧ albums', albums_path %h1.big_text - .back - = link_to '⇧ albums', albums_path = @album.name - -if mine? @album - .button.right#add_photos_button - = link_to 'Add Photos', '#' + -if current_user.owns? @album + .right + #add_photo_loader + = image_tag 'ajax-loader.gif' + = link_to 'Add Photos', '#new_photo_pane', :class => 'button', :id => "add_photo_button" - #add_photo_box.contextual_pane + .yo{:style => "display:none;"} + #new_photo_pane = render "photos/new_photo", :photo => @photo, :album => @album .sub_header ="updated #{how_long_ago(@album)}" --unless mine? @album +-unless current_user.owns? @album %h4= "by #{@album.person.real_name}" #thumbnails @@ -25,6 +27,7 @@ #content_bottom .back = link_to "⇧ albums", albums_path - -if mine? @album - .button.right - = link_to 'Edit Album', edit_album_path(@album) + + -if current_user.owns? @album + .right + = link_to 'Edit Album', edit_album_path(@album), :class => 'button' diff --git a/app/views/blogs/_blog.html.haml b/app/views/blogs/_blog.html.haml index 79d0612b3a708f5df89bf1ce7ee590c549f1c19f..0896d7d6b08650b2f5024d0a97dfe4accb306d20 100644 --- a/app/views/blogs/_blog.html.haml +++ b/app/views/blogs/_blog.html.haml @@ -1,9 +1,9 @@ -%li.message{:id => post.id, :class => ("mine" if mine?(post))} +%li.message{:id => post.id, :class => ("mine" if current_user.owns?(post))} = person_image_tag(post.person) %span.from - = link_to_person post.person + = link_to post.person.real_name, post.person %b wrote a new blog post %br %b= post.title @@ -15,6 +15,6 @@ = link_to "show comments (#{post.comments.count})", '#', :class => "show_post_comments" = render "comments/comments", :post => post - - if mine?(post) + - if current_user.owns?(post) .destroy_link = link_to 'Delete', blog_path(post), :confirm => 'Are you sure?', :method => :delete, :remote=> true diff --git a/app/views/bookmarks/_bookmark.html.haml b/app/views/bookmarks/_bookmark.html.haml index 8356bf91d0ebbd46e45f57d1ce371663fa85bbcd..5df9f1a253d20b59a3a1bca79bd8885f7217448a 100644 --- a/app/views/bookmarks/_bookmark.html.haml +++ b/app/views/bookmarks/_bookmark.html.haml @@ -1,9 +1,9 @@ -%li.message{:id => post.id, :class => ("mine" if mine?(post))} +%li.message{:id => post.id, :class => ("mine" if current_user.owns?(post))} = person_image_tag(post.person) %span.from - = link_to_person post.person + = link_to post.person.real_name, post.person %b shared a link %br = post.title @@ -16,6 +16,6 @@ = link_to "show comments (#{post.comments.count})", '#', :class => "show_post_comments" = render "comments/comments", :post => post - - if mine?(post) + - if current_user.owns?(post) .destroy_link = link_to 'Delete', bookmark_path(post), :confirm => 'Are you sure?', :method => :delete, :remote => true diff --git a/app/views/comments/_comment.html.haml b/app/views/comments/_comment.html.haml index 8783b4502f23ac44e84c4c91ccf2ed878ee2d80e..0c7fe954d01d1a980b236bebcff4538afea28798 100644 --- a/app/views/comments/_comment.html.haml +++ b/app/views/comments/_comment.html.haml @@ -1,7 +1,7 @@ %li.comment{:id => post.id} = person_image_tag(post.person) %span.from - = link_to_person post.person + = link_to post.person.real_name, post.person = auto_link post.text %div.time = "#{time_ago_in_words(post.updated_at)} ago" diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml index b03da351897847985d8258fe82d03e132a436548..8e268c9260c0b29fcd4ca5f832c9b12790b7e2aa 100644 --- a/app/views/devise/registrations/new.html.haml +++ b/app/views/devise/registrations/new.html.haml @@ -1,17 +1,29 @@ += image_tag "http://needcoffee.cachefly.net/needcoffee/uploads/2009/02/predator-arnold-schwarzenegger.jpg" + + %h2 Sign up = form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| = devise_error_messages! %p = f.label :email - %br/ = f.text_field :email %p = f.label :password - %br/ = f.password_field :password %p = f.label :password_confirmation - %br/ = f.password_field :password_confirmation + + = f.fields_for :person do |p| + = p.hidden_field :url, :value => "http://google.com/" + + = p.fields_for :profile do |pr| + %p + = pr.label :first_name + = pr.text_field :first_name + %p + = pr.label :last_name + = pr.text_field :last_name + %p= f.submit "Sign up" = render :partial => "devise/shared/links" diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml index 96b9ca9c4e8c619ffe75a061fb825f1b955c4efb..a36917c7b7a40388023f88d22b7c4c42b3391416 100644 --- a/app/views/devise/sessions/new.html.haml +++ b/app/views/devise/sessions/new.html.haml @@ -1,12 +1,13 @@ = form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %p + = f.text_field :email + %br = f.password_field :password + /%p + /- if devise_mapping.rememberable? + / = f.check_box :remember_me + / = f.label :remember_me %p - - if devise_mapping.rememberable? - /= f.check_box :remember_me - /= f.label :remember_me - - = hidden_field_tag "user_email", "#{User.owner.email}", :name => "user[email]" = f.submit "Sign in" -/= render :partial => "devise/shared/links" += render :partial => "devise/shared/links" diff --git a/app/views/groups/_new_group.haml b/app/views/groups/_new_group.haml new file mode 100644 index 0000000000000000000000000000000000000000..5ac136eae5d88aa9894f6f703481a147b7371833 --- /dev/null +++ b/app/views/groups/_new_group.haml @@ -0,0 +1,7 @@ +%h1 Add a new group += form_for Group.new do |f| + = f.error_messages + %p + = f.label :name + = f.text_field :name + = f.submit 'create', :class => 'button' diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..461bff1dba75673aa9eb2d4f1da00ba437ac3d73 --- /dev/null +++ b/app/views/groups/edit.html.haml @@ -0,0 +1,25 @@ +%h1.big_text + .back + = link_to "⇧ #{@group.name}", @group + + = "Editing #{@group.name}" + +.sub_header + ="updated #{how_long_ago(@group)}" + +- form_for @group do |a| + = a.error_messages + %p + = a.text_field :name + + #submit_block + = link_to "Cancel", root_path + or + = a.submit + +.button.delete + = link_to 'Delete Album', @group, :confirm => 'Are you sure?', :method => :delete + +#content_bottom + .back + = link_to "⇧ #{@group.name}", @group diff --git a/app/views/groups/index.html.haml b/app/views/groups/index.html.haml new file mode 100644 index 0000000000000000000000000000000000000000..b3b4d2acb8a7c1e83526135da400d964de4f23f7 --- /dev/null +++ b/app/views/groups/index.html.haml @@ -0,0 +1,11 @@ +%h1 + welcome home, + = current_user.profile.first_name + += render "shared/publisher" +%ul#stream + - for post in @posts + = render type_partial(post), :post => post +#pagination + = will_paginate @posts + diff --git a/app/views/albums/new.html.haml b/app/views/groups/new.html.haml similarity index 50% rename from app/views/albums/new.html.haml rename to app/views/groups/new.html.haml index 2f4450cd90550eb759cd798d629bfec651ff281a..c899fd9aec3bc675440e7edf07e096ce4b114719 100644 --- a/app/views/albums/new.html.haml +++ b/app/views/groups/new.html.haml @@ -1,9 +1,9 @@ %h1.big_text - =link_to 'albums', albums_path + =link_to 'groups', groups_path >> - new album + new group -= form_for @album do |f| += form_for @group do |f| = f.error_messages %p = f.label :name @@ -11,4 +11,4 @@ %p = f.submit -%p= link_to "Back to List", albums_path +%p= link_to "Back to List", groups_path diff --git a/app/views/dashboards/index.html.haml b/app/views/groups/show.html.haml similarity index 100% rename from app/views/dashboards/index.html.haml rename to app/views/groups/show.html.haml diff --git a/app/views/js/_websocket_js.haml b/app/views/js/_websocket_js.haml index 768c03cb7a3d38329468ce4ba6f70dd6a16d2818..e6596276158dad5513da5f4251aa6774faf8c239 100644 --- a/app/views/js/_websocket_js.haml +++ b/app/views/js/_websocket_js.haml @@ -7,7 +7,9 @@ $(document).ready(function(){ function debug(str){ $("#debug").append("<p>" + str); }; - ws = new WebSocket("ws://#{request.host}:8080/"); + ws = new WebSocket("ws://#{request.host}:8080/#{CGI::escape(current_user.id.to_s)}"); + + //Attach onmessage to websocket ws.onmessage = function(evt) { var obj = jQuery.parseJSON(evt.data); debug("got a " + obj['class']); @@ -62,6 +64,7 @@ function processStatusMessage(className, html, messageHash){ processPost(className, html); + console.log(messageHash) if(messageHash['mine?']){ updateMyLatestStatus(messageHash); } @@ -76,7 +79,7 @@ if (location.href.indexOf(photoHash['album_id']) == -1){ return ; } - html = "<div class=\'image_thumb\' id=\'"+photoHash['id']+"\'> \ + html = "<div class=\'image_thumb\' id=\'"+photoHash['id']+"\' style=\'padding-right:3px;\'> \ <a href=\"/photos/"+ photoHash['id'] +"\"> \ <img alt=\"New thumbnail\" src=\""+ photoHash['thumb_url'] +"\" /> \ </a> </div>" diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 4eb0281a4cbda35d3f0a01d0c68d3bc8f4725d09..62d0c4eb164723f8d00ec4148b7dee617285e83c 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -8,11 +8,17 @@ = stylesheet_link_tag "blueprint/screen", :media => 'screen' = stylesheet_link_tag "application", "ui", 'bubble' + + = stylesheet_link_tag "/../javascripts/fancybox/jquery.fancybox-1.3.1" + /= javascript_include_tag "http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" = javascript_include_tag 'jquery142', 'rails', 'google' - = javascript_include_tag 'tiny_mce/tiny_mce', 'jquery.infieldlabel' - = javascript_include_tag 'jquery.cycle/jquery.cycle.min.js' - = javascript_include_tag 'view', 'publisher', 'image_picker' + = javascript_include_tag 'tiny_mce/tiny_mce' + = javascript_include_tag 'jquery.infieldlabel', 'jquery.cycle/jquery.cycle.min.js' + + = javascript_include_tag 'fancybox/jquery.fancybox-1.3.1.pack' + + = javascript_include_tag 'view', 'publisher', 'image_picker', 'group_nav' = render 'js/websocket_js' = csrf_meta_tag @@ -23,51 +29,31 @@ = javascript_include_tag 'jquery.html5_upload' %body + - flash.each do |name, msg| + = content_tag :div, msg, :id => "flash_#{name}" + %header .container - - flash.each do |name, msg| - = content_tag :div, msg, :id => "flash_#{name}" - #diaspora_text{:href => root_path} - = link_to "DIASPORA*", root_path - %span.sub_text - PREVIEW - #session_action - if user_signed_in? - = link_to_person current_user - | - = link_to "requests (#{@request_count})", requests_path, :class => new_request(@request_count) - | - = link_to "logout", destroy_user_session_path + %ul#user_menu + %li.name= link_to current_user.real_name, current_user.person + %li= link_to "requests (#{@request_count})", requests_path, :class => new_request(@request_count) + %li= link_to "settings", edit_user_path(current_user) + %li= link_to "logout", destroy_user_session_path - else = link_to "login", new_user_session_path - .container - - if user_signed_in? - #user_name - = link_to(person_image_tag(current_user), root_path) - %h1 - = link_to current_user.real_name, root_path - %span#latest_message - = my_latest_message - - unless @latest_status_message.nil? - %span{:style => "font-size: small", :id => 'latest_message_time'} - = " - #{how_long_ago @latest_status_message}" + #diaspora_text{:href => root_path} + = link_to "DIASPORA*", root_path + %span.sub_text + PREVIEW + = render "shared/group_nav" - %ul.nav - %li= link_to "home", root_path - %li= link_to "photos", albums_path - %li= "|" - %li= link_to "edit profile", edit_user_path(current_user) + = link_to "photos", albums_path .container .span-24.last - .span-20.append-1.last - - = yield - - .span-3.last - = render 'people/sidebar' if user_signed_in? - - .span-24.last - = render "posts/debug" + = yield + .span-24.last + = render "posts/debug" diff --git a/app/views/layouts/session_wall.html.haml b/app/views/layouts/session_wall.html.haml index 3b85566bcd28bf9f5d4fb02568a980a724afebc6..95d0f7e3479a0dcfb8c4dea5502a24efabd83555 100644 --- a/app/views/layouts/session_wall.html.haml +++ b/app/views/layouts/session_wall.html.haml @@ -13,7 +13,7 @@ :javascript $(document).ready(function(){ - $("#user_password").focus(); + $("#user_email").focus(); }); = csrf_meta_tag @@ -40,18 +40,10 @@ </div> <![endif]--> - - - flash.each do |name, msg| = content_tag :div, msg, :id => "flash_#{name}" - - if User.owner - %div#huge_text - welcome back, - %span - = User.owner.real_name.downcase - = yield - -else - %div#huge_text - %span - you need to add a user first! - + %div#huge_text + diaspora + = yield + + /= link_to "signup", "/signup" diff --git a/app/views/photos/_new_photo.haml b/app/views/photos/_new_photo.haml index 23e4ad68c225087b367a64cd6627e66ebef47d5d..b577315967f91457c485f21d5f9071c9c61618da 100644 --- a/app/views/photos/_new_photo.haml +++ b/app/views/photos/_new_photo.haml @@ -4,45 +4,38 @@ // WE INSERT ALBUM_ID PARAM HERE url: "/photos?album_id=#{album.id}", sendBoundary: window.FormData || $.browser.mozilla, - onStart: function(event, total) { - return confirm("You are about to upload " + total + " photos. Are you sure?"); - }, setName: function(text) { $("#progress_report_name").text(text); }, - setStatus: function(text) { - $("#progress_report_status").text(text); - }, - setProgress: function(val) { - //$("#progress_report_bar").css('width', Math.ceil(val*100)+"%"); - }, - onFinishOne: function(event, response, name, number, total) { - //alert(response); - }, onFinish: function(event, total){ - $("#progress_report").delay(600).slideUp(200); - $("#add_photo_box").delay(600).fadeOut(200); + $("#add_photo_button").html( "Add Photos" ); + $("#add_photo_loader").fadeOut(400); + + $("#photo_title_status").text("Done!"); + $("#progress_report").html("Great job!"); }, onStart: function(event, total){ - $("#progress_report").slideDown(600); + $("#add_photo_button").html( "Uploading Photos" ); + $("#add_photo_loader").fadeIn(400); + + $("form").fadeOut(0); + $("#progress_report").fadeIn(0); + $("#photo_title_status").text("Uploading..."); return true; } }); }); -:css - #progress_report, #progress_report_name, #progress_report_status{ - font-size: 12px; - padding: 0; - line-height: auto; - } - +%h1 + %span{:id=>"photo_title_status"} + Add photos to + %i= album.name = form_for photo, :html => {:multipart => true} do |f| = f.error_messages = f.hidden_field :album_id, :value => album.id = f.file_field :image, :multiple => 'multiple' - #progress_report{ :style => "display:none;" } - = image_tag "loader.gif" - #progress_report_name - #progress_report_status{ :style => "font-style: italic;" } +#progress_report{ :style => "display:none;text-align:center;" } + = image_tag "ajax-loader.gif" + #progress_report_name + #progress_report_status diff --git a/app/views/photos/_photo.haml b/app/views/photos/_photo.haml index 9b663531a1f51cdca5158c5bbf2aa303a23b3f33..e6734639a40852c660961cec1bfd9c78c5a4ec14 100644 --- a/app/views/photos/_photo.haml +++ b/app/views/photos/_photo.haml @@ -2,7 +2,7 @@ = person_image_tag(post.person) %span.from - = link_to_person post.person + = link_to post.person.real_name, post.person %b posted a new photo to = link_to post.album.name, object_path(post.album) diff --git a/app/views/photos/edit.html.haml b/app/views/photos/edit.html.haml index c849b43b7979ac84d3ad407169826164ad510bee..baeb82a3d81ad7787776ae7aff0b50e49f69e004 100644 --- a/app/views/photos/edit.html.haml +++ b/app/views/photos/edit.html.haml @@ -15,7 +15,7 @@ #content_bottom .back = link_to "⇧ #{@album.name}", album_path(@album) - -if mine? @album + -if current_user.owns? @album .button.right = link_to 'Delete Photo', @photo, :confirm => 'Are you sure?', :method => :delete diff --git a/app/views/photos/show.html.haml b/app/views/photos/show.html.haml index d0879065077476f5d9dc336acacace27cecbd8d5..05443591f847f29762c16bdb90d1ec204aa5e513 100644 --- a/app/views/photos/show.html.haml +++ b/app/views/photos/show.html.haml @@ -1,33 +1,30 @@ +.back= link_to "⇧ #{@album.name}", album_path(@album) %h1.big_text - .back - = link_to "⇧ #{@album.name}", album_path(@album) = @photo.image - .button.right - = link_to 'Edit Photo', edit_photo_path(@photo) + .right + = link_to 'Edit Photo', edit_photo_path(@photo), :class => "button" .sub_header + = link_to_prev @photo, @album + | = link_to "full size", @photo.image.url + | + = link_to_next @photo, @album %div{:id => @photo.id} - #show_photo = linked_scaled_photo @photo, @album - .caption = @photo.caption - #next_prev_links - = link_to_prev @photo, @album - | - = link_to_next @photo, @album - #content_bottom .back = link_to "⇧ #{@album.name}", album_path(@album) - -if mine? @album - .button.right - = link_to 'Delete Photo', @photo, :confirm => 'Are you sure?', :method => :delete + + -if current_user.owns? @album + .right + = link_to 'Delete Photo', @photo, :confirm => 'Are you sure?', :method => :delete, :class => 'button' %h4{:class => "show_post_comments"} = "comments (#{@photo.comments.count})" diff --git a/app/views/publics/hcard.erb b/app/views/publics/hcard.erb index 34f88866e3bcdd136eea0376fee7bb857b41a797..7cfbe56040daeee027bcbee132b235f184f50e50 100644 --- a/app/views/publics/hcard.erb +++ b/app/views/publics/hcard.erb @@ -1,24 +1,24 @@ <div id="content"> - <h1><%=@user.real_name%></h1> + <h1><%=@person.real_name%></h1> <div id="content_inner"> <div id="i" class="entity_profile vcard author"> <h2>User profile</h2> <dl class="entity_nickname"> <dt>Nickname</dt> <dd> - <a href="<%=@user.url%>" rel="me" class="nickname url uid"><%= @user.real_name%></a> + <a href="<%=@person.url%>" rel="me" class="nickname url uid"><%= @person.real_name%></a> </dd> </dl> <dl class="entity_fn"> <dt>Full name</dt> <dd> - <span class="fn"><%= @user.real_name %></span> + <span class="fn"><%= @person.real_name %></span> </dd> </dl> <dl class="entity_url"> <dt>URL</dt> <dd> - <a href="<%= @user.url%>" rel="me" class="url"><%= @user.url%></a> + <a href="<%= @person.url%>" rel="me" class="url"><%= @person.url%></a> </dd> </dl> <dl class="entity_note"> diff --git a/app/views/publics/host_meta.erb b/app/views/publics/host_meta.erb index 53d8aeba49f64d7a588653fc1cb9dc6d633963cb..e28fb62117c7e719a8a23567499b1716f7643843 100644 --- a/app/views/publics/host_meta.erb +++ b/app/views/publics/host_meta.erb @@ -1,9 +1,9 @@ <?xml version='1.0' encoding='UTF-8'?> <XRD xmlns='http://docs.oasis-open.org/ns/xri/xrd-1.0' xmlns:hm='http://host-meta.net/xrd/1.0'> - <hm:Host><%= @user.terse_url %></hm:Host> + <hm:Host><%= terse_url(root_url) %></hm:Host> <Link rel='lrdd' - template='<%=@user.url%>webfinger?q={uri}'> + template='<%= root_url %>webfinger?q={uri}'> <Title>Resource Descriptor</Title> </Link> </XRD> diff --git a/app/views/publics/webfinger.erb b/app/views/publics/webfinger.erb index bafd58acb56e5d6e8a2cf6f5f8ae479efeaf0398..db4cd3a1cd069041cb0a5adbcb70040160eee29a 100644 --- a/app/views/publics/webfinger.erb +++ b/app/views/publics/webfinger.erb @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0"> - <Subject>acct:<%=@user.email%></Subject> - <Alias>"<%=@user.url%>hcard"</Alias> - <Link rel="http://microformats.org/profile/hcard" type="text/html" href="<%=@user.url%>hcard"/> - <Link rel="http://schemas.google.com/g/2010#updates-from" type="application/atom+xml" href="<%=@user.url%>status_messages.atom"/> - <Link rel="http://joindiaspora.com/seed_location" type = 'text/html' href="<%=@user.url%>"/> + <Subject>acct:<%=@person.email%></Subject> + <Alias>"<%= @person.url %>users/#{@user.id}/hcard"</Alias> + <Link rel="http://microformats.org/profile/hcard" type="text/html" href="<%=@person.url%>hcard"/> + <Link rel="http://schemas.google.com/g/2010#updates-from" type="application/atom+xml" href="<%=@person.url%>status_messages.atom"/> + <Link rel="http://joindiaspora.com/seed_location" type = 'text/html' href="<%=@person.receive_url%>"/> </XRD> diff --git a/app/views/requests/_new_request.haml b/app/views/requests/_new_request.haml index 714168fd23c80c2778951095f458269bebcee11c..42cd8b5e5cbc072928dc340d650420572ff05d96 100644 --- a/app/views/requests/_new_request.haml +++ b/app/views/requests/_new_request.haml @@ -1,8 +1,12 @@ -= form_for @request do |f| +%h1 + Add a new friend to + %i= @group.name + += form_for Request.new do |f| = f.error_messages Enter a Diaspora URL, Diaspora username, or random email address: - .field_with_submit - = f.text_field :destination_url - = f.submit + = f.text_field :destination_url + = f.hidden_field :group, :value => @group.id + = f.submit diff --git a/app/views/requests/_request.html.haml b/app/views/requests/_request.html.haml index 03ab427f3b333a8990bee680e71b2f101ded5323..3cd2c398f78f9643e9125848af663293b6ddce83 100644 --- a/app/views/requests/_request.html.haml +++ b/app/views/requests/_request.html.haml @@ -1,8 +1,23 @@ +:javascript + $(document).ready(function(){ + $(".group_selector").change( function() { + var id = $(this).children(":selected").val(); + $(this).parent().children(".accept").html( "<a href=\"/requests/#{request.id}/?accept=true&group_id="+id+"\" data-method=\"delete\" rel=\"nofollow\" class=\"button\">Accept</a>"); + }); + }); + + %li.message{:id => request.id} %span.from = link_to "#{request.person.real_name}", '#' %ul.request_buttons - %li= link_to 'Accept', request_path(request, :accept => true), :method => :delete - %li= link_to 'Ignore', request_path(request), :confirm => 'Are you sure?', :method => :delete + %select{ :class => "group_selector", :style=>"display:inline;"} + %option Add to group + %option + - for group in current_user.groups + %option{:value => group.id}= group.name + %li.accept= link_to 'Accept', request_path(request, :accept => true), :method => :delete, :class => "button" + %li.ignore= link_to 'Ignore', request_path(request), :confirm => 'Are you sure?', :method => :delete, :class => "button" + diff --git a/app/views/requests/index.html.haml b/app/views/requests/index.html.haml index 8278719ee5bc049290ca56134d9509d32dfbf80e..6ba3067c547fae77c60a230bbe6d8007eaf0dae5 100644 --- a/app/views/requests/index.html.haml +++ b/app/views/requests/index.html.haml @@ -3,10 +3,7 @@ = link_to "⇧ home", root_path Requests -= render "requests/new_request", :request => @request - %h3= "currently #{@request_count} requests" - %ul#stream - for request in @remote_requests = render "request", :request => request diff --git a/app/views/shared/_group_nav.haml b/app/views/shared/_group_nav.haml new file mode 100644 index 0000000000000000000000000000000000000000..66f4fa0bdeef9df0131649ba7650eb58ff2f7a0f --- /dev/null +++ b/app/views/shared/_group_nav.haml @@ -0,0 +1,21 @@ +#group + %ul + - for group in @groups + %li{:class => ("selected" if group.id.to_s == params[:id])} + = link_to group.name, group + + %li.new_group= link_to("NEW GROUP", "#add_group_pane", :id => "add_group_button") + + .yo{ :style => "display:none;"} + #add_group_pane + = render "groups/new_group" + + - if @group + #friend_pictures + - for friend in @group.people + = person_image_link(friend) + = link_to "+", "#add_request_pane", :id => 'add_request_button', :class => "add_new" + + .yo{:style => 'display:none'} + #add_request_pane + = render "requests/new_request" diff --git a/app/views/shared/_post_wrapper.haml b/app/views/shared/_post_wrapper.haml index bdba9db700bd28e792e7a1f438c6136f9b532037..a65866a084736e2d91d28f8be2b5e17621e1415a 100644 --- a/app/views/shared/_post_wrapper.haml +++ b/app/views/shared/_post_wrapper.haml @@ -1,4 +1,4 @@ -%li.message{:id => post.id, :class => ("mine" if mine?(post))} +%li.message{:id => post.id, :class => ("mine" if current_user.owns?(post))} = person_image_link(post.person) = yield post_yield_tag(post) - = = render type_partial(post), :post => post \ No newline at end of file + = = render type_partial(post), :post => post diff --git a/app/views/status_messages/_status_message.html.haml b/app/views/status_messages/_status_message.html.haml index 5681e9753add2999173e990af088a7058e505073..c6099504e5018031c343056557f384c59da51c75 100644 --- a/app/views/status_messages/_status_message.html.haml +++ b/app/views/status_messages/_status_message.html.haml @@ -1,10 +1,10 @@ -%li.message{:id => post.id, :class => ("mine" if mine?(post))} +%li.message{:id => post.id, :class => ("mine" if current_user.owns?(post))} = person_image_link(post.person) %span.from = link_to post.person.real_name, post.person - = auto_link post.message + = auto_link sanitize post.message %div.time = link_to(how_long_ago(post), object_path(post)) @@ -12,6 +12,6 @@ = link_to "show comments (#{post.comments.count})", '#', :class => "show_post_comments" = render "comments/comments", :post => post - - if mine?(post) + - if current_user.owns?(post) .destroy_link - = link_to 'Delete', status_message_path(post), :confirm => 'Are you sure?', :method => :delete, :remote => true + = link_to 'Delete', status_message_path(post), :confirm => 'Are you sure?', :method => :delete, :remote => true, :class => "delete" diff --git a/app/views/users/show.html.haml b/app/views/users/show.html.haml index 9182161a31d2c63e87dcd017c8e782ad47a422f3..b678b43776639f8e94c990c6eb1d7796848918ac 100644 --- a/app/views/users/show.html.haml +++ b/app/views/users/show.html.haml @@ -6,6 +6,6 @@ %p = @user.url %p - %b Key Fingerprint + %b Serialized Key %p - = @user.key_fingerprint + = @user.serialized_key diff --git a/config/initializers/logging.rb b/config/initializers/logging.rb new file mode 100644 index 0000000000000000000000000000000000000000..447ec5c17e2b0e423c7a042e3eb71f99b7a07c12 --- /dev/null +++ b/config/initializers/logging.rb @@ -0,0 +1,2 @@ +Rails.logger = Logger.new( + Rails.root.join("log",Rails.env + ".log"),3,5*1024*1024) diff --git a/config/initializers/socket.rb b/config/initializers/socket.rb index aebf023f3a92e2cb8865f5dc3653b76d51fa8af1..0f4e68f7b0e2990c9bc7b26335e59eb024f3061d 100644 --- a/config/initializers/socket.rb +++ b/config/initializers/socket.rb @@ -1,41 +1,21 @@ require 'em-websocket' require 'eventmachine' - -module WebSocket +require "lib/diaspora/websocket" EM.next_tick { - initialize_channel + Diaspora::WebSocket.initialize_channels EventMachine::WebSocket.start( :host => "0.0.0.0", :port => APP_CONFIG[:socket_port], :debug =>APP_CONFIG[:debug]) do |ws| ws.onopen { - @ws = ws - sid = @channel.subscribe{ |msg| ws.send msg }#SocketsController.new.new_subscriber + + sid = Diaspora::WebSocket.subscribe(ws.request['Path'].gsub('/',''), ws) ws.onmessage { |msg| SocketsController.new.incoming(msg) }#@channel.push msg; puts msg} - ws.onclose { SocketsController.new.delete_subscriber(sid) } + ws.onclose { Diaspora::WebSocket.unsubscribe(ws.request['Path'].gsub('/',''), sid) } } end } - def self.initialize_channel - @channel = EM::Channel.new - end - - def self.push_to_clients(html) - @channel.push(html) - end - - def self.unsubscribe(sid) - @channel.unsubscribe(sid) - end - - - def self.subscribe - @channel.subscribe{ |msg| ws.send msg } - end - -end - diff --git a/config/routes.rb b/config/routes.rb index 3726f5bf48f29cb3a1c993cadb0029c25b05391c..88c838d77c2aa9367160edaea28e7118a27883ea 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -8,28 +8,29 @@ Diaspora::Application.routes.draw do |map| resources :requests resources :photos resources :albums + resources :groups match "/images/files/*path" => "gridfs#serve" - match 'warzombie', :to => "dev_utilities#warzombie" - match 'zombiefriends', :to => "dev_utilities#zombiefriends" + match 'warzombie', :to => "dev_utilities#warzombie" + match 'zombiefriends', :to => "dev_utilities#zombiefriends" match 'zombiefriendaccept', :to => "dev_utilities#zombiefriendaccept" + match 'set_backer_number', :to => "dev_utilities#set_backer_number" #routes for devise, not really sure you will need to mess with this in the future, lets put default, #non mutable stuff in anohter file - devise_for :users, :path_names => {:sign_up => "signup", :sign_in => "login", :sign_out => "logout"} - match 'login', :to => 'devise/sessions#new', :as => "new_user_session" - match 'logout', :to => 'devise/sessions#destroy', :as => "destroy_user_session" - #match 'signup', :to => 'devise/registrations#new', :as => "new_user_registration" - resources :users - + devise_for :users, :path_names => {:sign_up => "get_to_the_choppa", :sign_in => "login", :sign_out => "logout"} + match 'login', :to => 'devise/sessions#new', :as => "new_user_session" + match 'logout', :to => 'devise/sessions#destroy', :as => "destroy_user_session" + match 'get_to_the_choppa', :to => 'devise/registrations#new', :as => "new_user_registration" #public routes - match 'receive', :to => 'publics#receive' - match '.well-known/host-meta',:to => 'publics#host_meta' - match 'webfinger', :to => 'publics#webfinger' - match 'hcard', :to => 'publics#hcard' - + # + match 'webfinger', :to => 'publics#webfinger' + match 'users/:id/hcard', :to => 'publics#hcard' + + match '.well-known/host-meta',:to => 'publics#host_meta' + match 'receive/users/:id', :to => 'publics#receive' #root - root :to => 'dashboards#index' + root :to => 'groups#index' end diff --git a/db/seeds/backer.rb b/db/seeds/backer.rb index f9f8ba3664996f4e8025d5cd8f1cb268f0f73bd3..bc5039aa16316821da29b2833d38fd1944ac0981 100644 --- a/db/seeds/backer.rb +++ b/db/seeds/backer.rb @@ -8,26 +8,21 @@ require 'config/environment' -def create(backer_number) +def create config = YAML.load_file(File.dirname(__FILE__) + '/../../config/deploy_config.yml') backer_info = config['servers']['backer'] - + backer_number = YAML.load_file(Rails.root.join('config','backer_number.yml'))[:seed_number].to_i # Create seed user username = backer_info[backer_number]['username'].gsub(/ /,'').downcase user = User.create( :email => "#{username}@#{username}.joindiaspora.com", :password => "#{username+backer_info[backer_number]['pin'].to_s}", - :profile => Profile.new( :first_name => backer_info[backer_number]['given_name'], :last_name => backer_info[backer_number]['family_name'] ), - :url=> "#{username}.joindiaspora.com") - - # Make connection with Diaspora Tom - #Person.create( :email => "tom@joindiaspora.com", :url => "http://tom.joindiaspora.com/", :active => true, :profile => Profile.new(:first_name => "Alexander", :last_name => "Hamiltom")) - # Make people - -# (0..10).each { |n| - #domain_name = backer_info[n][2].gsub(/ /,'').downcase - #url = "http://#{domain_name}.joindiaspora.com/" - #User.owner.send_friend_request_to(url) - #} + :person => Person.new( + :email => "#{username}@#{username}.joindiaspora.com", + :profile => Profile.new( :first_name => backer_info[backer_number]['given_name'], :last_name => backer_info[backer_number]['family_name'] ), + :url=> "http://#{username}.joindiaspora.com/") + ) + user.person.save + user.group(:name => "Presidents") end diff --git a/db/seeds/dev.rb b/db/seeds/dev.rb index 9bf7adb8008c012cd80c8a61b1c92395eab864a9..f13e27f4cd05c06745f105c31c41e4850604e8a3 100644 --- a/db/seeds/dev.rb +++ b/db/seeds/dev.rb @@ -9,5 +9,17 @@ require 'config/environment' # Create seed user -user = User.create( :email => "robert@joindiaspora.com", :password => "evankorth", :profile => Profile.new( :first_name => "bobert", :last_name => "brin" )) +user = User.create( :email => "robert@joindiaspora.com", + :password => "evankorth", + :person => Person.new( + :email => "robert@joindiaspora.com", + :url => "http://localhost:3000/", + :profile => Profile.new( + :first_name => "bobert", + :last_name => "brin" ))) +puts user.save +puts user.person.save! +puts user.save! +puts user.person.inspect +puts user.inspect diff --git a/db/seeds/tom.rb b/db/seeds/tom.rb index 4efae222d1afb013cff3525fd42b5946c46584b2..c8b1d41a6062d042bd97dcdc0889830a5503c63e 100644 --- a/db/seeds/tom.rb +++ b/db/seeds/tom.rb @@ -1,13 +1,27 @@ -#This file should contain all the record creation needed to seed the database with its default values. -# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup). -# -# Examples: -# -# cities = City.create([{ :name => 'Chicago' }, { :name => 'Copenhagen' }]) -# Mayor.create(:name => 'Daley', :city => citie - require 'config/environment' +remote_url = "http://tom.joindiaspora.com/" # Create seed user -user = User.create( :email => "tom@tom.joindiaspora.com", :password => "evankorth", :url => "http://tom.joindiaspora.com/", :profile => Profile.new( :first_name => "Alexander", :last_name => "Hamiltom" )) +user = User.create!( :email => "tom@tom.joindiaspora.com", + :password => "evankorth", + :person => Person.new( + :email => "tom@tom.joindiaspora.com", + :url => remote_url, + :profile => Profile.new( :first_name => "Alexander", :last_name => "Hamiltom" )) + ) +user.person.save! + +user2 = User.create!( :email => "korth@tom.joindiaspora.com", + :password => "evankorth", + :person => Person.new( :email => "korth@tom.joindiaspora.com", + :url => remote_url, + :profile => Profile.new( :first_name => "Evan", + :last_name => "Korth"))) + +user2.person.save! +# friending users +group = user.group(:name => "other dudes") +request = user.send_friend_request_to(user2.receive_url, group.id) +reversed_request = user2.accept_friend_request( request.id, user2.group(:name => "presidents").id ) +user.receive reversed_request.to_diaspora_xml diff --git a/lib/diaspora/parser.rb b/lib/diaspora/parser.rb index 07439dbb90d96212f0827531209c8d3e8ed5430e..8835bd83bc57b96e22d255cb01fb81a339cf8dbb 100644 --- a/lib/diaspora/parser.rb +++ b/lib/diaspora/parser.rb @@ -1,57 +1,33 @@ module Diaspora module Parser - def parse_owner_from_xml(xml) + def self.owner_id_from_xml(xml) doc = Nokogiri::XML(xml) { |cfg| cfg.noblanks } - email = doc.xpath("//person/email").text.to_s - Person.first(:email => email) + id = doc.xpath("//person_id").text.to_s + Person.first(:id => id) end - def parse_body_contents_from_xml(xml) + def self.get_or_create_person_object_from_xml(xml) doc = Nokogiri::XML(xml) { |cfg| cfg.noblanks } - doc.xpath("/XML/posts/post") - end - - def parse_owner_id_from_xml(doc) - id = doc.xpath("//person_id").text.to_s - Person.first(:id => id) + person_xml = doc.xpath("//request/person").to_s + person_id = doc.xpath("//request/person/_id").text.to_s + person = Person.first(:_id => person_id) + person ? person : Person.from_xml( person_xml) end - def parse_objects_from_xml(xml) - objects = [] - body = parse_body_contents_from_xml(xml) - body.children.each do |post| - begin - object = post.name.camelize.constantize.from_xml post.to_s - if object.respond_to? :person - object.person = parse_owner_from_xml post.to_s - elsif object.is_a? Profile - puts "got into parse objects from xml PROFILE" - person = parse_owner_id_from_xml post - person.profile = object - person.save - end - objects << object - rescue + def self.from_xml(xml) + + doc = Nokogiri::XML(xml) { |cfg| cfg.noblanks } + return unless body = doc.xpath("/XML/post").children.first + + begin + body.name.camelize.constantize.from_xml body.to_s + rescue NameError => e + if e.message.include? 'wrong constant name' Rails.logger.info "Not a real type: #{object.to_s}" end + raise e end - objects end - def store_objects_from_xml(xml) - objects = parse_objects_from_xml(xml) - objects.each do |p| - Rails.logger.info("Receiving object:\n#{p.inspect}") - if p.is_a? Retraction - p.perform - elsif p.is_a? Request - User.owner.receive_friend_request(p) - elsif p.is_a? Profile - p.save - elsif p.respond_to?(:person) && !(p.person.nil?) && !(p.person.is_a? User) - Rails.logger.info("Saving object with success: #{p.save}") - end - end - end end end diff --git a/lib/diaspora/webhooks.rb b/lib/diaspora/webhooks.rb index c6003e9578087734fc850a435f49ce10382f5c4f..dba3968e2161bb5ff504650bfc70f34604204e88 100644 --- a/lib/diaspora/webhooks.rb +++ b/lib/diaspora/webhooks.rb @@ -7,7 +7,7 @@ module Diaspora @@queue = MessageHandler.new def notify_people - if self.person_id == User.owner.id + unless self.person.owner.nil? push_to(people_with_permissions) end end @@ -18,37 +18,37 @@ module Diaspora def push_to(recipients) unless recipients.empty? - recipients.map!{|x| x = x.url + "receive/"} - xml = Post.build_xml_for(self) - Rails.logger.info("Adding xml for #{self} to message queue to #{recipients}") + recipients.map!{|x| x = x.receive_url } + xml = to_diaspora_xml + Rails.logger.debug("Adding xml for #{self} to message queue to #{recipients}") @@queue.add_post_request( recipients, xml ) end @@queue.process end def push_to_url(url) - hook_url = url + "receive/" - xml = self.class.build_xml_for(self) - Rails.logger.info("Adding xml for #{self} to message queue to #{url}") + hook_url = url + xml = to_diaspora_xml + Rails.logger.debug("Adding xml for #{self} to message queue to #{url}") @@queue.add_post_request( hook_url, xml ) @@queue.process end def to_diaspora_xml - "<post>#{self.to_xml.to_s}</post>" - end - - def people_with_permissions - Person.friends.all - end - - def self.build_xml_for(posts) xml = "<XML>" - xml += "\n <posts>" - [*posts].each {|x| xml << x.to_diaspora_xml} - xml += "</posts>" + xml += "<post>#{self.to_xml.to_s}</post>" xml += "</XML>" + end + def people_with_permissions + begin + friends = self.person.owner.friends.all + Rails.logger.error("Dan is wrong!") if friends.nil? + friends ||= [] + rescue + Rails.logger.fatal("Called people_with_permissions on a post from a remote user. We need to implement this shit.") + [] + end end end end diff --git a/lib/diaspora/websocket.rb b/lib/diaspora/websocket.rb new file mode 100644 index 0000000000000000000000000000000000000000..bfbc69c2658656c2c696e5d3b5bb0dda3ea0d966 --- /dev/null +++ b/lib/diaspora/websocket.rb @@ -0,0 +1,43 @@ +module Diaspora + module WebSocket + def self.initialize_channels + @channels = {} + end + + def self.push_to_user(uid, data) + Rails.logger.debug "Websocketing to #{uid}" + @channels[uid.to_s][0].push(data) if @channels[uid.to_s] + end + + def self.subscribe(uid, ws) + Rails.logger.debug "Subscribing socket to #{User.first(:id => uid).email}" + self.ensure_channel(uid) + @channels[uid][0].subscribe{ |msg| ws.send msg } + @channels[uid][1] += 1 + end + + def self.ensure_channel(uid) + @channels[uid] ||= [EM::Channel.new, 0 ] + end + + def self.unsubscribe(uid,sid) + Rails.logger.debug "Unsubscribing socket #{sid} from #{uid}" + @channels[uid][0].unsubscribe(sid) if @channels[uid] + @channels[uid][1] -= 1 + if @channels[uid][1] <= 0 + @channels.delete(uid) + end + end + end + + module Socketable + def socket_to_uid id + SocketsController.new.outgoing(id, self) + end + + def unsocket_from_uid id + SocketsController.new.outgoing(id, Retraction.for(self)) + end + + end +end diff --git a/lib/encryptable.rb b/lib/encryptable.rb index 4d352971e8d502322d4c4d715a1fb17ccaf40950..850499bff889182ff8e94414bd8e6e62d08f3090 100644 --- a/lib/encryptable.rb +++ b/lib/encryptable.rb @@ -10,32 +10,26 @@ if person.nil? Rails.logger.info("Verifying sig on #{signable_string} but no person is here") return false - elsif person.key.nil? + elsif person.encryption_key.nil? Rails.logger.info("Verifying sig on #{signable_string} but #{person.real_name} has no key") return false elsif signature.nil? Rails.logger.info("Verifying sig on #{signable_string} but #{person.real_name} did not sign") return false end - Rails.logger.info("Verifying sig on #{signable_string} from person #{person.real_name}") - validity = person.key.verify "SHA", Base64.decode64(signature), signable_string - Rails.logger.info("Validity: #{validity}") + Rails.logger.debug("Verifying sig on #{signable_string} from person #{person.real_name}") + validity = person.encryption_key.verify "SHA", Base64.decode64(signature), signable_string + Rails.logger.debug("Validity: #{validity}") validity end protected def sign_if_mine - if self.person == User.owner - self.creator_signature = sign - end - end - - def sign - sign_with_key(User.owner.key) + self.creator_signature = sign_with_key(person.encryption_key) unless person.owner_id.nil? end def sign_with_key(key) - Rails.logger.info("Signing #{signable_string}") + Rails.logger.debug("Signing #{signable_string}") Base64.encode64(key.sign "SHA", signable_string) end diff --git a/lib/tasks/db.rake b/lib/tasks/db.rake index 8c3bd23766a44742d398551e0ecc1bc15d524062..9b78b68555b95570ad2269ba687e3b957238bd44 100644 --- a/lib/tasks/db.rake +++ b/lib/tasks/db.rake @@ -11,10 +11,10 @@ namespace :db do require 'db/seeds/dev' end - task :backer, :num do |t, args| + task :backer do puts "Seeding the database for #{Rails.env}..." require 'db/seeds/backer' - create( Integer(args.num)) + create end end @@ -27,6 +27,9 @@ namespace :db do # Specifiy what models to remove # No! Drop the fucking database. MongoMapper::connection.drop_database(MongoMapper::database.name) + + puts 'Deleting tmp folder...' + `rm -rf #{File.dirname(__FILE__)}/../../public/uploads/tmp` end desc 'Purge and seed the current RAILS_ENV database using information from db/seeds.rb' diff --git a/public/images/ajax-loader.gif b/public/images/ajax-loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..e40f19a2818e4c81726bf965fc8dc108d52dc599 Binary files /dev/null and b/public/images/ajax-loader.gif differ diff --git a/public/images/user/default.jpg b/public/images/user/default.jpg index 788fd4f1d0d5a90933eb736a74c4f03c86049c97..b242c1e1c3ce1c06b7452a2fc93f74c05dea1950 100644 Binary files a/public/images/user/default.jpg and b/public/images/user/default.jpg differ diff --git a/public/javascripts/fancybox/blank.gif b/public/javascripts/fancybox/blank.gif new file mode 100644 index 0000000000000000000000000000000000000000..35d42e808f0a8017b8d52a06be2f8fec0b466a66 Binary files /dev/null and b/public/javascripts/fancybox/blank.gif differ diff --git a/public/javascripts/fancybox/fancy_close.png b/public/javascripts/fancybox/fancy_close.png new file mode 100644 index 0000000000000000000000000000000000000000..07035307ad435f8f2f8eedf0bce50f7ec8a858c2 Binary files /dev/null and b/public/javascripts/fancybox/fancy_close.png differ diff --git a/public/javascripts/fancybox/fancy_loading.png b/public/javascripts/fancybox/fancy_loading.png new file mode 100644 index 0000000000000000000000000000000000000000..2503017960b3972499d3aa92f89953935ae40934 Binary files /dev/null and b/public/javascripts/fancybox/fancy_loading.png differ diff --git a/public/javascripts/fancybox/fancy_nav_left.png b/public/javascripts/fancybox/fancy_nav_left.png new file mode 100644 index 0000000000000000000000000000000000000000..ebaa6a4fd34e51575a01da366312c20618985cbc Binary files /dev/null and b/public/javascripts/fancybox/fancy_nav_left.png differ diff --git a/public/javascripts/fancybox/fancy_nav_right.png b/public/javascripts/fancybox/fancy_nav_right.png new file mode 100644 index 0000000000000000000000000000000000000000..873294e969db9160f5ddd4e1ab498ff60b080e3f Binary files /dev/null and b/public/javascripts/fancybox/fancy_nav_right.png differ diff --git a/public/javascripts/fancybox/fancy_shadow_e.png b/public/javascripts/fancybox/fancy_shadow_e.png new file mode 100644 index 0000000000000000000000000000000000000000..2eda0893649371f8d92b92976d8542cdd1b601ed Binary files /dev/null and b/public/javascripts/fancybox/fancy_shadow_e.png differ diff --git a/public/javascripts/fancybox/fancy_shadow_n.png b/public/javascripts/fancybox/fancy_shadow_n.png new file mode 100644 index 0000000000000000000000000000000000000000..69aa10e233b039077e7dc600177ddb1eb46217e3 Binary files /dev/null and b/public/javascripts/fancybox/fancy_shadow_n.png differ diff --git a/public/javascripts/fancybox/fancy_shadow_ne.png b/public/javascripts/fancybox/fancy_shadow_ne.png new file mode 100644 index 0000000000000000000000000000000000000000..79f6980a3ba5c43de120d963dbba2516b8f27ac7 Binary files /dev/null and b/public/javascripts/fancybox/fancy_shadow_ne.png differ diff --git a/public/javascripts/fancybox/fancy_shadow_nw.png b/public/javascripts/fancybox/fancy_shadow_nw.png new file mode 100644 index 0000000000000000000000000000000000000000..7182cd938ae98e7e28c65a0bc55df576042ff9f5 Binary files /dev/null and b/public/javascripts/fancybox/fancy_shadow_nw.png differ diff --git a/public/javascripts/fancybox/fancy_shadow_s.png b/public/javascripts/fancybox/fancy_shadow_s.png new file mode 100644 index 0000000000000000000000000000000000000000..d8858bfb78efb8d7268736920efa1eae8873f89c Binary files /dev/null and b/public/javascripts/fancybox/fancy_shadow_s.png differ diff --git a/public/javascripts/fancybox/fancy_shadow_se.png b/public/javascripts/fancybox/fancy_shadow_se.png new file mode 100644 index 0000000000000000000000000000000000000000..541e3ffd3e88224b34a4d2097c66a780e6060aeb Binary files /dev/null and b/public/javascripts/fancybox/fancy_shadow_se.png differ diff --git a/public/javascripts/fancybox/fancy_shadow_sw.png b/public/javascripts/fancybox/fancy_shadow_sw.png new file mode 100644 index 0000000000000000000000000000000000000000..b451689fa7b57b7432820e4c06d0864c143c79ab Binary files /dev/null and b/public/javascripts/fancybox/fancy_shadow_sw.png differ diff --git a/public/javascripts/fancybox/fancy_shadow_w.png b/public/javascripts/fancybox/fancy_shadow_w.png new file mode 100644 index 0000000000000000000000000000000000000000..8a4e4a887f18384a204563c0048c9cd1328f7faa Binary files /dev/null and b/public/javascripts/fancybox/fancy_shadow_w.png differ diff --git a/public/javascripts/fancybox/fancy_title_left.png b/public/javascripts/fancybox/fancy_title_left.png new file mode 100644 index 0000000000000000000000000000000000000000..6049223d1ec6af46e100499c01f6489c9e2c6240 Binary files /dev/null and b/public/javascripts/fancybox/fancy_title_left.png differ diff --git a/public/javascripts/fancybox/fancy_title_main.png b/public/javascripts/fancybox/fancy_title_main.png new file mode 100644 index 0000000000000000000000000000000000000000..8044271f29b5d4e4471570e75cdce90bf9a1497c Binary files /dev/null and b/public/javascripts/fancybox/fancy_title_main.png differ diff --git a/public/javascripts/fancybox/fancy_title_over.png b/public/javascripts/fancybox/fancy_title_over.png new file mode 100644 index 0000000000000000000000000000000000000000..d9f458f4bb8770466e44ba97dd8fe1f2936090db Binary files /dev/null and b/public/javascripts/fancybox/fancy_title_over.png differ diff --git a/public/javascripts/fancybox/fancy_title_right.png b/public/javascripts/fancybox/fancy_title_right.png new file mode 100644 index 0000000000000000000000000000000000000000..e36d9db2a7c6e570aec993d3665cbc13620115e2 Binary files /dev/null and b/public/javascripts/fancybox/fancy_title_right.png differ diff --git a/public/javascripts/fancybox/fancybox-x.png b/public/javascripts/fancybox/fancybox-x.png new file mode 100644 index 0000000000000000000000000000000000000000..c2130f8698f682d68b1550bffedecfe19eaa1a81 Binary files /dev/null and b/public/javascripts/fancybox/fancybox-x.png differ diff --git a/public/javascripts/fancybox/fancybox-y.png b/public/javascripts/fancybox/fancybox-y.png new file mode 100644 index 0000000000000000000000000000000000000000..7ef399b9908976fc36f760fad7876a4d9c38e006 Binary files /dev/null and b/public/javascripts/fancybox/fancybox-y.png differ diff --git a/public/javascripts/fancybox/fancybox.png b/public/javascripts/fancybox/fancybox.png new file mode 100644 index 0000000000000000000000000000000000000000..65e14f68fd83b87f75c22c0c074e7b20bf20a133 Binary files /dev/null and b/public/javascripts/fancybox/fancybox.png differ diff --git a/public/javascripts/fancybox/jquery.easing-1.3.pack.js b/public/javascripts/fancybox/jquery.easing-1.3.pack.js new file mode 100644 index 0000000000000000000000000000000000000000..9028179e7bde19e3c0fdbf9f422c35c4a0d95034 --- /dev/null +++ b/public/javascripts/fancybox/jquery.easing-1.3.pack.js @@ -0,0 +1,72 @@ +/* + * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/ + * + * Uses the built in easing capabilities added In jQuery 1.1 + * to offer multiple easing options + * + * TERMS OF USE - jQuery Easing + * + * Open source under the BSD License. + * + * Copyright © 2008 George McGinley Smith + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * Neither the name of the author nor the names of contributors may be used to endorse + * or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * +*/ + +// t: current time, b: begInnIng value, c: change In value, d: duration +eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('h.i[\'1a\']=h.i[\'z\'];h.O(h.i,{y:\'D\',z:9(x,t,b,c,d){6 h.i[h.i.y](x,t,b,c,d)},17:9(x,t,b,c,d){6 c*(t/=d)*t+b},D:9(x,t,b,c,d){6-c*(t/=d)*(t-2)+b},13:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t+b;6-c/2*((--t)*(t-2)-1)+b},X:9(x,t,b,c,d){6 c*(t/=d)*t*t+b},U:9(x,t,b,c,d){6 c*((t=t/d-1)*t*t+1)+b},R:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t*t+b;6 c/2*((t-=2)*t*t+2)+b},N:9(x,t,b,c,d){6 c*(t/=d)*t*t*t+b},M:9(x,t,b,c,d){6-c*((t=t/d-1)*t*t*t-1)+b},L:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t*t*t+b;6-c/2*((t-=2)*t*t*t-2)+b},K:9(x,t,b,c,d){6 c*(t/=d)*t*t*t*t+b},J:9(x,t,b,c,d){6 c*((t=t/d-1)*t*t*t*t+1)+b},I:9(x,t,b,c,d){e((t/=d/2)<1)6 c/2*t*t*t*t*t+b;6 c/2*((t-=2)*t*t*t*t+2)+b},G:9(x,t,b,c,d){6-c*8.C(t/d*(8.g/2))+c+b},15:9(x,t,b,c,d){6 c*8.n(t/d*(8.g/2))+b},12:9(x,t,b,c,d){6-c/2*(8.C(8.g*t/d)-1)+b},Z:9(x,t,b,c,d){6(t==0)?b:c*8.j(2,10*(t/d-1))+b},Y:9(x,t,b,c,d){6(t==d)?b+c:c*(-8.j(2,-10*t/d)+1)+b},W:9(x,t,b,c,d){e(t==0)6 b;e(t==d)6 b+c;e((t/=d/2)<1)6 c/2*8.j(2,10*(t-1))+b;6 c/2*(-8.j(2,-10*--t)+2)+b},V:9(x,t,b,c,d){6-c*(8.o(1-(t/=d)*t)-1)+b},S:9(x,t,b,c,d){6 c*8.o(1-(t=t/d-1)*t)+b},Q:9(x,t,b,c,d){e((t/=d/2)<1)6-c/2*(8.o(1-t*t)-1)+b;6 c/2*(8.o(1-(t-=2)*t)+1)+b},P:9(x,t,b,c,d){f s=1.l;f p=0;f a=c;e(t==0)6 b;e((t/=d)==1)6 b+c;e(!p)p=d*.3;e(a<8.w(c)){a=c;f s=p/4}m f s=p/(2*8.g)*8.r(c/a);6-(a*8.j(2,10*(t-=1))*8.n((t*d-s)*(2*8.g)/p))+b},H:9(x,t,b,c,d){f s=1.l;f p=0;f a=c;e(t==0)6 b;e((t/=d)==1)6 b+c;e(!p)p=d*.3;e(a<8.w(c)){a=c;f s=p/4}m f s=p/(2*8.g)*8.r(c/a);6 a*8.j(2,-10*t)*8.n((t*d-s)*(2*8.g)/p)+c+b},T:9(x,t,b,c,d){f s=1.l;f p=0;f a=c;e(t==0)6 b;e((t/=d/2)==2)6 b+c;e(!p)p=d*(.3*1.5);e(a<8.w(c)){a=c;f s=p/4}m f s=p/(2*8.g)*8.r(c/a);e(t<1)6-.5*(a*8.j(2,10*(t-=1))*8.n((t*d-s)*(2*8.g)/p))+b;6 a*8.j(2,-10*(t-=1))*8.n((t*d-s)*(2*8.g)/p)*.5+c+b},F:9(x,t,b,c,d,s){e(s==u)s=1.l;6 c*(t/=d)*t*((s+1)*t-s)+b},E:9(x,t,b,c,d,s){e(s==u)s=1.l;6 c*((t=t/d-1)*t*((s+1)*t+s)+1)+b},16:9(x,t,b,c,d,s){e(s==u)s=1.l;e((t/=d/2)<1)6 c/2*(t*t*(((s*=(1.B))+1)*t-s))+b;6 c/2*((t-=2)*t*(((s*=(1.B))+1)*t+s)+2)+b},A:9(x,t,b,c,d){6 c-h.i.v(x,d-t,0,c,d)+b},v:9(x,t,b,c,d){e((t/=d)<(1/2.k)){6 c*(7.q*t*t)+b}m e(t<(2/2.k)){6 c*(7.q*(t-=(1.5/2.k))*t+.k)+b}m e(t<(2.5/2.k)){6 c*(7.q*(t-=(2.14/2.k))*t+.11)+b}m{6 c*(7.q*(t-=(2.18/2.k))*t+.19)+b}},1b:9(x,t,b,c,d){e(t<d/2)6 h.i.A(x,t*2,0,c,d)*.5+b;6 h.i.v(x,t*2-d,0,c,d)*.5+c*.5+b}});',62,74,'||||||return||Math|function|||||if|var|PI|jQuery|easing|pow|75|70158|else|sin|sqrt||5625|asin|||undefined|easeOutBounce|abs||def|swing|easeInBounce|525|cos|easeOutQuad|easeOutBack|easeInBack|easeInSine|easeOutElastic|easeInOutQuint|easeOutQuint|easeInQuint|easeInOutQuart|easeOutQuart|easeInQuart|extend|easeInElastic|easeInOutCirc|easeInOutCubic|easeOutCirc|easeInOutElastic|easeOutCubic|easeInCirc|easeInOutExpo|easeInCubic|easeOutExpo|easeInExpo||9375|easeInOutSine|easeInOutQuad|25|easeOutSine|easeInOutBack|easeInQuad|625|984375|jswing|easeInOutBounce'.split('|'),0,{})) + +/* + * + * TERMS OF USE - EASING EQUATIONS + * + * Open source under the BSD License. + * + * Copyright © 2001 Robert Penner + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * Neither the name of the author nor the names of contributors may be used to endorse + * or promote products derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ diff --git a/public/javascripts/fancybox/jquery.fancybox-1.3.1.css b/public/javascripts/fancybox/jquery.fancybox-1.3.1.css new file mode 100644 index 0000000000000000000000000000000000000000..28bbb132761d7d836df3fadd4572039bb3fd4cc3 --- /dev/null +++ b/public/javascripts/fancybox/jquery.fancybox-1.3.1.css @@ -0,0 +1,363 @@ +/* + * FancyBox - jQuery Plugin + * Simple and fancy lightbox alternative + * + * Examples and documentation at: http://fancybox.net + * + * Copyright (c) 2008 - 2010 Janis Skarnelis + * + * Version: 1.3.1 (05/03/2010) + * Requires: jQuery v1.3+ + * + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + */ + +#fancybox-loading { + position: fixed; + top: 50%; + left: 50%; + height: 40px; + width: 40px; + margin-top: -20px; + margin-left: -20px; + cursor: pointer; + overflow: hidden; + z-index: 1104; + display: none; +} + +* html #fancybox-loading { /* IE6 */ + position: absolute; + margin-top: 0; +} + +#fancybox-loading div { + position: absolute; + top: 0; + left: 0; + width: 40px; + height: 480px; + background-image: url('fancybox.png'); +} + +#fancybox-overlay { + position: fixed; + top: 0; + left: 0; + bottom: 0; + right: 0; + background: #000; + z-index: 1100; + display: none; +} + +* html #fancybox-overlay { /* IE6 */ + position: absolute; + width: 100%; +} + +#fancybox-tmp { + padding: 0; + margin: 0; + border: 0; + overflow: auto; + display: none; +} + +#fancybox-wrap { + position: absolute; + top: 0; + left: 0; + margin: 0; + padding: 20px; + z-index: 1101; + display: none; +} + +#fancybox-outer { + position: relative; + width: 100%; + height: 100%; + background: #FFF; +} + +#fancybox-inner { + position: absolute; + top: 0; + left: 0; + width: 1px; + height: 1px; + padding: 0; + margin: 0; + outline: none; + overflow: hidden; +} + +#fancybox-hide-sel-frame { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: transparent; +} + +#fancybox-close { + position: absolute; + top: -15px; + right: -15px; + width: 30px; + height: 30px; + background-image: url('fancybox.png'); + background-position: -40px 0px; + cursor: pointer; + z-index: 1103; + display: none; +} + +#fancybox_error { + color: #444; + font: normal 12px/20px Arial; + padding: 7px; + margin: 0; +} + +#fancybox-content { + height: auto; + width: auto; + padding: 0; + margin: 0; +} + +#fancybox-img { + width: 100%; + height: 100%; + padding: 0; + margin: 0; + border: none; + outline: none; + line-height: 0; + vertical-align: top; + -ms-interpolation-mode: bicubic; +} + +#fancybox-frame { + position: relative; + width: 100%; + height: 100%; + border: none; + display: block; +} + +#fancybox-title { + position: absolute; + bottom: 0; + left: 0; + font-family: Arial; + font-size: 12px; + z-index: 1102; +} + +.fancybox-title-inside { + padding: 10px 0; + text-align: center; + color: #333; +} + +.fancybox-title-outside { + padding-top: 5px; + color: #FFF; + text-align: center; + font-weight: bold; +} + +.fancybox-title-over { + color: #FFF; + text-align: left; +} + +#fancybox-title-over { + padding: 10px; + background-image: url('fancy_title_over.png'); + display: block; +} + +#fancybox-title-wrap { + display: inline-block; +} + +#fancybox-title-wrap span { + height: 32px; + float: left; +} + +#fancybox-title-left { + padding-left: 15px; + background-image: url('fancybox.png'); + background-position: -40px -90px; + background-repeat: no-repeat; +} + +#fancybox-title-main { + font-weight: bold; + line-height: 29px; + background-image: url('fancybox-x.png'); + background-position: 0px -40px; + color: #FFF; +} + +#fancybox-title-right { + padding-left: 15px; + background-image: url('fancybox.png'); + background-position: -55px -90px; + background-repeat: no-repeat; +} + +#fancybox-left, #fancybox-right { + position: absolute; + bottom: 0px; + height: 100%; + width: 35%; + cursor: pointer; + outline: none; + background-image: url('blank.gif'); + z-index: 1102; + display: none; +} + +#fancybox-left { + left: 0px; +} + +#fancybox-right { + right: 0px; +} + +#fancybox-left-ico, #fancybox-right-ico { + position: absolute; + top: 50%; + left: -9999px; + width: 30px; + height: 30px; + margin-top: -15px; + cursor: pointer; + z-index: 1102; + display: block; +} + +#fancybox-left-ico { + background-image: url('fancybox.png'); + background-position: -40px -30px; +} + +#fancybox-right-ico { + background-image: url('fancybox.png'); + background-position: -40px -60px; +} + +#fancybox-left:hover, #fancybox-right:hover { + visibility: visible; /* IE6 */ +} + +#fancybox-left:hover span { + left: 20px; +} + +#fancybox-right:hover span { + left: auto; + right: 20px; +} + +.fancy-bg { + position: absolute; + padding: 0; + margin: 0; + border: 0; + width: 20px; + height: 20px; + z-index: 1001; +} + +#fancy-bg-n { + top: -20px; + left: 0; + width: 100%; + background-image: url('fancybox-x.png'); +} + +#fancy-bg-ne { + top: -20px; + right: -20px; + background-image: url('fancybox.png'); + background-position: -40px -162px; +} + +#fancy-bg-e { + top: 0; + right: -20px; + height: 100%; + background-image: url('fancybox-y.png'); + background-position: -20px 0px; +} + +#fancy-bg-se { + bottom: -20px; + right: -20px; + background-image: url('fancybox.png'); + background-position: -40px -182px; +} + +#fancy-bg-s { + bottom: -20px; + left: 0; + width: 100%; + background-image: url('fancybox-x.png'); + background-position: 0px -20px; +} + +#fancy-bg-sw { + bottom: -20px; + left: -20px; + background-image: url('fancybox.png'); + background-position: -40px -142px; +} + +#fancy-bg-w { + top: 0; + left: -20px; + height: 100%; + background-image: url('fancybox-y.png'); +} + +#fancy-bg-nw { + top: -20px; + left: -20px; + background-image: url('fancybox.png'); + background-position: -40px -122px; +} + +/* IE */ + +#fancybox-loading.fancybox-ie div { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_loading.png', sizingMethod='scale'); } +.fancybox-ie #fancybox-close { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_close.png', sizingMethod='scale'); } + +.fancybox-ie #fancybox-title-over { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_over.png', sizingMethod='scale'); zoom: 1; } +.fancybox-ie #fancybox-title-left { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_left.png', sizingMethod='scale'); } +.fancybox-ie #fancybox-title-main { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_main.png', sizingMethod='scale'); } +.fancybox-ie #fancybox-title-right { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_title_right.png', sizingMethod='scale'); } + +.fancybox-ie #fancybox-left-ico { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_nav_left.png', sizingMethod='scale'); } +.fancybox-ie #fancybox-right-ico { background: transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_nav_right.png', sizingMethod='scale'); } + +.fancybox-ie .fancy-bg { background: transparent !important; } + +.fancybox-ie #fancy-bg-n { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_n.png', sizingMethod='scale'); } +.fancybox-ie #fancy-bg-ne { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_ne.png', sizingMethod='scale'); } +.fancybox-ie #fancy-bg-e { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_e.png', sizingMethod='scale'); } +.fancybox-ie #fancy-bg-se { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_se.png', sizingMethod='scale'); } +.fancybox-ie #fancy-bg-s { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_s.png', sizingMethod='scale'); } +.fancybox-ie #fancy-bg-sw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_sw.png', sizingMethod='scale'); } +.fancybox-ie #fancy-bg-w { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_w.png', sizingMethod='scale'); } +.fancybox-ie #fancy-bg-nw { filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='fancybox/fancy_shadow_nw.png', sizingMethod='scale'); } diff --git a/public/javascripts/fancybox/jquery.fancybox-1.3.1.js b/public/javascripts/fancybox/jquery.fancybox-1.3.1.js new file mode 100644 index 0000000000000000000000000000000000000000..688f93aa34a8b739cbaeaf23e3dbfbaac8c098a4 --- /dev/null +++ b/public/javascripts/fancybox/jquery.fancybox-1.3.1.js @@ -0,0 +1,1077 @@ +/* + * FancyBox - jQuery Plugin + * Simple and fancy lightbox alternative + * + * Examples and documentation at: http://fancybox.net + * + * Copyright (c) 2008 - 2010 Janis Skarnelis + * + * Version: 1.3.1 (05/03/2010) + * Requires: jQuery v1.3+ + * + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + */ + +(function($) { + + var tmp, loading, overlay, wrap, outer, inner, close, nav_left, nav_right, + + selectedIndex = 0, selectedOpts = {}, selectedArray = [], currentIndex = 0, currentOpts = {}, currentArray = [], + + ajaxLoader = null, imgPreloader = new Image(), imgRegExp = /\.(jpg|gif|png|bmp|jpeg)(.*)?$/i, swfRegExp = /[^\.]\.(swf)\s*$/i, + + loadingTimer, loadingFrame = 1, + + start_pos, final_pos, busy = false, shadow = 20, fx = $.extend($('<div/>')[0], { prop: 0 }), titleh = 0, + + isIE6 = !$.support.opacity && !window.XMLHttpRequest, + + /* + * Private methods + */ + + fancybox_abort = function() { + loading.hide(); + + imgPreloader.onerror = imgPreloader.onload = null; + + if (ajaxLoader) { + ajaxLoader.abort(); + } + + tmp.empty(); + }, + + fancybox_error = function() { + $.fancybox('<p id="fancybox_error">The requested content cannot be loaded.<br />Please try again later.</p>', { + 'scrolling' : 'no', + 'padding' : 20, + 'transitionIn' : 'none', + 'transitionOut' : 'none' + }); + }, + + fancybox_get_viewport = function() { + return [ $(window).width(), $(window).height(), $(document).scrollLeft(), $(document).scrollTop() ]; + }, + + fancybox_get_zoom_to = function () { + var view = fancybox_get_viewport(), + to = {}, + + margin = currentOpts.margin, + resize = currentOpts.autoScale, + + horizontal_space = (shadow + margin) * 2, + vertical_space = (shadow + margin) * 2, + double_padding = (currentOpts.padding * 2), + + ratio; + + if (currentOpts.width.toString().indexOf('%') > -1) { + to.width = ((view[0] * parseFloat(currentOpts.width)) / 100) - (shadow * 2) ; + resize = false; + + } else { + to.width = currentOpts.width + double_padding; + } + + if (currentOpts.height.toString().indexOf('%') > -1) { + to.height = ((view[1] * parseFloat(currentOpts.height)) / 100) - (shadow * 2); + resize = false; + + } else { + to.height = currentOpts.height + double_padding; + } + + if (resize && (to.width > (view[0] - horizontal_space) || to.height > (view[1] - vertical_space))) { + if (selectedOpts.type == 'image' || selectedOpts.type == 'swf') { + horizontal_space += double_padding; + vertical_space += double_padding; + + ratio = Math.min(Math.min( view[0] - horizontal_space, currentOpts.width) / currentOpts.width, Math.min( view[1] - vertical_space, currentOpts.height) / currentOpts.height); + + to.width = Math.round(ratio * (to.width - double_padding)) + double_padding; + to.height = Math.round(ratio * (to.height - double_padding)) + double_padding; + + } else { + to.width = Math.min(to.width, (view[0] - horizontal_space)); + to.height = Math.min(to.height, (view[1] - vertical_space)); + } + } + + to.top = view[3] + ((view[1] - (to.height + (shadow * 2 ))) * 0.5); + to.left = view[2] + ((view[0] - (to.width + (shadow * 2 ))) * 0.5); + + if (currentOpts.autoScale === false) { + to.top = Math.max(view[3] + margin, to.top); + to.left = Math.max(view[2] + margin, to.left); + } + + return to; + }, + + fancybox_format_title = function(title) { + if (title && title.length) { + switch (currentOpts.titlePosition) { + case 'inside': + return title; + case 'over': + return '<span id="fancybox-title-over">' + title + '</span>'; + default: + return '<span id="fancybox-title-wrap"><span id="fancybox-title-left"></span><span id="fancybox-title-main">' + title + '</span><span id="fancybox-title-right"></span></span>'; + } + } + + return false; + }, + + fancybox_process_title = function() { + var title = currentOpts.title, + width = final_pos.width - (currentOpts.padding * 2), + titlec = 'fancybox-title-' + currentOpts.titlePosition; + + $('#fancybox-title').remove(); + + titleh = 0; + + if (currentOpts.titleShow === false) { + return; + } + + title = $.isFunction(currentOpts.titleFormat) ? currentOpts.titleFormat(title, currentArray, currentIndex, currentOpts) : fancybox_format_title(title); + + if (!title || title === '') { + return; + } + + $('<div id="fancybox-title" class="' + titlec + '" />').css({ + 'width' : width, + 'paddingLeft' : currentOpts.padding, + 'paddingRight' : currentOpts.padding + }).html(title).appendTo('body'); + + switch (currentOpts.titlePosition) { + case 'inside': + titleh = $("#fancybox-title").outerHeight(true) - currentOpts.padding; + final_pos.height += titleh; + break; + + case 'over': + $('#fancybox-title').css('bottom', currentOpts.padding); + break; + + default: + $('#fancybox-title').css('bottom', $("#fancybox-title").outerHeight(true) * -1); + break; + } + + $('#fancybox-title').appendTo( outer ).hide(); + }, + + fancybox_set_navigation = function() { + $(document).unbind('keydown.fb').bind('keydown.fb', function(e) { + if (e.keyCode == 27 && currentOpts.enableEscapeButton) { + e.preventDefault(); + $.fancybox.close(); + + } else if (e.keyCode == 37) { + e.preventDefault(); + $.fancybox.prev(); + + } else if (e.keyCode == 39) { + e.preventDefault(); + $.fancybox.next(); + } + }); + + if ($.fn.mousewheel) { + wrap.unbind('mousewheel.fb'); + + if (currentArray.length > 1) { + wrap.bind('mousewheel.fb', function(e, delta) { + e.preventDefault(); + + if (busy || delta === 0) { + return; + } + + if (delta > 0) { + $.fancybox.prev(); + } else { + $.fancybox.next(); + } + }); + } + } + + if (!currentOpts.showNavArrows) { return; } + + if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex !== 0) { + nav_left.show(); + } + + if ((currentOpts.cyclic && currentArray.length > 1) || currentIndex != (currentArray.length -1)) { + nav_right.show(); + } + }, + + fancybox_preload_images = function() { + var href, + objNext; + + if ((currentArray.length -1) > currentIndex) { + href = currentArray[ currentIndex + 1 ].href; + + if (typeof href !== 'undefined' && href.match(imgRegExp)) { + objNext = new Image(); + objNext.src = href; + } + } + + if (currentIndex > 0) { + href = currentArray[ currentIndex - 1 ].href; + + if (typeof href !== 'undefined' && href.match(imgRegExp)) { + objNext = new Image(); + objNext.src = href; + } + } + }, + + _finish = function () { + inner.css('overflow', (currentOpts.scrolling == 'auto' ? (currentOpts.type == 'image' || currentOpts.type == 'iframe' || currentOpts.type == 'swf' ? 'hidden' : 'auto') : (currentOpts.scrolling == 'yes' ? 'auto' : 'visible'))); + + if (!$.support.opacity) { + inner.get(0).style.removeAttribute('filter'); + wrap.get(0).style.removeAttribute('filter'); + } + + $('#fancybox-title').show(); + + if (currentOpts.hideOnContentClick) { + inner.one('click', $.fancybox.close); + } + if (currentOpts.hideOnOverlayClick) { + overlay.one('click', $.fancybox.close); + } + + if (currentOpts.showCloseButton) { + close.show(); + } + + fancybox_set_navigation(); + + $(window).bind("resize.fb", $.fancybox.center); + + if (currentOpts.centerOnScroll) { + $(window).bind("scroll.fb", $.fancybox.center); + } else { + $(window).unbind("scroll.fb"); + } + + if ($.isFunction(currentOpts.onComplete)) { + currentOpts.onComplete(currentArray, currentIndex, currentOpts); + } + + busy = false; + + fancybox_preload_images(); + }, + + fancybox_draw = function(pos) { + var width = Math.round(start_pos.width + (final_pos.width - start_pos.width) * pos), + height = Math.round(start_pos.height + (final_pos.height - start_pos.height) * pos), + + top = Math.round(start_pos.top + (final_pos.top - start_pos.top) * pos), + left = Math.round(start_pos.left + (final_pos.left - start_pos.left) * pos); + + wrap.css({ + 'width' : width + 'px', + 'height' : height + 'px', + 'top' : top + 'px', + 'left' : left + 'px' + }); + + width = Math.max(width - currentOpts.padding * 2, 0); + height = Math.max(height - (currentOpts.padding * 2 + (titleh * pos)), 0); + + inner.css({ + 'width' : width + 'px', + 'height' : height + 'px' + }); + + if (typeof final_pos.opacity !== 'undefined') { + wrap.css('opacity', (pos < 0.5 ? 0.5 : pos)); + } + }, + + fancybox_get_obj_pos = function(obj) { + var pos = obj.offset(); + + pos.top += parseFloat( obj.css('paddingTop') ) || 0; + pos.left += parseFloat( obj.css('paddingLeft') ) || 0; + + pos.top += parseFloat( obj.css('border-top-width') ) || 0; + pos.left += parseFloat( obj.css('border-left-width') ) || 0; + + pos.width = obj.width(); + pos.height = obj.height(); + + return pos; + }, + + fancybox_get_zoom_from = function() { + var orig = selectedOpts.orig ? $(selectedOpts.orig) : false, + from = {}, + pos, + view; + + if (orig && orig.length) { + pos = fancybox_get_obj_pos(orig); + + from = { + width : (pos.width + (currentOpts.padding * 2)), + height : (pos.height + (currentOpts.padding * 2)), + top : (pos.top - currentOpts.padding - shadow), + left : (pos.left - currentOpts.padding - shadow) + }; + + } else { + view = fancybox_get_viewport(); + + from = { + width : 1, + height : 1, + top : view[3] + view[1] * 0.5, + left : view[2] + view[0] * 0.5 + }; + } + + return from; + }, + + fancybox_show = function() { + loading.hide(); + + if (wrap.is(":visible") && $.isFunction(currentOpts.onCleanup)) { + if (currentOpts.onCleanup(currentArray, currentIndex, currentOpts) === false) { + $.event.trigger('fancybox-cancel'); + + busy = false; + return; + } + } + + currentArray = selectedArray; + currentIndex = selectedIndex; + currentOpts = selectedOpts; + + inner.get(0).scrollTop = 0; + inner.get(0).scrollLeft = 0; + + if (currentOpts.overlayShow) { + if (isIE6) { + $('select:not(#fancybox-tmp select)').filter(function() { + return this.style.visibility !== 'hidden'; + }).css({'visibility':'hidden'}).one('fancybox-cleanup', function() { + this.style.visibility = 'inherit'; + }); + } + + overlay.css({ + 'background-color' : currentOpts.overlayColor, + 'opacity' : currentOpts.overlayOpacity + }).unbind().show(); + } + + final_pos = fancybox_get_zoom_to(); + + fancybox_process_title(); + + if (wrap.is(":visible")) { + $( close.add( nav_left ).add( nav_right ) ).hide(); + + var pos = wrap.position(), + equal; + + start_pos = { + top : pos.top , + left : pos.left, + width : wrap.width(), + height : wrap.height() + }; + + equal = (start_pos.width == final_pos.width && start_pos.height == final_pos.height); + + inner.fadeOut(currentOpts.changeFade, function() { + var finish_resizing = function() { + inner.html( tmp.contents() ).fadeIn(currentOpts.changeFade, _finish); + }; + + $.event.trigger('fancybox-change'); + + inner.empty().css('overflow', 'hidden'); + + if (equal) { + inner.css({ + top : currentOpts.padding, + left : currentOpts.padding, + width : Math.max(final_pos.width - (currentOpts.padding * 2), 1), + height : Math.max(final_pos.height - (currentOpts.padding * 2) - titleh, 1) + }); + + finish_resizing(); + + } else { + inner.css({ + top : currentOpts.padding, + left : currentOpts.padding, + width : Math.max(start_pos.width - (currentOpts.padding * 2), 1), + height : Math.max(start_pos.height - (currentOpts.padding * 2), 1) + }); + + fx.prop = 0; + + $(fx).animate({ prop: 1 }, { + duration : currentOpts.changeSpeed, + easing : currentOpts.easingChange, + step : fancybox_draw, + complete : finish_resizing + }); + } + }); + + return; + } + + wrap.css('opacity', 1); + + if (currentOpts.transitionIn == 'elastic') { + start_pos = fancybox_get_zoom_from(); + + inner.css({ + top : currentOpts.padding, + left : currentOpts.padding, + width : Math.max(start_pos.width - (currentOpts.padding * 2), 1), + height : Math.max(start_pos.height - (currentOpts.padding * 2), 1) + }) + .html( tmp.contents() ); + + wrap.css(start_pos).show(); + + if (currentOpts.opacity) { + final_pos.opacity = 0; + } + + fx.prop = 0; + + $(fx).animate({ prop: 1 }, { + duration : currentOpts.speedIn, + easing : currentOpts.easingIn, + step : fancybox_draw, + complete : _finish + }); + + } else { + inner.css({ + top : currentOpts.padding, + left : currentOpts.padding, + width : Math.max(final_pos.width - (currentOpts.padding * 2), 1), + height : Math.max(final_pos.height - (currentOpts.padding * 2) - titleh, 1) + }) + .html( tmp.contents() ); + + wrap.css( final_pos ).fadeIn( currentOpts.transitionIn == 'none' ? 0 : currentOpts.speedIn, _finish ); + } + }, + + fancybox_process_inline = function() { + tmp.width( selectedOpts.width ); + tmp.height( selectedOpts.height ); + + if (selectedOpts.width == 'auto') { + selectedOpts.width = tmp.width(); + } + if (selectedOpts.height == 'auto') { + selectedOpts.height = tmp.height(); + } + + fancybox_show(); + }, + + fancybox_process_image = function() { + busy = true; + + selectedOpts.width = imgPreloader.width; + selectedOpts.height = imgPreloader.height; + + $("<img />").attr({ + 'id' : 'fancybox-img', + 'src' : imgPreloader.src, + 'alt' : selectedOpts.title + }).appendTo( tmp ); + + fancybox_show(); + }, + + fancybox_start = function() { + fancybox_abort(); + + var obj = selectedArray[ selectedIndex ], + href, + type, + title, + str, + emb, + selector, + data; + + selectedOpts = $.extend({}, $.fn.fancybox.defaults, (typeof $(obj).data('fancybox') == 'undefined' ? selectedOpts : $(obj).data('fancybox'))); + title = obj.title || $(obj).title || selectedOpts.title || ''; + + if (obj.nodeName && !selectedOpts.orig) { + selectedOpts.orig = $(obj).children("img:first").length ? $(obj).children("img:first") : $(obj); + } + + if (title === '' && selectedOpts.orig) { + title = selectedOpts.orig.attr('alt'); + } + + if (obj.nodeName && (/^(?:javascript|#)/i).test(obj.href)) { + href = selectedOpts.href || null; + } else { + href = selectedOpts.href || obj.href || null; + } + + if (selectedOpts.type) { + type = selectedOpts.type; + + if (!href) { + href = selectedOpts.content; + } + + } else if (selectedOpts.content) { + type = 'html'; + + } else if (href) { + if (href.match(imgRegExp)) { + type = 'image'; + + } else if (href.match(swfRegExp)) { + type = 'swf'; + + } else if ($(obj).hasClass("iframe")) { + type = 'iframe'; + + } else if (href.match(/#/)) { + obj = href.substr(href.indexOf("#")); + + type = $(obj).length > 0 ? 'inline' : 'ajax'; + } else { + type = 'ajax'; + } + } else { + type = 'inline'; + } + + selectedOpts.type = type; + selectedOpts.href = href; + selectedOpts.title = title; + + if (selectedOpts.autoDimensions && selectedOpts.type !== 'iframe' && selectedOpts.type !== 'swf') { + selectedOpts.width = 'auto'; + selectedOpts.height = 'auto'; + } + + if (selectedOpts.modal) { + selectedOpts.overlayShow = true; + selectedOpts.hideOnOverlayClick = false; + selectedOpts.hideOnContentClick = false; + selectedOpts.enableEscapeButton = false; + selectedOpts.showCloseButton = false; + } + + if ($.isFunction(selectedOpts.onStart)) { + if (selectedOpts.onStart(selectedArray, selectedIndex, selectedOpts) === false) { + busy = false; + return; + } + } + + tmp.css('padding', (shadow + selectedOpts.padding + selectedOpts.margin)); + + $('.fancybox-inline-tmp').unbind('fancybox-cancel').bind('fancybox-change', function() { + $(this).replaceWith(inner.children()); + }); + + switch (type) { + case 'html' : + tmp.html( selectedOpts.content ); + fancybox_process_inline(); + break; + + case 'inline' : + $('<div class="fancybox-inline-tmp" />').hide().insertBefore( $(obj) ).bind('fancybox-cleanup', function() { + $(this).replaceWith(inner.children()); + }).bind('fancybox-cancel', function() { + $(this).replaceWith(tmp.children()); + }); + + $(obj).appendTo(tmp); + + fancybox_process_inline(); + break; + + case 'image': + busy = false; + + $.fancybox.showActivity(); + + imgPreloader = new Image(); + + imgPreloader.onerror = function() { + fancybox_error(); + }; + + imgPreloader.onload = function() { + imgPreloader.onerror = null; + imgPreloader.onload = null; + fancybox_process_image(); + }; + + imgPreloader.src = href; + + break; + + case 'swf': + str = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"><param name="movie" value="' + href + '"></param>'; + emb = ''; + + $.each(selectedOpts.swf, function(name, val) { + str += '<param name="' + name + '" value="' + val + '"></param>'; + emb += ' ' + name + '="' + val + '"'; + }); + + str += '<embed src="' + href + '" type="application/x-shockwave-flash" width="' + selectedOpts.width + '" height="' + selectedOpts.height + '"' + emb + '></embed></object>'; + + tmp.html(str); + + fancybox_process_inline(); + break; + + case 'ajax': + selector = href.split('#', 2); + data = selectedOpts.ajax.data || {}; + + if (selector.length > 1) { + href = selector[0]; + + if (typeof data == "string") { + data += '&selector=' + selector[1]; + } else { + data.selector = selector[1]; + } + } + + busy = false; + $.fancybox.showActivity(); + + ajaxLoader = $.ajax($.extend(selectedOpts.ajax, { + url : href, + data : data, + error : fancybox_error, + success : function(data, textStatus, XMLHttpRequest) { + if (ajaxLoader.status == 200) { + tmp.html( data ); + fancybox_process_inline(); + } + } + })); + + break; + + case 'iframe' : + $('<iframe id="fancybox-frame" name="fancybox-frame' + new Date().getTime() + '" frameborder="0" hspace="0" scrolling="' + selectedOpts.scrolling + '" src="' + selectedOpts.href + '"></iframe>').appendTo(tmp); + fancybox_show(); + break; + } + }, + + fancybox_animate_loading = function() { + if (!loading.is(':visible')){ + clearInterval(loadingTimer); + return; + } + + $('div', loading).css('top', (loadingFrame * -40) + 'px'); + + loadingFrame = (loadingFrame + 1) % 12; + }, + + fancybox_init = function() { + if ($("#fancybox-wrap").length) { + return; + } + + $('body').append( + tmp = $('<div id="fancybox-tmp"></div>'), + loading = $('<div id="fancybox-loading"><div></div></div>'), + overlay = $('<div id="fancybox-overlay"></div>'), + wrap = $('<div id="fancybox-wrap"></div>') + ); + + if (!$.support.opacity) { + wrap.addClass('fancybox-ie'); + loading.addClass('fancybox-ie'); + } + + outer = $('<div id="fancybox-outer"></div>') + .append('<div class="fancy-bg" id="fancy-bg-n"></div><div class="fancy-bg" id="fancy-bg-ne"></div><div class="fancy-bg" id="fancy-bg-e"></div><div class="fancy-bg" id="fancy-bg-se"></div><div class="fancy-bg" id="fancy-bg-s"></div><div class="fancy-bg" id="fancy-bg-sw"></div><div class="fancy-bg" id="fancy-bg-w"></div><div class="fancy-bg" id="fancy-bg-nw"></div>') + .appendTo( wrap ); + + outer.append( + inner = $('<div id="fancybox-inner"></div>'), + close = $('<a id="fancybox-close"></a>'), + + nav_left = $('<a href="javascript:;" id="fancybox-left"><span class="fancy-ico" id="fancybox-left-ico"></span></a>'), + nav_right = $('<a href="javascript:;" id="fancybox-right"><span class="fancy-ico" id="fancybox-right-ico"></span></a>') + ); + + close.click($.fancybox.close); + loading.click($.fancybox.cancel); + + nav_left.click(function(e) { + e.preventDefault(); + $.fancybox.prev(); + }); + + nav_right.click(function(e) { + e.preventDefault(); + $.fancybox.next(); + }); + + if (isIE6) { + overlay.get(0).style.setExpression('height', "document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px'"); + loading.get(0).style.setExpression('top', "(-20 + (document.documentElement.clientHeight ? document.documentElement.clientHeight/2 : document.body.clientHeight/2 ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop )) + 'px'"); + + outer.prepend('<iframe id="fancybox-hide-sel-frame" src="javascript:\'\';" scrolling="no" frameborder="0" ></iframe>'); + } + }; + + /* + * Public methods + */ + + $.fn.fancybox = function(options) { + $(this) + .data('fancybox', $.extend({}, options, ($.metadata ? $(this).metadata() : {}))) + .unbind('click.fb').bind('click.fb', function(e) { + e.preventDefault(); + + if (busy) { + return; + } + + busy = true; + + $(this).blur(); + + selectedArray = []; + selectedIndex = 0; + + var rel = $(this).attr('rel') || ''; + + if (!rel || rel == '' || rel === 'nofollow') { + selectedArray.push(this); + + } else { + selectedArray = $("a[rel=" + rel + "], area[rel=" + rel + "]"); + selectedIndex = selectedArray.index( this ); + } + + fancybox_start(); + + return false; + }); + + return this; + }; + + $.fancybox = function(obj) { + if (busy) { + return; + } + + busy = true; + + var opts = typeof arguments[1] !== 'undefined' ? arguments[1] : {}; + + selectedArray = []; + selectedIndex = opts.index || 0; + + if ($.isArray(obj)) { + for (var i = 0, j = obj.length; i < j; i++) { + if (typeof obj[i] == 'object') { + $(obj[i]).data('fancybox', $.extend({}, opts, obj[i])); + } else { + obj[i] = $({}).data('fancybox', $.extend({content : obj[i]}, opts)); + } + } + + selectedArray = jQuery.merge(selectedArray, obj); + + } else { + if (typeof obj == 'object') { + $(obj).data('fancybox', $.extend({}, opts, obj)); + } else { + obj = $({}).data('fancybox', $.extend({content : obj}, opts)); + } + + selectedArray.push(obj); + } + + if (selectedIndex > selectedArray.length || selectedIndex < 0) { + selectedIndex = 0; + } + + fancybox_start(); + }; + + $.fancybox.showActivity = function() { + clearInterval(loadingTimer); + + loading.show(); + loadingTimer = setInterval(fancybox_animate_loading, 66); + }; + + $.fancybox.hideActivity = function() { + loading.hide(); + }; + + $.fancybox.next = function() { + return $.fancybox.pos( currentIndex + 1); + }; + + $.fancybox.prev = function() { + return $.fancybox.pos( currentIndex - 1); + }; + + $.fancybox.pos = function(pos) { + if (busy) { + return; + } + + pos = parseInt(pos, 10); + + if (pos > -1 && currentArray.length > pos) { + selectedIndex = pos; + fancybox_start(); + } + + if (currentOpts.cyclic && currentArray.length > 1 && pos < 0) { + selectedIndex = currentArray.length - 1; + fancybox_start(); + } + + if (currentOpts.cyclic && currentArray.length > 1 && pos >= currentArray.length) { + selectedIndex = 0; + fancybox_start(); + } + + return; + }; + + $.fancybox.cancel = function() { + if (busy) { + return; + } + + busy = true; + + $.event.trigger('fancybox-cancel'); + + fancybox_abort(); + + if (selectedOpts && $.isFunction(selectedOpts.onCancel)) { + selectedOpts.onCancel(selectedArray, selectedIndex, selectedOpts); + } + + busy = false; + }; + + // Note: within an iframe use - parent.$.fancybox.close(); + $.fancybox.close = function() { + if (busy || wrap.is(':hidden')) { + return; + } + + busy = true; + + if (currentOpts && $.isFunction(currentOpts.onCleanup)) { + if (currentOpts.onCleanup(currentArray, currentIndex, currentOpts) === false) { + busy = false; + return; + } + } + + fancybox_abort(); + + $(close.add( nav_left ).add( nav_right )).hide(); + + $('#fancybox-title').remove(); + + wrap.add(inner).add(overlay).unbind(); + + $(window).unbind("resize.fb scroll.fb"); + $(document).unbind('keydown.fb'); + + function _cleanup() { + overlay.fadeOut('fast'); + + wrap.hide(); + + $.event.trigger('fancybox-cleanup'); + + inner.empty(); + + if ($.isFunction(currentOpts.onClosed)) { + currentOpts.onClosed(currentArray, currentIndex, currentOpts); + } + + currentArray = selectedOpts = []; + currentIndex = selectedIndex = 0; + currentOpts = selectedOpts = {}; + + busy = false; + } + + inner.css('overflow', 'hidden'); + + if (currentOpts.transitionOut == 'elastic') { + start_pos = fancybox_get_zoom_from(); + + var pos = wrap.position(); + + final_pos = { + top : pos.top , + left : pos.left, + width : wrap.width(), + height : wrap.height() + }; + + if (currentOpts.opacity) { + final_pos.opacity = 1; + } + + fx.prop = 1; + + $(fx).animate({ prop: 0 }, { + duration : currentOpts.speedOut, + easing : currentOpts.easingOut, + step : fancybox_draw, + complete : _cleanup + }); + + } else { + wrap.fadeOut( currentOpts.transitionOut == 'none' ? 0 : currentOpts.speedOut, _cleanup); + } + }; + + $.fancybox.resize = function() { + var c, h; + + if (busy || wrap.is(':hidden')) { + return; + } + + busy = true; + + c = inner.wrapInner("<div style='overflow:auto'></div>").children(); + h = c.height(); + + wrap.css({height: h + (currentOpts.padding * 2) + titleh}); + inner.css({height: h}); + + c.replaceWith(c.children()); + + $.fancybox.center(); + }; + + $.fancybox.center = function() { + busy = true; + + var view = fancybox_get_viewport(), + margin = currentOpts.margin, + to = {}; + + to.top = view[3] + ((view[1] - ((wrap.height() - titleh) + (shadow * 2 ))) * 0.5); + to.left = view[2] + ((view[0] - (wrap.width() + (shadow * 2 ))) * 0.5); + + to.top = Math.max(view[3] + margin, to.top); + to.left = Math.max(view[2] + margin, to.left); + + wrap.css(to); + + busy = false; + }; + + $.fn.fancybox.defaults = { + padding : 10, + margin : 20, + opacity : false, + modal : false, + cyclic : false, + scrolling : 'auto', // 'auto', 'yes' or 'no' + + width : 560, + height : 340, + + autoScale : true, + autoDimensions : true, + centerOnScroll : false, + + ajax : {}, + swf : { wmode: 'transparent' }, + + hideOnOverlayClick : true, + hideOnContentClick : false, + + overlayShow : true, + overlayOpacity : 0.3, + overlayColor : '#666', + + titleShow : true, + titlePosition : 'outside', // 'outside', 'inside' or 'over' + titleFormat : null, + + transitionIn : 'fade', // 'elastic', 'fade' or 'none' + transitionOut : 'fade', // 'elastic', 'fade' or 'none' + + speedIn : 300, + speedOut : 300, + + changeSpeed : 300, + changeFade : 'fast', + + easingIn : 'swing', + easingOut : 'swing', + + showCloseButton : true, + showNavArrows : true, + enableEscapeButton : true, + + onStart : null, + onCancel : null, + onComplete : null, + onCleanup : null, + onClosed : null + }; + + $(document).ready(function() { + fancybox_init(); + }); + +})(jQuery); \ No newline at end of file diff --git a/public/javascripts/fancybox/jquery.fancybox-1.3.1.pack.js b/public/javascripts/fancybox/jquery.fancybox-1.3.1.pack.js new file mode 100644 index 0000000000000000000000000000000000000000..8421d53a6d1e1770e3995009feea599375909718 --- /dev/null +++ b/public/javascripts/fancybox/jquery.fancybox-1.3.1.pack.js @@ -0,0 +1,44 @@ +/* + * FancyBox - jQuery Plugin + * Simple and fancy lightbox alternative + * + * Examples and documentation at: http://fancybox.net + * + * Copyright (c) 2008 - 2010 Janis Skarnelis + * + * Version: 1.3.1 (05/03/2010) + * Requires: jQuery v1.3+ + * + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + */ + +(function(b){var m,u,x,g,D,i,z,A,B,p=0,e={},q=[],n=0,c={},j=[],E=null,s=new Image,G=/\.(jpg|gif|png|bmp|jpeg)(.*)?$/i,S=/[^\.]\.(swf)\s*$/i,H,I=1,k,l,h=false,y=b.extend(b("<div/>")[0],{prop:0}),v=0,O=!b.support.opacity&&!window.XMLHttpRequest,J=function(){u.hide();s.onerror=s.onload=null;E&&E.abort();m.empty()},P=function(){b.fancybox('<p id="fancybox_error">The requested content cannot be loaded.<br />Please try again later.</p>',{scrolling:"no",padding:20,transitionIn:"none",transitionOut:"none"})}, +K=function(){return[b(window).width(),b(window).height(),b(document).scrollLeft(),b(document).scrollTop()]},T=function(){var a=K(),d={},f=c.margin,o=c.autoScale,t=(20+f)*2,w=(20+f)*2,r=c.padding*2;if(c.width.toString().indexOf("%")>-1){d.width=a[0]*parseFloat(c.width)/100-40;o=false}else d.width=c.width+r;if(c.height.toString().indexOf("%")>-1){d.height=a[1]*parseFloat(c.height)/100-40;o=false}else d.height=c.height+r;if(o&&(d.width>a[0]-t||d.height>a[1]-w))if(e.type=="image"||e.type=="swf"){t+=r; +w+=r;o=Math.min(Math.min(a[0]-t,c.width)/c.width,Math.min(a[1]-w,c.height)/c.height);d.width=Math.round(o*(d.width-r))+r;d.height=Math.round(o*(d.height-r))+r}else{d.width=Math.min(d.width,a[0]-t);d.height=Math.min(d.height,a[1]-w)}d.top=a[3]+(a[1]-(d.height+40))*0.5;d.left=a[2]+(a[0]-(d.width+40))*0.5;if(c.autoScale===false){d.top=Math.max(a[3]+f,d.top);d.left=Math.max(a[2]+f,d.left)}return d},U=function(a){if(a&&a.length)switch(c.titlePosition){case "inside":return a;case "over":return'<span id="fancybox-title-over">'+ +a+"</span>";default:return'<span id="fancybox-title-wrap"><span id="fancybox-title-left"></span><span id="fancybox-title-main">'+a+'</span><span id="fancybox-title-right"></span></span>'}return false},V=function(){var a=c.title,d=l.width-c.padding*2,f="fancybox-title-"+c.titlePosition;b("#fancybox-title").remove();v=0;if(c.titleShow!==false){a=b.isFunction(c.titleFormat)?c.titleFormat(a,j,n,c):U(a);if(!(!a||a==="")){b('<div id="fancybox-title" class="'+f+'" />').css({width:d,paddingLeft:c.padding, +paddingRight:c.padding}).html(a).appendTo("body");switch(c.titlePosition){case "inside":v=b("#fancybox-title").outerHeight(true)-c.padding;l.height+=v;break;case "over":b("#fancybox-title").css("bottom",c.padding);break;default:b("#fancybox-title").css("bottom",b("#fancybox-title").outerHeight(true)*-1);break}b("#fancybox-title").appendTo(D).hide()}}},W=function(){b(document).unbind("keydown.fb").bind("keydown.fb",function(a){if(a.keyCode==27&&c.enableEscapeButton){a.preventDefault();b.fancybox.close()}else if(a.keyCode== +37){a.preventDefault();b.fancybox.prev()}else if(a.keyCode==39){a.preventDefault();b.fancybox.next()}});if(b.fn.mousewheel){g.unbind("mousewheel.fb");j.length>1&&g.bind("mousewheel.fb",function(a,d){a.preventDefault();h||d===0||(d>0?b.fancybox.prev():b.fancybox.next())})}if(c.showNavArrows){if(c.cyclic&&j.length>1||n!==0)A.show();if(c.cyclic&&j.length>1||n!=j.length-1)B.show()}},X=function(){var a,d;if(j.length-1>n){a=j[n+1].href;if(typeof a!=="undefined"&&a.match(G)){d=new Image;d.src=a}}if(n>0){a= +j[n-1].href;if(typeof a!=="undefined"&&a.match(G)){d=new Image;d.src=a}}},L=function(){i.css("overflow",c.scrolling=="auto"?c.type=="image"||c.type=="iframe"||c.type=="swf"?"hidden":"auto":c.scrolling=="yes"?"auto":"visible");if(!b.support.opacity){i.get(0).style.removeAttribute("filter");g.get(0).style.removeAttribute("filter")}b("#fancybox-title").show();c.hideOnContentClick&&i.one("click",b.fancybox.close);c.hideOnOverlayClick&&x.one("click",b.fancybox.close);c.showCloseButton&&z.show();W();b(window).bind("resize.fb", +b.fancybox.center);c.centerOnScroll?b(window).bind("scroll.fb",b.fancybox.center):b(window).unbind("scroll.fb");b.isFunction(c.onComplete)&&c.onComplete(j,n,c);h=false;X()},M=function(a){var d=Math.round(k.width+(l.width-k.width)*a),f=Math.round(k.height+(l.height-k.height)*a),o=Math.round(k.top+(l.top-k.top)*a),t=Math.round(k.left+(l.left-k.left)*a);g.css({width:d+"px",height:f+"px",top:o+"px",left:t+"px"});d=Math.max(d-c.padding*2,0);f=Math.max(f-(c.padding*2+v*a),0);i.css({width:d+"px",height:f+ +"px"});if(typeof l.opacity!=="undefined")g.css("opacity",a<0.5?0.5:a)},Y=function(a){var d=a.offset();d.top+=parseFloat(a.css("paddingTop"))||0;d.left+=parseFloat(a.css("paddingLeft"))||0;d.top+=parseFloat(a.css("border-top-width"))||0;d.left+=parseFloat(a.css("border-left-width"))||0;d.width=a.width();d.height=a.height();return d},Q=function(){var a=e.orig?b(e.orig):false,d={};if(a&&a.length){a=Y(a);d={width:a.width+c.padding*2,height:a.height+c.padding*2,top:a.top-c.padding-20,left:a.left-c.padding- +20}}else{a=K();d={width:1,height:1,top:a[3]+a[1]*0.5,left:a[2]+a[0]*0.5}}return d},N=function(){u.hide();if(g.is(":visible")&&b.isFunction(c.onCleanup))if(c.onCleanup(j,n,c)===false){b.event.trigger("fancybox-cancel");h=false;return}j=q;n=p;c=e;i.get(0).scrollTop=0;i.get(0).scrollLeft=0;if(c.overlayShow){O&&b("select:not(#fancybox-tmp select)").filter(function(){return this.style.visibility!=="hidden"}).css({visibility:"hidden"}).one("fancybox-cleanup",function(){this.style.visibility="inherit"}); +x.css({"background-color":c.overlayColor,opacity:c.overlayOpacity}).unbind().show()}l=T();V();if(g.is(":visible")){b(z.add(A).add(B)).hide();var a=g.position(),d;k={top:a.top,left:a.left,width:g.width(),height:g.height()};d=k.width==l.width&&k.height==l.height;i.fadeOut(c.changeFade,function(){var f=function(){i.html(m.contents()).fadeIn(c.changeFade,L)};b.event.trigger("fancybox-change");i.empty().css("overflow","hidden");if(d){i.css({top:c.padding,left:c.padding,width:Math.max(l.width-c.padding* +2,1),height:Math.max(l.height-c.padding*2-v,1)});f()}else{i.css({top:c.padding,left:c.padding,width:Math.max(k.width-c.padding*2,1),height:Math.max(k.height-c.padding*2,1)});y.prop=0;b(y).animate({prop:1},{duration:c.changeSpeed,easing:c.easingChange,step:M,complete:f})}})}else{g.css("opacity",1);if(c.transitionIn=="elastic"){k=Q();i.css({top:c.padding,left:c.padding,width:Math.max(k.width-c.padding*2,1),height:Math.max(k.height-c.padding*2,1)}).html(m.contents());g.css(k).show();if(c.opacity)l.opacity= +0;y.prop=0;b(y).animate({prop:1},{duration:c.speedIn,easing:c.easingIn,step:M,complete:L})}else{i.css({top:c.padding,left:c.padding,width:Math.max(l.width-c.padding*2,1),height:Math.max(l.height-c.padding*2-v,1)}).html(m.contents());g.css(l).fadeIn(c.transitionIn=="none"?0:c.speedIn,L)}}},F=function(){m.width(e.width);m.height(e.height);if(e.width=="auto")e.width=m.width();if(e.height=="auto")e.height=m.height();N()},Z=function(){h=true;e.width=s.width;e.height=s.height;b("<img />").attr({id:"fancybox-img", +src:s.src,alt:e.title}).appendTo(m);N()},C=function(){J();var a=q[p],d,f,o,t,w;e=b.extend({},b.fn.fancybox.defaults,typeof b(a).data("fancybox")=="undefined"?e:b(a).data("fancybox"));o=a.title||b(a).title||e.title||"";if(a.nodeName&&!e.orig)e.orig=b(a).children("img:first").length?b(a).children("img:first"):b(a);if(o===""&&e.orig)o=e.orig.attr("alt");d=a.nodeName&&/^(?:javascript|#)/i.test(a.href)?e.href||null:e.href||a.href||null;if(e.type){f=e.type;if(!d)d=e.content}else if(e.content)f="html";else if(d)if(d.match(G))f= +"image";else if(d.match(S))f="swf";else if(b(a).hasClass("iframe"))f="iframe";else if(d.match(/#/)){a=d.substr(d.indexOf("#"));f=b(a).length>0?"inline":"ajax"}else f="ajax";else f="inline";e.type=f;e.href=d;e.title=o;if(e.autoDimensions&&e.type!=="iframe"&&e.type!=="swf"){e.width="auto";e.height="auto"}if(e.modal){e.overlayShow=true;e.hideOnOverlayClick=false;e.hideOnContentClick=false;e.enableEscapeButton=false;e.showCloseButton=false}if(b.isFunction(e.onStart))if(e.onStart(q,p,e)===false){h=false; +return}m.css("padding",20+e.padding+e.margin);b(".fancybox-inline-tmp").unbind("fancybox-cancel").bind("fancybox-change",function(){b(this).replaceWith(i.children())});switch(f){case "html":m.html(e.content);F();break;case "inline":b('<div class="fancybox-inline-tmp" />').hide().insertBefore(b(a)).bind("fancybox-cleanup",function(){b(this).replaceWith(i.children())}).bind("fancybox-cancel",function(){b(this).replaceWith(m.children())});b(a).appendTo(m);F();break;case "image":h=false;b.fancybox.showActivity(); +s=new Image;s.onerror=function(){P()};s.onload=function(){s.onerror=null;s.onload=null;Z()};s.src=d;break;case "swf":t='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+e.width+'" height="'+e.height+'"><param name="movie" value="'+d+'"></param>';w="";b.each(e.swf,function(r,R){t+='<param name="'+r+'" value="'+R+'"></param>';w+=" "+r+'="'+R+'"'});t+='<embed src="'+d+'" type="application/x-shockwave-flash" width="'+e.width+'" height="'+e.height+'"'+w+"></embed></object>";m.html(t); +F();break;case "ajax":a=d.split("#",2);f=e.ajax.data||{};if(a.length>1){d=a[0];if(typeof f=="string")f+="&selector="+a[1];else f.selector=a[1]}h=false;b.fancybox.showActivity();E=b.ajax(b.extend(e.ajax,{url:d,data:f,error:P,success:function(r){if(E.status==200){m.html(r);F()}}}));break;case "iframe":b('<iframe id="fancybox-frame" name="fancybox-frame'+(new Date).getTime()+'" frameborder="0" hspace="0" scrolling="'+e.scrolling+'" src="'+e.href+'"></iframe>').appendTo(m);N();break}},$=function(){if(u.is(":visible")){b("div", +u).css("top",I*-40+"px");I=(I+1)%12}else clearInterval(H)},aa=function(){if(!b("#fancybox-wrap").length){b("body").append(m=b('<div id="fancybox-tmp"></div>'),u=b('<div id="fancybox-loading"><div></div></div>'),x=b('<div id="fancybox-overlay"></div>'),g=b('<div id="fancybox-wrap"></div>'));if(!b.support.opacity){g.addClass("fancybox-ie");u.addClass("fancybox-ie")}D=b('<div id="fancybox-outer"></div>').append('<div class="fancy-bg" id="fancy-bg-n"></div><div class="fancy-bg" id="fancy-bg-ne"></div><div class="fancy-bg" id="fancy-bg-e"></div><div class="fancy-bg" id="fancy-bg-se"></div><div class="fancy-bg" id="fancy-bg-s"></div><div class="fancy-bg" id="fancy-bg-sw"></div><div class="fancy-bg" id="fancy-bg-w"></div><div class="fancy-bg" id="fancy-bg-nw"></div>').appendTo(g); +D.append(i=b('<div id="fancybox-inner"></div>'),z=b('<a id="fancybox-close"></a>'),A=b('<a href="javascript:;" id="fancybox-left"><span class="fancy-ico" id="fancybox-left-ico"></span></a>'),B=b('<a href="javascript:;" id="fancybox-right"><span class="fancy-ico" id="fancybox-right-ico"></span></a>'));z.click(b.fancybox.close);u.click(b.fancybox.cancel);A.click(function(a){a.preventDefault();b.fancybox.prev()});B.click(function(a){a.preventDefault();b.fancybox.next()});if(O){x.get(0).style.setExpression("height", +"document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px'");u.get(0).style.setExpression("top","(-20 + (document.documentElement.clientHeight ? document.documentElement.clientHeight/2 : document.body.clientHeight/2 ) + ( ignoreMe = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop )) + 'px'");D.prepend('<iframe id="fancybox-hide-sel-frame" src="javascript:\'\';" scrolling="no" frameborder="0" ></iframe>')}}}; +b.fn.fancybox=function(a){b(this).data("fancybox",b.extend({},a,b.metadata?b(this).metadata():{})).unbind("click.fb").bind("click.fb",function(d){d.preventDefault();if(!h){h=true;b(this).blur();q=[];p=0;d=b(this).attr("rel")||"";if(!d||d==""||d==="nofollow")q.push(this);else{q=b("a[rel="+d+"], area[rel="+d+"]");p=q.index(this)}C();return false}});return this};b.fancybox=function(a,d){if(!h){h=true;d=typeof d!=="undefined"?d:{};q=[];p=d.index||0;if(b.isArray(a)){for(var f=0,o=a.length;f<o;f++)if(typeof a[f]== +"object")b(a[f]).data("fancybox",b.extend({},d,a[f]));else a[f]=b({}).data("fancybox",b.extend({content:a[f]},d));q=jQuery.merge(q,a)}else{if(typeof a=="object")b(a).data("fancybox",b.extend({},d,a));else a=b({}).data("fancybox",b.extend({content:a},d));q.push(a)}if(p>q.length||p<0)p=0;C()}};b.fancybox.showActivity=function(){clearInterval(H);u.show();H=setInterval($,66)};b.fancybox.hideActivity=function(){u.hide()};b.fancybox.next=function(){return b.fancybox.pos(n+1)};b.fancybox.prev=function(){return b.fancybox.pos(n- +1)};b.fancybox.pos=function(a){if(!h){a=parseInt(a,10);if(a>-1&&j.length>a){p=a;C()}if(c.cyclic&&j.length>1&&a<0){p=j.length-1;C()}if(c.cyclic&&j.length>1&&a>=j.length){p=0;C()}}};b.fancybox.cancel=function(){if(!h){h=true;b.event.trigger("fancybox-cancel");J();e&&b.isFunction(e.onCancel)&&e.onCancel(q,p,e);h=false}};b.fancybox.close=function(){function a(){x.fadeOut("fast");g.hide();b.event.trigger("fancybox-cleanup");i.empty();b.isFunction(c.onClosed)&&c.onClosed(j,n,c);j=e=[];n=p=0;c=e={};h=false} +if(!(h||g.is(":hidden"))){h=true;if(c&&b.isFunction(c.onCleanup))if(c.onCleanup(j,n,c)===false){h=false;return}J();b(z.add(A).add(B)).hide();b("#fancybox-title").remove();g.add(i).add(x).unbind();b(window).unbind("resize.fb scroll.fb");b(document).unbind("keydown.fb");i.css("overflow","hidden");if(c.transitionOut=="elastic"){k=Q();var d=g.position();l={top:d.top,left:d.left,width:g.width(),height:g.height()};if(c.opacity)l.opacity=1;y.prop=1;b(y).animate({prop:0},{duration:c.speedOut,easing:c.easingOut, +step:M,complete:a})}else g.fadeOut(c.transitionOut=="none"?0:c.speedOut,a)}};b.fancybox.resize=function(){var a,d;if(!(h||g.is(":hidden"))){h=true;a=i.wrapInner("<div style='overflow:auto'></div>").children();d=a.height();g.css({height:d+c.padding*2+v});i.css({height:d});a.replaceWith(a.children());b.fancybox.center()}};b.fancybox.center=function(){h=true;var a=K(),d=c.margin,f={};f.top=a[3]+(a[1]-(g.height()-v+40))*0.5;f.left=a[2]+(a[0]-(g.width()+40))*0.5;f.top=Math.max(a[3]+d,f.top);f.left=Math.max(a[2]+ +d,f.left);g.css(f);h=false};b.fn.fancybox.defaults={padding:10,margin:20,opacity:false,modal:false,cyclic:false,scrolling:"auto",width:560,height:340,autoScale:true,autoDimensions:true,centerOnScroll:false,ajax:{},swf:{wmode:"transparent"},hideOnOverlayClick:true,hideOnContentClick:false,overlayShow:true,overlayOpacity:0.3,overlayColor:"#666",titleShow:true,titlePosition:"outside",titleFormat:null,transitionIn:"fade",transitionOut:"fade",speedIn:300,speedOut:300,changeSpeed:300,changeFade:"fast", +easingIn:"swing",easingOut:"swing",showCloseButton:true,showNavArrows:true,enableEscapeButton:true,onStart:null,onCancel:null,onComplete:null,onCleanup:null,onClosed:null};b(document).ready(function(){aa()})})(jQuery); \ No newline at end of file diff --git a/public/javascripts/fancybox/jquery.mousewheel-3.0.2.pack.js b/public/javascripts/fancybox/jquery.mousewheel-3.0.2.pack.js new file mode 100644 index 0000000000000000000000000000000000000000..b950db1a20304f828afb2bc025358ff4760b51d9 --- /dev/null +++ b/public/javascripts/fancybox/jquery.mousewheel-3.0.2.pack.js @@ -0,0 +1,13 @@ +/*! Copyright (c) 2009 Brandon Aaron (http://brandonaaron.net) + * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) + * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses. + * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers. + * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix. + * + * Version: 3.0.2 + * + * Requires: 1.2.2+ + */ + +(function(b){function d(a){var f=[].slice.call(arguments,1),e=0;a=b.event.fix(a||window.event);a.type="mousewheel";if(a.wheelDelta)e=a.wheelDelta/120;if(a.detail)e=-a.detail/3;f.unshift(a,e);return b.event.handle.apply(this,f)}var c=["DOMMouseScroll","mousewheel"];b.event.special.mousewheel={setup:function(){if(this.addEventListener)for(var a=c.length;a;)this.addEventListener(c[--a],d,false);else this.onmousewheel=d},teardown:function(){if(this.removeEventListener)for(var a=c.length;a;)this.removeEventListener(c[--a], +d,false);else this.onmousewheel=null}};b.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})})(jQuery); \ No newline at end of file diff --git a/public/javascripts/group_nav.js b/public/javascripts/group_nav.js new file mode 100644 index 0000000000000000000000000000000000000000..f3d9600bb3550a0b191647c2036cf3b86bf8eb2e --- /dev/null +++ b/public/javascripts/group_nav.js @@ -0,0 +1,16 @@ +$(document).ready( function() { + + var vars = [], hash; + var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&'); + for(var i = 0; i < hashes.length; i++) + { + hash = hashes[i].split('='); + vars.push(hash[0]); + vars[hash[0]] = hash[1]; + } + + $("."+vars['g']).addClass('selected'); + + $("#group img").load(function(){$(this).fadeIn("slow");}); + +}); diff --git a/public/javascripts/publisher.js b/public/javascripts/publisher.js index f8e0f369dc1c72a3045ceb6093841639b63ff2b1..28d902098d14d2b132dea0a45299be78e9d2b291 100644 --- a/public/javascripts/publisher.js +++ b/public/javascripts/publisher.js @@ -1,24 +1,20 @@ - $(document).ready( function() { +$(document).ready( function() { - $("#publisher_content_pickers .status_message").click(selectPublisherTab); - $("#publisher_content_pickers .bookmark").click(selectPublisherTab); - $("#publisher_content_pickers .blog").click(selectPublisherTab); - $("#publisher_content_pickers .photo").click(selectPublisherTab); - - $("#new_status_message").submit(function() { - - }); + $("#publisher_content_pickers .status_message").click(selectPublisherTab); + $("#publisher_content_pickers .bookmark").click(selectPublisherTab); + $("#publisher_content_pickers .blog").click(selectPublisherTab); + $("#publisher_content_pickers .photo").click(selectPublisherTab); - function selectPublisherTab(evt){ - evt.preventDefault(); - var form_id = "#new_" + this.className - if( $(form_id).css("display") == "none" ) { - $("#publisher_content_pickers").children("li").removeClass("selected"); - $("#publisher_form form").fadeOut(50); + function selectPublisherTab(evt){ + evt.preventDefault(); + var form_id = "#new_" + this.className + if( $(form_id).css("display") == "none" ) { + $("#publisher_content_pickers").children("li").removeClass("selected"); + $("#publisher_form form").fadeOut(50); - $(this).toggleClass("selected"); - $(form_id).delay(50).fadeIn(200); - } + $(this).toggleClass("selected"); + $(form_id).delay(50).fadeIn(200); } + } - }); +}); diff --git a/public/javascripts/view.js b/public/javascripts/view.js index 5da7a9f9e6bb8ef3a6be76d8f59c00bade700bf9..6648c171480d2f08e0b2cd88e7bb281e710353a2 100644 --- a/public/javascripts/view.js +++ b/public/javascripts/view.js @@ -21,15 +21,7 @@ $(document).ready(function(){ var show_comments_toggle = $(this).parent().prev().children(".show_post_comments"); show_comments_toggle.html("hide comments ("+ ($(this).children().length - 1) + ")"); }; - }); - - $('a').hover(function(){ - if( $(this).children("img").length < 1 ) - $(this).fadeTo(60, 0.5); - }, function(){ - if( $(this).children("img").length < 1 ) - $(this).fadeTo(80, 1); - }); + }); $('#debug_info').click(function() { $('#debug_more').toggle('fast', function() { @@ -89,21 +81,14 @@ $(document).ready(function(){ }); //buttons////// - $("#add_photos_button").toggle( - function(){ - $("#add_photo_box").fadeIn(300); - },function(){ - $("#add_photo_box").fadeOut(200); - } - ); + - $("#add_album_button").toggle( - function(){ - $("#add_album_box").fadeIn(300); - },function(){ - $("#add_album_box").fadeOut(200); - } - ); + $("#add_album_button").fancybox(); + $("#add_group_button").fancybox(); + $("#add_request_button").fancybox(); + $("#add_photo_button").fancybox(); + + //pane_toggler_button("photo"); $("input[type='submit']").addClass("button"); @@ -115,5 +100,22 @@ $(document).ready(function(){ $(this).fadeIn("slow"); }); + $(".delete").hover(function(){ + $(this).toggleClass("button"); + }); });//end document ready + + +function pane_toggler_button( name ) { + + $("#add_" + name + "_button").toggle( + function(evt){ + evt.preventDefault(); + $("#add_" + name + "_pane").fadeIn(300); + },function(evt){ + evt.preventDefault(); + $("#add_" + name +"_pane").fadeOut(200); + } + ); +} diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css index 9335a088faac8923f566dec4cfb062f274bf79e4..0d8edc7da480790048d55942cb24734dae2514e5 100644 --- a/public/stylesheets/application.css +++ b/public/stylesheets/application.css @@ -12,10 +12,12 @@ body { a { color: #018790; - text-decoration: none; - font-weight: bold; } + color: #556270; + text-decoration: none; } a:hover { - color: #018790; } + color: white; + background-color: #018790; + background-color: #556270; } #flash_notice, #flash_error, @@ -64,34 +66,30 @@ a { header { position: relative; margin: -2em; - margin-bottom: 30px; + margin-bottom: 20px; color: #555555; background-color: #2b2726; + background-color: black; border-bottom: 3px solid #333333; padding: 6px 0; padding-top: 0; } header #diaspora_text { + margin-bottom: 1em; font-family: "BrandonGrotesqueLightRegular"; - font-size: 24px; - position: absolute; + font-size: 16px; border: none; color: white; text-shadow: 0 2px 0 black; } header #diaspora_text a { color: #666666; } header #diaspora_text span.sub_text { - color: black; text-shadow: none; } header #session_action { float: right; - margin-top: 9px; text-shadow: 0 1px 0 black; padding-right: 10px; } - header #session_action a { - color: #777777; - border: none; } - header #session_action a.new_requests { - color: #df0101; } + header #session_action a.new_requests { + color: #df0101; } #show_filters { z-index: 100; @@ -108,13 +106,12 @@ header { ul#stream, ul#friend_stream { margin: 0; - padding: 0; - color: #666666; } + padding: 0; } ul#stream > li, ul#friend_stream > li { list-style: none; padding: 15px 0; - border-bottom: 1px solid #f1f1f1; - margin-bottom: 5px; } + margin-bottom: 5px; + border-bottom: 1px solid #eeeeee; } ul#friend_stream > li { padding: 0.2em 0; } @@ -144,10 +141,9 @@ h1 { font-size: 21px; font-weight: bold; line-height: 36px; } - h1 p.description, h1 span.description { + h1 p.description, h1 span.description, h1 .description { font-weight: 200; - color: #999999; - padding: 0.1em; } + color: #999999; } h3 { position: relativex; @@ -155,9 +151,10 @@ h3 { font-weight: bold; } form { + position: relative; font-size: 120%; margin: 1em; - margin-left: 0em; } + margin-left: 0em; } #user_name { margin-bottom: 20px; } @@ -300,7 +297,8 @@ label { color: #999999; position: absolute; top: 3px; - left: 0.48em; } + left: 0.48em; + font-weight: normal; } #publisher { background-color: rgba(10, 81, 109, 0.05); @@ -350,12 +348,12 @@ ul#publisher_content_pickers li { /* cycle it! */ .album { position: relative; - height: 200px; + height: 300px; width: 300px; display: inline-block; } .album .name { position: absolute; - z-index: 600; + z-index: 6; padding: 1em; background: rgba(0, 0, 0, 0.8); bottom: 20px; @@ -375,17 +373,20 @@ ul#publisher_content_pickers li { h1.big_text { position: relative; line-height: auto; - border-top: 2px solid #666666; - border-bottom: 1px solid #666666; - text-align: center; } + border-bottom: 1px solid #666666; } + h1.big_text .right { + top: -6px; } + +#content_bottom .right { + top: -5px; } .right { - float: right; - margin-top: 6px; } + display: inline; + float: right; } .back { - position: absolute; - font-size: 12px; } + font-size: 12px; + font-weight: normal; } #content_bottom { position: relative; @@ -400,15 +401,12 @@ h1.big_text { width: 100%; } .sub_header { + position: relative; text-align: center; font-style: italic; - margin-top: -5px; margin-bottom: 20px; color: #999999; } -#next_prev_links { - text-align: center; } - .image_thumb { display: inline-block; width: 100px; @@ -417,8 +415,58 @@ h1.big_text { min-height: 100px; } .image_thumb img { display: none; } - .image_thumb img:hover { - border-bottom: 2px solid #666666; } .image_cycle img { display: none; } + +#group { + color: #333333; } + #group ul { + margin: 0; + padding: 0; + font-size: 14px; } + #group ul > li { + display: inline; + margin-right: 10px; } + #group ul > li.selected, #group ul > li.selected a { + color: white; + font-weight: bold; + font-size: 18px; } + #group a { + color: #333333; + font-weight: normal; } + #group #friend_pictures .add_new { + position: relative; + display: inline-block; + height: 40px; + width: 40px; + background-color: #222222; + text-align: center; + font-size: 40px; + line-height: 33px; + top: -9px; } + #group #friend_pictures .add_new:hover { + background: #999999; + color: black; } + #group #friend_pictures img { + display: none; + height: 40px; } + +#add_photo_loader { + position: absolute; + display: none; + left: -25px; + top: 4px; } + +#user_menu { + background: #333333; + padding: 5px; + margin: 0; + list-style: none; } + #user_menu a { + color: #999999; } + #user_menu > li { + display: inline; + margin-right: 1em; } + #user_menu > li:last-child { + margin-right: 0; } diff --git a/public/stylesheets/sass/application.sass b/public/stylesheets/sass/application.sass index 0225b383a0da8b0cb3e51335545f2d27b5b3a4d9..9ef450368b97eafd1223f1ee14d260569a4d752c 100644 --- a/public/stylesheets/sass/application.sass +++ b/public/stylesheets/sass/application.sass @@ -11,12 +11,14 @@ body :margin 0 a :color #018790 + :color #556270 :text :decoration none - :font-weight bold &:hover - :color #018790 - + :color #fff + :background + :color #018790 + :color #556270 #flash_notice, #flash_error, @@ -68,20 +70,22 @@ a header :position relative :margin -2em - :bottom 30px + :bottom 20px :color #555 :background :color #2B2726 + :color #000 :border :bottom 3px solid #333 :padding 6px 0 :top 0 #diaspora_text + :margin + :bottom 1em :font :family 'BrandonGrotesqueLightRegular' - :size 24px - :position absolute + :size 16px :border none :color #fff :text @@ -90,18 +94,13 @@ header :color #666 span.sub_text - :color #000 :text :shadow none #session_action :float right - :margin - :top 9px :text-shadow 0 1px 0 #000 a - :color #777 - :border none &.new_requests :color #DF0101 :padding-right 10px @@ -121,13 +120,12 @@ header ul#stream, ul#friend_stream :margin 0 :padding 0 - :color #666 > li :list-style none :padding 15px 0 - :border - :bottom 1px solid #f1f1f1 :margin-bottom 5px + :border + :bottom 1px solid #eee ul#friend_stream > li @@ -168,11 +166,10 @@ h1 :weight bold :line-height 36px - p.description, span.description + p.description, span.description, .description :font :weight 200 :color #999 - :padding 0.1em h3 :position relativex @@ -181,11 +178,11 @@ h3 :weight bold form + :position relative :font :size 120% :margin 1em - :margin-left 0em - + :left 0em #user_name :margin @@ -366,6 +363,8 @@ label :position absolute :top 3px :left 0.48em + :font + :weight normal #publisher :background @@ -430,13 +429,13 @@ ul#publisher_content_pickers li .album :position relative - :height 200px + :height 300px :width 300px :display inline-block .name :position absolute - :z-index 600 + :z-index 6 :padding 1em :background rgba(0,0,0,0.8) :bottom 20px @@ -465,20 +464,23 @@ h1.big_text :position relative :line-height auto :border - :top 2px solid #666 :bottom 1px solid #666 - :text - :align center + + .right + :top -6px + +#content_bottom + .right + :top -5px .right + :display inline :float right - :margin - :top 6px .back - :position absolute :font :size 12px + :weight normal #content_bottom :position relative @@ -498,19 +500,15 @@ h1.big_text :width 100% .sub_header + :position relative :text :align center :font :style italic :margin - :top -5px :bottom 20px :color #999 -#next_prev_links - :text-align center - - .image_thumb :display inline-block :width 100px @@ -521,10 +519,76 @@ h1.big_text img :display none - &:hover - :border - :bottom 2px solid #666 - .image_cycle img :display none + +#group + :color #333 + ul + :margin 0 + :padding 0 + :font + :size 14px + > li + :display inline + :margin + :right 10px + + &.selected, &.selected a + :color #fff + :font + :weight bold + :size 18px + + a + :color #333 + :font + :weight normal + + #friend_pictures + .add_new + :position relative + :display inline-block + :height 40px + :width 40px + :background + :color #222 + :text-align center + :font-size 40px + :line-height 33px + :top -9px + + &:hover + :background #999 + :color #000 + + img + :display none + :height 40px + +#add_photo_loader + :position absolute + :display none + :left -25px + :top 4px + +#user_menu + :background #333 + :padding 5px + :margin 0 + :list-style none + + a + :color #999 + + > li + :display inline + :margin + :right 1em + + &:last-child + :margin + :right 0 + + diff --git a/public/stylesheets/sass/ui.sass b/public/stylesheets/sass/ui.sass index 50000a8d3b27af930231adce67ce8d766d80699e..ee01e08bc5d203f09d6408725eaa4b3a9ccca153 100644 --- a/public/stylesheets/sass/ui.sass +++ b/public/stylesheets/sass/ui.sass @@ -5,21 +5,22 @@ :display inline - :color #777 + :padding 4px + :font-size 12px :line-height 100% :text-shadow 0 1px 0 #fff - :min-height 14px + :min-height 10px - :background -webkit-gradient(linear, 0% 29%, 0% 85%, from(#FAFAFA), to(#E0E0E0)) - :background -moz-linear-gradient(top, #FAFAFA, #E0E0E0) + :background -webkit-gradient(linear, 0% 29%, 0% 85%, from(#FCFCFC), to(#F6F6F6)) + :background -moz-linear-gradient(top, #FCFCFC, #F6F6F6) - :border 1px solid #ccc - :bottom 1px solid #666 - :left 1px solid #999 - :right 1px solid #999 + :border 1px solid #EEE + :bottom 1px solid #999 + :left 1px solid #ccc + :right 1px solid #ccc :border-radius 3px :-moz-border-radius 3px @@ -27,28 +28,32 @@ :cursor pointer + :box-shadow 0 1px 1px #eee + :-webkit-box-shadow 0 1px 1px #eee + :-moz-box-shadow 0 1px 1px #eee - :box-shadow 0 1px 1px #ccc - :-webkit-box-shadow 0 1px 1px #ccc - :-moz-box-shadow 0 1px 1px #ccc - - a - :font-weight normal - :color #777 + :font-weight normal + :color #666 -.button - :padding 5px + &:hover + :color #666 + :background -webkit-gradient(linear, 0% 29%, 0% 85%, from(#FAFAFA), to(#F0F0F0)) + :background -moz-linear-gradient(top, #FAFAFA, #F0F0F0) &:active - :box-shadow 0 0px 2px #000 - :-webkit-box-shadow 0 0px 2px #000 - :-moz-box-shadow 0 0px 2px #000 - :color #555 + :color #666 + :background -webkit-gradient(linear, 0% 29%, 0% 85%, from(#F0F0F0), to(#FAFAFA)) + :background -moz-linear-gradient(top, #F0F0F0, #FAFAFA) + :border + :top 1px solid #ccc + ul.button_set - :padding 5px 0 + :padding + :left 0 + :right 0 > li :padding 5px @@ -75,8 +80,8 @@ ul.button_set :right none .button .selected, .button_set .selected - :background -webkit-gradient(linear, 0% 29%, 0% 85%, from(#E0E0E0), to(#FAFAFA)) - :background -moz-linear-gradient(top, #e0e0e0, #fafafa) + :background -webkit-gradient(linear, 0% 29%, 0% 85%, from(#F0F0F0), to(#FAFAFA)) + :background -moz-linear-gradient(top, #F0F0F0, #fafafa) :border :top 1px solid #aaa @@ -94,33 +99,17 @@ ul.button_set :display none - :right 0 :background - :color rgba( 30,30,30,0.95 ) + :color #fff - :border 2px solid #999 + :border 4px solid #000 - :border-radius 5px - :-moz-border-radius 5px - :-webkit-border-radius 5px + :border-radius 3px + :-moz-border-radius 3px + :-webkit-border-radius 3px - :color #999 + :box-shadow 0 0 5px #000 + :-webkit-box-shadow 0 0 10px #000 + + :padding 2em - :font - :size 12px - :weight normal - - :line-height auto - - form - :margin 0 - :padding 10px - :color #999 - - input[type='text'] - :width 80% - :display block - - p - :padding 10px - :display inline diff --git a/public/stylesheets/ui.css b/public/stylesheets/ui.css index 63c8dc0cccd78c40ce087a1282e4c92e2e44f3f7..dd791bafb2974a21fc21fcd4d28520e50977235c 100644 --- a/public/stylesheets/ui.css +++ b/public/stylesheets/ui.css @@ -2,38 +2,39 @@ font-family: "Lucida Grande", sans-serif; font-style: normal; display: inline; - color: #777777; + padding: 4px; font-size: 12px; line-height: 100%; text-shadow: 0 1px 0 white; - min-height: 14px; - background: -webkit-gradient(linear, 0% 29%, 0% 85%, from(#fafafa), to(#e0e0e0)); - background: -moz-linear-gradient(top, #fafafa, #e0e0e0); - border: 1px solid #cccccc; - border-bottom: 1px solid #666666; - border-left: 1px solid #999999; - border-right: 1px solid #999999; + min-height: 10px; + background: -webkit-gradient(linear, 0% 29%, 0% 85%, from(#fcfcfc), to(#f6f6f6)); + background: -moz-linear-gradient(top, #fcfcfc, #f6f6f6); + border: 1px solid #eeeeee; + border-bottom: 1px solid #999999; + border-left: 1px solid #cccccc; + border-right: 1px solid #cccccc; border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; cursor: pointer; - box-shadow: 0 1px 1px #cccccc; - -webkit-box-shadow: 0 1px 1px #cccccc; - -moz-box-shadow: 0 1px 1px #cccccc; } - .button a, .button_set a { - font-weight: normal; - color: #777777; } - -.button { - padding: 5px; } - .button:active { - box-shadow: 0 0px 2px black; - -webkit-box-shadow: 0 0px 2px black; - -moz-box-shadow: 0 0px 2px black; - color: #555555; } + box-shadow: 0 1px 1px #eeeeee; + -webkit-box-shadow: 0 1px 1px #eeeeee; + -moz-box-shadow: 0 1px 1px #eeeeee; + font-weight: normal; + color: #666666; } + .button:hover, .button_set:hover { + color: #666666; + background: -webkit-gradient(linear, 0% 29%, 0% 85%, from(#fafafa), to(#f0f0f0)); + background: -moz-linear-gradient(top, #fafafa, #f0f0f0); } + .button:active, .button_set:active { + color: #666666; + background: -webkit-gradient(linear, 0% 29%, 0% 85%, from(#f0f0f0), to(#fafafa)); + background: -moz-linear-gradient(top, #f0f0f0, #fafafa); + border-top: 1px solid #cccccc; } ul.button_set { - padding: 5px 0; } + padding-left: 0; + padding-right: 0; } ul.button_set > li { padding: 5px; display: inline; @@ -50,8 +51,8 @@ ul.button_set { border-right: none; } .button .selected, .button_set .selected { - background: -webkit-gradient(linear, 0% 29%, 0% 85%, from(#e0e0e0), to(#fafafa)); - background: -moz-linear-gradient(top, #e0e0e0, #fafafa); + background: -webkit-gradient(linear, 0% 29%, 0% 85%, from(#f0f0f0), to(#fafafa)); + background: -moz-linear-gradient(top, #f0f0f0, #fafafa); border-top: 1px solid #aaaaaa; } .right { @@ -63,23 +64,11 @@ ul.button_set { z-index: 20; position: absolute; display: none; - right: 0; - background-color: rgba(30, 30, 30, 0.95); - border: 2px solid #999999; - border-radius: 5px; - -moz-border-radius: 5px; - -webkit-border-radius: 5px; - color: #999999; - font-size: 12px; - font-weight: normal; - line-height: auto; } - .contextual_pane form { - margin: 0; - padding: 10px; - color: #999999; } - .contextual_pane form input[type='text'] { - width: 80%; - display: block; } - .contextual_pane form p { - padding: 10px; - display: inline; } + background-color: white; + border: 4px solid black; + border-radius: 3px; + -moz-border-radius: 3px; + -webkit-border-radius: 3px; + box-shadow: 0 0 5px black; + -webkit-box-shadow: 0 0 10px black; + padding: 2em; } diff --git a/spec/controllers/dashboards_controller_spec.rb b/spec/controllers/groups_controller_spec.rb similarity index 65% rename from spec/controllers/dashboards_controller_spec.rb rename to spec/controllers/groups_controller_spec.rb index b05603fb613dd21abe799870d3b25cbf69aa476f..6bfce5434d36baa8dac2feb6d79ccf0d438fec7c 100644 --- a/spec/controllers/dashboards_controller_spec.rb +++ b/spec/controllers/groups_controller_spec.rb @@ -1,9 +1,11 @@ require File.dirname(__FILE__) + '/../spec_helper' - -describe DashboardsController do +include ApplicationHelper +describe GroupsController do render_views before do - @user = Factory.create(:user, :profile => Profile.new( :first_name => "bob", :last_name => "smith")) + @user = Factory.create(:user) + @user.person.save + @person = Factory.create(:person) request.env['warden'] = mock_model(Warden, :authenticate? => @user, :authenticate! => @user, :authenticate => @user) end @@ -11,7 +13,7 @@ describe DashboardsController do sign_in :user, @user Factory.create :person get :index - assigns[:friends].should == Person.friends.all + assigns[:friends].should == @user.friends end end diff --git a/spec/controllers/publics_controller_spec.rb b/spec/controllers/publics_controller_spec.rb index 132210e6673735c728b3ff67744071fb8562ffbb..8ef2a30c866366661eb30937027ff0d4784f9f46 100644 --- a/spec/controllers/publics_controller_spec.rb +++ b/spec/controllers/publics_controller_spec.rb @@ -4,20 +4,59 @@ describe PublicsController do render_views before do - @user = Factory.create(:user, :profile => Profile.new( :first_name => "bob", :last_name => "smith")) + @user = Factory.create(:user) + @user.person.save request.env['warden'] = mock_model(Warden, :authenticate? => @user, :authenticate! => @user, :authenticate => @user) end describe 'receive endpoint' do - - it 'should accept a post from anohter node and save the information' do - + it 'should have a and endpoint and return a 200 on successful receipt of a request' do + post :receive, :id =>@user.person.id + response.code.should == '200' + end + + it 'should accept a post from another node and save the information' do + pending person = Factory.create(:person) message = StatusMessage.new(:message => 'foo', :person => person) - StatusMessage.all.count.should == 0 - post :receive, {:xml => Post.build_xml_for(message)} - StatusMessage.all.count.should == 1 + StatusMessage.all.count.should be 0 + post :receive, :id => @user.person.id, :xml => message.to_diaspora_xml(message) + StatusMessage.all.count.should be 1 end end + + describe 'friend requests' do + before do + @user2 = Factory.create(:user) + @user2.person.save + group = @user2.group(:name => 'disciples') + + @user3 = Factory.create(:user) + @user3.person.save + + req = @user2.send_friend_request_to(@user.person.url, group.id) + + @xml = req.to_diaspora_xml + + req.delete + @user2.reload + @user2.pending_requests.count.should be 1 + end + + it 'should add the pending request to the right user if the target person exists locally' do + @user2.delete + post :receive, :id => @user.person.id, :xml => @xml + + assigns(:user).should eq(@user) + end + + it 'should add the pending request to the right user if the target person does not exist locally' do + @user2.person.delete + @user2.delete + post :receive, :id => @user.person.id, :xml => @xml + + assigns(:user).should eq(@user) + end + end end diff --git a/spec/controllers/sockets_controller_spec.rb b/spec/controllers/sockets_controller_spec.rb index a5109e356b6096aa4f4090d6b13c75a2e0082bdf..19673cb243b96784afafb31a74701eaf25c18f47 100644 --- a/spec/controllers/sockets_controller_spec.rb +++ b/spec/controllers/sockets_controller_spec.rb @@ -7,32 +7,36 @@ describe 'SocketsController' do SocketsController.unstub!(:new) #EventMachine::WebSocket.stub!(:start) @controller = SocketsController.new + @controller.request = mock_model(Request, :env => + {'warden' => mock_model(Warden, :authenticate? => @user, :authenticate! => @user, :authenticate => @user)}) stub_sockets_controller end it 'should unstub the websockets' do - WebSocket.initialize_channel + WebSocket.initialize_channels @controller.class.should == SocketsController end - it 'should add a new subscriber to the websockets channel' do - WebSocket.initialize_channel - @controller.new_subscriber.should == 1 - end describe 'actionhash' do before do - @message = Factory.create(:status_message, :person => @user) + @message = @user.post :status_message, :message => "post through user for victory" end it 'should actionhash posts' do - json = @controller.action_hash(@message) + class SocketsController + def url_options + {:host => ""} + end + end + + json = @controller.action_hash(@user.id, @message) json.include?(@message.message).should be_true json.include?('status_message').should be_true end it 'should actionhash retractions' do retraction = Retraction.for @message - json = @controller.action_hash(retraction) + json = @controller.action_hash(@user.id, retraction) json.include?('retraction').should be_true json.include?("html\":null").should be_true end diff --git a/spec/factories.rb b/spec/factories.rb index bd098ec7c5f9ec3797f8fe500f880eaa1cbe436f..88f34e1f691794568f7a50472cbd715fdd6b1481 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -9,25 +9,27 @@ Factory.define :profile do |p| end Factory.define :person do |p| - p.email "bob-person@aol.com" - p.active true - p.sequence(:url) {|n|"http://google-#{n}.com/"} + p.sequence(:email) {|n| "bob-person-#{n}@aol.com"} + p.sequence(:url) {|n| "http://google-#{n}.com/"} + p.profile Factory.create(:profile) + p.serialized_key OpenSSL::PKey::RSA.generate(1024).public_key.export - p.profile Profile.new( :first_name => "Robert", :last_name => "Grimm" ) end Factory.define :person_with_private_key, :parent => :person do |p| p.serialized_key OpenSSL::PKey::RSA.generate(1024).export end +Factory.define :person_with_user, :parent => :person_with_private_key do |p| +end + Factory.define :user do |u| u.sequence(:email) {|n| "bob#{n}@aol.com"} u.password "bluepin7" u.password_confirmation "bluepin7" - u.url "www.example.com/" - u.serialized_key OpenSSL::PKey::RSA::generate(1024).export - u.profile Profile.new( :first_name => "Bob", :last_name => "Smith" ) + u.person { |a| Factory.create(:person_with_user, :owner_id => a._id)} end + Factory.define :status_message do |m| m.sequence(:message) {|n| "jimmy's #{n} whales"} m.person diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb index f4785626515364ee476bebbd57377aa66e4bce82..bb886bd8341b7a22e8311aa38b2ea61f630bd998 100644 --- a/spec/helpers/application_helper_spec.rb +++ b/spec/helpers/application_helper_spec.rb @@ -1,22 +1,12 @@ require File.dirname(__FILE__) + '/../spec_helper' include ApplicationHelper - describe ApplicationHelper do before do @user = Factory.create(:user) @person = Factory.create(:person) end - it "should specifiy if a post is not owned user" do - p = Factory.create(:post, :person => @person) - mine?(p).should be false - end - - it "should specifiy if a post is owned current user" do - p = Factory.create(:post, :person => @user) - mine?(p).should be true - end it "should provide a correct show path for a given person" do person_url(@person).should == "/people/#{@person.id}" @@ -25,4 +15,5 @@ describe ApplicationHelper do it "should provide a correct show path for a given user" do person_url(@user).should == "/users/#{@user.id}" end + end diff --git a/spec/helpers/publics_helper_spec.rb b/spec/helpers/publics_helper_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..bdc9c8250a63c6df30c4429fe97519cb7bd06c4b --- /dev/null +++ b/spec/helpers/publics_helper_spec.rb @@ -0,0 +1,15 @@ +require File.dirname(__FILE__) + '/../spec_helper' + +include PublicsHelper +describe PublicsHelper do + before do + @user = Factory.create(:user) + @person = Factory.create(:person) + end + + it 'should be able to give me the terse url for webfinger' do + @user.person.url = "http://example.com/" + + terse_url( @user.person.url ).should == 'example.com' + end +end diff --git a/spec/helpers/requests_helper_spec.rb b/spec/helpers/requests_helper_spec.rb index 6f5b37442b3a8c3e22a4a807a82565def21874d0..8419bd566c362ed7eb8d12010d09aa94888ceb4d 100644 --- a/spec/helpers/requests_helper_spec.rb +++ b/spec/helpers/requests_helper_spec.rb @@ -20,7 +20,7 @@ describe RequestsHelper do end it 'should return the correct tag and url for a given address' do - relationship_flow('tom@tom.joindiaspora.com')[:friend].should == 'http://tom.joindiaspora.com/' + relationship_flow('tom@tom.joindiaspora.com')[:friend].include?("receive/user").should == true end end diff --git a/spec/lib/diaspora_parser_spec.rb b/spec/lib/diaspora_parser_spec.rb index 10f02f6ef353653af992a862f5fb37a1cd340ced..3e4344a64ad8e856a3db63d79913ec1b44559791 100644 --- a/spec/lib/diaspora_parser_spec.rb +++ b/spec/lib/diaspora_parser_spec.rb @@ -3,98 +3,79 @@ require File.dirname(__FILE__) + '/../spec_helper' include ApplicationHelper include Diaspora::Parser + + describe Diaspora::Parser do before do @user = Factory.create(:user, :email => "bob@aol.com") - @person = Factory.create(:person, :email => "bill@gates.com") + @group = @user.group(:name => 'spies') + @person = Factory.create(:person_with_private_key, :email => "bill@gates.com") + @user2 = Factory.create(:user) end - it "should not store posts from me" do - status_messages = [] - 10.times { status_messages << Factory.build(:status_message, :person => @user)} - xml = Post.build_xml_for(status_messages) - store_objects_from_xml(xml) - StatusMessage.count.should == 0 - end - - it "should reject xml with no sender" do - xml = "<XML> - <head> - </head><posts> - <post><status_message>\n <message>Here is another message</message>\n <owner>a@a.com</owner>\n <snippet>a@a.com</snippet>\n <source>a@a.com</source>\n</status_message></post> - <post><person></person></post> - <post><status_message>\n <message>HEY DUDE</message>\n <owner>a@a.com</owner>\n <snippet>a@a.com</snippet>\n <source>a@a.com</source>\n</status_message></post> - </posts></XML>" - store_objects_from_xml(xml) - Post.count.should == 0 - end - - it "should reject xml with a sender not in the database" do - xml = "<XML> - <head> - <sender> - <email>foo@example.com</email> - </sender> - </head><posts> - <post><status_message>\n <message>Here is another message</message>\n <owner>a@a.com</owner>\n <snippet>a@a.com</snippet>\n <source>a@a.com</source>\n</status_message></post> - <post><person></person></post> - <post><status_message>\n <message>HEY DUDE</message>\n <owner>a@a.com</owner>\n <snippet>a@a.com</snippet>\n <source>a@a.com</source>\n</status_message></post> - </posts></XML>" - store_objects_from_xml(xml) - Post.count.should == 0 - end - - it 'should discard types which are not of type post' do - xml = "<XML> - <head> - <sender> - <email>#{Person.first.email}</email> - </sender> - </head> - <posts> - <post><person></person></post> - </posts></XML>" - - store_objects_from_xml(xml) - Post.count.should == 0 + it "should associate the post with a group" do + @user.activate_friend(@person, @group) + + status_message = Factory.build(:status_message, :message => "hey!", :person => @person) + @user.receive status_message.to_diaspora_xml + + + # mongomapper doesn't support joins, meaning we can't do a query + # on user.groups. + # should this code below be a function of a user? + # something like self.find_group_for(friend_id) ? + groups = @user.groups + groups.shift while not groups[0].person_ids.include?(@person.id) + group = groups[0] + #### + + @group.posts.count.should == 1 end - describe "parsing compliant XML object" do + + describe 'with encryption' do before do - @status_messages = [] - 10.times { @status_messages << Factory.build(:status_message)} - @xml = Post.build_xml_for(@status_messages) + unstub_mocha_stubs end - - it 'should be able to parse the body\'s contents' do - body = parse_body_contents_from_xml(@xml).to_s - body.should_not include "<head>" - body.should_not include "</head>" - body.should_not include "<posts>" - body.should_not include "</posts>" - body.should include "<post>" - body.should include "</post>" + after do + stub_signature_verification + end + it "should not store posts from me" do + 10.times { + message = Factory.build(:status_message, :person => @user) + xml = message.to_diaspora_xml + @user.receive xml + } + StatusMessage.count.should == 0 + end + + it "should reject xml with no sender" do + xml = "<XML> + <head> + </head> + <post><status_message>\n <message>Here is another message</message>\n <owner>a@a.com</owner>\n <snippet>a@a.com</snippet>\n <source>a@a.com</source>\n</status_message></post> + <post><person></person></post> + <post><status_message>\n <message>HEY DUDE</message>\n <owner>a@a.com</owner>\n <snippet>a@a.com</snippet>\n <source>a@a.com</source>\n</status_message></post> + </XML>" + @user.receive xml + Post.count.should == 0 end + end - it 'should be able to extract all posts to an array' do - posts = parse_objects_from_xml(@xml) - posts.is_a?(Array).should be true - posts.count.should == 10 + describe "parsing compliant XML object" do + before do + @xml = Factory.build(:status_message).to_diaspora_xml end it 'should be able to correctly handle comments' do person = Factory.create(:person, :email => "test@testing.com") - post = Factory.create(:status_message) + post = Factory.create(:status_message, :person => @user.person) comment = Factory.build(:comment, :post => post, :person => person, :text => "Freedom!") - xml = "<XML> - <posts> - <post>#{comment.to_xml}</post> - </posts></XML>" + xml = comment.to_diaspora_xml - objects = parse_objects_from_xml(xml) - comment = objects.first + comment = Diaspora::Parser.from_xml(xml) comment.text.should == "Freedom!" comment.person.should == person comment.post.should == post @@ -104,53 +85,95 @@ describe Diaspora::Parser do person = Factory.create(:person) message = Factory.create(:status_message, :person => person) retraction = Retraction.for(message) - request = Post.build_xml_for( [retraction] ) + request = retraction.to_diaspora_xml StatusMessage.count.should == 1 - store_objects_from_xml( request ) + @user.receive request StatusMessage.count.should == 0 end it "should create a new person upon getting a person request" do + person_count = Person.all.count request = Request.instantiate(:to =>"http://www.google.com/", :from => @person) original_person_id = @person.id - xml = Request.build_xml_for [request] - + xml = request.to_diaspora_xml + @person.destroy - Person.all.count.should be 1 - store_objects_from_xml(xml) - Person.all.count.should be 2 + Person.all.count.should == person_count -1 + @user.receive xml + Person.all.count.should == person_count - Person.where(:url => request.callback_url).first.id.should == original_person_id + Person.first(:_id => original_person_id).serialized_key.include?("PUBLIC").should be true + url = "http://" + request.callback_url.split("/")[2] + "/" + Person.where(:url => url).first.id.should == original_person_id end + it "should not create a new person if the person is already here" do + person_count = Person.all.count + request = Request.instantiate(:to =>"http://www.google.com/", :from => @user2.person) + + original_person_id = @user2.person.id + xml = request.to_diaspora_xml + + + Person.all.count.should be person_count + @user.receive xml + Person.all.count.should be person_count + + @user2.reload + @user2.person.reload + @user2.person.serialized_key.include?("PRIVATE").should be true + + url = "http://" + request.callback_url.split("/")[2] + "/" + Person.where(:url => url).first.id.should == original_person_id + end it "should activate the Person if I initiated a request to that url" do - request = Request.instantiate(:to => @person.url, :from => @user).save - - request_remote = Request.new - request_remote.destination_url = @user.url - request_remote.callback_url = @user.url - request_remote.person = @person - request_remote.exported_key = @person.export_key + request = @user.send_friend_request_to( @user2.receive_url, @group.id) + + request.reverse @user2 - xml = Request.build_xml_for [request_remote] + xml = request.to_diaspora_xml + + @user2.person.destroy + @user2.destroy + + @user.receive xml + new_person = Person.first(:url => @user2.person.url) + new_person.nil?.should be false - @person.destroy - request_remote.destroy - store_objects_from_xml(xml) - Person.first(:url => @person.url).active.should be true + @user.reload + @group.reload + @group.people.include?(new_person).should be true + @user.friends.include?(new_person).should be true end - it 'should marshal a retraction for a person' do - retraction = Retraction.for(@user) - request = Retraction.build_xml_for( [retraction] ) + it 'should process retraction for a person' do + person_count = Person.all.count + request = @user.send_friend_request_to( @user2.receive_url, @group.id) + request.reverse @user2 + xml = request.to_diaspora_xml + + retraction = Retraction.for(@user2) + retraction_xml = retraction.to_diaspora_xml + + @user2.person.destroy + @user2.destroy + @user.receive xml + + @group.reload + group_people_count = @group.people.size + #They are now friends + + + Person.count.should == person_count + @user.receive retraction_xml + Person.count.should == person_count-1 - Person.count.should == 2 - store_objects_from_xml( request ) - Person.count.should == 1 + @group.reload + @group.people.size.should == group_people_count -1 end it 'should marshal a profile for a person' do @@ -165,26 +188,24 @@ describe Diaspora::Parser do old_profile.first_name.should == 'bob' #Build xml for profile, clear profile - xml = Post.build_xml_for(person.profile) - reloaded_person = Person.first(:id => id) + xml = person.profile.to_diaspora_xml + reloaded_person = Person.first(:id => id) reloaded_person.profile = nil - reloaded_person.save + reloaded_person.save(:validate => false) #Make sure profile is cleared - Person.first(:id=> id).profile.should be nil + Person.first(:id => id).profile.should be nil old_profile.first_name.should == 'bob' #Marshal profile - store_objects_from_xml xml + @user.receive xml #Check that marshaled profile is the same as old profile person = Person.first(:id => person.id) person.profile.should_not be nil - person.profile.first_name.should == old_profile.first_name + person.profile.first_name.should == old_profile.first_name person.profile.last_name.should == old_profile.last_name person.profile.image_url.should == old_profile.image_url - - end end end diff --git a/spec/lib/message_handler_spec.rb b/spec/lib/message_handler_spec.rb index 553135b9672e972ceed22abebe9c2e809d498412..ba13f8fef0390d97db01e5806b7183098050117c 100644 --- a/spec/lib/message_handler_spec.rb +++ b/spec/lib/message_handler_spec.rb @@ -138,7 +138,6 @@ class FakeHttpRequest @callback = callback_wanted end def response - "NOTE YOU ARE IN FAKE HTTP" end def post; end diff --git a/spec/lib/socket_renderer_spec.rb b/spec/lib/socket_renderer_spec.rb deleted file mode 100644 index 009de8b78ab416718060708fd1a793c5ff34b145..0000000000000000000000000000000000000000 --- a/spec/lib/socket_renderer_spec.rb +++ /dev/null @@ -1,24 +0,0 @@ -=begin - require File.dirname(__FILE__) + '/../spec_helper' - -describe SocketRenderer do - before do - SocketRenderer.instantiate_view - @user = Factory.create(:user, :email => "bob@jones.com") - @user.profile = Factory.create(:profile, :person => @user) - end - - it 'should render a partial for a status message' do - message = Factory.create(:status_message, :person => @user) - html = SocketRenderer.view_for message - html.include? message.message - end - - it 'should prepare a class/view hash' do - message = Factory.create(:status_message, :person => @user) - - hash = SocketRenderer.view_hash(message) - hash[:class].should == "status_messages" - end -end -=end diff --git a/spec/lib/web_hooks_spec.rb b/spec/lib/web_hooks_spec.rb index d1819980f9e54104f29410f054d3819b575d8508..63739f636106366c5ca76f24faa5c9dda25b969d 100644 --- a/spec/lib/web_hooks_spec.rb +++ b/spec/lib/web_hooks_spec.rb @@ -7,12 +7,13 @@ describe Diaspora do describe Webhooks do before do @user = Factory.create(:user, :email => "bob@aol.com") + @user.person.save @person = Factory.create(:person) end describe "body" do before do - @post = Factory.create(:status_message, :person => @user) + @post = Factory.build(:status_message, :person => @user.person) end it "should add the following methods to Post on inclusion" do @@ -21,46 +22,36 @@ describe Diaspora do @post.respond_to?(:people_with_permissions).should be true end - it "should convert an object to a proper diaspora entry" do - @post.to_diaspora_xml.should == "<post>#{@post.to_xml.to_s}</post>" - end - it "should retrieve all valid person endpoints" do - Factory.create(:person, :url => "http://www.bob.com/") - Factory.create(:person, :url => "http://www.alice.com/") - Factory.create(:person, :url => "http://www.jane.com/") + @user.friends << Factory.create(:person, :url => "http://www.bob.com/") + @user.friends << Factory.create(:person, :url => "http://www.alice.com/") + @user.friends << Factory.create(:person, :url => "http://www.jane.com/") + @user.save - non_users = Person.where( :_type => "Person" ).all - @post.people_with_permissions.should == non_users + @post.person.owner.reload + + @post.people_with_permissions.should == @user.friends end it "should send an owners post to their people" do - q = Post.send(:class_variable_get, :@@queue) - q.should_receive :process - @post.save + message_queue.should_receive :process + @user.post :status_message, :message => "hi" end it "should check that it does not send a person's post to an owners people" do - Post.stub(:build_xml_for).and_return(true) - Post.should_not_receive(:build_xml_for) - + message_queue.should_not_receive(:add_post_request) Factory.create(:status_message, :person => Factory.create(:person)) end it "should ensure one url is created for every person" do - 5.times {Factory.create(:person)} - @post.people_with_permissions.size.should == 6 + 5.times {@user.friends << Factory.create(:person)} + @user.save + + @post.person.owner.reload + + @post.people_with_permissions.size.should == 5 end - it "should build an xml object containing multiple Post types" do - Factory.create(:status_message) - Factory.create(:bookmark) - - stream = Post.stream - xml = Post.build_xml_for(stream) - xml.should include "<status_message>" - xml.should include "<bookmark>" - end end end diff --git a/spec/misc_spec.rb b/spec/misc_spec.rb index 773b8c6d9c20f1771008efde0190bd60bd82ebb1..9e9d61efaf95203d39536295bc2ff699b6de1bfd 100644 --- a/spec/misc_spec.rb +++ b/spec/misc_spec.rb @@ -12,6 +12,11 @@ describe 'making sure the spec runner works' do User.count.should == 0 end + it 'should factory create a user with a person saved' do + user = Factory.create(:user) + loaded_user = User.first(:id => user.id) + loaded_user.person.owner_id.should == user.id + end describe 'testing a before do block' do before do Factory.create(:user) diff --git a/spec/models/album_spec.rb b/spec/models/album_spec.rb index b93de4888c7e5a40e29573f7ea81fb9a13261995..f5038ec1c1a86cf888e13748c35fed4b1057d130 100644 --- a/spec/models/album_spec.rb +++ b/spec/models/album_spec.rb @@ -4,7 +4,8 @@ describe Album do before do @fixture_name = File.dirname(__FILE__) + '/../fixtures/bp.jpeg' @user = Factory.create(:user) - @album = Album.new(:name => "test collection", :person => @user) + @user.person.save + @album = Album.new(:name => "test collection", :person => @user.person) end it 'should belong to a person' do @@ -26,8 +27,8 @@ describe Album do end it 'should contain photos' do - album = Album.create(:name => "test collection", :person => @user) - photo = Factory.build(:photo, :person => @user) + album = Album.create(:name => "test collection", :person => @user.person) + photo = Factory.build(:photo, :person => @user.person) album.photos << photo album.photos.count.should == 1 @@ -36,7 +37,7 @@ describe Album do it 'should remove all photos on album delete' do photos = [] 1.upto 3 do - photo = Photo.new(:person => @user, :album => @album, :created_at => Time.now) + photo = Photo.new(:person => @user.person, :album => @album, :created_at => Time.now) photo.image.store! File.open @fixture_name photos << photo end @@ -51,7 +52,7 @@ describe Album do before do @photos = [] 1.upto 3 do |n| - photo = Photo.new(:person => @user, :album => @album, :created_at => Time.now + n) + photo = Photo.new(:person => @user.person, :album => @album, :created_at => Time.now + n) photo.image.store! File.open @fixture_name @photos << photo end diff --git a/spec/models/blogs_spec.rb b/spec/models/blogs_spec.rb index 270339a85cc52f6ed4982f1825ebacdfde44cea6..9be9db74b7989376bb1b31cdc58cfb0329728f64 100644 --- a/spec/models/blogs_spec.rb +++ b/spec/models/blogs_spec.rb @@ -18,7 +18,7 @@ describe Blog do describe "XML" do it 'should serialize to XML' do - body = Factory.create(:blog, :title => "yessir", :body => "penguins") + body = Factory.create(:blog, :title => "yessir", :body => "penguins", :person => @user.person) body.to_xml.to_s.should include "<title>yessir</title>" body.to_xml.to_s.should include "<body>penguins</body>" end diff --git a/spec/models/bookmark_spec.rb b/spec/models/bookmark_spec.rb index 879408430dd88f7a995d046cf56cd2850a0fdf07..ae4567bc1ec155e0d1f18fce7ff541792b592963 100644 --- a/spec/models/bookmark_spec.rb +++ b/spec/models/bookmark_spec.rb @@ -10,34 +10,6 @@ describe Bookmark do it 'should validate its link' do bookmark = Factory.build(:bookmark) - - #links changed valid - bookmark.link = "google.com" - bookmark.valid?.should == true - bookmark.link.should == "http://google.com/" - - bookmark.link = "www.google.com" - bookmark.valid?.should == true - bookmark.link.should == "http://www.google.com/" - - bookmark.link = "google.com/" - bookmark.valid?.should == true - bookmark.link.should == "http://google.com/" - - bookmark.link = "www.google.com/" - bookmark.valid?.should == true - bookmark.link.should == "http://www.google.com/" - - bookmark.link = "http://google.com" - bookmark.valid?.should == true - bookmark.link.should == "http://google.com/" - - bookmark.link = "http://www.google.com" - bookmark.valid?.should == true - - #bookmark.link = "http://babycakes.sofaer.net:3000" - #bookmark.valid?.should == true - #invalid links bookmark.link = "zsdvzxdg" bookmark.valid?.should == false @@ -54,11 +26,29 @@ describe Bookmark do bookmark.link = "http:///www.asodij.com/" bookmark.valid?.should == false end + + it 'should clean links' do + bad_links = [ + "google.com", + "www.google.com", + "google.com/", + "www.google.com/", + "http://google.com", + "http://www.google.com" + ] + + bad_links.each{ |link| + Bookmark.clean_link(link).should satisfy{ |link| + /^(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?$/ix.match(link) + } + } + + end describe "XML" do it 'should serialize to XML' do - Factory.create(:user) - message = Factory.create(:bookmark, :title => "Reddit", :link => "http://reddit.com/") + u = Factory.create(:user) + message = Factory.create(:bookmark, :title => "Reddit", :link => "http://reddit.com/", :person => u.person) message.to_xml.to_s.should include "<title>Reddit</title>" message.to_xml.to_s.should include "<link>http://reddit.com/</link>" end @@ -71,4 +61,20 @@ describe Bookmark do parsed.valid?.should be_true end end + + describe 'with encryption' do + before do + unstub_mocha_stubs + @user = Factory.create(:user) + end + + after do + stub_signature_verification + end + + it 'should save a signed bookmark' do + bookmark = @user.post(:bookmark, :title => "I love cryptography", :link => "http://pgp.mit.edu/") + bookmark.created_at.should_not be nil + end + end end diff --git a/spec/models/comments_spec.rb b/spec/models/comments_spec.rb index 4f5b79115df6ed347f023c3d227db67765faca9f..3be39564486b9d8579cf80a7f62564a993fd76a5 100644 --- a/spec/models/comments_spec.rb +++ b/spec/models/comments_spec.rb @@ -4,9 +4,10 @@ describe Comment do describe "user" do before do @user = Factory.create :user + @user.person.save end it "should be able to comment on his own status" do - status = Factory.create(:status_message, :person => @user) + status = Factory.create(:status_message, :person => @user.person) status.comments.should == [] @user.comment "Yeah, it was great", :on => status @@ -19,42 +20,48 @@ describe Comment do @user.comment "sup dog", :on => status StatusMessage.first.comments.first.text.should == "sup dog" - StatusMessage.first.comments.first.person.should == @user + StatusMessage.first.comments.first.person.should == @user.person end it 'should not send out comments when we have no people' do - status = Factory.create(:status_message, :person => @user) - Comment.send(:class_variable_get, :@@queue).should_not_receive(:add_post_request) + status = Factory.create(:status_message, :person => @user.person) + message_queue.should_not_receive(:add_post_request) @user.comment "sup dog", :on => status end describe 'comment propagation' do before do @person = Factory.create(:person) - @person_two = Factory.create(:person) - @person_status = Factory.create(:status_message, :person => @person) - @user_status = Factory.create(:status_message, :person => @user) + @user.friends << Factory.create(:person) + @user.save + @person2 = Factory.create(:person) + @person_status = Factory.build(:status_message, :person => @person) + @user_status = Factory.build(:status_message, :person => @user.person) end it "should send a user's comment on a person's post to that person" do - Comment.send(:class_variable_get, :@@queue).should_receive(:add_post_request) + message_queue.should_receive(:add_post_request) @user.comment "yo", :on => @person_status end it 'should send a user comment on his own post to lots of people' do - allowed_urls = @user_status.people_with_permissions.map!{|x| x = x.url + "receive/"} - Comment.send(:class_variable_get, :@@queue).should_receive(:add_post_request).with(allowed_urls, anything ) + allowed_urls = @user_status.people_with_permissions.map{|x| x = x.receive_url} + message_queue.should_receive(:add_post_request).with(allowed_urls, anything) @user.comment "yo", :on => @user_status end it 'should send a comment a person made on your post to all people' do - Comment.send(:class_variable_get, :@@queue).should_receive(:add_post_request) - com = Comment.create(:person => @person, :text => "balls", :post => @user_status) + message_queue.should_receive(:add_post_request) + @person.comment "balls", :on => @user_status end + it 'should not send a comment a person made on his own post to anyone' do + message_queue.should_not_receive(:add_post_request) + @person.comment "balls", :on => @person_status + end it 'should not send a comment a person made on a person post to anyone' do - Comment.send(:class_variable_get, :@@queue).should_not_receive(:add_post_request) - com = Comment.create(:person => @person, :text => "balls", :post => @person_status) + message_queue.should_not_receive(:add_post_request) + @person2.comment "balls", :on => @person_status end end end diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb new file mode 100644 index 0000000000000000000000000000000000000000..1d0f400d5f9541231681aab49ad1f67f529853c4 --- /dev/null +++ b/spec/models/group_spec.rb @@ -0,0 +1,55 @@ +require File.dirname(__FILE__) + '/../spec_helper' + +describe Group do + before do + @user = Factory.create(:user) + @friend = Factory.create(:person) + @user2 = Factory.create(:user) + @friend_2 = Factory.create(:person) + end + + describe 'creation' do + it 'should have a name' do + group = @user.group(:name => 'losers') + group.name.should == "losers" + end + + it 'should be able to have people' do + group = @user.group(:name => 'losers', :people => [@friend, @friend_2]) + group.people.size.should == 2 + end + + it 'should be able to have other users' do + group = @user.group(:name => 'losers', :people => [@user2.person]) + group.people.include?(@user.person).should be false + group.people.include?(@user2.person).should be true + group.people.size.should == 1 + end + + it 'should be able to have users and people' do + group = @user.group(:name => 'losers', :people => [@user2.person, @friend_2]) + group.people.include?(@user.person).should be false + group.people.include?(@user2.person).should be true + group.people.include?(@friend_2).should be true + group.people.size.should == 2 + end + + end + + describe 'querying' do + before do + @group = @user.group(:name => 'losers', :people => [@friend]) + end + + it 'belong to a user' do + @group.user.id.should == @user.id + @user.groups.size.should == 1 + @user.groups.first.id.should == @group.id + end + + it 'should have people' do + @group.people.all.include?(@friend).should be true + @group.people.size.should == 1 + end + end +end diff --git a/spec/models/person_spec.rb b/spec/models/person_spec.rb index 1660371b6ba4ad31bb0675921a1731d3c04a53cc..c062d396b65222007c77b7acd38e779902ae5585 100644 --- a/spec/models/person_spec.rb +++ b/spec/models/person_spec.rb @@ -1,54 +1,54 @@ require File.dirname(__FILE__) + '/../spec_helper' describe Person do - it 'should not allow two people with the same url' do - person_one = Factory.create(:person) - person_two = Factory.build(:person, :url => person_one.url) - person_two.valid?.should == false - end - - it 'should not allow a person with the same url as the user' do - user = Factory.create(:user) - person = Factory.build(:person, :url => user.url) - person.valid?.should == false + before do + @user = Factory.create(:user) + @user2 = Factory.create(:user) + @person = Factory.create(:person) + @group = @user.group(:name => "Dudes") + @group2 = @user2.group(:name => "Abscence of Babes") end - it 'should serialize to xml' do - person = Factory.create(:person) - xml = person.to_xml.to_s - (xml.include? "person").should == true - end - it 'should have a profile in its xml' do - person = Factory.create(:person) - xml = person.to_xml.to_s - (xml.include? "first_name").should == true + it 'should not allow two people with the same email' do + person_two = Factory.build(:person, :url => @person.email) + person_two.valid?.should == false end - it 'should only return active friends' do - Factory.create(:person) - Factory.create(:person, :active => false) - Factory.create(:person, :active => false) + describe 'xml' do + before do + @xml = @person.to_xml.to_s + end + it 'should serialize to xml' do + (@xml.include? "person").should == true + end - Person.friends.all.count.should == 1 + it 'should have a profile in its xml' do + (@xml.include? "first_name").should == true + end end + + it 'should know when a post belongs to it' do + person_message = Factory.create(:status_message, :person => @person) + person_two = Factory.create(:person) + @person.owns?(person_message).should be true + person_two.owns?(person_message).should be false + end it 'should delete all of user except comments upon user deletion' do - Factory.create(:user) - f = Factory.create(:person) - p = Factory.create(:person) + Factory.create(:status_message, :person => f) Factory.create(:blog, :person => f) Factory.create(:bookmark, :person => f) Factory.create(:status_message, :person => f) - s = Factory.create(:status_message, :person => p) + s = Factory.create(:status_message, :person => @person) Factory.create(:comment, :person_id => f.id, :text => "yes i do", :post => s) Factory.create(:comment, :person_id => f.id, :text => "i love you", :post => s) Factory.create(:comment, :person_id => f.id, :text => "hello", :post => s) - Factory.create(:comment, :person_id => p.id, :text => "you are creepy", :post => s) + Factory.create(:comment, :person_id => @person.id, :text => "you are creepy", :post => s) f.destroy @@ -57,15 +57,44 @@ describe Person do s.comments.count.should == 4 end - it 'should let a user unfriend another user' do - u = Factory.create(:user) + describe "unfriending" do + it 'should delete an orphaned friend' do + + request = @user.send_friend_request_to @person.receive_url, @group.id + + @user.activate_friend(@person, @group) + @user.reload + + Person.all.count.should == 3 + @user.friends.count.should == 1 + @user.unfriend(@person) + @user.reload + @user.friends.count.should == 0 + Person.all.count.should == 2 + end + + it 'should not delete an un-orphaned friend' do + request = @user.send_friend_request_to @person.receive_url, @group.id + request2 = @user2.send_friend_request_to @person.receive_url, @group2.id + + @user.activate_friend(@person, @group) + @user2.activate_friend(@person, @group2) + + @user.reload + @user2.reload + + Person.all.count.should == 3 + @user.friends.count.should == 1 + @user2.friends.count.should == 1 - f = Factory.create(:person, :active => true) + @user.unfriend(@person) + @user.reload + @user2.reload + @user.friends.count.should == 0 + @user2.friends.count.should == 1 - Person.friends.all.count.should == 1 - u.unfriend(f.id) - Person.friends.all.count.should == 0 - Person.all.count.should == 1 + Person.all.count.should == 3 + end end end diff --git a/spec/models/photo_spec.rb b/spec/models/photo_spec.rb index 3920d83b2d22b276cec4c51afad8a44085e960cb..3091ed74a76df149eeebc07ce2f194ec6b1742f3 100644 --- a/spec/models/photo_spec.rb +++ b/spec/models/photo_spec.rb @@ -3,22 +3,23 @@ require File.dirname(__FILE__) + '/../spec_helper' describe Photo do before do @user = Factory.create(:user) + @user.person.save + @fixture_filename = 'bp.jpeg' @fixture_name = File.dirname(__FILE__) + '/../fixtures/bp.jpeg' @fail_fixture_name = File.dirname(__FILE__) + '/../fixtures/msg.xml' - @album = Album.create(:name => "foo", :person => @user) - @photo = Photo.new(:person => @user, :album => @album) + @album = Album.create(:name => "foo", :person => @user.person) + @photo = Photo.new(:person => @user.person, :album => @album) end it 'should have a constructor' do image = File.open(@fixture_name) - photo = Photo.instantiate(:person => @user, :album => @album, :user_file => [image]) + photo = Photo.instantiate(:person => @user.person, :album => @album, :user_file => [image]) photo.created_at.nil?.should be false - photo.image.read.nil?.should be false end - it 'should save a @photo to GridFS' do + it 'should save a photo to GridFS' do @photo.image.store! File.open(@fixture_name) @photo.save.should == true binary = @photo.image.read @@ -27,11 +28,11 @@ describe Photo do end it 'must have an album' do - photo = Photo.new(:person => @user) + photo = Photo.new(:person => @user.person) photo.image = File.open(@fixture_name) photo.save photo.valid?.should be false - photo.album = Album.create(:name => "foo", :person => @user) + photo.album = Album.create(:name => "foo", :person => @user.person) photo.save Photo.first.album.name.should == 'foo' end @@ -49,6 +50,7 @@ describe Photo do @user.profile.image_url = @photo.image.url(:thumb_medium) @user.save + @user.person.save User.first.profile.image_url.should == @photo.image.url(:thumb_medium) @photo.destroy @@ -56,8 +58,8 @@ describe Photo do end it 'should not use the imported filename as the url' do + pending "Until this passes, duplicate photos will cause errors" @photo.image.store! File.open(@fixture_name) - puts @photo.image.url(:thumb_medium) @photo.image.url.include?(@fixture_filename).should be false @photo.image.url(:thumb_medium).include?("/" + @fixture_filename).should be false end @@ -71,13 +73,6 @@ describe Photo do }.should raise_error end - it 'should not save' do - pending "We need to figure out the difference between us and the example app" - file = File.open(@fail_fixture_name) - @photo.image.should_receive(:check_whitelist!) - @photo.image = file - @photo.save.should == false - end end describe 'with encryption' do @@ -90,8 +85,8 @@ describe Photo do stub_signature_verification end - it 'should save a signed @photo to GridFS' do - photo = Photo.create(:person => @user, :album => @album, :image => File.open(@fixture_name)) + it 'should save a signed photo to GridFS' do + photo = Photo.create(:person => @user.person, :album => @album, :image => File.open(@fixture_name)) photo.save.should == true photo.verify_creator_signature.should be true end diff --git a/spec/models/post_spec.rb b/spec/models/post_spec.rb index aac4898aa01c5f54d74c37c5daeacfe13e87e1bd..a20ffb504b14837d3e5a4ccefa3b78ea537a55fa 100644 --- a/spec/models/post_spec.rb +++ b/spec/models/post_spec.rb @@ -3,17 +3,7 @@ require File.dirname(__FILE__) + '/../spec_helper' describe Post do before do @user = Factory.create(:user, :email => "bob@aol.com") - end - - describe 'defaults' do - before do - WebSocket.stub!(:update_clients) - @post = Factory.create(:post, :person => nil) - end - - it "should associate the owner if none is present" do - @post.person.should == User.owner - end + @user.person.save end describe "newest" do @@ -21,28 +11,21 @@ describe Post do @person_one = Factory.create(:person, :email => "some@dudes.com") @person_two = Factory.create(:person, :email => "other@dudes.com") (2..4).each {|n| Blog.create(:title => "title #{n}", :body => "test #{n}", :person => @person_one)} - (5..8).each { |n| Blog.create(:title => "title #{n}",:body => "test #{n}", :person => @user)} + (5..8).each { |n| Blog.create(:title => "title #{n}",:body => "test #{n}", :person => @user.person)} (9..11).each { |n| Blog.create(:title => "title #{n}",:body => "test #{n}", :person => @person_two)} - Factory.create(:status_message) - Factory.create(:bookmark) + Factory.create(:status_message, :person => @user) + Factory.create(:bookmark, :person => @user) end it "should give the most recent blog title and body from owner" do - blog = Blog.my_newest() - blog.person.email.should == @user.email + blog = Blog.newest_for(@user.person) + blog.person.email.should == @user.person.email blog.class.should == Blog blog.title.should == "title 8" blog.body.should == "test 8" end - - it "should give the most recent blog body for a given email" do - blog = Blog.newest_by_email("some@dudes.com") - blog.person.email.should == @person_one.email - blog.class.should == Blog - blog.title.should == "title 4" - blog.body.should == "test 4" - end + end describe "stream" do @@ -51,10 +34,10 @@ describe Post do @person_one = Factory.create(:person, :email => "some@dudes.com") @person_two = Factory.create(:person, :email => "other@dudes.com") - Factory.create(:status_message, :message => "puppies", :created_at => Time.now+1, :person => @owner) + Factory.create(:status_message, :message => "puppies", :created_at => Time.now+1, :person => @owner.person) Factory.create(:bookmark, :title => "Reddit", :link => "http://reddit.com", :created_at => Time.now+2, :person => @person_one) Factory.create(:status_message, :message => "kittens", :created_at => Time.now+3, :person => @person_two) - Factory.create(:blog, :title => "Bears", :body => "Bear's body", :created_at => Time.now+4, :person => @owner) + Factory.create(:blog, :title => "Bears", :body => "Bear's body", :created_at => Time.now+4, :person => @owner.person) Factory.create(:bookmark, :title => "Google", :link => "http://google.com", :created_at => Time.now+5, :person => @person_two) end @@ -78,15 +61,15 @@ describe Post do end describe 'xml' do it 'should serialize to xml with its person' do - message = Factory.create(:status_message, :person => @user) - (message.to_xml.to_s.include? @user.email).should == true + message = Factory.create(:status_message, :person => @user.person) + (message.to_xml.to_s.include? @user.person.email).should == true end end describe 'deletion' do it 'should delete a posts comments on delete' do - post = Factory.create(:status_message, :person => @user) - @user.comment "hey", :on=> post + post = Factory.create(:status_message, :person => @user.person) + @user.comment "hey", :on => post post.destroy Post.all(:id => post.id).empty?.should == true Comment.all(:text => "hey").empty?.should == true diff --git a/spec/models/request_spec.rb b/spec/models/request_spec.rb index 788b7aee5451794a0ba57b94642231bb49a853f4..c5b49cc64290a04c02750e249852bbfa9fcfe056 100644 --- a/spec/models/request_spec.rb +++ b/spec/models/request_spec.rb @@ -1,7 +1,10 @@ require File.dirname(__FILE__) + '/../spec_helper' describe Request do - + before do + @user = Factory.create(:user) + @group = @user.group(:name => "dudes") + end it 'should require a destination and callback url' do person_request = Request.new person_request.valid?.should be false @@ -11,49 +14,26 @@ describe Request do end it 'should generate xml for the User as a Person' do - user = Factory.create(:user) - user.profile.save - - request = Request.instantiate(:to => "http://www.google.com/", :from => user) + request = @user.send_friend_request_to "http://www.google.com/", @group.id xml = request.to_xml.to_s - xml.include?(user.email).should be true - xml.include?(user.url).should be true - xml.include?(user.profile.first_name).should be true - xml.include?(user.profile.last_name).should be true - end - - - it "should should activate a user" do - remote_person = Factory.create(:person, :email => "robert@grimm.com", :url => "http://king.com/") - f = Request.create(:destination_url => remote_person.url, :person => remote_person) - f.activate_friend - Person.where(:id => remote_person.id).first.active.should be true + xml.include?(@user.person.email).should be true + xml.include?(@user.url).should be true + xml.include?(@user.profile.first_name).should be true + xml.include?(@user.profile.last_name).should be true end - it 'should allow me to see only friend requests sent to me' do - user = Factory.create(:user) - remote_person = Factory.build(:user, :email => "robert@grimm.com", :url => "http://king.com/") + remote_person = Factory.build(:person, :email => "robert@grimm.com", :url => "http://king.com/") - Request.instantiate(:from => user, :to => remote_person.url).save - Request.instantiate(:from => user, :to => remote_person.url).save - Request.instantiate(:from => user, :to => remote_person.url).save - Request.instantiate(:from => remote_person, :to => user.url).save + Request.instantiate(:into => @group.id, :from => @user.person, :to => remote_person.receive_url).save + Request.instantiate(:into => @group.id, :from => @user.person, :to => remote_person.receive_url).save + Request.instantiate(:into => @group.id, :from => @user.person, :to => remote_person.receive_url).save + Request.instantiate(:into => @group.id, :from => remote_person, :to => @user.receive_url).save - Request.for_user(user).all.count.should == 1 - end - - it 'should allow me to see only friend requests sent by me' do - user = Factory.create(:user) - remote_person = Factory.build(:user, :email => "robert@grimm.com", :url => "http://king.com/") - - Request.instantiate(:from => user, :to => remote_person.url).save - Request.instantiate(:from => user, :to => remote_person.url).save - Request.instantiate(:from => user, :to => remote_person.url).save - Request.instantiate(:from => remote_person, :to => user.url).save + Request.for_user(@user).all.count.should == 1 end end diff --git a/spec/models/retraction_spec.rb b/spec/models/retraction_spec.rb index 276a74cb60638b59d3d35fb1bbf47b24902402aa..5c8695feaadacbdf0cdfcf0806c274a8649743b3 100644 --- a/spec/models/retraction_spec.rb +++ b/spec/models/retraction_spec.rb @@ -1,23 +1,27 @@ require File.dirname(__FILE__) + '/../spec_helper' describe Retraction do - describe "posts" do before do @user = Factory.create(:user) - @post = Factory.create(:status_message, :person => @user) + @post = @user.post(:status_message, :message => "Destroy!") + @person = Factory.create(:person) + @user.friends << @person + @user.save end - + describe 'serialization' do it 'should have a post id after serialization' do retraction = Retraction.for(@post) xml = retraction.to_xml.to_s xml.include?(@post.id.to_s).should == true end - + end + describe 'dispatching' do it 'should dispatch a message on delete' do Factory.create(:person) - Post.send(:class_variable_get, :@@queue).should_receive(:add_post_request) + message_queue.should_receive(:add_post_request) @post.destroy end - end + + end diff --git a/spec/models/status_message_spec.rb b/spec/models/status_message_spec.rb index 4bab96af292a0bfcdf881ac9bd314f4988c00626..e4d5b0f500240dcee0ae00ca7ac8f1d5a253ff78 100644 --- a/spec/models/status_message_spec.rb +++ b/spec/models/status_message_spec.rb @@ -18,7 +18,7 @@ describe StatusMessage do describe "XML" do it 'should serialize to XML' do - message = Factory.create(:status_message, :message => "I hate WALRUSES!") + message = Factory.create(:status_message, :message => "I hate WALRUSES!", :person => @user.person) message.to_xml.to_s.should include "<message>I hate WALRUSES!</message>" end diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb index 1431b1cd5bda46b915444d680a3998229d56a21e..eb77b1f05dc675e007220c0d13eed07c5d41c917 100644 --- a/spec/models/user_spec.rb +++ b/spec/models/user_spec.rb @@ -1,35 +1,54 @@ require File.dirname(__FILE__) + '/../spec_helper' describe User do - it "should be a person" do - n = Person.count - Factory.create(:user) - Person.count.should == n+1 + before do + @user = Factory.create(:user) + @group = @user.group(:name => 'heroes') + end + + it 'should instantiate with a person and be valid' do + user = User.instantiate(:email => "bob@bob.com", + :password => "password", + :password_confirmation => "password", + :person => + {:profile => { + :first_name => "bob", + :last_name => "grimm"}}) + + user.save.should be true + user.person.should_not be nil + user.person.profile.should_not be nil end describe 'friend requesting' do - before do - @user = Factory.create(:user) + it "should assign a request to a group" do + friend = Factory.create(:person) + group = @user.group(:name => "Dudes") + group.requests.size.should == 0 + + @user.send_friend_request_to(friend.receive_url, group.id) + + group.reload + group.requests.size.should == 1 end - it "should be able to accept a pending friend request" do - friend = Factory.create(:person, :active => false) - r = Request.instantiate(:to => @user.url, :from => friend) + + it "should be able to accept a pending friend request" do + friend = Factory.create(:person) + r = Request.instantiate(:to => @user.receive_url, :from => friend) r.save Person.all.count.should == 2 Request.for_user(@user).all.count.should == 1 - @user.accept_friend_request(r.id) + @user.accept_friend_request(r.id, @group.id) Request.for_user(@user).all.count.should == 0 - Person.where(:id => friend.id).first.active.should == true end it 'should be able to ignore a pending friend request' do - friend = Factory.create(:person, :active => false) - r = Request.instantiate(:to => @user.url, :from => friend) + friend = Factory.create(:person) + r = Request.instantiate(:to => @user.receive_url, :from => friend) r.save Person.count.should == 2 - friend.active.should == false @user.ignore_friend_request(r.id) @@ -39,25 +58,218 @@ describe User do it 'should not be able to friend request an existing friend' do friend = Factory.create(:person) + + @user.friends << friend + @user.save + + + @user.send_friend_request_to( friend.receive_url, @group.id ).should be nil + end + + + + describe 'multiple users accepting/rejecting the same person' do + before do + @person_one = Factory.create :person + @person_one.save + + @user2 = Factory.create :user + @group2 = @user2.group(:name => "group two") + + @user.pending_requests.empty?.should be true + @user.friends.empty?.should be true + @user2.pending_requests.empty?.should be true + @user2.friends.empty?.should be true + + @request = Request.instantiate(:to => @user.receive_url, :from => @person_one) + @request_two = Request.instantiate(:to => @user2.receive_url, :from => @person_one) + @request_three = Request.instantiate(:to => @user2.receive_url, :from => @user.person) + + @req_xml = @request.to_diaspora_xml + @req_two_xml = @request_two.to_diaspora_xml + @req_three_xml = @request_three.to_diaspora_xml + + @request.destroy + @request_two.destroy + @request_three.destroy + end + + it 'should befriend the user other user on the same pod' do + + @user2.receive @req_three_xml + @user2.pending_requests.size.should be 1 + @user2.accept_friend_request @request_three.id, @group2.id + @user2.friends.include?(@user.person).should be true + Person.all.count.should be 3 + end + + it 'should not delete the ignored user on the same pod' do + + @user2.receive @req_three_xml + @user2.pending_requests.size.should be 1 + @user2.ignore_friend_request @request_three.id + @user2.friends.include?(@user.person).should be false + Person.all.count.should be 3 + end + + it 'should both users should befriend the same person' do + + @user.receive @req_xml + @user.pending_requests.size.should be 1 + @user.accept_friend_request @request.id, @group.id + @user.friends.include?(@person_one).should be true + + @user2.receive @req_two_xml + @user2.pending_requests.size.should be 1 + @user2.accept_friend_request @request_two.id, @group2.id + @user2.friends.include?(@person_one).should be true + Person.all.count.should be 3 + end + + it 'should keep the person around if one of the users rejects him' do + + @user.receive @req_xml + @user.pending_requests.size.should be 1 + @user.accept_friend_request @request.id, @group.id + @user.friends.include?(@person_one).should be true + + @user2.receive @req_two_xml + @user2.pending_requests.size.should be 1 + @user2.ignore_friend_request @request_two.id + @user2.friends.include?(@person_one).should be false + Person.all.count.should be 3 + end + + it 'should not keep the person around if the users ignores them' do + @user.receive @req_xml + @user.pending_requests.size.should be 1 + @user.ignore_friend_request @user.pending_requests.first.id + @user.friends.include?(@person_one).should be false + + @user2.receive @req_two_xml + @user2.pending_requests.size.should be 1 + @user2.ignore_friend_request @user2.pending_requests.first.id#@request_two.id + @user2.friends.include?(@person_one).should be false + Person.all.count.should be 2 + end + - @user.send_friend_request_to( friend.url ).should be nil end - it 'should be able to give me the terse url for webfinger' do - @user.terse_url.should == 'example.com' + describe 'a user accepting rejecting multiple people' do + before do + @person_one = Factory.create :person + @person_two = Factory.create :person + + @user.pending_requests.empty?.should be true + @user.friends.empty?.should be true + + @request = Request.instantiate(:to => @user.receive_url, :from => @person_one) + @request_two = Request.instantiate(:to => @user.receive_url, :from => @person_two) + end + + after do + @user.receive_friend_request @request + + @person_two.destroy + @user.pending_requests.size.should be 1 + @user.friends.size.should be 0 + + @user.receive_friend_request @request_two + @user.pending_requests.size.should be 2 + @user.friends.size.should be 0 + + @user.accept_friend_request @request.id, @group.id + @user.pending_requests.size.should be 1 + @user.friends.size.should be 1 + @user.friends.include?(@person_one).should be true + + @user.ignore_friend_request @request_two.id + @user.pending_requests.size.should be 0 + @user.friends.size.should be 1 + @user.friends.include?(@person_two).should be false + + end + end + end + describe 'profiles' do it 'should be able to update their profile and send it to their friends' do Factory.create(:person) updated_profile = {:profile => {:first_name => 'bob', :last_name => 'billytown', :image_url => "http://clown.com"}} - queue = Profile.send :class_variable_get, :@@queue - queue.should_receive(:process) + message_queue.should_receive(:process) - @user.update_profile(updated_profile).should == true + @user.person.update_profile(updated_profile).should == true @user.profile.image_url.should == "http://clown.com" end end + describe 'receiving' do + before do + @user2 = Factory.create(:user) + @user.friends << @user2.person + @user2.friends << @user.person + @user.person.user_refs += 1 + @user2.person.user_refs += 1 + @user.save + @user2.save + end + + it 'should be able to parse and store a status message from xml' do + status_message = @user2.post :status_message, :message => 'store this!' + person = @user2.person + + xml = status_message.to_diaspora_xml + @user2.destroy + status_message.destroy + StatusMessage.all.size.should == 0 + @user.receive( xml ) + + person.posts.first.message.should == 'store this!' + StatusMessage.all.size.should == 1 + end + end + + describe 'unfriending' do + before do + @user2 = Factory.create :user + @group2 = @user2.group(:name => "Gross people") + + request = @user.send_friend_request_to( @user2.receive_url, @group.id) + request.reverse @user2 + @user2.activate_friend(@user.person, @group2) + @user.receive request.to_diaspora_xml + end + + it 'should unfriend the other user on the same seed' do + @user.reload + @user2.reload + + @user.friends.count.should == 1 + @user2.friends.count.should == 1 + + @user.person.user_refs.should == 1 + + @user2.person.user_refs.should == 1 + + @user2.unfriend @user.person + @user2.friends.count.should be 0 + + @user.person.reload + @user.person.user_refs.should == 0 + + @user.unfriended_by @user2.person + + @user2.person.reload + @user2.person.user_refs.should == 0 + + @group.reload + @group2.reload + @group.people.count.should == 0 + @group2.people.count.should == 0 + end + end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 9eba3000c0b762a42dacd51f26ca4373d115261b..fb730c6db0feb91f720d02ea8f06ef4da7ef787e 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -71,3 +71,7 @@ end end models end + + def message_queue + Post.send(:class_variable_get, :@@queue) + end diff --git a/spec/user_encryption_spec.rb b/spec/user_encryption_spec.rb index 729920af265efb745a4d35be9c33ed4eb15252a6..fde3cf5a8de4c838d89365b9234f54c504c4909e 100644 --- a/spec/user_encryption_spec.rb +++ b/spec/user_encryption_spec.rb @@ -3,16 +3,10 @@ include ApplicationHelper include Diaspora::Parser describe 'user encryption' do - before :all do - #ctx = GPGME::Ctx.new - #keys = ctx.keys - #keys.each{|k| ctx.delete_key(k, true)} - - end before do unstub_mocha_stubs @user = Factory.create(:user) - @user.save + @group = @user.group(:name => 'dudes') @person = Factory.create(:person_with_private_key, :profile => Profile.new(:first_name => 'Remote', :last_name => 'Friend'), @@ -33,28 +27,28 @@ describe 'user encryption' do #keys.each{|k| ctx.delete_key(k, true)} end it 'should have a key' do - @user.key.should_not be nil + @user.encryption_key.should_not be nil end describe 'key exchange on friending' do - it 'should send over a public key' do - Comment.send(:class_variable_get, :@@queue).stub!(:add_post_request) - request = @user.send_friend_request_to("http://example.com/") - Request.build_xml_for([request]).include?( @user.export_key).should be true + it 'should send over a public key' do + message_queue.stub!(:add_post_request) + request = @user.send_friend_request_to("http://example.com/", @group.id) + request.to_diaspora_xml.include?( @user.export_key).should be true end it 'should receive and marshal a public key from a request' do person = Factory.build(:person, :url => "http://test.url/" ) - person.key.nil?.should== false + person.encryption_key.nil?.should== false #should move this to friend request, but i found it here id = person.id original_key = person.export_key request = Request.instantiate(:to =>"http://www.google.com/", :from => person) - xml = Request.build_xml_for [request] + xml = request.to_diaspora_xml person.destroy personcount = Person.all.count - store_objects_from_xml(xml) + @user.receive xml Person.all.count.should == personcount + 1 new_person = Person.first(:url => "http://test.url/") new_person.id.should == id @@ -65,9 +59,20 @@ describe 'user encryption' do describe 'signing and verifying' do it 'should sign a message on create' do - message = Factory.create(:status_message, :person => @user) + message = @user.post :status_message, :message => "hi" message.verify_creator_signature.should be true end + + it 'should sign a retraction on create' do + + unstub_mocha_stubs + message = @user.post :status_message, :message => "hi" + + + retraction = Retraction.for(message) + retraction.verify_creator_signature.should be true + + end it 'should not be able to verify a message from a person without a key' do person = Factory.create(:person, :serialized_key => "lskdfhdlfjnh;klsf") @@ -78,7 +83,7 @@ describe 'user encryption' do it 'should verify a remote signature' do message = Factory.build(:status_message, :person => @person) - message.creator_signature = message.send(:sign_with_key,@person.key) + message.creator_signature = message.send(:sign_with_key,@person.encryption_key) message.save(:validate => false) message.verify_creator_signature.should be true end @@ -86,14 +91,14 @@ describe 'user encryption' do it 'should know if the signature is from the wrong person' do message = Factory.build(:status_message, :person => @person) message.save(:validate => false) - message.creator_signature = message.send(:sign_with_key,@person.key) + message.creator_signature = message.send(:sign_with_key,@person.encryption_key) message.person = @user message.verify_creator_signature.should be false end it 'should know if the signature is for the wrong text' do message = Factory.build(:status_message, :person => @person) - message.creator_signature = message.send(:sign_with_key,@person.key) + message.creator_signature = message.send(:sign_with_key,@person.encryption_key) message.message = 'I love VENISON' message.save(:validate => false) message.verify_creator_signature.should be false @@ -102,18 +107,22 @@ describe 'user encryption' do describe 'sending and recieving signatures' do it 'should contain the signature in the xml' do - message = Factory.create(:status_message, :person => @user) + message = @user.post :status_message, :message => "hi" xml = message.to_xml.to_s xml.include?(message.creator_signature).should be true end + it 'A message with an invalid signature should be rejected' do - message = Factory.build(:status_message, :person => @person) - message.creator_signature = message.send(:sign ) - message.save - xml = Post.build_xml_for([message]) + @user2 = Factory.create :user + + message = @user2.post :status_message, :message => "hey" + message.creator_signature = "totally valid" + message.save(:validate => false) + + xml = message.to_diaspora_xml message.destroy Post.count.should be 0 - store_objects_from_xml(xml) + @user.receive xml Post.count.should be 0 end @@ -121,9 +130,9 @@ describe 'user encryption' do describe 'comments' do before do @remote_message = Factory.build(:status_message, :person => @person) - @remote_message.creator_signature = @remote_message.send(:sign_with_key,@person.key) + @remote_message.creator_signature = @remote_message.send(:sign_with_key,@person.encryption_key) @remote_message.save - @message = Factory.create(:status_message, :person => @user) + @message = @user.post :status_message, :message => "hi" end it 'should attach the creator signature if the user is commenting' do @user.comment "Yeah, it was great", :on => @remote_message @@ -131,25 +140,25 @@ describe 'user encryption' do end it 'should sign the comment if the user is the post creator' do - message = Factory.create(:status_message, :person => @user) + message = @user.post :status_message, :message => "hi" @user.comment "Yeah, it was great", :on => message message.comments.first.verify_creator_signature.should be true - StatusMessage.first(:message => message.message).comments.first.verify_post_creator_signature.should be true + message.comments.first.verify_post_creator_signature.should be true end it 'should verify a comment made on a remote post by a different friend' do comment = Comment.new(:person => @person2, :text => "balls", :post => @remote_message) - comment.creator_signature = comment.send(:sign_with_key,@person2.key) + comment.creator_signature = comment.send(:sign_with_key,@person2.encryption_key) comment.verify_creator_signature.should be true comment.valid?.should be false - comment.post_creator_signature = comment.send(:sign_with_key,@person.key) + comment.post_creator_signature = comment.send(:sign_with_key,@person.encryption_key) comment.verify_post_creator_signature.should be true comment.valid?.should be true end it 'should reject comments on a remote post with only a creator sig' do comment = Comment.new(:person => @person2, :text => "balls", :post => @remote_message) - comment.creator_signature = comment.send(:sign_with_key,@person2.key) + comment.creator_signature = comment.send(:sign_with_key,@person2.encryption_key) comment.verify_creator_signature.should be true comment.verify_post_creator_signature.should be false comment.save.should be false @@ -157,7 +166,7 @@ describe 'user encryption' do it 'should receive remote comments on a user post with a creator sig' do comment = Comment.new(:person => @person2, :text => "balls", :post => @message) - comment.creator_signature = comment.send(:sign_with_key,@person2.key) + comment.creator_signature = comment.send(:sign_with_key,@person2.encryption_key) comment.save.should be true end diff --git a/test/selenium/post_and_delete_status_message_not_testing_websocket b/test/selenium/post_and_delete_status_message_not_testing_websocket deleted file mode 100644 index bb1cbf7da30103e0b7266c609465af765871c094..0000000000000000000000000000000000000000 --- a/test/selenium/post_and_delete_status_message_not_testing_websocket +++ /dev/null @@ -1,77 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head profile="http://selenium-ide.openqa.org/profiles/test-case"> -<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> -<link rel="selenium.base" href="http://tom.joindiaspora.com/" /> -<title>post_and_delete_status_message_not_testing_websocket</title> -</head> -<body> -<table cellpadding="1" cellspacing="1" border="1"> -<thead> -<tr><td rowspan="1" colspan="3">post_and_delete_status_message_not_testing_websocket</td></tr> -</thead><tbody> -<tr> - <td>open</td> - <td>/login</td> - <td></td> -</tr> -<tr> - <td>type</td> - <td>user_password</td> - <td>evankorth</td> -</tr> -<tr> - <td>clickAndWait</td> - <td>user_submit</td> - <td></td> -</tr> -<tr> - <td>type</td> - <td>status_message_message</td> - <td>THIS IS A RUNNING SELENIUM TEST AAAAAAAAH</td> -</tr> -<tr> - <td>click</td> - <td>status_message_submit</td> - <td></td> -</tr> -<tr> - <td>refreshAndWait</td> - <td></td> - <td></td> -</tr> -<tr> - <td>verifyTextPresent</td> - <td>THIS IS A RUNNING SELENIUM TEST AAAAAAAAH</td> - <td></td> -</tr> -<tr> - <td>click</td> - <td>link=Delete</td> - <td></td> -</tr> -<tr> - <td>assertConfirmation</td> - <td>Are you sure?</td> - <td></td> -</tr> -<tr> - <td>refreshAndWait</td> - <td></td> - <td></td> -</tr> -<tr> - <td>verifyTextNotPresent</td> - <td>THIS IS A RUNNING SELENIUM TEST AAAAAAAAH</td> - <td></td> -</tr> -<tr> - <td>clickAndWait</td> - <td>link=logout</td> - <td></td> -</tr> - -</tbody></table> -</body> -</html>