card 1.15.4 → 1.15.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/config/initializers/recaptcha.rb +1 -1
  4. data/db/migrate_core_cards/20141208162106_add_ace_script.rb +2 -4
  5. data/db/migrate_core_cards/20150508212032_menu_compatibility.rb +1 -2
  6. data/db/migrate_core_cards/20150605115802_add_performance_log_card.rb +7 -0
  7. data/lib/card/content.rb +6 -0
  8. data/lib/card/log.rb +110 -17
  9. data/lib/card/query.rb +31 -21
  10. data/lib/cardio.rb +1 -0
  11. data/mod/01_core/set/all/collection.rb +42 -8
  12. data/mod/01_core/set/all/permissions.rb +21 -21
  13. data/mod/01_core/set/all/templating.rb +18 -12
  14. data/mod/01_core/spec/set/all/collection_spec.rb +7 -1
  15. data/mod/01_history/set/all/content_history.rb +14 -12
  16. data/mod/02_basic_types/set/type/pointer.rb +54 -24
  17. data/mod/03_machines/lib/javascript/wagn_mod.js.coffee +1 -1
  18. data/mod/03_machines/lib/stylesheets/style_cards.scss +3 -0
  19. data/mod/03_machines/set/type/scss.rb +5 -5
  20. data/mod/05_email/set/right/follow.rb +3 -3
  21. data/mod/05_standard/set/all/rich_html/content.rb +17 -13
  22. data/mod/05_standard/set/self/performance_log.rb +92 -0
  23. data/mod/05_standard/set/type/search_type.rb +15 -17
  24. data/spec/lib/card/content_spec.rb +12 -0
  25. metadata +4 -17
  26. data/db/seed/README.md +0 -2
  27. data/db/seed/new/card_actions.yml +0 -4495
  28. data/db/seed/new/card_acts.yml +0 -7
  29. data/db/seed/new/card_changes.yml +0 -29416
  30. data/db/seed/new/card_references.yml +0 -4348
  31. data/db/seed/new/cards.yml +0 -28134
  32. data/db/seed/test/fixtures/.gitkeep +0 -0
  33. data/db/seed/test/fixtures/card_actions.yml +0 -6336
  34. data/db/seed/test/fixtures/card_acts.yml +0 -841
  35. data/db/seed/test/fixtures/card_changes.yml +0 -34632
  36. data/db/seed/test/fixtures/card_references.yml +0 -5783
  37. data/db/seed/test/fixtures/cards.yml +0 -32803
  38. data/db/seed/test/fixtures/mao2.jpg +0 -0
  39. data/db/seed/test/fixtures/rails.gif +0 -0
  40. data/db/seed/test/seed.rb +0 -201
@@ -1,5 +1,5 @@
1
1
 
2
- Card.error_codes.merge! :permission_denied=>[:denial, 403], :captcha=>[:error,449]
2
+ Card.error_codes.merge! :permission_denied=>[:denial, 403], :captcha=>[:errors,449]
3
3
 
4
4
 
5
5
  # ok? and ok! are public facing methods to approve one action at a time
@@ -36,7 +36,7 @@ end
36
36
 
37
37
  def permission_rule_card action
38
38
  opcard = rule_card action
39
-
39
+
40
40
  unless opcard # RULE missing. should not be possible. generalize this to handling of all required rules
41
41
  errors.add :permission_denied, "No #{action} rule for #{name}"
42
42
  raise Card::PermissionDenied.new(self)
@@ -90,7 +90,7 @@ def permit action, verb=nil
90
90
  if Card.config.read_only # not called by ok_to_read
91
91
  deny_because "Currently in read-only mode"
92
92
  end
93
-
93
+
94
94
  verb ||= action.to_s
95
95
  unless permitted? action
96
96
  deny_because you_cant("#{verb} #{name.present? ? name : 'this'}")
@@ -102,7 +102,7 @@ def ok_to_create
102
102
  if @action_ok and junction?
103
103
  [:left, :right].each do |side|
104
104
  next if side==:left && @superleft # left is supercard; create permissions will get checked there.
105
- part_card = send side, :new=>{}
105
+ part_card = send side, :new=>{}
106
106
  if part_card && part_card.new_card? # if no card, there must be other errors
107
107
  unless part_card.ok? :create
