importable_attachments 0.0.13

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. data/.gitignore +24 -0
  2. data/.ruby-gemset +1 -0
  3. data/.ruby-version +1 -0
  4. data/Gemfile +38 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.md +8 -0
  7. data/README.rdoc +3 -0
  8. data/Rakefile +29 -0
  9. data/app/assets/images/importable_attachments/.gitkeep +0 -0
  10. data/app/assets/images/importable_attachments/buttons/.htaccess +5 -0
  11. data/app/assets/images/importable_attachments/buttons/download_32.png +0 -0
  12. data/app/assets/images/importable_attachments/buttons/upload_32.png +0 -0
  13. data/app/assets/javascripts/importable_attachments/application.js +14 -0
  14. data/app/assets/javascripts/importable_attachments/attachments.coffee +41 -0
  15. data/app/assets/stylesheets/importable_attachments/application.css +14 -0
  16. data/app/assets/stylesheets/importable_attachments/attachments.css +4 -0
  17. data/app/assets/stylesheets/scaffold.css +56 -0
  18. data/app/controllers/importable_attachments/application_controller.rb +4 -0
  19. data/app/controllers/importable_attachments/attachments_controller.rb +190 -0
  20. data/app/controllers/importable_attachments/versions_controller.rb +87 -0
  21. data/app/helpers/importable_attachments/application_helper.rb +4 -0
  22. data/app/models/attachment.rb +24 -0
  23. data/app/models/importable_attachments/attachment.rb +143 -0
  24. data/app/models/importable_attachments/version.rb +50 -0
  25. data/app/validators/existing_class_validator.rb +17 -0
  26. data/app/validators/importable_attachments/csv_validator.rb +36 -0
  27. data/app/validators/importable_attachments/excel.rb +18 -0
  28. data/app/validators/importable_attachments/excel_validator.rb +18 -0
  29. data/app/views/importable_attachments/attachments/_attachment.html.haml +9 -0
  30. data/app/views/importable_attachments/attachments/_form.html.haml +22 -0
  31. data/app/views/importable_attachments/attachments/_nested_form.html.haml +20 -0
  32. data/app/views/importable_attachments/attachments/edit.html.haml +39 -0
  33. data/app/views/importable_attachments/attachments/index.html.haml +23 -0
  34. data/app/views/importable_attachments/attachments/index.xml.builder +23 -0
  35. data/app/views/importable_attachments/attachments/new.html.haml +10 -0
  36. data/app/views/importable_attachments/attachments/show.html.haml +43 -0
  37. data/app/views/importable_attachments/versions/_form.html.haml +25 -0
  38. data/app/views/importable_attachments/versions/edit.html.haml +7 -0
  39. data/app/views/importable_attachments/versions/index.html.haml +27 -0
  40. data/app/views/importable_attachments/versions/new.html.haml +5 -0
  41. data/app/views/importable_attachments/versions/show.html.haml +21 -0
  42. data/app/views/layouts/_version.html.haml +33 -0
  43. data/app/views/layouts/importable_attachments/application.html.haml +48 -0
  44. data/bin/set_lc.sh +47 -0
  45. data/config/database.yml +25 -0
  46. data/config/features/attachments.rb +8 -0
  47. data/config/features/mark_requirements.rb +3 -0
  48. data/config/features/smarter_dates.rb +3 -0
  49. data/config/features/versioning.rb +7 -0
  50. data/config/initializers/0_configuration.rb +7 -0
  51. data/config/initializers/formtastic.rb +76 -0
  52. data/config/initializers/generators.rb +10 -0
  53. data/config/initializers/paperclip.rb +27 -0
  54. data/config/locales/responders.en.yml +10 -0
  55. data/config/routes.rb +11 -0
  56. data/db/migrate/001_create_importable_attachments_versions.rb +14 -0
  57. data/db/migrate/100_create_attachments.rb +19 -0
  58. data/importable_attachments.gemspec +81 -0
  59. data/lib/generators/importable_attachments/install_generator.rb +66 -0
  60. data/lib/generators/importable_attachments/templates/features/attachments.rb.erb +7 -0
  61. data/lib/generators/importable_attachments/templates/features/versioning.rb +7 -0
  62. data/lib/generators/importable_attachments/templates/initializers/paperclip.rb +27 -0
  63. data/lib/importable_attachments/base.rb +108 -0
  64. data/lib/importable_attachments/blueprints.rb +9 -0
  65. data/lib/importable_attachments/engine.rb +8 -0
  66. data/lib/importable_attachments/importers/csv.rb +208 -0
  67. data/lib/importable_attachments/importers/excel.rb +37 -0
  68. data/lib/importable_attachments/importers.rb +7 -0
  69. data/lib/importable_attachments/version.rb +3 -0
  70. data/lib/importable_attachments.rb +9 -0
  71. data/lib/paperclip_processors/save_upload.rb +33 -0
  72. data/lib/tasks/importable_attachments_tasks.rake +4 -0
  73. data/script/rails +8 -0
  74. data/spec/attachments/books.csv +6 -0
  75. data/spec/attachments/books.txt +6 -0
  76. data/spec/attachments/books2.csv +4 -0
  77. data/spec/attachments/empty.csv +0 -0
  78. data/spec/attachments/failed_instances.csv +3 -0
  79. data/spec/attachments/invalid_headers.csv +3 -0
  80. data/spec/attachments/just_headers.csv +1 -0
  81. data/spec/attachments/mostly_empty.csv +2 -0
  82. data/spec/attachments/mostly_empty_copy.xls +0 -0
  83. data/spec/controllers/importable_attachments/attachments_controller_spec.rb +236 -0
  84. data/spec/controllers/importable_attachments/versions_controller_spec.rb +158 -0
  85. data/spec/dummy/README.rdoc +261 -0
  86. data/spec/dummy/Rakefile +7 -0
  87. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  88. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  89. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  90. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  91. data/spec/dummy/app/mailers/.gitkeep +0 -0
  92. data/spec/dummy/app/models/.gitkeep +0 -0
  93. data/spec/dummy/app/models/book.rb +13 -0
  94. data/spec/dummy/app/models/library.rb +54 -0
  95. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  96. data/spec/dummy/config/application.rb +65 -0
  97. data/spec/dummy/config/boot.rb +10 -0
  98. data/spec/dummy/config/database.yml +25 -0
  99. data/spec/dummy/config/environment.rb +5 -0
  100. data/spec/dummy/config/environments/development.rb +37 -0
  101. data/spec/dummy/config/environments/production.rb +67 -0
  102. data/spec/dummy/config/environments/test.rb +37 -0
  103. data/spec/dummy/config/initializers/0_configuration.rb +7 -0
  104. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  105. data/spec/dummy/config/initializers/inflections.rb +15 -0
  106. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  107. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  108. data/spec/dummy/config/initializers/session_store.rb +8 -0
  109. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  110. data/spec/dummy/config/locales/en.yml +5 -0
  111. data/spec/dummy/config/routes.rb +4 -0
  112. data/spec/dummy/config.ru +4 -0
  113. data/spec/dummy/db/migrate/101_create_libraries.rb +10 -0
  114. data/spec/dummy/db/migrate/102_create_books.rb +12 -0
  115. data/spec/dummy/db/schema.rb +57 -0
  116. data/spec/dummy/features/person_uploads_generic_file.feature +11 -0
  117. data/spec/dummy/features/step_definitions/person_uploads_generic_file_steps.rb +11 -0
  118. data/spec/dummy/features/step_definitions/web_steps.rb +211 -0
  119. data/spec/dummy/features/support/capybara.rb +6 -0
  120. data/spec/dummy/features/support/database_cleaner.rb +26 -0
  121. data/spec/dummy/features/support/developer_helpers.rb +47 -0
  122. data/spec/dummy/features/support/env.rb +53 -0
  123. data/spec/dummy/features/support/paths.rb +33 -0
  124. data/spec/dummy/features/support/poltergeist.rb +1 -0
  125. data/spec/dummy/features/support/selectors.rb +39 -0
  126. data/spec/dummy/features/support/transactional_fixtures.rb +14 -0
  127. data/spec/dummy/lib/assets/.gitkeep +0 -0
  128. data/spec/dummy/log/.gitkeep +0 -0
  129. data/spec/dummy/public/404.html +38 -0
  130. data/spec/dummy/public/422.html +38 -0
  131. data/spec/dummy/public/500.html +36 -0
  132. data/spec/dummy/public/favicon.ico +0 -0
  133. data/spec/dummy/script/rails +6 -0
  134. data/spec/dummy/spec/support/.gitkeep +0 -0
  135. data/spec/dummy/spec/support/paperclip.rb +1 -0
  136. data/spec/models/importable_attachments/attachment_spec.rb +177 -0
  137. data/spec/models/importable_attachments/library_spec.rb +155 -0
  138. data/spec/models/importable_attachments/version_spec.rb +25 -0
  139. data/spec/routing/importable_attachments/versions_routing_spec.rb +43 -0
  140. data/spec/spec.opts +5 -0
  141. data/spec/spec_helper.rb +30 -0
  142. metadata +737 -0
