alchemy-custom-model 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +147 -0
- data/Rakefile +32 -0
- data/app/assets/config/alchemy_custom_model_manifest.js +3 -0
- data/app/assets/images/alchemy-custom-model/no_image.png +0 -0
- data/app/assets/javascripts/alchemy-custom-model/change_language.js +11 -0
- data/app/assets/javascripts/alchemy-custom-model/common_init.js +16 -0
- data/app/assets/javascripts/alchemy-custom-model/custom_admin_element_editor.js.coffee +25 -0
- data/app/assets/javascripts/alchemy-custom-model/custom_tiny_mce.js.coffee.erb +95 -0
- data/app/assets/javascripts/alchemy-custom-model/el_finder.js.coffee.erb +241 -0
- data/app/assets/javascripts/alchemy-custom-model/elfinder_ui_manifest.js +4 -0
- data/app/assets/javascripts/alchemy-custom-model/manifest.js +23 -0
- data/app/assets/javascripts/alchemy-custom-model/nested_attributes_sortable.js.coffee +25 -0
- data/app/assets/javascripts/alchemy-custom-model/select2filter.js +51 -0
- data/app/assets/javascripts/alchemy-custom-model/subobjects.js +98 -0
- data/app/assets/javascripts/alchemy-custom-model/total_page_elfinder.js.coffee +15 -0
- data/app/assets/stylesheets/alchemy-custom-model/custom_elfinder.css.scss +130 -0
- data/app/assets/stylesheets/alchemy-custom-model/custom_style.css.scss +228 -0
- data/app/assets/stylesheets/alchemy-custom-model/custom_tiny_mce.scss +6 -0
- data/app/assets/stylesheets/alchemy-custom-model/manifest.css +16 -0
- data/app/controllers/alchemy/custom/model/admin/base_controller.rb +189 -0
- data/app/controllers/alchemy/custom/model/admin/files_controller.rb +106 -0
- data/app/controllers/alchemy/pages_controller_decorator.rb +1 -0
- data/app/helpers/alchemy/custom/model/admin/base_helper.rb +379 -0
- data/app/helpers/alchemy/custom/model/base_helper.rb +18 -0
- data/app/helpers/alchemy/custom/model/custom_model_helper.rb +112 -0
- data/app/helpers/alchemy/pages_helper_decorator.rb +95 -0
- data/app/models/admin_override_to_param.rb +9 -0
- data/app/models/application_record.rb +9 -0
- data/app/views/alchemy/custom/model/admin/base/_buttons_tool.html.erb +16 -0
- data/app/views/alchemy/custom/model/admin/base/_gallery_item.html.erb +4 -0
- data/app/views/alchemy/custom/model/admin/base/_language_tree_select.html.erb +9 -0
- data/app/views/alchemy/custom/model/admin/base/_search_box.html.erb +19 -0
- data/app/views/alchemy/custom/model/admin/base/_seo.html.erb +8 -0
- data/app/views/alchemy/custom/model/admin/base/_table.html.erb +33 -0
- data/app/views/alchemy/custom/model/admin/base/_title.html.erb +3 -0
- data/app/views/alchemy/custom/model/admin/base/edit.html.erb +18 -0
- data/app/views/alchemy/custom/model/admin/base/index.html.erb +39 -0
- data/app/views/alchemy/custom/model/admin/base/new.html.erb +19 -0
- data/app/views/alchemy/custom/model/admin/files/error_notice.json.jbuilder +1 -0
- data/app/views/alchemy/custom/model/admin/files/ui.html.erb +13 -0
- data/config/initializers/elfinder_abilities.rb +1 -0
- data/config/locales/en.yml +11 -0
- data/config/locales/it.yml +21 -0
- data/config/routes.rb +8 -0
- data/lib/alchemy-custom-model.rb +29 -0
- data/lib/alchemy/custom/model/el_finder.rb +17 -0
- data/lib/alchemy/custom/model/el_finder/ability.rb +16 -0
- data/lib/alchemy/custom/model/el_finder/connector.rb +435 -0
- data/lib/alchemy/custom/model/el_finder/image.rb +35 -0
- data/lib/alchemy/custom/model/el_finder/path_name.rb +220 -0
- data/lib/alchemy/custom/model/el_finder/paths.rb +21 -0
- data/lib/alchemy/custom/model/el_finder/paths/active_record_reference.rb +50 -0
- data/lib/alchemy/custom/model/el_finder/paths/base.rb +298 -0
- data/lib/alchemy/custom/model/el_finder/paths/component_file.rb +59 -0
- data/lib/alchemy/custom/model/el_finder/paths/component_files.rb +34 -0
- data/lib/alchemy/custom/model/el_finder/paths/file.rb +23 -0
- data/lib/alchemy/custom/model/el_finder/paths/files.rb +25 -0
- data/lib/alchemy/custom/model/el_finder/paths/image.rb +42 -0
- data/lib/alchemy/custom/model/el_finder/paths/images.rb +31 -0
- data/lib/alchemy/custom/model/el_finder/paths/root.rb +24 -0
- data/lib/alchemy/custom/model/el_finder/volumes.rb +18 -0
- data/lib/alchemy/custom/model/el_finder/volumes/alchemy_file.rb +197 -0
- data/lib/alchemy/custom/model/el_finder/volumes/alchemy_files.rb +51 -0
- data/lib/alchemy/custom/model/el_finder/volumes/alchemy_images.rb +69 -0
- data/lib/alchemy/custom/model/el_finder/volumes/base.rb +149 -0
- data/lib/alchemy/custom/model/el_finder/volumes/component_attribute.rb +130 -0
- data/lib/alchemy/custom/model/engine.rb +40 -0
- data/lib/alchemy/custom/model/global_id_setter.rb +35 -0
- data/lib/alchemy/custom/model/model_decoration.rb +82 -0
- data/lib/alchemy/custom/model/pages_controller_dec.rb +132 -0
- data/lib/alchemy/custom/model/translation_scope.rb +18 -0
- data/lib/alchemy/custom/model/version.rb +7 -0
- data/lib/alchemy/touching_decorator.rb +12 -0
- data/lib/tasks/alchemy_custom_model_tasks.rake +41 -0
- data/vendor/elfinder/css/elfinder.full.css +5117 -0
- data/vendor/elfinder/css/elfinder.min.css +9 -0
- data/vendor/elfinder/css/theme.css +349 -0
- data/vendor/elfinder/js/elfinder.full.js +34270 -0
- data/vendor/elfinder/js/elfinder.min.js +25 -0
- metadata +194 -0
@@ -0,0 +1,59 @@
|
|
1
|
+
module Alchemy::Custom::Model::ElFinder
|
2
|
+
module Paths
|
3
|
+
class ComponentFile < ActiveRecordReference
|
4
|
+
|
5
|
+
def active_record_class
|
6
|
+
self.volume.attribute_class
|
7
|
+
end
|
8
|
+
|
9
|
+
def alchemy_record
|
10
|
+
return @_alch_record_cache if @_alch_record_cache
|
11
|
+
base = active_record_instance
|
12
|
+
self.volume.file_link_ref.split('.').each {|m| base = base.try(m)}
|
13
|
+
@_alch_record_cache = base
|
14
|
+
end
|
15
|
+
|
16
|
+
def file
|
17
|
+
case alchemy_record
|
18
|
+
when ::Alchemy::Attachment
|
19
|
+
alchemy_record.file
|
20
|
+
when ::Alchemy::Picture
|
21
|
+
alchemy_record.image_file
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
def file=(val)
|
27
|
+
case alchemy_record
|
28
|
+
when ::Alchemy::Attachment
|
29
|
+
alchemy_record.file = val
|
30
|
+
when ::Alchemy::Picture
|
31
|
+
alchemy_record.image_file = val
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
delegate :save, to: :alchemy_record
|
36
|
+
|
37
|
+
def full_fill_paylod(payload)
|
38
|
+
payload[:tmb] = self.tmb
|
39
|
+
payload
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
def tmb
|
44
|
+
case alchemy_record
|
45
|
+
when ::Alchemy::Attachment
|
46
|
+
''
|
47
|
+
when ::Alchemy::Picture
|
48
|
+
file.thumb('100x100#').url
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
def is_image?
|
54
|
+
alchemy_record.is_a? ::Alchemy::Picture
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Alchemy::Custom::Model::ElFinder
|
2
|
+
module Paths
|
3
|
+
class ComponentFiles < Base
|
4
|
+
|
5
|
+
|
6
|
+
def children(with_directory = true)
|
7
|
+
|
8
|
+
@volume.record.send(@volume.attribute).collect do |p|
|
9
|
+
|
10
|
+
build_file_path(p)
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
##
|
17
|
+
# Costruisce il singolo file, passandogli l'active record di alchemy (Picture o Attachment)
|
18
|
+
#
|
19
|
+
# @param [Alchemy::Picture | Alchemy::Attachment] p
|
20
|
+
def build_file_path(p)
|
21
|
+
|
22
|
+
base_class = ComponentFile
|
23
|
+
|
24
|
+
|
25
|
+
file_path = base_class.new(@root, "#{self.path}/#{base_class.file_to_uri(p)}", volume: self.volume)
|
26
|
+
|
27
|
+
file_path.active_record_instance = p
|
28
|
+
|
29
|
+
file_path
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Alchemy::Custom::Model::ElFinder
|
2
|
+
module Paths
|
3
|
+
class File < ActiveRecordReference
|
4
|
+
|
5
|
+
def full_fill_paylod(payload)
|
6
|
+
payload[:original_url] = ::Alchemy::Engine.routes.url_helpers.download_attachment_path(id: active_record_instance.id, name: active_record_instance.urlname)
|
7
|
+
payload
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
def active_record_class
|
12
|
+
::Alchemy::Attachment
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
def global_id
|
17
|
+
active_record_instance.to_signed_global_id.to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Alchemy::Custom::Model::ElFinder
|
2
|
+
module Paths
|
3
|
+
class Files < Base
|
4
|
+
|
5
|
+
def children(with_directory = true)
|
6
|
+
::Alchemy::Attachment.all.collect {|p|
|
7
|
+
build_file_path(p)
|
8
|
+
}
|
9
|
+
end
|
10
|
+
|
11
|
+
def build_file_path(p)
|
12
|
+
base_class = Paths::File
|
13
|
+
|
14
|
+
Rails.logger.debug {"#{@root}-#{self.path}"}
|
15
|
+
image = base_class.new(@root, "#{self.path}/#{base_class.file_to_uri(p)}")
|
16
|
+
|
17
|
+
image.active_record_instance = p
|
18
|
+
|
19
|
+
image
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Alchemy::Custom::Model::ElFinder
|
2
|
+
module Paths
|
3
|
+
class Image < Paths::File
|
4
|
+
|
5
|
+
#
|
6
|
+
# url per la thumb
|
7
|
+
def tmb
|
8
|
+
active_record_instance.image_file.thumb('100x100#').url
|
9
|
+
end
|
10
|
+
|
11
|
+
def full_fill_paylod(payload)
|
12
|
+
payload[:tmb] = self.tmb
|
13
|
+
payload[:original_url] = active_record_instance.image_file.url
|
14
|
+
payload
|
15
|
+
end
|
16
|
+
|
17
|
+
def active_record_class
|
18
|
+
::Alchemy::Picture
|
19
|
+
end
|
20
|
+
|
21
|
+
def file
|
22
|
+
active_record_instance.image_file
|
23
|
+
end
|
24
|
+
|
25
|
+
def file=(val)
|
26
|
+
active_record_instance.image_file = val
|
27
|
+
end
|
28
|
+
|
29
|
+
delegate :save, to: :active_record_instance
|
30
|
+
|
31
|
+
def is_image?
|
32
|
+
true
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
def dim
|
37
|
+
"#{active_record_instance.image_file_width}x#{active_record_instance.image_file_height}"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Alchemy::Custom::Model::ElFinder
|
2
|
+
module Paths
|
3
|
+
class Images < Base
|
4
|
+
|
5
|
+
|
6
|
+
def children(with_directory = true)
|
7
|
+
::Alchemy::Picture.all.collect {|p|
|
8
|
+
build_file_path(p)
|
9
|
+
}
|
10
|
+
end
|
11
|
+
|
12
|
+
##
|
13
|
+
# Costruisce il singolo file, passandogli l'active record di alchemy (Picture o Attachment)
|
14
|
+
#
|
15
|
+
# @param [Alchemy::Picture | Alchemy::Attachment] p
|
16
|
+
def build_file_path(p)
|
17
|
+
|
18
|
+
base_class = Paths::Image
|
19
|
+
|
20
|
+
Rails.logger.debug {"#{@root}-#{self.path}"}
|
21
|
+
image = base_class.new(@root, "#{self.path}/#{base_class.file_to_uri(p)}")
|
22
|
+
|
23
|
+
image.active_record_instance = p
|
24
|
+
|
25
|
+
image
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Alchemy::Custom::Model::ElFinder
|
2
|
+
module Paths
|
3
|
+
class Root < Base
|
4
|
+
|
5
|
+
def is_root?
|
6
|
+
true
|
7
|
+
end
|
8
|
+
|
9
|
+
def with_sub_dirs?
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
def children(with_directory = true)
|
15
|
+
[
|
16
|
+
Images.new(@root, 'images', volume: @volume),
|
17
|
+
Files.new(@root, 'files', volume: @volume)
|
18
|
+
]
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Alchemy
|
2
|
+
module Custom
|
3
|
+
module Model
|
4
|
+
module ElFinder::Volumes
|
5
|
+
extend ActiveSupport::Autoload
|
6
|
+
|
7
|
+
autoload :AlchemyFile
|
8
|
+
autoload :AlchemyFiles
|
9
|
+
autoload :AlchemyImages
|
10
|
+
autoload :Base
|
11
|
+
autoload :ComponentAttribute
|
12
|
+
|
13
|
+
# eager_autoload do
|
14
|
+
# end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,197 @@
|
|
1
|
+
module Alchemy::Custom::Model::ElFinder
|
2
|
+
module Volumes
|
3
|
+
class AlchemyFile < Base
|
4
|
+
|
5
|
+
def initialize(options = {root: '/alchemy_library', name: 'Alchemy Library', id: 'alchemy_library', url: '/'})
|
6
|
+
super
|
7
|
+
end
|
8
|
+
|
9
|
+
|
10
|
+
def cwd(target = nil)
|
11
|
+
|
12
|
+
target = Paths::Root.new(@root) if target.nil?
|
13
|
+
|
14
|
+
Rails.logger.debug {"CWD:#{target.inspect} "}
|
15
|
+
path_info(target)
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
def decode(hash)
|
20
|
+
super do |path|
|
21
|
+
case path.to_s
|
22
|
+
when 'images'
|
23
|
+
Paths::Images.new(@root, path, volume: self)
|
24
|
+
when 'files'
|
25
|
+
Paths::Files.new(@root, path, volume: self)
|
26
|
+
when /images\/*/
|
27
|
+
Paths::Image.new(@root, path, volume: self)
|
28
|
+
when /files\/*/
|
29
|
+
Paths::File.new(@root, path, volume: self)
|
30
|
+
when @root, '.'
|
31
|
+
Paths::Root.new(@root, path, volume: self)
|
32
|
+
else
|
33
|
+
Rails.logger.debug {"PATH BASE:#{path}"}
|
34
|
+
if block_given?
|
35
|
+
Rails.logger.debug {"YIELDING:#{self.class.name}"}
|
36
|
+
yield(path)
|
37
|
+
else
|
38
|
+
Paths::Base.new(@root, path, volume: self)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def path_info(target)
|
45
|
+
is_dir = target.directory?
|
46
|
+
mime = target.mime_type
|
47
|
+
name = @name if target.is_root?
|
48
|
+
name ||= target.name
|
49
|
+
|
50
|
+
dirs = 0
|
51
|
+
if is_dir
|
52
|
+
# check if has sub directories
|
53
|
+
dirs = 1 if target.with_sub_dirs?
|
54
|
+
end
|
55
|
+
|
56
|
+
size = 0
|
57
|
+
unless is_dir
|
58
|
+
size = target.size
|
59
|
+
end
|
60
|
+
|
61
|
+
result = {
|
62
|
+
name: name,
|
63
|
+
hash: encode(target.path.to_s),
|
64
|
+
mime: mime,
|
65
|
+
ts: target.mtime.to_i,
|
66
|
+
size: size,
|
67
|
+
dirs: dirs,
|
68
|
+
read: 1,
|
69
|
+
write: 1,
|
70
|
+
locked: 0,
|
71
|
+
class: target.class.name,
|
72
|
+
tmb: nil,
|
73
|
+
global_id: target.global_id
|
74
|
+
}
|
75
|
+
|
76
|
+
result = target.full_fill_paylod(result)
|
77
|
+
|
78
|
+
if target.is_root?
|
79
|
+
result[:volumeid] = "#{@id}_"
|
80
|
+
else
|
81
|
+
result[:phash] = encode(target.dirname.path.to_s)
|
82
|
+
end
|
83
|
+
|
84
|
+
result
|
85
|
+
end
|
86
|
+
|
87
|
+
def files(target = '.')
|
88
|
+
Rails.logger.debug {"FILES PER : #{target.inspect}"}
|
89
|
+
unless target.is_a?(Paths::Base)
|
90
|
+
if target == '.'
|
91
|
+
target = Paths::Root.new(@root, '.', volume: self)
|
92
|
+
else
|
93
|
+
Rails.logger.debug {target.inspect}
|
94
|
+
target = PathName.new(@root, target)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
#Elenco tutte le cartelle
|
99
|
+
files = target.children.map {|p| path_info(p)}
|
100
|
+
|
101
|
+
#inserisco sempre anche il padre delle cartelle
|
102
|
+
files << cwd(target)
|
103
|
+
files
|
104
|
+
end
|
105
|
+
|
106
|
+
def pathname(target)
|
107
|
+
target.fisical_path
|
108
|
+
end
|
109
|
+
|
110
|
+
def upload(target, upload)
|
111
|
+
response = {}
|
112
|
+
select = []
|
113
|
+
added = []
|
114
|
+
upload.to_a.each do |file|
|
115
|
+
if file.respond_to?(:tempfile)
|
116
|
+
the_file = file.tempfile
|
117
|
+
else
|
118
|
+
the_file = file
|
119
|
+
end
|
120
|
+
if upload_max_size_in_bytes > 0 && File.size(the_file.path) > upload_max_size_in_bytes
|
121
|
+
response[:error] ||= "Some files were not uploaded"
|
122
|
+
response[:errorData][@options[:original_filename_method].call(file)] = 'File exceeds the maximum allowed filesize'
|
123
|
+
else
|
124
|
+
|
125
|
+
dst = yield(file)
|
126
|
+
|
127
|
+
select << encode(dst)
|
128
|
+
added << path_info(dst)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
response[:select] = select unless select.empty?
|
132
|
+
response[:added] = added unless added.empty?
|
133
|
+
|
134
|
+
|
135
|
+
response
|
136
|
+
end
|
137
|
+
|
138
|
+
|
139
|
+
##
|
140
|
+
# Copia un file di alchemy in questo volume
|
141
|
+
#
|
142
|
+
# @param [ElFinder::Paths::Base] src
|
143
|
+
# @return [ElFinder::Paths::Base]
|
144
|
+
def copy(src)
|
145
|
+
raise 'Non si può copiare nella cartella di alchemy'
|
146
|
+
end
|
147
|
+
|
148
|
+
##
|
149
|
+
# Ricerca nel volume
|
150
|
+
# @param [String] type tipo di ricerca
|
151
|
+
# @param [String] q query di ricerca
|
152
|
+
def search(type:, q:)
|
153
|
+
query_search = yield
|
154
|
+
query_search.uniq.collect do |p|
|
155
|
+
path_info(root_path.build_file_path(p))
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def rm(target)
|
160
|
+
raise "To Implement"
|
161
|
+
end
|
162
|
+
|
163
|
+
def upload_max_size_in_bytes
|
164
|
+
999999999
|
165
|
+
end
|
166
|
+
|
167
|
+
def duplicable?(target)
|
168
|
+
false
|
169
|
+
end
|
170
|
+
|
171
|
+
private
|
172
|
+
|
173
|
+
##
|
174
|
+
# Costruisce la query di ricerca
|
175
|
+
#
|
176
|
+
# @param [ActiveRecord::Base] klass
|
177
|
+
# @param [String] type tipo di ricerca
|
178
|
+
# @param [String] q query di ricerca
|
179
|
+
# @param [Symbol] mime_attribute campo da usare per la ricerca del mime
|
180
|
+
def search_query_build(klass:, type:, q:, mime_attribute:)
|
181
|
+
case type
|
182
|
+
when 'AlchemyTags'
|
183
|
+
klass.tagged_with(q)
|
184
|
+
when 'mimes'
|
185
|
+
klass.where(mime_attribute => q)
|
186
|
+
when 'full_search'
|
187
|
+
ransack_query = "#{klass.searchable_alchemy_resource_attributes.join('_or_')}_cont"
|
188
|
+
klass.ransack(ransack_query.to_sym => q).result
|
189
|
+
else
|
190
|
+
klass.none
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
|
195
|
+
end
|
196
|
+
end
|
197
|
+
end
|