108
108
  deny_because you_cant("create #{part_card.name}")
@@ -199,7 +199,7 @@ event :check_permissions, :after=>:approve do
199
199
  else
200
200
  @action
201
201
  end
202
-
202
+
203
203
  track_permission_errors do
204
204
  ok? task
205
205
  end
@@ -208,12 +208,12 @@ end
208
208
  def track_permission_errors
209
209
  @permission_errors = []
210
210
  result = yield
211
-
211
+
212
212
  @permission_errors.each do |message|
213
213
  errors.add :permission_denied, message
214
214
  end
215
215
  @permission_errors = nil
216
-
216
+
217
217
  result
218
218
  end
219
219
 
@@ -224,16 +224,16 @@ def recaptcha_on?
224
224
  !Auth.signed_in? &&
225
225
  !Auth.needs_setup? &&
226
226
  !Auth.always_ok? &&
227
- Card.toggle( rule :captcha )
227
+ Card.toggle( rule :captcha )
228
228
  end
229
229
 
230
230
  def have_recaptcha_keys?
231
- @@have_recaptcha_keys = defined?(@@have_recaptcha_keys) ? @@have_recaptcha_keys :
231
+ @@have_recaptcha_keys = defined?(@@have_recaptcha_keys) ? @@have_recaptcha_keys :
232
232
  !!( Card.config.recaptcha_public_key && Card.config.recaptcha_private_key )
233
233
  end
234
234
 
235
235
  event :recaptcha, :before=>:approve do
236
- if !@supercard && !Env[:recaptcha_used] && recaptcha_on?
236
+ if !@supercard && !Env[:recaptcha_used] && recaptcha_on?
237
237
  Env[:recaptcha_used] = true
238
238
  Env[:controller].verify_recaptcha :model=>self, :attribute=>:captcha
239
239
  end
@@ -242,43 +242,43 @@ end
242
242
  module Accounts
243
243
  # This is a short-term hack that is used in account-related cards to allow a permissions pattern where
244
244
  # permissions are restricted to the owner of the account (and, by default, Admin)
245
- # That pattern should be permitted by our card representation (without creating
245
+ # That pattern should be permitted by our card representation (without creating
246
246
  # separate rules for each account holder) but is not yet.
247
-
247
+
248
248
  def permit action, verb=nil
249
249
  case
250
250
  when action==:comment ; @action_ok = false
251
- when action==:create ; @superleft ? true : super( action, verb )
251
+ when action==:create ; @superleft ? true : super( action, verb )
252
252
  #restricts account creation to subcard handling on permitted card (unless explicitly permitted)
253
253
  when is_own_account? ; true
254
254
  else ; super action, verb
255
255
  end
256
256
  end
257
-
257
+
258
258
  end
259
259
 
260
- module Follow
260
+ module Follow
261
261
  def ok_to_update
262
262
  permit :update
263
263
  end
264
-
264
+
265
265
  def ok_to_create
266
266
  permit :create
267
267
  end
268
-
268
+
269
269
  def ok_to_delete
270
270
  permit :delete
271
271
  end
272
-
272
+
273
273
  def permit action, verb=nil
274
- if [:create, :delete, :update].include?(action) && Auth.signed_in? &&
274
+ if [:create, :delete, :update].include?(action) && Auth.signed_in? &&
275
275
  (user = rule_user) && Auth.current_id == user.id
276
276
  return true
277
277
  else
278
278
  super action, verb
279
279
  end
280
280
  end
281
-
281
+
282
282
  end
283
-
283
+
284
284
 
@@ -12,29 +12,34 @@ def template
12
12
  # note that a *default template is never returned for an existing card.
13
13
  @template ||= begin
14
14
  @virtual = false
15
+
16
+ # NEW CARDS
15
17
  if new_card?
16
- default_card = rule_card :default, :skip_modules=>true
18
+ default = rule_card :default, :skip_modules=>true
17
19
 
18
20
  dup_card = dup
19
- dup_card.type_id = default_card ? default_card.type_id : Card.default_type_id
20
-
21
+ dup_card.type_id = default ? default.type_id : Card.default_type_id
21
22
 
22
- if content_card = dup_card.structure_rule_card
23
+ if structure = dup_card.structure_rule_card
23
24
  @virtual = true if junction?
