diff --git a/.gitignore b/.gitignore index 35f258b..549ebcd 100644 --- a/.gitignore +++ b/.gitignore @@ -14,5 +14,7 @@ # Ignore all logfiles and tempfiles. /log/*.log /tmp -/public/screenshots +/public/screenshots/ /public/assets/ +/public/system/ +/public/screenshots diff --git a/Gemfile b/Gemfile index 8e22019..9246d1a 100644 --- a/Gemfile +++ b/Gemfile @@ -94,3 +94,6 @@ gem 'pg_search' # Use SLIM as our templating language gem 'slim-rails' + +# Attachment/image handling +gem "paperclip", "~> 4.2" diff --git a/Gemfile.lock b/Gemfile.lock index 408b7c7..c056c89 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -48,6 +48,10 @@ GEM columnize (~> 0.8) debugger-linecache (~> 1.2) slop (~> 3.6) + climate_control (0.0.3) + activesupport (>= 3.0) + cocaine (0.5.5) + climate_control (>= 0.0.3, < 1.0) coderay (1.1.0) coffee-rails (4.1.0) coffee-script (>= 2.2.0) @@ -93,6 +97,11 @@ GEM multi_json (1.10.1) nokogiri (1.6.5) mini_portile (~> 0.6.0) + paperclip (4.2.1) + activemodel (>= 3.0.0) + activesupport (>= 3.0.0) + cocaine (~> 0.5.3) + mime-types pg (0.17.1) pg_search (0.7.8) activerecord (>= 3.1) @@ -189,6 +198,7 @@ DEPENDENCIES jbuilder (~> 2.0) jquery-rails jquery.fileupload-rails + paperclip (~> 4.2) pg pg_search rails (= 4.2.0) diff --git a/README.Developer b/README.Developer index b4a9e1e..1d21366 100644 --- a/README.Developer +++ b/README.Developer @@ -32,3 +32,6 @@ coalesce("packages"."long_description"::text, ''))) ); Used: https://github.com/semaperepelitsa/jquery.fileupload-rails Which is a gem for: https://github.com/blueimp/jQuery-File-Upload + +Paperclip for attachment/screenshot file handlind within ActiveRecord +https://github.com/thoughtbot/paperclip \ No newline at end of file diff --git a/app/assets/stylesheets/my.scss b/app/assets/stylesheets/my.scss index 493124d..58f8395 100644 --- a/app/assets/stylesheets/my.scss +++ b/app/assets/stylesheets/my.scss @@ -296,3 +296,17 @@ a.black text-shadow: 0 0 2px black; } } + +/* Properties of a screenshot - shown in details view */ +.property-title +{ + font-weight: bolder; + font-size: 120%; + color: #808080; +} + +.property +{ + margin-left: 2em; + margin-bottom: 0.5em; +} \ No newline at end of file diff --git a/app/controllers/packages_controller.rb b/app/controllers/packages_controller.rb index fe62262..6095bf7 100644 --- a/app/controllers/packages_controller.rb +++ b/app/controllers/packages_controller.rb @@ -58,9 +58,26 @@ class PackagesController < ApplicationController # TODO raise "name not given" unless params[:name] @package = Package.find_by(name: params[:name]) + @new_screenshot = @package.screenshots.new end def upload_image - "uploaded" + #render text: params[:image].to_json + #render text: params.to_json + @package = Package.find_by(name: params[:name]) + @new_screenshot = @package.screenshots.create(image: params[:image]) + @new_screenshot.save + #raise + #@package.save + #new_screenshot.image = params[:image] + + #render text: "File has been uploaded successfully" + redirect_to upload_package_by_name_path end + + private + + #def user_params + # params.require(:screenshot).permit(:image) + #end end diff --git a/app/models/screenshot.rb b/app/models/screenshot.rb index 5a51727..fdf0890 100644 --- a/app/models/screenshot.rb +++ b/app/models/screenshot.rb @@ -5,22 +5,11 @@ class Screenshot < ActiveRecord::Base order('uploaddatetime DESC') } - def image_url(size) - "#{Rails.configuration.images_path_prefix}/#{self.package.name[0]}/#{self.package.name}/#{self.id}_#{size}.png" - end - - # Get the URL leading to a screenshot of this package - def url(size) - if self.approved - # TODO: Make the path configurable - basepath = "/screenshots/" - else - # TODO: Choose a path that makes unapproved screenshots unavailable - basepath = "/screenshots/unapproved/" - end - - File.join(basepath, self.package.name[0], self.package.name, "#{self.id}_#{size}.png") - end + has_attached_file :image, + styles: { :large => "800x600>", :thumb => "160x120>" }, + default_url: "/images/dummy/no-screenshots-upload-one.svg" + #path: :rails_root/public/system/:class/:attachment/:id_partition/:style/:filename + validates_attachment_content_type :image, :content_type => /\Aimage\/png\Z/ # Return caption for full-screen screenshots. # Takes the description of a screenshot if available. @@ -33,27 +22,24 @@ class Screenshot < ActiveRecord::Base end end - def image_file(size) - # Screenshot files are at e.g. - # .../public/screenshots/f/firefox/5871654_large.png - Rails.configuration.images_path.join(self.package.name[0], self.package.name, "#{self.id}_#{size}.png") + def uploader + # TODO: Implement the ownership of images + "Anonymous" end - # Delete all image files related to this screenshot - def delete_all_images - Rails.configuration.image_sizes.each do |size,dimensions| - image_file = self.image_file(size) - Rails.logger.info "(before_destroy) Deleting screenshot image '#{image_file}' from disk" - if File.exist?(image_file) - File.delete(image_file) - else - Rails.logger.error "(before_destroy) File '#{image_file}' not found - could not delete it" - end + def status + text = '' + # Completes the sentence: "This image…" + if self.approved + text <<'is public' + else + text <<'has to be moderated before being publicly visible' end - end - # Callback to delete image files from disk when a screenshot record gets destroyed - before_destroy do |screenshot| - screenshot.delete_all_images + if self.markedfordelete + text <<' (and was requested to be removed)' + end + + text end end diff --git a/app/views/packages/_grid_thumbnail.slim b/app/views/packages/_grid_thumbnail.slim index 77bfbd1..92c331f 100644 --- a/app/views/packages/_grid_thumbnail.slim +++ b/app/views/packages/_grid_thumbnail.slim @@ -2,7 +2,9 @@ a.black href=package_path(name: pkg.name) div.grid-thumbnail - if pkg.screenshots.any? - img src=pkg.screenshots[0].url('small') + // TODO: smarter search for the beste screenshot instead of taking the first one + - screenshot = pkg.screenshots.first + = image_tag(screenshot.image.url(:thumb, timestamp: false), alt: screenshot.caption) - else img.screenshot src="/images/dummy/no-screenshots-upload-one.svg" div diff --git a/app/views/packages/details.slim b/app/views/packages/details.slim index 7d90a36..cb0bf09 100644 --- a/app/views/packages/details.slim +++ b/app/views/packages/details.slim @@ -13,12 +13,25 @@ p.subtitle = @package.description ul.small-block-grid-1.medium-block-grid-2.large-block-grid-2 - - for screenshot in @package.screenshots + - @package.screenshots.each do |screenshot| li - a.black.fancybox href=screenshot.url('large') rel='fancybox-thumb' title=screenshot.caption - img src=screenshot.url('large') + a.black.fancybox href=screenshot.image.url(:large, timestamp: false) rel='fancybox-thumb' title=screenshot.caption + = image_tag(screenshot.image.url(:large, timestamp: false), alt: screenshot.caption) .imgcaption =screenshot.caption + // Upload image + li + //a.button.radius.expand href=upload_package_by_name_path(name: @package.name) Upload a new screenshot + //= form_for @package, :url => upload_image_path, :html => { :multipart => true } do |form| + //= form.file_field :image + + = form_for :screenshot, url: upload_image_path, html: { multipart: true } do |f| + = f.label :image, 'Upload new screenshot' + = f.file_field :image, id: 'fileupload', multiple: true + = f.submit 'Save' + + //- raise + // TODO: Enable comments in a later version // = partial '/package/comments' @@ -35,7 +48,19 @@ ' The goal of Icedove is to produce a cross platform standalone mail ' application using the XUL user interface language. - a.button.radius.expand href=upload_package_by_name_path(name: @package.name) Upload a new screenshot + //a.button.radius.expand href=upload_package_by_name_path(name: @package.name) Upload a new screenshot + +javascript: + $(function () { + $('#fileupload').fileupload({ + dataType: 'json', + done: function (e, data) { + $.each(data.result.files, function (index, file) { + $('
').text(file.name).appendTo(document.body); + }); + } + }); + }); // TODO: Enable comment form //javascript: diff --git a/app/views/packages/index-list.slim b/app/views/packages/index-list.slim index 329331f..1a4e4c8 100644 --- a/app/views/packages/index-list.slim +++ b/app/views/packages/index-list.slim @@ -20,8 +20,10 @@ =pkg.name ' > - if pkg.screenshots.any? - a.black.fancybox title=pkg.screenshots.first.caption rel=pkg.id href=pkg.screenshots.first.url('large') - img.screenshot src=pkg.screenshots.first.url('large') + // TODO: smarter search for the beste screenshot instead of taking the first one + - screenshot = pkg.screenshots.first + a.black.fancybox title=screenshot.caption rel=pkg.id href=screenshot.image.url(:large, timestamp: false) + = image_tag(screenshot.image.url(:large, timestamp: false), alt: screenshot.caption) - if pkg.screenshots.length > 1 a.black href=package_path(name: pkg.name) .text-center More screenshots… diff --git a/app/views/packages/upload.slim b/app/views/packages/upload.slim index ab30f37..eb6f4f3 100644 --- a/app/views/packages/upload.slim +++ b/app/views/packages/upload.slim @@ -4,11 +4,19 @@ p.subtitle = @package.description .row.packagepage - .small-8.columns + .small-12.medium-7.large-8.columns // First row contains the upload form .row .small-6.columns - input id="fileupload" type="file" name="files[]" data-url=upload_image_path(name: @package.name) multiple=true + //input id="fileupload" type="file" name="files[]" data-url=upload_image_path(name: @package.name) multiple=true + + //= form_for @new_screenshot, :url => upload_image_path, :html => { :multipart => true } do |form| + // = form.file_field :image + // = form.submit 'Save' + = form_tag(upload_image_path, multipart: true) + = file_field_tag('image') + = submit_tag + a.button.radius.expand href=upload_package_by_name_path(name: @package.name) ' Click or drag a PNG screenshot file here .small-6.columns @@ -17,8 +25,19 @@ .row img src=screenshot.url('large') + - puts @package.screenshots + - @package.screenshots.each do |screenshot| + .listview + a.black.fancybox href=screenshot.image.url(:large, timestamp: false) rel='fancybox-thumb' title=screenshot.caption + = image_tag(screenshot.image.url(:large, timestamp: false), alt: screenshot.caption) +// .imgcaption +// => screenshot.caption +// - if screenshot.uploader +// | (Uploaded by +// =< screenshot.uploader +// | ) - .small-4.columns + .small-12.medium-5.large-4.columns .bigpanel p Thanks for uploading more screenshots. Please note: ul diff --git a/app/views/welcome/home.slim b/app/views/welcome/home.slim index 15097c1..a08f186 100644 --- a/app/views/welcome/home.slim +++ b/app/views/welcome/home.slim @@ -31,7 +31,7 @@ div.row // TODO: load actual newest upload and cache it // TODO: link to the package page a.black href=package_path(@newest_uploaded_package.name) - img src=@newest_uploaded_package.screenshots[0].image_url('large') + img src=@newest_uploaded_package.screenshots.first.image.url(:large, timestamp: false) p strong =@newest_uploaded_package.name @@ -43,7 +43,7 @@ div.row // TODO: load actual most popular package and highest-rated screenshot and cache it // TODO: link to the package page a.black href=package_path(@most_popular_package.name) - img src=@most_popular_package.screenshots[0].image_url('large') + img src=@most_popular_package.screenshots.first.image.url(:large, timestamp: false) p strong =@most_popular_package.name diff --git a/config/environments/development.rb b/config/environments/development.rb index 0e89cdb..b39331a 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -27,6 +27,10 @@ Debshots::Application.configure do # number of complex assets. config.assets.debug = true + # ActiveRecord errors propagate normally (forward deprecation to Rails 5) + config.active_record.raise_in_transactional_callbacks = true + + # URL prefix leading to the static images that should get delivered by the web server config.images_path_prefix = '/screenshots' diff --git a/db/migrate/20150103182901_add_attachment_image_to_screenshots.rb b/db/migrate/20150103182901_add_attachment_image_to_screenshots.rb new file mode 100644 index 0000000..4dba184 --- /dev/null +++ b/db/migrate/20150103182901_add_attachment_image_to_screenshots.rb @@ -0,0 +1,11 @@ +class AddAttachmentImageToScreenshots < ActiveRecord::Migration + def self.up + change_table :screenshots do |t| + t.attachment :image + end + end + + def self.down + remove_attachment :screenshots, :image + end +end diff --git a/db/migrate/20150103194230_add_fingerprint_column_to_screenshot.rb b/db/migrate/20150103194230_add_fingerprint_column_to_screenshot.rb new file mode 100644 index 0000000..b3e2963 --- /dev/null +++ b/db/migrate/20150103194230_add_fingerprint_column_to_screenshot.rb @@ -0,0 +1,9 @@ +class AddFingerprintColumnToScreenshot < ActiveRecord::Migration + def self.up + add_column :screenshots, :image_fingerprint, :string + end + + def self.down + remove_column :screenshots, :image_fingerprint + end +end diff --git a/db/schema.rb b/db/schema.rb index cf2c660..489ff6c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20141229173351) do +ActiveRecord::Schema.define(version: 20150103194230) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -41,16 +41,21 @@ ActiveRecord::Schema.define(version: 20141229173351) do create_table "screenshots", force: :cascade do |t| t.integer "package_id" - t.string "version", limit: 50 + t.string "version", limit: 50 t.datetime "uploaddatetime" - t.string "uploaderhash", limit: 72 - t.string "uploaderip", limit: 15 + t.string "uploaderhash", limit: 72 + t.string "uploaderip", limit: 15 t.boolean "approved" t.boolean "markedfordelete" - t.string "delete_reason", limit: 100 - t.string "description", limit: 40 + t.string "delete_reason", limit: 100 + t.string "description", limit: 40 t.datetime "created_at" t.datetime "updated_at" + t.string "image_file_name" + t.string "image_content_type" + t.integer "image_file_size" + t.datetime "image_updated_at" + t.string "image_fingerprint" end add_index "screenshots", ["id", "approved"], name: "id_approved", using: :btree diff --git a/lib/tasks/import_debian.rake b/lib/tasks/import_debian.rake index d8eb298..dfd6c63 100644 --- a/lib/tasks/import_debian.rake +++ b/lib/tasks/import_debian.rake @@ -47,7 +47,7 @@ task :import_debian => :environment do Rails.logger.level = Logger::INFO #Rails.logger.level = Logger::DEBUG - puts "Importing Debian package information" + Rails.logger.info "Importing Debian package information" repositories.each do |repository| Rails.logger.info "Fetching Release file for repository: #{repository[:url]} with components: #{repository[:components]}" diff --git a/lib/tasks/screenshots_to_paperclip.rake b/lib/tasks/screenshots_to_paperclip.rake new file mode 100644 index 0000000..1daba4b --- /dev/null +++ b/lib/tasks/screenshots_to_paperclip.rake @@ -0,0 +1,32 @@ +desc "Convert images from the original screenshots directory tree to paperclip-styled images" + +task :screenshots_to_paperclip => :environment do + Rails.logger = Logger.new(STDOUT) + Rails.logger.level = Logger::INFO + #Rails.logger.level = Logger::DEBUG + + base_path = Rails.root.join('public') + + Rails.logger.info "Iterating over screenshots" + Screenshot.all.each do |screenshot| + path = File.join(base_path, screenshot.image_url(:large)) + Rails.logger.info "- #{screenshot.id} (package: #{screenshot.package.name}) (path: #{path})" + + # Check that the file actually exists + unless File.file? path + Rails.logger.error "Screenshots not found at #{path}. Skipping." + next + end + + # Has the screenshot been migrated already? + if screenshot.image.exists? + Rails.logger.error "Screenshot already migrated. Skipping." + next + end + + File.open(path, 'rb') do |image_file| + screenshot.image = image_file + screenshot.save + end + end +end