card 1.20.1 → 1.20.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/card.gemspec +2 -2
  4. data/db/migrate_core_cards/20160811115836_rename_stats_to_admin.rb +2 -2
  5. data/db/migrate_core_cards/20170209132834_email_test_context.rb +47 -0
  6. data/db/migrate_core_cards/data/mailer/follower_notification_email.html +1 -1
  7. data/db/migrate_core_cards/data/mailer/follower_notification_email.txt +1 -1
  8. data/db/migrate_core_cards/data/mailer/mail_config.json +1 -1
  9. data/db/seed/new/card_actions.yml +699 -771
  10. data/db/seed/new/card_acts.yml +64 -616
  11. data/db/seed/new/card_changes.yml +9222 -25055
  12. data/db/seed/new/card_references.yml +767 -606
  13. data/db/seed/new/cards.yml +2125 -1829
  14. data/db/seed/test/fixtures/card_actions.yml +1713 -1825
  15. data/db/seed/test/fixtures/card_acts.yml +341 -893
  16. data/db/seed/test/fixtures/card_changes.yml +20868 -36801
  17. data/db/seed/test/fixtures/card_references.yml +1516 -1250
  18. data/db/seed/test/fixtures/cards.yml +3194 -2898
  19. data/db/version_core_cards.txt +1 -1
  20. data/lib/card/env/location.rb +1 -1
  21. data/lib/card/format/content.rb +1 -1
  22. data/lib/card/format/nest/subformat.rb +2 -1
  23. data/lib/card/format/render.rb +19 -1
  24. data/lib/card/mailer.rb +5 -2
  25. data/lib/card/model/save_helper.rb +15 -4
  26. data/lib/card/name.rb +1 -45
  27. data/lib/card/name/fields_and_traits.rb +10 -9
  28. data/lib/card/name/{variants.rb → name_variants.rb} +1 -1
  29. data/lib/card/query.rb +28 -2
  30. data/lib/card/query/helpers.rb +1 -0
  31. data/lib/card/query/interpretation.rb +1 -0
  32. data/lib/card/query/relational_attributes.rb +27 -5
  33. data/lib/card/query/sql_statement.rb +1 -1
  34. data/lib/card/tasks/card/create.rake +177 -0
  35. data/mod/carrierwave/set/type/file.rb +1 -1
  36. data/mod/carrierwave/set/type/image.rb +9 -2
  37. data/mod/core/chunk/reference.rb +1 -1
  38. data/mod/core/set/all/assign_attributes.rb +14 -14
  39. data/mod/core/set/all/collection.rb +1 -1
  40. data/mod/core/set/all/fetch.rb +4 -0
  41. data/mod/core/set/all/haml.rb +82 -3
  42. data/mod/core/set/all/name.rb +7 -6
  43. data/mod/core/set/all/references.rb +1 -1
  44. data/mod/core/set/all/subcards.rb +4 -0
  45. data/mod/core/set_pattern/07_type_plus_right.rb +1 -1
  46. data/mod/core/spec/set/all/{tracked_attributes_spec.rb → assign_attributes_spec.rb} +1 -1
  47. data/mod/email/set/abstract/test_context.rb +26 -0
  48. data/mod/email/set/all/notify.rb +10 -5
  49. data/mod/email/set/right/html_message.rb +2 -0
  50. data/mod/email/set/right/subject.rb +1 -0
  51. data/mod/email/set/right/text_message.rb +1 -0
  52. data/mod/history/set/all/content_history.rb +2 -1
  53. data/mod/machines/set/type/coffee_script.rb +1 -1
  54. data/mod/pointer/set/abstract/01_pointer/edit.rb +10 -7
  55. data/mod/pointer/spec/set/type/pointer_spec.rb +2 -2
  56. data/mod/standard/set/abstract/wql_search.rb +1 -1
  57. data/mod/standard/set/all/rich_html/form.rb +128 -169
  58. data/mod/standard/set/all/rich_html/form_elements.rb +52 -0
  59. data/mod/standard/set/all/rich_html/formgroup.rb +34 -0
  60. data/mod/standard/set/type/session.rb +2 -8
  61. data/mod/standard/set/type/toggle.rb +23 -3
  62. data/mod/standard/spec/set/type/email_template/email_config_spec.rb +24 -13
  63. data/mod/standard/spec/set/type/toggle_spec.rb +13 -2
  64. data/spec/lib/card/name_spec.rb +1 -224
  65. data/spec/lib/card/query_spec.rb +56 -1
  66. data/spec/lib/card/stage_director_spec.rb +19 -0
  67. data/spec/support/helper/render_helper.rb +2 -0
  68. data/tmpsets/set/mod001-core/all/actify.rb +6 -5
  69. data/tmpsets/set/mod001-core/all/fetch.rb +12 -14
  70. data/tmpsets/set/mod001-core/all/name.rb +1 -1
  71. data/tmpsets/set/mod001-core/all/permissions.rb +22 -12
  72. data/tmpsets/set/mod001-core/all/tracked_attributes.rb +0 -76
  73. data/tmpsets/set/mod001-core/all/utils.rb +3 -40
  74. data/tmpsets/set/mod002-history/all/history.rb +2 -1
  75. data/tmpsets/set/mod008-solid_cache/abstract/solid_cache.rb +1 -1
  76. metadata +15 -17
  77. data/tmpsets/set/mod013-carrierwave/abstract/attachment.rb +0 -282
  78. data/tmpsets/set/mod013-carrierwave/type/file.rb +0 -155
  79. data/tmpsets/set/mod013-carrierwave/type/image.rb +0 -96
  80. data/tmpsets/set/mod014-admin/self/admin.rb +0 -113
  81. data/tmpsets/set/mod014-admin/self/admin_info.rb +0 -110
  82. data/tmpsets/set/mod014-admin/self/version.rb +0 -15
  83. data/tmpsets/set/mod015-developer/all/event_viz.rb +0 -59
  84. data/tmpsets/set/mod015-developer/all/view_viz.rb +0 -30
  85. data/tmpsets/set/mod015-developer/right/debug.rb +0 -96
