diff --git a/README b/README index 0d40953..934cb95 100644 --- a/README +++ b/README @@ -4,8 +4,10 @@ Made by Espen Antonsen == Requirements +Tested with Ruby 1.8.6 and Rails 2.3 + Software -- FreeIamge (required for Image Science) +- FreeImage (required for Image_Science) - ExifTool (required for Mini_EfixTool) Ruby Gems diff --git a/app/controllers/albums_controller.rb b/app/controllers/albums_controller.rb index b882f3c..5f47405 100644 --- a/app/controllers/albums_controller.rb +++ b/app/controllers/albums_controller.rb @@ -9,6 +9,15 @@ class AlbumsController < ApplicationController format.xml { render :xml => @albums } end end + + def untouched + @albums = Album.untouched() + respond_to do |format| + format.html + format.json { render :json => @albums } + format.xml { render :xml => @albums } + end + end def show @album = Album.find( params[:id]) diff --git a/app/controllers/collections_controller.rb b/app/controllers/collections_controller.rb new file mode 100644 index 0000000..d5b6ef2 --- /dev/null +++ b/app/controllers/collections_controller.rb @@ -0,0 +1,60 @@ +class CollectionsController < ApplicationController + before_filter :require_user, :only => [:new, :create, :edit, :update, :delete, :destroy] + + def index + @collections = Collection.find(:all) + respond_to do |format| + format.html + format.json { render :json => @collections } + format.xml { render :xml => @collections } + end + end + + def show + @collection = Collection.find( params[:id]) + respond_to do |format| + format.html + format.json { render :json => @collection } + format.xml { render :xml => @collection } + format.pdf { render :pdf => @collection.title } + end + end + + def new + @collection = Collection.new + end + + def create + @collection = Collection.new(params[:collection]) + if @collection.save + flash[:notice] = "Collection created!" + redirect_to @collection + else + render :action => :new + end + end + + def edit + @collection = Collection.find( params[:id]) + end + + def update + @collection = Collection.find( params[:id]) + if @collection.update_attributes(params[:collection]) + flash[:notice] = "collection updated!" + redirect_to @collection + else + render :action => :edit + end + end + + def destroy + @collection = Collection.find( params[:id]) + if @collection.destroy + redirect_to collections_path + else + redirect_to @collection + end + end + +end diff --git a/app/controllers/photos_controller.rb b/app/controllers/photos_controller.rb index abf1e64..787db43 100644 --- a/app/controllers/photos_controller.rb +++ b/app/controllers/photos_controller.rb @@ -45,10 +45,13 @@ class PhotosController < ApplicationController @photo = Photo.new(params[:photo]) if params[:Filedata] @photo.swf_uploaded_data = params[:Filedata] - @photo.save! - - format.html { render :text => "FILEID:" + @photo.public_path_modified("album") } - format.xml { render :nothing => true } + if @photo.save + format.html { render :text => "FILEID:" + @photo.path_modified_public("album") } + format.xml { render :nothing => true } + else + format.html { render :text => "ERRORS:" + @photo.errors.full_messages.join(" "), :status => 500 } + format.xml { render :xml => @photo.errors, :status => 500 } + end else if @photo.save flash[:notice] = 'Created' diff --git a/app/helpers/collections_helper.rb b/app/helpers/collections_helper.rb new file mode 100644 index 0000000..3017985 --- /dev/null +++ b/app/helpers/collections_helper.rb @@ -0,0 +1,2 @@ +module CollectionsHelper +end diff --git a/app/models/album.rb b/app/models/album.rb index dde9546..92cfaeb 100644 --- a/app/models/album.rb +++ b/app/models/album.rb @@ -1,5 +1,7 @@ class Album < ActiveRecord::Base has_many :photos, :dependent => :destroy + has_many :collection_albums + has_many :collections, :through => :collection_albums validates_uniqueness_of :path, :message => "Album already exsists on disc" @@ -9,45 +11,69 @@ class Album < ActiveRecord::Base attr_accessor :tag_list attr_protected :path + - protected + + def self.untouched + self.find(:all, :conditions => "Albums.Id IN ( SELECT DISTINCT Photos.Album_Id FROM Photos WHERE Photos.description IS NULL AND Photos.Id NOT IN ( SELECT Photo_ID FROM Photo_Tags) )" ) + end + def ensure_path self.path = self.title if !self.path end def tag_list + # should maybe cache this to databse? + tags = Array.new self.photos.map{ |photo| if photo.tags.empty? + # photo has no tags => no unversial tags for this album return else photo.tags - end }.each_with_index{ |tag,i| - puts tag.inspect - tag.each { |t| - puts t.title - puts i - if i == 0 - tags.push(t.title) - elsif !tags.include?(t.title) - tags.delete(t.title) - end - } - } - return tags.join(" ") + end + }.each_with_index{ |photo_tags,i| + # returns tag collection for each photo + if i == 0 + tags = photo_tags + else + # combine arrays if they have identical tags. + # Will remove tags that are only tagged to one photo + tags = tags & photo_tags + end + } + return tags.collect{|tag| tag.title }.join(" ") end - + def tag_list=(tags) return if tags == self.tag_list + current_tags = self.tag_list.split(" ") + tags = tags.split(" ") - #TODO HERE! - ts = Array.new - tags.split(" ").each do |tag| - ts.push( Tag.find_or_create_by_title( :title => tag) ) + # find tags that should be removed from this album - thus remove from all photos in album + # i.e. tags listed in self.tag_list but no in parameter tags + #current_tags.map {|tag|tag if !tags.include?(tag) }.compact + (current_tags - tags).each { |tag| + #puts "remove #{tag}" + self.photos.each {|photo| + #TODO in photo model + #photo.tag_remove( tag ) + } + } + + # add universial tags to all photos in album + tags.each do |tag| + #puts "tag photos with #{tag}" if !current_tags.include?( tag ) + self.photos.each { |photo| + #TODO in photo model + #photo.tag_with( tag ) if !current_tags.include?( tag ) # no need to re-tag + } end - self.tags = ts - end + end + protected + private def create_folders diff --git a/app/models/collection.rb b/app/models/collection.rb new file mode 100644 index 0000000..a572f2a --- /dev/null +++ b/app/models/collection.rb @@ -0,0 +1,5 @@ +class Collection < ActiveRecord::Base + has_many :collection_albums + has_many :albums, :through => :collection_albums + +end diff --git a/app/models/collection_album.rb b/app/models/collection_album.rb new file mode 100644 index 0000000..5010b5e --- /dev/null +++ b/app/models/collection_album.rb @@ -0,0 +1,4 @@ +class CollectionAlbum < ActiveRecord::Base + belongs_to :album + belongs_to :collection +end diff --git a/app/models/photo.rb b/app/models/photo.rb index 49ce140..f95f380 100644 --- a/app/models/photo.rb +++ b/app/models/photo.rb @@ -9,7 +9,9 @@ class Photo < ActiveRecord::Base validates_uniqueness_of :path, :message => "Photo already exsists on disc" validates_presence_of :title - before_create :create_thumbnails, :read_exif + before_create :exif_read + after_create :create_thumbnails + before_update :exif_write # should only write if tags are changed as images can be large and thus ExifTool will take a while to write to the file before_destroy :destroy_file attr_accessor :tag_list @@ -20,20 +22,16 @@ class Photo < ActiveRecord::Base self.find(:all, :conditions => "Photos.description IS NULL AND Photos.Id NOT IN ( SELECT Photo_ID FROM Photo_Tags)", :include => :album ) end - def path_original - return APP_CONFIG[:photos_path] + self.path + def extension + return File.extname(self.path_original) end def path_original_public return APP_CONFIG[:photos_path_public] + self.path end - def path_modified(size) - return APP_CONFIG[:thumbs_path] + self.album.path + "/" + self.id.to_s + "_" + size + ".jpg" - end - def path_modified_public(size) - return APP_CONFIG[:thumbs_path_public] + self.album.path + "/" + self.id.to_s + "_" + size + ".jpg" + return APP_CONFIG[:thumbs_path_public] + self.album.path + "/" + self.id.to_s + "_" + size + self.extension end @@ -50,40 +48,6 @@ class Photo < ActiveRecord::Base end - def create_thumbnails - ImageScience.with_image(APP_CONFIG[:photos_path] + self.path) do |img| - #puts " thumbing it..thumbing it.." - ext = File.extname( APP_CONFIG[:photos_path] + self.path ) - - img.thumbnail(85) do |thumb| - thumb.save APP_CONFIG[:thumbs_path] + self.album.path + "/" + self.id.to_s + "_thumb" + ext - end - img.thumbnail(150) do |thumb| - thumb.save APP_CONFIG[:thumbs_path] + self.album.path + "/" + self.id.to_s + "_album" + ext - end - img.thumbnail(800) do |thumb| - thumb.save APP_CONFIG[:thumbs_path] + self.album.path + "/" + self.id.to_s + "_large" + ext - end - end - end - - def read_exif - photo = MiniExiftool.new(self.path_original) - self.longitude = photo.GPSLongitude - self.latitude = photo.GPSLatitude - self.title = photo.DocumentName - self.description = photo.ImageDescription - end - - def write_exif - photo = MiniExiftool.new(self.path_original) - photo.GPSLongitude = self.longitude - photo.GPSLatitude = self.latitude - photo.DocumentName = self.title - photo.ImageDescription = self.description - photo.save - end - def exif_info photo = MiniExiftool.new(self.path_original) photo.tags.sort.each do |tag| @@ -101,10 +65,55 @@ class Photo < ActiveRecord::Base File.open(APP_CONFIG[:photos_path] + self.path, "wb") { |f| f.write(data.read) } end + protected + + def path_original + return APP_CONFIG[:photos_path] + self.path + end + + def path_modified(size) + return APP_CONFIG[:thumbs_path] + self.album.path + "/" + self.id.to_s + "_" + size + self.extension + end + private + + def create_thumbnails + ImageScience.with_image(APP_CONFIG[:photos_path] + self.path) do |img| + #puts " thumbing it..thumbing it.." + ext = File.extname( APP_CONFIG[:photos_path] + self.path ) + + img.thumbnail(85) do |thumb| + thumb.save APP_CONFIG[:thumbs_path] + self.album.path + "/" + self.id.to_s + "_thumb" + ext + end + img.thumbnail(150) do |thumb| + thumb.save APP_CONFIG[:thumbs_path] + self.album.path + "/" + self.id.to_s + "_album" + ext + end + img.thumbnail(800) do |thumb| + thumb.save APP_CONFIG[:thumbs_path] + self.album.path + "/" + self.id.to_s + "_large" + ext + end + end + end + + def exif_read + photo = MiniExiftool.new(self.path_original) + self.longitude = photo.GPSLongitude if self.longitude.nil? + self.latitude = photo.GPSLatitude if self.latitude.nil? + self.title = photo.DocumentName if self.title.nil? + self.description = photo.ImageDescription if self.description.nil? + self.tag_list = photo.Keywords.map { |tag| tag.gsub(" ", "_") }.join(" ") if self.tags.empty? && !photo.Keywords.nil? + end - + def exif_write + photo = MiniExiftool.new(self.path_original) + photo.GPSLongitude = self.longitude + photo.GPSLatitude = self.latitude + photo.DocumentName = self.title + photo.ImageDescription = self.description + photo.Keywords = self.tags + photo.save + end + def destroy_file #puts "DELETE THUMBS OF " + APP_CONFIG[:photos_path] + self.path #File.delete( APP_CONFIG[:photos_path] + self.path ) if File.exists?( APP_CONFIG[:photos_path] + self.path ) diff --git a/app/views/albums/show.html.erb b/app/views/albums/show.html.erb index 2aa6203..a32a88b 100644 --- a/app/views/albums/show.html.erb +++ b/app/views/albums/show.html.erb @@ -1,6 +1,7 @@ <% for photo in @album.photos %> -<%= link_to image_tag( photo.public_path_modified("album") ), photo %> +<%= link_to image_tag( photo.path_modified_public("album") ), photo %> <% end %>
<%= link_to "Update album", edit_album_path(@album) %> +
<%= link_to "Upload photos", upload_album_path(@album) %>
<%= link_to "All albums", albums_path %> \ No newline at end of file diff --git a/app/views/albums/untouched.html.erb b/app/views/albums/untouched.html.erb new file mode 100644 index 0000000..d8c1536 --- /dev/null +++ b/app/views/albums/untouched.html.erb @@ -0,0 +1,2 @@ +

