card 1.93.5 → 1.93.6

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/db/migrate_core_cards/data/1.12_stylesheets/classic_cards.scss +1 -1
  4. data/db/migrate_core_cards/data/1.12_stylesheets/traditional.scss +2 -1
  5. data/lib/card/format/nest.rb +4 -1
  6. data/lib/card/format/nest/mode.rb +11 -3
  7. data/lib/card/query.rb +6 -2
  8. data/lib/card/query/sorting.rb +21 -12
  9. data/lib/card/query/sql_statement.rb +1 -2
  10. data/lib/card/view/options.rb +17 -12
  11. data/mod/Modfile +1 -0
  12. data/mod/core/layout/simple_modal.html +3 -0
  13. data/mod/core/set/all/fetch_helper.rb +42 -30
  14. data/mod/core/spec/format/html_format_spec.rb +10 -17
  15. data/mod/core/spec/set/all/fetch_helper_spec.rb +48 -0
  16. data/mod/machines/file/all_script_machine_output/file.js +132 -18
  17. data/mod/machines/lib/javascript/decko.js.coffee +11 -2
  18. data/mod/machines/lib/javascript/decko_filter.js.coffee +116 -9
  19. data/mod/machines/lib/stylesheets/style_cards.scss +24 -3
  20. data/mod/pointer/lib/javascript/script_pointer_config.js.coffee +16 -6
  21. data/mod/pointer/set/abstract/00_paging_params.rb +17 -4
  22. data/mod/pointer/set/abstract/02_pointer/filtered.rb +48 -0
  23. data/mod/pointer/set/self/input_options.rb +1 -0
  24. data/mod/pointer/spec/set/self/input_options_spec.rb +1 -1
  25. data/mod/pointer/template/abstract/02_pointer/filtered/filter_items.haml +34 -0
  26. data/mod/pointer/template/abstract/02_pointer/filtered/filtered_list_input.haml +30 -0
  27. data/mod/search/lib/card/filter_query.rb +81 -0
  28. data/mod/search/set/abstract/00_filter_helper.rb +51 -0
  29. data/mod/search/set/abstract/01_filter_form_helper.rb +77 -0
  30. data/mod/search/set/abstract/01_search_params.rb +3 -11
  31. data/mod/search/set/abstract/02_filter_formgroups.rb +134 -0
  32. data/mod/search/set/abstract/03_filter.rb +117 -0
  33. data/mod/search/set/abstract/04_right_filter_form.rb +23 -0
  34. data/mod/search/set/abstract/search.rb +44 -10
  35. data/mod/search/set/abstract/wql_search.rb +22 -18
  36. data/mod/search/spec/set/{all → abstract}/filter_spec.rb +6 -5
  37. data/mod/search/template/{all/filter → abstract/03_filter}/_filter_input.haml +0 -0
  38. data/mod/search/template/{all/filter → abstract/03_filter}/filter_form.haml +9 -7
  39. data/mod/search/template/abstract/search/checkbox_item.haml +7 -0
  40. data/mod/search/template/abstract/search/select_item.haml +14 -0
  41. data/mod/standard/set/all/rich_html/editing.rb +4 -4
  42. data/mod/standard/set/all/rich_html/form_elements.rb +11 -2
  43. data/mod/standard/set/all/rich_html/modal.rb +26 -19
  44. data/mod/standard/set/all/rich_html/new.rb +8 -2
  45. data/mod/standard/set/all/rich_html/wrapper.rb +22 -18
  46. data/mod/standard/set/type/cardtype.rb +2 -2
  47. data/mod/standard/spec/set/all/rich_html/editing_spec.rb +0 -1
  48. data/mod/utility/set/abstract/utility.rb +13 -0
  49. data/mod/utility/spec/set/abstract/utility_spec.rb +16 -0
  50. metadata +21 -7
  51. data/mod/search/set/all/filter.rb +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 22a6880a14a1b28876da170d7ac7c6c766d66a3c
