card 1.20.0 → 1.20.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.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/card.gemspec +1 -1
  4. data/lib/card.rb +7 -3
  5. data/lib/card/act_manager/stage_director.rb +22 -10
  6. data/lib/card/cache/persistent.rb +15 -9
  7. data/lib/card/format/nest.rb +12 -5
  8. data/lib/card/format/nest/fetch.rb +2 -1
  9. data/lib/card/format/render.rb +5 -2
  10. data/lib/card/set/event.rb +7 -1
  11. data/lib/card/subcards.rb +3 -3
  12. data/lib/card/view/cache.rb +1 -1
  13. data/lib/card/view/fetch.rb +17 -5
  14. data/lib/card/view/options.rb +52 -26
  15. data/lib/cardio.rb +2 -1
  16. data/mod/account/spec/set/right/account_spec.rb +17 -3
  17. data/mod/admin/set/self/admin.rb +0 -2
  18. data/mod/admin/spec/set/self/admin_spec.rb +14 -11
  19. data/mod/bootstrap/set/all/bootstrap/helper.rb +27 -29
  20. data/mod/carrierwave/set/type/file.rb +1 -1
  21. data/mod/carrierwave/set/type/image.rb +18 -6
  22. data/mod/core/set/all/collection.rb +33 -7
  23. data/mod/core/set/all/fetch.rb +16 -3
  24. data/mod/core/set/all/permissions.rb +6 -12
  25. data/mod/core/set/all/trash.rb +3 -1
  26. data/mod/core/spec/set/all/collection_spec.rb +9 -8
  27. data/mod/email/set/all/notify.rb +27 -17
  28. data/mod/email/set/right/follow.rb +49 -36
  29. data/mod/email/set/type/email_template.rb +25 -69
  30. data/mod/email/set/type/email_template/email_config.rb +63 -0
  31. data/mod/email/set/type_plus_right/user/follow.rb +3 -3
  32. data/mod/machines/lib/stylesheets/style_cards.scss +292 -0
  33. data/mod/pointer/set/abstract/01_pointer.rb +8 -8
  34. data/mod/pointer/set/abstract/01_pointer/edit.rb +6 -2
  35. data/mod/prosemirror_editor/lib/javascript/script_prosemirror.js +12283 -11605
  36. data/mod/prosemirror_editor/lib/javascript/script_prosemirror_config.js.coffee +1 -1
  37. data/mod/standard/set/abstract/01_search_params.rb +1 -1
  38. data/mod/standard/set/abstract/search/paging.rb +4 -4
  39. data/mod/standard/set/all/comment.rb +67 -47
  40. data/mod/standard/set/all/links.rb +2 -2
  41. data/mod/standard/set/all/rich_html/content.rb +1 -1
  42. data/mod/standard/set/all/rich_html/editing.rb +3 -2
  43. data/mod/standard/set/all/rich_html/form.rb +21 -12
  44. data/mod/standard/set/all/rich_html/header.rb +9 -0
  45. data/mod/standard/set/all/rich_html/menu.rb +16 -12
  46. data/mod/standard/set/all/rich_html/toolbar.rb +140 -130
  47. data/mod/standard/set/all/rich_html/wrapper.rb +11 -1
  48. data/mod/standard/set/rstar/rules_editor.rb +2 -34
  49. data/mod/standard/set/self/search.rb +1 -1
  50. data/mod/standard/set/type/set.rb +4 -4
  51. data/mod/standard/spec/set/type/email_template/email_config_spec.rb +218 -0
  52. data/mod/standard/spec/set/type/email_template_spec.rb +3 -185
  53. data/spec/lib/card/cache_spec.rb +0 -1
  54. data/spec/lib/card/format/render_spec.rb +19 -0
  55. data/spec/lib/card/stage_director_spec.rb +1 -1
  56. data/tmpsets/set/mod001-core/all/actify.rb +5 -6
  57. data/tmpsets/set/mod001-core/all/fetch.rb +14 -12
  58. data/tmpsets/set/mod001-core/all/name.rb +1 -1
  59. data/tmpsets/set/mod001-core/all/permissions.rb +12 -22
  60. data/tmpsets/set/mod001-core/all/tracked_attributes.rb +76 -0
  61. data/tmpsets/set/mod001-core/all/utils.rb +40 -3
  62. data/tmpsets/set/mod002-history/all/history.rb +1 -2
  63. data/tmpsets/set/mod008-solid_cache/abstract/solid_cache.rb +1 -1
  64. data/tmpsets/set/mod013-carrierwave/abstract/attachment.rb +282 -0
  65. data/tmpsets/set/mod013-carrierwave/type/file.rb +155 -0
  66. data/tmpsets/set/mod013-carrierwave/type/image.rb +96 -0
  67. data/tmpsets/set/mod014-admin/self/admin.rb +113 -0
  68. data/tmpsets/set/mod014-admin/self/admin_info.rb +110 -0
  69. data/tmpsets/set/mod014-admin/self/version.rb +15 -0
  70. data/tmpsets/set/mod015-developer/all/event_viz.rb +59 -0
  71. data/tmpsets/set/mod015-developer/all/view_viz.rb +30 -0
  72. data/tmpsets/set/mod015-developer/right/debug.rb +96 -0
  73. metadata +15 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f6f7c57e5d0fbbb3e0d01a20620dda63db140430