Albums

+<%= render :partial => @albums %> \ No newline at end of file diff --git a/app/views/albums/upload.html.erb b/app/views/albums/upload.html.erb index 7ff0ffd..6f6fbee 100644 --- a/app/views/albums/upload.html.erb +++ b/app/views/albums/upload.html.erb @@ -7,9 +7,8 @@ $(document).ready(function() { uploader:'/javascripts/jquery.uploadify-v1.6.2.mit/uploader.swf', script:'<%= photos_path %>', scriptData: { - '<%= get_session_key %>' : '<%= cookies[get_session_key] %>', - 'method' : '_put', - 'authenticity_token' : '<%= u form_authenticity_token %>', + '<%= get_session_key %>' : '<%= u cookies[get_session_key] %>', + '<%= request_forgery_protection_token %>' : '<%= u form_authenticity_token %>', 'photo[album_id]' : "<%= @album.id %>" }, cancelImg:'/javascripts/jquery.uploadify-v1.6.2.mit/cancel.png', @@ -22,6 +21,8 @@ $(document).ready(function() { image.attr('src', res.substring(7) ) image.fadeIn('slow') } + }, + onError : function (e,queueId,fileObj,errorObj,res) { } }) }) diff --git a/app/views/collections/index.html.erb b/app/views/collections/index.html.erb new file mode 100644 index 0000000..ddbbbd4 --- /dev/null +++ b/app/views/collections/index.html.erb @@ -0,0 +1,5 @@ +

