alchemy-dragonfly-s3 5.0.4 → 5.0.5
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 +4 -4
- data/app/assets/config/alchemy_dragonfly_s3_manifest.js +1 -0
- data/app/assets/images/alchemy/missing-image.svg +1 -0
- data/app/models/alchemy/attachment/s3_url.rb +11 -0
- data/app/models/alchemy/picture/s3_url.rb +41 -0
- data/app/models/alchemy/picture_thumb.rb +38 -0
- data/app/models/alchemy/picture_thumb/create.rb +18 -0
- data/app/models/alchemy/picture_thumb/signature.rb +23 -0
- data/app/models/alchemy/picture_thumb/uid.rb +22 -0
- data/app/models/alchemy/picture_variant.rb +114 -0
- data/app/views/alchemy/admin/attachments/show.html.erb +54 -0
- data/app/views/alchemy/admin/pictures/_picture.html.erb +53 -0
- data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +20 -0
- data/app/views/alchemy/admin/pictures/show.html.erb +43 -0
- data/app/views/alchemy/essences/_essence_file_view.html.erb +14 -0
- data/db/migrate/1_create_alchemy_picture_thumbs.rb +12 -0
- data/lib/alchemy/dragonfly/s3/version.rb +1 -1
- metadata +16 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 02d80fac356bf2e699b152896713ac7731cb23f0a1e26b0b6eba79648c90236d
|
4
|
+
data.tar.gz: fbbe2ced0c05ff53e75df1cd39a3d7b754dad998c0230a896b9ceadae2e3864b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f9af0f1daaeedc925e70fe185968e7ea02f93f10d8dce08a06c0360e30445bbefe0bdceade9c99e9f7c6c616cb83f5699fadce2a0214121a8f486c0c23031dbb
|
7
|
+
data.tar.gz: 4f2ffac175138c3f792615c20d14c32724c79f922f16bb993d94af2f441a2c17585716b89160d7ea2927c9afc319004e3dc79b976485f2d6e7ca3ac45293b85a
|
@@ -0,0 +1 @@
|
|
1
|
+
//= link alchemy/missing-image.svg
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg aria-hidden="true" focusable="false" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" width="16" height="16"><path fill="#f7f7f7" d="M569.517 440.013C587.975 472.007 564.806 512 527.94 512H48.054c-36.937 0-59.999-40.055-41.577-71.987L246.423 23.985c18.467-32.009 64.72-31.951 83.154 0l239.94 416.028zM288 354c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z" class=""></path></svg>
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Alchemy
|
4
|
+
class Picture < BaseRecord
|
5
|
+
class S3Url
|
6
|
+
attr_reader :variant
|
7
|
+
|
8
|
+
# @param [Alchemy::PictureVariant]
|
9
|
+
#
|
10
|
+
def initialize(variant)
|
11
|
+
raise ArgumentError, "Variant missing!" if variant.nil?
|
12
|
+
|
13
|
+
@variant = variant
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(*)
|
17
|
+
return variant.image.remote_url unless processible_image?
|
18
|
+
|
19
|
+
::Dragonfly.app(:alchemy_pictures).remote_url_for(uid)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def processible_image?
|
25
|
+
variant.image.is_a?(::Dragonfly::Job)
|
26
|
+
end
|
27
|
+
|
28
|
+
def uid
|
29
|
+
signature = PictureThumb::Signature.call(variant)
|
30
|
+
thumb = variant.picture.thumbs.detect { |t| t.signature == signature }
|
31
|
+
if thumb
|
32
|
+
uid = thumb.uid
|
33
|
+
else
|
34
|
+
uid = PictureThumb::Uid.call(signature, variant)
|
35
|
+
PictureThumb::Create.call(variant, signature, uid)
|
36
|
+
end
|
37
|
+
uid
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Alchemy
|
4
|
+
# The persisted version of a rendered picture variant
|
5
|
+
#
|
6
|
+
class PictureThumb < BaseRecord
|
7
|
+
belongs_to :picture, class_name: "Alchemy::Picture"
|
8
|
+
|
9
|
+
validates :signature, presence: true
|
10
|
+
validates :uid, presence: true
|
11
|
+
|
12
|
+
class << self
|
13
|
+
# Upfront generation of picture thumbnails
|
14
|
+
#
|
15
|
+
# Called after a Alchemy::Picture has been created (after an image has been uploaded)
|
16
|
+
#
|
17
|
+
# Generates three types of thumbnails that are used by Alchemys picture archive and
|
18
|
+
# persists them in the configures file store (Default Dragonfly::FileDataStore).
|
19
|
+
#
|
20
|
+
# @see Picture::THUMBNAIL_SIZES
|
21
|
+
def generate_thumbs!(picture)
|
22
|
+
Alchemy::Picture::THUMBNAIL_SIZES.values.map do |size|
|
23
|
+
variant = Alchemy::PictureVariant.new(picture, {
|
24
|
+
size: size,
|
25
|
+
flatten: true,
|
26
|
+
})
|
27
|
+
signature = Alchemy::PictureThumb::Signature.call(variant)
|
28
|
+
thumb = find_by(signature: signature)
|
29
|
+
next if thumb
|
30
|
+
|
31
|
+
uid = Alchemy::PictureThumb::Uid.call(signature, variant)
|
32
|
+
Alchemy::PictureThumb::Create.call(variant, signature, uid)
|
33
|
+
uid
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Alchemy
|
2
|
+
class PictureThumb < BaseRecord
|
3
|
+
# Stores the render result of a Alchemy::PictureVariant
|
4
|
+
# in the Dragonfly S3 datastore
|
5
|
+
#
|
6
|
+
class Create
|
7
|
+
def self.call(variant, signature, uid)
|
8
|
+
image = variant.image
|
9
|
+
image.store(path: uid)
|
10
|
+
variant.picture.thumbs.create!(
|
11
|
+
picture: variant.picture,
|
12
|
+
signature: signature,
|
13
|
+
uid: uid,
|
14
|
+
)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Alchemy
|
4
|
+
class PictureThumb < BaseRecord
|
5
|
+
class Signature
|
6
|
+
# Returns a unique image process signature
|
7
|
+
#
|
8
|
+
# @param [Alchemy::PictureVariant]
|
9
|
+
#
|
10
|
+
# @return [String]
|
11
|
+
def self.call(variant)
|
12
|
+
steps_without_fetch = variant.image.steps.reject do |step|
|
13
|
+
step.is_a?(::Dragonfly::Job::Fetch)
|
14
|
+
end
|
15
|
+
|
16
|
+
steps_with_id = [[variant.picture.id]] + steps_without_fetch
|
17
|
+
job_string = steps_with_id.map(&:to_a).to_dragonfly_unique_s
|
18
|
+
|
19
|
+
Digest::SHA1.hexdigest(job_string)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Alchemy
|
4
|
+
class PictureThumb < BaseRecord
|
5
|
+
class Uid
|
6
|
+
# Returns a image variant uid for storage
|
7
|
+
#
|
8
|
+
# @param [String]
|
9
|
+
# @param [Alchemy::PictureVariant]
|
10
|
+
#
|
11
|
+
# @return [String]
|
12
|
+
def self.call(signature, variant)
|
13
|
+
picture = variant.picture
|
14
|
+
filename = variant.image_file_name || "image"
|
15
|
+
name = File.basename(filename, ".*").gsub(/[^\w.]+/, "_")
|
16
|
+
ext = variant.render_format
|
17
|
+
|
18
|
+
"pictures/#{picture.id}/#{signature}/#{name}.#{ext}"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "forwardable"
|
4
|
+
|
5
|
+
module Alchemy
|
6
|
+
# Represents a rendered picture
|
7
|
+
#
|
8
|
+
# Resizes, crops and encodes the image with imagemagick
|
9
|
+
#
|
10
|
+
class PictureVariant
|
11
|
+
extend Forwardable
|
12
|
+
|
13
|
+
include Alchemy::Logger
|
14
|
+
include Alchemy::Picture::Transformations
|
15
|
+
|
16
|
+
attr_reader :picture, :render_format
|
17
|
+
|
18
|
+
def_delegators :@picture,
|
19
|
+
:image_file,
|
20
|
+
:image_file_width,
|
21
|
+
:image_file_height,
|
22
|
+
:image_file_name,
|
23
|
+
:image_file_size
|
24
|
+
|
25
|
+
# @param [Alchemy::Picture]
|
26
|
+
#
|
27
|
+
# @param [Hash] options passed to the image processor
|
28
|
+
# @option options [Boolean] :crop Pass true to enable cropping
|
29
|
+
# @option options [String] :crop_from Coordinates to start cropping from
|
30
|
+
# @option options [String] :crop_size Size of the cropping area
|
31
|
+
# @option options [Boolean] :flatten Pass true to flatten GIFs
|
32
|
+
# @option options [String|Symbol] :format Image format to encode the image in
|
33
|
+
# @option options [Integer] :quality JPEG compress quality
|
34
|
+
# @option options [String] :size Size of resulting image in WxH
|
35
|
+
# @option options [Boolean] :upsample Pass true to upsample (grow) an image if the original size is lower than the resulting size
|
36
|
+
#
|
37
|
+
def initialize(picture, options = {})
|
38
|
+
raise ArgumentError, "Picture missing!" if picture.nil?
|
39
|
+
|
40
|
+
@picture = picture
|
41
|
+
@options = options
|
42
|
+
@render_format = options[:format] || picture.default_render_format
|
43
|
+
end
|
44
|
+
|
45
|
+
# Process a variant of picture
|
46
|
+
#
|
47
|
+
# @return [Dragonfly::Attachment|Dragonfly::Job] The processed image variant
|
48
|
+
#
|
49
|
+
def image
|
50
|
+
image = image_file
|
51
|
+
|
52
|
+
raise MissingImageFileError, "Missing image file for #{picture.inspect}" if image.nil?
|
53
|
+
|
54
|
+
image = processed_image(image, @options)
|
55
|
+
image = encoded_image(image, @options)
|
56
|
+
image
|
57
|
+
rescue MissingImageFileError, WrongImageFormatError => e
|
58
|
+
log_warning(e.message)
|
59
|
+
nil
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
# Returns the processed image dependent of size and cropping parameters
|
65
|
+
def processed_image(image, options = {})
|
66
|
+
size = options[:size]
|
67
|
+
upsample = !!options[:upsample]
|
68
|
+
|
69
|
+
return image unless size.present? && picture.has_convertible_format?
|
70
|
+
|
71
|
+
if options[:crop]
|
72
|
+
crop(size, options[:crop_from], options[:crop_size], upsample)
|
73
|
+
else
|
74
|
+
resize(size, upsample)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns the encoded image
|
79
|
+
#
|
80
|
+
# Flatten animated gifs, only if converting to a different format.
|
81
|
+
# Can be overwritten via +options[:flatten]+.
|
82
|
+
#
|
83
|
+
def encoded_image(image, options = {})
|
84
|
+
unless render_format.in?(Alchemy::Picture.allowed_filetypes)
|
85
|
+
raise WrongImageFormatError.new(picture, @render_format)
|
86
|
+
end
|
87
|
+
|
88
|
+
options = {
|
89
|
+
flatten: render_format != "gif" && picture.image_file_format == "gif",
|
90
|
+
}.with_indifferent_access.merge(options)
|
91
|
+
|
92
|
+
encoding_options = []
|
93
|
+
|
94
|
+
convert_format = render_format != picture.image_file_format.sub("jpeg", "jpg")
|
95
|
+
|
96
|
+
if render_format =~ /jpe?g/ && convert_format
|
97
|
+
quality = options[:quality] || Config.get(:output_image_jpg_quality)
|
98
|
+
encoding_options << "-quality #{quality}"
|
99
|
+
end
|
100
|
+
|
101
|
+
if options[:flatten]
|
102
|
+
encoding_options << "-flatten"
|
103
|
+
end
|
104
|
+
|
105
|
+
convertion_needed = convert_format || encoding_options.present?
|
106
|
+
|
107
|
+
if picture.has_convertible_format? && convertion_needed
|
108
|
+
image = image.encode(render_format, encoding_options.join(" "))
|
109
|
+
end
|
110
|
+
|
111
|
+
image
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
<div class="resource_info">
|
2
|
+
<div class="value">
|
3
|
+
<label>
|
4
|
+
<%= render_icon @attachment.icon_css_class, style: 'regular', size: 'lg' %>
|
5
|
+
</label>
|
6
|
+
<p><%= @attachment.file_name %></p>
|
7
|
+
</div>
|
8
|
+
<div class="value with-icon">
|
9
|
+
<label><%= Alchemy::Attachment.human_attribute_name(:url) %></label>
|
10
|
+
<p><%= @attachment.url %></p>
|
11
|
+
<a data-clipboard-text="<%= @attachment.url %>" class="icon_button--right">
|
12
|
+
<%= render_icon(:clipboard, style: 'regular') %>
|
13
|
+
</a>
|
14
|
+
</div>
|
15
|
+
<div class="value with-icon">
|
16
|
+
<label><%= Alchemy::Attachment.human_attribute_name(:download_url) %></label>
|
17
|
+
<p><%= @attachment.url %></p>
|
18
|
+
<a data-clipboard-text="<%= @attachment.url %>" class="icon_button--right">
|
19
|
+
<%= render_icon(:clipboard, style: 'regular') %>
|
20
|
+
</a>
|
21
|
+
</div>
|
22
|
+
</div>
|
23
|
+
|
24
|
+
<% case @attachment.icon_css_class %>
|
25
|
+
<% when "file-image" %>
|
26
|
+
<div class="attachment_preview_container image-preview">
|
27
|
+
<%= image_tag(@attachment.url, class: "full_width") %>
|
28
|
+
</div>
|
29
|
+
<% when "file-audio" %>
|
30
|
+
<div class="attachment_preview_container player-preview">
|
31
|
+
<%= audio_tag(@attachment.url, preload: "none", controls: true, class: "full_width") %>
|
32
|
+
</div>
|
33
|
+
<% when "file-video" %>
|
34
|
+
<div class="attachment_preview_container player-preview">
|
35
|
+
<%= video_tag(@attachment.url, preload: "metadata", controls: true, class: "full_width") %>
|
36
|
+
</div>
|
37
|
+
<% when "file-pdf" %>
|
38
|
+
<iframe src="<%= @attachment.url %>" frameborder=0 class="full-iframe">
|
39
|
+
Your browser does not support frames.
|
40
|
+
</iframe>
|
41
|
+
<% end %>
|
42
|
+
|
43
|
+
<script type="text/javascript">
|
44
|
+
$(function() {
|
45
|
+
var clipboard = new Clipboard('.icon_button--right');
|
46
|
+
clipboard.on('success', function(e) {
|
47
|
+
Alchemy.growl('<%= Alchemy.t("Copied to clipboard") %>');
|
48
|
+
e.clearSelection();
|
49
|
+
});
|
50
|
+
Alchemy.currentDialog().dialog.on('DialogClose.Alchemy', function() {
|
51
|
+
clipboard.destroy();
|
52
|
+
});
|
53
|
+
});
|
54
|
+
</script>
|
@@ -0,0 +1,53 @@
|
|
1
|
+
<div class="picture_thumbnail <%= @size %>" id="picture_<%= picture.id %>" name="<%= picture.name %>">
|
2
|
+
<span class="picture_tool select">
|
3
|
+
<%= check_box_tag "picture_ids[]", picture.id %>
|
4
|
+
</span>
|
5
|
+
<% if picture.deletable? && can?(:destroy, picture) %>
|
6
|
+
<span class="picture_tool delete">
|
7
|
+
<%= link_to_confirm_dialog(
|
8
|
+
render_icon(:minus),
|
9
|
+
Alchemy.t(:confirm_to_delete_image_from_server),
|
10
|
+
alchemy.admin_picture_path(
|
11
|
+
id: picture,
|
12
|
+
q: search_filter_params[:q],
|
13
|
+
page: params[:page],
|
14
|
+
tagged_with: search_filter_params[:tagged_with],
|
15
|
+
size: params[:size],
|
16
|
+
filter: search_filter_params[:filter]
|
17
|
+
),
|
18
|
+
{
|
19
|
+
title: Alchemy.t('Delete image')
|
20
|
+
}
|
21
|
+
) -%>
|
22
|
+
</span>
|
23
|
+
<% end %>
|
24
|
+
<% image = image_tag(
|
25
|
+
picture.url(size: preview_size(@size), flatten: true) || "alchemy/missing-image.svg",
|
26
|
+
alt: picture.name,
|
27
|
+
title: Alchemy.t(:zoom_image)
|
28
|
+
) %>
|
29
|
+
<% if can?(:edit, picture) %>
|
30
|
+
<%= link_to(
|
31
|
+
image,
|
32
|
+
alchemy.admin_picture_path(
|
33
|
+
id: picture,
|
34
|
+
q: search_filter_params[:q],
|
35
|
+
page: params[:page],
|
36
|
+
tagged_with: search_filter_params[:tagged_with],
|
37
|
+
size: params[:size],
|
38
|
+
filter: search_filter_params[:filter]
|
39
|
+
),
|
40
|
+
class: 'thumbnail_background'
|
41
|
+
) %>
|
42
|
+
<% else %>
|
43
|
+
<%= image %>
|
44
|
+
<% end %>
|
45
|
+
<span class="picture_name" title="<%= picture.name %>">
|
46
|
+
<%= picture.name %>
|
47
|
+
</span>
|
48
|
+
<div class="picture_tags">
|
49
|
+
<% picture.tag_list.each do |tag| %>
|
50
|
+
<span class="tag"><%= tag %></span>
|
51
|
+
<% end %>
|
52
|
+
</div>
|
53
|
+
</div>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<div class="picture_thumbnail assign_image_list_detail <%= size.blank? ? 'medium' : size %>" name="<%= picture_to_assign.name %>" id="picture_to_assign_<%= picture_to_assign.id %>">
|
2
|
+
<%= link_to(
|
3
|
+
image_tag(
|
4
|
+
picture_to_assign.url(size: preview_size(size), flatten: true) || "alchemy/missing-image.svg",
|
5
|
+
alt: picture_to_assign.name
|
6
|
+
),
|
7
|
+
alchemy.assign_admin_essence_pictures_path(
|
8
|
+
picture_id: picture_to_assign.id,
|
9
|
+
content_id: @content
|
10
|
+
),
|
11
|
+
remote: true,
|
12
|
+
onclick: '$(self).attr("href", "#").off("click"); return false',
|
13
|
+
method: 'put',
|
14
|
+
title: Alchemy.t(:assign_image),
|
15
|
+
class: 'thumbnail_background'
|
16
|
+
) %>
|
17
|
+
<div class="picture_name" title="<%= picture_to_assign.name %>">
|
18
|
+
<%= picture_to_assign.name %>
|
19
|
+
</div>
|
20
|
+
</div>
|
@@ -0,0 +1,43 @@
|
|
1
|
+
<div class="zoomed-picture-background">
|
2
|
+
<%= image_tag @picture.url || "alchemy/missing-image.svg" %>
|
3
|
+
</div>
|
4
|
+
|
5
|
+
<div class="picture-overlay-navigation">
|
6
|
+
<% if @previous %>
|
7
|
+
<%= link_to alchemy.admin_picture_path(
|
8
|
+
id: @previous,
|
9
|
+
q: search_filter_params[:q],
|
10
|
+
page: params[:page],
|
11
|
+
tagged_with: search_filter_params[:tagged_with],
|
12
|
+
size: params[:size],
|
13
|
+
filter: search_filter_params[:filter]
|
14
|
+
),
|
15
|
+
class: "previous-picture",
|
16
|
+
remote: true do %>
|
17
|
+
<i class="icon fas fa-angle-left fa-fw"></i>
|
18
|
+
<% end %>
|
19
|
+
<% end %>
|
20
|
+
<% if @next %>
|
21
|
+
<%= link_to alchemy.admin_picture_path(
|
22
|
+
id: @next,
|
23
|
+
q: search_filter_params[:q],
|
24
|
+
page: params[:page],
|
25
|
+
tagged_with: search_filter_params[:tagged_with],
|
26
|
+
size: params[:size],
|
27
|
+
filter: search_filter_params[:filter]
|
28
|
+
),
|
29
|
+
class: "next-picture",
|
30
|
+
remote: true do %>
|
31
|
+
<i class="icon fas fa-angle-right fa-fw"></i>
|
32
|
+
<% end %>
|
33
|
+
<% end %>
|
34
|
+
</div>
|
35
|
+
|
36
|
+
<div class="picture-details-overlay">
|
37
|
+
<%= render 'form' %>
|
38
|
+
<%= render 'infos' %>
|
39
|
+
</div>
|
40
|
+
|
41
|
+
<div class="picture-overlay-handle">
|
42
|
+
<i class="icon fas fa-angle-double-right fa-fw"></i>
|
43
|
+
</div>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<% content = local_assigns[:content] || local_assigns[:essence_file_view] %>
|
2
|
+
<%- if attachment = content.ingredient -%>
|
3
|
+
<%- html_options = local_assigns.fetch(:html_options, {}) -%>
|
4
|
+
<%= link_to(
|
5
|
+
content.essence.link_text.presence ||
|
6
|
+
content.settings_value(:link_text, local_assigns.fetch(:options, {})) ||
|
7
|
+
attachment.name,
|
8
|
+
attachment.url,
|
9
|
+
{
|
10
|
+
class: content.essence.css_class.presence,
|
11
|
+
title: content.essence.title.presence
|
12
|
+
}.merge(html_options)
|
13
|
+
) -%>
|
14
|
+
<%- end -%>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class CreateAlchemyPictureThumbs < ActiveRecord::Migration[5.0]
|
4
|
+
def change
|
5
|
+
create_table :alchemy_picture_thumbs do |t|
|
6
|
+
t.references :picture, null: false, foreign_key: { to_table: :alchemy_pictures }
|
7
|
+
t.string :signature, null: false
|
8
|
+
t.text :uid, null: false
|
9
|
+
end
|
10
|
+
add_index :alchemy_picture_thumbs, :signature, unique: true
|
11
|
+
end
|
12
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alchemy-dragonfly-s3
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.0.
|
4
|
+
version: 5.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas von Deyen
|
@@ -123,6 +123,21 @@ extra_rdoc_files: []
|
|
123
123
|
files:
|
124
124
|
- MIT-LICENSE
|
125
125
|
- README.md
|
126
|
+
- app/assets/config/alchemy_dragonfly_s3_manifest.js
|
127
|
+
- app/assets/images/alchemy/missing-image.svg
|
128
|
+
- app/models/alchemy/attachment/s3_url.rb
|
129
|
+
- app/models/alchemy/picture/s3_url.rb
|
130
|
+
- app/models/alchemy/picture_thumb.rb
|
131
|
+
- app/models/alchemy/picture_thumb/create.rb
|
132
|
+
- app/models/alchemy/picture_thumb/signature.rb
|
133
|
+
- app/models/alchemy/picture_thumb/uid.rb
|
134
|
+
- app/models/alchemy/picture_variant.rb
|
135
|
+
- app/views/alchemy/admin/attachments/show.html.erb
|
136
|
+
- app/views/alchemy/admin/pictures/_picture.html.erb
|
137
|
+
- app/views/alchemy/admin/pictures/_picture_to_assign.html.erb
|
138
|
+
- app/views/alchemy/admin/pictures/show.html.erb
|
139
|
+
- app/views/alchemy/essences/_essence_file_view.html.erb
|
140
|
+
- db/migrate/1_create_alchemy_picture_thumbs.rb
|
126
141
|
- lib/alchemy-dragonfly-s3.rb
|
127
142
|
- lib/alchemy/attachment_monkey_patch.rb
|
128
143
|
- lib/alchemy/dragonfly/s3/engine.rb
|