product_tours 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +41 -0
- data/MIT-LICENSE +19 -0
- data/README.md +209 -0
- data/Rakefile +11 -0
- data/app/controllers/product_tours/application_controller.rb +68 -0
- data/app/controllers/product_tours/media_controller.rb +14 -0
- data/app/controllers/product_tours/posts_controller.rb +230 -0
- data/app/controllers/product_tours/tours_controller.rb +69 -0
- data/app/controllers/product_tours/widgets_controller.rb +28 -0
- data/app/helpers/product_tours/posts_helper.rb +19 -0
- data/app/helpers/product_tours/widget_helper.rb +14 -0
- data/app/models/product_tours/application_record.rb +7 -0
- data/app/models/product_tours/post.rb +128 -0
- data/app/views/layouts/product_tours/application.html.erb +20 -0
- data/app/views/product_tours/posts/_form.html.erb +177 -0
- data/app/views/product_tours/posts/_post_panel.html.erb +111 -0
- data/app/views/product_tours/posts/edit.html.erb +5 -0
- data/app/views/product_tours/posts/index.html.erb +92 -0
- data/app/views/product_tours/posts/new.html.erb +5 -0
- data/app/views/product_tours/posts/show.html.erb +5 -0
- data/config/locales/product_tours.ar.yml +11 -0
- data/config/locales/product_tours.bg.yml +11 -0
- data/config/locales/product_tours.bn.yml +11 -0
- data/config/locales/product_tours.de.yml +11 -0
- data/config/locales/product_tours.el.yml +11 -0
- data/config/locales/product_tours.en.yml +11 -0
- data/config/locales/product_tours.es.yml +11 -0
- data/config/locales/product_tours.fr.yml +11 -0
- data/config/locales/product_tours.hi.yml +11 -0
- data/config/locales/product_tours.hr.yml +11 -0
- data/config/locales/product_tours.id.yml +11 -0
- data/config/locales/product_tours.it.yml +11 -0
- data/config/locales/product_tours.ja.yml +11 -0
- data/config/locales/product_tours.ko.yml +11 -0
- data/config/locales/product_tours.lb.yml +11 -0
- data/config/locales/product_tours.nl.yml +11 -0
- data/config/locales/product_tours.pl.yml +11 -0
- data/config/locales/product_tours.pt.yml +11 -0
- data/config/locales/product_tours.ro.yml +11 -0
- data/config/locales/product_tours.ru.yml +11 -0
- data/config/locales/product_tours.th.yml +11 -0
- data/config/locales/product_tours.tr.yml +11 -0
- data/config/locales/product_tours.uk.yml +11 -0
- data/config/locales/product_tours.ur.yml +11 -0
- data/config/locales/product_tours.vi.yml +11 -0
- data/config/locales/product_tours.zh-CN.yml +11 -0
- data/config/routes.rb +23 -0
- data/lib/generators/product_tours/install/install_generator.rb +44 -0
- data/lib/generators/product_tours/install/templates/create_product_tours_posts.rb.tt +29 -0
- data/lib/generators/product_tours/install/templates/initializer.rb +21 -0
- data/lib/product_tours/configuration.rb +18 -0
- data/lib/product_tours/content_security_policy.rb +24 -0
- data/lib/product_tours/dashboard.css +196 -0
- data/lib/product_tours/dashboard.js +229 -0
- data/lib/product_tours/engine.rb +28 -0
- data/lib/product_tours/errors.rb +14 -0
- data/lib/product_tours/seeds.rb +147 -0
- data/lib/product_tours/version.rb +5 -0
- data/lib/product_tours/video_metadata.rb +60 -0
- data/lib/product_tours/video_resolver.rb +129 -0
- data/lib/product_tours/widget.js +359 -0
- data/lib/product_tours/widget.rb +59 -0
- data/lib/product_tours.rb +35 -0
- data/lib/tasks/product_tours_tasks.rake +12 -0
- metadata +131 -0
data/config/routes.rb
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
ProductTours::Engine.routes.draw do
|
|
4
|
+
get 'widget.js', to: 'widgets#show', as: :widget_script
|
|
5
|
+
get 'dashboard.js', to: 'widgets#dashboard', as: :dashboard_script
|
|
6
|
+
get 'dashboard.css', to: 'widgets#dashboard_stylesheet', as: :dashboard_stylesheet
|
|
7
|
+
|
|
8
|
+
scope :widget, as: :widget do
|
|
9
|
+
get :post, to: 'tours#resolve'
|
|
10
|
+
post :signal, to: 'tours#signal'
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
get 'media/:id', to: 'media#show', as: :media, constraints: { id: /\d+/ }
|
|
14
|
+
|
|
15
|
+
resources :posts do
|
|
16
|
+
post :refresh_video_metadata, on: :member
|
|
17
|
+
post :add_translation, on: :member
|
|
18
|
+
patch :publish, on: :member
|
|
19
|
+
patch :unpublish, on: :member
|
|
20
|
+
get :video_preview, on: :collection
|
|
21
|
+
end
|
|
22
|
+
root to: 'posts#index'
|
|
23
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails/generators'
|
|
4
|
+
require 'rails/generators/active_record'
|
|
5
|
+
|
|
6
|
+
module ProductTours
|
|
7
|
+
module Generators
|
|
8
|
+
class InstallGenerator < Rails::Generators::Base
|
|
9
|
+
include ActiveRecord::Generators::Migration
|
|
10
|
+
|
|
11
|
+
source_root File.expand_path('templates', __dir__)
|
|
12
|
+
desc 'Installs product_tours: initializer, posts migration, and engine mount.'
|
|
13
|
+
|
|
14
|
+
def create_initializer
|
|
15
|
+
copy_file 'initializer.rb', 'config/initializers/product_tours.rb'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def create_migration_file
|
|
19
|
+
migration_template 'create_product_tours_posts.rb.tt', 'db/migrate/create_product_tours_posts.rb'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def mount_engine
|
|
23
|
+
route %(mount_product_tours at: "/product_tours")
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def post_install
|
|
27
|
+
say "\nproduct_tours installed. Run `bin/rails db:migrate`.", :green
|
|
28
|
+
say 'The migration adds ready-to-use demo posts in development.'
|
|
29
|
+
say "\nCopy this into any ERB view to try them:\n\n"
|
|
30
|
+
say ProductTours::Seeds.trigger_html
|
|
31
|
+
say 'Manage tutorials at /product_tours (development only until config.authorize_admin is set).'
|
|
32
|
+
say 'Run `bin/rails product_tours:seed_demo` any time to refresh every demo locale.'
|
|
33
|
+
say 'Run `bin/rails active_storage:install` for uploads and '
|
|
34
|
+
say '`bin/rails action_text:install` for rich descriptions.\n'
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def migration_version
|
|
40
|
+
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class CreateProductToursPosts < ActiveRecord::Migration<%= migration_version %>
|
|
4
|
+
def change
|
|
5
|
+
create_table :product_tours_posts do |t|
|
|
6
|
+
t.string :key, null: false
|
|
7
|
+
t.string :locale, null: false
|
|
8
|
+
t.string :status, null: false, default: "draft"
|
|
9
|
+
t.string :title, null: false
|
|
10
|
+
t.text :video_url
|
|
11
|
+
t.json :video_metadata, null: false, default: {}
|
|
12
|
+
t.string :action_label
|
|
13
|
+
t.text :action_url
|
|
14
|
+
t.string :action_post_key
|
|
15
|
+
|
|
16
|
+
t.timestamps
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
add_index :product_tours_posts, %i[locale key], unique: true
|
|
20
|
+
add_index :product_tours_posts, :locale
|
|
21
|
+
add_index :product_tours_posts, :status
|
|
22
|
+
|
|
23
|
+
reversible do |direction|
|
|
24
|
+
direction.up do
|
|
25
|
+
ProductTours::Seeds.load_for_install!
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
ProductTours.configure do |config|
|
|
4
|
+
# Who can see and invoke product tours. Defaults to everyone.
|
|
5
|
+
# config.enabled = ->(request) { true }
|
|
6
|
+
|
|
7
|
+
# Who can manage tutorials at the mount path. Defaults to development only.
|
|
8
|
+
# config.authorize_admin = ->(request) { request.env["warden"]&.user&.admin? }
|
|
9
|
+
|
|
10
|
+
# Render the dashboard in your own admin shell.
|
|
11
|
+
# config.admin_layout = "admin/application"
|
|
12
|
+
|
|
13
|
+
# Tutorials resolve in the page's current I18n.locale and fall back to
|
|
14
|
+
# I18n.default_locale when no translation exists.
|
|
15
|
+
|
|
16
|
+
# Optional dedicated Active Storage service for uploaded videos.
|
|
17
|
+
# config.storage_service = :product_tours
|
|
18
|
+
|
|
19
|
+
# Keep this in sync only when mounting the engine manually.
|
|
20
|
+
# config.mount_path = "/product_tours"
|
|
21
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ProductTours
|
|
4
|
+
class Configuration
|
|
5
|
+
attr_accessor :enabled, :authorize_admin, :admin_layout, :mount_path,
|
|
6
|
+
:storage_service
|
|
7
|
+
|
|
8
|
+
def initialize
|
|
9
|
+
@enabled = ->(_request) { true }
|
|
10
|
+
@authorize_admin = ->(_request) { Rails.env.development? }
|
|
11
|
+
@admin_layout = 'product_tours/application'
|
|
12
|
+
@mount_path = '/product_tours'
|
|
13
|
+
@storage_service = nil
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def widget_endpoint = "#{mount_path.to_s.chomp('/')}/widget"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ProductTours
|
|
4
|
+
module ContentSecurityPolicy
|
|
5
|
+
FRAME_SOURCES = %w[
|
|
6
|
+
https://www.youtube-nocookie.com
|
|
7
|
+
https://player.vimeo.com
|
|
8
|
+
https://www.loom.com
|
|
9
|
+
https://www.tella.tv
|
|
10
|
+
https://embed.voomly.com
|
|
11
|
+
].freeze
|
|
12
|
+
|
|
13
|
+
module_function
|
|
14
|
+
|
|
15
|
+
def apply!(policy)
|
|
16
|
+
return unless policy
|
|
17
|
+
|
|
18
|
+
sources = Array(policy.directives['frame-src'])
|
|
19
|
+
sources = Array(policy.directives['default-src']) if sources.empty?
|
|
20
|
+
sources = sources.reject { |source| source == "'none'" }
|
|
21
|
+
policy.frame_src(*(sources + FRAME_SOURCES).uniq)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|