Collections

+<% for collection in @collections %> +<%= link_to collection.title, collection %> +<%= render :partial => collection.albums %> +<% end %> \ No newline at end of file diff --git a/app/views/collections/show.html.erb b/app/views/collections/show.html.erb new file mode 100644 index 0000000..58b4055 --- /dev/null +++ b/app/views/collections/show.html.erb @@ -0,0 +1 @@ +<%= render :partial => @collection.albums %> diff --git a/app/views/photos/_photo.html.erb b/app/views/photos/_photo.html.erb index 22b6283..37ba320 100644 --- a/app/views/photos/_photo.html.erb +++ b/app/views/photos/_photo.html.erb @@ -1,4 +1,4 @@
  • - " title="<%= photo.title %>"> - <%= image_tag photo.public_path_modified("album"), { :id => 'thumb_' + photo.id.to_s } %> + " title="<%= photo.title %>"> + <%= image_tag photo.path_modified_public("album"), { :id => 'thumb_' + photo.id.to_s } %>
  • diff --git a/app/views/photos/edit.html.erb b/app/views/photos/edit.html.erb index 139291c..88286ae 100644 --- a/app/views/photos/edit.html.erb +++ b/app/views/photos/edit.html.erb @@ -6,7 +6,7 @@ <%= f.submit "Update" %> <% end %> -<%= image_tag @photo.public_path_modified("large") %> +<%= image_tag @photo.path_modified_public("large") %>
    <%= link_to("Delete photo", { :action => "destroy", :id => @photo }, :confirm => "Are you sure you want to delete this photo?", :method => :delete) %> diff --git a/app/views/photos/show.html.erb b/app/views/photos/show.html.erb index 58f1eff..797820f 100644 --- a/app/views/photos/show.html.erb +++ b/app/views/photos/show.html.erb @@ -1,8 +1,9 @@

    <%= @photo.title%>

    -<%= image_tag @photo.public_path_modified("large") %> +<%= image_tag @photo.path_modified_public("large") %>
    Tagged with: <%= @photo.tag_list %>

    <%= @photo.description %>


    <%= link_to "Update photo details", edit_photo_path(@photo) %> +
    <%= link_to "Back to #{@photo.album.title}", @photo.album %>
    <%= link_to "All albums", albums_path %> \ No newline at end of file diff --git a/config/environment.rb b/config/environment.rb index a0590f7..6426342 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -19,11 +19,6 @@ Rails::Initializer.run do |config| config.i18n.default_locale = 'no-NB' - config.action_controller.session = { - :session_key => '_gallery_session', - :secret => '060feafeop90cuepaiam324eoimxeaioa2b4220c445486dace48f53fc0a0d4ec4e8de033e1db323628d66b6cx990loibjustintime99' - } - config.action_mailer.smtp_settings = { :address => "smtp.gmail.com", :port => 587, diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb index 044653f..0b224e3 100644 --- a/config/initializers/session_store.rb +++ b/config/initializers/session_store.rb @@ -6,7 +6,7 @@ # no regular words or you'll be exposed to dictionary attacks. ActionController::Base.session = { :key => '_gallery_session', - :secret => 'eb2b1c59315d0f788fd425feab3e10d78a6830dd2bf843a56ac4af333eb290781b06e6605c15d87a1539181b3a928852b76f7459e963b32fdb77e5995af0b1d6' + :secret => '06xfeafeop90cuepaiam324eoimxeaioa2b4220c445486dace48f53fc1a0d4ec4e8de033e1db323628d66b6cx990loibjustintime99' } # Use the database for sessions instead of the cookie-based default, @@ -14,4 +14,5 @@ ActionController::Base.session = { # (create the session table with "rake db:sessions:create") # ActionController::Base.session_store = :active_record_store -ActionController::Dispatcher.middleware.use FlashSessionCookieMiddleware, ActionController::Base.session_options[:key] \ No newline at end of file +ActionController::Dispatcher.middleware.insert_before(ActionController::Session::CookieStore, FlashSessionCookieMiddleware, ActionController::Base.session_options[:key]) +#ActionController::Dispatcher.middleware.use FlashSessionCookieMiddleware, ActionController::Base.session_options[:key] \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 6b10857..8e4825b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -7,13 +7,14 @@ ActionController::Routing::Routes.draw do |map| map.logout "logout", :controller => "user_sessions", :action => "destroy" map.resources :photos, :collection => { :untouched => :get } - map.resources :albums, :has_many => [ :photos ], :collection => { :untouched => :get }, :member => { :upload => :get} + map.resources :albums, :collection => { :untouched => :get }, :member => { :upload => :get}, :has_many => [ :photos ] + map.resources :collections map.resources :tags, :has_many => [ :photos ] map.namespace :admin do |admin| admin.resources :users end - map.root :controller => "albums" + map.root :controller => "collections" end diff --git a/db/migrate/20090602120344_add_location_to_photo.rb b/db/migrate/20090602120344_add_location_to_photo.rb new file mode 100644 index 0000000..cbc42cd --- /dev/null +++ b/db/migrate/20090602120344_add_location_to_photo.rb @@ -0,0 +1,11 @@ +class AddLocationToPhoto < ActiveRecord::Migration + def self.up + add_column :photos, :longitude, :float + add_column :photos, :latitude, :float + end + + def self.down + remove_column :photos, :latitude + remove_column :photos, :longitude + end +end diff --git a/db/migrate/20090602131321_create_collections.rb b/db/migrate/20090602131321_create_collections.rb new file mode 100644 index 0000000..08c7c3e --- /dev/null +++ b/db/migrate/20090602131321_create_collections.rb @@ -0,0 +1,14 @@ +class CreateCollections < ActiveRecord::Migration + def self.up + create_table :collections do |t| + t.string :title, :null => false + t.string :description + + t.timestamps + end + end + + def self.down + drop_table :collections + end +end diff --git a/db/migrate/20090602131547_create_collection_albums.rb b/db/migrate/20090602131547_create_collection_albums.rb new file mode 100644 index 0000000..bced531 --- /dev/null +++ b/db/migrate/20090602131547_create_collection_albums.rb @@ -0,0 +1,14 @@ +class CreateCollectionAlbums < ActiveRecord::Migration + def self.up + create_table :collection_albums do |t| + t.references :collection + t.references :album + + t.timestamps + end + end + + def self.down + drop_table :collection_albums + end +end diff --git a/db/schema.rb b/db/schema.rb index db1a955..026bffb 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -9,7 +9,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20090529155414) do +ActiveRecord::Schema.define(:version => 20090602131547) do create_table "albums", :force => true do |t| t.string "title", :null => false @@ -23,6 +23,20 @@ ActiveRecord::Schema.define(:version => 20090529155414) do t.text "note" end + create_table "collection_albums", :force => true do |t| + t.integer "collection_id" + t.integer "album_id" + t.datetime "created_at" + t.datetime "updated_at" + end + + create_table "collections", :force => true do |t| + t.string "title", :null => false + t.string "description" + t.datetime "created_at" + t.datetime "updated_at" + end + create_table "photo_tags", :force => true do |t| t.integer "tag_id" t.integer "photo_id" @@ -37,6 +51,8 @@ ActiveRecord::Schema.define(:version => 20090529155414) do t.datetime "created_at" t.datetime "updated_at" t.text "path" + t.float "longitude" + t.float "latitude" end create_table "tags", :force => true do |t| diff --git a/public/javascripts/jquery.uploadify-v1.6.2.mit/jquery.uploadify (Source).js b/public/javascripts/jquery.uploadify-v1.6.2.mit/jquery.uploadify (Source).js index f5fdeb7..f6451f7 100755 --- a/public/javascripts/jquery.uploadify-v1.6.2.mit/jquery.uploadify (Source).js +++ b/public/javascripts/jquery.uploadify-v1.6.2.mit/jquery.uploadify (Source).js @@ -98,6 +98,7 @@ if(jQuery)( for (var name in settings.scriptData) { scriptDataString += '&' + name + '=' + settings.scriptData[name]; } + alert( scriptDataString ) data += '&scriptData=' + escape(scriptDataString); } data += '&btnWidth=' + settings.width; diff --git a/test/fixtures/collection_albums.yml b/test/fixtures/collection_albums.yml new file mode 100644 index 0000000..dbcae94 --- /dev/null +++ b/test/fixtures/collection_albums.yml @@ -0,0 +1,9 @@ +# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html + +one: + collection: + album: + +two: + collection: + album: diff --git a/test/fixtures/collections.yml b/test/fixtures/collections.yml new file mode 100644 index 0000000..6f31613 --- /dev/null +++ b/test/fixtures/collections.yml @@ -0,0 +1,7 @@ +# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html + +one: + title: MyString + +two: + title: MyString diff --git a/test/functional/collections_controller_test.rb b/test/functional/collections_controller_test.rb new file mode 100644 index 0000000..b8b207d --- /dev/null +++ b/test/functional/collections_controller_test.rb @@ -0,0 +1,8 @@ +require 'test_helper' + +class CollectionsControllerTest < ActionController::TestCase + # Replace this with your real tests. + test "the truth" do + assert true + end +end diff --git a/test/unit/collection_albums_test.rb b/test/unit/collection_albums_test.rb new file mode 100644 index 0000000..fcab98d --- /dev/null +++ b/test/unit/collection_albums_test.rb @@ -0,0 +1,8 @@ +require 'test_helper' + +class CollectionAlbumsTest < ActiveSupport::TestCase + # Replace this with your real tests. + test "the truth" do + assert true + end +end diff --git a/test/unit/collection_test.rb b/test/unit/collection_test.rb new file mode 100644 index 0000000..e74bac2 --- /dev/null +++ b/test/unit/collection_test.rb @@ -0,0 +1,8 @@ +require 'test_helper' + +class CollectionTest < ActiveSupport::TestCase + # Replace this with your real tests. + test "the truth" do + assert true + end +end diff --git a/test/unit/helpers/collections_helper_test.rb b/test/unit/helpers/collections_helper_test.rb new file mode 100644 index 0000000..16a85d9 --- /dev/null +++ b/test/unit/helpers/collections_helper_test.rb @@ -0,0 +1,4 @@ +require 'test_helper' + +class CollectionsHelperTest < ActionView::TestCase +end