@@ -21,7 +21,7 @@ format do
21
21
  end
22
22
 
23
23
  def source_url
24
- card.attachment.url
24
+ internal_url card.attachment.url
25
25
  end
26
26
 
27
27
  view :core do
@@ -16,7 +16,7 @@ format do
16
16
 
17
17
  def source_url
18
18
  return card.raw_content if card.web?
19
- selected_version.url
19
+ internal_url selected_version.url
20
20
  end
21
21
 
22
22
  def selected_version
@@ -90,8 +90,15 @@ format :html do
90
90
  end
91
91
  end
92
92
 
93
+ format do
94
+ view :inline do
95
+ _render_core
96
+ end
97
+ end
98
+
93
99
  format :email_html do
94
- view :core do
100
+ view :inline do
101
+ determine_image_size
95
102
  url_generator = voo.closest_live_option(:inline_attachment_url)
96
103
  path = selected_version.path
97
104
  return _render_source unless url_generator && ::File.exist?(path)
@@ -32,7 +32,7 @@ class Card
32
32
  chunk.replace_reference old_name, new_name
33
33
  end
34
34
  else
35
- @name = name.to_name.replace_part(old_name, new_name)
35
+ @name = name.to_name.replace(old_name, new_name)
36
36
  end
37
37
  end
38
38
 
@@ -17,6 +17,19 @@ def assign_set_specific_attributes
17
17
  end
18
18
  end
19
19
 
