pageflow-panorama 0.3.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +10 -0
  4. data/CHANGELOG.md +32 -34
  5. data/Gemfile +2 -0
  6. data/README.md +1 -0
  7. data/app/jobs/pageflow/panorama/unpack_package_job.rb +35 -9
  8. data/app/models/pageflow/panorama/package.rb +6 -18
  9. data/app/views/pageflow/panorama/page.html.erb +1 -1
  10. data/bin/{rails → rails-cmd} +0 -0
  11. data/bin/rspec +17 -0
  12. data/config/locales/de.yml +8 -3
  13. data/config/locales/en.yml +8 -3
  14. data/db/migrate/20160824115300_add_parent_file_to_packages.rb +8 -0
  15. data/lib/generators/pageflow_panorama/install/install_generator.rb +17 -0
  16. data/lib/pageflow/panorama/archive.rb +16 -0
  17. data/lib/pageflow/panorama/engine.rb +1 -0
  18. data/lib/pageflow/panorama/job_status_attributes.rb +8 -0
  19. data/lib/pageflow/panorama/page_type.rb +2 -1
  20. data/lib/pageflow/panorama/s3_bucket.rb +25 -0
  21. data/lib/pageflow/panorama/unpack_to_s3.rb +18 -23
  22. data/lib/pageflow/panorama/validation/kr_pano.rb +6 -2
  23. data/lib/pageflow/panorama/version.rb +1 -1
  24. data/lib/pageflow-panorama.rb +8 -0
  25. data/pageflow-panorama.gemspec +7 -3
  26. data/spec/fixtures/dir_some.txt.zip +0 -0
  27. data/spec/fixtures/krpano.zip +0 -0
  28. data/spec/fixtures/krpano_with_unprocessable_thumbnail.zip +0 -0
  29. data/spec/fixtures/some.txt.zip +0 -0
  30. data/spec/models/pageflow/panorama/package_spec.rb +91 -0
  31. data/spec/pageflow/panorama/job_status_attributes_spec.rb +49 -0
  32. data/spec/pageflow/panorama/unpack_to_s3_spec.rb +75 -0
  33. data/spec/pageflow/panorama/validation/kr_pano_spec.rb +78 -0
  34. data/spec/spec_helper.rb +17 -0
  35. data/spec/support/config/pageflow_panorama.rb +11 -0
  36. data/spec/support/config/resque.rb +13 -0
  37. data/spec/support/helpers/doubles.rb +27 -0
  38. metadata +83 -13
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: acb5097faba23f51c911ebbcd0f8bfb1858bf776
4
- data.tar.gz: 7507871e96e9c34315fa51730a8d4b6eb6077c0c
3
+ metadata.gz: 996c50b7bf13b13050dee80f7be7afc680b093f8
4
+ data.tar.gz: f57ea9aebabb7bb1abc22bccc3a608fc2c49bc45
5
5
  SHA512:
6
- metadata.gz: c0f19e3b882d533d714f3f113d1fa9a8258eb3ba55d470db41e7e3a5b2576174beb679a79ba340b0019a0320b163a7430d88283d1c8ffd66c25efc783a3aa525
7
- data.tar.gz: c4e2071b78cbbdd11a5b504d558a31e28439f692c0a33430a94f0c19670acdf3496c980032f84915739278ce167b36d91be75b544ca14f943c841ce105d4c7cf
6
+ metadata.gz: bdafd79e06f79f022ded852273a4c98f3406db68765a020ad2ef2f620ddcdf709e26597b410c111ed13d4a0f82d62f8ed281cc0cb3a9cedc3b3cfde46502cda0
7
+ data.tar.gz: 39288597011f17121c9d22998e6d73dc0c9fb77b638e342bd5151a09bd08f1a4ac7b5ed99d85f7de3313094381192e894bbde5bbead801099c46df182b7f9d6d
data/.gitignore CHANGED
@@ -14,6 +14,7 @@ lib/bundler/man
14
14
  pkg
15
15
  rdoc
16
16
  spec/reports
17
+ spec/dummy
17
18
  tmp
18
19
  log
19
20
 
data/.travis.yml ADDED
@@ -0,0 +1,10 @@
1
+ language: ruby
2
+ rvm: 2.1
3
+
4
+ # User container based travis infrastructure which allows caching
5
+ # features for open source projects.
6
+ sudo: false
7
+ cache: bundler
8
+
9
+ script:
10
+ - bin/rspec
data/CHANGELOG.md CHANGED
@@ -1,36 +1,34 @@
1
1
  # CHANGELOG
2
2
 
