engine2 1.0.4 → 1.0.9

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.
Files changed (131) hide show
  1. checksums.yaml +5 -5
  2. data/Gemfile +0 -0
  3. data/Rakefile +4 -4
  4. data/app/{engine2actions.coffee → actions.coffee} +341 -215
  5. data/app/app.coffee +0 -0
  6. data/app/app.css +17 -0
  7. data/app/engine2.coffee +158 -208
  8. data/app/modal.coffee +138 -0
  9. data/bower.json +4 -2
  10. data/conf/message.yaml +5 -0
  11. data/conf/message_pl.yaml +7 -2
  12. data/config.coffee +24 -12
  13. data/engine2.gemspec +8 -8
  14. data/lib/engine2.rb +12 -10
  15. data/lib/engine2/action.rb +1338 -133
  16. data/lib/engine2/action/array.rb +189 -0
  17. data/lib/engine2/{meta/decode_meta.rb → action/decode.rb} +52 -21
  18. data/lib/engine2/action/delete.rb +64 -0
  19. data/lib/engine2/action/form.rb +16 -0
  20. data/lib/engine2/{meta/infra_meta.rb → action/infra.rb} +123 -89
  21. data/lib/engine2/action/link.rb +117 -0
  22. data/lib/engine2/action/list.rb +333 -0
  23. data/lib/engine2/action/save.rb +28 -0
  24. data/lib/engine2/action/view.rb +8 -0
  25. data/lib/engine2/action_node.rb +221 -0
  26. data/lib/engine2/core.rb +175 -87
  27. data/lib/engine2/handler.rb +14 -13
  28. data/lib/engine2/model.rb +85 -43
  29. data/lib/engine2/models/Files.rb +4 -1
  30. data/lib/engine2/models/UserInfo.rb +6 -3
  31. data/lib/engine2/post_bootstrap.rb +4 -3
  32. data/lib/engine2/pre_bootstrap.rb +10 -6
  33. data/lib/engine2/scheme.rb +107 -65
  34. data/lib/engine2/templates.rb +41 -6
  35. data/lib/engine2/type_info.rb +51 -23
  36. data/lib/engine2/version.rb +2 -1
  37. data/package.json +22 -16
  38. data/public/favicon.ico +0 -0
  39. data/public/img/ajax-loader-dark.gif +0 -0
  40. data/public/img/ajax-loader.gif +0 -0
  41. data/views/fields/blob.slim +1 -1
  42. data/views/fields/bs_select.slim +2 -2
  43. data/views/fields/bsselect_picker.slim +4 -4
  44. data/views/fields/bsselect_picker_opt.slim +5 -5
  45. data/views/fields/checkbox.slim +4 -4
  46. data/views/fields/checkbox_button.slim +6 -0
  47. data/views/fields/checkbox_buttons.slim +3 -3
  48. data/views/fields/checkbox_buttons_opt.slim +3 -3
  49. data/views/fields/currency.slim +2 -2
  50. data/views/fields/date.slim +4 -4
  51. data/views/fields/date_range.slim +9 -9
  52. data/views/fields/date_time.slim +9 -9
  53. data/views/fields/datetime.slim +8 -8
  54. data/views/fields/decimal.slim +1 -1
  55. data/views/fields/decimal_date.slim +3 -3
  56. data/views/fields/decimal_time.slim +3 -3
  57. data/views/fields/email.slim +3 -3
  58. data/views/fields/file_store.slim +11 -11
  59. data/views/fields/input_text.slim +4 -4
  60. data/views/fields/integer.slim +1 -1
  61. data/views/fields/list_bsmselect.slim +20 -0
  62. data/views/fields/list_bsselect.slim +5 -5
  63. data/views/fields/list_bsselect_opt.slim +6 -6
  64. data/views/fields/list_buttons.slim +1 -1
  65. data/views/fields/list_buttons_opt.slim +2 -2
  66. data/views/fields/list_mbuttons.slim +9 -0
  67. data/views/fields/list_mbuttons_opt.slim +11 -0
  68. data/views/fields/list_mselect.slim +12 -0
  69. data/views/fields/list_select.slim +4 -4
  70. data/views/fields/list_select_opt.slim +5 -5
  71. data/views/fields/password.slim +4 -4
  72. data/views/fields/radio_checkbox.slim +3 -3
  73. data/views/fields/scaffold.slim +2 -2
  74. data/views/fields/scaffold_picker.slim +5 -5
  75. data/views/fields/select_picker.slim +3 -3
  76. data/views/fields/select_picker_opt.slim +4 -4
  77. data/views/fields/text_area.slim +4 -3
  78. data/views/fields/time.slim +5 -4
  79. data/views/fields/typeahead_picker.slim +12 -9
  80. data/views/index.slim +3 -3
  81. data/views/infra/index.slim +0 -0
  82. data/views/infra/inspect.slim +41 -10
  83. data/views/modals/close_m.slim +0 -0
  84. data/views/modals/confirm_m.slim +0 -0
  85. data/views/modals/empty_m.slim +0 -0
  86. data/views/modals/menu_m.slim +1 -1
  87. data/views/modals/yes_no_m.slim +0 -0
  88. data/views/panels/menu_m.slim +1 -1
  89. data/views/scaffold/confirm.slim +0 -0
  90. data/views/scaffold/fields.slim +6 -4
  91. data/views/scaffold/form.slim +1 -1
  92. data/views/scaffold/form_collapse.slim +4 -3
  93. data/views/scaffold/form_tabs.slim +3 -2
  94. data/views/scaffold/list.slim +0 -0
  95. data/views/scaffold/message.slim +0 -0
  96. data/views/scaffold/search.slim +4 -4
  97. data/views/scaffold/search_collapse.slim +8 -7
  98. data/views/scaffold/search_tabs.slim +6 -5
  99. data/views/scaffold/view.slim +2 -2
  100. data/views/scaffold/view_collapse.slim +5 -4
  101. data/views/scaffold/view_tabs.slim +4 -3
  102. data/views/search_fields/bsmselect_picker.slim +4 -4
  103. data/views/search_fields/bsselect_picker.slim +4 -4
  104. data/views/search_fields/checkbox.slim +3 -3
  105. data/views/search_fields/checkbox2.slim +5 -5
  106. data/views/search_fields/checkbox_buttons.slim +3 -3
  107. data/views/search_fields/date.slim +20 -0
  108. data/views/search_fields/date_range.slim +8 -8
  109. data/views/search_fields/decimal_date_range.slim +5 -5
  110. data/views/search_fields/input_text.slim +2 -2
  111. data/views/search_fields/integer.slim +1 -1
  112. data/views/search_fields/integer_range.slim +2 -2
  113. data/views/search_fields/list_bsmselect.slim +4 -4
  114. data/views/search_fields/list_bsselect.slim +4 -4
  115. data/views/search_fields/list_buttons.slim +2 -2
  116. data/views/search_fields/list_mbuttons.slim +12 -0
  117. data/views/search_fields/list_select.slim +3 -3
  118. data/views/search_fields/scaffold_picker.slim +2 -2
  119. data/views/search_fields/select_picker.slim +3 -3
  120. data/views/search_fields/typeahead_picker.slim +8 -7
  121. metadata +53 -48
  122. data/lib/engine2/meta.rb +0 -1216
  123. data/lib/engine2/meta/array_meta.rb +0 -82
  124. data/lib/engine2/meta/delete_meta.rb +0 -60
  125. data/lib/engine2/meta/form_meta.rb +0 -15
  126. data/lib/engine2/meta/link_meta.rb +0 -134
  127. data/lib/engine2/meta/list_meta.rb +0 -281
  128. data/lib/engine2/meta/save_meta.rb +0 -50
  129. data/lib/engine2/meta/view_meta.rb +0 -7
  130. data/public/__sinatra__/404.png +0 -0
  131. data/public/__sinatra__/500.png +0 -0