20
+ def extract_subcard_args! args
21
+ subcards = args.delete("subcards") || args.delete(:subcards) || {}
22
+ if (subfields = args.delete("subfields") || args.delete(:subfields))
23
+ subfields.each_pair do |key, value|
24
+ subcards[cardname.field(key)] = value
25
+ end
26
+ end
27
+ args.keys.each do |key|
28
+ subcards[key] = args.delete(key) if key =~ /^\+/
29
+ end
30
+ subcards
31
+ end
32
+
20
33
  protected
21
34
 
22
35
  def prepare_assignment_params args
@@ -67,26 +80,13 @@ def normalize_type_attributes args
67
80
  args["type_id"] = new_type_id if new_type_id
68
81
  end
69
82
 
70
- def extract_subcard_args! args
71
- subcards = args.delete("subcards") || {}
72
- if (subfields = args.delete("subfields"))
73
- subfields.each_pair do |key, value|
74
- subcards[cardname.field(key)] = value
75
- end
76
- end
77
- args.keys.each do |key|
78
- subcards[key] = args.delete(key) if key =~ /^\+/
79
- end
80
- subcards
81
- end
82
-
83
83
  def extract_type_id! args={}
84
84
  type_id =
85
85
  case
86
86
  when args["type_id"]
87
87
  id = args.delete("type_id").to_i
88
88
  # type_id can come in as 0,'' or nil
89
- id == 0 ? nil : id
89
+ id.zero? ? nil : id
90
90
  when args["type_code"]
91
91
  Card.fetch_id args.delete("type_code").to_sym
92
92
  when args["type"]
@@ -136,7 +136,7 @@ end
136
136
 
137
137
  def with_context card
138
138
  old_context = @context_card
139
- @context_card = card
139
+ @context_card = card if card
140
140
  result = yield
141
141
  @context_card = old_context
142
142
  result
@@ -91,6 +91,10 @@ module ClassMethods
91
91
  end
92
92
  end
93
93
 
94
+ def fetch_type_id mark
95
+ (card = quick_fetch(mark)) && card.type_id
96
+ end
97
+
94
98
  def quick_fetch mark
95
99
  fetch mark, skip_virtual: true, skip_modules: true
96
100
  end
@@ -1,7 +1,86 @@
1
1
  format do
2
- def render_haml locals={}, template=nil, a_binding=nil, &block
3
- template ||= yield
2
+ # Renders haml templates. The haml template can be passed as string or
3
+ # block or a symbol that refers to a view template.
4
+ # @param template_or_locals [Hash, String, Symbol]
5
+ # If a symbol is given then a template is expected in the corresponding view
6
+ # directory. Note that {view_template_path} needs to be overridden in
7
+ # that case to get the right path to the template.
8
+ # @return [String] rendered haml as HTML
9
+ # @example render a view template
10
+ # # view/type/basic/my_template.haml:
11
+ # %p
12
+ # Hi
13
+ # = name
14
+ #
15
+ # # set/type/basic.rb:
16
+ # view :my_view do
17
+ # render_haml :my_template, name: "Joe: # => "<p>Hi Joe<p/>"
18
+ # end
19
+ # @example use a block to pass haml
20
+ # render_haml name: "Joe" do
21
+ # <<-HAML.strip_heredoc
22
+ # %p
23
+ # Hi
24
+ # = name
25
+ # HAML
26
+ # # => <p>Hi Joe</p>
27
+ # @example create a slot in haml code
28
+ # - haml_wrap do
29
+ # %p
30
+ # some haml
31
+ def render_haml template_or_locals={}, locals_or_binding=nil, a_binding=nil
32
+ if template_or_locals.is_a?(Symbol)
33
+ return render_haml_template template_or_locals, locals_or_binding || {}
34
+ end
35
+ if block_given?
36
+ haml_to_html yield, template_or_locals, locals_or_binding
37
+ else
38
+ haml_to_html template_or_locals, locals_or_binding, a_binding
39
+ end
40
+ end
41
+
42
+ # @todo Make this more like Rails a implicit feature of a view.
43
+ # For a start use a different view command. Example
44
+ # # view/type/basic/my_view.haml:
45
+ # = name
46
+ #
47
+ # # set/type/basic.rb:
48
+ # haml_view :myview do
49
+ # @name = "Joe"
50
+ # end
51
+ def render_haml_template view, locals={}
52
+ template = ::File.read view_template_path(view)
53
+ voo = View.new self, view, locals, @voo
54
+ with_voo voo do
55
+ haml_to_html template, locals
56
+ end
57
+ end
58
+
59
+ # @todo This is a hack to make haml view templates work.
60
+ # Needs a general automatic solution.
61
+ # This method must be overridden in every set that uses haml templates
62
+ # so that `__FILE__` points to the right file.
63
+ # @return [String] path to haml view template
64
+ # @example
65
+ # def view_template_path view
66
+ # super(view, __FILE__)
67
+ # end
68
+ def view_template_path view, tmp_set_path=__FILE__
69
+ basename = ::File.basename(tmp_set_path, ".rb")
70
+ try_view_template_path("../#{view}", tmp_set_path) ||
71
+ try_view_template_path("../#{basename}/#{view}", tmp_set_path) ||
72
+ raise(Card::Error, "can't find haml template for #{view}")
73
+ end
74
+
75
+ def try_view_template_path template_path, tmp_set_path, ext="haml"
76
+ path = ::File.expand_path("#{template_path}.#{ext}", tmp_set_path)
77
+ .gsub(%r{/tmp/set/mod\d+-([^/]+)/}, '/mod/\1/view/')
78
+ ::File.exist?(path) && path
79
+ end
80
+
81
+ def haml_to_html haml, locals, a_binding=nil
4
82
  a_binding ||= binding