4
- data.tar.gz: 7cc371c0a6316b66dade977c1757d9bd172c6ca4
3
+ metadata.gz: c534f962f8efbd355dba40eb9c56d372a404ad31
4
+ data.tar.gz: 96581a6169cfb59c688226d2dec3ae3e649e4a78
5
5
  SHA512:
6
- metadata.gz: 4c412b712c3d638ba1d1701473ce9294541834ecf566d937db1b92f1e520709c2a7dc9d9f991fcfcbc99ba198c8403d0e52ddfee20a318b53823aa3eb6f10ea4
7
- data.tar.gz: 97ea814246b69a991fd77a29f7c3019fe827d46ed7efcac6773c6c1862ce4bd4daafe141abdfd7778f9c66f2078afbe7303aeb599699b79e5b477e0d26df8969
6
+ metadata.gz: 22480806d1d43f92b17003808caa026c0bd7061b210669cd5d761ae319b740e9e227685e08e9eb4b4abe7ec303db26ce49ed743a7181f3393abe24f2afdc1b66
7
+ data.tar.gz: ebc1391547c721118de7c1198936e5f27ab094f5e8285a7120a98d980298546eec0de17f2d2dafe829b6fc79653fdb7244e0df8e95b95df7543f9ee5246086b2
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.20.0
1
+ 1.20.1
@@ -47,7 +47,7 @@ Gem::Specification.new do |s|
47
47
  ["sass", "~> 3.2"],
48
48
  ["coffee-script", "~> 2.2"],
49
49
  ["uglifier", "~> 3.0"],
50
- ["nokogiri", "~> 1.6.8"],
50
+ ["nokogiri", "~> 1.6.8"], # 1.7 needs ruby 2.1
51
51
  ["haml", "~> 4.0"],
52
52
  ["kaminari", "~> 0.16"],
53
53
  ["bootstrap-kaminari-views", "~> 0"],
@@ -50,8 +50,8 @@ class Card < ActiveRecord::Base
50
50
  serializable_attr_accessor(
51
51
  :action, :supercard, :superleft,
52
52
  :current_act, :current_action,
53
- :comment, :comment_author, # obviated soon
54
- :update_referers, # wrong mechanism for this
53
+ :comment, # obviated soon
54
+ :update_referers, # wrong mechanism for this
55
55
  :update_all_users, # if the above is wrong then this one too
56
56
  :silent_change, # and this probably too
57
57
  :remove_rule_stash,
@@ -66,12 +66,16 @@ class Card < ActiveRecord::Base
66
66
 
67
67
  # VALIDATION PHASE
68
68
  :initialize_stage, :prepare_to_validate_stage, :validate_stage,
69
+ :initialize_final_stage, :prepare_to_validate_final_stage,
70
+ :validate_final_stage,
69
71
 
70
72
  # STORAGE PHASE
71
73
  :prepare_to_store_stage, :store_stage, :finalize_stage,
74
+ :prepare_to_store_final_stage, :store_final_stage, :finalize_final_stage,
72
75
 
73
76
  # INTEGRATION PHASE
74
- :integrate_stage, :integrate_with_delay_stage
77
+ :integrate_stage, :integrate_with_delay_stage,
78
+ :integrate_final_stage, :integrate_with_delay_final_stage
75
79
  )
