Class: Crm::UploadCardComponent

Inherits:
ViewComponent::Base
  • Object
show all
Defined in:
app/components/crm/upload_card_component.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(upload:, context_object: nil, context_class: nil, controller_path: nil, disable_delete: false, parent_form_id: nil) ⇒ UploadCardComponent

Returns a new instance of UploadCardComponent.

Raises:

  • (ArgumentError)


6
7
8
9
10
11
12
13
14
15
16
# File 'app/components/crm/upload_card_component.rb', line 6

def initialize(upload:, context_object: nil, context_class: nil, controller_path: nil, disable_delete: false, parent_form_id: nil)
  super()
  @upload = upload
  @context_object = context_object
  @context_class = context_class || context_object&.class
  raise ArgumentError, 'context_class is required when context_object is nil' if @context_class.nil?

  @controller_path = controller_path || (@context_class.is_a?(Class) ? @context_class.name.tableize : @context_class.to_s.tableize)
  @disable_delete = disable_delete
  @parent_form_id = parent_form_id
end

Instance Attribute Details

#context_classObject (readonly)

Returns the value of attribute context_class.



4
5
6
# File 'app/components/crm/upload_card_component.rb', line 4

def context_class
  @context_class
end

#context_objectObject (readonly)

Returns the value of attribute context_object.



4
5
6
# File 'app/components/crm/upload_card_component.rb', line 4

def context_object
  @context_object
end

#controller_pathObject (readonly)

Returns the value of attribute controller_path.



4
5
6
# File 'app/components/crm/upload_card_component.rb', line 4

def controller_path
  @controller_path
end

#disable_deleteObject (readonly)

Returns the value of attribute disable_delete.



4
5
6
# File 'app/components/crm/upload_card_component.rb', line 4

def disable_delete
  @disable_delete
end

#parent_form_idObject (readonly)

Returns the value of attribute parent_form_id.



4
5
6
# File 'app/components/crm/upload_card_component.rb', line 4

def parent_form_id
  @parent_form_id
end

#uploadObject (readonly)

Returns the value of attribute upload.



4
5
6
# File 'app/components/crm/upload_card_component.rb', line 4

def upload
  @upload
end

Instance Method Details

#attachment_nameObject



53
54
55
# File 'app/components/crm/upload_card_component.rb', line 53

def attachment_name
  helpers.attachment_name(upload)
end


67
68
69
# File 'app/components/crm/upload_card_component.rb', line 67

def download_link
  helpers.upload_path(upload)
end

#fancybox_groupObject



84
85
86
87
# File 'app/components/crm/upload_card_component.rb', line 84

def fancybox_group
  # Unique group per upload to prevent gallery behavior
  "upload-#{upload.id}"
end

#fancybox_typeObject



71
72
73
74
75
76
77
78
79
80
81
82
# File 'app/components/crm/upload_card_component.rb', line 71

def fancybox_type
  # Use cached mime_type from database (fast) instead of attachment.mime_type
  # which can trigger network calls
  mime = upload.attachment_mime_type || upload.mime_type
  if mime&.start_with?('image')
    'image'
  elsif mime == 'application/pdf'
    'pdf'
  else
    'iframe'
  end
end

#file_sizeObject



57
58
59
# File 'app/components/crm/upload_card_component.rb', line 57

def file_size
  helpers.number_to_human_size(upload.attachment_size)
end

#hidden_field_tag_htmlObject



18
19
20
21
22
23
24
25
26
27
28
29
# File 'app/components/crm/upload_card_component.rb', line 18

def hidden_field_tag_html
  # Handle both Class and String inputs for context_class
  class_name = context_class.is_a?(String) ? context_class : context_class.name
  param_name = "#{class_name.tableize.singularize}[upload_ids][]"

  # If parent_form_id is specified, associate the hidden field with that form
  if parent_form_id.present?
    helpers.hidden_field_tag param_name, upload.id, form: parent_form_id
  else
    helpers.hidden_field_tag param_name, upload.id
  end
end

#image_urlObject



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'app/components/crm/upload_card_component.rb', line 31

def image_url
  # For publications: use ImageKit CDN cover image (fast, no network calls)
  # For images: use presigned URL directly (browser scales, no Dragonfly processing)
  # For PDFs: use Dragonfly/libvips generated thumbnail
  # For other files: no thumbnail
  if upload.publication
    upload.publication.cover_image_url(width: 400)
  elsif upload.is_image?
    # Use presigned URL directly - browser can display and scale the image
    # This avoids slow Dragonfly thumbnail generation
    upload.presigned_url(expires_in: 6.days)
  elsif upload.is_pdf?
    # Use Dragonfly libvips for PDF thumbnail generation (first page)
    upload.thumbnail_url(dimensions: '300x300>')
  else
    nil # Skip for non-thumbnailable files (e.g., .doc, .xls)
  end
rescue StandardError => e
  Rails.logger.debug { "[UploadCardComponent] image_url error: #{e.message}" }
  nil
end

#preview_urlObject



61
62
63
64
65
# File 'app/components/crm/upload_card_component.rb', line 61

def preview_url
  # Use local presigned URL generation (fast, no S3 network call)
  # No fallback to slow remote_url - if presigned fails, link will be broken but page loads fast
  upload.presigned_url(expires_in: 6.days)
end

#remove_buttonObject



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'app/components/crm/upload_card_component.rb', line 89

def remove_button
  # Use controller_path explicitly for route generation
  # This handles irregular controllers (e.g., article_trainings vs Article model)
  remove_params = {
    upload_id: upload.id,
    context_object_id: context_object&.id || 0,
    context_class: context_class.name,
    format: :turbo_stream
  }

  # Use url_for with explicit controller_path for route generation
  remove_url = helpers.url_for(controller: controller_path,
                                action: :remove_attachment,
                                **remove_params,
                                only_path: true)

  helpers.link_to(
    remove_url,
    class: 'btn btn-sm btn-outline-danger w-100',
    data: {
      turbo_method: :delete,
      turbo_stream: true,
      turbo_confirm: 'Are you sure you want to delete this attachment?'
    }
  ) do
    fa_icon('trash', text: 'Remove')
  end
end