@@ -0,0 +1,143 @@
1
+ require 'filemagic'
2
+ require 'mime/types'
3
+ require 'paper_trail'
4
+ require 'paperclip'
5
+ require 'smarter_dates'
6
+ #require File.join(File.dirname(__FILE__), '../..', 'config/initializers/0_configuration')
7
+
8
+ # An attachment represents a file within the system.
9
+ module ImportableAttachments
10
+ class Attachment < ActiveRecord::Base
11
+ self.abstract_class = true
12
+ self.table_name = :importable_attachments_attachments
13
+
14
+ include SmarterDates if ::Configuration.for('smarter_dates').enabled
15
+ include Rails::MarkRequirements if ::Configuration.for('mark_requirements').enabled
16
+
17
+ if ::Configuration.for('versioning').enabled
18
+ has_paper_trail ignore: [:updated_at], class_name: 'ImportableAttachments::Version'
19
+ end
20
+
21
+ # url for client downloadable content
22
+ if ::Configuration.for('attachments').enabled
23
+ include Paperclip::Glue
24
+ if ::Configuration.for('attachments').include_revision_in_filename
25
+ CONTENT_URL = ::Configuration.for('versioned').url
26
+ CONTENT_PATH = ::Configuration.for('versioned').path
27
+ else
28
+ CONTENT_URL = ::Configuration.for('attachments').url
29
+ CONTENT_PATH = ::Configuration.for('attachments').path
30
+ end
31
+
32
+ has_attached_file :io_stream, :url => CONTENT_URL, :path => CONTENT_PATH,
33
+ :styles => {original: {io_stream_attr: :attach}},
34
+ :processors => [:save_upload]
35
+ end
36
+
37
+ # --------------------------------------------------------------------------
38
+ # define: attributes and relationships
39
+ belongs_to :attachable, :polymorphic => true
40
+
41
+ # --------------------------------------------------------------------------
42
+ # define: aliases and delegations
43
+ delegate :url, :to => :io_stream, :prefix => true
44
+
45
+ # --------------------------------------------------------------------------
46
+ # define: DTD i.e. validations
47
+
48
+ # NOTE: to save nested-model forms, new instances must be valid. Therefore,
49
+ # attachable_id = nil must be valid when attachable is != nil
50
+ validates :attachable_id, :if => :attachable_id?,
51
+ :numericality => {only_integer: true, greater_than: 0}
52
+
53
+ validates :attachable_type, alpha_numeric: {punctuation: true}, existing_class: true, :if => :attachable_type?
54
+
55
+ validates_attachment :io_stream, :presence => true,
56
+ :size => {greater_than: 0}
57
+
58
+ validates :io_stream_file_name, :presence => true,
59
+ :alpha_numeric => {punctuation: true}
60
+
61
+ validates :io_stream_file_size, :presence => true,
62
+ :numericality => {only_integer: true, greater_than_or_equal_to: 0}
63
+
64
+ validates :io_stream_content_type, :presence => true,
65
+ :alpha_numeric => {punctuation: true}
66
+
67
+ validates :io_stream_updated_at, :chronic_parsable => true,
68
+ :if => :io_stream_updated_at?
69
+
70
+ # --------------------------------------------------------------------------
71
+ # define: scopes
72
+
73
+ attr_accessible :attachable_id, :attachable_type
74
+ attr_accessible :io_stream
75
+ attr_accessible :io_stream_file_name, :io_stream_content_type, :io_stream_file_size,
76
+ :io_stream_updated_at
77
+
78
+ # --------------------------------------------------------------------------
79
+ # define: behaviors
80
+
81
+ # :call-seq:
82
+ # revision_number
83
+ #
84
+ # yields an integer representing the version-index
85
+ #
86
+ # NOTE: paper_trail manages version-tracking automatically
87
+
88
+ def revision_number
89
+ ver = version
90
+ case
91
+ when live? then
92
+ versions.count
93
+ when ver then
94
+ ver.index
95
+ else
96
+ 0
97
+ end
98
+ end
99
+
100
+ # :call-seq:
101
+ # io_stream_mime_type
102
+ #
103
+ # yields the files MIME::Type
104
+
105
+ def io_stream_mime_type
106
+ mime = new_record? ? io_stream.content_type : magic_mime_type
107
+ MIME::Types[mime].first
108
+ end
109
+
110
+ # :call-seq:
111
+ # magic_mime_type
112
+ #
113
+ # yields a saved attachments mime_type according to libmagic
114
+
115
+ def magic_mime_type
116
+ return if new_record?
117
+ return unless File.exists? io_stream.path
118
+ FileMagic.mime.file(io_stream.path).split(/;\s*/).first
119
+ end
120
+
121
+ end
122
+ end
123
+
124
+ # == Schema Information
125
+ #
126
+ # Table name: attachments
127
+ #
128
+ # id :integer not null, primary key
129
+ # attachable_type :string(255)
130
+ # attachable_id :string(255)
131
+ # io_stream_file_name :string(255)
132
+ # io_stream_content_type :string(255)
133
+ # io_stream_file_size :integer
134
+ # io_stream_updated_at :datetime
135
+ # created_at :datetime not null
136
+ # updated_at :datetime not null
137
+ #
138
+ # Indexes
139
+ #
140
+ # idx_importable_attachments_on_attachable_type_and_id (attachable_type,attachable_id)
141
+ # index_attachments_on_io_stream_file_name (io_stream_file_name)
142
+ #
143
+
@@ -0,0 +1,50 @@
1
+ # versions are managed by the paper_trail gem... providing a history of
2
+ # instance-deltas
3
+ module ImportableAttachments
4
+ class Version < ActiveRecord::Base
5
+ self.abstract_class = true
6
+ self.table_name = :importable_attachments_versions
7
+ attr_accessible :event, :item_id, :item_type, :object, :object_changes, :whodunnit
8
+
9
+ include SmarterDates if ::Configuration.for('smarter_dates').enabled
10
+ include Rails::MarkRequirements if ::Configuration.for('mark_requirements').enabled
11
+
12
+ belongs_to :item, polymorphic: true
13
+
14
+ # NOTE: to save nested-model forms, new instances must be valid. Therefore,
15
+ # attachable_id = nil must be valid when attachable is != nil
16
+ #validates :item_id, if: :item_id?, numericality: {only_integer: true, greater_than: 0}
17
+ validates :item_id, alpha_numeric: {punctuation: true}, if: :item_id?
18
+
19
+ validates :item_type, alpha_numeric: {punctuation: true}, if: :item_type?
20
+
21
+ if ::Configuration.for('versioning').validate_item_type_constants
22
+ validates :item_type, existing_class: true, if: :item_type?
23
+ end
24
+
25
+ # :call-seq:
26
+ # object_has? :pattern
27
+ #
28
+ # yields versions in which the object contains a pattern
29
+
30
+ scope :object_has?, lambda { |pattern| where('object LIKE ?', "%#{pattern}%") }
31
+
32
+ # :call-seq:
33
+ # Klass.in_the_last N
34
+ #
35
+ # yields objects created in the last N (where N is a timestamp)
36
+
37
+ scope :in_the_last, lambda { |dt| where('created_at > ?', dt.ago) }
38
+
39
+ # :call-seq:
40
+ # yml_to_ruby
41
+ #
42
+ # loads the yaml object into a ruby-hash
43
+ # if this is the 'destroyed' version, then RTFM reify
44
+
45
+ def yml_to_ruby
46
+ Psych.load object
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,17 @@
1
+ # validate field contains the name of an existing class
2
+ class ExistingClassValidator < ActiveModel::EachValidator
3
+
4
+ # :call-seq:
5
+ # validate_each :record, :attr, :value
6
+ #
7
+ # validates that value is the name of an existing class
8
+
9
+ def validate_each(record, attr, value)
10
+ types = value.split(/::/).map(&:to_sym)
11
+ item_type_result = types.inject(Module) do |constant, name|
12
+ constant.const_get(name) if constant && constant.constants.include?(name)
13
+ end
14
+ record.errors[attr] << 'unknown module or class' unless item_type_result.present?
15
+ end
16
+
17
+ end
@@ -0,0 +1,36 @@
1
+ require 'csv'
2
+
3
+ # validate attachment is a CSV file
4
+ module ImportableAttachments # :nodoc:
5
+ class CsvValidator < ActiveModel::Validator
6
+
7
+ # :call-seq:
8
+ # validate :record
9
+ #
10
+ # ensures that the record's attachment file name has a .xls extension
11
+
12
+ def validate(record)
13
+ extension = record.attachment.io_stream_file_name.split('.').last
14
+ if extension.downcase != 'csv'
15
+ record.errors.add :attachment, 'invalid attachment'
16
+ record.attachment.errors.add :base, 'File must be a CSV (.csv) file'
17
+ end
18
+
19
+ if defined? FasterCSV
20
+ begin
21
+ FasterCSV.read record.attachment.io_stream
22
+ rescue FasterCSV::MalformedCSVError => err
23
+ record.errors.add :attachment, 'invalid attachment'
24
+ record.attachment.errors.add :base, err.messages.join(', ')
25
+ end
26
+ else
27
+ begin
28
+ CSV.read record.attachment.io_stream.path
29
+ rescue CSV::MalformedCSVError => err
30
+ record.errors.add :attachment, 'invalid attachment'
31
+ record.attachment.errors.add :base, err.messages.join(', ')
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,18 @@
1
+ module ImportableAttachments # :nodoc:
2
+ # validate attachment is an excel file
3
+ class ExcelValidator < ActiveModel::Validator
4
+
5
+ # :call-seq:
6
+ # validate :record
7
+ #
8
+ # ensures that the record's attachment file name has a .xls extension
9
+
10
+ def validate(record)
11
+ extension = record.attachment.io_stream_file_name.split('.').last
12
+ if extension != 'xls'
13
+ record.errors[:attachment] << 'File must be an Excel (.xls) file'
14
+ end
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ module ImportableAttachments # :nodoc:
2
+ # validate attachment is an excel file
3
+ class ExcelValidator < ActiveModel::Validator
4
+
5
+ # :call-seq:
6
+ # validate :record
7
+ #
8
+ # ensures that the record's attachment file name has a .xls extension
9
+
10
+ def validate(record)
11
+ extension = record.attachment.io_stream_file_name.split('.').last
12
+ if extension != 'xls'
13
+ record.errors[:attachment] << 'File must be an Excel (.xls) file'
14
+ end
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,9 @@
1
+ %tr.group_data
2
+ - img_tag = image_tag '/assets/importable_attachments/buttons/download_32.png', alt: "Download #{attachment.io_stream_file_name}", title: "Download #{attachment.io_stream_file_name.inspect}", id: "icon_file_download_#{attachment.id}", :class => 'faux_link'
3
+ %td.text_col{style: 'text-align: center;'}= link_to img_tag, attachment.io_stream.url
4
+ %td.text_col= link_to attachment.io_stream_file_name, attachment, title: "View metadata for #{attachment.io_stream_file_name.inspect}", alt: "View metadata for #{attachment.io_stream_file_name.inspect}"
5
+ %td.text_col{style: 'text-align: center;'}= attachment.revision_number
6
+ %td.text_col= attachment.updated_at.strftime('%Y-%m-%d %I:%M %p')
7
+ %td.action_col= link_to 'Edit', edit_attachment_path(attachment)
8
+ %td.action_col= link_to 'Destroy', attachment, confirm: 'Are you sure?', method: :delete
9
+
@@ -0,0 +1,22 @@
1
+ = javascript_include_tag 'importable_attachments/attachments'
2
+
3
+ #spreadsheet_action_panel.actions_menu
4
+ = image_tag '/assets/importable_attachments/buttons/upload_32.png', alt: 'Upload File', title: 'Upload File', id: 'icon_file_upload', :class => 'faux_link'
5
+
6
+ - if attachment.new_record?
7
+ = image_tag '/assets/importable_attachments/buttons/download_32.png', alt: 'No File to Download', title: 'No File to Download', id: 'icon_file_download', :class => 'faux_link'
8
+ - else
9
+ - img_tag = image_tag '/assets/importable_attachments/buttons/download_32.png', alt: 'Download Original File', title: 'Download Original File', id: 'icon_file_download', :class => 'faux_link'
10
+ =link_to img_tag, attachment.io_stream_url
11
+
12
+ %li
13
+ %label.label File name:
14
+ #file_name{disabled: 'disabled', value: attachment.io_stream_file_name || ""}
15
+ = f.inputs id: 'attachment_attributes_io_stream_fields' do
16
+ - opts = { as: :file, id: 'attachment_io_stream_input' }
17
+ - opts.merge! required: f.object.mark_required?(:io_stream) if ::Configuration.for('mark_requirements').enabled
18
+ = f.input :io_stream, opts
19
+
20
+ - if attachment.attachable_type || attachment.attachable_id
21
+ = f.input :attachable_type, as: :hidden, input_html: { value: attachment.attachable_type }
22
+ = f.input :attachable_id, as: :hidden, input_html: { value: attachment.attachable_id }
@@ -0,0 +1,20 @@
1
+ = javascript_include_tag 'importable_attachments/attachments'
2
+
3
+ #spreadsheet_action_panel.actions_menu
4
+ = image_tag '/assets/importable_attachments/buttons/upload_32.png', alt: 'Upload File', title: 'Upload File', id: 'icon_file_upload', :class => 'faux_link'
5
+
6
+ - if attachment.new_record?
7
+ = image_tag '/assets/importable_attachments/buttons/download_32.png', alt: 'No File to Download', title: 'No File to Download', id: 'icon_file_download', :class => 'faux_link'
8
+ - else
9
+ - img_tag = image_tag '/assets/importable_attachments/buttons/download_32.png', alt: 'Download Original File', title: 'Download Original File', id: 'icon_file_download', :class => 'faux_link'
10
+ =link_to img_tag, attachment.io_stream_url
11
+
12
+ %li
13
+ %label.label File name
14
+ %input#file_name{disabled: 'disabled', value: attachment.io_stream_file_name}
15
+ = f.inputs id: 'attachment_attributes_io_stream_fields' do
16
+ - opts = { as: :file, id: 'attachment_io_stream_input' }
17
+ = f.semantic_fields_for :attachment do |attachment_form|
18
+ - opts.merge! required: attachment_form.object.mark_required?(:io_stream) if ::Configuration.for('mark_requirements').enabled
19
+ = attachment_form.inputs do
20
+ = attachment_form.input :io_stream, opts
@@ -0,0 +1,39 @@
1
+ %h2 Editing Attachment #{@attachment.io_stream_file_name}
2
+
3
+ = semantic_form_for @attachment, url: attachment_path(@attachment), html: {multipart: true} do |f|
4
+ = f.inputs do
5
+ = render 'form', f: f, attachment: @attachment
6
+
7
+ = f.action :submit, input_html: { value: 'Upload File', onclick: "this.disabled=true;this.value='Please wait...';this.form.submit();" }
8
+
9
+ - if @attachment.attachable_type
10
+ %p
11
+ %b Represents:
12
+ = "#{@attachment.attachable_type} id: #{@attachment.attachable_id}"
13
+
14
+ %p
15
+ %b File Name:
16
+ =link_to @attachment.io_stream_file_name, @attachment.io_stream.url, title: @attachment.io_stream_file_name, alt: @attachment.io_stream_file_name
17
+
18
+ - if %w(development test).include?(Rails.env)
19
+ %p
20
+ %b File Path:
21
+ =link_to @attachment.io_stream.path.sub(Rails.root.to_s + '/', ""), File.dirname(@attachment.io_stream.path)
22
+
23
+ %p
24
+ %b File Size:
25
+ = "#{@attachment.io_stream_file_size} bytes"
26
+
27
+ %p
28
+ %b Content Type:
29
+ = @attachment.io_stream.content_type
30
+
31
+ %p
32
+ %b Version:
33
+ = @attachment.revision_number
34
+
35
+ %br/
36
+ = link_to 'Show', @attachment
37
+ |
38
+ = link_to 'View All Attachments', attachments_path
39
+
@@ -0,0 +1,23 @@
1
+ %h2 Attachments
2
+
3
+ = semantic_form_for Attachment.new, url: attachments_path, html: {multipart: true} do |f|
4
+ = f.inputs do
5
+ = render 'form', f: f, attachment: f.object
6
+
7
+ = f.action :submit, input_html: { value: 'Upload File', onclick: "this.disabled=true;this.value='Please wait...';this.form.submit();" }
8
+
9
+ %table#resource_table{alt: 'Attachments'}
10
+ %thead
11
+ %tr
12
+ %th Download
13
+ %th File Name
14
+ %th Version
15
+ %th Last Modified
16
+ %th.action_col_header{colspan: 2} Actions
17
+
18
+ %tbody
19
+ = render @attachments
20
+
21
+ %br/
22
+ = link_to 'New Attachment', new_attachment_path, title: 'New Attachment'
23
+
@@ -0,0 +1,23 @@
1
+ xml.instruct! :xml, version: '1.0', encoding: 'UTF-8'
2
+ xml.attachments do
3
+ xml.page params[:page]
4
+ xml.total_pages(@filtered_collection ? (@filtered_collection.count / params[:rows].to_f).ceil : 1)
5
+ xml.num_records(@filtered_collection ? @filtered_collection.count : 0)
6
+ xml.rows do
7
+ @attachments && @attachments.each do |u|
8
+ xml.attachment id: u.id do
9
+ xml.id u.id
10
+ xml.parent_type u.parent_type
11
+ xml.parent_id u.parent_id
12
+ xml.revision_number u.revision_number
13
+ xml.io_stream_file_name u.io_stream_file_name
14
+ xml.io_stream_content_type u.io_stream_content_type
15
+ xml.io_stream_file_size u.io_stream_file_size
16
+ xml.io_stream_updated_at u.io_stream_updated_at
17
+ xml.created_at u.created_at
18
+ xml.updated_at u.updated_at
19
+ end
20
+ end
21
+ end
22
+ end
23
+
@@ -0,0 +1,10 @@
1
+ %h2 New Attachment
2
+
3
+ = semantic_form_for @attachment, url: attachments_path, html: {multipart: true} do |f|
4
+ = f.inputs do
5
+ = render 'form', f: f, attachment: @attachment
6
+
7
+ = f.action :submit, input_html: { value: 'Upload File', onclick: "this.disabled=true;this.value='Please wait...';this.form.submit();" }
8
+
9
+ = link_to 'View All Attachments', attachments_path
10
+
@@ -0,0 +1,43 @@
1
+ %h2 Attachment #{@attachment.io_stream_file_name}
2
+
3
+ #spreadsheet_action_panel.actions_menu
4
+ - img_tag = image_tag '/assets/importable_attachments/buttons/download_32.png', alt: 'Download Original File', title: 'Download Original File', id: 'icon_file_download', :class => 'faux_link'
5
+ =link_to img_tag, @attachment.io_stream.url, title: @attachment.io_stream_file_name, alt: @attachment.io_stream_file_name
6
+
7
+ - if @attachment.attachable_type
8
+ %p
9
+ %b Represents:
10
+ = "#{@attachment.attachable_type} id: #{@attachment.attachable_id}"
11
+
12
+ %p
13
+ %b File Name:
14
+ =link_to @attachment.io_stream_file_name, @attachment.io_stream.url, title: @attachment.io_stream_file_name, alt: @attachment.io_stream_file_name
15
+
16
+ - if %w(development test).include?(Rails.env)
17
+ %p
18
+ %b File Path:
19
+ =link_to @attachment.io_stream.path.sub(Rails.root.to_s + '/', ""), File.dirname(@attachment.io_stream.path)
20
+
21
+ %p
22
+ %b File Size:
23
+ = "#{@attachment.io_stream_file_size} bytes"
24
+
25
+ %p
26
+ %b Content Type:
27
+ = @attachment.io_stream_mime_type.try(:simplified) || 'Unknown'
28
+
29
+ %p
30
+ %b Version:
31
+ = @attachment.revision_number
32
+
33
+ %p
34
+ %b Last Modified:
35
+ = @attachment.updated_at.strftime('%Y-%m-%d %I:%M %p')
36
+
37
+ %br/
38
+ = link_to 'Edit', edit_attachment_path(@attachment)
39
+ |
40
+ = link_to 'Destroy', @attachment, confirm: 'Are you sure?', method: :delete
41
+ |
42
+ = link_to 'View All Attachments', attachments_path
43
+
@@ -0,0 +1,25 @@
1
+ = form_for @version do |f|
2
+ - if @version.errors.any?
3
+ #error_explanation
4
+ %h2= "#{pluralize(@version.errors.count, "error")} prohibited this version from being saved:"
5
+ %ul
6
+ - @version.errors.full_messages.each do |msg|
7
+ %li= msg
8
+
9
+ .field
10
+ = f.label :item_type
11
+ = f.text_field :item_type
12
+ .field
13
+ = f.label :item_id
14
+ = f.text_field :item_id
15
+ .field
16
+ = f.label :event
17
+ = f.text_field :event
18
+ .field
19
+ = f.label :whodunit
20
+ = f.text_field :whodunit
21
+ .field
22
+ = f.label :object
23
+ = f.text_area :object
24
+ .actions
25
+ = f.submit 'Save'
@@ -0,0 +1,7 @@
1
+ %h1 Editing version
2
+
3
+ = render 'form'
4
+
5
+ = link_to 'Show', @version
6
+ \|
7
+ = link_to 'Back', versions_path
@@ -0,0 +1,27 @@
1
+ %h1 Listing versions
2
+
3
+ %table
4
+ %tr
5
+ %th Item type
6
+ %th Item
7
+ %th Event
8
+ %th Whodunit
9
+ %th Object
10
+ %th
11
+ %th
12
+ %th
13
+
14
+ - @versions.each do |version|
15
+ %tr
16
+ %td= version.item_type
17
+ %td= version.item_id
18
+ %td= version.event
19
+ %td= version.whodunit
20
+ %td= version.object
21
+ %td= link_to 'Show', version
22
+ %td= link_to 'Edit', edit_version_path(version)
23
+ %td= link_to 'Destroy', version, :method => :delete, :data => { :confirm => 'Are you sure?' }
24
+
25
+ %br
26
+
27
+ = link_to 'New Version', new_version_path
@@ -0,0 +1,5 @@
1
+ %h1 New version
2
+
3
+ = render 'form'
4
+
5
+ = link_to 'Back', versions_path
@@ -0,0 +1,21 @@
1
+ %p#notice= notice
2
+
3
+ %p
4
+ %b Item type:
5
+ = @version.item_type
6
+ %p
7
+ %b Item:
8
+ = @version.item_id
9
+ %p
10
+ %b Event:
11
+ = @version.event
12
+ %p
13
+ %b Whodunit:
14
+ = @version.whodunit
15
+ %p
16
+ %b Object:
17
+ = @version.object
18
+
19
+ = link_to 'Edit', edit_version_path(@version)
20
+ \|
21
+ = link_to 'Back', versions_path
@@ -0,0 +1,33 @@
1
+ - current_version = collection.last || Version.new
2
+ %h3
3
+ Current Version: #{collection.length}
4
+
5
+ %b Created At:
6
+ = current_version.created_at
7
+
8
+ %br/
9
+ = succeed ':' do
10
+ %b Admin
11
+
12
+ %br/
13
+ - if collection.length.to_i > 1
14
+ - if params[:version].to_i > 1 || !params[:version]
15
+ = link_to 'Previous version', {version: (params[:version] || collection.length).to_i - 1}
16
+
17
+ %br/
18
+
19
+ - if params[:version]
20
+ %h3
21
+ This is #{params[:version]} version
22
+
23
+ %b Modify at:
24
+ = collection[(params[:version].to_i - 1)].created_at
25
+
26
+ %br/
27
+
28
+ = succeed ':' do
29
+ %b Admin
30
+
31
+ %br/
32
+ = link_to 'Go to current version'
33
+
@@ -0,0 +1,48 @@
1
+ !!! 1.1
2
+ %html{lang: 'en', 'xml:lang' => 'en', xmlns: 'http://www.w3.org/1999/xhtml'}
3
+ %head
4
+ %meta{content: 'text/html; charset=utf-8', :'http-equiv' => 'Content-type'}/
5
+ %meta{name: 'document-rights', content: 'Copyrighted Work'}
6
+ %meta{name: 'Copyright', content: 'Copyright (c) Paul Belt'}
7
+ %meta{name: 'Rating', content: 'General'}
8
+ %meta{name: 'Keywords', content: 'attachments upload download'}
9
+ %meta{name: 'Description', content: 'Attachments Engine'}
10
+ %meta{name: 'csrf-token_name', content: request_forgery_protection_token}
11
+ %meta{name: 'csrf-token', content: form_authenticity_token}
12
+ %meta{name: 'csrf-param', content: 'authenticity_token'}
13
+
14
+ %title Attachments
15
+
16
+ = stylesheet_link_tag 'importable_attachments/application', media: 'all', charset: 'utf-8'
17
+ = javascript_include_tag 'importable_attachments/application', charset: 'utf-8'
18
+
19
+ /[if IE 6]
20
+ = stylesheet_link_tag 'formtastic_ie6'
21
+ /[if IE 7]
22
+ = stylesheet_link_tag 'formtastic_ie7'
23
+
24
+ - if protect_against_forgery?
25
+ = csrf_meta_tags # this must be last
26
+
27
+ %body
28
+ #flash
29
+ - flash.each do |key, value|
30
+ %div{:id => "flash_#{key}"}
31
+ %p{:style => 'float:right;'}
32
+ = link_to_function 'X', "Effect.Fade('flash_#{key}')"
33
+ %ul
34
+ - if value.is_a?(Hash)
35
+ %li.message
36
+ = h value[:message]
37
+ %li.flash_followup_action
38
+ = h value[:followup]
39
+ - else
40
+ %li.message
41
+ = h value
42
+ .clear
43
+
44
+ #contents
45
+ %noscript.noscript
46
+ %p Please enable JavaScript for a better experience.
47
+
48
+ = yield