24
- content_card
25
+ self.type_id = structure.type_id if assign_type_to?(structure)
26
+ structure
25
27
  else
26
- default_card
27
- end
28
- elsif tmpl = structure_rule_card
29
- # this is a mechanism for repairing bad data. like #repair_key, it should be obviated and removed.
30
- if type_id != tmpl.type_id and tmpl.assigns_type?
31
- repair_type tmpl.type_id
28
+ default
32
29
  end
33
- tmpl
30
+
31
+ # EXISTING CARDS
32
+ elsif structure = structure_rule_card
33
+ repair_type structure.type_id if assign_type_to?(structure)
34
+ structure
34
35
  end
35
36
  end
36
37
  end
37
38
 
39
+ def assign_type_to? structure
40
+ type_id != structure.type_id and structure.assigns_type?
41
+ end
42
+
38
43
  def structure
39
44
  if template && template.is_structure?
40
45
  template
@@ -102,6 +107,7 @@ end
102
107
  private
103
108
 
104
109
  def repair_type template_type_id
110
+ # this is a mechanism for repairing bad data. like #repair_key, it should be obviated and removed.
105
111
  self.type_id = template_type_id
106
112
  update_column :type_id, type_id
107
113
  reset_patterns
@@ -94,6 +94,12 @@ describe Card::Set::All::Collection do
94
94
  assert_select "li > a[data-toggle=tab][data-url=#{path}]"
95
95
  end
96
96
  end
97
-
97
+ it 'handles nests as items' do
98
+ tabs = render_card :tabs, :name=>'tab_test', :type_id=>Card::PlainTextID, :content=>"{{A|type;title:my tab title}}"
99
+ assert_view_select tabs, 'div[role=tabpanel]' do
100
+ assert_select 'li > a[data-toggle=tab][href=#tab_test-a]', 'my tab title'
101
+ assert_select 'div.tab-pane#tab_test-a', 'Basic'
102
+ end
103
+ end
98
104
  end
99
105
  end
@@ -26,23 +26,23 @@ end
26
26
  def last_change_on(field, opts={})
27
27
  where_sql = 'card_actions.card_id = :card_id AND field = :field AND (draft is not true) '
28
28
  where_sql += if opts[:before]
29
- 'AND card_action_id < :action_id'
29
+ 'AND card_action_id < :action_id'
30
30
  elsif opts[:not_after]
31
31
  'AND card_action_id <= :action_id'
32
32
  else
33
33
  ''
34
34
  end
35
-
35
+
36
36
  action_arg = opts[:before] || opts[:not_after]
37
37
  action_id = action_arg.kind_of?(Card::Action) ? action_arg.id : action_arg
38
38
  field_index = Card::TRACKED_FIELDS.index(field.to_s)