5
- ::Haml::Engine.new(template).render(a_binding, locals)
83
+ ::Haml::Engine.new(haml).render a_binding, locals || {}
6
84
  end
7
85
  end
86
+
@@ -46,23 +46,24 @@ def key= newkey
46
46
  newkey
47
47
  end
48
48
 
49
- def update_subcard_names cardname
49
+ def update_subcard_names new_name, name_to_replace=nil
50
50
  return unless @subcards
51
51
  subcards.each do |subcard|
52
52
  # if subcard has a relative name like +C
53
53
  # and self is a subcard as well that changed from +B to A+B then
54
- # +C should change to A+B+C. #replace_part doesn't work in this case
54
+ # +C should change to A+B+C. #replace doesn't work in this case
55
55
  # because the old name +B is not a part of +C
56
- name_to_replace =
56
+ name_to_replace ||=
57
57
  if subcard.cardname.junction? &&
58
58
  subcard.cardname.parts.first.empty? &&
59
- cardname.parts.first.present?
59
+ new_name.parts.first.present?
60
60
  # replace the empty part
61
61
  "".to_name
62
62
  else
63
63
  name
64
64
  end
65
- subcard.name = subcard.cardname.replace_part name_to_replace, cardname.s
65
+ subcard.name = subcard.cardname.replace name_to_replace, new_name.s
66
+ subcard.update_subcard_names new_name, name
66
67
  end
67
68
  end
68
69
 
@@ -265,7 +266,7 @@ event :cascade_name_changes, :finalize, on: :update, changed: :name do
265
266
  # cards, have to go this low level to avoid callbacks.
266
267
  Rails.logger.info "cascading name: #{de.name}"
267
268
  Card.expire de.name # old name
268
- newname = de.cardname.replace_part name_was, name
269
+ newname = de.cardname.replace name_was, name
269
270
  Card.where(id: de.id).update_all name: newname.to_s, key: newname.key
270
271
  de.update_referers = update_referers
271
272
  de.refresh_references_in
@@ -46,7 +46,7 @@ def replace_reference_syntax old_name, new_name
46
46
  obj_content = Card::Content.new raw_content, self
