visual_condition_builder 0.0.2
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 +155 -0
- data/Rakefile +34 -0
- data/app/assets/javascripts/visual_condition_builder/Sortable.js +1385 -0
- data/app/assets/javascripts/visual_condition_builder/autoNumeric-2.0-BETA.js +2156 -0
- data/app/assets/javascripts/visual_condition_builder/autonumeric_ujs.js +94 -0
- data/app/assets/javascripts/visual_condition_builder/condition_builder.js +633 -0
- data/app/assets/javascripts/visual_condition_builder/diacritics.js +116 -0
- data/app/assets/javascripts/visual_condition_builder/select2.full.js +6436 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/ar.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/az.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/bg.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/ca.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/cs.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/da.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/de.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/el.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/en.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/es.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/et.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/eu.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/fa.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/fi.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/fr.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/gl.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/he.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/hi.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/hr.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/hu.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/id.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/is.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/it.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/ja.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/km.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/ko.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/lt.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/lv.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/mk.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/ms.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/nb.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/nl.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/pl.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/pt-BR.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/pt.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/ro.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/ru.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/sk.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/sr-Cyrl.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/sr.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/sv.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/th.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/tr.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/uk.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/vi.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/zh-CN.js +3 -0
- data/app/assets/javascripts/visual_condition_builder/select2_i18n/zh-TW.js +3 -0
- data/app/assets/javascripts/visual_condition_builder.js +6 -0
- data/app/assets/stylesheets/visual_condition_builder/condition_builder.css +87 -0
- data/app/assets/stylesheets/visual_condition_builder/select2-bootstrap.css +722 -0
- data/app/assets/stylesheets/visual_condition_builder/select2.css +484 -0
- data/app/assets/stylesheets/visual_condition_builder.css +5 -0
- data/app/controllers/application_widget.rb +56 -0
- data/app/controllers/visual_condition_builder/application_controller.rb +5 -0
- data/app/controllers/visual_condition_builder/widgets_controller.rb +45 -0
- data/app/helpers/visual_condition_builder/application_helper.rb +74 -0
- data/app/models/visual_condition_builder/user.rb +10 -0
- data/app/views/visual_condition_builder/widgets/_widgets_list.html.erb +24 -0
- data/app/views/visual_condition_builder/widgets/index.html.erb +25 -0
- data/config/initializers/assets.rb +1 -0
- data/config/initializers/visual_condition_builder.rb +7 -0
- data/config/routes.rb +19 -0
- data/lib/generators/templates/create_taxweb_widgets_users.rb +18 -0
- data/lib/generators/templates/generic_widget.erb +12 -0
- data/lib/generators/templates/generic_widget.html.erb +2 -0
- data/lib/generators/visual_condition_builder/install_generator.rb +26 -0
- data/lib/generators/visual_condition_builder/view_generator.rb +11 -0
- data/lib/generators/visual_condition_builder/widget_generator.rb +25 -0
- data/lib/visual_condition_builder/converter.rb +22 -0
- data/lib/visual_condition_builder/dictionary.rb +166 -0
- data/lib/visual_condition_builder/engine.rb +6 -0
- data/lib/visual_condition_builder/helper.rb +19 -0
- data/lib/visual_condition_builder/version.rb +3 -0
- data/lib/visual_condition_builder.rb +9 -0
- metadata +127 -0
@@ -0,0 +1,56 @@
|
|
1
|
+
class ApplicationWidget < ::ApplicationController
|
2
|
+
include SingletonHelper
|
3
|
+
|
4
|
+
attr_singleton :refresh_interval, 0
|
5
|
+
|
6
|
+
def initialize(request)
|
7
|
+
self.request = request
|
8
|
+
end
|
9
|
+
|
10
|
+
def render_template(view_file=nil, *args)
|
11
|
+
args << {template: view_file}
|
12
|
+
render_to_string *args
|
13
|
+
end
|
14
|
+
|
15
|
+
def view(view_file=nil, klass=nil)
|
16
|
+
class_caller = klass || (caller[0].match(/(\b\w+)\.rb/)[1] rescue '')
|
17
|
+
action_caller = view_file || (caller[0].match(/`(.*)'/)[1] rescue '')
|
18
|
+
view_file = "widgets/#{class_caller.to_s.sub('_widget','')}/#{action_caller}" unless lookup_context.find_all(view_file).any?
|
19
|
+
instance_variable_set(:@view_file, view_file)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.name?
|
23
|
+
instance_variable_defined?(:@widget_name) ? instance_variable_get(:@widget_name) : ''
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.name!(value)
|
27
|
+
# define_singleton_method(:widget_name) {value}
|
28
|
+
instance_variable_set(:@widget_name, value)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.description?(attr=nil)
|
32
|
+
attr='widget' if attr.nil?
|
33
|
+
instance_variable_defined?("@description_#{attr}") ? instance_variable_get("@description_#{attr}") : ''
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.description!(*args)
|
37
|
+
if args.size == 1
|
38
|
+
instance_variable_set(:@description_widget, args[0])
|
39
|
+
elsif args.size == 2
|
40
|
+
instance_variable_set("@description_#{args[0]}", args[1])
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.widgets
|
45
|
+
# ApplicationWidget.descendants.map do |klass| #Não estava carregando no primeiro load...
|
46
|
+
Dir["#{Rails.root}/app/widgets/*.rb"].map do |file_path|
|
47
|
+
file_name = File.basename(file_path, ".rb")
|
48
|
+
klass = Object.const_get file_name.classify
|
49
|
+
actions = klass.instance_methods(false).map do |action|
|
50
|
+
{name: action, description: klass.description?(action)}
|
51
|
+
end
|
52
|
+
{code: klass.to_s.tableize.sub('_widgets',''), name: klass.name?, description: klass.description?, actions: actions}
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require_dependency "visual_condition_builder/application_controller"
|
2
|
+
|
3
|
+
module VisualConditionBuilder
|
4
|
+
class WidgetsController < ApplicationController
|
5
|
+
|
6
|
+
def load
|
7
|
+
widget = VisualConditionBuilder::Widget.new(params[:widget_name], self.request)
|
8
|
+
content = widget.html(params[:widget_action])
|
9
|
+
rescue Exception => e
|
10
|
+
content = e.message
|
11
|
+
ensure
|
12
|
+
render html: content, layout: false
|
13
|
+
end
|
14
|
+
|
15
|
+
def user
|
16
|
+
user_id = params[:id] || current_user.id
|
17
|
+
@widgets_code = VisualConditionBuilder::User.where(user_id: user_id).pluck(:widget, :action).map{|r| "#{r[0]}_#{r[1]}"}
|
18
|
+
render partial: 'widgets_list'
|
19
|
+
end
|
20
|
+
|
21
|
+
def index
|
22
|
+
end
|
23
|
+
|
24
|
+
def save
|
25
|
+
user_id = params[:user_id] || current_user.id
|
26
|
+
widgets = params[:widgets]
|
27
|
+
widget_name_user = []
|
28
|
+
action_user = []
|
29
|
+
if widgets.present?
|
30
|
+
widgets.each do |widget|
|
31
|
+
widget_name, action = widget.split('|')
|
32
|
+
if widget_name && action
|
33
|
+
widget_name_user << widget_name
|
34
|
+
action_user << action
|
35
|
+
VisualConditionBuilder::User.find_or_create_by(widget: widget_name, action: action, user_id: user_id)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
VisualConditionBuilder::User.where(user_id: user_id).where.not(widget: widget_name_user, action: action_user).destroy_all
|
40
|
+
flash[:success] = 'Alterações foram salvas com sucesso!'
|
41
|
+
redirect_to visual_condition_builder_path
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module VisualConditionBuilder
|
2
|
+
module ApplicationHelper
|
3
|
+
|
4
|
+
def build_conditions(dictionary, *args)
|
5
|
+
dictionary_name = get_dictionary_name(dictionary)
|
6
|
+
container_name = "#{dictionary_name}_condition_container"
|
7
|
+
|
8
|
+
hArgs = (args ||= []).reduce(Hash.new, :merge)
|
9
|
+
hArgs = normalize_placeholder_label(hArgs)
|
10
|
+
|
11
|
+
builder_options = {
|
12
|
+
dictionary: ObrigacaoDictionary.dictionary
|
13
|
+
}.deep_merge(hArgs)
|
14
|
+
|
15
|
+
capture do
|
16
|
+
concat(content_tag(:div, nil, id: container_name))
|
17
|
+
concat(javascript_tag(<<txtjs
|
18
|
+
$(document).ready(function () {
|
19
|
+
$('##{container_name}').conditionBuilder(#{builder_options.to_json});
|
20
|
+
});
|
21
|
+
txtjs
|
22
|
+
))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def conditions_fields(dictionary, *args)
|
27
|
+
dictionary_name = get_dictionary_name(dictionary)
|
28
|
+
container_name = "#{dictionary_name}_condition_container"
|
29
|
+
capture do
|
30
|
+
content_tag(:div, class: 'dropdown add-condition', data: {target: "##{container_name}"}) do
|
31
|
+
concat(content_tag(:button, class: 'btn btn-default dropdown-toggle', data: {toggle: 'dropdown'}, type: 'button') do
|
32
|
+
concat(I18n.t(:dropdown, default: ['Fields'], scope: [:condition_builder]))
|
33
|
+
concat(content_tag(:span, nil, class:'caret'))
|
34
|
+
end)
|
35
|
+
concat(content_tag(:ul, class: 'dropdown-menu add-condition-menu') do
|
36
|
+
create_conditions_fields_item(ObrigacaoDictionary.fields(get_dictionary_context(dictionary)))
|
37
|
+
end)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
def create_conditions_fields_item(fields)
|
44
|
+
fields.each do |field, attrs|
|
45
|
+
if field.is_a?(Hash) #GROUP
|
46
|
+
group_label = field.values.first
|
47
|
+
concat(content_tag(:li, group_label, class: 'dropdown-header'))
|
48
|
+
create_conditions_fields_item(attrs)
|
49
|
+
else
|
50
|
+
concat(content_tag(:li, link_to(attrs[:label], '#', class: 'add-condition-field', data: {field: field})))
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def get_dictionary_context(dictionary)
|
56
|
+
dictionary.is_a?(Hash) ? dictionary.values.first : :default
|
57
|
+
end
|
58
|
+
def get_dictionary_name(dictionary)
|
59
|
+
"#{dictionary.is_a?(Hash) ? dictionary.keys.first : dictionary}_#{get_dictionary_context(dictionary)}"
|
60
|
+
end
|
61
|
+
|
62
|
+
def normalize_placeholder_label(args)
|
63
|
+
args[:placeholder] ||= {}
|
64
|
+
[:fields, :operators, :values].each do |attr|
|
65
|
+
unless args[:placeholder][attr].present?
|
66
|
+
label = I18n.t(attr, default: [''], scope: [:condition_builder, :placeholder])
|
67
|
+
args[:placeholder][attr] = label if label.present?
|
68
|
+
end
|
69
|
+
end
|
70
|
+
args
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
<% ApplicationWidget.widgets.each do |widget| %>
|
2
|
+
<ul>
|
3
|
+
<li>
|
4
|
+
<b><%= widget[:name] %></b>
|
5
|
+
<br><span class="help-block"><%= widget[:description] %></span>
|
6
|
+
<ul>
|
7
|
+
<% widget[:actions].each do |action| %>
|
8
|
+
<% widget_code = "#{widget[:code]}_#{action[:name]}" %>
|
9
|
+
<li>
|
10
|
+
<div class="checkbox">
|
11
|
+
<%= label_tag widget_code do %>
|
12
|
+
<%= check_box_tag 'widgets[]', "#{widget[:code]}|#{action[:name]}", @widgets_code.include?(widget_code), {id: widget_code} %>
|
13
|
+
<b><%= action[:name].to_s.humanize %></b>
|
14
|
+
<% if action[:description].present? %>
|
15
|
+
<br><span class="help-block"><%= action[:description] %></span>
|
16
|
+
<% end %>
|
17
|
+
<% end %>
|
18
|
+
</div>
|
19
|
+
</li>
|
20
|
+
<% end %>
|
21
|
+
</ul>
|
22
|
+
</li>
|
23
|
+
</ul>
|
24
|
+
<% end %>
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<div class="row">
|
2
|
+
<div class="col-md-12">
|
3
|
+
<div class="panel panel-default">
|
4
|
+
<div class="panel-heading">
|
5
|
+
<div class="panel-title">Selecione os Widgets que deseja utilizar:</div>
|
6
|
+
</div>
|
7
|
+
<div class="panel-body">
|
8
|
+
<%= form_tag(visual_condition_builder_save_path, method: :put, class: 'widget_config') do %>
|
9
|
+
|
10
|
+
<div class="form-group">
|
11
|
+
<label class="control-label">Usuário:</label>
|
12
|
+
<%= select_tag :user_id, options_from_collection_for_select(User.all, :id, :email, current_user.id), include_blank: false, class: 'form-control widget-user-control' %>
|
13
|
+
</div>
|
14
|
+
|
15
|
+
<fieldset class="widgets_list">
|
16
|
+
<legend>Widgets</legend>
|
17
|
+
<div class="list"></div>
|
18
|
+
</fieldset>
|
19
|
+
|
20
|
+
<%= submit_tag "Salvar", class: 'btn btn-success' %>
|
21
|
+
<% end %>
|
22
|
+
</div>
|
23
|
+
</div>
|
24
|
+
</div>
|
25
|
+
</div>
|
@@ -0,0 +1 @@
|
|
1
|
+
Rails.application.config.assets.precompile += %w( visual_condition_builder.js visual_condition_builder.css )
|
data/config/routes.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Rails.application.routes.draw do
|
2
|
+
|
3
|
+
|
4
|
+
namespace :visual_condition_builder do
|
5
|
+
|
6
|
+
get 'widgets/load/:widget_name/:widget_action', to: 'widgets#load', as: 'load'
|
7
|
+
get 'widgets/user(/:id)', to: 'widgets#user', as: 'user'
|
8
|
+
get 'widgets', to: 'widgets#index', as: ''
|
9
|
+
put 'widgets/save', to: 'widgets#save', as: 'save'
|
10
|
+
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class CreateVisualConditionBuilderUsers < ActiveRecord::Migration
|
2
|
+
|
3
|
+
def up
|
4
|
+
unless table_exists?(:visual_condition_builder_users)
|
5
|
+
create_table :visual_condition_builder_users do |t|
|
6
|
+
t.references :user, index: true, foreign_key: false
|
7
|
+
t.string :widget
|
8
|
+
t.string :action
|
9
|
+
t.index [:widget, :action]
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def down
|
15
|
+
drop_table :visual_condition_builder_users if table_exists? :visual_condition_builder_users
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class <%= @widget_name %>Widget < ApplicationWidget
|
2
|
+
|
3
|
+
name! "<%= @widget_name %>"
|
4
|
+
description! "O Widget <%= @widget_name %> tem como função..."
|
5
|
+
#refresh_interval 60000 #60 segundos para refresh automático
|
6
|
+
|
7
|
+
description! :exemplo, 'Essa ação é um exemplo'
|
8
|
+
def exemplo
|
9
|
+
@data = Date.today
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'rails/generators/base'
|
2
|
+
require 'rails/generators/migration'
|
3
|
+
|
4
|
+
module VisualConditionBuilder
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
6
|
+
source_root File.expand_path("../../templates", __FILE__)
|
7
|
+
include Rails::Generators::Migration
|
8
|
+
|
9
|
+
class_option :orm
|
10
|
+
desc 'Instalando Taxweb Widgets'
|
11
|
+
|
12
|
+
desc 'Criando Migrations'
|
13
|
+
def self.next_migration_number(path)
|
14
|
+
unless @prev_migration_nr
|
15
|
+
@prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
|
16
|
+
else
|
17
|
+
@prev_migration_nr += 1
|
18
|
+
end
|
19
|
+
@prev_migration_nr.to_s
|
20
|
+
end
|
21
|
+
|
22
|
+
def create_migration_file
|
23
|
+
migration_template 'create_visual_condition_builder_users.rb', 'db/migrate/create_visual_condition_builder_users.rb'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'rails/generators/base'
|
2
|
+
|
3
|
+
module VisualConditionBuilder
|
4
|
+
class ViewGenerator < Rails::Generators::Base
|
5
|
+
source_root File.expand_path("../../../../app/views/visual_condition_builder", __FILE__)
|
6
|
+
|
7
|
+
def copy_views
|
8
|
+
directory 'widgets', 'app/views/visual_condition_builder/widgets'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rails/generators/base'
|
2
|
+
|
3
|
+
module VisualConditionBuilder
|
4
|
+
class WidgetGenerator < Rails::Generators::NamedBase
|
5
|
+
source_root File.expand_path("../../templates", __FILE__)
|
6
|
+
|
7
|
+
def generate_widget
|
8
|
+
@widget_name = file_name.classify
|
9
|
+
view_dir = "app/views/widgets/#{widget_name_file}"
|
10
|
+
|
11
|
+
template "generic_widget.erb", File.join('app/widgets', "#{widget_name_file}_widget.rb")
|
12
|
+
|
13
|
+
if self.behavior == :revoke && Dir.exists?(view_dir)
|
14
|
+
require 'fileutils'
|
15
|
+
FileUtils.rm_rf(view_dir)
|
16
|
+
elsif self.behavior == :invoke
|
17
|
+
copy_file "generic_widget.html.erb", File.join(view_dir, 'exemplo.html.erb')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def widget_name_file
|
22
|
+
file_name.underscore
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module VisualConditionBuilder
|
2
|
+
class Converter
|
3
|
+
def self.to_ransack(params)
|
4
|
+
ransack_q = {}
|
5
|
+
conditions = params.is_a?(Array) ? params : JSON.parse(params ||= '[]')
|
6
|
+
conditions.map do |p|
|
7
|
+
#TODO: Verificar se o código deve ser inserido com inteligência para juntar os campos de mesmo operador
|
8
|
+
if ransack_q["#{p[0]}_#{p[1]}"].present?
|
9
|
+
old_value = ransack_q["#{p[0]}_#{p[1]}"]
|
10
|
+
ransack_q.delete("#{p[0]}_#{p[1]}")
|
11
|
+
ransack_q["#{p[0]}_in"] = []
|
12
|
+
ransack_q["#{p[0]}_in"] << old_value
|
13
|
+
ransack_q["#{p[0]}_in"] << p[2]
|
14
|
+
else
|
15
|
+
ransack_q["#{p[0]}_#{p[1]}"] = p[2]
|
16
|
+
end
|
17
|
+
# ransack_q["#{p[0]}_#{p[1]}"] = p[2]
|
18
|
+
end
|
19
|
+
ransack_q
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
module VisualConditionBuilder
|
2
|
+
class Dictionary
|
3
|
+
class_attribute :dictionaries
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def method_missing(m, *args, &block)
|
7
|
+
if m =~ /_url|_path/
|
8
|
+
Rails.application.routes.url_helpers.send(m, args)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def dictionary(name=:default, &block)
|
13
|
+
(self.dictionaries ||= {})[name] ||= []
|
14
|
+
@dictionary_name = name
|
15
|
+
block.call if block_given?
|
16
|
+
self.dictionaries[name]
|
17
|
+
end
|
18
|
+
|
19
|
+
def fields(dictionary_name=:default)
|
20
|
+
dictionary ||= {}
|
21
|
+
self.dictionaries[dictionary_name].group_by{|h| h[:group]}.each do |group, attrs|
|
22
|
+
dictionary[group] ||= {} if group.present?
|
23
|
+
attrs.each do |attr|
|
24
|
+
if group.present?
|
25
|
+
dictionary[group][attr[:field]] = attr.slice(:label, :type)
|
26
|
+
else
|
27
|
+
dictionary[attr[:field]] = attr.slice(:label, :type)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
dictionary
|
32
|
+
end
|
33
|
+
|
34
|
+
def param(attr, *args)
|
35
|
+
#DEFAULT VALUES
|
36
|
+
args = array_hashes_to_hash(args)
|
37
|
+
args[:type] ||= 'STRING'
|
38
|
+
args[:operators] = operators_by_type(args[:type]) unless args[:operators].present?
|
39
|
+
args[:operators] = normalize_operators(args[:operators])
|
40
|
+
args[:values] ||= []
|
41
|
+
args[:group] ||= ''
|
42
|
+
if args[:group].present? && args[:group].is_a?(Symbol)
|
43
|
+
args[:label] ||= I18n.t(attr.to_sym, default: attr.to_s.humanize, scope: [:condition_dictionaries, args[:group]])
|
44
|
+
args[:field] ||= "#{args[:group]}_#{attr}"
|
45
|
+
args[:group] = {args[:group] => I18n.t(args[:group], default: args[:group].to_s, scope: [:condition_builder, :dictionaries])}
|
46
|
+
else
|
47
|
+
args[:label] ||= I18n.t(attr.to_sym, default: attr.to_s.humanize, scope: [:condition_dictionaries, dictionary_name])
|
48
|
+
args[:field] ||= attr
|
49
|
+
end
|
50
|
+
if args[:values].present? && args[:values].is_a?(Proc)
|
51
|
+
args[:values] = args[:values].call
|
52
|
+
end
|
53
|
+
self.dictionaries[@dictionary_name] << args
|
54
|
+
end
|
55
|
+
|
56
|
+
def operators_by_type(type)
|
57
|
+
type = type.present? ? type.to_s.downcase.to_sym : 'string'
|
58
|
+
operators = case type
|
59
|
+
when :date, :datetime
|
60
|
+
[:eq, :between, :today, :yesterday, :this_week, :last_week, :present, :blank]
|
61
|
+
when :time
|
62
|
+
[:eq, :between, :present, :blank]
|
63
|
+
when :decimal, :integer
|
64
|
+
[:eq, :between]
|
65
|
+
when :string
|
66
|
+
[:cont, :eq, :start, :end, :present, :blank]
|
67
|
+
else
|
68
|
+
[:eq]
|
69
|
+
end
|
70
|
+
operators.map{|op| operator_default(op) }
|
71
|
+
end
|
72
|
+
|
73
|
+
def normalize_operators(operators)
|
74
|
+
operators.map do |operator|
|
75
|
+
operator = operator_default(operator) unless operator.is_a?(Hash)
|
76
|
+
operator[:no_value] ||= false
|
77
|
+
operator[:multiple] ||= false
|
78
|
+
operator[:label] ||= operator_translate(operator[:operator])
|
79
|
+
operator
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def operators_list(op=nil)
|
84
|
+
operators = {
|
85
|
+
between: {multiple: 2},
|
86
|
+
today: {no_value: true},
|
87
|
+
yesterday: {no_value: true},
|
88
|
+
this_week: {no_value: true},
|
89
|
+
last_wee: {no_value: true},
|
90
|
+
|
91
|
+
eq: {multiple: false},
|
92
|
+
not_eq: {multiple: false},
|
93
|
+
|
94
|
+
matches: {multiple: false},
|
95
|
+
does_not_match: {multiple: false},
|
96
|
+
|
97
|
+
lt: {multiple: false},
|
98
|
+
gt: {multiple: false},
|
99
|
+
|
100
|
+
lteq: {multiple: false},
|
101
|
+
gteq: {multiple: false},
|
102
|
+
|
103
|
+
in: {multiple: true},
|
104
|
+
not_in: {multiple: true},
|
105
|
+
|
106
|
+
cont: {multiple: false},
|
107
|
+
not_cont: {multiple: false},
|
108
|
+
|
109
|
+
cont_any: {multiple: true},
|
110
|
+
not_cont_any: {multiple: true},
|
111
|
+
|
112
|
+
cont_all: {multiple: true},
|
113
|
+
not_cont_all: {multiple: true},
|
114
|
+
|
115
|
+
start: {multiple: false},
|
116
|
+
not_start: {multiple: false},
|
117
|
+
|
118
|
+
end: {multiple: false},
|
119
|
+
not_end: {multiple: false},
|
120
|
+
|
121
|
+
true: {no_value: true, multiple: false},
|
122
|
+
not_true: {no_value: true, multiple: false},
|
123
|
+
|
124
|
+
false: {no_value: true, multiple: false},
|
125
|
+
not_false: {no_value: true, multiple: false},
|
126
|
+
|
127
|
+
present: {no_value: true, multiple: false},
|
128
|
+
blank: {no_value: true, multiple: false},
|
129
|
+
|
130
|
+
null: {no_value: true, multiple: false},
|
131
|
+
not_null: {no_value: true, multiple: false},
|
132
|
+
}
|
133
|
+
if op.present?
|
134
|
+
(operators[operator_name(op)] || {})
|
135
|
+
else
|
136
|
+
operators
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def operator_default(op)
|
141
|
+
op_default = operators_list(op)
|
142
|
+
operator = {operator: operator_name(op)}
|
143
|
+
operator.deep_merge!(op_default) if op_default.present?
|
144
|
+
operator
|
145
|
+
end
|
146
|
+
|
147
|
+
def operator_translate(op)
|
148
|
+
I18n.t(op, default: op.to_s.humanize, scope: [:condition_builder, :operators])
|
149
|
+
end
|
150
|
+
|
151
|
+
def dictionary_name
|
152
|
+
self.to_s.sub('Dictionary', '').underscore.to_sym
|
153
|
+
end
|
154
|
+
|
155
|
+
def array_hashes_to_hash(array=nil)
|
156
|
+
array ||= []
|
157
|
+
array.reduce Hash.new, :merge
|
158
|
+
end
|
159
|
+
|
160
|
+
def operator_name(op)
|
161
|
+
op.to_s.downcase.to_sym
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
166
|
+
end
|