card 1.95.3 → 1.96.0

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/lib/card.rb +10 -2
  4. data/lib/card/migration/import.rb +1 -1
  5. data/lib/card/set.rb +1 -1
  6. data/lib/card/set/event.rb +63 -65
  7. data/lib/card/set/event/callbacks.rb +21 -0
  8. data/lib/card/set/event/delayed_event.rb +11 -16
  9. data/lib/card/set/event/options.rb +78 -0
  10. data/lib/card/set/format.rb +5 -93
  11. data/lib/card/set/format/abstract_format.rb +104 -0
  12. data/mod/Modfile +1 -0
  13. data/mod/basic_formats/set/all/all_csv.rb +1 -1
  14. data/mod/basic_formats/set/all/json.rb +61 -4
  15. data/mod/basic_formats/spec/set/all/json_spec.rb +51 -1
  16. data/mod/basic_formats/spec/shared_context/json_shared_context.rb +40 -0
  17. data/mod/bootstrap/lib/stylesheets/style_bootstrap_cards.scss +17 -1
  18. data/mod/bootstrap/set/abstract/bootswatch_theme.rb +2 -12
  19. data/mod/bootstrap/set/abstract/bootswatch_theme/html_views.rb +31 -0
  20. data/mod/bootstrap/set/type/customized_bootswatch_skin.rb +12 -0
  21. data/mod/bootstrap/set/type/customized_bootswatch_skin/core.haml +5 -0
  22. data/mod/bootstrap/set/type/customized_bootswatch_skin/html_views.rb +36 -0
  23. data/mod/bootstrap/set/type_plus_right/customized_bootswatch_skin/colors.rb +14 -10
  24. data/mod/bootstrap/set/type_plus_right/customized_bootswatch_skin/colors/_colorpicker.haml +1 -1
  25. data/mod/bootstrap/set/type_plus_right/customized_bootswatch_skin/colors/editor.haml +13 -9
  26. data/mod/core/chunk/link.rb +8 -0
  27. data/mod/core/set/abstract/code_file.rb +5 -0
  28. data/mod/core/set/all/chunk.rb +46 -24
  29. data/mod/core/set/all/event_conditions.rb +32 -11
  30. data/mod/core/set/all/export.rb +3 -5
  31. data/mod/core/set/all/item.rb +16 -0
  32. data/mod/core/set/all/name.rb +1 -0
  33. data/mod/core/set/all/references.rb +25 -16
  34. data/mod/core/set/all/rename.rb +20 -21
  35. data/mod/core/set/all/trash.rb +13 -4
  36. data/mod/core/spec/set/all/actify_spec.rb +4 -4
  37. data/mod/core/spec/set/all/event_conditions_spec.rb +68 -10
  38. data/mod/core/spec/set/all/export_spec.rb +7 -4
  39. data/mod/core/spec/set/all/references_spec.rb +38 -1
  40. data/mod/core/spec/set/all/rename_spec.rb +15 -9
  41. data/mod/follow/spec/set/right/followers_spec.rb +1 -1
  42. data/mod/follow/spec/set/right/following_spec.rb +4 -8
  43. data/mod/follow/spec/set/type/notification_template_spec.rb +1 -1
  44. data/mod/history/set/all/act_view.rb +2 -2
  45. data/mod/item/set/all/bar.haml +12 -0
  46. data/mod/item/set/all/bar.rb +77 -0
  47. data/mod/item/set/all/box.haml +10 -0
  48. data/mod/item/set/all/box.rb +8 -0
  49. data/mod/item/set/all/expanded_bar.haml +10 -0
  50. data/mod/machines/file/all_script_machine_output/file.js +30622 -66
  51. data/mod/machines/file/all_style_machine_output/file.css +3 -3
  52. data/mod/machines/file/script_html5shiv_printshiv_machine_output/file.js +1 -1
  53. data/mod/machines/lib/javascript/decko_slot.js.coffee +18 -13
  54. data/mod/machines/set/abstract/skin_box.rb +34 -0
  55. data/mod/machines/set/abstract/skin_box/box_bottom.haml +4 -0
  56. data/mod/machines/set/type/skin.rb +1 -1
  57. data/mod/pointer/set/abstract/01_paging.rb +49 -4
  58. data/mod/pointer/set/abstract/01_paging/paging_links.rb +6 -6
  59. data/mod/pointer/set/abstract/02_pointer/html_views.rb +10 -0
  60. data/mod/pointer/set/abstract/02_pointer/other_views.rb +9 -5
  61. data/mod/pointer/spec/set/abstract/pointer/html_views_spec.rb +4 -10
  62. data/mod/pointer/spec/set/abstract/pointer/other_views_spec.rb +20 -1
  63. data/mod/search/set/abstract/01_filter_form_helper.rb +4 -4
  64. data/mod/search/set/abstract/02_search_params.rb +1 -1
  65. data/mod/search/set/abstract/03_filter.rb +8 -0
  66. data/mod/search/set/abstract/search.rb +10 -0
  67. data/mod/settings/set/right/style.rb +13 -0
  68. data/mod/settings/set/right/style/editor.haml +4 -4
  69. data/mod/standard/set/all/path.rb +6 -0
  70. data/mod/standard/set/type/list.rb +3 -2
  71. data/mod/standard/set/type/listed_by.rb +5 -1
  72. data/mod/standard/spec/content/chunk/include_spec.rb +2 -2
  73. data/mod/standard/spec/set/all/rich_html/editing_spec.rb +4 -69
  74. data/mod/standard/spec/set/type/listed_by_spec.rb +2 -2
  75. data/mod/standard/spec/set/type/search_type_spec.rb +56 -0
  76. data/mod/standard/spec/set/type/set/html_views_spec.rb +5 -9
  77. data/mod/utility/set/abstract/bs_badge.rb +21 -0
  78. data/mod/utility/set/abstract/bs_badge/bs_badge.haml +5 -0
  79. data/mod/utility/set/abstract/bs_badge/labeled_badge.haml +5 -0
  80. data/mod/utility/set/abstract/bs_badge/tab_badge.haml +5 -0
  81. data/mod/utility/set/abstract/media.rb +27 -0
  82. data/mod/utility/set/abstract/media/media_snippet.haml +9 -0
  83. metadata +28 -10
  84. data/mod/machines/set/abstract/skin_thumbnail.rb +0 -28
  85. data/mod/machines/set/abstract/skin_thumbnail/thumbnail.haml +0 -10