76
80
 
77
81
  # Validation and integration phase are only called for the act card
@@ -202,12 +202,22 @@ class Card
202
202
  def run_single_stage stage, &block
203
203
  return true unless valid_next_stage? stage
204
204
  # puts "#{@card.name}: #{stage} stage".red
205
+ prepare_stage_run stage
206
+ execute_stage_run stage, &block
207
+ rescue => e
208
+ @card.clean_after_stage_fail
209
+ raise e
210
+ end
205
211
 
212
+ def prepare_stage_run stage
206
213
  @stage = stage_index stage
207
- if stage == :initialize
208
- @running ||= true
209
- prepare_for_phases
210
- end
214
+ return unless stage == :initialize
215
+
216
+ @running ||= true
217
+ prepare_for_phases
218
+ end
219
+
220
+ def execute_stage_run stage, &block
211
221
  # in the store stage it can be necessary that
212
222
  # other subcards must be saved before we save this card
213
223
  if stage == :store
@@ -215,24 +225,26 @@ class Card
215
225
  else
216
226
  run_stage_callbacks stage
217
227
  run_subdirector_stages stage
228
+ run_final_stage_callbacks stage
218
229
  end
219
- rescue => e
220
- @card.clean_after_stage_fail
221
- raise e
222
230
  end
223
231
 
224
- def run_stage_callbacks stage
232
+ def run_stage_callbacks stage, callback_postfix=""
225
233
  Rails.logger.debug "#{stage}: #{@card.name}"
226
234
  # we use abort :success in the :store stage for :save_draft
227
235
  if stage_index(stage) <= stage_index(:store) && !main?
228
236
  @card.abortable do
229
- @card.run_callbacks :"#{stage}_stage"
237
+ @card.run_callbacks :"#{stage}#{callback_postfix}_stage"
230
238
  end
231
239
  else
232
- @card.run_callbacks :"#{stage}_stage"
240
+ @card.run_callbacks :"#{stage}#{callback_postfix}_stage"
233
241
  end
234
242
  end
235
243
 
244
+ def run_final_stage_callbacks stage
245
+ run_stage_callbacks stage, "_final"
246
+ end
247
+
236
248
  def run_subdirector_stages stage
237
249
  @subdirectors.each do |subdir|
238
250
  subdir.catch_up_to_stage stage
@@ -63,7 +63,7 @@ class Card
63
63
  # the cache. Note that Cardio.cache is a simple Rails::Cache, not
64
64
  # a Card::Cache object.
65
65
  def stamp
66
- @stamp ||= Cardio.cache.fetch stamp_key { new_stamp }
66
+ @stamp ||= Cardio.cache.fetch(stamp_key) { new_stamp }
67
67
  end
68
68
 
69
69
  # key for looking up the current stamp
@@ -73,7 +73,7 @@ class Card
73
73
 
74
74
  # stamp generator
75
75
  def new_stamp
76
- Time.now.to_i.to_s 32
76
+ Time.now.to_i.to_s(32) + rand(9999).to_s(32)
77
77
  end
78
78
 
79
79
  # prefix added to cache key to create a system-wide unique key
@@ -96,17 +96,23 @@ class Card
96
96
  # @param key [String]
97
97
  # @param attribute [String, Symbol]
98
98
  def write_attribute key, attribute, value
99
- if @store && (object = read key)
99
+ return value unless @store
100
+ if (object = deep_read key)
100
101
  object.instance_variable_set "@#{attribute}", value
101
102
  write key, object
102
103
  end
103
104
  value
