pageflow-panorama 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +19 -0
  3. data/CHANGELOG.md +11 -0
  4. data/Gemfile +10 -0
  5. data/README.md +76 -0
  6. data/Rakefile +17 -0
  7. data/app/assets/images/pageflow/ov-panorama.png +0 -0
  8. data/app/assets/images/pageflow/panorama_pictogram.png +0 -0
  9. data/app/assets/images/pageflow/panorama_pictogram_small.png +0 -0
  10. data/app/assets/images/pageflow/panorama_sprite.png +0 -0
  11. data/app/assets/javascripts/pageflow/panorama.js +5 -0
  12. data/app/assets/javascripts/pageflow/panorama/editor.js +8 -0
  13. data/app/assets/javascripts/pageflow/panorama/editor/config.js +9 -0
  14. data/app/assets/javascripts/pageflow/panorama/editor/models/configuration_mixin.js +16 -0
  15. data/app/assets/javascripts/pageflow/panorama/editor/models/package.js +11 -0
  16. data/app/assets/javascripts/pageflow/panorama/editor/views/configuration_editor.js +49 -0
  17. data/app/assets/javascripts/pageflow/panorama/page_type.js +88 -0
  18. data/app/assets/stylesheets/pageflow/panorama.css.scss +13 -0
  19. data/app/assets/stylesheets/pageflow/panorama/editor.css.scss +3 -0
  20. data/app/helpers/pageflow/panorama/packages_helper.rb +14 -0
  21. data/app/jobs/pageflow/panorama/unpack_package_job.rb +29 -0
  22. data/app/models/pageflow/panorama/package.rb +63 -0
  23. data/app/views/pageflow/panorama/editor/packages/_package.json.jbuilder +1 -0
  24. data/app/views/pageflow/panorama/page.html.erb +48 -0
  25. data/app/views/pageflow/panorama/page_type.json.jbuilder +1 -0
  26. data/bin/rails +8 -0
  27. data/config/locales/de.yml +39 -0
  28. data/config/locales/en.yml +57 -0
  29. data/config/pageflow-panorama-proxies.conf.example +17 -0
  30. data/config/pageflow_panorama.rb.example +16 -0
  31. data/db/migrate/20140915133249_create_packages.rb +12 -0
  32. data/lib/pageflow-panorama.rb +17 -0
  33. data/lib/pageflow/panorama/configuration.rb +12 -0
  34. data/lib/pageflow/panorama/engine.rb +11 -0
  35. data/lib/pageflow/panorama/job_status_attributes.rb +40 -0
  36. data/lib/pageflow/panorama/page_type.rb +31 -0
  37. data/lib/pageflow/panorama/unpack_to_s3.rb +58 -0
  38. data/lib/pageflow/panorama/validation.rb +9 -0
  39. data/lib/pageflow/panorama/validation/error.rb +14 -0
  40. data/lib/pageflow/panorama/validation/kr_pano.rb +34 -0
  41. data/lib/pageflow/panorama/validation/result.rb +8 -0
  42. data/lib/pageflow/panorama/zip_entry_paperclip_io_adapter.rb +37 -0
  43. data/pageflow-panorama.gemspec +25 -0
  44. metadata +185 -0
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ MWUwNzdiMWE2ZDkyNTRiYTU0MThhNTAzODU3Y2ZlOWM2MDFlYTIyOA==
5
+ data.tar.gz: !binary |-
6
+ OGNlMjA3YzRhYWQzNzA4OGYyMWIwZDhlMmU2ZmQ3MzMzMGYzOTEwOA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ YzVhNzMxZWM1MGEyY2YxZDM3YWI5YTg0Y2IxOGM0YTI1MGY1NTJhYzNmZGM4
10
+ NTMyMjgxNDY2NGU2OTMxZGVkMTI5OGQxM2Y3MTUxNzBiNDg1ZWM5NTZkZWZk
11
+ ODczYzc3NmFjMTcxYjY1MTJjZWMzZmMyNmNlMDQzMzcyOTA4MjA=
12
+ data.tar.gz: !binary |-
13
+ YTM2ZDFhMTYyZWZlOGU4NDVjZmM0MWI3NzRkNDJkMTAzYTMzODkzZWRmNjcz
14
+ ZmQ3NjFiNTIxMWZjNWQ1ZGMzODkyMWExZDk4NzNhYjU0NWRhYzkyYmQxNWIx
15
+ NzliZjUyYjJhOWVlOThlYmQyYWIwMzY0OTk2ZDdhYzg1Y2JjYzA=
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ *.sqlite3
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ tmp
17
+ log
18
+
19
+ .localeapp
data/CHANGELOG.md ADDED
@@ -0,0 +1,11 @@
1
+ # CHANGELOG
2
+
3
+ ### Changes on `master`
4
+
5
+ [Compare changes](https://github.com/codevise/pageflow-panorama/compare/v0.1.0...master)
6
+
7
+ ### Version 0.1.0
8
+
9
+ 2015-06-05
10
+
11
+ Initial release.
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in panorama.gemspec
4
+ gemspec
5
+
6
+ gem 'state_machine', git: 'https://github.com/tf/state_machine.git', branch: 'master'
7
+ gem 'activeadmin', git: 'https://github.com/codevise/active_admin.git', branch: 'rails4'
8
+ gem 'ransack'
9
+ gem 'inherited_resources', '1.4.1'
10
+ gem 'formtastic', '2.3.0'
data/README.md ADDED
@@ -0,0 +1,76 @@
1
+ # Pageflow Panorama
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/pageflow-panorama.svg)](http://badge.fury.io/rb/pageflow-panorama)
4
+
5
+ Page type showing 360° panoramas in embedded iframes. Currently
6
+ supported are panoramas by palmsfilm.com, panogate.com and KRPano via
7
+ upload in the editor.
8
+
9
+ ## Installation
10
+
11
+ Add pageflow-panorama to your application's Gemfile:
12
+
13
+ # Gemfile
14
+ gem 'pageflow-panorama'
15
+
16
+ and run `bundle install`.
17
+
18
+ Register the page type:
19
+
20
+ # config/initializers/pageflow.rb
21
+ Pageflow.configure do |config|
22
+ config.register_page_type(Pageflow::Panorama.page_type)
23
+ end
24
+
25
+ Include javascripts and stylesheets:
26
+
27
+ # app/assets/javascripts/pageflow/application.js
28
+ //= require pageflow/panorama
29
+
30
+ # app/assets/javascripts/pageflow/editor.js
31
+ //= require pageflow/panorama/editor
32
+
33
+ # app/assets/stylesheets/pageflow/application.css.scss
34
+ @import "pageflow/panorama";
35
+
36
+ Install and run migrations:
37
+
38
+ $ rake pageflow_panorama:install:migrations
39
+ $ rake db:migrate
40
+
41
+ ### Create Proxies for the Panorama Providers:
42
+
43
+ To circumvent the same-origin policy, a proxy from the domain that
44
+ serves pageflow to the domain of the panorma-providers has to be
45
+ configured.
46
+
47
+ Example for Nginx:
48
+ Copy `config/pageflow-panorama-proxies.conf.example` to your Nginx config
49
+ directory, for example `/etc/nginx/pageflow-panorama-proxies.conf`
50
+ and include it in you pageflow config file:
51
+
52
+ include /etc/nginx/pageflow-panorama-proxies.conf
53
+
54
+ ### Configure the Supported Panorama Providers
55
+
56
+ If you support both palmfilms and panogate just copy
57
+ `config/pageflow_panorama.rb.example` to `config/initializers/pageflow_panorama.rb`
58
+ in your app. This sets the `base_path` to correspond with the proxy configuration above.
59
+
60
+ Restart the application server.
61
+
62
+ ## Troubleshooting
63
+
64
+ If you run into problems while installing the page type, please also
65
+ refer to the
66
+ [Troubleshooting](https://github.com/codevise/pageflow/wiki/Troubleshooting)
67
+ wiki page in the
68
+ [Pageflow repository](https://github.com/codevise/pageflow). If that
69
+ doesn't help, consider
70
+ [filing an issue](https://github.com/codevise/pageflow-panorama/issues).
71
+
72
+ ## Contributing Locales
73
+
74
+ Edit the translations directly on the
75
+ [pageflow-panorama](http://www.localeapp.com/projects/public?search=tf/pageflow-panorama)
76
+ locale project.
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'Pageflow Panorama'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,5 @@
1
+ //= require_self
2
+
3
+ //= require ./panorama/page_type
4
+
5
+ pageflow.panorama = pageflow.panorama || {};
@@ -0,0 +1,8 @@
1
+ //= require_self
2
+
3
+ //= require_tree ./editor/models
4
+ //= require_tree ./editor/views
5
+
6
+ //= require ./editor/config
7
+
8
+ pageflow.panorama = pageflow.panorama || {};
@@ -0,0 +1,9 @@
1
+ pageflow.editor.fileTypes.register('pageflow_panorama_packages', {
2
+ model: pageflow.panorama.Package,
3
+ matchUpload: function(upload) {
4
+ return upload.type.match(/^application\/zip/) ||
5
+ upload.name.match(/\.zip$/);
6
+ }
7
+ });
8
+
9
+ pageflow.editor.registerPageConfigurationMixin(pageflow.panorama.configurationMixin);
@@ -0,0 +1,16 @@
1
+ pageflow.panorama.configurationMixin = {
2
+ getPanoramaUrl: function() {
3
+ if (this.get('panorama_source') === 'url') {
4
+ return this.get('panorama_url');
5
+ }
6
+ else {
7
+ var panoramaPackage = this.getReference('panorama_package_id', 'pageflow_panorama_packages');
8
+
9
+ if (panoramaPackage && panoramaPackage.isReady()) {
10
+ return panoramaPackage.get('index_document_path');
11
+ }
12
+
13
+ return '';
14
+ }
15
+ }
16
+ };
@@ -0,0 +1,11 @@
1
+ pageflow.panorama.Package = pageflow.HostedFile.extend({
2
+ processingStages: [
3
+ {
4
+ name: 'unpacking',
5
+ activeStates: ['unpacking'],
6
+ failedStates: ['unpacking_failed']
7
+ }
8
+ ],
9
+
10
+ readyState: 'unpacked'
11
+ });
@@ -0,0 +1,49 @@
1
+ pageflow.ConfigurationEditorView.register('panorama', {
2
+ configure: function() {
3
+ var providers = this.options.pageType.providers;
4
+
5
+ this.tab('general', function() {
6
+ this.group('general');
7
+
8
+ this.input('additional_title', pageflow.TextInputView);
9
+ this.input('additional_description', pageflow.TextAreaInputView, {size: 'short'});
10
+ });
11
+
12
+ this.tab('files', function() {
13
+ if (providers.length) {
14
+ this.input('panorama_source', pageflow.SelectInputView, {
15
+ values: ['package', 'url'],
16
+ ensureValueDefined: true
17
+ });
18
+ this.input('panorama_url', pageflow.ProxyUrlInputView, {
19
+ required: true,
20
+ proxies: providers,
21
+ displayPropertyName: 'display_panorama_url',
22
+ visibleBinding: 'panorama_source',
23
+ visibleBindingValue: 'url'
24
+ });
25
+ this.input('panorama_package_id', pageflow.FileInputView, {
26
+ collection: 'pageflow_panorama_packages',
27
+ imagePositioning: false,
28
+ visibleBinding: 'panorama_source',
29
+ visibleBindingValue: 'package'
30
+ });
31
+ }
32
+ else {
33
+ this.input('panorama_package_id', pageflow.FileInputView, {
34
+ collection: 'pageflow_panorama_packages',
35
+ imagePositioning: false
36
+ });
37
+ }
38
+
39
+ this.input('thumbnail_image_id', pageflow.FileInputView, {
40
+ collection: pageflow.imageFiles,
41
+ imagePositioning: false
42
+ });
43
+ });
44
+
45
+ this.tab('options', function() {
46
+ this.group('options');
47
+ });
48
+ }
49
+ });
@@ -0,0 +1,88 @@
1
+ pageflow.pageType.register('panorama', _.extend({
2
+ enhance: function(pageElement, configuration) {
3
+ pageElement.addClass('hide_content_with_text');
4
+
5
+ pageElement.find('.play_button').on('mousedown touchstart', function() {
6
+ pageflow.hideText.activate();
7
+ });
8
+
9
+ pageElement.find('.close_button').on('click', function(e) {
10
+ pageflow.hideText.deactivate();
11
+ e.stopPropagation();
12
+ });
13
+ },
14
+
15
+ prepare: function(pageElement, configuration) {
16
+ this._ensureIframe(pageElement, configuration);
17
+ },
18
+
19
+ preload: function(pageElement, configuration) {
20
+ return pageflow.preload.backgroundImage(pageElement.find('.background_image'));
21
+ },
22
+
23
+ activating: function(pageElement, configuration) {
24
+ this._ensureIframe(pageElement, configuration);
25
+ },
26
+
27
+ activated: function(pageElement, configuration) {},
28
+
29
+ deactivating: function(pageElement, configuration) {},
30
+
31
+ deactivated: function(pageElement, configuration) {},
32
+
33
+ update: function(pageElement, configuration) {
34
+ pageElement.find('h2 .tagline').text(configuration.get('tagline') || '');
35
+ pageElement.find('h2 .title').text(configuration.get('title') || '');
36
+ pageElement.find('h2 .subtitle').text(configuration.get('subtitle') || '');
37
+ pageElement.find('p').html(configuration.get('text') || '');
38
+
39
+ this.updateInfoBox(pageElement, configuration);
40
+ this.updateCommonPageCssClasses(pageElement, configuration);
41
+
42
+ pageElement.find('.shadow').css({
43
+ opacity: configuration.get('gradient_opacity') / 100
44
+ });
45
+
46
+ if (this.panoramaUrl !== configuration.getPanoramaUrl()) {
47
+ this.panoramaUrl = configuration.getPanoramaUrl();
48
+
49
+ this._ensureIframeCreated(pageElement);
50
+ this.iframe.attr('src', this.panoramaUrl);
51
+ }
52
+ },
53
+
54
+ _ensureIframe: function(pageElement, configuration) {
55
+ if (!this.iframe) {
56
+ var panoramaUrl = pageElement.find('.iframeWrapper').data('panoramaUrl');
57
+
58
+ if (panoramaUrl) {
59
+ this._ensureIframeCreated(pageElement);
60
+ this.iframe.attr('src', panoramaUrl);
61
+
62
+ $(this.iframe).load(function() {
63
+ $(this).contents().find('body').keydown(function(event) {
64
+ if(event.keyCode == 27) {
65
+ pageflow.hideText.deactivate();
66
+ }
67
+ });
68
+ });
69
+ }
70
+ }
71
+ },
72
+
73
+ _ensureIframeCreated: function(pageElement) {
74
+ if (!this.iframe) {
75
+ this.iframe = $('<iframe style="width: 100%; height: 100%; position: absolute; top: 0; left: 0;" name="°" scrolling="no" frameborder="0" align="aus" marginheight="0" marginwidth="0" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true"></iframe>');
76
+ pageElement.find('.iframeWrapper').prepend(this.iframe);
77
+ }
78
+ },
79
+
80
+ embeddedEditorViews: function() {
81
+ return {
82
+ '.background_image': {
83
+ view: pageflow.BackgroundImageEmbeddedView,
84
+ options: {propertyName: 'fallback_image_id'}
85
+ }
86
+ };
87
+ }
88
+ }, pageflow.commonPageCssClasses, pageflow.infoBox));
@@ -0,0 +1,13 @@
1
+ @include pageflow-page-type(panorama);
2
+
3
+ .js .panorama_page {
4
+ overflow: hidden;
5
+
6
+ .contentText {
7
+ margin-bottom: 200px;
8
+
9
+ @include phone {
10
+ margin-bottom: 100px;
11
+ }
12
+ }
13
+ }
@@ -0,0 +1,3 @@
1
+ @include pageflow-hosted-file-stage('unpacking') {
2
+ @include archive-icon;
3
+ }
@@ -0,0 +1,14 @@
1
+ module Pageflow
2
+ module Panorama
3
+ module PackagesHelper
4
+ def panorama_url(configuration)
5
+ if configuration['panorama_source'] == 'url'
6
+ configuration['panorama_url']
7
+ else
8
+ package = Package.find_by_id(configuration['panorama_package_id'])
9
+ package ? package.index_document_path : nil
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,29 @@
1
+ module Pageflow
2
+ module Panorama
3
+ class UnpackPackageJob
4
+ @queue = :slow
5
+
6
+ extend StateMachineJob
7
+
8
+ def self.perform_with_result(package, options)
9
+ JobStatusAttributes.handle(package, stage: :unpacking) do |&progress|
10
+ parse(package)
11
+
12
+ package.unpacker.upload(&progress)
13
+ package.attachment_on_filesystem.destroy
14
+ end
15
+
16
+ :ok
17
+ end
18
+
19
+ private
20
+
21
+ def self.parse(package)
22
+ result = Validation.parse(package.archive)
23
+
24
+ package.index_document = result.index_document
25
+ package.thumbnail = package.archive.find_entry(result.thumbnail)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,63 @@
1
+ require 'zip'
2
+
3
+ module Pageflow
4
+ module Panorama
5
+ class Package < ActiveRecord::Base
6
+ include HostedFile
7
+
8
+ processing_state_machine do
9
+ state 'unpacking'
10
+ state 'unpacked'
11
+ state 'unpacking_failed'
12
+
13
+ event :process do
14
+ transition any => 'unpacking'
15
+ end
16
+
17
+ event :retry do
18
+ transition 'unpacking_failed' => 'unpacking'
19
+ end
20
+
21
+ job UnpackPackageJob do
22
+ on_enter 'unpacking'
23
+ result :ok, state: 'unpacked'
24
+ result :error, state: 'unpacking_failed'
25
+ end
26
+ end
27
+
28
+ has_attached_file(:thumbnail, Pageflow.config.paperclip_s3_default_options
29
+ .merge(default_url: ':pageflow_placeholder',
30
+ default_style: :thumbnail,
31
+ styles: Pageflow.config.thumbnail_styles))
32
+
33
+ # @override
34
+ def keep_on_filesystem_after_upload_to_s3?
35
+ true
36
+ end
37
+
38
+ def thumbnail_url(*args)
39
+ thumbnail.url(*args)
40
+ end
41
+
42
+ def unpack_base_path
43
+ attachment_on_s3.present? ? File.dirname(attachment_on_s3.path(:unpacked)) : nil
44
+ end
45
+
46
+ def index_document_path
47
+ if attachment_on_s3.present? && index_document
48
+ File.join(Panorama.config.packages_base_path, unpack_base_path, index_document)
49
+ end
50
+ end
51
+
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
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1 @@
1
+ json.(package, :unpacking_progress, :unpacking_error_message, :index_document_path)
@@ -0,0 +1,48 @@
1
+ <div class="blackLayer"></div>
2
+ <div class="content_and_background panorama_page">
3
+ <div class="close_button text_hidden_only" tabindex="4" title="<%= t('.close_title') %>">
4
+ <div class="label">
5
+ <%= t('.close') %>
6
+ </div>
7
+ </div>
8
+
9
+ <div class="backgroundArea">
10
+ <%= background_image_div(configuration, 'fallback_image') %>
11
+ <%= content_tag(:div, class: 'videoWrapper iframeWrapper', data: {panorama_url: panorama_url(configuration) }) do %>
12
+ <% end %>
13
+ <%= shadow_div :opacity => configuration['gradient_opacity'] %>
14
+ </div>
15
+
16
+ <div class="content">
17
+ <div class="controls">
18
+ <span class="hint"><%= t('.start') %></span>
19
+ <%= info_box(configuration) %>
20
+ <div class="vjs-control-bar view-control">
21
+ <div class="play_button vjs-controls vjs-default-skin vjs-player">
22
+ <a class="vjs-play-control vjs-play vjs-control" tabindex="4" title="<%= t('.start') %>"><span></span></a>
23
+ </div>
24
+ <div class="control_bar_text">
25
+ <%= t('.start') %>
26
+ </div>
27
+ </div>
28
+ </div>
29
+
30
+ <div class="scroller">
31
+ <div>
32
+ <div class="contentWrapper">
33
+ <div class="page_header">
34
+ <h2>
35
+ <span class="tagline"><%= configuration['tagline'] %></span>
36
+ <span class="title"><%= configuration['title'] %></span>
37
+ <span class="subtitle"><%= configuration['subtitle'] %></span>
38
+ <%= background_image_tag(configuration['fallback_image_id'], {"class" => "print_image"}) %>
39
+ </h2>
40
+ </div>
41
+ <div class="contentText">
42
+ <p><%= raw configuration['text'] %></p>
43
+ </div>
44
+ </div>
45
+ </div>
46
+ </div>
47
+ </div>
48
+ </div>
@@ -0,0 +1 @@
1
+ json.providers Pageflow::Panorama.config.providers
data/bin/rails ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 4 gems installed from the root of your application.
3
+
4
+ ENGINE_ROOT = File.expand_path('../..', __FILE__)
5
+ ENGINE_PATH = File.expand_path('../../lib/pageflow/panorama/engine', __FILE__)
6
+
7
+ require 'rails/all'
8
+ require 'rails/engine/commands'
@@ -0,0 +1,39 @@
1
+ de:
2
+ activerecord:
3
+ attributes:
4
+ pageflow/page:
5
+ panorama_package_id: KRPano
6
+ panorama_source: Panorama Quelle
7
+ panorama_url: Panorama URL
8
+ values:
9
+ pageflow/page:
10
+ panorama_source:
11
+ package: KRPano
12
+ url: Externes Panorama
13
+ pageflow:
14
+ editor:
15
+ files:
16
+ stages:
17
+ unpacking:
18
+ active: Wird entpackt.
19
+ failed: Fehler beim entpacken.
20
+ finished: Erfolgreich entpackt.
21
+ pending: Noch nicht entpackt.
22
+ tabs:
23
+ pageflow_panorama_packages: KRPanos
24
+ panorama:
25
+ help_entries:
26
+ page_type:
27
+ menu_item: 360° Panorama
28
+ text: ! "# 360° Panorama\n\nBettet ein interaktives Panorama ein. Zwei 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
+ page:
30
+ close: Schließen
31
+ close_title: 360°-Ansicht verlassen und Text einblenden
32
+ start: 360°-Ansicht starten
33
+ page_type_category_name: Interaktiv
34
+ page_type_description: Interaktive Panorama-Ansicht mit KRPano.
35
+ page_type_name: 360° Ansicht
36
+ validation:
37
+ missing_index_document: Index-Dokument nicht gefunden.
38
+ missing_preview: Vorschau-Bild nicht gefunden.
39
+ missing_tiles_directory: Tiles-Verzeichnis nicht gefunden.
@@ -0,0 +1,57 @@
1
+ en:
2
+ activerecord:
3
+ attributes:
4
+ pageflow/page:
5
+ panorama_package_id: KRPano
6
+ panorama_source: Panorama Source
7
+ panorama_url: Panorama URL
8
+ values:
9
+ pageflow/page:
10
+ panorama_source:
11
+ package: KRPano
12
+ url: External Panorama
13
+ pageflow:
14
+ editor:
15
+ files:
16
+ stages:
17
+ unpacking:
18
+ active: Unpacking.
19
+ failed: Error while unpacking.
20
+ finished: Successfully unpacked.
21
+ pending: Not yet unpacked.
22
+ tabs:
23
+ pageflow_panorama_packages: KRPanos
24
+ panorama:
25
+ help_entries:
26
+ page_type:
27
+ menu_item: 360° Panorama
28
+ text: ! '# 360° Panorama
29
+
30
+
31
+ Embeds an interactive panorama.
32
+
33
+
34
+ ### External Panorama
35
+
36
+
37
+ Panoramas that are already available on the web can be embedded via an URL. Choose "External Panorama" as Panorama Source and paste the URL.
38
+
39
+
40
+ ### Uploaded Zip File
41
+
42
+
43
+ Alternatively, 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.
44
+
45
+
46
+ Typical use cases: Impressing places, travel reports, architecture'
47
+ page:
48
+ close: Close
49
+ close_title: Close 360° panorama and display text
50
+ start: Start 360° panorama
51
+ page_type_category_name: Interactive
52
+ page_type_description: Interactive panorama using KRPano.
53
+ page_type_name: 360° Panorama
54
+ validation:
55
+ missing_index_document: Index document not found.
56
+ missing_preview: Preview image not found.
57
+ missing_tiles_directory: Tiles directory not found.
@@ -0,0 +1,17 @@
1
+ # Example Nginx configuration for pageflow-panorama
2
+ # vi: ft=nginx
3
+
4
+ location /panogate/ {
5
+ proxy_pass http://www.panogate.de/;
6
+ proxy_redirect http://www.panogate.de/ $scheme://$host/panogate/;
7
+ }
8
+
9
+ location /palmfilms/ {
10
+ proxy_pass http://www.palmfilms.com/;
11
+ proxy_redirect http://www.palmfilms.com/ $scheme://$host/palmfilms/;
12
+ }
13
+
14
+ location /bucket/ {
15
+ proxy_pass http://BUCKET_NAME.s3-website-eu-west-1.amazonaws.com/;
16
+ proxy_redirect http://BUCKET_NAME.s3-website-eu-west-1.amazonaws.com/ $scheme://$host/bucket/;
17
+ }
@@ -0,0 +1,16 @@
1
+ # Rails initializer example for Pageflow-panorama
2
+ # vi: ft=ruby
3
+
4
+ Pageflow::Panorama.configure do |config|
5
+ config.providers = [{
6
+ name: "palmsfilm.com",
7
+ base_path: "/panorama",
8
+ url: "http://palmsfilm.com/"
9
+ },{
10
+ name: "panogate.de",
11
+ base_path: "/panogate",
12
+ url: "http://www.panogate.de/"
13
+ }]
14
+
15
+ config.packages_base_path = "/bucket"
16
+ end
@@ -0,0 +1,12 @@
1
+ class CreatePackages < ActiveRecord::Migration
2
+ def change
3
+ create_table :pageflow_panorama_packages do |t|
4
+ Pageflow::HostedFile.columns(t)
5
+
6
+ t.integer(:unpacking_progress)
7
+ t.string(:unpacking_error_message)
8
+ t.string(:index_document)
9
+ t.attachment(:thumbnail)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,17 @@
1
+ require 'pageflow/panorama/engine'
2
+
3
+ module Pageflow
4
+ module Panorama
5
+ def self.config
6
+ @config ||= Panorama::Configuration.new
7
+ end
8
+
9
+ def self.configure(&block)
10
+ block.call(config)
11
+ end
12
+
13
+ def self.page_type
14
+ Panorama::PageType.new
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,12 @@
1
+ module Pageflow
2
+ module Panorama
3
+ class Configuration
4
+ attr_accessor :providers, :packages_base_path
5
+
6
+ def initialize
7
+ @providers = []
8
+ @packages_base_path = ''
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ require 'pageflow/panorama/zip_entry_paperclip_io_adapter'
2
+
3
+ module Pageflow
4
+ module Panorama
5
+ class Engine < Rails::Engine
6
+ isolate_namespace Pageflow::Panorama
7
+
8
+ config.autoload_paths << File.join(config.root, 'lib')
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,40 @@
1
+ module Pageflow
2
+ module Panorama
3
+ class JobStatusAttributes < Struct.new(:record, :stage_name)
4
+ def self.handle(record, options = {}, &block)
5
+ new(record, options[:stage]).call(&block)
6
+ end
7
+
8
+ def call(&block)
9
+ update_progress(0)
10
+
11
+ with_error_message_handling do
12
+ block.call do |percent|
13
+ update_progress(percent)
14
+ end
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def update_progress(percent)
21
+ record.update(stage_attribute_name(:progress) => percent,
22
+ stage_attribute_name(:error_message) => nil)
23
+ end
24
+
25
+ def with_error_message_handling
26
+ yield
27
+ rescue StandardError => e
28
+ if e.respond_to?(:message_i18n_key)
29
+ record[stage_attribute_name(:error_message)] = e.message_i18n_key
30
+ end
31
+
32
+ raise
33
+ end
34
+
35
+ def stage_attribute_name(suffix)
36
+ [stage_name, suffix].compact.join('_')
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,31 @@
1
+ module Pageflow
2
+ module Panorama
3
+ class PageType < Pageflow::PageType
4
+ name 'panorama'
5
+
6
+ def view_helpers
7
+ [
8
+ Pageflow::Panorama::PackagesHelper
9
+ ]
10
+ end
11
+
12
+ def file_types
13
+ [
14
+ FileType.new(model: Package,
15
+ editor_partial: 'pageflow/panorama/editor/packages/package')
16
+ ]
17
+ end
18
+
19
+ def json_seed_template
20
+ 'pageflow/panorama/page_type.json.jbuilder'
21
+ end
22
+
23
+ def thumbnail_candidates
24
+ [
25
+ {attribute: 'thumbnail_image_id', file_collection: 'image_files'},
26
+ {attribute: 'panorama_package_id', file_collection: 'pageflow_panorama_packages'}
27
+ ]
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,58 @@
1
+ require 'zip'
2
+
3
+ module Pageflow
4
+ module Panorama
5
+ class UnpackToS3
6
+ attr_reader :archive, :destination_bucket, :destination_base_path
7
+
8
+ def initialize(options)
9
+ @archive = options.fetch(:archive)
10
+ @destination_bucket = options.fetch(:destination_bucket)
11
+ @destination_base_path = options.fetch(:destination_base_path)
12
+ end
13
+
14
+ def upload(&progress)
15
+ archive.entries.each_with_index do |entry, index|
16
+ yield(100.0 * index / archive.entries.size) if block_given?
17
+ upload_entry(entry)
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def upload_entry(entry)
24
+ return unless entry.file?
25
+ with_retry do
26
+ s3_object(entry.name).write(entry.get_input_stream,
27
+ acl: :public_read,
28
+ content_length: entry.size)
29
+ end
30
+ end
31
+
32
+ def s3_object(file_name)
33
+ destination_bucket.objects[destination_path(file_name)]
34
+ end
35
+
36
+ def destination_path(file_name)
37
+ File.join(destination_base_path, file_name)
38
+ end
39
+
40
+ def with_retry(&block)
41
+ retries = 0
42
+
43
+ begin
44
+ yield
45
+ rescue AWS::S3::Errors::SlowDown
46
+ retries += 1
47
+
48
+ if retries <= 5
49
+ sleep((2 ** retries) * 0.5)
50
+ retry
51
+ else
52
+ raise
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,9 @@
1
+ module Pageflow
2
+ module Panorama
3
+ module Validation
4
+ def self.parse(archive)
5
+ KrPano.new(archive.entries).parse
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,14 @@
1
+ module Pageflow
2
+ module Panorama
3
+ module Validation
4
+ class Error < StandardError
5
+ attr_reader :message_i18n_key
6
+
7
+ def initialize(message_i18n_key)
8
+ super("Archive is not valid: #{message_i18n_key}")
9
+ @message_i18n_key = message_i18n_key
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,34 @@
1
+ module Pageflow
2
+ module Panorama
3
+ module Validation
4
+ class KrPano < Struct.new(:entries)
5
+ def parse
6
+ find_tiles_directory!
7
+
8
+ Result.new(find_index_document!,
9
+ find_thumbnail!)
10
+ end
11
+
12
+ private
13
+
14
+ def find_tiles_directory!
15
+ find_file!('*.tiles/*', :missing_tiles_directory)
16
+ end
17
+
18
+ def find_index_document!
19
+ find_file!('*.html', :missing_index_document)
20
+ end
21
+
22
+ def find_thumbnail!
23
+ find_file!('**/mobile_f.jpg', :missing_preview)
24
+ end
25
+
26
+ def find_file!(glob, message_i18n_key)
27
+ entries.map(&:name).find do |name|
28
+ File.fnmatch(glob, name)
29
+ end || raise(Error.new("pageflow.panorama.validation.#{message_i18n_key}"))
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,8 @@
1
+ module Pageflow
2
+ module Panorama
3
+ module Validation
4
+ class Result < Struct.new(:index_document, :thumbnail)
5
+ end
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,37 @@
1
+ require 'zip'
2
+ require 'paperclip'
3
+
4
+ module Pageflow
5
+ module Panorama
6
+ class ZipEntryPaperclipIOAdapter < Paperclip::AbstractAdapter
7
+ # Paperclip < 3.3.1 compatibility
8
+ unless Paperclip::AbstractAdapter.instance_methods.include?(:original_filename=)
9
+ attr_writer(:original_filename)
10
+ end
11
+
12
+ def initialize(entry)
13
+ @entry = entry
14
+ cache_current_values
15
+ end
16
+
17
+ private
18
+
19
+ def cache_current_values
20
+ self.original_filename = @entry.name
21
+ @tempfile = copy_to_tempfile(@entry)
22
+ @content_type = Paperclip::ContentTypeDetector.new(@tempfile.path).detect
23
+ @size = @entry.size
24
+ end
25
+
26
+ def copy_to_tempfile(entry)
27
+ override_existing_file = proc { true }
28
+ @entry.extract(destination.path, &override_existing_file)
29
+ destination
30
+ end
31
+ end
32
+
33
+ Paperclip.io_adapters.register(ZipEntryPaperclipIOAdapter) do |entry|
34
+ Zip::Entry === entry
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "pageflow-panorama"
5
+ spec.version = "0.1.0"
6
+ spec.authors = ["Codevise Solutions"]
7
+ spec.email = ["info@codevise.de"]
8
+ spec.summary = "Pagetype for iframe embedded 360° panoramas"
9
+ spec.homepage = ""
10
+ spec.license = "MIT"
11
+
12
+ spec.files = `git ls-files`.split($/)
13
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
14
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
15
+ spec.require_paths = ["lib"]
16
+
17
+ spec.add_runtime_dependency "pageflow"
18
+ spec.add_runtime_dependency "rubyzip", "~> 1.1"
19
+
20
+ spec.add_development_dependency "bundler"
21
+ spec.add_development_dependency "rake"
22
+ spec.add_development_dependency "rspec-rails", "~> 2.0"
23
+ spec.add_development_dependency 'factory_girl_rails'
24
+ spec.add_development_dependency "mysql2"
25
+ end
metadata ADDED
@@ -0,0 +1,185 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pageflow-panorama
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Codevise Solutions
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-06-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pageflow
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rubyzip
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.1'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec-rails
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '2.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '2.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: factory_girl_rails
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: mysql2
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ! '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description:
112
+ email:
113
+ - info@codevise.de
114
+ executables:
115
+ - rails
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - .gitignore
120
+ - CHANGELOG.md
121
+ - Gemfile
122
+ - README.md
123
+ - Rakefile
124
+ - app/assets/images/pageflow/ov-panorama.png
125
+ - app/assets/images/pageflow/panorama_pictogram.png
126
+ - app/assets/images/pageflow/panorama_pictogram_small.png
127
+ - app/assets/images/pageflow/panorama_sprite.png
128
+ - app/assets/javascripts/pageflow/panorama.js
129
+ - app/assets/javascripts/pageflow/panorama/editor.js
130
+ - app/assets/javascripts/pageflow/panorama/editor/config.js
131
+ - app/assets/javascripts/pageflow/panorama/editor/models/configuration_mixin.js
132
+ - app/assets/javascripts/pageflow/panorama/editor/models/package.js
133
+ - app/assets/javascripts/pageflow/panorama/editor/views/configuration_editor.js
134
+ - app/assets/javascripts/pageflow/panorama/page_type.js
135
+ - app/assets/stylesheets/pageflow/panorama.css.scss
136
+ - app/assets/stylesheets/pageflow/panorama/editor.css.scss
137
+ - app/helpers/pageflow/panorama/packages_helper.rb
138
+ - app/jobs/pageflow/panorama/unpack_package_job.rb
139
+ - app/models/pageflow/panorama/package.rb
140
+ - app/views/pageflow/panorama/editor/packages/_package.json.jbuilder
141
+ - app/views/pageflow/panorama/page.html.erb
142
+ - app/views/pageflow/panorama/page_type.json.jbuilder
143
+ - bin/rails
144
+ - config/locales/de.yml
145
+ - config/locales/en.yml
146
+ - config/pageflow-panorama-proxies.conf.example
147
+ - config/pageflow_panorama.rb.example
148
+ - db/migrate/20140915133249_create_packages.rb
149
+ - lib/pageflow-panorama.rb
150
+ - lib/pageflow/panorama/configuration.rb
151
+ - lib/pageflow/panorama/engine.rb
152
+ - lib/pageflow/panorama/job_status_attributes.rb
153
+ - lib/pageflow/panorama/page_type.rb
154
+ - lib/pageflow/panorama/unpack_to_s3.rb
155
+ - lib/pageflow/panorama/validation.rb
156
+ - lib/pageflow/panorama/validation/error.rb
157
+ - lib/pageflow/panorama/validation/kr_pano.rb
158
+ - lib/pageflow/panorama/validation/result.rb
159
+ - lib/pageflow/panorama/zip_entry_paperclip_io_adapter.rb
160
+ - pageflow-panorama.gemspec
161
+ homepage: ''
162
+ licenses:
163
+ - MIT
164
+ metadata: {}
165
+ post_install_message:
166
+ rdoc_options: []
167
+ require_paths:
168
+ - lib
169
+ required_ruby_version: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ required_rubygems_version: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - ! '>='
177
+ - !ruby/object:Gem::Version
178
+ version: '0'
179
+ requirements: []
180
+ rubyforge_project:
181
+ rubygems_version: 2.4.2
182
+ signing_key:
183
+ specification_version: 4
184
+ summary: Pagetype for iframe embedded 360° panoramas
185
+ test_files: []