importable_attachments 0.0.13
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +24 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +38 -0
- data/MIT-LICENSE +20 -0
- data/README.md +8 -0
- data/README.rdoc +3 -0
- data/Rakefile +29 -0
- data/app/assets/images/importable_attachments/.gitkeep +0 -0
- data/app/assets/images/importable_attachments/buttons/.htaccess +5 -0
- data/app/assets/images/importable_attachments/buttons/download_32.png +0 -0
- data/app/assets/images/importable_attachments/buttons/upload_32.png +0 -0
- data/app/assets/javascripts/importable_attachments/application.js +14 -0
- data/app/assets/javascripts/importable_attachments/attachments.coffee +41 -0
- data/app/assets/stylesheets/importable_attachments/application.css +14 -0
- data/app/assets/stylesheets/importable_attachments/attachments.css +4 -0
- data/app/assets/stylesheets/scaffold.css +56 -0
- data/app/controllers/importable_attachments/application_controller.rb +4 -0
- data/app/controllers/importable_attachments/attachments_controller.rb +190 -0
- data/app/controllers/importable_attachments/versions_controller.rb +87 -0
- data/app/helpers/importable_attachments/application_helper.rb +4 -0
- data/app/models/attachment.rb +24 -0
- data/app/models/importable_attachments/attachment.rb +143 -0
- data/app/models/importable_attachments/version.rb +50 -0
- data/app/validators/existing_class_validator.rb +17 -0
- data/app/validators/importable_attachments/csv_validator.rb +36 -0
- data/app/validators/importable_attachments/excel.rb +18 -0
- data/app/validators/importable_attachments/excel_validator.rb +18 -0
- data/app/views/importable_attachments/attachments/_attachment.html.haml +9 -0
- data/app/views/importable_attachments/attachments/_form.html.haml +22 -0
- data/app/views/importable_attachments/attachments/_nested_form.html.haml +20 -0
- data/app/views/importable_attachments/attachments/edit.html.haml +39 -0
- data/app/views/importable_attachments/attachments/index.html.haml +23 -0
- data/app/views/importable_attachments/attachments/index.xml.builder +23 -0
- data/app/views/importable_attachments/attachments/new.html.haml +10 -0
- data/app/views/importable_attachments/attachments/show.html.haml +43 -0
- data/app/views/importable_attachments/versions/_form.html.haml +25 -0
- data/app/views/importable_attachments/versions/edit.html.haml +7 -0
- data/app/views/importable_attachments/versions/index.html.haml +27 -0
- data/app/views/importable_attachments/versions/new.html.haml +5 -0
- data/app/views/importable_attachments/versions/show.html.haml +21 -0
- data/app/views/layouts/_version.html.haml +33 -0
- data/app/views/layouts/importable_attachments/application.html.haml +48 -0
- data/bin/set_lc.sh +47 -0
- data/config/database.yml +25 -0
- data/config/features/attachments.rb +8 -0
- data/config/features/mark_requirements.rb +3 -0
- data/config/features/smarter_dates.rb +3 -0
- data/config/features/versioning.rb +7 -0
- data/config/initializers/0_configuration.rb +7 -0
- data/config/initializers/formtastic.rb +76 -0
- data/config/initializers/generators.rb +10 -0
- data/config/initializers/paperclip.rb +27 -0
- data/config/locales/responders.en.yml +10 -0
- data/config/routes.rb +11 -0
- data/db/migrate/001_create_importable_attachments_versions.rb +14 -0
- data/db/migrate/100_create_attachments.rb +19 -0
- data/importable_attachments.gemspec +81 -0
- data/lib/generators/importable_attachments/install_generator.rb +66 -0
- data/lib/generators/importable_attachments/templates/features/attachments.rb.erb +7 -0
- data/lib/generators/importable_attachments/templates/features/versioning.rb +7 -0
- data/lib/generators/importable_attachments/templates/initializers/paperclip.rb +27 -0
- data/lib/importable_attachments/base.rb +108 -0
- data/lib/importable_attachments/blueprints.rb +9 -0
- data/lib/importable_attachments/engine.rb +8 -0
- data/lib/importable_attachments/importers/csv.rb +208 -0
- data/lib/importable_attachments/importers/excel.rb +37 -0
- data/lib/importable_attachments/importers.rb +7 -0
- data/lib/importable_attachments/version.rb +3 -0
- data/lib/importable_attachments.rb +9 -0
- data/lib/paperclip_processors/save_upload.rb +33 -0
- data/lib/tasks/importable_attachments_tasks.rake +4 -0
- data/script/rails +8 -0
- data/spec/attachments/books.csv +6 -0
- data/spec/attachments/books.txt +6 -0
- data/spec/attachments/books2.csv +4 -0
- data/spec/attachments/empty.csv +0 -0
- data/spec/attachments/failed_instances.csv +3 -0
- data/spec/attachments/invalid_headers.csv +3 -0
- data/spec/attachments/just_headers.csv +1 -0
- data/spec/attachments/mostly_empty.csv +2 -0
- data/spec/attachments/mostly_empty_copy.xls +0 -0
- data/spec/controllers/importable_attachments/attachments_controller_spec.rb +236 -0
- data/spec/controllers/importable_attachments/versions_controller_spec.rb +158 -0
- data/spec/dummy/README.rdoc +261 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +15 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.gitkeep +0 -0
- data/spec/dummy/app/models/.gitkeep +0 -0
- data/spec/dummy/app/models/book.rb +13 -0
- data/spec/dummy/app/models/library.rb +54 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config/application.rb +65 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +67 -0
- data/spec/dummy/config/environments/test.rb +37 -0
- data/spec/dummy/config/initializers/0_configuration.rb +7 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +4 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/db/migrate/101_create_libraries.rb +10 -0
- data/spec/dummy/db/migrate/102_create_books.rb +12 -0
- data/spec/dummy/db/schema.rb +57 -0
- data/spec/dummy/features/person_uploads_generic_file.feature +11 -0
- data/spec/dummy/features/step_definitions/person_uploads_generic_file_steps.rb +11 -0
- data/spec/dummy/features/step_definitions/web_steps.rb +211 -0
- data/spec/dummy/features/support/capybara.rb +6 -0
- data/spec/dummy/features/support/database_cleaner.rb +26 -0
- data/spec/dummy/features/support/developer_helpers.rb +47 -0
- data/spec/dummy/features/support/env.rb +53 -0
- data/spec/dummy/features/support/paths.rb +33 -0
- data/spec/dummy/features/support/poltergeist.rb +1 -0
- data/spec/dummy/features/support/selectors.rb +39 -0
- data/spec/dummy/features/support/transactional_fixtures.rb +14 -0
- data/spec/dummy/lib/assets/.gitkeep +0 -0
- data/spec/dummy/log/.gitkeep +0 -0
- data/spec/dummy/public/404.html +38 -0
- data/spec/dummy/public/422.html +38 -0
- data/spec/dummy/public/500.html +36 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/dummy/spec/support/.gitkeep +0 -0
- data/spec/dummy/spec/support/paperclip.rb +1 -0
- data/spec/models/importable_attachments/attachment_spec.rb +177 -0
- data/spec/models/importable_attachments/library_spec.rb +155 -0
- data/spec/models/importable_attachments/version_spec.rb +25 -0
- data/spec/routing/importable_attachments/versions_routing_spec.rb +43 -0
- data/spec/spec.opts +5 -0
- data/spec/spec_helper.rb +30 -0
- 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,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,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
|