104
- rescue
105
- # FIXME: somehow read is finding Card objects with set_modules_loaded
106
- # That shouldn't be possible (#fetch is designed to prevent it), and
107
- # it immediately breaks write. Best guess is that #read is somehow
108
- # shortcutting and returning current object. need to research!
109
- Rails.logger.info "failed to write attribute: #{attribute}"
105
+ end
106
+
107
+ def deep_read key
108
+ local_cache = @store.send :local_cache
109
+ local_cache.clear if local_cache
110
+ read key
111
+ end
112
+
113
+ def read_attribute key, attribute
114
+ object = deep_read key
115
+ object.instance_variable_get "@#{attribute}"
110
116
  end
111
117
 
112
118
  def write key, value
@@ -50,20 +50,27 @@ class Card
50
50
  end
51
51
 
52
52
  def nest_subformat nested_card, opts, view
53
- return self if reuse_format? opts, view
53
+ return self if reuse_format? opts[:nest_name], view
54
54
  sub = subformat nested_card
55
55
  sub.main! if opts[:main]
56
56
  sub
57
57
  end
58
58
 
59
- def reuse_format? opts, view
60
- return false unless opts[:nest_name] =~ /^_(self)?$/
61
- !content_view? view
59
+ def reuse_format? nest_name, view
60
+ nest_name =~ /^_(self)?$/ &&
61
+ card.context_card == card &&
62
+ !nest_recursion_risk?(view)
63
+ end
64
+
65
+ def nest_recursion_risk? view
66
+ content_view?(view) && voo.structure
62
67
  end
63
68
 
64
69
  def content_view? view
65
70
  # TODO: this should be specified in view definition
66
- [:core, :content, :titled, :open, :closed].member? view.to_sym
71
+ [
72
+ :core, :content, :titled, :open, :closed, :open_content
73
+ ].member? view.to_sym
67
74
  end
68
75
 
69
76
  # Main difference compared to #nest is that you can use
@@ -7,6 +7,7 @@ class Card
7
7
  case cardish
8
8
  when Card then cardish
9
9
  when Symbol, Integer then Card.fetch cardish
10
+ when "_", "_self" then card.context_card
10
11
  else
11
12
  opts[:nest_name] = cardish.to_s
12
13
  Card.fetch cardish, new: nest_new_args(opts)
@@ -19,7 +20,7 @@ class Card
19
20
  nest_name = nest_opts[:nest_name].to_s
20
21
  new_args = { name: nest_name, type: nest_opts[:type] }
21
22
 
22
- new_args[:supercard] = card unless nest_name.strip.blank?
23
+ new_args[:supercard] = card.context_card unless nest_name.strip.blank?
23
24
  # special case. gets absolutized incorrectly. fix in smartname?
24
25
 
25
26
  nest_new_main_args new_args if nest_name =~ /^_main\+/
@@ -49,8 +49,11 @@ class Card
49
49
 
50
50
  # setting (:alway, :never, :nested) designated in view definition
51
51
  def view_cache_setting view
52
- setting_method = self.class.view_cache_setting_method view
53
- respond_to?(setting_method) ? send(setting_method) : :standard
52
+ method = self.class.view_cache_setting_method view
53
+ coded_setting = respond_to?(method) ? send(method) : :standard
54
+ return :never if coded_setting == :never
55
+ # seems unwise to override a hard-coded "never"
56
+ (voo && voo.cache) || coded_setting
54
57
  end
55
58
 
56
59
  def stub_render cached_content
@@ -78,11 +78,17 @@ class Card
78
78
  if opts[:after] || opts[:before]
79
79
  # ignore :in options
80
80
  elsif opts[:in]
81
- opts[:after] = :"#{opts.delete(:in)}_stage" if opts[:in]
81
+ opts[:after] =
82
+ callback_name opts.delete(:in), opts.delete(:after_subcards)
82
83
  end
83
84
  opts[:on] = [:create, :update] if opts[:on] == :save
84
85
  end
85
86
 
87
+ def callback_name stage, after_subcards=false
88
+ name = after_subcards ? "#{stage}_final_stage" : "#{stage}_stage"
89
+ name.to_sym
90
+ end
91
+
86
92
  def define_event_method event, call_method
