card 1.20.0 → 1.20.1

Sign up to get free protection for your applications and to get access to all the features.
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