@@ -0,0 +1,104 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ class Card
4
+ module Set
5
+ module Format
6
+ # All Format modules are extended with this module in order to support
7
+ # the basic format API, including view, layout, and basket definitions
8
+ module AbstractFormat
9
+ include Set::Basket
10
+ include Set::Format::HamlViews
11
+
12
+ mattr_accessor :views
13
+ self.views = Hash.new { |h, k| h[k] = {} }
14
+
15
+ def before view, &block
16
+ define_method "_before_#{view}", &block
17
+ end
18
+
19
+ def view view, *args, &block
20
+ # view = view.to_viewname.key.to_sym
21
+ interpret_view_opts view, args[0] if block_given?
22
+ view_method_block = view_block(view, args, &block)
23
+ if async_view? args
24
+ # This case makes only sense for HtmlFormat
25
+ # but I don't see an easy way to override class methods for a specific
26
+ # format. All formats are extended with this general module. So
27
+ # a HtmlFormat.view method would be overridden by AbstractFormat.view
28
+ # We need something like AbstractHtmlFormat for that.
29
+ define_async_view_method view, &view_method_block
30
+ else
31
+ define_standard_view_method view, &view_method_block
32
+ end
33
+ end
34
+
35
+ def view_for_override viewname
36
+ view viewname do
37
+ "override '#{viewname}' view"
38
+ end
39
+ end
40
+
41
+ def define_standard_view_method view, &block
42
+ views[self][view] = block
43
+ define_method "_view_#{view}", &block
44
+ end
45
+
46
+ def define_async_view_method view, &block
47
+ view_content = "#{view}_async_content"
48
+ define_standard_view_method view_content, &block
49
+ define_standard_view_method view do
50
+ %(<card-view-placeholder data-url="#{path view: view_content}" />)
51
+ end
52
+ end
53
+
54
+ def interpret_view_opts view, opts
55
+ return unless opts.present?
56
+ Card::Format.interpret_view_opts view, opts
57
+ extract_view_cache_rules view, opts.delete(:cache)
58
+ end
59
+
60
+ def extract_view_cache_rules view, cache_rule
61
+ return unless cache_rule
62
+ methodname = Card::Format.view_cache_setting_method view
63
+ define_method(methodname) { cache_rule }
64
+ end
65
+
66
+ def view_block view, args, &block
67
+ return haml_view_block(view, wrap_with_slot?(args), &block) if haml_view?(args)
68
+ block_given? ? block : lookup_alias_block(view, args)
69
+ end
70
+
71
+ def haml_view? args
72
+ args.first.is_a?(Hash) && args.first[:template] == :haml
73
+ end
74
+
75
+ def wrap_with_slot? args
76
+ args.first.is_a?(Hash) && args.first[:slot]
77
+ end
78
+
79
+ def async_view? args
80
+ args.first.is_a?(Hash) && args.first[:async]
81
+ end
82
+
83
+ def lookup_alias_block view, args
84
+ opts = args[0].is_a?(Hash) ? args.shift : { view: args.shift }
85
+ opts[:mod] ||= self
86
+ opts[:view] ||= view
87
+ views[opts[:mod]][opts[:view]] || begin
88
+ raise "cannot find #{opts[:view]} view in #{opts[:mod]}; " \
89
+ "failed to alias #{view} in #{self}"
90
+ end
91
+ end
92
+
93
+ def source_location
94
+ set_module.source_location
95
+ end
96
+
97
+ # remove the format part of the module name
98
+ def set_module
99
+ Card.const_get name.split("::")[0..-2].join("::")
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
@@ -4,6 +4,7 @@ mod 'core'
4
4
  mod 'virtual'