4
- data.tar.gz: 435e1b6b1746051ebca11c4532ab93887817ef1c
3
+ metadata.gz: b0adcfab0f64530119b1670a194d67fde9845ad6
4
+ data.tar.gz: 3febe6d143c9de76acff582cbddd9ec8fded0104
5
5
  SHA512:
6
- metadata.gz: f05ee5687c4f1f67823576af89880a5b18becf2fef033815c7a5eb4024796a53807f5020cbf40e4b0175bdfabe44cbb55601f4acce566caa0e92635af6663b76
7
- data.tar.gz: 6e12874f9150fb3adede3f6f9ed12e41bff2c1bc8ee13ef51e37b876644d1f9c11d173860c6760ea51f30c85703f976afe691e985702d973761cc2d62d79c38e
6
+ metadata.gz: a9f35f827cce3f73f984671c7a09f0d6adeff29523503f6b46b64bcfdee09c71449dcae5ab2356084f81788a9122a24821dc07a02b0036c9ee79f28ee2f699ae
7
+ data.tar.gz: f843c07e3dd51ae50d2cae972cdfd307706b7e8ae1b0057cd83dd2d0256b9336de707b5b9e9e49353881aaf526331559d1dcf3f4bd05da2e1a1fb73c61d1ca8d
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.5
1
+ 0.3.6
@@ -1,5 +1,5 @@
1
1
  /*
2
- This stylesheet defines the core rules of the "classic" Wagn look.
2
+ This stylesheet defines the core rules of the "classic" Decko look.
3
3
  */
4
4
 