87
93
  class_eval do
88
94
  define_method event do
@@ -41,8 +41,6 @@ class Card
41
41
  case name_or_card_or_attr
42
42
  when Card
43
43
  new_by_card name_or_card_or_attr, attr_or_opts
44
- when Symbol, String
45
- new_by_attributes name_or_card_or_attr, attr_or_opts
46
44
  when Hash
47
45
  args = name_or_card_or_attr
48
46
  if args[:name]
@@ -50,6 +48,8 @@ class Card
50
48
  else
51
49
  multi_add args
52
50
  end
51
+ else
52
+ new_by_attributes name_or_card_or_attr, attr_or_opts
53
53
  end
54
54
  end
55
55
 
@@ -251,7 +251,7 @@ class Card
251
251
  (absolute_name.parts.size - @context_card.cardname.parts.size) > 2
252
252
  left_card = new_by_attributes absolute_name.left
253
253
  new_by_card left_card, transact_in_stage: attributes[:transact_in_stage]
254
- left_card.new_by_attributes absolute_name, attributes
254
+ left_card.subcards.new_by_attributes absolute_name, attributes
255
255
  else
256
256
  subcard_args = extract_subcard_args! attributes
257
257
  t_i_s = attributes.delete(:transact_in_stage)
@@ -20,7 +20,7 @@ class Card
20
20
  end
21
21
 
22
22
  # answers: should this cache fetch depend on one already in progress?
23
- # Note that f you create a brand new format object (ie, not a subformat)
23
+ # Note that if you create a brand new format object (ie, not a subformat)
24
24
  # midrender, (eg card.format...), it needs to be treated as unrelated to
25
25
  # any caching in progress.
26
26
  def caching?
@@ -11,10 +11,12 @@ class Card
11
11
  # - creating a stub within another render
12
12
  # (so that the stub may be rendered later)
13
13
  def fetch &block
14
- case cache_level
15
- when :yield then yield
16
- when :cache_yield then cache_fetch(&block)
17
- when :stub then stub
14
+ with_fetch_logging do |cache_level|
15
+ case cache_level
16
+ when :yield then yield
17
+ when :cache_yield then cache_fetch(&block)
18
+ when :stub then stub
19
+ end
18
20
  end
19
21
  end
20
22
 
@@ -27,11 +29,21 @@ class Card
27
29
  # * *standard* (default) cache independently or dependently, but
28
30
  # don't double cache
29
31
  # * *never* don't ever cache this view
30
- def cache_level
32
+ def determine_cache_level
31
33
  return :yield unless Cardio.config.view_cache
32
34
  send "#{caching? ? 'dependent' : 'independent'}_cache_level"
33
35
  end
34
36
 
37
+ def with_fetch_logging
38
+ cache_level = determine_cache_level
39
+ logging = false # TODO: make configurable
40
+ if logging
41
+ puts "FETCH_VIEW (#{card.name}##{requested_view})" \
42
+ "cache-level = #{cache_level}"
43
+ end
44
+ yield cache_level
45
+ end
46
+
35
47
  # INDEPENDENT CACHING
36
48
  # takes place on its own (not within another view being cached)
37
49
 
@@ -7,30 +7,31 @@ class Card
7
7
  nest: [
8
8
  :view, # view to render
9
9
  :show, # render these views when optional
10
- :hide, # do render these views when optional
10
+ :hide, # do not render these views when optional
11
11
  :nest_name, # name as used in nest
12
12
  :nest_syntax # full nest syntax
13
13
  ],
14
14
  # note: show/hide can be single view (Symbol), list of views (Array),
15
15
  # or comma separated views (String)
16
16
  heir: [
17
- :main, # format object is page's "main" object (Boolean)
18
- :home_view, # view for slot to return to when no view specified
19
- :edit_structure # use a different structure for editing (Array)
20
-
17
+ :main, # format object is page's "main" object (Boolean)
18
+ :home_view, # view for slot to return to when no view specified
19
+ :edit_structure # use a different structure for editing (Array)
21
20
  ],
