resizing-rails 0.1.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +28 -0
  4. data/Rakefile +41 -0
  5. data/app/assets/config/resizing_rails_manifest.js +2 -0
  6. data/app/assets/javascripts/resizing/rails/application.js +15 -0
  7. data/app/assets/javascripts/resizing/rails/clipboard.js +15 -0
  8. data/app/assets/javascripts/resizing/rails/progressbar.js +33 -0
  9. data/app/assets/javascripts/resizing/rails/toast.js +35 -0
  10. data/app/assets/javascripts/resizing/rails/video.js +69 -0
  11. data/app/assets/javascripts/resizing/rails/video_fetcher.js +15 -0
  12. data/app/assets/javascripts/resizing/rails/video_uploader.js +77 -0
  13. data/app/assets/stylesheets/resizing/rails/application.scss +15 -0
  14. data/app/assets/stylesheets/resizing/rails/videos.scss +4 -0
  15. data/app/controllers/resizing/rails/application_controller.rb +7 -0
  16. data/app/controllers/resizing/rails/videos_controller.rb +26 -0
  17. data/app/helpers/resizing/rails/application_helper.rb +6 -0
  18. data/app/helpers/resizing/rails/videos_helper.rb +4 -0
  19. data/app/helpers/resizing/rails/webpack_bundle_helper.rb +21 -0
  20. data/app/javascript/packs/resizing.js +1 -0
  21. data/app/javascript/src/video.js +42 -0
  22. data/app/jobs/resizing/rails/application_job.rb +6 -0
  23. data/app/mailers/resizing/rails/application_mailer.rb +8 -0
  24. data/app/models/resizing/rails/application_record.rb +7 -0
  25. data/app/models/resizing/rails/video.rb +37 -0
  26. data/app/views/kaminari/_first_page.html.slim +2 -0
  27. data/app/views/kaminari/_gap.html.slim +2 -0
  28. data/app/views/kaminari/_last_page.html.slim +2 -0
  29. data/app/views/kaminari/_next_page.html.slim +2 -0
  30. data/app/views/kaminari/_page.html.slim +6 -0
  31. data/app/views/kaminari/_paginator.html.slim +12 -0
  32. data/app/views/kaminari/_prev_page.html.slim +2 -0
  33. data/app/views/layouts/resizing/rails/application.html.slim +20 -0
  34. data/app/views/resizing/rails/common/_clipboard.html.slim +1 -0
  35. data/app/views/resizing/rails/common/_toast.html.slim +10 -0
  36. data/app/views/resizing/rails/videos/_upload_form.html.slim +35 -0
  37. data/app/views/resizing/rails/videos/index.html.slim +53 -0
  38. data/app/views/resizing/rails/videos/show.html.slim +75 -0
  39. data/config/routes.rb +7 -0
  40. data/db/migrate/20210122043613_create_resizing_rails_videos.rb +9 -0
  41. data/lib/resizing/rails.rb +7 -0
  42. data/lib/resizing/rails/engine.rb +25 -0
  43. data/lib/resizing/rails/version.rb +5 -0
  44. data/lib/tasks/resizing/rails_tasks.rake +4 -0
  45. metadata +204 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 8e0b8f97f32819b39ebb857fea3e47d87a24dde886efeafa5b27311a91f2fc83