5
5
  mod 'history'
6
6
  mod 'basic_formats'
7
+ mod 'item'
7
8
  mod 'pointer'
8
9
  mod 'ace_editor'
9
10
  mod 'prosemirror_editor'
@@ -79,7 +79,7 @@ format :csv do
79
79
  def column_titles extra_titles=nil
80
80
  res = Array extra_titles
81
81
  card1 = Card.fetch card.item_names(limit: 1).first
82
- card1.each_nested_chunk do |chunk|
82
+ card1.nest_chunks.each do |chunk|
83
83
  res << column_title(chunk.options)
84
84
  end
85
85
  res.compact
@@ -1,4 +1,9 @@
1
1
  format :json do
2
+ # because card.item_cards returns "[[#{self}]]"
3
+ def item_cards
4
+ uniq_nested_cards
5
+ end
6
+
2
7
  AUTOCOMPLETE_LIMIT = 8 # number of name suggestions for autocomplete text fields
3
8
 
4
9
  def default_nest_view
@@ -13,8 +18,11 @@ format :json do
13
18
  params[:max_depth].present? ? params[:max_depth].to_i : 1
14
19
  end
15
20
 
21
+ # TODO: support layouts in json
22
+ # eg layout=stamp gives you the metadata currently in "page" view
23
+ # and layout=none gives you ONLY the requested view (default atom)
16
24
  def show view, args
17
- view ||= :content
25
+ view ||= :molecule
18
26
  raw = render! view, args
19
27
  return raw if raw.is_a? String
20
28
  method = params[:compress] ? :generate : :pretty_generate
@@ -54,20 +62,69 @@ format :json do
54
62
  hash
55
63
  end
56
64
 
57
- view :content, cache: :never do
65
+ view :page, cache: :never do
58
66
  { url: request_url,
59
67
  timestamp: Time.now.to_s,
60
68
  card: _render_atom }
61
69
  end
62
70
 
71
+ view :content do
72
+ render_page
73
+ end
74
+
75
+ view :core do
76
+ { card.name => card.content }
77
+ end
78
+
79
+ view :nucleus, cache: :never do
80
+ {
81
+ id: card.id,
82
+ name: card.name,
83
+ url: path(format: :json),
84
+ html_url: path
85
+ }
86
+ end
87
+
63
88
  view :atom, cache: :never do
64
- h = { name: card.name, type: card.type_name }
89
+ h = _render_nucleus
90
+ h[:type] = card.type_name
91
+ h[:type_url] = path mark: card.type_name, format: :json
92
+ h[:atom_url] = path format: :json, view: :atom
93
+ h[:nucleus_url] = path format: :json, view: :nucleus
65
94
  h[:content] = card.db_content unless card.structure
66
95
  h[:codename] = card.codename if card.codename
67
- h[:value] = _render_core if depth < max_depth
68
96
  h
69
97
  end
70
98
 