22
21
  both: [
23
- :help, # cue text when editing
24
- :structure, # overrides the content of the card
25
- :title, # overrides the name of the card
26
- :variant, # override the canonical version of the name with
27
- # a different variant
28
- :editor, # inline_nests makes a form within standard content
29
- # (Symbol)
30
- :type, # set the default type of new cards
31
- :size, # set an image size
32
- :params, # parameters for add button. deprecate?
33
- :items # options for items (Hash)
22
+ :help, # cue text when editing
23
+ :structure, # overrides the content of the card
24
+ :title, # overrides the name of the card
25
+ :variant, # override the canonical version of the name with
26
+ # a different variant
27
+ :editor, # inline_nests makes a form within standard content
28
+ # (Symbol)
29
+ :type, # set the default type of new cards
30
+ :size, # set an image size
31
+ :params, # parameters for add button. deprecate?
32
+ :items, # options for items (Hash)
33
+ :cache # change view cache behaviour
34
+ # (Symbol<:always, :standard, :never>)
34
35
  ],
35
36
  none: [
36
37
  :skip_perms, # do not check permissions for this view (Boolean)
@@ -55,6 +56,24 @@ class Card
55
56
  def heir_keys
56
57
  @heir_keys ||= ::Set.new(keymap[:both]) + keymap[:heir]
57
58
  end
59
+
60
+ def accessible_keys
61
+ heir_keys + [:nest_name, :nest_syntax] - [:items]
62
+ end
63
+
64
+ def define_getter option_key
65
+ define_method option_key do
66
+ norm_method = "normalize_#{option_key}"
67
+ value = live_options[option_key]
68
+ try(norm_method, value) || value
69
+ end
70
+ end
71
+
72
+ def define_setter option_key
73
+ define_method "#{option_key}=" do |value|
74
+ live_options[option_key] = value
75
+ end
76
+ end
58
77
  end
59
78
 
60
79
  # There are two primary options hashes:
@@ -76,28 +95,35 @@ class Card
76
95
  live_options[:items] ||= {}
77
96
  end
78
97
 
79
- (heir_keys + [:nest_name, :nest_syntax] - [:items]).each do |option_key|
80
- define_method option_key do
81
- norm_method = "normalize_#{option_key}"
82
- value = live_options[option_key]
83
- try(norm_method, value) || value
84
- end
85
-
86
- define_method "#{option_key}=" do |value|
87
- live_options[option_key] = value
88
- end
98
+ accessible_keys.each do |option_key|
99
+ define_getter option_key
100
+ define_setter option_key
89
101
  end
90
102
 
91
103
  def normalize_editor value
92
104
  value && value.to_sym
93
105
  end
94
106
 
107
+ def normalize_cache value
108
+ value && value.to_sym
109
+ end
110
+
95
111
  # options to be used in data attributes of card slots (normalized options
96
112
  # with standard keys)
97
113
  def slot_options
98
114
  normalized_options.select { |k, _v| Options.all_keys.include? k }
99
115
  end
100
116
 
117
+ def closest_live_option key
118
+ if live_options.key? key
119
+ live_options[key]
120
+ else
121
+ (parent && parent.closest_live_option(key)) ||
122
+ (format.parent && format.parent.voo &&
123
+ format.parent.voo.closest_live_option(key))
124
+ end
125
+ end
126
+
101
127
  private
102
128
 
103
129
  # option normalization includes standardizing options into a hash with
@@ -47,6 +47,7 @@ module Cardio
47
47
  acts_per_page: 10,
48
48
  space_last_in_multispace: true,
49
49
  closed_search_limit: 10,
50
+ paging_limit: 20,
50
51
 
51
52
  non_createable_types: [%w(signup setting set)],
52
53
  view_cache: false,
@@ -58,7 +59,7 @@ module Cardio
58
59
 
59
60
  file_storage: :local,
60
61
  file_buckets: {},
61
- file_default_bucket: nil
62
+ file_default_bucket: nil
62
63
  }
63
64
  end
64
65