4
+ data.tar.gz: 2bc13646968446e0903d4f7e29af1c7aa7a4b441a161ddbed11f10a83f721004
5
+ SHA512:
6
+ metadata.gz: 7a05f15665f5d6dea1451c95e0c78090bda0bffdfc89fbc80b3ec2e60a9bd8e3c13f25aed7e7b8906a01acc26e5eb3297259da219d93d4428d80a9fd3d8c3392
7
+ data.tar.gz: ca25a67ff560dad4aa4b48b6f5ab36abfbc97045b7719e86075307185ef1d8f5e98d461924a73eaba02f52c67eabed364861170baeaac6ffe057acd5b7e90e32
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2021 Junichiro Kasuya
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,28 @@
1
+ # Resizing::Rails
2
+ Short description and motivation.
3
+
4
+ ## Usage
5
+ How to use my plugin.
6
+
7
+ ## Installation
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'resizing-rails'
12
+ ```
13
+
14
+ And then execute:
15
+ ```bash
16
+ $ bundle
17
+ ```
18
+
19
+ Or install it yourself as:
20
+ ```bash
21
+ $ gem install resizing-rails
22
+ ```
23
+
24
+ ## Contributing
25
+ Contribution directions go here.
26
+
27
+ ## License
28
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,41 @@
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
+ require 'github_changelog_generator/task'
9
+
10
+ RDoc::Task.new(:rdoc) do |rdoc|
11
+ rdoc.rdoc_dir = 'rdoc'
12
+ rdoc.title = 'Resizing::Rails'
13
+ rdoc.options << '--line-numbers'
14
+ rdoc.rdoc_files.include('README.md')
15
+ rdoc.rdoc_files.include('lib/**/*.rb')
16
+ end
17
+
18
+ APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
19
+ load 'rails/tasks/engine.rake'
20
+
21
+ load 'rails/tasks/statistics.rake'
22
+
23
+ require 'bundler/gem_tasks'
24
+
25
+ require 'rake/testtask'
26
+
27
+ Rake::TestTask.new(:test) do |t|
28
+ t.libs << 'test'
29
+ t.pattern = 'test/**/*_test.rb'
30
+ t.verbose = false
31
+ end
32
+
33
+ task default: :test
34
+
35
+
36
+ GitHubChangelogGenerator::RakeTask.new :changelog do |config|
37
+ config.user = 'jksy'
38
+ config.project = 'resizing-rails'
39
+ # config.since_tag = '0.0.1'
40
+ config.future_release = 'add-changelog'
41
+ end
@@ -0,0 +1,2 @@
1
+ //= link_directory ../javascripts/resizing/rails .js
2
+ //= link_directory ../stylesheets/resizing/rails .css
@@ -0,0 +1,15 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // compiled file. JavaScript code in this file should be added after the last require_* statement.
9
+ //
10
+ // Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require rails-ujs
14
+ //= require bootstrap
15
+ //= require_tree .
@@ -0,0 +1,15 @@
1
+ window.addEventListener('click', (e) => {
2
+ src = e.srcElement
3
+ if(src.hasAttribute('data-copy-url')) {
4
+ url = src.getAttribute('data-copy-url')
5
+ if(url !== null) {
6
+ elem = document.getElementById('clipboard')
7
+ elem.value = url
8
+ elem.select()
9
+ document.execCommand("copy")
10
+ toast = new Resizing.Rails.Toast()
11
+ index = url.lastIndexOf('/')
12
+ toast.show("コピーしました", '...' + url.substr(index, url.length))
13
+ }
14
+ }
15
+ })
@@ -0,0 +1,33 @@
1
+ window.Resizing ||= {}
2
+ window.Resizing.Rails ||= {}
3
+
4
+ // Usage
5
+ // min = 0
6
+ // max = 100
7
+ // bar = new Resizing.Rails.ProgressBar(document.querySelector('...'), min, max)
8
+ // bar.setCurrent(20)
9
+ //
10
+
11
+ class ProgressBar {
12
+ constructor(element, min, max) {
13
+ this.element = element
14
+ this.current = this.min = min
15
+ this.max = max
16
+ }
17
+
18
+ setCurrent(value) {
19
+ this.current = value
20
+ this.applyStyle()
21
+ }
22
+
23
+ applyStyle() {
24
+ let percentage = Math.floor(this.current / (this.max - this.min) * 100)
25
+ this.element.style = `width: ${percentage}%;`
26
+ this.element.setAttribute('aria-valuenow', this.current)
27
+ this.element.setAttribute('aria-valuemin', this.min)
28
+ this.element.setAttribute('aria-valuemax', this.max)
29
+ this.element.textContent = `${percentage}%`
30
+ }
31
+ }
32
+
33
+ window.Resizing.Rails.ProgressBar = ProgressBar
@@ -0,0 +1,35 @@
1
+ window.Resizing ||= {}
2
+ window.Resizing.Rails ||= {}
3
+
4
+ // Usage
5
+ // toast = new Resizing.Rails.Toast()
6
+ // toast.show('title', 'body-text')
7
+ //
8
+ class Toast {
9
+ constructor() {
10
+ this.container = document.getElementById('toast-container')
11
+ this.template = document.getElementById('toast-template').content
12
+ }
13
+
14
+ show(title, text) {
15
+ let $node = document.importNode(this.template, true)
16
+ let $toast = $node.querySelector('.toast')
17
+ let id = $toast.id = `toast-${this.generateUniqueId()}`
18
+ $node.querySelector('.toast-title').textContent = title
19
+ $node.querySelector('.toast-body').textContent = text
20
+ this.container.appendChild($node)
21
+
22
+ let $elem = document.getElementById(id)
23
+ let t = new bootstrap.Toast($elem)
24
+ t.show()
25
+ $elem.addEventListener('hidden.bs.toast',() => {
26
+ $elem.remove()
27
+ })
28
+ }
29
+
30
+ generateUniqueId() {
31
+ return (new Date).getTime().toString(16)
32
+ }
33
+ }
34
+
35
+ window.Resizing.Rails.Toast = Toast
@@ -0,0 +1,69 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
3
+
4
+ window.Resizing ||= {}
5
+ window.Resizing.Rails ||= {}
6
+
7
+ class Video {
8
+ constructor(self_url, parentElement) {
9
+ this.self_url = self_url
10
+ this.parentElement = parentElement
11
+ this.listener = null
12
+ let video = this.buildVideoTag()
13
+ this.video = videojs(video.id, {fluid: true})
14
+ this.record = null
15
+ }
16
+
17
+ fetch() {
18
+ let fetcher = new Resizing.Rails.VideoFetcher(this.self_url)
19
+ fetcher.fetch().then(record => {
20
+ this.record = record
21
+ this.call('video_fetched', record)
22
+ if(record.thumbnail_url) {
23
+ this.renderVideo(record)
24
+ }
25
+ if(record.state != 'ready') {
26
+ setTimeout(this.fetch.bind(this), 5_000)
27
+ }
28
+ })
29
+ }
30
+
31
+ renderVideo(record) {
32
+ this.video.poster(record.thumbnail_url)
33
+ if(record.m3u8_url) {
34
+ this.video.src({type: 'application/x-mpegURL', src: record.m3u8_url})
35
+ }
36
+ if(record.avc_url) {
37
+ this.video.src({type: 'video/mp4', src: record.avc_url})
38
+ }
39
+ }
40
+
41
+ buildVideoTag() {
42
+ let video = document.createElement('video')
43
+ video.setAttribute('class', 'video-js')
44
+ video.setAttribute('muted', 'true')
45
+ video.setAttribute('controls', '')
46
+ video.setAttribute('preload', 'metadata')
47
+ video.setAttribute('data-setup', '{}')
48
+ video.setAttribute('poster', '')
49
+ video.id = `video-${this.generateUniqueId()}`
50
+ this.parentElement.appendChild(video)
51
+ return video
52
+ }
53
+
54
+ generateUniqueId() {
55
+ return (new Date).getTime().toString(16)
56
+ }
57
+
58
+ addEventListener(listener) {
59
+ this.listener = listener
60
+ }
61
+
62
+ call(...args) {
63
+ if(this.listener !== null) {
64
+ this.listener(...args)
65
+ }
66
+ }
67
+ }
68
+
69
+ window.Resizing.Rails.Video = Video
@@ -0,0 +1,15 @@
1
+ window.Resizing ||= {}
2
+ window.Resizing.Rails ||= {}
3
+
4
+ class VideoFetcher {
5
+ constructor(self_url) {
6
+ this.self_url = self_url
7
+ }
8
+
9
+ fetch() {
10
+ return fetch(this.self_url, {method: 'GET', credentials: 'same-origin', headers: {'Content-Type': 'application/json'}})
11
+ .then(response => response.json())
12
+ }
13
+ }
14
+
15
+ window.Resizing.Rails.VideoFetcher = VideoFetcher
@@ -0,0 +1,77 @@
1
+ // Place all the behaviors and hooks related to the matching controller here.
2
+ // All this logic will automatically be available in application.js.
3
+
4
+ window.Resizing ||= {}
5
+ window.Resizing.Rails ||= {}
6
+
7
+ class VideoUploader {
8
+ constructor(file_field, prepare_url) {
9
+ this.file_field = file_field
10
+ this.prepare_url = prepare_url
11
+ this.callback = null
12
+ }
13
+
14
+ upload() {
15
+ let file = this.file_field.files[0]
16
+ if(file === undefined) {
17
+ this.call('no_file_found')
18
+ return
19
+ }
20
+ this.prepare(file.name)
21
+ .catch(error => {
22
+ this.call('upload_failed')
23
+ })
24
+ }
25
+
26
+ prepare(filename) {
27
+ let body = JSON.stringify({filename: filename})
28
+ return fetch(this.prepare_url, {method: 'POST', credentials: 'same-origin', headers: {'Content-Type': 'application/json'}, body: body})
29
+ .then(response => {
30
+ if(!response.ok) {
31
+ return Promise.reject(response)
32
+ }
33
+ return response.json()
34
+ }).then(record => {
35
+ return this.uploadFile(record)
36
+ })
37
+ }
38
+
39
+ uploadFile(record) {
40
+ let file = this.file_field.files[0]
41
+ let data = record.data
42
+ return fetch(data.s3_presigned_url, {method: 'PUT', credentials: 'same-origin', headers: {'Content-Type': file.type}, body: file})
43
+ .then(response => {
44
+ if(!response.ok) {
45
+ return Promise.reject(response)
46
+ }
47
+ // ignore response body
48
+ }).then(data => {
49
+ return this.uploadDone(record)
50
+ })
51
+ }
52
+
53
+ uploadDone(record) {
54
+ let data = record.data
55
+ return fetch(data.upload_completed_url, {method: 'PUT', credentials: 'same-origin', headers:{'Content-Type': 'application/json'}})
56
+ .then(response => {
57
+ if(!response.ok) {
58
+ return Promise.reject(response)
59
+ }
60
+ return response.json()
61
+ }).then(data => {
62
+ window.location.pathname = record.self_path
63
+ })
64
+ }
65
+
66
+ addEventListener(callback) {
67
+ this.callback = callback
68
+ }
69
+
70
+ call(state) {
71
+ if(this.callback !== undefined) {
72
+ this.callback(state)
73
+ }
74
+ }
75
+ }
76
+
77
+ window.Resizing.Rails.VideoUploader = VideoUploader
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ */
14
+ @import 'bootstrap';
15
+ @import 'videos';
@@ -0,0 +1,4 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */
@@ -0,0 +1,7 @@
1
+ module Resizing
2
+ module Rails
3
+ class ApplicationController < ActionController::Base
4
+ protect_from_forgery with: :exception
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,26 @@
1
+ require_dependency "resizing/rails/application_controller"
2
+
3
+ module Resizing::Rails
4
+ class VideosController < ApplicationController
5
+ skip_before_action :verify_authenticity_token, only: [:prepare]
6
+
7
+ def index
8
+ @videos = Resizing::Rails::Video.order('created_at desc').page(params[:page]).per(20)
9
+ render text: 'index'
10
+ end
11
+
12
+ def prepare
13
+ response = client.prepare
14
+ video = Resizing::Rails::Video.create!(data: response)
15
+ render json: video
16
+ end
17
+
18
+ def client
19
+ @client ||= Resizing::Video::Client.new
20
+ end
21
+
22
+ def show
23
+ @video = Resizing::Rails::Video.find(params[:id])
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,6 @@
1
+ module Resizing
2
+ module Rails
3
+ module ApplicationHelper
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,4 @@
1
+ module Resizing::Rails
2
+ module VideosHelper
3
+ end
4
+ end
@@ -0,0 +1,21 @@
1
+ # ref. https://qiita.com/Tak-Iwamoto/items/efce14f67eb572d8742e
2
+ module Resizing::Rails::WebpackBundleHelper
3
+ class BundleNotFound < StandardError; end
4
+
5
+ def asset_bundle_path(file)
6
+ valid_file?(file)
7
+ return "/assets" + manifest.fetch(file)
8
+ end
9
+
10
+ private
11
+
12
+ def manifest
13
+ return @manifest ||= JSON.parse(File.read("app/javascript/dist/manifest.json"))
14
+ end
15
+
16
+ def valid_file?(entry)
17
+ return true if manifest.key?(entry)
18
+ raise BundleNotFound, "Could not find bundle with name #{entry}"
19
+ end
20
+
21
+ end
@@ -0,0 +1 @@
1
+ import { Video } from '../src/video'
@@ -0,0 +1,42 @@
1
+ class Video {
2
+ constructor(element) {
3
+ this.element = element
4
+ this.element
5
+ }
6
+
7
+ upload() {
8
+ file = this.element.files[0]
9
+ prepare(file.name)
10
+ }
11
+
12
+ prepare(filename) {
13
+ body = JSON.stringify({filename: filename})
14
+ fetch(prepare_url, {method: 'POST', credentials: 'same-origin', headers: {'Content-Type': 'application/json'}, body: body})
15
+ .then(response => response.json())
16
+ .then(data => console.log(data))
17
+ }
18
+
19
+ file_upload(record) {
20
+ file = this.element.files[0]
21
+ fetch(record.s3_presigned_url, {method: 'PUT', credentials: 'same-origin', headers: {'Content-Type': file.type}, body: file})
22
+ .then(response => console.log(response))
23
+ .then(data => done_upload(record))
24
+ }
25
+
26
+ done_upload(record) {
27
+ fetch(record.upload_completed_url, {method: 'PUT', credentials: 'same-origin', headers:{'Content-Type': 'application/json'}})
28
+ .then(response => response.json())
29
+ .then(data => monitor_state(data))
30
+ }
31
+
32
+ monitor_state(record) {
33
+ alert('uploaded')
34
+ }
35
+
36
+ // monitor_state(record) {
37
+ // _record = record
38
+ // intervalID = setInternal(() => fetch(_record.self_url, method: 'GET', credentials: 'same-origin', headers:{'Content-Type': 'application/json'})
39
+ // }
40
+ }
41
+
42
+ export { Video }
@@ -0,0 +1,6 @@
1
+ module Resizing
2
+ module Rails
3
+ class ApplicationJob < ActiveJob::Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,8 @@
1
+ module Resizing
2
+ module Rails
3
+ class ApplicationMailer < ActionMailer::Base
4
+ default from: 'from@example.com'
5
+ layout 'mailer'
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ module Resizing
2
+ module Rails
3
+ class ApplicationRecord < ActiveRecord::Base
4
+ self.abstract_class = true
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,37 @@
1
+ module Resizing::Rails
2
+ class Video < ApplicationRecord
3
+ serialize :data, JSON
4
+
5
+ %w(
6
+ id
7
+ project_id
8
+ state
9
+ source_uri
10
+ deleted_at
11
+ s3_presigned_url
12
+ converted_uri
13
+ created_at
14
+ updated_at
15
+ upload_completed_url
16
+ self_url
17
+ m3u8_url
18
+ hevc_url
19
+ avc_url
20
+ thumbnail_url
21
+ job_state
22
+ ).each do |name|
23
+ define_method "data_#{name}" do
24
+ self.data[name]
25
+ end
26
+ end
27
+
28
+ def self_path
29
+ Resizing::Rails.railtie_routes_url_helpers.video_path(self)
30
+ end
31
+
32
+ def as_json *args
33
+ hash = super(*args)
34
+ hash.merge(self_path: self_path)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,2 @@
1
+ li.page-item
2
+ = link_to_unless current_page.first?, raw(t 'views.pagination.first'), url, remote: remote, class: 'page-link'
@@ -0,0 +1,2 @@
1
+ li.page-item.disabled
2
+ = link_to raw(t 'views.pagination.truncate'), '#', class: 'page-link'
@@ -0,0 +1,2 @@
1
+ li.page-item
2
+ = link_to_unless current_page.last?, raw(t 'views.pagination.last'), url, remote: remote, class: 'page-link'
@@ -0,0 +1,2 @@
1
+ li.page-item
2
+ = link_to_unless current_page.last?, raw(t 'views.pagination.next'), url, rel: 'next', remote: remote, class: 'page-link'
@@ -0,0 +1,6 @@
1
+ - if page.current?
2
+ li.page-item.active
3
+ = content_tag :a, page, data: { remote: remote }, rel: page.rel, class: 'page-link'
4
+ - else
5
+ li.page-item
6
+ = link_to page, url, remote: remote, rel: page.rel, class: 'page-link'
@@ -0,0 +1,12 @@
1
+ = paginator.render do
2
+ nav
3
+ ul.pagination.justify-content-center
4
+ == first_page_tag unless current_page.first?
5
+ == prev_page_tag unless current_page.first?
6
+ - each_page do |page|
7
+ - if page.left_outer? || page.right_outer? || page.inside_window?
8
+ == page_tag page
9
+ - elsif !page.was_truncated?
10
+ == gap_tag
11
+ == next_page_tag unless current_page.last?
12
+ == last_page_tag unless current_page.last?
@@ -0,0 +1,2 @@
1
+ li.page-item
2
+ = link_to_unless current_page.first?, raw(t 'views.pagination.previous'), url, rel: 'prev', remote: remote, class: 'page-link'
@@ -0,0 +1,20 @@
1
+ doctype html
2
+ html
3
+ head
4
+ meta charset='utf-8'
5
+ title Resizing rails
6
+ = csrf_meta_tags
7
+ = csp_meta_tag
8
+
9
+ link href="//vjs.zencdn.net/7.8.2/video-js.min.css" rel="stylesheet"
10
+ script src="//vjs.zencdn.net/7.8.2/video.min.js"
11
+
12
+ = stylesheet_link_tag "resizing/rails/application", media: "all"
13
+ = javascript_include_tag "resizing/rails/application"
14
+
15
+ body
16
+ .container
17
+ = yield
18
+
19
+ = render 'resizing/rails/common/toast'
20
+ = render 'resizing/rails/common/clipboard'
@@ -0,0 +1 @@
1
+ input#clipboard type='hidden' value=''
@@ -0,0 +1,10 @@
1
+ #toast-container.toast-container.position-fixed.top-0.end-0.p-3 style=("z-index: 5")
2
+ template#toast-template
3
+ .toast aria-atomic="true" aria-live="assertive" id="" role="alert"
4
+ .toast-header
5
+ /! img src="..." class="rounded me-2" alt="..."
6
+ strong.me-auto.toast-title Bootstrap
7
+ small.text-muted 2 seconds ago
8
+ button.btn-close aria-label="Close" data-bs-dismiss="toast" type="button"
9
+ .toast-body
10
+ | Heads up, toasts will stack automatically
@@ -0,0 +1,35 @@
1
+ form
2
+ .mb-3.row
3
+ label.form-label.col-sm-3.col-form-label for='video' File(MP4/MOV/AVI/WMV/ASF/WebM)
4
+ .col-sm-10
5
+ input.form-control#video type='file'
6
+ button.btn.btn-primary.mb-3#submit type='submit' upload
7
+
8
+ javascript:
9
+ document.addEventListener('DOMContentLoaded', (event)=> {
10
+ video = new Resizing.Rails.VideoUploader(
11
+ document.getElementById('video'),
12
+ #{raw Resizing::Rails.railtie_routes_url_helpers.prepare_videos_url(only_path: true).to_json}
13
+ );
14
+
15
+ document.getElementById('submit').addEventListener(
16
+ 'click',
17
+ (e) => {
18
+ e.preventDefault()
19
+ e.target.setAttribute('disabled', 'true')
20
+ video.upload()
21
+ }
22
+ )
23
+
24
+ video.addEventListener(e => {
25
+ switch(e) {
26
+ case 'no_file_found':
27
+ (new Resizing.Rails.Toast()).show('Error', 'ファイルを指定してください')
28
+ break;
29
+ case 'upload_failed':
30
+ (new Resizing.Rails.Toast()).show('Error', 'アップロードに失敗しました')
31
+ break;
32
+ }
33
+ document.getElementById('submit').removeAttribute('disabled')
34
+ })
35
+ })
@@ -0,0 +1,53 @@
1
+ h1 動画アップロード
2
+
3
+ = render 'resizing/rails/videos/upload_form'
4
+
5
+ = paginate(@videos)
6
+
7
+ .row.row-cols-1.row-cols-md-4.g-3
8
+ - @videos.each do |video|
9
+ .col
10
+ .card.h-100 data-video-url=video.data_self_url
11
+ img.js-video-thumbnail.card-img-top
12
+ .card-body
13
+ h5.card-title = "#{video.id}:#{video.data_id}"
14
+ ul.list-group.list-group-flush
15
+ li.list-group-item
16
+ | State:
17
+ span.video-state = video.data_state
18
+ li.list-group-item
19
+ | AVC
20
+ a.card-link.avc-url.data-copy-url href='#'
21
+ | Copy URL
22
+ li.list-group-item
23
+ | HEVC
24
+ a.card-link.hevc-url.data-copy-url href='#'
25
+ | Copy URL
26
+ .card-footer
27
+ small.text-muted = 'asfadf'
28
+ .card-body
29
+ = link_to 'Show video details', video, class: 'btn btn-primary'
30
+
31
+ = paginate(@videos)
32
+
33
+ javascript:
34
+ document.addEventListener('DOMContentLoaded', ()=> {
35
+ let setDataCopyURLOrRemoveElement = (elem, value) => {
36
+ if(value) {
37
+ elem.setAttribute('data-copy-url', value)
38
+ } else {
39
+ elem.remove()
40
+ }
41
+ }
42
+ elements = document.querySelectorAll('[data-video-url]')
43
+ elements.forEach(elem => {
44
+ url = elem.getAttribute('data-video-url')
45
+ fetcher = new Resizing.Rails.VideoFetcher(url)
46
+ fetcher.fetch().then(data => {
47
+ elem.querySelector('.js-video-thumbnail').setAttribute('src', data.thumbnail_url)
48
+ elem.querySelector('.video-state').textContent = data.state
49
+ setDataCopyURLOrRemoveElement(elem.querySelector('.avc-url'), data.avc_url)
50
+ setDataCopyURLOrRemoveElement(elem.querySelector('.hevc-url'), data.hevc_url)
51
+ })
52
+ })
53
+ })
@@ -0,0 +1,75 @@
1
+
2
+ .card
3
+ .card-img-top
4
+ #video
5
+ .card-body
6
+ .card-title = "Video##{@video.id}"
7
+ ul.list-group.list-group-flush
8
+ li.list-group-item
9
+ | 進捗
10
+ .progress
11
+ .progress-bar.progress-bar-striped.progress-bar-animated role='progressbar' style="width: 0%;" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100" 25%
12
+ li.list-group-item
13
+ | AVC
14
+ a.card-link.avc-url.data-copy-url href='#'
15
+ | Copy URL
16
+ li.list-group-item
17
+ | HEVC
18
+ a.card-link.hevc-url.data-copy-url href='#'
19
+ | Copy URL
20
+ li.list-group-item
21
+ label.form-label for='copy-tag' コピー用のタグ(このサイト内だけで有効です)
22
+ textarea#copy-tag class='form-control' rows='10'
23
+ | <div id='video-#{@video.id}'></div>
24
+ <script>
25
+ document.addEventListner('DOMContentLoaded', function () {
26
+ video = new Resizing.Rails.Video("#{@video.data_self_url}", document.querySelector('video-#{@video.id}'))
27
+ video.fetch()
28
+ })
29
+ </script>
30
+
31
+ p
32
+ | ※Resizing.Rails.Video classの読み込みが必要です。
33
+ b 例:
34
+ pre
35
+ code
36
+ | javascript_include_tag "resizing/rails/video"
37
+
38
+ javascript:
39
+ document.addEventListener('DOMContentLoaded', function() {
40
+ progress = new Resizing.Rails.ProgressBar(document.querySelector('.progress-bar'), 0, 100)
41
+
42
+ let setDataCopyURLOrRemoveElement = (elem, value) => {
43
+ if(!elem) {
44
+ return
45
+ }
46
+
47
+ if(value) {
48
+ elem.setAttribute('data-copy-url', value)
49
+ elem.textContent = 'Copy URL'
50
+ } else {
51
+ elem.textContent = ''
52
+ }
53
+ }
54
+
55
+ video_root = document.querySelector('#video')
56
+ video = new Resizing.Rails.Video("#{@video.data_self_url}", video_root)
57
+ video.fetch()
58
+ video.addEventListener((state, data) => {
59
+ console.log('eventListener')
60
+ console.log(data)
61
+ switch(state) {
62
+ case 'video_fetched':
63
+ if(data.job_state?.job_percent_complete !== undefined) {
64
+ progress.setCurrent(data.job_state?.job_percent_complete)
65
+ }
66
+ setDataCopyURLOrRemoveElement(document.querySelector('.avc-url'), data.avc_url)
67
+ setDataCopyURLOrRemoveElement(document.querySelector('.hevc-url'), data.hevc_url)
68
+ break
69
+ default:
70
+ break
71
+ }
72
+ })
73
+
74
+ })
75
+
data/config/routes.rb ADDED
@@ -0,0 +1,7 @@
1
+ Resizing::Rails::Engine.routes.draw do
2
+ resources :videos do
3
+ collection do
4
+ post :prepare
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ class CreateResizingRailsVideos < ActiveRecord::Migration[5.2]
2
+ def change
3
+ create_table :resizing_rails_videos do |t|
4
+ t.text :data
5
+
6
+ t.timestamps
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ require "resizing/rails/engine"
2
+
3
+ module Resizing
4
+ module Rails
5
+ # Your code goes here...
6
+ end
7
+ end
@@ -0,0 +1,25 @@
1
+ Gem.loaded_specs['resizing-rails'].dependencies.each do |d|
2
+ require d.name
3
+ rescue LoadError
4
+ require d.name.gsub('-', '/')
5
+ end
6
+
7
+ module Resizing
8
+ module Rails
9
+ class Engine < ::Rails::Engine
10
+ isolate_namespace Resizing::Rails
11
+
12
+ # initializer 'ResizingRails precompile hook', group: :all do |app|
13
+ # puts app.config.assets.precompile
14
+ # app.config.assets.precompile += %w(
15
+ # resizing/rails/videos.js
16
+ # )
17
+ # end
18
+
19
+ # rake_tasks do
20
+ # Dir[File.join(File.dirname(__FILE__), '../tasks/*.rake')].each { |f| load f }
21
+ # end
22
+ end
23
+ end
24
+ end
25
+
@@ -0,0 +1,5 @@
1
+ module Resizing
2
+ module Rails
3
+ VERSION = '0.1.0.pre'
4
+ end
5
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :resizing_rails do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,204 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: resizing-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0.pre
5
+ platform: ruby
6
+ authors:
7
+ - Junichiro Kasuya
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-02-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 5.2.4
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 5.2.4.4
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: 5.2.4
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 5.2.4.4
33
+ - !ruby/object:Gem::Dependency
34
+ name: resizing
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: 0.8.0
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: 0.8.0
47
+ - !ruby/object:Gem::Dependency
48
+ name: slim-rails
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ - !ruby/object:Gem::Dependency
62
+ name: kaminari
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ - !ruby/object:Gem::Dependency
76
+ name: bootstrap
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: 5.0.0.beta1
82
+ type: :runtime
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: 5.0.0.beta1
89
+ - !ruby/object:Gem::Dependency
90
+ name: sassc
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ type: :runtime
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ - !ruby/object:Gem::Dependency
104
+ name: sqlite3
105
+ requirement: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ type: :development
111
+ prerelease: false
112
+ version_requirements: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ - !ruby/object:Gem::Dependency
118
+ name: github_changelog_generator
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ description: Resizing mountable module for Rails application.
132
+ email:
133
+ - junichiro.kasuya@gmail.com
134
+ executables: []
135
+ extensions: []
136
+ extra_rdoc_files: []
137
+ files:
138
+ - MIT-LICENSE
139
+ - README.md
140
+ - Rakefile
141
+ - app/assets/config/resizing_rails_manifest.js
142
+ - app/assets/javascripts/resizing/rails/application.js
143
+ - app/assets/javascripts/resizing/rails/clipboard.js
144
+ - app/assets/javascripts/resizing/rails/progressbar.js
145
+ - app/assets/javascripts/resizing/rails/toast.js
146
+ - app/assets/javascripts/resizing/rails/video.js
147
+ - app/assets/javascripts/resizing/rails/video_fetcher.js
148
+ - app/assets/javascripts/resizing/rails/video_uploader.js
149
+ - app/assets/stylesheets/resizing/rails/application.scss
150
+ - app/assets/stylesheets/resizing/rails/videos.scss
151
+ - app/controllers/resizing/rails/application_controller.rb
152
+ - app/controllers/resizing/rails/videos_controller.rb
153
+ - app/helpers/resizing/rails/application_helper.rb
154
+ - app/helpers/resizing/rails/videos_helper.rb
155
+ - app/helpers/resizing/rails/webpack_bundle_helper.rb
156
+ - app/javascript/packs/resizing.js
157
+ - app/javascript/src/video.js
158
+ - app/jobs/resizing/rails/application_job.rb
159
+ - app/mailers/resizing/rails/application_mailer.rb
160
+ - app/models/resizing/rails/application_record.rb
161
+ - app/models/resizing/rails/video.rb
162
+ - app/views/kaminari/_first_page.html.slim
163
+ - app/views/kaminari/_gap.html.slim
164
+ - app/views/kaminari/_last_page.html.slim
165
+ - app/views/kaminari/_next_page.html.slim
166
+ - app/views/kaminari/_page.html.slim
167
+ - app/views/kaminari/_paginator.html.slim
168
+ - app/views/kaminari/_prev_page.html.slim
169
+ - app/views/layouts/resizing/rails/application.html.slim
170
+ - app/views/resizing/rails/common/_clipboard.html.slim
171
+ - app/views/resizing/rails/common/_toast.html.slim
172
+ - app/views/resizing/rails/videos/_upload_form.html.slim
173
+ - app/views/resizing/rails/videos/index.html.slim
174
+ - app/views/resizing/rails/videos/show.html.slim
175
+ - config/routes.rb
176
+ - db/migrate/20210122043613_create_resizing_rails_videos.rb
177
+ - lib/resizing/rails.rb
178
+ - lib/resizing/rails/engine.rb
179
+ - lib/resizing/rails/version.rb
180
+ - lib/tasks/resizing/rails_tasks.rake
181
+ homepage: https://github.com/jksy/resizing-rails/
182
+ licenses:
183
+ - MIT
184
+ metadata: {}
185
+ post_install_message:
186
+ rdoc_options: []
187
+ require_paths:
188
+ - lib
189
+ required_ruby_version: !ruby/object:Gem::Requirement
190
+ requirements:
191
+ - - ">="
192
+ - !ruby/object:Gem::Version
193
+ version: '0'
194
+ required_rubygems_version: !ruby/object:Gem::Requirement
195
+ requirements:
196
+ - - ">"
197
+ - !ruby/object:Gem::Version
198
+ version: 1.3.1
199
+ requirements: []
200
+ rubygems_version: 3.0.3
201
+ signing_key:
202
+ specification_version: 4
203
+ summary: Resizing mountable module for Rails application.
204
+ test_files: []