99
+ view :items, cache: :never do
100
+ item_cards.map do |i_card|
101
+ nest i_card
102
+ end
103
+ end
104
+
105
+ view :links, cache: :never do
106
+ card.link_chunks.map do |chunk|
107
+ if chunk.referee_name
108
+ path mark: chunk.referee_name, format: :json
109
+ else
110
+ link_to_resource chunk.link_target
111
+ end
112
+ end
113
+ end
114
+
115
+ view :ancestors, cache: :never do
116
+ card.name.ancestors.map do |name|
117
+ nest name
118
+ end
119
+ end
120
+
121
+ view :molecule, cache: :never do
122
+ _render_atom.merge items: _render_items,
123
+ links: _render_links,
124
+ ancestors: _render_ancestors
125
+
126
+ end
127
+
71
128
  # minimum needed to re-fetch card
72
129
  view :cast, cache: :never do
73
130
  card.cast
@@ -1,6 +1,56 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
- describe Card::Set::All::Json, "JSON mod" do
3
+ RSpec.describe Card::Set::All::Json do
4
+ include_context "json context"
5
+ specify "nucleus view" do
6
+ expect_view(:nucleus, format: :json)
7
+ .to eq nucleus_values
8
+ end
9
+
10
+ specify "atom view" do
11
+ expect_view(:atom, format: :json)
12
+ .to eq atom_values
13
+ end
14
+
15
+ describe "molecule view" do
16
+ context "with internal link" do
17
+ it "has link url" do
18
+ expect_view(:molecule, format: :json)
19
+ .to eq atom_values.merge items: [],
20
+ links: [json_url("Z")],
21
+ ancestors: []
22
+ end
23
+ end
24
+
25
+ context "with external link" do
26
+ def card_subject
27
+ @card ||= create "external link",
28
+ content: "[[http://xkcd.com|link text]]" \
29
+ "[[/Z]]"
30
+ end
31
+
32
+ it "has link urls" do
33
+ expect_view(:molecule, format: :json)
34
+ .to eq atom_values.merge items: [],
35
+ links: ["http://xkcd.com", url("Z")],
36
+ ancestors: []
37
+ end
38
+ end
39
+
40
+ context "with nests" do
41
+ def card_subject
42
+ Card["B"]
43
+ end
44
+
45
+ it "has nests" do
46
+ expect_view(:molecule, format: :json)
47
+ .to eq atom_values.merge items: [atom_values(Card["Z"])],
48
+ links: [],
49
+ ancestors: []
50
+ end
51
+ end
52
+ end
53
+
4
54
  context "status view" do
5
55
  it "handles real and virtual cards" do
6
56
  jf = Card::Format::JsonFormat
@@ -0,0 +1,40 @@
1
+ RSpec.shared_context "json context", shared_context: :json do
2
+ before do
3
+ Card::Env[:host] = "json.com"
4
+ Card::Env[:protocol] = "http://"
5
+ end
6
+
7
+ let(:root) { "http://json.com" }
8
+
9
+ def json_url target, query=nil
10
+ url "#{target}.json", query
11
+ end
12
+
13
+ def url target, query=nil
14
+ ["#{root}/#{target}", query].compact.join "?"
15
+ end
16
+
17
+ def nucleus_values card=card_subject
18
+ {
19
+ id: card.id,
20
+ name: card.name,
21
+ url: json_url(card.name.url_key),
22
+ html_url: "#{root}/#{card.name.url_key}"
23
+ }
24
+ end
25
+
26
+ def atom_values card=card_subject, structured: false
27
+ values = nucleus_values(card).merge(
28
+ type: card.type_name,
29
+ type_url: json_url(card.type_name),
30
+ atom_url: json_url(card.name.url_key, "view=atom"),
31
+ nucleus_url: json_url(card.name.url_key, "view=nucleus")
32
+ )
33
+ values[:content] = card.content unless structured
34
+ values
35
+ end
36
+
37
+ def structured_atom_values card=card_subject
38
+ atom_values card, structured: true
39
+ end
40
+ end
@@ -11,6 +11,7 @@
11
11
  $label_color: $gray-600;
12
12
  $header_color: $gray-200;
13
13
  $credit_color: $primary;
14
+ $bar_stripe_color: $gray-700;
14
15
 