39
- Change.joins(:action).where( where_sql,
39
+ Change.joins(:action).where( where_sql,
40
40
  {:card_id=>id, :field=>field_index, :action_id=>action_id}
41
41
  ).order(:id).last
42
42
  end
43
43
 
44
44
  def selected_action_id
45
- @selected_action_id || (@current_action and @current_action.id) || last_action_id
45
+ @selected_action_id || (@current_action and @current_action.id) || last_action_id
46
46
  end
47
47
 
48
48
  def selected_action_id= action_id
@@ -55,9 +55,9 @@ def selected_action
55
55
  end
56
56
 
57
57
  def selected_content_action_id
58
- @selected_action_id ||
59
- (@current_action and @current_action.new_content? and @current_action.id) ||
60
- last_content_action_id
58
+ @selected_action_id ||
59
+ (@current_action and @current_action.new_content? and @current_action.id) ||
60
+ last_content_action_id
61
61
  end
62
62
 
63
63
  def last_action_id
@@ -81,11 +81,13 @@ def last_actor
81
81
  end
82
82
 
83
83
  def last_act
84
- last_act_on_self = acts.last
85
- if last_act_on_self and (last_action.act == last_act_on_self or last_act_on_self.acted_at > last_action.act.acted_at)
86
- last_act_on_self
87
- else
88
- last_action.act
84
+ if action = last_action
85
+ last_act_on_self = acts.last
86
+ if last_act_on_self and ( action.act==last_act_on_self || last_act_on_self.acted_at>action.act.acted_at )
87
+ last_act_on_self
88
+ else
89
+ action.act
90
+ end
89
91
  end
90
92
  end
91
93
 
@@ -61,12 +61,12 @@ format :html do
61
61
  args ||= {}
62
62
  items = args[:item_list] || card.item_names(:context=>:raw)
63
63
  items = [''] if items.empty?
64
- options_card_name = (oc = card.options_card) ? oc.cardname.url_key : ':all'
64
+ options_card_name = (oc = card.options_rule_card) ? oc.cardname.url_key : ':all'
65
65
 
66
66
  extra_css_class = args[:extra_css_class] || 'pointer-list-ul'
67
67
 
68
68
  %{
69
- <ul class="pointer-list-editor #{extra_css_class}" options-card="#{options_card_name}">
69
+ <ul class="pointer-list-editor #{extra_css_class}" data-options-card="#{options_card_name}">
70
70
  #{
71
71
  items.map do |item|
72
72
  _render_list_item args.merge( :pointer_item=>item )
@@ -106,14 +106,15 @@ format :html do
106
106
 
107
107
 
108
108
  view :checkbox do |args|
109
- options = card.options.map do |option|
110
- checked = card.item_names.include?(option.name)
111
- id = "pointer-checkbox-#{option.cardname.key}"
112
- description = pointer_option_description option
109
+ options = card.option_names.map do |option_name|
110
+ checked = card.item_names.include?(option_name)
111
+ label = ((o_card = Card.fetch(option_name)) && o_card.label) || option_name
112
+ id = "pointer-checkbox-#{option_name.to_name.key}"
113
+ description = pointer_option_description option_name
113
114
  %{
114
115
  <div class="pointer-checkbox">
115
- #{ check_box_tag "pointer_checkbox", option.name, checked, :id=>id, :class=>'pointer-checkbox-button' }
116
- <label for="#{id}">#{option.name}</label>
116
+ #{ check_box_tag "pointer_checkbox", option_name, checked, :id=>id, :class=>'pointer-checkbox-button' }
117
+ <label for="#{id}">#{label}</label>
117
118
  #{ %{<div class="checkbox-option-description">#{ description }</div>} if description }
118
119
  </div>
119
120
  }
@@ -123,21 +124,23 @@ format :html do
123
124
  end
124
125
 
125
126
  view :multiselect do |args|
126
- selected_options = card.item_names.map{|i_n| (c=Card.fetch(i_n) and c.name) or i_n}
127
- options = options_from_collection_for_select(card.options,:name,:name,selected_options)
128
- select_tag("pointer_multiselect", options, :multiple=>true, :class=>'pointer-multiselect form-control')
127
+ select_tag("pointer_multiselect",
128
+ options_for_select(card.option_names, card.item_names),
129
+ :multiple=>true, :class=>'pointer-multiselect form-control'
130
+ )
129
131
  end
130
132
 
131
133
  view :radio do |args|
132
134
  input_name = "pointer_radio_button-#{card.key}"
133
- options = card.options.map do |option|
134
- checked = (option.name==card.item_names.first)
135
- id = "pointer-radio-#{option.cardname.key}"
136
- description = pointer_option_description option
135
+ options = card.option_names.map do |option_name|
136
+ checked = (option_name==card.item_names.first)
137
+ id = "pointer-radio-#{option_name.to_name.key}"
138
+ label = ((o_card = Card.fetch(option_name)) && o_card.label) || option_name
139
+ description = pointer_option_description option_name
137
140
  %{
138
141
  <li class="pointer-radio radio">
139
- #{ radio_button_tag input_name, option.name, checked, :id=>id, :class=>'pointer-radio-button' }
140
- <label for="#{id}">#{ option.label }</label>
142
+ #{ radio_button_tag input_name, option_name, checked, :id=>id, :class=>'pointer-radio-button' }
143
+ <label for="#{id}">#{ label }</label>
141
144
  #{ %{<div class="radio-option-description">#{ description }</div>} if description }
142
145
  </li>
143
146
  }
@@ -147,14 +150,17 @@ format :html do
147
150
  end
148
151
 
149
152
  view :select do |args|
150
- options = [["-- Select --",""]] + card.options.map{|x| [x.name,x.name]}
151
- select_tag("pointer_select", options_for_select(options, card.item_names.first), :class=>'pointer-select form-control')
153
+ options = [["-- Select --",""]] + card.option_names.map{ |x| [x,x]}
154
+ select_tag("pointer_select",
155
+ options_for_select(options, card.item_names.first),
156
+ :class=>'pointer-select form-control'
157
+ )
152
158
  end
153
159
 
154
160
 
155
161
  def pointer_option_description option
156
162
  pod_name = card.rule(:options_label) || 'description'
157
- dcard = Card[ "#{option.name}+#{pod_name}" ]
163
+ dcard = Card[ "#{option}+#{pod_name}" ]
158
164
  if dcard and dcard.ok? :read
159
165
  with_inclusion_mode :normal do
160
166
  subformat(dcard).render_core
@@ -255,7 +261,7 @@ def item_ids args={}
255
261
  end
256
262
 
257
263
  def item_type
258
- opt = options_card
264
+ opt = options_rule_card
259
265
  if !opt or opt==self #fixme, need better recursion prevention
260
266
  nil
261
267
  else
@@ -283,6 +289,10 @@ def add_item name
283
289
  self.content="[[#{(item_names << name).reject(&:blank?)*"]]\n[["}]]"
284
290
  end
285
291
  end
292
+ def add_item! name
293
+ add_item name
294
+ save!
295
+ end
286
296
 
287
297
  def drop_item name
288
298
  if include_item? name
@@ -291,6 +301,10 @@ def drop_item name
291
301
  self.content = new_names.empty? ? '' : "[[#{new_names * "]]\n[["}]]"
292
302
  end
293
303
  end
304
+ def drop_item! name
305
+ drop_item name
306
+ save!
307
+ end
294
308
 
295
309
  def insert_item index, name
296
310
  new_names = item_names
@@ -298,14 +312,30 @@ def insert_item index, name
298
312
  new_names.insert(index,name)
299
313
  self.content = new_names.map { |name| "[[#{name}]]" }.join "\n"
300
314
  end
315
+ def insert_item! index, name
316
+ insert_item index, name
317
+ save!
318
+ end
301
319
 
302
320
 
303
- def options_card
321
+ def options_rule_card
304
322
  self.rule_card :options
305
323
  end
306
324
 
307
- def options
308
- result_cards = if oc = options_card
325
+ def option_names
326
+ result_cards = if oc = options_rule_card
327
+ oc.item_names :default_limit=>50, :context=>name
328
+ else
329
+ Card.search :sort=>'name', :limit=>50, :return=>:name
330
+ end
331
+ if selected_options = item_names
332
+ result_cards = result_cards | selected_options
333
+ end
334
+ result_cards
335
+ end
336
+
337
+ def option_cards
338
+ result_cards = if oc = options_rule_card
309
339
  oc.item_cards :default_limit=>50, :context=>name
310
340
  else
311
341
  Card.search :sort=>'alpha', :limit=>50
@@ -25,7 +25,7 @@ $.extend wagn,
25
25
  }
26
26
 
27
27
  initPointerList: (input)->
28
- optionsCard = input.closest('ul').attr('options-card')
28
+ optionsCard = input.closest('ul').data('options-card')
29
29
  input.autocomplete { source: wagn.prepUrl wagn.rootPath + '/' + optionsCard + '.json?view=name_complete' }
30
30
 
31
31
  setTinyMCEConfig: (string)->
@@ -894,4 +894,7 @@ html>body .open-view {
894
894
  font-size: .85em;
895
895
  }
896
896
 
897
+ .SELF-Xperformance_log.open-view .panel-group {
898
+ margin-bottom: 0;
899
+ }
897
900
 
@@ -2,21 +2,21 @@ include Type::Css
2
2
 
3
3
  def diff_args
4
4
  {:format=>:text}
5
- end
5
+ end
6
6
 
7
7
  format do
8
8
  include Css::Format
9
-
9
+
10
10
  view :core do |args|
11
11
  compile_scss(process_content _render_raw)
12
12
  end
13
-
13
+
14
14
  def compile_scss scss, style=:expanded
15
15
  Sass.compile scss, :style=>style
16
16
  rescue =>e
17
17
  e
18
18
  end
19
-
19
+
20
20
  end
21
21
 
22
- format( :html ) { include Css::HtmlFormat }
22
+ format( :html ) { include Css::HtmlFormat }