5
5
  body {
@@ -1,5 +1,6 @@
1
1
  /*
2
- This "traditional" styling is for backwards compatibility. It is not intended for use in Wagns created after version 1.12.
2
+ This "traditional" styling is for backwards compatibility.
3
+ It is not intended for use in decks created after Wagnversion 1.12.
3
4
 
4
5
  There are three types of rules here:
5
6
  1. rules applying to selectors no longer included in standard layouts (#menu, #logo, #credit)
@@ -17,7 +17,10 @@ class Card
17
17
  return "" if nest_invisible?
18
18
  nested_card = fetch_nested_card cardish, options
19
19
  view, options = interpret_nest_options nested_card, options
20
- nest_render nested_card, view, options, override, &block
20
+
21
+ with_nest_mode options.delete(:mode) do
22
+ nest_render nested_card, view, options, override, &block
23
+ end
21
24
  end
22
25
 
23
26
  # nested by another card's content
@@ -18,12 +18,20 @@ class Card
18
18
  # run block with new_mode as nest_mode, then return to prior mode
19
19
  # @param new_mode [Symbol] :normal, :closed, :edit, or :template
20
20
  # @return block result
21
- def with_nest_mode new_mode
21
+ def with_nest_mode new_mode, &block
22
+ if new_mode
23
+ with_altered_nest_mode new_mode, &block
24
+ else
25
+ yield
26
+ end
27
+ end
28
+
29
+ def with_altered_nest_mode new_mode
22
30
  old_mode = nest_mode
23
31
  @nest_mode = new_mode
24
- result = yield
32
+ yield
33
+ ensure
25
34
  @nest_mode = old_mode
26
- result
27
35
  end
28
36
 
29
37
  # view to be rendered in current mode
@@ -78,7 +78,7 @@ class Card
78
78
  OPERATORS =
79
79
  %w(!= = =~ < > in ~).each_with_object({}) { |v, h| h[v] = v }.merge(
80
80
  {
81
- eq: "=", gt: ">", lt: "<", match: "~", ne: "!=", "not in" => nil
81
+ eq: "=", gt: ">", lt: "<", match: "~", ne: "!=", "not in": "not in"
82
82
  }.stringify_keys
83
83
  )
84
84
 
@@ -152,7 +152,11 @@ class Card
152
152
  end
153
153
 
154
154
  def limit
155
- @mods[:limit].to_i
155
+ mods[:limit].to_i
156
+ end
157
+
158
+ def full?
159
+ !superquery && mods[:return] != "count"
156
160
  end
157
161
  end
158
162
  end
@@ -1,34 +1,43 @@
1
1
  class Card
2
2
  class Query
3
3
  module Sorting
4
- SORT_JOIN_TO_ITEM_MAP = { left: "left_id", right: "right_id" }.freeze
4
+ SORT_BY_ITEM_JOIN_MAP = { left: "left_id", right: "right_id" }.freeze
5
5
 
6
6
  def sort val
7
- return nil if @superquery
7
+ return nil unless full?
8
8
  sort_field = val[:return] || "db_content"
9
+ val = val.clone
9
10
  item = val.delete(:item) || "left"
10
-
11
11
  if sort_field == "count"
12
12
  sort_by_count val, item
13
- elsif (join_field = SORT_JOIN_TO_ITEM_MAP[item.to_sym])
14
- sq = join_cards(val, to_field: join_field,
15
- side: "LEFT",
16
- conditions_on_join: true)
17
- @mods[:sort] ||= "#{sq.table_alias}.#{sort_field}"
18
13
  else
19
- raise Card::Error::BadQuery, "sort item: #{item} not yet implemented"
14
+ sort_by_item_join val, item, sort_field
20
15
  end
21
16
  end
22
17
 
18
+ def sort_by_item_join val, item, sort_field
19
+ join_field = sort_by_item_join_field item
20
+ join = join_cards val, to_field: join_field,
21
+ side: "LEFT",
22
+ conditions_on_join: true
23
+ @mods[:sort] ||= "#{join.table_alias}.#{sort_field}"
24
+ end
25
+
26
+ def sort_by_item_join_field item
27
+ SORT_BY_ITEM_JOIN_MAP[item.to_sym] || sort_method_not_implemented(:join, item)
28
+ end
29
+
23
30
  # EXPERIMENTAL!
24
31
  def sort_by_count val, item
25
32
  method_name = "sort_by_count_#{item}"
26
- unless respond_to?(method_name)
27
- raise Card::Error::BadQuery, "count with item: #{item} not yet implemented"
28
- end
33
+ sort_by_count_not_implemented :count, item unless respond_to? method_name
29
34
  send method_name, val
30
35
  end
31
36
 
37
+ def sort_method_not_implemented method, item
38
+ raise Card::Error::BadQuery, "sorting by ##{method}/#{item} not yet implemented"
39
+ end
40
+
32
41
  def sort_by_count_referred_to val
33
42
  @mods[:sort] = "coalesce(count,0)" # needed for postgres
34
43
  cs = Query.new(
@@ -179,8 +179,7 @@ class Card
179
179
  end
180
180
 
181
181
  def full_syntax
182
- return if @query.superquery || @mods[:return] == "count"
183
- yield
182
+ @query.full? ? yield : return
184
183
  end
185
184
 
186
185
  def order
@@ -16,17 +16,18 @@ class Card
16
16
 
17
17
  @keymap = {
18
18
  carditect: [
19
- :view, # view to render
20
- :nest_name, # name as used in nest
21
- :nest_syntax, # full nest syntax
22
- :show, # render these views when optional
23
- :hide # do not render these views when optional
24
- ], # note: show/hide can be single view (Symbol), list of views (Array),
25
- # or comma separated views (String)
19
+ :view, # view to render
20
+ :nest_name, # name as used in nest
21
+ :nest_syntax, # full nest syntax
22
+ :show, # render these views when optional
23
+ :hide # do not render these views when optional
24
+ ], # show/hide can be view (Symbol), list of views (Array),
25
+ # or comma separated views (String)
26
26
  heir: [
27
27
  :main, # format object is page's "main" object (Boolean)
28
28
  :home_view, # view for slot to return to when no view specified
29
- :edit_structure # use a different structure for editing (Array)
29
+ :edit_structure, # use a different structure for editing (Array)
30
+ :wql # contextual wql alterations for search cards (Hash)
30
31
  ],
31
32
  both: [
32
33
  :help, # cue text when editing
@@ -36,10 +37,10 @@ class Card
36
37
  :editor, # inline_nests makes a form within standard content (Symbol)
37
38
  :type, # set the default type of new cards
38
39
  :size, # set an image size
39
- :params, # parameters for add button. deprecate?
40
+ :params, # parameters for add button. deprecate!
40
41
  :items, # options for items (Hash)
41
42
  :cache # change view cache behaviour
42
- ], # (Symbol<:always, :standard, :never>)
43
+ ], # (Symbol<:always, :standard, :never>)
43
44
  none: [
44
45
  :skip_perms, # do not check permissions for this view (Boolean)
45
46
  :main_view # this is main view of page (Boolean)
@@ -136,9 +137,14 @@ class Card
136
137
 
137
138
  # options to be used in data attributes of card slots (normalized options
138
139
  # with standard keys)
140
+ # FIXME: what we really want is options as they were when render was called.
141
+ # normalized is wrong because it can get changed before render. live is wrong
142
+ # because they can get changed after. current solution is a compromise.
139
143
  # @return [Hash]
140
144
  def slot_options
141
- normalized_options.select { |k, _v| Options.all_keys.include? k }
145
+ normalized_options.merge(view: requested_view).select do |k, _v|
146
+ Options.all_keys.include? k
147
+ end
142
148
  end
143
149
 
144
150
  def closest_live_option key
@@ -175,7 +181,6 @@ class Card
175
181
  opts
176
182
  end
177
183
 
178
-
179
184
  # typically options are already a hash. this also handles an array of
180
185
  # hashes and nil.
181
186
  def options_to_hash opts
@@ -1,3 +1,4 @@
1
+ mod 'utility'
1
2
  mod 'admin'
2
3
  mod 'core'
3
4
  mod 'history'
@@ -0,0 +1,3 @@
1
+ <div class="modal-body ">
2
+ {{_main}}
3
+ </div>
@@ -1,38 +1,45 @@
1
-
2
1
  module ClassMethods
3
-
4
2
  # a fetch method to support the needs of the card controller.
5
3
  # should be in Decko?
6
4
  def controller_fetch args
7
- opts = controller_fetch_opts args
5
+ card_opts = controller_fetch_opts args
8
6
  if args[:action] == "create"
9
7
  # FIXME: we currently need a "new" card to catch duplicates
10
8
  # (otherwise save will just act like a normal update)
11
9
  # We may need a "#create" instance method to handle this checking?
12
- Card.new opts
10
+ Card.new card_opts
13
11
  else
14
- mark = args[:id] || opts[:name]
15
- Card.fetch mark, look_in_trash: args[:look_in_trash], new: opts
12
+ standard_controller_fetch args, card_opts
16
13
  end
17
14
  end
18
15
 
19
16
  private
20
17
 
18
+ def standard_controller_fetch args, card_opts
19
+ mark = args[:id] || card_opts[:name]
20
+ card = Card.fetch mark, look_in_trash: args[:look_in_trash], new: card_opts
21
+ card.assign_attributes card_opts if args[:assign] && card&.real?
22
+ card
23
+ end
24
+
21
25
  def controller_fetch_opts args
22
- opts =
23
- # clone doesn't work for Parameters
24
- if args[:card].respond_to?(:to_unsafe_h)
25
- args[:card].to_unsafe_h
26
- else
27
- (args[:card] || {}).clone
28
- end
29
- # clone so that original params remain unaltered. need deeper clone?
26
+ opts = safe_card_opts args[:card]
30
27
  opts[:type] ||= args[:type] if args[:type]
31
28
  # for /new/:type shortcut. we should handle in routing and deprecate this
32
29
  opts[:name] ||= Card::Name.url_key_to_standard(args[:id])
33
30
  opts
34
31
  end
35
32
 
33
+ def safe_card_opts card_opts
34
+ if card_opts.respond_to? :to_unsafe_h
35
+ # clone doesn't work for Parameters
36
+ card_opts.to_unsafe_h
37
+ else
38
+ # clone so that original params remain unaltered. need deeper clone?
39
+ (card_opts || {}).clone
40
+ end
41
+ end
42
+
36
43
  def validate_fetch_opts! opts
37
44
  return unless opts[:new] && opts[:skip_virtual]
38
45
  raise Card::Error, "fetch called with new args and skip_virtual"
@@ -46,23 +53,30 @@ module ClassMethods
46
53
  opts[:skip_virtual] || opts[:new].present? || opts[:skip_type_lookup]
47
54
  end
48
55
 
56
+ # look in cache. if that doesn't work, look in database
57
+ # @return [{Card}, {True/False}] Card object and "needs_caching" ruling
49
58
  def retrieve_existing mark, opts
50
59
  return [nil, false] unless mark.present?
51
60
  mark_type, mark_key = retrievable_mark_type_and_value mark
52
- needs_caching = false # until proven true :)
53
-
54
- # look in cache
55
- card = send "retrieve_from_cache_by_#{mark_type}", mark_key, opts[:local_only]
56
-
57
- if retrieve_from_db? card, mark_type, mark_key, opts[:look_in_trash]
58
- # look in db if needed
61
+ if (card = retrieve_from_cache_by_mark mark_type, mark_key, opts)
62
+ # we have an acceptable card in the cache
63
+ # (and don't need to cache it again!)
64
+ [card, false]
65
+ else
66
+ # try to find the card in the database
59
67
  card = retrieve_from_db mark_type, mark_key, opts[:look_in_trash]
60
- needs_caching = !card.nil? && !card.trash
68
+ [card, !(card.nil? || card.trash)]
61
69
  end
70
+ end
62
71
 
63
- [card, needs_caching]
72
+ def retrieve_from_cache_by_mark mark_type, mark_key, opts
73
+ card = send "retrieve_from_cache_by_#{mark_type}", mark_key, opts[:local_only]
74
+ return_cached_card?(card, opts[:look_in_trash]) ? card : nil
64
75
  end
65
76
 
77
+ # In both the cache and the db, ids and keys are used to retrieve card data.
78
+ # This method identifies the kind of mark to use and its value
79
+ # @return [Array] first item is :id or :key, second is corresponding value
66
80
  def retrievable_mark_type_and_value mark
67
81
  # return mark_type and mark_value
68
82
  if mark.is_a? Integer
@@ -72,17 +86,16 @@ module ClassMethods
72
86
  end
73
87
  end
74
88
 
75
- def retrieve_from_db? card, mark_type, mark_key, look_in_trash
76
- return false if card&.real? # real card found in cache
77
- # return false if mark_type == :key && mark_key.to_name.relative? # no relative names in db
78
- card.nil? || (look_in_trash && !card.trash) # card not found in cache (or trash lookup)
89
+ def return_cached_card? card, look_in_trash
90
+ return false unless card
91
+ card.real? || !look_in_trash
79
92
  end
80
93
 
94
+ # @return [Card, nil] Card object
81
95
  def retrieve_from_db mark_type, mark_key, look_in_trash=false
82
96
  query = { mark_type => mark_key }
83
97
  query[:trash] = false unless look_in_trash
84
- card = Card.where(query).take
85
- card
98
+ Card.where(query).take
86
99
  end
87
100
 
88
101
  def standard_fetch_results card, mark, opts
@@ -120,7 +133,6 @@ module ClassMethods
120
133
  return mark unless mark.name? && supercard
121
134
  mark.to_name.absolute_name supercard.name
122
135
  end
123
-
124
136
  end
125
137
 
126
138
  public
@@ -107,16 +107,12 @@ RSpec.describe Card::Format::HtmlFormat do
107
107
  it "does not recurse" do
108
108
  @layout_card.content = "Mainly {{_main|core}}"
109
109
  Card::Auth.as_bot { @layout_card.save }
110
-
111
- expect(@layout_card.format.render!(:layout)).to eq(
112
- "Mainly <div id=\"main\"><div class=\"CodeRay\">\n " \
113
- "<div class=\"code\"><pre>Mainly {{_main|core}}</pre></div>\n" \
114
- "</div>\n</div>\n" \
115
- '<div class="modal fade" role="dialog" id="modal-main-slot">' \
116
- '<div class="modal-dialog"><div class="modal-content">' \
117
- "</div></div></div>"
118
- )
119
- # probably better to check that it matches "Mainly" exactly twice.
110
+ rendered = @layout_card.format.render! :layout
111
+ expect(rendered).to have_tag "div#main" do
112
+ have_tag "div.code" do
113
+ have_tag("pre") { with_text "Mainly {{_main|core}}" }
114
+ end
115
+ end
120
116
  end
121
117
 
122
118
  it "handles nested _main references" do
@@ -125,13 +121,10 @@ RSpec.describe Card::Format::HtmlFormat do
125
121
  @layout_card.save!
126
122
  Card.create name: "outer space", content: "{{_main|name}}"
127
123
  end
128
-
129
- expect(@main_card.format.render!(:layout)).to eq(
130
- '<div id="main">Joe User</div>' + "\n" \
131
- '<div class="modal fade" role="dialog" id="modal-main-slot">' \
132
- '<div class="modal-dialog"><div class="modal-content">' \
133
- "</div></div></div>"
134
- )
124
+ rendered = @main_card.format.render! :layout
125
+ expect(rendered).to have_tag "div#main" do
126
+ with_text "Joe User"
127
+ end
135
128
  end
136
129
  end
137
130
  end
@@ -0,0 +1,48 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ RSpec.describe Card::Set::All::FetchHelper do
4
+ let(:retrieve) { test_retrieve_existing }
5
+ let(:retrieve_from_trash) { test_retrieve_existing look_in_trash: true }
6
+
7
+ def test_retrieve_existing opts={}
8
+ Card.send :retrieve_existing, "A".to_name, opts
9
+ end
10
+
11
+ describe "retrieve_existing" do
12
+ it "looks for non-cached card in database" do
13
+ expect_db_retrieval_with(:key, "a", nil) { retrieve }
14
+ end
15
+
16
+ it "doesn't look in db for cached cards(real)" do
17
+ Card.cache.write "a", Card["B"]
18
+ expect_no_db_retrieval { retrieve }
19
+ end
20
+
21
+ it "doesn't look in db for cached cards (new)" do
22
+ Card.cache.write "a", Card.new
23
+ expect_no_db_retrieval { retrieve }
24
+ end
25
+
26
+ it "doesn't look in db for cached cards (real) if 'look_in_trash' option used" do
27
+ Card.cache.write "a", Card["B"]
28
+ expect_no_db_retrieval { retrieve_from_trash }
29
+ end
30
+
31
+ it "looks in db for cached cards (new) if 'look_in_trash' option used" do
32
+ Card.cache.write "a", Card.new
33
+ expect_db_retrieval_with(:key, "a", true) { retrieve_from_trash }
34
+ end
35
+
36
+ def expect_no_db_retrieval
37
+ allow(Card).to receive(:retrieve_from_db)
38
+ yield
39
+ expect(Card).not_to have_received(:retrieve_from_db)
40
+ end
41
+
42
+ def expect_db_retrieval_with *args
43
+ allow(Card).to receive(:retrieve_from_db)
44
+ yield
45
+ expect(Card).to have_received(:retrieve_from_db).with(*args)
46
+ end
47
+ end
48
+ end