15
16
  header {
16
17
  a {
@@ -57,7 +58,6 @@ form {
57
58
  padding: 0px;
58
59
  }
59
60
 
60
-
61
61
  .link-muted {
62
62
  color: $text-muted;
63
63
  &:hover {
@@ -65,6 +65,13 @@ form {
65
65
  }
66
66
  }
67
67
 
68
+ .grow-1 {
69
+ flex-grow: 1;
70
+ }
71
+ .grow-2 {
72
+ flex-grow: 2;
73
+ }
74
+
68
75
  /*-------- Special Pages --------*/
69
76
 
70
77
  /*-- sign in page --*/
@@ -336,3 +343,12 @@ body.mceContentBody {
336
343
  display: none !important;
337
344
  }
338
345
  }
346
+
347
+ .bar-top.left-stripe, .bar.left-stripe {
348
+ border-left: 4px solid $bar_stripe_color !important;
349
+ }
350
+
351
+ .bar-bottom .bar.left-stripe {
352
+ border-left: 3px solid $bar_stripe_color !important;
353
+ }
354
+
@@ -10,7 +10,7 @@
10
10
  #
11
11
  # The content of a bootswatch theme card consists of four parts:
12
12
  # * pre_variables: hard-coded theme independent stuff
13
- # and bootstrap functions to make the available in the variables part
13
+ # and bootstrap functions to make them available in the variables part
14
14
  # * variables: the content from `_variables.scss`,
15
15
  # * post_variables: the bootstrap css and libraries like select2 and
16
16
  # bootstrap-colorpicker that depend on the theme
@@ -39,7 +39,7 @@
39
39
  include_set Abstract::Machine
40
40
  include_set Type::Scss
41
41
  include_set Abstract::CodeFile
42
- include_set Abstract::SkinThumbnail
42
+ include_set Abstract::SkinBox
43
43
 
44
44
  CONTENT_PARTS = %i[pre_variables variables post_variables stylesheets].freeze
45
45
 
@@ -155,13 +155,3 @@ def source_dir
155
155
  @source_dir ||=
156
156
  ::File.expand_path "../../../vendor/bootswatch/dist/#{theme_name}", __FILE__
157
157
  end
158
-
159
- format :html do
160
- view :thumbnail, template: :haml do
161
- voo.show! :customize_button, :thumbnail_image
162
- end
163
-
164
- view :closed_content do
165
- ""
166
- end
167
- end
@@ -0,0 +1,31 @@
1
+ include_set Abstract::Media
2
+ include_set Abstract::BsBadge
3
+
4
+ format :html do
5
+ before :box do
6
+ super()
7
+ voo.show! :customize_button, :box_middle
8
+ end
9
+
10
+ view :closed_content do
11
+ ""
12
+ end
13
+
14
+ view :bar_left do
15
+ class_up "card-title", "my-0 ml-2"
16
+ class_up "media-left", "m-0", true
17
+ text_with_image size: :small, title: "", text: _render_title,
18
+ media_opts: { class: "align-items-center" }
19
+ # field_nest(:image, view: :core) + wrap_with(:h4, render(:title))
20
+ end
21
+
22
+ view :bar_right do
23
+ customize_button text: "Customize"
24
+ end
25
+
26
+ view :bar_bottom do
27
+ wrap_with :code do
28
+ render_core
29
+ end
30
+ end
31
+ end
@@ -12,6 +12,18 @@ card_accessor :colors
12
12
  card_accessor :variables
13
13
  card_accessor :stylesheets
14
14
 
15
+ def top_level_item_cards
16
+ cards = PRE_VARIABLES_CARD_NAMES.map { |n| Card[n] }
17
+ cards += [colors_card, variables_card]
18
+ cards += POST_VARIABLES_CARD_NAMES.map { |n| Card[n] }
19
+ cards << stylesheets_card
20
+ cards
21
+ end
22
+
23
+ def editable_item_cards
24
+ [colors_card, variables_card, stylesheets_card]
25
+ end
26
+
15
27
  def variables_card_names
16
28
  %i[colors variables].map { |s| Card.fetch_name name, s }
17
29
  end
@@ -0,0 +1,5 @@
1
+ %h5
2
+ Skin configuration from simplest to most advanced
3
+ = field_nest :colors, view: :bar, title: "Palette and uses of colors"
4
+ = field_nest :variables, view: :bar, title: "Additional SCSS variables", show: :edit_button
5
+ = field_nest :stylesheets, view: :bar, title: "SCSS and CSS stylesheets", show: :edit_button