card-mod-carrierwave 0.11.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.
@@ -0,0 +1,85 @@
1
+ # action id of the cached upload
2
+ attr_accessor :action_id_of_cached_upload
3
+
4
+ def actionable?
5
+ super || preliminary_upload?
6
+ end
7
+
8
+ event :prepare_attachment, :prepare_to_validate, on: :save, when: :preliminary_upload? do
9
+ save_original_filename # save original filename as comment in action
10
+ write_identifier # set db_content
11
+ # (needs original filename to determine extension)
12
+ store_attachment!
13
+ store_card_changes
14
+ # finalize_action # create Card::Change entry for db_content
15
+
16
+ card_id = new_card? ? upload_cache_card.id : id
17
+ @current_action.update! draft: true, card_id: card_id
18
+ success << {
19
+ target: (new_card? ? upload_cache_card : self),
20
+ type: type_name,
21
+ view: "preview_editor",
22
+ rev_id: current_action.id
23
+ }
24
+ abort :success
25
+ end
26
+
27
+ event :assign_attachment_on_create, :initialize,
28
+ after: :assign_action, on: :create, when: :save_preliminary_upload? do
29
+ return unless (action = Card::Action.fetch(@action_id_of_cached_upload))
30
+ upload_cache_card.selected_action_id = action.id
31
+ upload_cache_card.select_file_revision
32
+ assign_attachment upload_cache_card.attachment.file, action.comment
33
+ end
34
+
35
+ event :assign_attachment_on_update, :initialize,
36
+ after: :assign_action, on: :update, when: :save_preliminary_upload? do
37
+ return unless (action = Card::Action.fetch(@action_id_of_cached_upload))
38
+ uploaded_file = with_selected_action_id(action.id) { attachment.file }
39
+ assign_attachment uploaded_file, action.comment
40
+ end
41
+
42
+ def assign_attachment file, original_filename
43
+ send "#{attachment_name}=", file
44
+ write_identifier
45
+ @current_action&.update! comment: original_filename
46
+ end
47
+
48
+ event :delete_cached_upload_file_on_create, :integrate,
49
+ on: :create, when: :save_preliminary_upload? do
50
+ return unless (action = Card::Action.fetch(@action_id_of_cached_upload))
51
+ upload_cache_card.delete_files_for_action action
52
+ action.delete
53
+ end
54
+
55
+ # at some point uploaded files of canceled file card creation
56
+ # should be deleted. We do this when ever an new file is created.
57
+ event :clear_draft_files, :integrate_with_delay, priority: 100, on: :create do
58
+ Card.delete_tmp_files_of_cached_uploads
59
+ end
60
+
61
+ event :delete_cached_upload_file_on_update, :integrate,
62
+ on: :update, when: :save_preliminary_upload? do
63
+ return unless (action = Card::Action.fetch(@action_id_of_cached_upload))
64
+ delete_files_for_action action
65
+ action.delete
66
+ end
67
+
68
+ # used for uploads for new cards until the new card is created
69
+ def upload_cache_card
70
+ cache_card_codename = "new_#{attachment_name}"
71
+ @upload_cache_card ||= Card::Codename.card(cache_card_codename) { Card[:new_file] }
72
+ end
73
+
74
+ def preliminary_upload?
75
+ Card::Env && Card::Env.params[:attachment_upload]
76
+ end
77
+
78
+ def save_preliminary_upload?
79
+ @action_id_of_cached_upload.present?
80
+ end
81
+
82
+ # place for files if card doesn't have an id yet
83
+ def tmp_upload_dir _action_id=nil
84
+ "#{files_base_dir}/#{upload_cache_card.id}"
85
+ end
@@ -0,0 +1,3 @@
1
+ def no_upload?
2
+ web? || storage_type_from_config == :web
3
+ end
@@ -0,0 +1,41 @@
1
+ module ClassMethods
2
+ def update_all_storage_locations
3
+ Card.search(type_id: ["in", Card::FileID, Card::ImageID])
4
+ .each(&:update_storage_location!)
5
+ end
6
+
7
+ def delete_tmp_files_of_cached_uploads
8
+ cards_with_disposable_attachments do |card, action|
9
+ card.delete_files_for_action action
10
+ action.delete
11
+ end
12
+ end
13
+
14
+ def cards_with_disposable_attachments
15
+ draft_actions_with_attachment.each do |action|
16
+ # we don't want to delete uploads in progress
17
+ next unless old_enough?(action.created_at) && (card = action.card)
18
+ # we can't delete attachments we don't have write access to
19
+ next if card.read_only?
20
+
21
+ yield card, action
22
+ end
23
+ end
24
+
25
+ def old_enough? time, expiration_time=5.day.to_i
26
+ Time.now - time > expiration_time
27
+ end
28
+
29
+ def draft_actions_with_attachment
30
+ Card::Action.find_by_sql(
31
+ "SELECT * FROM card_actions "\
32
+ "INNER JOIN cards ON card_actions.card_id = cards.id "\
33
+ "WHERE cards.type_id IN (#{Card::FileID}, #{Card::ImageID}) "\
34
+ "AND card_actions.draft = true"
35
+ )
36
+ end
37
+
38
+ def count_cards_with_attachment
39
+ Card.search type_id: ["in", Card::FileID, Card::ImageID], return: :count
40
+ end
41
+ end
@@ -0,0 +1,23 @@
1
+ add_to_basket(
2
+ :tasks,
3
+ name: :update_file_storage_locations,
4
+ execute_policy: -> { Card.update_all_storage_locations },
5
+ stats: {
6
+ title: "cards with attachment",
7
+ count: -> { Card.count_cards_with_attachment }
8
+ # link_text: "update storage locations",
9
+ # task: "update_file_storage_locations"
10
+ }
11
+ )
12
+
13
+ add_to_basket(
14
+ :tasks,
15
+ name: :delete_upload_tmp_files,
16
+ execute_policy: -> { Card.delete_tmp_files_of_cached_uploads },
17
+ stats: {
18
+ title: "tmp files of canceled uploads",
19
+ count: -> { ::Card.draft_actions_with_attachment },
20
+ link_text: "delete tmp files",
21
+ task: "delete_tmp_files_of_cached_uploads"
22
+ }
23
+ )
@@ -0,0 +1,16 @@
1
+ format :html do
2
+ view :source do
3
+ source = card.type_id == Card::ImageID ? super() : nil
4
+ source.present? ? source : nest(:logo, view: :source, size: voo.size)
5
+ end
6
+
7
+ view :link_tag, perms: :none do
8
+ return unless (source = render :source, size: :small)
9
+ tag :link, rel: "shortcut icon", href: source
10
+ end
11
+
12
+ def raw_help_text
13
+ "A favicon (or shortcut icon) is a small image used by browsers to help identify "\
14
+ "your website. [[http://www.decko.org/favicon|How to customize your favicon]]"
15
+ end
16
+ end
@@ -0,0 +1,13 @@
1
+ format :html do
2
+ view :source, cache: :never do
3
+ super()
4
+ end
5
+
6
+ view :core, cache: :never do
7
+ super()
8
+ end
9
+
10
+ view :input, cache: :never do
11
+ super()
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ format :html do
2
+ view :source, cache: :never do
3
+ super()
4
+ end
5
+
6
+ view :core, cache: :never do
7
+ super()
8
+ end
9
+
10
+ view :input, cache: :never do
11
+ super()
12
+ end
13
+ end
@@ -0,0 +1,116 @@
1
+ attachment :file, uploader: CarrierWave::FileCardUploader
2
+
3
+ module SelectedAction
4
+ def select_action_by_params params
5
+ # skip action table lookups for current revision
6
+ rev_id = params[:rev_id]
7
+ super unless rev_id && rev_id == last_content_action_id
8
+ end
9
+
10
+ def last_content_action_id
11
+ return super if temporary_storage_type_change?
12
+ # find action id from content (saves lookups)
13
+ db_content.to_s.split(%r{[/\.]})[-2]
14
+ end
15
+ end
16
+ include SelectedAction
17
+
18
+ format do
19
+ view :source do
20
+ file = card.attachment
21
+ return "" unless file.valid?
22
+ contextualize_path file.url
23
+ end
24
+
25
+ view :core do
26
+ handle_source do |source|
27
+ card_url source
28
+ end
29
+ end
30
+
31
+ def short_content
32
+ number_to_human_size card.attachment.size
33
+ end
34
+
35
+ def handle_source
36
+ source = _render_source
37
+ return "" if source.blank?
38
+ block_given? ? yield(source) : source
39
+ rescue => e
40
+ Rails.logger.info "Error with file source: #{e.message}"
41
+ tr :file_error
42
+ end
43
+
44
+ def selected_version
45
+ card.attachment
46
+ end
47
+ end
48
+
49
+ format :file do
50
+ # NOCACHE because returns send_file args. not in love with this...
51
+ view :core, cache: :never do
52
+ # this means we only support known formats. dislike.
53
+ attachment_format = card.attachment_format(params[:format])
54
+ return _render_not_found unless attachment_format
55
+ return card.format(:html).render_core if card.remote_storage?
56
+ set_response_headers
57
+ args_for_send_file
58
+ end
59
+
60
+ def args_for_send_file
61
+ file = selected_version
62
+ [file.path, { type: file.content_type,
63
+ filename: "#{card.name.safe_key}#{file.extension}",
64
+ x_sendfile: true,
65
+ disposition: (params[:format] == "file" ? "attachment" : "inline") }]
66
+ end
67
+
68
+ def set_response_headers
69
+ return unless params[:explicit_file] && (response = controller&.response)
70
+ response.headers["Expires"] = 1.year.from_now.httpdate
71
+ # currently using default "private", because proxy servers could block
72
+ # needed permission checks
73
+ # r.headers["Cache-Control"] = "public"
74
+ end
75
+ end
76
+
77
+ format :html do
78
+ view :core do
79
+ handle_source do |source|
80
+ "<a href=\"#{source}\">#{tr :download, title: title_in_context(voo.title)}</a>"
81
+ end
82
+ end
83
+
84
+ view :input do
85
+ if card.no_upload?
86
+ text_field :content, class: "d0-card-content"
87
+ else
88
+ haml :file_chooser, action_text: file_chooser_action_text
89
+ end
90
+ end
91
+
92
+ view :preview_editor, unknown: true, cache: :never do
93
+ haml :preview_editor
94
+ end
95
+
96
+ def file_chooser_action_text
97
+ action = card.new_card? ? "Add" : "Replace"
98
+ "#{action} #{humanized_attachment_name}..."
99
+ end
100
+
101
+ def humanized_attachment_name
102
+ card.attachment_name.to_s.humanize
103
+ end
104
+
105
+ def preview
106
+ ""
107
+ end
108
+
109
+ def cached_upload_card_name
110
+ Card::Env.params[:attachment_upload].gsub(/\[\w+\]$/, "[action_id_of_cached_upload]")
111
+ end
112
+
113
+ def preview_editor_delete_text
114
+ tr :delete
115
+ end
116
+ end
@@ -0,0 +1,15 @@
1
+ .choose-file
2
+ = preview
3
+ %span.btn.btn-secondary.fileinput-button
4
+ = icon_tag "cloud_upload"
5
+ %span<
6
+ = action_text
7
+ %input.file-upload.slotter.form-control{ id: "card_#{card.type_code}",
8
+ name: "card[#{card.type_code}]",
9
+ type: "file" }
10
+ = hidden_field_tag "attachment_type_id", card.type_id
11
+ = hidden_field card.attachment_name, class: "attachment_card_name", value: ""
12
+ = hidden_field_tag 'file_card_name', card.name.url_key
13
+ #progress.progress.mb-2{ style: "display: none;" }
14
+ .progress-bar.progress-bar-success{ style: "width: 0%;" }
15
+ .chosen-file
@@ -0,0 +1,19 @@
1
+ .chosen-file
2
+ %input{ name: cached_upload_card_name, type: "hidden", value: card.selected_action_id }
3
+ %table.table.table-striped{ role: "presentation" }
4
+ %tbody.files
5
+ %tr.template-download.fade.show
6
+ %td
7
+ %span.preview
8
+ = preview
9
+ %td
10
+ %p.name
11
+ = card.original_filename
12
+ %td
13
+ %span.size
14
+ = number_to_human_size card.attachment.size
15
+ %td.float-right
16
+ %button.btn.btn-danger.delete.cancel-upload{ "data-type": "DELETE" }
17
+ = icon_tag :delete
18
+ %span
19
+ = preview_editor_delete_text
@@ -0,0 +1,101 @@
1
+ attachment :image, uploader: CarrierWave::ImageCardUploader
2
+
3
+ include File::SelectedAction
4
+
5
+ def create_versions? new_file
6
+ new_file.extension != "svg"
7
+ end
8
+
9
+ def svg?
10
+ image&.extension == ".svg"
11
+ end
12
+
13
+ format do
14
+ include File::Format
15
+
16
+ view :one_line_content do
17
+ _render_core size: :icon
18
+ end
19
+
20
+ def short_content
21
+ render_core size: :icon
22
+ end
23
+
24
+ view :source do
25
+ return card.content if card.web?
26
+ image = selected_version
27
+ return "" unless image.valid?
28
+ contextualize_path image.url
29
+ end
30
+
31
+ def selected_version
32
+ size = determine_image_size
33
+ if size && size != :original
34
+ card.image.versions[size]
35
+ else
36
+ card.image
37
+ end
38
+ end
39
+
40
+ def handle_source
41
+ super
42
+ end
43
+
44
+ def closed_size
45
+ :icon
46
+ end
47
+
48
+ def main_size
49
+ :large
50
+ end
51
+
52
+ def default_size
53
+ :medium
54
+ end
55
+
56
+ def determine_image_size
57
+ voo.size =
58
+ case
59
+ when nest_mode == :closed then closed_size
60
+ when voo.size.present? then voo.size.to_sym
61
+ when main? then main_size
62
+ else default_size
63
+ end
64
+ voo.size = :original if voo.size == :full
65
+ voo.size
66
+ end
67
+
68
+ view :inline do
69
+ _render_core
70
+ end
71
+ end
72
+
73
+ format :email_html do
74
+ view :inline, cache: :never do
75
+ handle_source do |source|
76
+ return source unless (mail = inherit :active_mail) &&
77
+ ::File.exist?(path = selected_version.path)
78
+ url = attach_image mail, path
79
+ image_tag url
80
+ end
81
+ end
82
+
83
+ def attach_image mail, path
84
+ mail.attachments.inline[path] = ::File.read path
85
+ mail.attachments[path].url
86
+ end
87
+ end
88
+
89
+ format :css do
90
+ view :core do
91
+ handle_source
92
+ end
93
+
94
+ view :content do # why is this necessary?
95
+ render_core
96
+ end
97
+ end
98
+
99
+ format :file do
100
+ include File::FileFormat
101
+ end