47
47
  obj_content.find_chunks(Card::Content::Chunk::Reference).select do |chunk|
48
48
  next unless (old_ref_name = chunk.referee_name)
49
- next unless (new_ref_name = old_ref_name.replace_part old_name, new_name)
49
+ next unless (new_ref_name = old_ref_name.replace old_name, new_name)
50
50
  chunk.referee_name = chunk.replace_reference old_name, new_name
51
51
  refs = Card::Reference.where referee_key: old_ref_name.key
52
52
  refs.update_all referee_key: new_ref_name.key
@@ -49,6 +49,10 @@ def clear_subcards
49
49
  subcards.clear
50
50
  end
51
51
 
52
+ def subfield_present? field_name
53
+ (field_card = subfield(field_name)) && field_card.content.present?
54
+ end
55
+
52
56
  def deep_clear_subcards
53
57
  subcards.deep_clear
54
58
  end
@@ -16,7 +16,7 @@ def prototype_args anchor
16
16
  end
17
17
 
18
18
  def anchor_name card
19
- left = card.left
19
+ left = card.left new: {}
20
20
  type_name = (left && left.type_name) || Card[Card.default_type_id].name
21
21
  "#{type_name}+#{card.cardname.tag}"
22
22
  end
@@ -29,7 +29,7 @@ module RenameMethods
29
29
  end
30
30
  end
31
31
 
32
- describe Card::Set::All::AssignAttributes do
32
+ RSpec.describe Card::Set::All::AssignAttributes do
33
33
  include RenameMethods
34
34
 
35
35
  describe "set_name" do
@@ -0,0 +1,26 @@
1
+ format :html do
2
+ view :core do
3
+ return super() if voo.hide? :test_context
4
+ card.with_context test_context_card do
5
+ super()
6
+ end
7
+ end
8
+
9
+ def test_context_card
10
+ (tc = card.left.fetch(trait: :test_context)) && tc.item_cards.first
11
+ end
12
+ end
13
+
14
+ format :email_html do
15
+ view :core do
16
+ voo.hide! :test_context
17
+ super()
18
+ end
19
+ end
20
+
21
+ format :email_text do
22
+ view :core do
23
+ voo.hide! :test_context
24
+ super()
25
+ end
26
+ end
@@ -184,7 +184,7 @@ format do
184
184
  (option_card = follow_option_card)
185
185
  option_card.description set_card
186
186
  else
187
- "followed card"
187
+ "*followed set of cards*"
188
188
  end
189
189
  end
190
190
 
@@ -258,17 +258,22 @@ format do
258
258
  end
259
259
  end
260
260
 
261
- format :email_text do
262
- view :last_action, perms: :none do |args|
261
+ format do
262
+ view :last_action_verb do |args|
263
263
  act = get_act(args)
264
264
  "#{act.main_action.action_type}d"
265
265
  end
266
266
  end
267
267
 
268
+ format :email_text do
269
+ view :last_action, perms: :none do |args|
270
+ _render_last_action_verb args
271
+ end
272
+ end
273
+
268
274
  format :email_html do
269
275
  view :last_action, perms: :none do |args|
270
- act = get_act(args)
271
- "#{act.main_action.action_type}d"
276
+ _render_last_action_verb args
272
277
  end
273
278
 
274
279
  def wrap_list list
@@ -1,3 +1,5 @@
1
+ include_set Abstract::TestContext
2
+
1
3
  def clean_html?
2
4
  false
3
5
  end
@@ -0,0 +1 @@
1
+ include_set Abstract::TestContext
@@ -0,0 +1 @@
1
+ include_set Abstract::TestContext
@@ -164,5 +164,6 @@ end
164
164
  def edit_conflict?
165
165
  last_action_id_before_edit &&
166
166
  last_action_id_before_edit.to_i != last_action_id &&
