agile_rails 0.0.0.1
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/CHANGELOG.md +5 -0
- data/MIT-LICENSE +20 -0
- data/README.md +285 -0
- data/Rakefile +39 -0
- data/agile_rails.gemspec +36 -0
- data/app/assets/fonts/ibm-plex-sans-300.woff2 +0 -0
- data/app/assets/fonts/ibm-plex-sans-400.woff2 +0 -0
- data/app/assets/fonts/ibm-plex-sans-500.woff2 +0 -0
- data/app/assets/fonts/ibm-plex-sans-600.woff2 +0 -0
- data/app/assets/fonts/ibm-plex-sans-700.woff2 +0 -0
- data/app/assets/fonts/ibm-plex-sans-italic.woff2 +0 -0
- data/app/assets/images/32px.png +0 -0
- data/app/assets/images/throbber.gif +0 -0
- data/app/assets/javascripts/agile/agile.js +1489 -0
- data/app/assets/javascripts/agile/jquery-migrate.js +702 -0
- data/app/assets/javascripts/agile/jquery.bpopup.js +372 -0
- data/app/assets/javascripts/agile/jquery.datetimepicker.js +1353 -0
- data/app/assets/javascripts/agile/jstree.min.js +6 -0
- data/app/assets/javascripts/agile/select-multiple.js +459 -0
- data/app/assets/javascripts/agile/some_scripts.js +33 -0
- data/app/assets/javascripts/agile.js +22 -0
- data/app/assets/javascripts/agile_application.js +22 -0
- data/app/assets/javascripts/agile_editor.js +22 -0
- data/app/assets/stylesheets/agile/agile.css +1882 -0
- data/app/assets/stylesheets/agile/agile_apps.css +149 -0
- data/app/assets/stylesheets/agile/jquery.datetimepicker.css +304 -0
- data/app/assets/stylesheets/agile/jstree.css +1107 -0
- data/app/assets/stylesheets/agile/select-multiple.css +110 -0
- data/app/assets/stylesheets/agile/th-bg.png +0 -0
- data/app/assets/stylesheets/agile/theme.css +49 -0
- data/app/assets/stylesheets/agile.css +21 -0
- data/app/assets/stylesheets/agile_application.css +20 -0
- data/app/assets/stylesheets/agile_editor.css +19 -0
- data/app/controllers/agile_application_controller.rb +735 -0
- data/app/controllers/agile_common_controller.rb +345 -0
- data/app/controllers/agile_controller.rb +977 -0
- data/app/controllers/agile_main_controller.rb +36 -0
- data/app/controls/agile_control.rb +120 -0
- data/app/controls/agile_report.rb +364 -0
- data/app/controls/ar_category_control.rb +39 -0
- data/app/controls/ar_help_control.rb +139 -0
- data/app/controls/ar_image_control.rb +180 -0
- data/app/controls/ar_journal_control.rb +47 -0
- data/app/controls/ar_menu_item_control.rb +55 -0
- data/app/controls/ar_page_control.rb +64 -0
- data/app/controls/ar_poll_result_control.rb +84 -0
- data/app/controls/ar_setup_control.rb +62 -0
- data/app/controls/belongs_to_control.rb +61 -0
- data/app/controls/browse_models_control.rb +98 -0
- data/app/controls/settings_form_control.rb +137 -0
- data/app/forms/agile_help.yml +112 -0
- data/app/forms/agile_menu.yml +140 -0
- data/app/forms/agile_report_defaults.yml +39 -0
- data/app/forms/all_options.yml +810 -0
- data/app/forms/ar_ad.yml +121 -0
- data/app/forms/ar_big_table.yml +60 -0
- data/app/forms/ar_big_table_value.yml +52 -0
- data/app/forms/ar_browse_fields.yml +35 -0
- data/app/forms/ar_browse_models.yml +48 -0
- data/app/forms/ar_category.yml +73 -0
- data/app/forms/ar_category_as_tree.yml +31 -0
- data/app/forms/ar_design.yml +75 -0
- data/app/forms/ar_filter.yml +52 -0
- data/app/forms/ar_folder_permission.yml +56 -0
- data/app/forms/ar_folder_rule.yml +48 -0
- data/app/forms/ar_gallery.yml +55 -0
- data/app/forms/ar_image.yml +126 -0
- data/app/forms/ar_image_search.yml +83 -0
- data/app/forms/ar_journal.yml +76 -0
- data/app/forms/ar_json_ld.yml +56 -0
- data/app/forms/ar_key_value.yml +33 -0
- data/app/forms/ar_key_value_store.yml +33 -0
- data/app/forms/ar_link.yml +60 -0
- data/app/forms/ar_menu.yml +67 -0
- data/app/forms/ar_menu_item.yml +141 -0
- data/app/forms/ar_page.yml +187 -0
- data/app/forms/ar_part.yml +91 -0
- data/app/forms/ar_permission.yml +52 -0
- data/app/forms/ar_permission_rule.yml +40 -0
- data/app/forms/ar_piece.yml +106 -0
- data/app/forms/ar_policy.yml +64 -0
- data/app/forms/ar_policy_rule.yml +42 -0
- data/app/forms/ar_policy_rule_nocms.yml +40 -0
- data/app/forms/ar_poll.yml +118 -0
- data/app/forms/ar_poll_item.yml +78 -0
- data/app/forms/ar_poll_result.yml +88 -0
- data/app/forms/ar_poll_result_export.yml +35 -0
- data/app/forms/ar_removed_url.yml +41 -0
- data/app/forms/ar_role.yml +43 -0
- data/app/forms/ar_seo.yml +32 -0
- data/app/forms/ar_setup.yml +45 -0
- data/app/forms/ar_site.yml +149 -0
- data/app/forms/ar_steps_template.yml +51 -0
- data/app/forms/ar_user.yml +140 -0
- data/app/forms/ar_user_role.yml +57 -0
- data/app/forms/help/dc_category_as_tree.en +4 -0
- data/app/forms/help/dc_category_as_tree.sl +5 -0
- data/app/forms/json_ld_schema.yml +168 -0
- data/app/helpers/agile_application_helper.rb +1162 -0
- data/app/helpers/agile_category_helper.rb +128 -0
- data/app/helpers/agile_common_helper.rb +308 -0
- data/app/helpers/agile_edit_helper.rb +645 -0
- data/app/helpers/agile_helper.rb +509 -0
- data/app/helpers/agile_index_helper.rb +677 -0
- data/app/helpers/ar_image_helper.rb +128 -0
- data/app/models/agile_form_fields/action.rb +61 -0
- data/app/models/agile_form_fields/agile_form_field.rb +322 -0
- data/app/models/agile_form_fields/belongs_to.rb +112 -0
- data/app/models/agile_form_fields/check_box.rb +73 -0
- data/app/models/agile_form_fields/comment.rb +62 -0
- data/app/models/agile_form_fields/date_picker.rb +104 -0
- data/app/models/agile_form_fields/date_select.rb +68 -0
- data/app/models/agile_form_fields/datetime_picker.rb +88 -0
- data/app/models/agile_form_fields/datetime_select.rb +73 -0
- data/app/models/agile_form_fields/file_field.rb +52 -0
- data/app/models/agile_form_fields/file_select.rb +69 -0
- data/app/models/agile_form_fields/hidden_field.rb +51 -0
- data/app/models/agile_form_fields/html_field.rb +69 -0
- data/app/models/agile_form_fields/journal_diff.rb +62 -0
- data/app/models/agile_form_fields/link_to.rb +69 -0
- data/app/models/agile_form_fields/method.rb +66 -0
- data/app/models/agile_form_fields/multitext_autocomplete.rb +215 -0
- data/app/models/agile_form_fields/number_field.rb +92 -0
- data/app/models/agile_form_fields/password_field.rb +63 -0
- data/app/models/agile_form_fields/radio_button.rb +95 -0
- data/app/models/agile_form_fields/readonly.rb +77 -0
- data/app/models/agile_form_fields/select.rb +281 -0
- data/app/models/agile_form_fields/submit_tag.rb +58 -0
- data/app/models/agile_form_fields/text_area.rb +61 -0
- data/app/models/agile_form_fields/text_autocomplete.rb +171 -0
- data/app/models/agile_form_fields/text_field.rb +55 -0
- data/app/models/agile_form_fields/text_with_select.rb +94 -0
- data/app/models/agile_form_fields/tree_select.rb +170 -0
- data/app/models/ar_big_table.rb +82 -0
- data/app/models/ar_big_table_value.rb +53 -0
- data/app/models/ar_category.rb +109 -0
- data/app/models/ar_design.rb +116 -0
- data/app/models/ar_filter.rb +200 -0
- data/app/models/ar_folder_permission.rb +50 -0
- data/app/models/ar_folder_rule.rb +47 -0
- data/app/models/ar_gallery.rb +53 -0
- data/app/models/ar_image.rb +198 -0
- data/app/models/ar_internals.rb +60 -0
- data/app/models/ar_journal.rb +46 -0
- data/app/models/ar_json_ld.rb +131 -0
- data/app/models/ar_key_value_store.rb +128 -0
- data/app/models/ar_link.rb +48 -0
- data/app/models/ar_memory.rb +172 -0
- data/app/models/ar_menu.rb +144 -0
- data/app/models/ar_menu_item.rb +106 -0
- data/app/models/ar_page.rb +74 -0
- data/app/models/ar_part.rb +66 -0
- data/app/models/ar_permission.rb +180 -0
- data/app/models/ar_permission_rule.rb +65 -0
- data/app/models/ar_policy.rb +78 -0
- data/app/models/ar_policy_rule.rb +65 -0
- data/app/models/ar_poll.rb +74 -0
- data/app/models/ar_poll_item.rb +47 -0
- data/app/models/ar_poll_result.rb +38 -0
- data/app/models/ar_removed_url.rb +42 -0
- data/app/models/ar_role.rb +84 -0
- data/app/models/ar_setup.rb +115 -0
- data/app/models/ar_site.rb +68 -0
- data/app/models/ar_temp.rb +150 -0
- data/app/models/ar_user.rb +72 -0
- data/app/models/ar_user_group.rb +38 -0
- data/app/models/ar_user_role.rb +54 -0
- data/app/models/ar_visit.rb +41 -0
- data/app/models/concerns/ar_page_concern.rb +128 -0
- data/app/models/concerns/ar_part_concern.rb +48 -0
- data/app/models/concerns/ar_piece_concern.rb +48 -0
- data/app/models/concerns/ar_policy_rule_concern.rb +87 -0
- data/app/models/concerns/ar_seo_concern.rb +66 -0
- data/app/models/concerns/ar_site_concern.rb +103 -0
- data/app/models/concerns/ar_user_concern.rb +195 -0
- data/app/renderers/agile_common_renderer.rb +93 -0
- data/app/renderers/agile_renderer.rb +59 -0
- data/app/renderers/ar_ad_renderer.rb +219 -0
- data/app/renderers/ar_captcha_renderer.rb +113 -0
- data/app/renderers/ar_common_renderer.rb +90 -0
- data/app/renderers/ar_gallery_renderer.rb +107 -0
- data/app/renderers/ar_menu_renderer.rb +195 -0
- data/app/renderers/ar_page_renderer.rb +147 -0
- data/app/renderers/ar_part_renderer.rb +235 -0
- data/app/renderers/ar_piece_renderer.rb +119 -0
- data/app/renderers/ar_poll_renderer.rb +272 -0
- data/app/views/agile/_edit_stuff.html.erb +57 -0
- data/app/views/agile/_form.html.erb +24 -0
- data/app/views/agile/_result.html.erb +28 -0
- data/app/views/agile/edit.html.erb +13 -0
- data/app/views/agile/error.html.erb +2 -0
- data/app/views/agile/index.html.erb +14 -0
- data/app/views/agile/login.html.erb +19 -0
- data/app/views/agile/new.html.erb +12 -0
- data/app/views/agile_common/_help.html.erb +18 -0
- data/app/views/agile_common/_iframe_edit.html.erb +2 -0
- data/app/views/agile_common/paste_clipboard.html.erb +17 -0
- data/app/views/layouts/agile.html.erb +17 -0
- data/app/views/layouts/content.html.erb +20 -0
- data/app/views/models/dump_models.html.erb +47 -0
- data/config/initializers/kaminari_patch.rb +56 -0
- data/config/locales/agile_de.yml +138 -0
- data/config/locales/agile_en.yml +162 -0
- data/config/locales/agile_sl.yml +163 -0
- data/config/locales/datetimepicker.yml +19 -0
- data/config/locales/de.yml +231 -0
- data/config/locales/en.yml +13 -0
- data/config/locales/kaminari.yml +26 -0
- data/config/locales/models_en.yml +1032 -0
- data/config/locales/models_sl.yml +1065 -0
- data/config/locales/sl.yml +211 -0
- data/db/migrate/20240120160001_add_sessions_table.rb +12 -0
- data/db/migrate/20240120160002_ar_big_table.rb +17 -0
- data/db/migrate/20240120160003_ar_big_table_value.rb +18 -0
- data/db/migrate/20240120160004_ar_category.rb +22 -0
- data/db/migrate/20240120160005_ar_design.rb +20 -0
- data/db/migrate/20240120160006_ar_filter.rb +17 -0
- data/db/migrate/20240120160007_ar_gallery.rb +21 -0
- data/db/migrate/20240120160008_ar_journal.rb +19 -0
- data/db/migrate/20240120160009_ar_key_value_store.rb +11 -0
- data/db/migrate/20240120160010_ar_link.rb +19 -0
- data/db/migrate/20240120160011_ar_memory.rb +8 -0
- data/db/migrate/20240120160012_ar_menu.rb +21 -0
- data/db/migrate/20240120160013_ar_menu_item.rb +28 -0
- data/db/migrate/20240120160014_ar_page.rb +50 -0
- data/db/migrate/20240120160015_ar_part.rb +33 -0
- data/db/migrate/20240120160016_ar_permission.rb +16 -0
- data/db/migrate/20240120160017_ar_permission_rule.rb +17 -0
- data/db/migrate/20240120160018_ar_piece.rb +28 -0
- data/db/migrate/20240120160019_ar_policy.rb +21 -0
- data/db/migrate/20240120160020_ar_policy_rule.rb +18 -0
- data/db/migrate/20240120160021_ar_poll.rb +27 -0
- data/db/migrate/20240120160022_ar_poll_item.rb +23 -0
- data/db/migrate/20240120160023_ar_poll_result.rb +14 -0
- data/db/migrate/20240120160024_ar_removed_url.rb +16 -0
- data/db/migrate/20240120160025_ar_role.rb +17 -0
- data/db/migrate/20240120160026_ar_site.rb +37 -0
- data/db/migrate/20240120160027_ar_temp.rb +11 -0
- data/db/migrate/20240120160028_ar_user.rb +42 -0
- data/db/migrate/20240120160029_ar_user_group.rb +12 -0
- data/db/migrate/20240120160030_ar_user_role.rb +18 -0
- data/db/migrate/20240120160031_ar_visit.rb +15 -0
- data/db/migrate/20240703016001_ar_setup.rb +16 -0
- data/db/migrate/20240703016002_ar_folder_permission.rb +15 -0
- data/db/migrate/20240703016003_ar_folder_rule.rb +14 -0
- data/db/migrate/20250115000001_ar_image.rb +25 -0
- data/lib/agile/configuration.rb +43 -0
- data/lib/agile/engine.rb +29 -0
- data/lib/agile/version.rb +27 -0
- data/lib/agile.rb +282 -0
- data/lib/agile_rails.rb +1 -0
- data/lib/generators/agile/USAGE +11 -0
- data/lib/generators/agile/new_form_generator.rb +369 -0
- data/lib/generators/convert_to_ar/convert_to_ar_generator.rb +158 -0
- data/lib/tasks/agile_db_clone.rake +132 -0
- data/lib/tasks/agile_db_export_to_yaml.rake +37 -0
- data/lib/tasks/agile_db_migrate.rake +35 -0
- metadata +414 -0
@@ -0,0 +1,509 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2024+ Damjan Rems
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#+
|
23
|
+
|
24
|
+
###########################################################################
|
25
|
+
#
|
26
|
+
# AgileHelper module defines common methods used for AgileRails forms.
|
27
|
+
#
|
28
|
+
###########################################################################
|
29
|
+
module AgileHelper
|
30
|
+
# javascript part created by form helpers
|
31
|
+
attr_reader :js
|
32
|
+
|
33
|
+
############################################################################
|
34
|
+
# Creates code for script action type.
|
35
|
+
############################################################################
|
36
|
+
def agile_script_action(yaml)
|
37
|
+
icon = agile_icon_for_link yaml['icon']
|
38
|
+
yaml['html'] ||= {}
|
39
|
+
yaml['html']['data-url'] = 'script'
|
40
|
+
yaml['html']['data-request'] = 'script'
|
41
|
+
yaml['html']['data-script'] = (yaml['js'] || yaml['script']).to_s
|
42
|
+
yaml['html']['class'] ||= 'ar-link-ajax'
|
43
|
+
attributes = yaml['html'].map { |k, v| "#{k}=\"#{v}\"" }.join(' ')
|
44
|
+
%(<li><div #{attributes}>#{icon} #{ t(yaml['caption'], yaml['caption']) }</div></li>)
|
45
|
+
end
|
46
|
+
|
47
|
+
############################################################################
|
48
|
+
# Will return field form definition if field is defined on form. Field definition
|
49
|
+
# will then be used for creating filter input field.
|
50
|
+
############################################################################
|
51
|
+
def self.get_field_form_definition(name, form) #:nodoc:
|
52
|
+
return if form['form'].nil?
|
53
|
+
|
54
|
+
found = nil
|
55
|
+
if form['form']['tabs']
|
56
|
+
form['form']['tabs'].each do |tab, data|
|
57
|
+
found = data.find{ |k, v| k.is_a?(Integer) && v['name'] == name }
|
58
|
+
break if found
|
59
|
+
end
|
60
|
+
elsif form['form']['fields']
|
61
|
+
found = form['form']['fields'].find{ |k, v| k.is_a?(Integer) && v['name'] == name }
|
62
|
+
end
|
63
|
+
found ? found.last : nil
|
64
|
+
end
|
65
|
+
|
66
|
+
############################################################################
|
67
|
+
# Return field code, label and help text for a field defined on a AgileRails Form.
|
68
|
+
#
|
69
|
+
# Parameters:
|
70
|
+
# options : Hash : Field definition
|
71
|
+
#
|
72
|
+
# Returns: Array[3]
|
73
|
+
# field_html : String : HTML code for field definition
|
74
|
+
# label : String : Label text
|
75
|
+
# help : String : Help text
|
76
|
+
############################################################################
|
77
|
+
def agile_field_label_help(options)
|
78
|
+
label, help = agile_label_help(options)
|
79
|
+
# create field object from type and call its render method
|
80
|
+
if options['type'].present?
|
81
|
+
klass_string = options['type'].camelize
|
82
|
+
field_html = if AgileFormFields.const_defined?(klass_string) # when field type defined
|
83
|
+
klass = AgileFormFields.const_get(klass_string)
|
84
|
+
field = klass.new(self, @record, options).render
|
85
|
+
@js += field.js
|
86
|
+
@css += field.css
|
87
|
+
field.html
|
88
|
+
else
|
89
|
+
"Error: Field type #{options['type']} not defined!"
|
90
|
+
end
|
91
|
+
else
|
92
|
+
"Error: Field type missing!"
|
93
|
+
end
|
94
|
+
[field_html, label, help]
|
95
|
+
end
|
96
|
+
|
97
|
+
############################################################################
|
98
|
+
# Return label and help text for a field defined on Form.
|
99
|
+
#
|
100
|
+
# Parameters:
|
101
|
+
# options : Hash : Field definition
|
102
|
+
#
|
103
|
+
# Returns:
|
104
|
+
# label : String : Label text
|
105
|
+
# help : String : Help text
|
106
|
+
############################################################################
|
107
|
+
def agile_label_help(options)
|
108
|
+
# no label or help in comments
|
109
|
+
return [nil, nil] if %w[comment action].include?(options['type'])
|
110
|
+
|
111
|
+
label = options['caption'] || options['text'] || options['label']
|
112
|
+
#label = '' if options['type'] == 'check_box'
|
113
|
+
if options['name']
|
114
|
+
label = if label.to_s.empty?
|
115
|
+
t_label_for_field(options['name'], options['name'].capitalize.gsub('_',' ') )
|
116
|
+
elsif options['name']
|
117
|
+
t(label, label)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
# help text can be defined in form or in translations starting with helpers. or as helpers.help.collection.field
|
121
|
+
help = options['help']
|
122
|
+
if help.blank?
|
123
|
+
help = if options['name']
|
124
|
+
# if defined as i18n_prefix replace "label" with "help"
|
125
|
+
prefix = @form['i18n_prefix'] ? @form['i18n_prefix'].sub('label', 'help') : "helpers.help.#{@form['table']}"
|
126
|
+
"#{prefix}.#{options['name']}"
|
127
|
+
end
|
128
|
+
help = help.to_s
|
129
|
+
end
|
130
|
+
help = t(help, ' ') if help.to_s.match(/help\./)
|
131
|
+
|
132
|
+
[label, help]
|
133
|
+
end
|
134
|
+
|
135
|
+
############################################################################
|
136
|
+
# Return label and help for tab on Form.
|
137
|
+
#
|
138
|
+
# Parameters:
|
139
|
+
# options : String : Tab name on form
|
140
|
+
#
|
141
|
+
# Returns:
|
142
|
+
# label : String : Label text
|
143
|
+
# help : String : Help text
|
144
|
+
############################################################################
|
145
|
+
def agile_tab_label_help(tab_name)
|
146
|
+
label = @form.dig('form', 'tabs', tab_name, 'caption') || tab_name
|
147
|
+
label = t(label, t_label_for_field(label, label))
|
148
|
+
help = @form.dig('form', 'tabs', tab_name, 'help') || "helpers.help.#{@form['table']}.#{tab_name}"
|
149
|
+
help = t(help, t_label_for_field(help, help))
|
150
|
+
help = nil if help.match('helpers.') # help not found in translation
|
151
|
+
|
152
|
+
[label, help]
|
153
|
+
end
|
154
|
+
|
155
|
+
############################################################################
|
156
|
+
# Creates code for including data entry field in index actions.
|
157
|
+
############################################################################
|
158
|
+
def agile_field_action(yaml)
|
159
|
+
# assign value if value found in parameters
|
160
|
+
if params['record']
|
161
|
+
value = params['record'][yaml['name']]
|
162
|
+
params["p_#{yaml['name']}"] = value
|
163
|
+
end
|
164
|
+
# find field definition on form
|
165
|
+
if ( field_definition = AgileHelper.get_field_form_definition(yaml['name'], @form) )
|
166
|
+
# some options may be redefined
|
167
|
+
field_definition['size'] = yaml['size'] if yaml['size']
|
168
|
+
field, label, help = agile_field_label_help(field_definition)
|
169
|
+
else
|
170
|
+
yaml['type'] = yaml['field_type']
|
171
|
+
field, label, help = agile_field_label_help(yaml)
|
172
|
+
end
|
173
|
+
# input field will have label as placeholder
|
174
|
+
field = field.sub('input',"input placeholder=\"#{label}\"")
|
175
|
+
%(<li class="no-background">#{field}</li>)
|
176
|
+
end
|
177
|
+
|
178
|
+
############################################################################
|
179
|
+
# Create ex. class="my-class" html code from html options for action
|
180
|
+
############################################################################
|
181
|
+
def agile_get_html_data(yaml)
|
182
|
+
return '' if yaml.blank?
|
183
|
+
|
184
|
+
yaml.reject{ |k, v| v.nil? }.map{ |k, v| "#{k}=\"#{v}\"" }.join(' ')
|
185
|
+
end
|
186
|
+
|
187
|
+
############################################################################
|
188
|
+
# There are several options for defining caption (caption,label, text). This method
|
189
|
+
# will ensure that caption is returned anyhow provided.
|
190
|
+
############################################################################
|
191
|
+
def agile_get_caption(yaml)
|
192
|
+
yaml['caption'] || yaml['text'] || yaml['label']
|
193
|
+
end
|
194
|
+
|
195
|
+
############################################################################
|
196
|
+
# Creates code for link, ajax or windows action for index or form actions.
|
197
|
+
#
|
198
|
+
# Parameters:
|
199
|
+
# yaml: Hash : Action definition
|
200
|
+
# record : Object : Currently selected record if available
|
201
|
+
# action_active : Boolean : Is action active or disabled
|
202
|
+
#
|
203
|
+
# Returns:
|
204
|
+
# String : HTML code for action
|
205
|
+
############################################################################
|
206
|
+
def agile_link_ajax_window_submit_action(yaml, record = nil, action_active = true)
|
207
|
+
parms = {}
|
208
|
+
caption = agile_get_caption(yaml)
|
209
|
+
caption = caption ? t(caption.downcase.to_s, caption) : nil
|
210
|
+
icon = yaml['icon'] ? mi_icon(yaml['icon']).to_s : ''
|
211
|
+
# action is not active
|
212
|
+
unless agile_is_action_active?(yaml)
|
213
|
+
return %(<li><div class="ar-link-no">#{icon} #{caption}</div></li>)
|
214
|
+
end
|
215
|
+
# set data-confirm when confirm shortcut present
|
216
|
+
yaml['html'] ||= {}
|
217
|
+
text = yaml['html']['data-confirm'] || yaml['confirm']
|
218
|
+
yaml['html']['data-confirm'] = t(text) if text.present?
|
219
|
+
|
220
|
+
text = yaml['html']['title'] || yaml['title']
|
221
|
+
yaml['html']['title'] = t(text) if text.present?
|
222
|
+
|
223
|
+
yaml['html']['target'] ||= yaml['target']
|
224
|
+
# direct url
|
225
|
+
if yaml['url']
|
226
|
+
parms['url'] = yaml['url']
|
227
|
+
parms['idr'] = record.id if record
|
228
|
+
# make url from action controller
|
229
|
+
else
|
230
|
+
parms['controller'] = yaml['controller'] || :agile
|
231
|
+
parms['action'] = yaml['action']
|
232
|
+
parms['table'] = yaml['table'] || @form['table']
|
233
|
+
parms['form_name'] = yaml['form_name']
|
234
|
+
parms['control'] = yaml['control'] if yaml['control']
|
235
|
+
parms['id'] = record.id if record
|
236
|
+
end
|
237
|
+
# add current id to parameters
|
238
|
+
parms['id'] = record.id if record
|
239
|
+
# overwrite with or add additional parameters from environment or record
|
240
|
+
yaml['params'].each { |k, v| parms[k] = agile_value_for_parameter(v, record) } if yaml['params']
|
241
|
+
|
242
|
+
parms['table'] = parms['table'].underscore if parms['table'] # might be CamelCase
|
243
|
+
# error if controller parameter is missing
|
244
|
+
return "<li>#{'Controller not defined'}</li>" if parms['controller'].nil? && parms['url'].nil?
|
245
|
+
|
246
|
+
html_data = agile_get_html_data(yaml['html'])
|
247
|
+
url_forward_params(parms)
|
248
|
+
url = url_for(parms) rescue 'URL error'
|
249
|
+
url = nil if parms['url'] == '#'
|
250
|
+
request = yaml['request'] || yaml['method'] || 'get'
|
251
|
+
|
252
|
+
code = case yaml['type']
|
253
|
+
# ajax button
|
254
|
+
when 'ajax'
|
255
|
+
clas = 'ar-link-ajax'
|
256
|
+
%(<div class="#{clas}" data-url="#{action_active ? url : ''}" #{html_data}
|
257
|
+
data-request="#{request}" title="#{yaml['title']}">#{icon}#{caption}</div>)
|
258
|
+
|
259
|
+
# submit button
|
260
|
+
when 'submit'
|
261
|
+
# It's dirty hack, but will prevent not authorized message and render index action correctly
|
262
|
+
parms[:filter] = 'on'
|
263
|
+
url = url_for(parms) rescue 'URL error'
|
264
|
+
clas = 'ar-action-submit'
|
265
|
+
%(<div class="#{clas}" data-url="#{action_active ? url : ''}" #{html_data}
|
266
|
+
data-request="#{request}" title="#{yaml['title']}">#{icon}#{caption}</div>)
|
267
|
+
|
268
|
+
# link button
|
269
|
+
when 'link'
|
270
|
+
yaml['html'] = agile_yaml_add_option(yaml['html'], class: 'ar-link')
|
271
|
+
link = agile_link_to(caption, yaml['icon'], parms, yaml['html'] )
|
272
|
+
(action_active ? link : caption).to_s
|
273
|
+
|
274
|
+
# open window
|
275
|
+
when 'window'
|
276
|
+
clas = 'ar-link ar-window-open'
|
277
|
+
%(<div class="#{clas}" data-url="#{action_active ? url : ''}" #{html_data}>#{icon}#{caption}</div>)
|
278
|
+
|
279
|
+
# popup dialog
|
280
|
+
when 'popup'
|
281
|
+
clas = 'ar-link ar-popup-open'
|
282
|
+
%(<div class="#{clas}" data-url="#{action_active ? url : ''}" #{html_data}>#{icon}#{caption}</div>)
|
283
|
+
|
284
|
+
else
|
285
|
+
'Type error!'
|
286
|
+
end
|
287
|
+
"<li>#{code}</li>"
|
288
|
+
end
|
289
|
+
|
290
|
+
############################################################################
|
291
|
+
# Add new option to yaml. Subroutine of agile_link_ajax_window_submit_action.
|
292
|
+
############################################################################
|
293
|
+
def agile_yaml_add_option(source, options) #nodoc
|
294
|
+
options.each do |k, v|
|
295
|
+
key = k.to_s
|
296
|
+
source[key] ||= ''
|
297
|
+
# only if not already present
|
298
|
+
source[key] += " #{v}" unless source[key].match(v.to_s)
|
299
|
+
end
|
300
|
+
source
|
301
|
+
end
|
302
|
+
|
303
|
+
############################################################################
|
304
|
+
# Log exception to rails log. Usefull for debugging eval errors.
|
305
|
+
############################################################################
|
306
|
+
def agile_log_exception(exception, msg = '')
|
307
|
+
log = "\n*** ERROR ***\n"
|
308
|
+
log += exception ? "#{msg}: #{exception.message}\n#{exception.backtrace.first.inspect}\n" : msg.to_s
|
309
|
+
log += "\nAgileRails Form: #{AgileHelper.form_param(params)}, line: #{session[:form_processing]}\n"
|
310
|
+
|
311
|
+
logger.error log
|
312
|
+
end
|
313
|
+
|
314
|
+
############################################################################
|
315
|
+
# Will return form id, to be used on each form for simpler css selecting.
|
316
|
+
############################################################################
|
317
|
+
def agile_form_id
|
318
|
+
%( id=#{AgileHelper.form_param(params) || AgileHelper.table_param(params)} )
|
319
|
+
end
|
320
|
+
|
321
|
+
############################################################################
|
322
|
+
# Will return form_name from parameter regardless if set as form_name or just f.
|
323
|
+
############################################################################
|
324
|
+
def self.form_param(params)
|
325
|
+
params[:form_name] || params[:f]
|
326
|
+
end
|
327
|
+
|
328
|
+
############################################################################
|
329
|
+
# Will return table name from parameter regardless if set as table or just t.
|
330
|
+
############################################################################
|
331
|
+
def self.table_param(params)
|
332
|
+
params[:table] || params[:t]
|
333
|
+
end
|
334
|
+
|
335
|
+
########################################################################
|
336
|
+
# Searches forms path for file_name and returns full file name or nil if not found.
|
337
|
+
#
|
338
|
+
# @param [String] Form file name. File name can be passed as gem_name.filename. This can
|
339
|
+
# be useful when you are extending form but want to retain same name as original form
|
340
|
+
# For example. You are extending agile_user form from AgileRails gem and want to
|
341
|
+
# retain same agile_user form name, because it is used in AgileRails application menu.
|
342
|
+
# This can be done by setting agile_rails.agile_user as extend option.
|
343
|
+
#
|
344
|
+
# @return [String] Form file name including path or nil if not found.
|
345
|
+
########################################################################
|
346
|
+
def self.form_file_find(form_file)
|
347
|
+
form_path = nil
|
348
|
+
form_path, form_file = form_file.split(/\.|\//) if form_file.match(/\.|\//)
|
349
|
+
|
350
|
+
Agile.paths(:forms).reverse.each do |path|
|
351
|
+
f = "#{path}/#{form_file}.yml"
|
352
|
+
return f if File.exist?(f) && (form_path.nil? || path.to_s.match(/\/#{form_path}(-|\/)/i))
|
353
|
+
end
|
354
|
+
raise "Exception: Form file #{form_file}.yml not found!"
|
355
|
+
end
|
356
|
+
|
357
|
+
########################################################################
|
358
|
+
# Merges two forms when current form extends other form. Subroutine of agile_form_read.
|
359
|
+
# With a little help of https://www.ruby-forum.com/topic/142809
|
360
|
+
########################################################################
|
361
|
+
def self.forms_merge(hash1, hash2)
|
362
|
+
target = hash1.dup
|
363
|
+
hash2.keys.each do |key|
|
364
|
+
if hash2[key].is_a?(Hash) && hash1[key].is_a?(Hash)
|
365
|
+
target[key] = AgileHelper.forms_merge(hash1[key], hash2[key])
|
366
|
+
next
|
367
|
+
end
|
368
|
+
target[key] = hash2[key] == '/' ? nil : hash2[key]
|
369
|
+
end
|
370
|
+
# delete keys with nil value
|
371
|
+
target.delete_if { |k, v| v.nil? }
|
372
|
+
end
|
373
|
+
|
374
|
+
####################################################################
|
375
|
+
# Wrapper for i18 t method, with some spice added. If translation is not found English
|
376
|
+
# translation value will be returned. And if still not found default value will be returned if passed.
|
377
|
+
#
|
378
|
+
# Parameters:
|
379
|
+
# [key] String. String to be translated into locale.
|
380
|
+
# [default] String. Value returned if translation is not found.
|
381
|
+
#
|
382
|
+
# Example:
|
383
|
+
# t('translate.this','Enter text for ....')
|
384
|
+
#
|
385
|
+
# Returns:
|
386
|
+
# String. Translated text.
|
387
|
+
####################################################################
|
388
|
+
def self.t(key, default = nil)
|
389
|
+
return default if key.nil?
|
390
|
+
|
391
|
+
c = I18n.t(key)
|
392
|
+
if c.class == Hash || c.match(/translation missing/i)
|
393
|
+
c = I18n.t(key, locale: 'en')
|
394
|
+
# Still not found. Return default if set
|
395
|
+
if c.class == Hash || c.match(/translation missing/i)
|
396
|
+
c = default.nil? ? key : default
|
397
|
+
end
|
398
|
+
end
|
399
|
+
c
|
400
|
+
end
|
401
|
+
|
402
|
+
###########################################################################
|
403
|
+
# When select field is used on form options for select can be provided by
|
404
|
+
# helpers.label.table_name.choices_for_name locale. This is how select
|
405
|
+
# field options are translated. Method returns selected choice translated
|
406
|
+
# to current locale.
|
407
|
+
#
|
408
|
+
# Parameters:
|
409
|
+
# [model] String. Table (table) model name (lowercase).
|
410
|
+
# [field] String. Field name used.
|
411
|
+
# [value] String. Value of field which translation will be returned.
|
412
|
+
#
|
413
|
+
# Example:
|
414
|
+
# # usage in program. Choice values for state are 'Deactivated:0,Active:1,Waiting:2'
|
415
|
+
# agile_text_for_value('agile_user', 'state', @record.active )
|
416
|
+
#
|
417
|
+
# # usage in form
|
418
|
+
# columns:
|
419
|
+
# 2:
|
420
|
+
# name: state
|
421
|
+
# eval: agile_text_for_value agile_user, state
|
422
|
+
#
|
423
|
+
# Returns:
|
424
|
+
# String. Descriptive text (translated) for selected choice value.
|
425
|
+
############################################################################
|
426
|
+
def self.name_for_value(model, field, value)
|
427
|
+
return '' if value.nil?
|
428
|
+
|
429
|
+
choices = t("helpers.label.#{model}.choices_for_#{field}")
|
430
|
+
values = choices.chomp.split(',').map{ _1.split(':') }
|
431
|
+
values.each{ |e| return e.first if e.last.to_s == value.to_s }
|
432
|
+
'???'
|
433
|
+
end
|
434
|
+
|
435
|
+
############################################################################
|
436
|
+
# Returns html code for displaying date/time formatted by strftime. Will return '' if value is nil.
|
437
|
+
#
|
438
|
+
# Parameters:
|
439
|
+
# [value] Date/DateTime/Time.
|
440
|
+
# [format] String. strftime format mask. Defaults to locale's default format.
|
441
|
+
############################################################################
|
442
|
+
def self.format_date_time(value, format = nil)
|
443
|
+
return '' if value.blank?
|
444
|
+
|
445
|
+
format ||= value.class == Date ? t('date.formats.default') : t('time.formats.default')
|
446
|
+
if format.size == 1
|
447
|
+
format = format.match(/d/i) ? t('date.formats.default') : t('time.formats.default')
|
448
|
+
end
|
449
|
+
#value.localtime.strftime(format)
|
450
|
+
value.strftime(format)
|
451
|
+
end
|
452
|
+
|
453
|
+
############################################################################
|
454
|
+
# Returns html code for displaying formatted number.
|
455
|
+
#
|
456
|
+
# Parameters:
|
457
|
+
# [value] Numeric number.
|
458
|
+
# [decimals] Integer. Number of decimals
|
459
|
+
# [separator] String. Decimals separator
|
460
|
+
# [delimiter] String. Thousands delimiter.
|
461
|
+
# [currency] String. Currency symbol if applied to result string.
|
462
|
+
############################################################################
|
463
|
+
def self.format_number(value = 0, decimals = nil, separator = nil, delimiter = nil, currency = nil)
|
464
|
+
decimals ||= I18n.t('number.currency.format.precision')
|
465
|
+
separator ||= I18n.t('number.currency.format.separator')
|
466
|
+
separator = '' if decimals == 0
|
467
|
+
delimiter ||= I18n.t('number.currency.format.delimiter')
|
468
|
+
whole, dec = value.to_s.split('.')
|
469
|
+
whole = '0' if whole.blank?
|
470
|
+
# remove and remember sign
|
471
|
+
sign = ''
|
472
|
+
if whole[0] == '-'
|
473
|
+
whole.delete_prefix!('-')
|
474
|
+
sign = '-'
|
475
|
+
end
|
476
|
+
# format decimals
|
477
|
+
dec ||= '0'
|
478
|
+
dec = dec.ljust(decimals, '0')[0, decimals]
|
479
|
+
# slice whole on chunks of 3
|
480
|
+
whole_a = []
|
481
|
+
while whole.size > 0 do
|
482
|
+
n = whole.size >= 3 ? 3 : whole.size
|
483
|
+
whole_a << whole.slice!(n*-1, n)
|
484
|
+
end
|
485
|
+
# put it all back
|
486
|
+
"#{sign}#{whole_a.reverse.join(delimiter)}#{separator}#{dec}"
|
487
|
+
end
|
488
|
+
|
489
|
+
####################################################################
|
490
|
+
# Returns true if parameter has value of 0, false, no, none or -.
|
491
|
+
# Returns value of default if parameter has nil value.
|
492
|
+
#
|
493
|
+
# Parameters:
|
494
|
+
# [what] String/boolean/Integer.
|
495
|
+
# [default] Default value when what has value of nil. False by default.
|
496
|
+
#
|
497
|
+
# Example:
|
498
|
+
# agile_dont?('none') # => true
|
499
|
+
# agile_dont?('-') # => true
|
500
|
+
# agile_dont?(1) # => false
|
501
|
+
# agile_dont?(nil, true) # => true
|
502
|
+
####################################################################
|
503
|
+
def self.dont?(what, default = false)
|
504
|
+
return default if what.nil?
|
505
|
+
|
506
|
+
%w(0 n - no none false).include?(what.to_s.downcase.strip)
|
507
|
+
end
|
508
|
+
|
509
|
+
end
|