3
- ### Version 0.3.0
4
-
5
- 2016-09-09
6
-
7
- [Compare changes](https://github.com/codevise/pageflow-panorama/compare/v0.2.0...v0.3.0)
8
-
9
- - Add support for slim player control theme variant
10
- ([#8](https://github.com/codevise/pageflow-panorama/pull/8))
11
-
12
- ### Version 0.2.0
13
-
14
- 2016-06-09
15
-
16
- [Compare changes](https://github.com/codevise/pageflow-panorama/compare/v0.1.0...v0.2.0)
17
-
18
- - Bug fix: Assign content types when unpacking to S3 to ensure display
19
- in all browsers
20
- ([#7](https://github.com/codevise/pageflow-panorama/pull/7))
21
- - Do not declare bin stubs as executables
22
- ([#6](https://github.com/codevise/pageflow-panorama/pull/6))
23
- - Use configurable page type pictograms
24
- ([#5](https://github.com/codevise/pageflow-panorama/pull/5))
25
- - Add pageflow-public-i18n to gemspec
26
- ([#4](https://github.com/codevise/pageflow-panorama/pull/4))
27
- - Extract publicly visible i18n strings from locale
28
- ([#3](https://github.com/codevise/pageflow-panorama/pull/3))
29
- - Add .idea entry to .gitignore
30
- ([#2](https://github.com/codevise/pageflow-panorama/pull/2))
31
-
32
- ### Version 0.1.0
33
-
34
- 2015-06-05
35
-
36
- Initial release.
3
+ ### Version 1.0.0
4
+
5
+ 2017-08-10
6
+
7
+ [Compare changes](https://github.com/codevise/pageflow-panorama/compare/0-3-stable...v1.0.0)
8
+
9
+ - Improve thumbnail processing
10
+ ([#19](https://github.com/codevise/pageflow-panorama/pull/19))
11
+ - Load subdirectories of `config/locales`.
12
+ ([#18](https://github.com/codevise/pageflow-panorama/pull/18))
13
+ - Fix unpacking progress and improve retry
14
+ ([#17](https://github.com/codevise/pageflow-panorama/pull/17))
15
+ - Prevent leaving invalid packages on the file system
16
+ ([#16](https://github.com/codevise/pageflow-panorama/pull/16))
17
+ - Update semmy
18
+ ([#15](https://github.com/codevise/pageflow-panorama/pull/15))
19
+ - Setup travis
20
+ ([#14](https://github.com/codevise/pageflow-panorama/pull/14))
21
+ - Migration added index for video files instead of packages
22
+ ([#13](https://github.com/codevise/pageflow-panorama/pull/13))
23
+ - Allow different thumbnail names
24
+ ([#12](https://github.com/codevise/pageflow-panorama/pull/12))
25
+ - Support pageflow 12
26
+ ([#11](https://github.com/codevise/pageflow-panorama/pull/11))
27
+ - Add css class to background for slim controls shadow
28
+ ([#10](https://github.com/codevise/pageflow-panorama/pull/10))
29
+ - Add nested files support
30
+ ([#9](https://github.com/codevise/pageflow-panorama/pull/9))
31
+
32
+ See
33
+ [0-3-stable branch](https://github.com/codevise/pageflow-panorama/blob/0-3-stable/CHANGELOG.md)
34
+ for previous changes.
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in panorama.gemspec
4
4
  gemspec
5
+
6
+ gem 'state_machine', git: 'https://github.com/codevise/state_machine.git'
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Pageflow Panorama
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/pageflow-panorama.svg)](http://badge.fury.io/rb/pageflow-panorama)
4
+ [![Build Status](https://travis-ci.org/codevise/pageflow-panorama.svg?branch=master)](https://travis-ci.org/codevise/pageflow-panorama)
4
5
 
5
6
  Page type showing 360° panoramas in embedded iframes. Currently
6
7
  supported are panoramas by palmsfilm.com, panogate.com and KRPano via
@@ -1,3 +1,5 @@
1
+ require 'pageflow/panorama/validation'
2
+
1
3
  module Pageflow
2
4
  module Panorama
3
5
  class UnpackPackageJob
@@ -5,24 +7,48 @@ module Pageflow
5
7
 
6
8
  extend StateMachineJob
7
9
 
8
- def self.perform_with_result(package, options)
10
+ def self.perform_with_result(package, _options)
9
11
  JobStatusAttributes.handle(package, stage: :unpacking) do |&progress|
10
- parse(package)
11
-
12
- package.unpacker.upload(&progress)
13
- package.attachment_on_filesystem.destroy
12
+ Archive.for(package) do |archive|
13
+ parse(package, archive)
14
+ unpack_to_s3(package, archive, &progress)
15
+ end
14
16
  end
15
17
 
16
18
  :ok
19
+ rescue Panorama::Validation::Error
20
+ :error
17
21
  end
18
22
 
19
- private
23
+ private_class_method
24
+
25
+ def self.unpack_to_s3(package, archive, &progress)
26
+ bucket = Panorama.bucket_factory.from_attachment(package.attachment_on_s3)
27
+
28
+ UnpackToS3
29
+ .new(archive: archive,
30
+ destination_bucket: bucket,
31
+ destination_base_path: package.unpack_base_path,
32
+ content_type_mapping: Panorama.config.content_type_mapping)
33
+ .upload(&progress)
34
+ end
20
35
 
21
- def self.parse(package)
22
- result = Validation.parse(package.archive)
36
+ def self.parse(package, archive)
37
+ result = Validation.parse(archive)
23
38
 
24
39
  package.index_document = result.index_document
25
- package.thumbnail = package.archive.find_entry(result.thumbnail)
40
+ process_thumbnail(package, archive.find_entry(result.thumbnail))
41
+ end
42
+
43
+ def self.process_thumbnail(package, thumbnail_file)
44
+ package.thumbnail = thumbnail_file
45
+ package.valid?
46
+
47
+ if package.errors.include?(:thumbnail)
48
+ package.thumbnail = nil
49
+ raise(Panorama::Validation::Error
50
+ .new('pageflow.panorama.validation.unprocessable_thumbnail'))
51
+ end
26
52
  end
27
53
  end
28
54
  end
@@ -18,6 +18,10 @@ module Pageflow
18
18
  transition 'unpacking_failed' => 'unpacking'
19
19
  end
20
20
 
21
+ before_transition on: :retry do |package|
22
+ JobStatusAttributes.reset(package, stage: :unpacking)
23
+ end
24
+
21
25
  job UnpackPackageJob do
22
26
  on_enter 'unpacking'
23
27
  result :ok, state: 'unpacked'
@@ -30,34 +34,18 @@ module Pageflow
30
34
  default_style: :thumbnail,
31
35
  styles: Pageflow.config.thumbnail_styles))
32
36
 
33
- # @override
34
- def keep_on_filesystem_after_upload_to_s3?
35
- true
36
- end
37
-
38
37
  def thumbnail_url(*args)
39
38
  thumbnail.url(*args)
40
39
  end
41
40
 
42
- def unpack_base_path
43
- attachment_on_s3.present? ? File.dirname(attachment_on_s3.path(:unpacked)) : nil
44
- end
45
-
46
41
  def index_document_path
47
42
  if attachment_on_s3.present? && index_document
48
43
  File.join(Panorama.config.packages_base_path, unpack_base_path, index_document)
49
44
  end
50
45
  end
51
46
 
52
- def archive
53
- @archive ||= Zip::File.open(attachment_on_filesystem.path)
54
- end
55
-
56
- def unpacker
57
- UnpackToS3.new(archive: archive,
58
- destination_bucket: attachment_on_s3.s3_bucket,
59
- destination_base_path: unpack_base_path,
60
- content_type_mapping: Panorama.config.content_type_mapping)
47
+ def unpack_base_path
48
+ attachment_on_s3.present? ? File.dirname(attachment_on_s3.path(:unpacked)) : nil
61
49
  end
62
50
  end
63
51
  end
@@ -6,7 +6,7 @@
6
6
  </div>
7
7
  </div>
8
8
 
9
- <div class="backgroundArea">
9
+ <div class="backgroundArea page_background page_background-for_page_with_player_controls">
10
10
  <%= background_image_div(configuration, 'fallback_image') %>
11
11
  <%= content_tag(:div, class: 'videoWrapper iframeWrapper', data: {panorama_url: panorama_url(configuration) }) do %>
12
12
  <% end %>
File without changes
data/bin/rspec ADDED
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+ #
4
+ # This file was generated by Bundler.
5
+ #
6
+ # The application 'rspec' is installed as part of a gem, and
7
+ # this file is here to facilitate running it.
8
+ #
9
+
10
+ require "pathname"
11
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
12
+ Pathname.new(__FILE__).realpath)
13
+
14
+ require "rubygems"
15
+ require "bundler/setup"
16
+
17
+ load Gem.bin_path("rspec-core", "rspec")
@@ -5,6 +5,10 @@ de:
5
5
  panorama_package_id: KRPano
6
6
  panorama_source: Panorama Quelle
7
7
  panorama_url: Panorama URL
8
+ models:
9
+ pageflow/panorama/package:
10
+ one: Panorama Package File
11
+ other: Panorama Package Files
8
12
  values:
9
13
  pageflow/page:
10
14
  panorama_source:
@@ -24,12 +28,13 @@ de:
24
28
  panorama:
25
29
  help_entries:
26
30
  page_type:
27
- menu_item: 360° Panorama
28
- text: ! "# 360° Panorama\n\n*Bettet ein interaktives Panorama ein*\n \nZwei verschiedene Quellen werden unterstützt:\n \n### Externes Panorama \n\nVon Drittanbieter erstellte Panoramen, die bereits über eine URL erreichbar sind können direkt eingebunden werden. Wähle dazu \"Externes Panorama\" als Panorama Quelle und füge die URL in das Textfeld ein.\n\n### Hochgeladene Zip Datei\n\nAlternativ können Panoramen mit dem Programm KRPano erstellt und unter \"Dateien verwalten > KRPano\" hochgeladen werden. Wähle danach \"KRPano\" als Panorama Quelle und wähle das gewünschte Panorama aus.\n\nTypische Anwendungsbeispiele: Beeindruckende Orte, Reiseberichte, Darstellung von Architektur"
31
+ menu_item: 360° Bild
32
+ text: "# 360° Bild\n\n*Bettet ein interaktives Panorama ein*\n \nZwei verschiedene Quellen werden unterstützt:\n \n### Externes Panorama \n\nVon Drittanbieter erstellte Panoramen, die bereits über eine URL erreichbar sind können direkt eingebunden werden. Wähle dazu \"Externes Panorama\" als Panorama Quelle und füge die URL in das Textfeld ein.\n\n### Hochgeladene Zip Datei\n\nAlternativ können Panoramen mit dem Programm KRPano erstellt und unter \"Dateien verwalten > KRPano\" hochgeladen werden. Wähle danach \"KRPano\" als Panorama Quelle und wähle das gewünschte Panorama aus.\n\nTypische Anwendungsbeispiele: Beeindruckende Orte, Reiseberichte, Darstellung von Architektur"
29
33
  page_type_category_name: Interaktiv
30
34
  page_type_description: Interaktive Panorama-Ansicht mit KRPano.
31
- page_type_name: 360° Ansicht
35
+ page_type_name: 360° Bild
32
36
  validation:
33
37
  missing_index_document: Index-Dokument nicht gefunden.
34
38
  missing_preview: Vorschau-Bild nicht gefunden.
35
39
  missing_tiles_directory: Tiles-Verzeichnis nicht gefunden.
40
+ unprocessable_thumbnail: Thumbnail konnte nicht verarbeitet werden.
@@ -5,6 +5,10 @@ en:
5
5
  panorama_package_id: KRPano
6
6
  panorama_source: Panorama Source
7
7
  panorama_url: Panorama URL
8
+ models:
9
+ pageflow/panorama/package:
10
+ one: Panorama Package File
11
+ other: Panorama Package Files
8
12
  values:
9
13
  pageflow/page:
10
14
  panorama_source:
@@ -24,12 +28,13 @@ en:
24
28
  panorama:
25
29
  help_entries:
26
30
  page_type:
27
- menu_item: 360° Panorama
28
- text: ! "# 360° Panorama\n\n*Embeds an interactive panorama*\n \n### External Panorama\n\nPanoramas that are already available on the web can be embedded via an URL. Choose \"External Panorama\" as Panorama Source and paste the URL.\n\n### Uploaded Zip File\n\nAlternatively, panoramas can be created using the program KRPano. Visit \"Manage Files > KRPano\" and upload the resulting zip file. Now choose \"KRPano\" as Panorama Source and select an uploaded panorama.\n\nTypical use cases: Impressing places, travel reports, architecture"
31
+ menu_item: 360° Image
32
+ text: "# 360° Image\n\n*Embeds an interactive panorama*\n \n### External Panorama\n\nPanoramas that are already available on the web can be embedded via an URL. Choose \"External Panorama\" as Panorama Source and paste the URL.\n\n### Uploaded Zip File\n\nAlternatively, panoramas can be created using the program KRPano. Visit \"Manage Files > KRPano\" and upload the resulting zip file. Now choose \"KRPano\" as Panorama Source and select an uploaded panorama.\n\nTypical use cases: Impressing places, travel reports, architecture"
29
33
  page_type_category_name: Interactive
30
34
  page_type_description: Interactive panorama using KRPano.
31
- page_type_name: 360° Panorama
35
+ page_type_name: 360° Image
32
36
  validation:
33
37
  missing_index_document: Index document not found.
34
38
  missing_preview: Preview image not found.
35
39
  missing_tiles_directory: Tiles directory not found.
40
+ unprocessable_thumbnail: Unprocessable thumbnail.
@@ -0,0 +1,8 @@
1
+ class AddParentFileToPackages < ActiveRecord::Migration
2
+ def change
3
+ add_column :pageflow_panorama_packages, :parent_file_id, :integer
4
+ add_column :pageflow_panorama_packages, :parent_file_model_type, :string
5
+ add_index :pageflow_panorama_packages, [:parent_file_id, :parent_file_model_type],
6
+ name: 'index_package_files_on_parent_id_and_parent_model_type'
7
+ end
8
+ end
@@ -0,0 +1,17 @@
1
+ module PageflowPanorama
2
+ class InstallGenerator < Rails::Generators::Base
3
+ desc 'Install the Pageflow plugin and the necessary migrations.'
4
+
5
+ def register_plugin
6
+ inject_into_file('config/initializers/pageflow.rb',
7
+ after: "Pageflow.configure do |config|\n") do
8
+
9
+ " config.page_types.register(Pageflow::Panorama.page_type)\n"
10
+ end
11
+ end
12
+
13
+ def install_migrations
14
+ rake "pageflow_panorama:install:migrations"
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ module Pageflow
2
+ module Panorama
3
+ module Archive
4
+ def self.for(package)
5
+ tempfile = Paperclip.io_adapters.for(package.attachment)
6
+
7
+ begin
8
+ yield(Zip::File.open(tempfile.path))
9
+ ensure
10
+ tempfile.close
11
+ tempfile.unlink
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -7,6 +7,7 @@ module Pageflow
7
7
  isolate_namespace Pageflow::Panorama
8
8
 
9
9
  config.autoload_paths << File.join(config.root, 'lib')
10
+ config.i18n.load_path += Dir[config.root.join('config', 'locales', '**', '*.yml').to_s]
10
11
  end
11
12
  end
12
13
  end
@@ -5,6 +5,10 @@ module Pageflow
5
5
  new(record, options[:stage]).call(&block)
6
6
  end
7
7
 
8
+ def self.reset(record, options = {})
9
+ new(record, options[:stage]).reset
10
+ end
11
+
8
12
  def call(&block)
9
13
  update_progress(0)
10
14
 
@@ -15,6 +19,10 @@ module Pageflow
15
19
  end
16
20
  end
17
21
 
22
+ def reset
23
+ update_progress(0)
24
+ end
25
+
18
26
  private
19
27
 
20
28
  def update_progress(percent)
@@ -12,7 +12,8 @@ module Pageflow
12
12
  def file_types
13
13
  [
14
14
  FileType.new(model: Package,
15
- editor_partial: 'pageflow/panorama/editor/packages/package')
15
+ editor_partial: 'pageflow/panorama/editor/packages/package',
16
+ top_level_type: true)
16
17
  ]
17
18
  end
18
19
 
@@ -0,0 +1,25 @@
1
+ module Pageflow
2
+ module Panorama
3
+ class S3Bucket
4
+ attr_reader :bucket
5
+
6
+ def initialize(bucket)
7
+ @bucket = bucket
8
+ end
9
+
10
+ def write(name:, input_stream:, content_length:, content_type:)
11
+ object = bucket.objects[name]
12
+ object.write(input_stream,
13
+ acl: :public_read,
14
+ content_type: content_type,
15
+ content_length: content_length)
16
+ end
17
+
18
+ class Factory
19
+ def from_attachment(attachment)
20
+ S3Bucket.new(attachment.s3_bucket)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -3,21 +3,22 @@ require 'zip'
3
3
  module Pageflow
4
4
  module Panorama
5
5
  class UnpackToS3
6
- attr_reader :archive, :destination_bucket, :destination_base_path,
7
- :content_type_mapping
6
+ attr_reader :archive, :destination_bucket, :destination_base_path, :content_type_mapping
8
7
 
9
- def initialize(options)
10
- @archive = options.fetch(:archive)
11
- @destination_bucket = options.fetch(:destination_bucket)
12
- @destination_base_path = options.fetch(:destination_base_path)
13
- @content_type_mapping = options.fetch(:content_type_mapping, {})
8
+ def initialize(archive:, destination_bucket:, destination_base_path:, content_type_mapping: {})
9
+ @archive = archive
10
+ @destination_bucket = destination_bucket
11
+ @destination_base_path = destination_base_path
12
+ @content_type_mapping = content_type_mapping
14
13
  end
15
14
 
16
- def upload(&progress)
15
+ def upload
17
16
  archive.entries.each_with_index do |entry, index|
18
17
  yield(100.0 * index / archive.entries.size) if block_given?
19
18
  upload_entry(entry)
20
19
  end
20
+
21
+ yield(100) if block_given?
21
22
  end
22
23
 
23
24
  private
@@ -25,17 +26,13 @@ module Pageflow
25
26
  def upload_entry(entry)
26
27
  return unless entry.file?
27
28
  with_retry do
28
- s3_object(entry.name).write(entry.get_input_stream,
29
- acl: :public_read,
30
- content_length: entry.size,
31
- content_type: content_type_for(entry.name))
29
+ destination_bucket.write(name: destination_path(entry.name),
30
+ input_stream: entry.get_input_stream,
31
+ content_length: entry.size,
32
+ content_type: content_type_for(entry.name))
32
33
  end
33
34
  end
34
35
 
35
- def s3_object(file_name)
36
- destination_bucket.objects[destination_path(file_name)]
37
- end
38
-
39
36
  def destination_path(file_name)
40
37
  File.join(destination_base_path, file_name)
41
38
  end
@@ -44,7 +41,7 @@ module Pageflow
44
41
  content_type_mapping[File.extname(file_name).delete('.')]
45
42
  end
46
43
 
47
- def with_retry(&block)
44
+ def with_retry
48
45
  retries = 0
49
46
 
50
47
  begin
@@ -52,12 +49,10 @@ module Pageflow
52
49
  rescue AWS::S3::Errors::SlowDown
53
50
  retries += 1
54
51
 
55
- if retries <= 5
56
- sleep((2 ** retries) * 0.5)
57
- retry
58
- else
59
- raise
60
- end
52
+ raise if retries > 5
53
+
54
+ sleep((2**retries) * 0.5)
55
+ retry
61
56
  end
62
57
  end
63
58
  end
@@ -20,14 +20,18 @@ module Pageflow
20
20
  end
21
21
 
22
22
  def find_thumbnail!
23
- find_file!('**/mobile_f.jpg', :missing_preview)
23
+ find_file!('**/*_f.jpg', :missing_preview)
24
24
  end
25
25
 
26
26
  def find_file!(glob, message_i18n_key)
27
- entries.map(&:name).find do |name|
27
+ ignore_dot_files(entries.map(&:name)).find do |name|
28
28
  File.fnmatch(glob, name)
29
29
  end || raise(Error.new("pageflow.panorama.validation.#{message_i18n_key}"))
30
30
  end
31
+
32
+ def ignore_dot_files(names)
33
+ names.reject { |name| File.basename(name).start_with?('.') }
34
+ end
31
35
  end
32
36
  end
33
37
  end
@@ -1,5 +1,5 @@
1
1
  module Pageflow
2
2
  module Panorama
3
- VERSION = '0.3.0'.freeze
3
+ VERSION = '1.0.0'.freeze
4
4
  end
5
5
  end
@@ -13,5 +13,13 @@ module Pageflow
13
13
  def self.page_type
14
14
  Panorama::PageType.new
15
15
  end
16
+
17
+ def self.bucket_factory
18
+ @bucket_factory ||= Panorama::S3Bucket::Factory.new
19
+ end
20
+
21
+ def self.bucket_factory=(bucket_factory)
22
+ @bucket_factory = bucket_factory
23
+ end
16
24
  end
17
25
  end
@@ -16,16 +16,20 @@ Gem::Specification.new do |spec|
16
16
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
17
  spec.require_paths = ["lib"]
18
18
 
19
- spec.add_runtime_dependency "pageflow", "~> 0.11"
19
+ spec.required_ruby_version = '~> 2.1'
20
+
21
+ spec.add_runtime_dependency "pageflow", [">= 0.11", "< 13"]
22
+ spec.add_runtime_dependency 'state_machine_job', ['>= 0.2', '< 2']
20
23
  spec.add_runtime_dependency "rubyzip", "~> 1.1"
21
24
  spec.add_runtime_dependency 'pageflow-public-i18n', '~> 1.0'
22
25
 
26
+ spec.add_development_dependency 'pageflow-support', '>= 0.11.4'
23
27
  spec.add_development_dependency "bundler"
24
28
  spec.add_development_dependency "rake"
25
- spec.add_development_dependency "rspec-rails", "~> 2.0"
29
+ spec.add_development_dependency "rspec-rails", "~> 3.0"
26
30
  spec.add_development_dependency 'factory_girl_rails'
27
31
  spec.add_development_dependency "mysql2"
28
32
 
29
33
  # Semantic versioning rake tasks
30
- spec.add_development_dependency 'semmy', '~> 0.3.0'
34
+ spec.add_development_dependency 'semmy', '~> 1.0'
31
35
  end
Binary file
Binary file
Binary file
@@ -0,0 +1,91 @@
1
+ require 'spec_helper'
2
+
3
+ module Pageflow
4
+ module Panorama
5
+ describe Package do
6
+ describe '#process', inline_resque: true do
7
+ it 'parses thumbnail and index document' do
8
+ zip_file = File.open(Engine.root.join('spec', 'fixtures', 'krpano.zip'))
9
+ package = Package.create!(attachment: zip_file)
10
+
11
+ package.publish!
12
+ package.reload
13
+
14
+ expect(package.thumbnail).to be_present
15
+ expect(package.index_document).to be_present
16
+ end
17
+
18
+ it 'uploads files to bucket' do
19
+ zip_file = File.open(Engine.root.join('spec', 'fixtures', 'krpano.zip'))
20
+ package = Package.create!(attachment: zip_file)
21
+ bucket = Doubles.bucket
22
+
23
+ Panorama.bucket_factory = TestBucketFactory.new(bucket)
24
+
25
+ package.publish!
26
+ package.reload
27
+
28
+ expect(bucket).to have_received(:write)
29
+ .with(hash_including(name: package.index_document_path))
30
+ end
31
+
32
+ it 'updates unpacking_progress' do
33
+ zip_file = File.open(Engine.root.join('spec', 'fixtures', 'krpano.zip'))
34
+ package = Package.create!(attachment: zip_file)
35
+
36
+ package.publish!
37
+ package.reload
38
+
39
+ expect(package.unpacking_progress).to eq(100)
40
+ end
41
+
42
+ it 'transitions to failed state if validation fails' do
43
+ zip_file = File.open(Engine.root.join('spec', 'fixtures', 'some.txt.zip'))
44
+ package = Package.create!(attachment: zip_file)
45
+
46
+ package.publish!
47
+ package.reload
48
+
49
+ expect(package.state).to eq('unpacking_failed')
50
+ end
51
+
52
+ it 'transitions to failed state if thumbnail is unprocessable' do
53
+ zip_file = File.open(Engine.root.join('spec',
54
+ 'fixtures',
55
+ 'krpano_with_unprocessable_thumbnail.zip'))
56
+ package = Package.create!(attachment: zip_file)
57
+
58
+ package.publish!
59
+ package.reload
60
+
61
+ expect(package.state).to eq('unpacking_failed')
62
+ end
63
+
64
+ class TestBucketFactory
65
+ def initialize(bucket)
66
+ @bucket = bucket
67
+ end
68
+
69
+ def from_attachment(_attachment)
70
+ @bucket
71
+ end
72
+ end
73
+ end
74
+
75
+ describe '#retry', stub_resque: true do
76
+ it 'resets unpacking progress and error_message' do
77
+ zip_file = File.open(Engine.root.join('spec', 'fixtures', 'krpano.zip'))
78
+ package = Package.create!(attachment: zip_file,
79
+ state: 'unpacking_failed',
80
+ unpacking_progress: 50,
81
+ unpacking_error_message: 'failed')
82
+
83
+ package.retry!
84
+
85
+ expect(package.unpacking_progress).to eq(0)
86
+ expect(package.unpacking_error_message).to eq(nil)
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ module Pageflow
4
+ module Panorama
5
+ describe JobStatusAttributes do
6
+ describe '#handle' do
7
+ it 'updates phase progress attribute when passed block is called' do
8
+ record = Package.create!(unpacking_progress: 0)
9
+
10
+ JobStatusAttributes.handle(record, stage: :unpacking) do |&progress|
11
+ progress.call(20)
12
+ end
13
+
14
+ expect(record.reload.unpacking_progress).to eq(20)
15
+ end
16
+
17
+ it 'sets phase error message if error with message_i18n_key is raised' do
18
+ record = Package.create!(unpacking_progress: 0)
19
+ error_with_message_i18n_key = Class.new(RuntimeError) do
20
+ def message_i18n_key
21
+ :i18n_key
22
+ end
23
+ end
24
+
25
+ begin
26
+ JobStatusAttributes.handle(record, stage: :unpacking) do |&progress|
27
+ raise(error_with_message_i18n_key.new)
28
+ end
29
+ rescue error_with_message_i18n_key
30
+ end
31
+
32
+ expect(record.unpacking_error_message).to eq('i18n_key')
33
+ end
34
+ end
35
+
36
+ describe '#reset' do
37
+ it 'resets progress and error message attrbute' do
38
+ record = Package.create!(unpacking_progress: 20,
39
+ unpacking_error_message: 'fail')
40
+
41
+ JobStatusAttributes.reset(record, stage: :unpacking)
42
+
43
+ expect(record.unpacking_progress).to eq(0)
44
+ expect(record.unpacking_error_message).to eq(nil)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+
3
+ module Pageflow
4
+ module Panorama
5
+ describe UnpackToS3 do
6
+ describe '#upload' do
7
+ it 'writes files from zip to bucket' do
8
+ archive = Zip::File.open(Engine.root.join('spec', 'fixtures', 'some.txt.zip'))
9
+ bucket = Doubles.bucket
10
+ unpack_to_s3 = UnpackToS3.new(archive: archive,
11
+ destination_bucket: bucket,
12
+ destination_base_path: 'base')
13
+
14
+ unpack_to_s3.upload
15
+
16
+ expect(bucket).to have_received(:write).with(hash_including(name: 'base/some.txt'))
17
+ end
18
+
19
+ it 'reports progress' do
20
+ archive = Zip::File.open(Engine.root.join('spec', 'fixtures', 'some.txt.zip'))
21
+ bucket = Doubles.bucket
22
+ unpack_to_s3 = UnpackToS3.new(archive: archive,
23
+ destination_bucket: bucket,
24
+ destination_base_path: 'base')
25
+
26
+ expect { |probe|
27
+ unpack_to_s3.upload(&probe)
28
+ }.to yielding_successive_args(0, 100)
29
+ end
30
+
31
+ it 'determines content type via mapping' do
32
+ archive = Zip::File.open(Engine.root.join('spec', 'fixtures', 'some.txt.zip'))
33
+ bucket = Doubles.bucket
34
+ unpack_to_s3 = UnpackToS3.new(archive: archive,
35
+ destination_bucket: bucket,
36
+ destination_base_path: 'base',
37
+ content_type_mapping: {
38
+ 'txt' => 'text/plain'
39
+ })
40
+
41
+ unpack_to_s3.upload
42
+
43
+ expect(bucket).to have_received(:write).with(hash_including(content_type: 'text/plain'))
44
+ end
45
+
46
+ it 'retries when write fails' do
47
+ archive = Zip::File.open(Engine.root.join('spec', 'fixtures', 'some.txt.zip'))
48
+ bucket = Doubles.bucket_raising_once(AWS::S3::Errors::SlowDown)
49
+ unpack_to_s3 = UnpackToS3.new(archive: archive,
50
+ destination_bucket: bucket,
51
+ destination_base_path: 'base')
52
+
53
+ allow(unpack_to_s3).to receive(:sleep)
54
+ unpack_to_s3.upload
55
+
56
+ expect(bucket).to have_received(:write).twice
57
+ end
58
+
59
+ it 're-raises exception when write fails too often' do
60
+ archive = Zip::File.open(Engine.root.join('spec', 'fixtures', 'some.txt.zip'))
61
+ bucket = Doubles.bucket_raising(AWS::S3::Errors::SlowDown)
62
+ unpack_to_s3 = UnpackToS3.new(archive: archive,
63
+ destination_bucket: bucket,
64
+ destination_base_path: 'base')
65
+
66
+ allow(unpack_to_s3).to receive(:sleep)
67
+
68
+ expect {
69
+ unpack_to_s3.upload
70
+ }.to raise_error(AWS::S3::Errors::SlowDown)
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,78 @@
1
+ require 'spec_helper'
2
+
3
+ module Pageflow
4
+ module Panorama
5
+ module Validation
6
+ describe KrPano do
7
+ def entry_double(name, type, size)
8
+ double(name: name, size: size).tap do |entry|
9
+ allow(entry).to receive(:file?).and_return(type == :file)
10
+ end
11
+ end
12
+
13
+ let(:entries_of_valid_archive) do
14
+ [
15
+ entry_double('pano.tiles/', :directory, 0),
16
+ entry_double('pano.tiles/mobile_f.jpg', :file, 40),
17
+ entry_double('pano.html', :file, 60),
18
+ entry_double('pano.xml', :file, 60)
19
+ ]
20
+ end
21
+
22
+ let(:entries_of_archive_without_tiles) do
23
+ [
24
+ entry_double('pano.html', :file, 60),
25
+ entry_double('pano.xml', :file, 60)
26
+ ]
27
+ end
28
+
29
+ let(:entries_silly_macosx_archive) do
30
+ [
31
+ entry_double('__MACOSX/', :directory, 0),
32
+ entry_double('__MACOSX/pano.tiles/', :directory, 0),
33
+ entry_double('__MACOSX/pano.tiles/._mobile_f.jpg', :file, 40),
34
+ entry_double('pano.tiles/', :directory, 0),
35
+ entry_double('pano.tiles/mobile_f.jpg', :file, 40),
36
+ entry_double('pano.html', :file, 60),
37
+ entry_double('pano.xml', :file, 60)
38
+ ]
39
+ end
40
+
41
+ describe '#parse' do
42
+ it 'finds thumbnail' do
43
+ validation = KrPano.new(entries_of_valid_archive)
44
+
45
+ result = validation.parse
46
+
47
+ expect(result.thumbnail).to eq('pano.tiles/mobile_f.jpg')
48
+ end
49
+
50
+ it 'ignores thumbnails starting with dot' do
51
+ validation = KrPano.new(entries_silly_macosx_archive)
52
+
53
+ result = validation.parse
54
+
55
+ expect(result.thumbnail).to eq('pano.tiles/mobile_f.jpg')
56
+ end
57
+
58
+ it 'finds index document' do
59
+ validation = KrPano.new(entries_of_valid_archive)
60
+
61
+ result = validation.parse
62
+
63
+ expect(result.index_document).to eq('pano.html')
64
+ end
65
+
66
+ it 'raises validation error if tiles dir is missing' do
67
+ entries = entries_of_archive_without_tiles
68
+ validation = KrPano.new(entries)
69
+
70
+ expect {
71
+ validation.parse
72
+ }.to raise_error(Error)
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,17 @@
1
+ ENV['RAILS_ENV'] ||= 'test'
2
+ ENV['PAGEFLOW_PLUGIN_ENGINE'] = 'pageflow_panorama'
3
+
4
+ require 'pageflow/support'
5
+ Pageflow::Dummy.setup
6
+
7
+ require 'rspec/rails'
8
+
9
+ engine_root = File.join(File.dirname(__FILE__), '..')
10
+ Dir[File.join(engine_root, 'spec/support/**/*.rb')].each { |file| require(file) }
11
+
12
+ RSpec.configure do |config|
13
+ config.infer_spec_type_from_file_location!
14
+ config.use_transactional_fixtures = true
15
+ config.infer_base_class_for_anonymous_controllers = false
16
+ config.order = "random"
17
+ end
@@ -0,0 +1,11 @@
1
+ RSpec.configure do |config|
2
+ config.before(:each) do
3
+ Pageflow::Panorama.bucket_factory = DoubleBucketFactory.new
4
+ end
5
+
6
+ class DoubleBucketFactory
7
+ def from_attachment(_attachment)
8
+ Doubles.bucket
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,13 @@
1
+ RSpec.configure do |config|
2
+ config.before(:each, inline_resque: true) do
3
+ Resque.inline = true
4
+ end
5
+
6
+ config.after(:each, inline_resque: true) do
7
+ Resque.inline = false
8
+ end
9
+
10
+ config.before(:each, stub_resque: true) do
11
+ allow(Resque).to receive(:enqueue)
12
+ end
13
+ end
@@ -0,0 +1,27 @@
1
+ module Doubles
2
+ extend RSpec::Mocks::ExampleMethods
3
+ extend self
4
+
5
+ def bucket
6
+ instance_double(Pageflow::Panorama::S3Bucket).as_null_object
7
+ end
8
+
9
+ def bucket_raising_once(error)
10
+ bucket.tap do |bucket|
11
+ called = false
12
+
13
+ allow(bucket).to receive(:write) do
14
+ unless called
15
+ called = true
16
+ raise error
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ def bucket_raising(error)
23
+ bucket.tap do |bucket|
24
+ allow(bucket).to receive(:write).and_raise(error)
25
+ end
26
+ end
27
+ end
metadata CHANGED
@@ -1,29 +1,55 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pageflow-panorama
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Codevise Solutions
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-09-09 00:00:00.000000000 Z
11
+ date: 2017-08-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pageflow
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0.11'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '13'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - "~>"
27
+ - - ">="
25
28
  - !ruby/object:Gem::Version
26
29
  version: '0.11'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '13'
33
+ - !ruby/object:Gem::Dependency
34
+ name: state_machine_job
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ version: '0.2'
40
+ - - "<"
41
+ - !ruby/object:Gem::Version
42
+ version: '2'
43
+ type: :runtime
44
+ prerelease: false
45
+ version_requirements: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0.2'
50
+ - - "<"
51
+ - !ruby/object:Gem::Version
52
+ version: '2'
27
53
  - !ruby/object:Gem::Dependency
28
54
  name: rubyzip
29
55
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +78,20 @@ dependencies:
52
78
  - - "~>"
53
79
  - !ruby/object:Gem::Version
54
80
  version: '1.0'
81
+ - !ruby/object:Gem::Dependency
82
+ name: pageflow-support
83
+ requirement: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: 0.11.4
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: 0.11.4
55
95
  - !ruby/object:Gem::Dependency
56
96
  name: bundler
57
97
  requirement: !ruby/object:Gem::Requirement
@@ -86,14 +126,14 @@ dependencies:
86
126
  requirements:
87
127
  - - "~>"
88
128
  - !ruby/object:Gem::Version
89
- version: '2.0'
129
+ version: '3.0'
90
130
  type: :development
91
131
  prerelease: false
92
132
  version_requirements: !ruby/object:Gem::Requirement
93
133
  requirements:
94
134
  - - "~>"
95
135
  - !ruby/object:Gem::Version
96
- version: '2.0'
136
+ version: '3.0'
97
137
  - !ruby/object:Gem::Dependency
98
138
  name: factory_girl_rails
99
139
  requirement: !ruby/object:Gem::Requirement
@@ -128,14 +168,14 @@ dependencies:
128
168
  requirements:
129
169
  - - "~>"
130
170
  - !ruby/object:Gem::Version
131
- version: 0.3.0
171
+ version: '1.0'
132
172
  type: :development
133
173
  prerelease: false
134
174
  version_requirements: !ruby/object:Gem::Requirement
135
175
  requirements:
136
176
  - - "~>"
137
177
  - !ruby/object:Gem::Version
138
- version: 0.3.0
178
+ version: '1.0'
139
179
  description:
140
180
  email:
141
181
  - info@codevise.de
@@ -144,6 +184,7 @@ extensions: []
144
184
  extra_rdoc_files: []
145
185
  files:
146
186
  - ".gitignore"
187
+ - ".travis.yml"
147
188
  - CHANGELOG.md
148
189
  - Gemfile
149
190
  - README.md
@@ -170,17 +211,22 @@ files:
170
211
  - app/views/pageflow/panorama/editor/packages/_package.json.jbuilder
171
212
  - app/views/pageflow/panorama/page.html.erb
172
213
  - app/views/pageflow/panorama/page_type.json.jbuilder
173
- - bin/rails
214
+ - bin/rails-cmd
215
+ - bin/rspec
174
216
  - config/locales/de.yml
175
217
  - config/locales/en.yml
176
218
  - config/pageflow-panorama-proxies.conf.example
177
219
  - config/pageflow_panorama.rb.example
178
220
  - db/migrate/20140915133249_create_packages.rb
221
+ - db/migrate/20160824115300_add_parent_file_to_packages.rb
222
+ - lib/generators/pageflow_panorama/install/install_generator.rb
179
223
  - lib/pageflow-panorama.rb
224
+ - lib/pageflow/panorama/archive.rb
180
225
  - lib/pageflow/panorama/configuration.rb
181
226
  - lib/pageflow/panorama/engine.rb
182
227
  - lib/pageflow/panorama/job_status_attributes.rb
183
228
  - lib/pageflow/panorama/page_type.rb
229
+ - lib/pageflow/panorama/s3_bucket.rb
184
230
  - lib/pageflow/panorama/unpack_to_s3.rb
185
231
  - lib/pageflow/panorama/validation.rb
186
232
  - lib/pageflow/panorama/validation/error.rb
@@ -189,6 +235,18 @@ files:
189
235
  - lib/pageflow/panorama/version.rb
190
236
  - lib/pageflow/panorama/zip_entry_paperclip_io_adapter.rb
191
237
  - pageflow-panorama.gemspec
238
+ - spec/fixtures/dir_some.txt.zip
239
+ - spec/fixtures/krpano.zip
240
+ - spec/fixtures/krpano_with_unprocessable_thumbnail.zip
241
+ - spec/fixtures/some.txt.zip
242
+ - spec/models/pageflow/panorama/package_spec.rb
243
+ - spec/pageflow/panorama/job_status_attributes_spec.rb
244
+ - spec/pageflow/panorama/unpack_to_s3_spec.rb
245
+ - spec/pageflow/panorama/validation/kr_pano_spec.rb
246
+ - spec/spec_helper.rb
247
+ - spec/support/config/pageflow_panorama.rb
248
+ - spec/support/config/resque.rb
249
+ - spec/support/helpers/doubles.rb
192
250
  homepage: https://github.com/codevise/pageflow-panorama
193
251
  licenses:
194
252
  - MIT
@@ -199,9 +257,9 @@ require_paths:
199
257
  - lib
200
258
  required_ruby_version: !ruby/object:Gem::Requirement
201
259
  requirements:
202
- - - ">="
260
+ - - "~>"
203
261
  - !ruby/object:Gem::Version
204
- version: '0'
262
+ version: '2.1'
205
263
  required_rubygems_version: !ruby/object:Gem::Requirement
206
264
  requirements:
207
265
  - - ">="
@@ -209,8 +267,20 @@ required_rubygems_version: !ruby/object:Gem::Requirement
209
267
  version: '0'
210
268
  requirements: []
211
269
  rubyforge_project:
212
- rubygems_version: 2.5.1
270
+ rubygems_version: 2.6.8
213
271
  signing_key:
214
272
  specification_version: 4
215
273
  summary: Pagetype for iframe embedded 360° panoramas
216
- test_files: []
274
+ test_files:
275
+ - spec/fixtures/dir_some.txt.zip
276
+ - spec/fixtures/krpano.zip
277
+ - spec/fixtures/krpano_with_unprocessable_thumbnail.zip
278
+ - spec/fixtures/some.txt.zip
279
+ - spec/models/pageflow/panorama/package_spec.rb
280
+ - spec/pageflow/panorama/job_status_attributes_spec.rb
281
+ - spec/pageflow/panorama/unpack_to_s3_spec.rb
282
+ - spec/pageflow/panorama/validation/kr_pano_spec.rb
283
+ - spec/spec_helper.rb
284
+ - spec/support/config/pageflow_panorama.rb
285
+ - spec/support/config/resque.rb
286
+ - spec/support/helpers/doubles.rb