@@ -1,82 +0,0 @@
1
- # coding: utf-8
2
-
3
- module Engine2
4
- class ArrayListMeta < Meta
5
- meta_type :list
6
- include MetaListSupport
7
-
8
- (DefaultFilters ||= {}).merge!(
9
- exact: lambda{|entries, name, value, type_info, hash|
10
- entries.select{|e|e[name] == value}
11
- },
12
- string: lambda{|entries, name, value, type_info, hash|
13
- entries.select{|e|e[name].to_s[value]}
14
- },
15
- boolean: lambda{|*args| DefaultFilters[:exact].(*args)},
16
- integer: lambda{|entries, name, value, type_info, hash|
17
- if value.is_a? Hash
18
- from, to = value[:from], value[:to]
19
- if from && to
20
- entries.select{|e|e[name] >= from.to_i && e[name] <= to.to_i}
21
- else
22
- entries.select{|e| from ? e[name] >= from.to_i : e[name] <= to.to_i}
23
- end
24
- elsif value.is_a? Integer
25
- entries.select{|e|e[name] == value.to_i}
26
- else
27
- nil
28
- end
29
- }
30
- )
31
-
32
- def data_source handler
33
- []
34
- end
35
-
36
- def invoke handler
37
- params = handler.params
38
- # if params[:initial] || params[:refresh]
39
- entries = data_source(handler)
40
-
41
- per_page = lookup(:config, :per_page)
42
- page = params[:page].to_i
43
- handler.permit page >= 0 && page < 1000
44
-
45
- if order_str = params[:order]
46
- order = order_str.to_sym
47
- handler.permit lookup(:info, order, :sort)
48
- entries = entries.sort_by{|e|e[order].to_s}
49
- entries = entries.reverse if params[:asc] == "true"
50
- end
51
-
52
- if search = params[:search]
53
- entries = list_search(entries, handler, search)
54
- end
55
-
56
- {entries: entries.drop(page).take(per_page), count: entries.size}
57
- end
58
-
59
- def list_search entries, handler, search
60
- hash = JSON.parse(search, symbolize_names: true) rescue handler.halt_forbidden
61
- model = assets[:model]
62
- sfields = lookup(:search_fields)
63
- handler.permit sfields
64
- hash.each_pair do |name, value|
65
- handler.permit sfields.include?(name)
66
-
67
- type_info = get_type_info(name)
68
- entries = if filter = (@filters && @filters[name]) || (dynamic? && (static.filters && static.filters[name]))
69
- filter.(entries, hash, handler)
70
- elsif filter = DefaultFilters[type_info[:otype]]
71
- filter.(entries, name, value, type_info, hash)
72
- else
73
- raise E2Error.new("Filter not found for field '#{name}' in model '#{model}'") unless filter
74
- end
75
-
76
- handler.permit entries
77
- end
78
-
79
- entries
80
- end
81
- end
82
- end
@@ -1,60 +0,0 @@
1
- # coding: utf-8
2
-
3
- module Engine2
4
- class DeleteMetaBase < Meta
5
-
6
- def invoke_delete_db handler, ids
7
- begin
8
- model = assets[:model]
9
- model.db.transaction do
10
- ids.each do |id|
11
- keys = split_keys(id)
12
- restrict = model.association_reflections.select do |name, rel|
13
- case rel[:type]
14
- when :one_to_many
15
- !model.db[name].where(Hash[rel[:keys].zip(keys)]).empty?
16
- when :many_to_many
17
- !model.db[rel[:join_table]].where(Hash[rel[:left_keys].zip(keys)]).empty?
18
- when :many_to_one
19
- when :one_to_one
20
- else
21
- unsupported_association rel[:type]
22
- end
23
- end
24
- raise Sequel::DestroyFailed.new("Blokujące relacje: #{restrict.map{|name, rel| name}.join(', ')}" ) unless restrict.empty?
25
-
26
- rec = model.call(Hash[model.primary_keys.zip(keys)])
27
- rec.destroy(transaction: false)
28
- # model.where(model.primary_keys_hash(keys)).delete # model.dataset[model.primary_key => id].delete
29
- end
30
- end
31
- {}
32
- rescue Sequel::NoExistingObject
33
- handler.halt_not_found LOCS[:no_entry]
34
- rescue Sequel::DestroyFailed => failure
35
- handler.halt_forbidden failure.error.to_s
36
- end
37
- end
38
-
39
- end
40
-
41
- class DeleteMeta < DeleteMetaBase
42
- include MetaDeleteSupport
43
-
44
- def invoke handler
45
- handler.permit id = handler.params[:id]
46
- invoke_delete_db(handler, [id])
47
- end
48
- end
49
-
50
- class BulkDeleteMeta < DeleteMetaBase
51
- include MetaBulkDeleteSupport
52
-
53
- def invoke handler
54
- ids = handler.param_to_json(:ids)
55
- handler.permit ids.is_a?(Array)
56
- invoke_delete_db(handler, ids)
57
- end
58
- end
59
-
60
- end
@@ -1,15 +0,0 @@
1
- # coding: utf-8
2
-
3
- module Engine2
4
- class FormMeta < Meta
5
- include MetaQuerySupport
6
- end
7
-
8
- class CreateMeta < FormMeta
9
- include MetaCreateSupport
10
- end
11
-
12
- class ModifyMeta < FormMeta
13
- include MetaModifySupport
14
- end
15
- end
@@ -1,134 +0,0 @@
1
- # coding: utf-8
2
-
3
- module Engine2
4
- class StarToManyLinkMeta < Meta
5
- include MetaModelSupport
6
- http_method :post
7
- meta_type :star_to_many_link
8
-
9
- def invoke handler
10
- json = handler.post_to_json
11
- parent = json[:parent_id]
12
- ids = json[:ids]
13
- handler.permit parent && ids
14
- model = assets[:model]
15
- assoc = assets[:assoc]
16
- case assoc[:type]
17
- when :one_to_many
18
- model.db.transaction do
19
- self.class.one_to_many_link_db model, assoc, split_keys(parent), ids
20
- end
21
- {}
22
- when :many_to_many
23
- self.class.many_to_many_link_db model, assoc, split_keys(parent), ids
24
- {}
25
- else unsupported_association
26
- end
27
- end
28
-
29
- def self.one_to_many_link_db model, assoc, parent, ids
30
- pk = Hash[assoc[:keys].zip(parent)]
31
- ids.each do |id|
32
- model.where(model.primary_keys_hash(Sequel::split_keys(id))).update(pk)
33
- end
34
- end
35
-
36
- def self.many_to_many_link_db model, assoc, parent, ids
37
- p_pk = Hash[assoc[:left_keys].zip(parent)]
38
- values = ids.map do |id|
39
- p_pk.merge Hash[assoc[:right_keys].zip(Sequel::split_keys(id))]
40
- end
41
- model.db[assoc[:join_table]].multi_insert values
42
- end
43
- end
44
-
45
- class StarToManyUnlinkMetaBase < Meta
46
- include MetaModelSupport
47
- http_method :delete
48
-
49
- def one_to_many_unlink_db handler, ids
50
- model = assets[:model]
51
- assoc = assets[:assoc]
52
- keys = assoc[:keys]
53
- if keys.all?{|k|model.db_schema[k][:allow_null] == true}
54
- model.db.transaction do
55
- self.class.one_to_many_unlink_db model, assoc, ids
56
- end
57
- {}
58
- else
59
- handler.halt_method_not_allowed LOCS[:"non_nullable"]
60
- end
61
- end
62
-
63
- def self.one_to_many_unlink_db model, assoc, ids
64
- keys = assoc[:keys]
65
- ids.each do |id|
66
- model.where(model.primary_keys_hash(Sequel::split_keys(id))).update(Hash[keys.zip([nil])])
67
- end
68
- end
69
-
70
- def many_to_many_unlink_db parent, ids
71
- model = assets[:model]
72
- assoc = assets[:assoc]
73
-
74
- model.db.transaction do
75
- self.class.many_to_many_unlink_db model, assoc, Sequel::split_keys(parent), ids
76
- end
77
- {}
78
- end
79
-
80
- def self.many_to_many_unlink_db model, assoc, parent, ids
81
- p_pk = Hash[assoc[:left_keys].zip(parent)]
82
- ds = model.db[assoc[:join_table]]
83
- ids.each do |id|
84
- ds.where(p_pk, Hash[assoc[:right_keys].zip(Sequel::split_keys(id))]).delete
85
- end
86
- end
87
- end
88
-
89
- class StarToManyUnlinkMeta < StarToManyUnlinkMetaBase
90
- meta_type :star_to_many_unlink
91
-
92
- def pre_run
93
- super
94
- action.parent.parent.*.menu(:item_menu).option :confirm_unlink, icon: "minus", show: "action.selected_size() == 0", button_loc: false
95
- end
96
-
97
- def invoke handler
98
- handler.permit id = handler.params[:id]
99
- assoc = assets[:assoc]
100
- case assoc[:type]
101
- when :one_to_many
102
- one_to_many_unlink_db(handler, [id])
103
- when :many_to_many
104
- handler.permit parent = handler.params[:parent_id]
105
- many_to_many_unlink_db(parent, [id])
106
- else unsupported_association
107
- end
108
- end
109
- end
110
-
111
- class StarToManyBulkUnlinkMeta < StarToManyUnlinkMetaBase
112
- meta_type :star_to_many_bulk_unlink
113
-
114
- def pre_run
115
- super
116
- action.parent.parent.*.select_toggle_menu
117
- action.parent.parent.*.menu(:menu).option_after :default_order, :confirm_bulk_unlink, icon: "minus", show: "action.selected_size() > 0", button_loc: false
118
- end
119
-
120
- def invoke handler
121
- ids = handler.param_to_json(:ids)
122
- handler.permit ids.is_a?(Array)
123
- assoc = assets[:assoc]
124
- case assoc[:type]
125
- when :one_to_many
126
- one_to_many_unlink_db(handler, ids)
127
- when :many_to_many
128
- handler.permit parent = handler.params[:parent_id]
129
- many_to_many_unlink_db(parent, ids)
130
- else unsupported_association
131
- end
132
- end
133
- end
134
- end
@@ -1,281 +0,0 @@
1
- # coding: utf-8
2
-
3
- module Engine2
4
- class ListMeta < Meta
5
- meta_type :list
6
- include MetaListSupport, MetaQuerySupport
7
-
8
- (DefaultFilters ||= {}).merge!(
9
- string: lambda{|query, name, value, type_info, hash|
10
- case type_info[:type]
11
- when :many_to_one
12
- query.where(name => value)
13
- else
14
- query.where(name.like("%#{value}%"))
15
- end
16
- },
17
- date: lambda{|query, name, value, type_info, hash|
18
- if value.is_a? Hash
19
- from, to = value[:from], value[:to]
20
- if from && to
21
- query.where(name => from .. to)
22
- elsif from
23
- query.where(name >= Sequel.string_to_date(from))
24
- elsif to
25
- query.where(name <= Sequel.string_to_date(to))
26
- else
27
- query # ?
28
- end
29
- else
30
- query.where(name => Sequel.string_to_date(value))
31
- end
32
- },
33
- integer: lambda{|query, name, value, type_info, hash|
34
- if value.is_a? Hash
35
- from, to = value[:from], value[:to]
36
- if from && to
37
- query.where(name => from .. to)
38
- else
39
- query.where(from ? name >= from.to_i : name <= to.to_i)
40
- end
41
- elsif value.is_a? Integer
42
- query.where(name => value)
43
- elsif value.is_a? Array
44
- if !value.empty?
45
- case type_info[:type]
46
- when :many_to_one
47
- keys = type_info[:keys]
48
- if keys.length == 1
49
- query.where(name => value)
50
- else
51
- query.where(keys.map{|k| hash[k]}.transpose.map{|vals| Hash[keys.zip(vals)]}.inject{|q, c| q | c})
52
- end
53
- when :list_select
54
- query.where(name => value) # decode in sql query ?
55
- when :integer
56
- query
57
- else
58
- nil
59
- end
60
- else
61
- nil
62
- end
63
- else
64
- nil
65
- end
66
- }
67
- )
68
-
69
- def post_run
70
- query select(*assets[:model].columns.reject{|col| assets[:model].type_info[col][:length].to_i > 20}.take(10)) unless @query
71
- super
72
- end
73
-
74
- def invoke handler
75
- params = handler.params
76
- model = assets[:model]
77
- query = list_context(get_query, handler)
78
-
79
- if search = params[:search]
80
- query = list_search(query, handler, search)
81
- end
82
-
83
- count = query.count if lookup(:config, :use_count)
84
-
85
- if order_str = params[:order]
86
- order = order_str.to_sym
87
- handler.permit lookup(:info, order, :sort)
88
-
89
- if order_blk = (@orders && @orders[order]) || (dynamic? && (static.orders && static.orders[order]))
90
- query = order_blk.(query, handler)
91
- else
92
- order = order.qualify(model.table_name) if model.type_info[order]
93
- query = query.order(order)
94
- end
95
-
96
- query = query.reverse if params[:asc] == "true"
97
- end
98
-
99
- per_page = lookup(:config, :per_page)
100
- page = params[:page].to_i
101
- handler.permit page >= 0 && page < 1000
102
-
103
- query = query.limit(per_page, page)
104
-
105
- res = {entries: query.all}
106
- res[:count] = count if count
107
- res
108
- end
109
-
110
- def list_search query, handler, search
111
- hash = JSON.parse(search, symbolize_names: true) rescue handler.halt_forbidden
112
- model = assets[:model]
113
- sfields = lookup(:search_fields)
114
- handler.permit sfields
115
- hash.each_pair do |name, value|
116
- handler.permit sfields.include?(name)
117
-
118
- type_info = get_type_info(name)
119
- query = if filter = (@filters && @filters[name]) || (dynamic? && (static.filters && static.filters[name]))
120
- filter.(query, hash, handler)
121
- elsif filter = DefaultFilters[type_info[:otype]]
122
- name = model.type_info[name] ? name.qualify(model.table_name) : Sequel.expr(name)
123
- filter.(query, name, value, type_info, hash)
124
- else
125
- raise E2Error.new("Filter not found for field '#{name}' in model '#{model}'") unless filter
126
- end
127
-
128
- handler.permit query
129
- end
130
- query
131
- end
132
-
133
- def list_context query, handler
134
- query
135
- end
136
- end
137
-
138
- #
139
- # Many to One
140
- #
141
- class ManyToOneListMeta < ListMeta
142
- meta_type :many_to_one_list
143
-
144
- def pre_run
145
- super
146
- end
147
- end
148
-
149
- #
150
- # * to Many
151
- #
152
- class StarToManyListMeta < ListMeta
153
- meta_type :star_to_many_list
154
- def pre_run
155
- super
156
- menu(:panel_menu).option_at 0, :cancel, icon: "remove"
157
- panel_title "#{:list.icon} #{LOCS[assets[:assoc][:name]]}"
158
- end
159
-
160
- # def decode_panel_title handler
161
- # if handler.initial?
162
- # # Hash[assets[:model].primary_keys.zip(split_keys(id))]]
163
- # p action.parent.decode_entry.*.invoke_decode([[handler.params[:parent_id]]])
164
- # panel_title "ADFASDF"
165
- # end
166
- # end
167
-
168
- # def post_run
169
- # super
170
- # unless @request_meta_proc
171
- # request{|h| decode_panel_title h}
172
- # end
173
- # end
174
-
175
- def list_context query, handler
176
- handler.permit parent = handler.params[:parent_id]
177
- model = assets[:model]
178
- assoc = assets[:assoc]
179
- parent_keys = split_keys(parent)
180
- case assoc[:type]
181
- when :one_to_many
182
- keys = assoc[:keys]
183
- condition = parent_keys.all?(&:empty?) ? false : Hash[keys.map{|k| k.qualify(model.table_name)}.zip(parent_keys)]
184
- if handler.params[:negate]
185
- query = query.exclude(condition)
186
- query = query.or(Hash[keys.zip([nil])]) if keys.all?{|k|model.db_schema[k][:allow_null] == true} # type_info[:required] ?
187
- query
188
- else
189
- query.where(condition)
190
- end
191
- when :many_to_many
192
- q_pk = model.primary_keys_qualified
193
- j_table = assoc[:join_table]
194
- l_keys = assoc[:left_keys].map{|k| k.qualify(j_table)}
195
- r_keys = assoc[:right_keys].map{|k| k.qualify(j_table)}
196
- r_keys_vals = Hash[r_keys.zip(q_pk)]
197
- l_keys_vals = parent_keys.all?(&:empty?) ? false : Hash[l_keys.zip(parent_keys)]
198
-
199
- if handler.params[:negate]
200
- query.exclude(model.db[j_table].select(nil).where(r_keys_vals, l_keys_vals).exists)
201
- else
202
- # query.qualify.join(j_table, [r_keys_vals, l_keys_vals])
203
- query.qualify.left_join(j_table, r_keys_vals).filter(l_keys_vals)
204
- end
205
- else unsupported_association
206
- end
207
- end
208
- end
209
-
210
- class StarToManyLinkListMeta < StarToManyListMeta
211
- meta_type :star_to_many_link_list
212
- def pre_run
213
- super
214
- panel_title LOCS[:link_title]
215
- menu(:panel_menu).option_at 0, :link, icon: "ok", enabled: "action.selected_size() > 0"
216
- action.parent.*.menu(:menu).option_at 0, :link_list, icon: "paperclip", button_loc: false
217
- end
218
- end
219
-
220
- # *_to_many_field
221
- class StarToManyFieldMeta < StarToManyListMeta
222
- meta_type :star_to_many_field
223
-
224
- def pre_run
225
- super
226
- modal_action false
227
- panel_panel_template false
228
- end
229
-
230
- def list_context query, handler
231
- unlinked = handler.param_to_json(:unlinked)
232
- linked = handler.param_to_json(:linked)
233
- query = super(query, handler)
234
- model = assets[:model]
235
- pks = model.primary_keys_qualified
236
-
237
- if handler.params[:negate]
238
- query = unlinked.map{|ln| pks.zip(split_keys(ln))}.inject(query){|q, c| q.or c}
239
- # query = query.or *unlinked.map{|unl| Hash[model.primary_keys.zip(split_keys(unl))]}.inject{|q, c| q | c}
240
- query = query.where *linked.map{|ln| pks.zip(split_keys(ln)).sql_negate}
241
-
242
- else
243
- query = query.where *unlinked.map{|unl| pks.zip(split_keys(unl)).sql_negate}
244
- # query = query.or *linked.map{|ln| model.primary_keys.zip(split_keys(ln))}
245
- # query = query.or *linked.map{|ln| Hash[model.primary_keys.zip(split_keys(ln))]}.inject{|q, c| q | c}
246
- case assets[:assoc][:type]
247
- when :one_to_many
248
- query = linked.map{|ln| pks.zip(split_keys(ln))}.inject(query){|q, c| q.or c}
249
- when :many_to_many
250
- query = linked.map{|ln| pks.zip(split_keys(ln))}.inject(query){|q, c| q.or c}.distinct
251
- else unsupported_association
252
- end unless linked.empty?
253
- end
254
-
255
- query
256
- end
257
- end
258
-
259
- class StarToManyFieldUnlinkMeta < Meta
260
- meta_type :star_to_many_field_unlink
261
-
262
- def pre_run
263
- super
264
- action.parent.parent.*.menu(:item_menu).option :confirm_unlink, icon: "minus", show: "action.selected_size() == 0", button_loc: false
265
- end
266
- end
267
-
268
- class StarToManyFieldLinkListMeta < StarToManyFieldMeta
269
- meta_type :star_to_many_field_link_list
270
-
271
- def pre_run
272
- super
273
- modal_action true
274
- panel_panel_template 'scaffold/list'
275
- panel_title LOCS[:link_title]
276
- menu(:panel_menu).option_at 0, :link, icon: "ok", enabled: "action.selected_size() > 0"
277
- action.parent.*.menu(:menu).option_at 0, :link_list, icon: "paperclip", button_loc: false
278
- end
279
- end
280
- end
281
-