167
- last_action.act.actor_id != Auth.current_id
167
+ (la = last_action) &&
168
+ la.act.actor_id != Auth.current_id
168
169
  end
@@ -17,6 +17,6 @@ format do
17
17
  def compile_coffee script
18
18
  ::CoffeeScript.compile script
19
19
  rescue => e
20
- raise Card::Error, "CoffeeScript::Error (#{name}): #{e.message}"
20
+ raise Card::Error, "CoffeeScript::Error (#{card.name}): #{e.message}"
21
21
  end
22
22
  end
@@ -79,7 +79,7 @@ format :html do
79
79
  id = "pointer-checkbox-#{option_name.to_name.key}"
80
80
  <<-HTML
81
81
  <div class="pointer-checkbox">
82
- #{check_box_tag 'pointer_checkbox', option_name, checked,
82
+ #{check_box_tag "pointer_checkbox-#{unique_id}", option_name, checked,
83
83
  id: id, class: 'pointer-checkbox-button'}
84
84
  #{option_label option_name, id}
85
85
  #{option_description 'checkbox', option_name}
@@ -92,7 +92,7 @@ format :html do
92
92
 
93
93
  view :multiselect do |_args|
94
94
  select_tag(
95
- "pointer_multiselect",
95
+ "pointer_multiselect-#{unique_id}",
96
96
  options_for_select(card.option_names, card.item_names),
97
97
  multiple: true, class: "pointer-multiselect form-control"
98
98
  )
@@ -117,9 +117,12 @@ format :html do
117
117
  end
118
118
 
119
119
  def option_label option_name, id
120
+ %(<label for="#{id}">#{option_label_text option_name}</label>)
121
+ end
122
+
123
+ def option_label_text option_name
120
124
  o_card = Card.fetch(option_name)
121
- label = (o_card && o_card.label) || option_name
122
- %(<label for="#{id}">#{label}</label>)
125
+ (o_card && o_card.label) || option_name
123
126
  end
124
127
 
125
128
  # @param option_type [String] "checkbox" or "radio"
@@ -130,7 +133,7 @@ format :html do
130
133
 
131
134
  view :select do |_args|
132
135
  options = [["-- Select --", ""]] + card.option_names.map { |x| [x, x] }
133
- select_tag("pointer_select",
136
+ select_tag("pointer_select-#{unique_id}",
134
137
  options_for_select(options, card.item_names.first),
135
138
  class: "pointer-select form-control")
136
139
  end
@@ -161,8 +164,8 @@ def << item
161
164
  add_item newname
162
165
  end
163
166
 
164
- def add_item name
165
- return if include_item? name
167
+ def add_item name, allow_duplicates=false
168
+ return if !allow_duplicates && include_item?(name)
166
169
  self.content = "[[#{(item_names << name).reject(&:blank?) * "]]\n[["}]]"
167
170
  end
168
171
 
@@ -150,10 +150,10 @@ describe Card::Set::Type::Pointer do
150
150
  option_html =
151
151
  'input[class="pointer-checkbox-button"]'\
152
152
  '[checked="checked"]'\
153
- '[name="pointer_checkbox"][type="checkbox"]'\
153
+ '[type="checkbox"]'\
154
154
  '[value="nonexistingcardmustnotexistthisistherule"]'\
155
155
  '[id="pointer-checkbox-nonexistingcardmustnotexistthisistherule"]'
156
- assert_view_select @pointer.format.render_checkbox, option_html
156
+ debug_assert_view_select @pointer.format.render_checkbox, option_html
157
157
  assert_view_select @inherit_pointer.format.render_checkbox, option_html
158
158
  end
159
159
 
@@ -18,7 +18,7 @@ def wql_hash
18
18
  end
19
19
 
20
20
  def query args={}
21
- query_args = wql_hash.merge! args
21
+ query_args = wql_hash.merge args
22
22
  query_args = standardized_query_args query_args
23
23
  Query.new query_args, name
24
24
  end