alchemy-custom-model 0.1.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.
- 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
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 6e6c70590f98f7fe1059a6473d7040a66c9db41c
|
|
4
|
+
data.tar.gz: 18f20f4575cafc620bddda500c480fdc625ea86d
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 51728d319fc807d859f16377af2b92184f6ade99a46371f55c7677488d078c029c24ba192f2de4a5431443418d968a503aa20887ac1e07b2d3ea60ff16f42fde
|
|
7
|
+
data.tar.gz: b78843f5e537763eef6dc5e75e0bffcb66ed99a7395ce9ff3a404a9e3f31a74699557ec13dd2c7d791df309be61c31c786eaf86e90b182535d6cad7b1f5c5593
|
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright 2018 Alessandro Baccanelli
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# Alchemy::Custom::Model [WIP]
|
|
2
|
+
Short description and motivation.
|
|
3
|
+
|
|
4
|
+
## Usage
|
|
5
|
+
How to use my plugin.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
Add this line to your application's Gemfile:
|
|
9
|
+
|
|
10
|
+
```ruby
|
|
11
|
+
gem 'alchemy-custom-model'
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
And then execute:
|
|
15
|
+
```bash
|
|
16
|
+
$ bundle
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Or install it yourself as:
|
|
20
|
+
```bash
|
|
21
|
+
$ gem install alchemy-custom-model
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Then run the installer
|
|
25
|
+
```bash
|
|
26
|
+
bin/rails alchemy_custom_model:install
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Usage
|
|
30
|
+
|
|
31
|
+
* Generate your model
|
|
32
|
+
|
|
33
|
+
* remember to append a column for language:
|
|
34
|
+
```ruby
|
|
35
|
+
t.integer :language_id
|
|
36
|
+
```
|
|
37
|
+
* if this model would have a custom url and the relative layout, go to the
|
|
38
|
+
[friendly_id page](https://github.com/norman/friendly_id) to make the correct install
|
|
39
|
+
* we can define on the model this attributes to be used for page SEO:
|
|
40
|
+
* text :meta_description
|
|
41
|
+
* text :meta_keywords
|
|
42
|
+
* string :meta_title
|
|
43
|
+
* boolean :robot_follow
|
|
44
|
+
* boolean :robot_index
|
|
45
|
+
|
|
46
|
+
* include the model decorator
|
|
47
|
+
```ruby
|
|
48
|
+
|
|
49
|
+
include Alchemy::Custom::Model::ModelDecoration
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
* attach yours belongs_to relations to alchemy_elements
|
|
53
|
+
```ruby
|
|
54
|
+
|
|
55
|
+
# For attachments, the foreign_key is the key defined in the model, can be omitted if it's standard Rails naming
|
|
56
|
+
belongs_to :file, class_name: "Alchemy::Attachment", optional: true, foreign_key: :file_id
|
|
57
|
+
global_id_setter :file
|
|
58
|
+
|
|
59
|
+
# For Pictures
|
|
60
|
+
belongs_to :picture, class_name: 'Alchemy::Picture', optional: true, touch: true
|
|
61
|
+
global_id_setter :picture
|
|
62
|
+
```
|
|
63
|
+
* Generate your controller:
|
|
64
|
+
```ruby
|
|
65
|
+
bin/rails g controller Admin::Posts
|
|
66
|
+
```
|
|
67
|
+
* inherit from Alchemy::Custom::Model::Admin::BaseController
|
|
68
|
+
* Create the routes (prepend it to alchemy routes and alchemy_custom_model routes)
|
|
69
|
+
* Build the ability for your recipe:
|
|
70
|
+
```ruby
|
|
71
|
+
class PostAbility
|
|
72
|
+
include CanCan::Ability
|
|
73
|
+
|
|
74
|
+
def initialize(user)
|
|
75
|
+
if user.present? && (user.is_admin? or user.has_role?("editor"))
|
|
76
|
+
can :manage, Post #model
|
|
77
|
+
can :manage, :admin_posts #routes to the posts withouth _path
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
end
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
* build the abilities in ad initializer Es: "menu_and_abilities.rb"
|
|
85
|
+
```ruby
|
|
86
|
+
Alchemy::Modules.register_module({
|
|
87
|
+
name: 'Posts', # custom name
|
|
88
|
+
order: 2,
|
|
89
|
+
navigation: {
|
|
90
|
+
name: 'modules.posts',
|
|
91
|
+
controller: '/admin/posts', #controller path
|
|
92
|
+
action: 'index', #action
|
|
93
|
+
icon: "question" # custom icon
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
Alchemy.register_ability(PostAbility)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
* Costruisci la form per il modello
|
|
100
|
+
```ruby
|
|
101
|
+
|
|
102
|
+
<%= base_form_container do %>
|
|
103
|
+
<div class="form_in_page">
|
|
104
|
+
<%= simple_form_for [:admin,@obj] do |f| %>
|
|
105
|
+
<fieldset>
|
|
106
|
+
|
|
107
|
+
<%= f.input :name %>
|
|
108
|
+
<%= rich_text_editor(f, :description) %>
|
|
109
|
+
<%= single_image_input(f, :picture) %>
|
|
110
|
+
<%= single_attachment_input(f, :file) %>
|
|
111
|
+
...
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
* Per elementi come subobject seguire l'esempio di codice nei test che rivedono le varie opzioni
|
|
116
|
+
* Per modelli che si legano direttamente con componenti di alchemy è necessario utilizzare delle relazioni generiche che identificato il record:
|
|
117
|
+
```ruby
|
|
118
|
+
belongs_to :picture, class_name: 'Alchemy::Picture', touch: true
|
|
119
|
+
belongs_to :alchemy_file_instance, class_name: 'Alchemy::Picture', foreign_key: :picture_id #relazione generica per i files utilizzata nel volume di elfinder
|
|
120
|
+
```
|
|
121
|
+
* Per la visualizzazione creare quindi un layout in Alchemy con attributi custom_model e custom_model_action che serve per identificare
|
|
122
|
+
la generazione dei link index e show
|
|
123
|
+
```yml
|
|
124
|
+
- name: layout_name_list
|
|
125
|
+
elements: [element_for_list]
|
|
126
|
+
custom_model: "CustomModelClass"
|
|
127
|
+
custom_model_action: "index"
|
|
128
|
+
cache: false
|
|
129
|
+
|
|
130
|
+
- name: layout_name_show
|
|
131
|
+
elements: [element_for_show]
|
|
132
|
+
custom_model: "CustomModelClass"
|
|
133
|
+
custom_model_action: "show"
|
|
134
|
+
cache: false
|
|
135
|
+
```
|
|
136
|
+
* E' necessario quindi creare le due pagine nella struttura di alchemy
|
|
137
|
+
|
|
138
|
+
## Development
|
|
139
|
+
|
|
140
|
+
git clone --recursive git@github.com:ArchimediaZerogroup/alchemy-custom-model.git
|
|
141
|
+
|
|
142
|
+
docker build -t alchemy_custom_image .
|
|
143
|
+
|
|
144
|
+
docker run -it -p3000:3000 --rm -v "$(pwd)":/app alchemy_custom_image bin/rails s -b 0.0.0.0
|
|
145
|
+
|
|
146
|
+
## License
|
|
147
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require 'bundler/setup'
|
|
3
|
+
rescue LoadError
|
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
require 'rdoc/task'
|
|
8
|
+
|
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
11
|
+
rdoc.title = 'Alchemy::Custom::Model'
|
|
12
|
+
rdoc.options << '--line-numbers'
|
|
13
|
+
rdoc.rdoc_files.include('README.md')
|
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
|
|
18
|
+
load 'rails/tasks/engine.rake'
|
|
19
|
+
|
|
20
|
+
load 'rails/tasks/statistics.rake'
|
|
21
|
+
|
|
22
|
+
require 'bundler/gem_tasks'
|
|
23
|
+
|
|
24
|
+
require 'rake/testtask'
|
|
25
|
+
|
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
|
27
|
+
t.libs << 'test'
|
|
28
|
+
t.pattern = 'test/**/*_test.rb'
|
|
29
|
+
t.verbose = false
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
task default: :test
|
|
Binary file
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
|
|
2
|
+
$(document).on("page:change turbolinks:load",function () {
|
|
3
|
+
|
|
4
|
+
$('select#change_language').on('change',function (e){
|
|
5
|
+
var url = window.location.pathname;
|
|
6
|
+
var delimiter = url.match(/\?/) ? '&' : '?';
|
|
7
|
+
Turbolinks.visit(url+delimiter+"language_id="+$(this).val());
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
});
|
|
11
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
$(document).on("'page:change turbolinks:load", function(){
|
|
2
|
+
$(".datepicker-date").datetimepicker({
|
|
3
|
+
scrollInput: false,
|
|
4
|
+
format: "d/m/Y",
|
|
5
|
+
timepicker: false,
|
|
6
|
+
datepicker: true,
|
|
7
|
+
dayOfWeekStart: 0
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
$(".datepicker-time").datetimepicker({
|
|
11
|
+
format:'H:i',
|
|
12
|
+
timepicker: true,
|
|
13
|
+
datepicker: false,
|
|
14
|
+
step: 15
|
|
15
|
+
})
|
|
16
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#= require 'alchemy/alchemy.element_editors'
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
window.CustomProxedElementEditor = $.extend {}, Alchemy.ElementEditors
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
$.extend window.CustomProxedElementEditor,
|
|
9
|
+
init: (selector = "#element_area")->
|
|
10
|
+
@element_area = $(selector)
|
|
11
|
+
@bindEvents()
|
|
12
|
+
|
|
13
|
+
@initialize_tinymce()
|
|
14
|
+
return
|
|
15
|
+
|
|
16
|
+
initialize_tinymce: ()->
|
|
17
|
+
ids = []
|
|
18
|
+
@element_area.find('.has_tinymce').each (i, e)->
|
|
19
|
+
ids.push($(e).attr("id").match(/[0-9]+/)[0])
|
|
20
|
+
Alchemy.Tinymce.init(ids)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# disattivazione del check di reload pagina
|
|
24
|
+
$(document).on 'submit', '.simple_form.alchemy', (e)=>
|
|
25
|
+
window.onbeforeunload = null;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#= require 'lodash/lodash.js'
|
|
2
|
+
|
|
3
|
+
#duplichiamo la classe
|
|
4
|
+
class CustomTinyMce extends Alchemy.Tinymce
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
#per come è stato fatto dobbiamo estendere la classe tramite i metodi che usa jquery
|
|
8
|
+
$.extend CustomTinyMce,
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# {
|
|
12
|
+
# skin: 'alchemy',
|
|
13
|
+
# width: 'auto',
|
|
14
|
+
# resize: true,
|
|
15
|
+
# autoresize_min_height: '105',
|
|
16
|
+
# autoresize_max_height: '480',
|
|
17
|
+
# menubar: false,
|
|
18
|
+
# statusbar: true,
|
|
19
|
+
# toolbar: [
|
|
20
|
+
# 'bold italic underline | strikethrough subscript superscript | numlist bullist indent outdent | removeformat | fullscreen',
|
|
21
|
+
# 'pastetext charmap hr | undo redo | alchemy_link unlink anchor | code'
|
|
22
|
+
# ],
|
|
23
|
+
# fix_list_elements: true,
|
|
24
|
+
# convert_urls: false,
|
|
25
|
+
# entity_encoding: 'raw',
|
|
26
|
+
# paste_as_text: true,
|
|
27
|
+
# element_format: 'html',
|
|
28
|
+
# branding: false
|
|
29
|
+
# }
|
|
30
|
+
|
|
31
|
+
getDefaultConfig: (id) ->
|
|
32
|
+
configs = $.extend true, {}, Alchemy.Tinymce.getDefaultConfig(id)
|
|
33
|
+
configs.init_instance_callback = @initInstanceCallback
|
|
34
|
+
|
|
35
|
+
configs.plugins += ",image"
|
|
36
|
+
configs.toolbar[1] += ' | link image'
|
|
37
|
+
configs.file_picker_callback = (callback, value, meta)->
|
|
38
|
+
|
|
39
|
+
volumes = []
|
|
40
|
+
|
|
41
|
+
if (meta.filetype == 'file')
|
|
42
|
+
volumes.push('AlchemyFiles');
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# // Provide image and alt text for the image dialog
|
|
46
|
+
if (meta.filetype == 'image')
|
|
47
|
+
volumes.push('AlchemyImages');
|
|
48
|
+
|
|
49
|
+
tinymce.activeEditor.windowManager.open({
|
|
50
|
+
file: '<%= Alchemy::Custom::Model::Engine.routes.url_helpers.admin_elfinder_ui_path() %>?'+$.param({volumes:volumes}),# Routes.admin_elfinder_ui_path(volumes:volumes), #// use an absolute path!
|
|
51
|
+
title: 'elFinder 2.1',
|
|
52
|
+
width: 900,
|
|
53
|
+
height: 450,
|
|
54
|
+
resizable: 'yes'
|
|
55
|
+
}, {
|
|
56
|
+
oninsert: (file, fm)->
|
|
57
|
+
# // URL normalization
|
|
58
|
+
url = fm.convAbsUrl(file.url);
|
|
59
|
+
|
|
60
|
+
# // Make file info
|
|
61
|
+
info = file.name + ' (' + fm.formatSize(file.size) + ')';
|
|
62
|
+
|
|
63
|
+
# // Provide file and text for the link dialog
|
|
64
|
+
if (meta.filetype == 'file')
|
|
65
|
+
callback(file.original_url, {text: info, title: info})
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# // Provide image and alt text for the image dialog
|
|
69
|
+
if (meta.filetype == 'image')
|
|
70
|
+
callback(file.original_url, {alt: info})
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
# // Provide alternative source and posted for the media dialog
|
|
74
|
+
if (meta.filetype == 'media')
|
|
75
|
+
callback(url)
|
|
76
|
+
|
|
77
|
+
return false;
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
return configs
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
initInstanceCallback: (editor) ->
|
|
85
|
+
$this = $("##{editor.id}")
|
|
86
|
+
element = $this.closest('.tinymce_container')
|
|
87
|
+
element.on 'parent_stop_sorted', _.debounce(()=>
|
|
88
|
+
id = editor.getElement().id.replace(/^tinymce_/, '')
|
|
89
|
+
editor.remove();
|
|
90
|
+
CustomTinyMce.initEditor(id)
|
|
91
|
+
, 100)
|
|
92
|
+
element.find('.spinner').remove()
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
@CustomTinyMce = CustomTinyMce
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
#= require elfinder/js/elfinder.full
|
|
2
|
+
# require js-routes
|
|
3
|
+
#= require 'eventemitter3/umd/eventemitter3'
|
|
4
|
+
|
|
5
|
+
##
|
|
6
|
+
# Classe di elfinder per autoconfigurarsi rispetto a determinate opzioni
|
|
7
|
+
# mode: Modalità di selezione:
|
|
8
|
+
# - single_selection -> indica la selezione singola
|
|
9
|
+
# - multiple_selection -> selection multipla dei files
|
|
10
|
+
# volumes -> Elenco dei volumi da montare come stringa divisa da ,
|
|
11
|
+
# AlchemyImages -> solo immagini
|
|
12
|
+
# AlchemyFiles -> solo attachments
|
|
13
|
+
# non settato -> tutti -> Alchemy
|
|
14
|
+
# nome_inventato -> dovrà avere la relativa configurazione nella volumes_cfgs e le informazioni
|
|
15
|
+
# per identificare correttamente che volume montare
|
|
16
|
+
# volumes_cfgs -> oggetto con configurazioni per i volumi
|
|
17
|
+
# l'oggetto dovrà essere composto da chiave=nome del volume usato in volumes e un oggetto con
|
|
18
|
+
# le configurazioni:
|
|
19
|
+
# {
|
|
20
|
+
# - volume = nome del volume da utilizzare in ruby come connettore
|
|
21
|
+
# - attribute = attributo nell'oggetto a cui si riferisce il collegamento del volume
|
|
22
|
+
# - object = oggetto identificato con un global_id signed
|
|
23
|
+
# }
|
|
24
|
+
#
|
|
25
|
+
class ElFinderConfigurator
|
|
26
|
+
|
|
27
|
+
constructor: (opts)->
|
|
28
|
+
@ee = new EventEmitter3;
|
|
29
|
+
|
|
30
|
+
{@mode, @volumes, @volumes_cfgs}=opts
|
|
31
|
+
|
|
32
|
+
@mode = opts.mode ? 'single_selection'
|
|
33
|
+
@volumes = opts.volumes ? null
|
|
34
|
+
@volumes_cfgs = opts.volumes_cfgs ? null
|
|
35
|
+
|
|
36
|
+
@height = opts.height ? 400 #TODO automatizzare dinamicamente l'altezza?
|
|
37
|
+
|
|
38
|
+
@el_finder = null
|
|
39
|
+
|
|
40
|
+
start: (container)->
|
|
41
|
+
@el_finder = container.elfinder(@configurations())
|
|
42
|
+
@attach_events()
|
|
43
|
+
|
|
44
|
+
configurations: ->
|
|
45
|
+
cfgs = {
|
|
46
|
+
url:'<%= Alchemy::Custom::Model::Engine.routes.url_helpers.admin_elfinder_path() %>'
|
|
47
|
+
#lang: 'it',
|
|
48
|
+
cssAutoLoad: false # Disable CSS auto loading
|
|
49
|
+
baseUrl: './'
|
|
50
|
+
height: @height,
|
|
51
|
+
commands: ['*'],
|
|
52
|
+
soundPath:'<%= asset_path('/assets/elfinder/sounds') %>',
|
|
53
|
+
reloadClearHistory: true
|
|
54
|
+
rememberLastDir: false
|
|
55
|
+
useBrowserHistory: false
|
|
56
|
+
commandsOptions:
|
|
57
|
+
search:
|
|
58
|
+
incsearch:
|
|
59
|
+
enable: false # // is enable true or false
|
|
60
|
+
# minlen: 1 # // minimum number of characters
|
|
61
|
+
# wait: 10000 # // wait milliseconds
|
|
62
|
+
searchTypes:
|
|
63
|
+
SearchMime: # // The key is search type that send to the connector
|
|
64
|
+
name: 'btnMime'# // Button text to be processed in i18n()
|
|
65
|
+
title: 'searchMime' #// Button title to be processed in i18n()
|
|
66
|
+
AlchemyTags:
|
|
67
|
+
name: 'Alchemy Tags'
|
|
68
|
+
title: 'Ricerca per tags di alchemy'
|
|
69
|
+
uiOptions: {
|
|
70
|
+
toolbar: [
|
|
71
|
+
#['home', 'back', 'forward', 'up', 'reload'],
|
|
72
|
+
#['netmount'],
|
|
73
|
+
#['mkdir', 'mkfile', 'upload'],
|
|
74
|
+
['upload'],
|
|
75
|
+
['open', 'download', 'getfile'],
|
|
76
|
+
#['undo', 'redo'],
|
|
77
|
+
['rm'],
|
|
78
|
+
#['copy', 'cut', 'paste', 'rm', 'empty', 'hide'],
|
|
79
|
+
['duplicate', 'rename', 'edit', 'resize'], #, 'chmod'
|
|
80
|
+
['selectall', 'selectnone', 'selectinvert'],
|
|
81
|
+
['quicklook'], #, 'info'
|
|
82
|
+
#['extract', 'archive'],
|
|
83
|
+
['search'],
|
|
84
|
+
['view', 'sort'],
|
|
85
|
+
#['preference', 'help'],
|
|
86
|
+
#['fullscreen']
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if(@volumes)
|
|
92
|
+
cfgs.customData = cfgs.customData || {}
|
|
93
|
+
cfgs.customData['volumes'] = @volumes.split(',')
|
|
94
|
+
if(@volumes_cfgs)
|
|
95
|
+
cfgs.customData['volumes_cfgs'] = @volumes_cfgs
|
|
96
|
+
|
|
97
|
+
if(@mode == 'single_selection')
|
|
98
|
+
cfgs.getFileCallback = (file, fm)=>
|
|
99
|
+
@emit('file_select', file, fm)
|
|
100
|
+
|
|
101
|
+
cfgs
|
|
102
|
+
|
|
103
|
+
attach_events: ()->
|
|
104
|
+
@elfinder_instance().bind 'paste', (event, fm)=>
|
|
105
|
+
@emit('paste_files', event, fm)
|
|
106
|
+
@emit('change', event, fm)
|
|
107
|
+
@elfinder_instance().bind 'upload', (event,fm)=>
|
|
108
|
+
@emit('upload', event, fm)
|
|
109
|
+
@elfinder_instance().bind 'remove', (event, fm)=>
|
|
110
|
+
@emit('remove_files', event, fm)
|
|
111
|
+
@emit('change', event, fm)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
on: ()->
|
|
115
|
+
@ee.on.apply(@ee, arguments)
|
|
116
|
+
|
|
117
|
+
once: ()->
|
|
118
|
+
@ee.once.apply(@ee, arguments)
|
|
119
|
+
|
|
120
|
+
emit: ()->
|
|
121
|
+
@ee.emit.apply(@ee, arguments)
|
|
122
|
+
|
|
123
|
+
remove: ()->
|
|
124
|
+
@el_finder.remove();
|
|
125
|
+
|
|
126
|
+
elfinder_instance: ()->
|
|
127
|
+
@el_finder.elfinder('instance')
|
|
128
|
+
|
|
129
|
+
@ElFinderConfigurator = ElFinderConfigurator
|
|
130
|
+
|
|
131
|
+
##
|
|
132
|
+
# Classe per la gestione e configurazione di elfinder e della sua apertura in modal
|
|
133
|
+
#
|
|
134
|
+
# Configurazioni presenti su data dell'activator(bottone o altro che lancia l'evento di el finder)
|
|
135
|
+
#
|
|
136
|
+
# elfinderTarget -> indica la input in cui posizionare il valore selezionato nella single selection
|
|
137
|
+
# oppure il selector da utilizzare per rimpiazzare con il contenuto proveniente dal
|
|
138
|
+
# partial generato
|
|
139
|
+
#
|
|
140
|
+
# elfinderThumbTarget -> tag in cui settare la src con la thumb dell'immagine
|
|
141
|
+
#
|
|
142
|
+
# elfinderMimeIconUpdater -> selettore css dove applicare le classi di elfinder per l'incona dell'imagine
|
|
143
|
+
#
|
|
144
|
+
#
|
|
145
|
+
# Configurazioni che vengono riportare poi verso ElFinderConfigurator
|
|
146
|
+
# elfinderMode: Modalità di selezione:
|
|
147
|
+
# - single_selection -> indica la selezione singola
|
|
148
|
+
# - multiple_selection -> selection multipla dei files
|
|
149
|
+
# elfinderVolumes -> Elenco dei volumi da montare
|
|
150
|
+
# AlchemyImages -> solo immagini
|
|
151
|
+
# AlchemyFiles -> solo attachments
|
|
152
|
+
# non settato -> tutti -> Alchemy
|
|
153
|
+
class ElFinderDialog
|
|
154
|
+
|
|
155
|
+
constructor: (@activator)->
|
|
156
|
+
options = $(@activator).data()
|
|
157
|
+
|
|
158
|
+
@opts = {
|
|
159
|
+
target: options['elfinderTarget'],
|
|
160
|
+
thumb_target: options['elfinderThumbTarget'],
|
|
161
|
+
mime_icon_updater: options['elfinderMimeIconUpdater']
|
|
162
|
+
target_upgrader: options['elfinderTargetUpgrader']
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
@elfinder = new ElFinderConfigurator({
|
|
166
|
+
mode: options['elfinderMode'],
|
|
167
|
+
volumes: options['elfinderVolumes'],
|
|
168
|
+
volumes_cfgs: options['elfinderVolumesCfgs'],
|
|
169
|
+
height: 700
|
|
170
|
+
})
|
|
171
|
+
|
|
172
|
+
@dialog_container = $("<div><div class='el_finder'></div></div>")
|
|
173
|
+
$('body').append(@dialog_container)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
attach_events: ()->
|
|
177
|
+
if(@elfinder.mode == 'single_selection')
|
|
178
|
+
@elfinder.once('file_select', (file, fm)=>
|
|
179
|
+
$(@opts.target).val(file.global_id)
|
|
180
|
+
if(@opts.thumb_target)
|
|
181
|
+
$(@opts.thumb_target).attr('src', file.tmb)
|
|
182
|
+
if(@opts.mime_icon_updater)
|
|
183
|
+
$(@opts.mime_icon_updater).attr('class', '').addClass("elfinder-cwd-icon #{fm.mime2class(file.mime)}")
|
|
184
|
+
|
|
185
|
+
@close()
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
if(@elfinder.mode == 'multiple_selection')
|
|
189
|
+
@elfinder.on 'change', (event)=>
|
|
190
|
+
reload_target_url.call(this)
|
|
191
|
+
|
|
192
|
+
@elfinder.on 'upload', (event)=>
|
|
193
|
+
reload_target_url.call(this)
|
|
194
|
+
|
|
195
|
+
reload_target_url = ->
|
|
196
|
+
$.ajax
|
|
197
|
+
url: @opts.target_upgrader
|
|
198
|
+
success: (data)=>
|
|
199
|
+
elemento_gallery = $(data).find(@opts.target)
|
|
200
|
+
$(@opts.target).html($(elemento_gallery).html())
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
open: ->
|
|
204
|
+
@dialog_container.dialog
|
|
205
|
+
width: $(document).width() * 0.7
|
|
206
|
+
modal: true
|
|
207
|
+
position: { my: "top", at: "top", of: window }
|
|
208
|
+
|
|
209
|
+
open: ()=>
|
|
210
|
+
@elfinder.start(@dialog_container.find('.el_finder'))
|
|
211
|
+
@attach_events()
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
close: ->
|
|
215
|
+
@elfinder.remove();
|
|
216
|
+
@dialog_container.dialog('close').dialog("destroy");
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
$(document).on 'click', '.open_el_finder', (e)->
|
|
220
|
+
e.preventDefault()
|
|
221
|
+
dialog = new ElFinderDialog(this)
|
|
222
|
+
dialog.open();
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
##
|
|
226
|
+
# Pulizia selezione
|
|
227
|
+
$(document).on 'click', '.clear_selection', (e)->
|
|
228
|
+
e.preventDefault()
|
|
229
|
+
opts = $(this).data();
|
|
230
|
+
$(opts.clearfieldTarget).val(null)
|
|
231
|
+
if(opts.clearfieldThumbTarget)
|
|
232
|
+
$(opts.clearfieldThumbTarget).attr('src', opts.clearfieldThumbTargetReplace)
|
|
233
|
+
if(opts.clearfieldIcon)
|
|
234
|
+
$(opts.clearfieldIcon).attr('class','')
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
|