card 1.99.5 → 1.99.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/db/migrate_core_cards/20140629222005_add_email_cards.rb +1 -1
- data/lib/card.rb +13 -23
- data/lib/card/act_manager.rb +1 -0
- data/lib/card/act_manager/event_delay.rb +10 -5
- data/lib/card/act_manager/subdirector_array.rb +2 -0
- data/lib/card/auth/current.rb +0 -2
- data/lib/card/cache/prepopulate.rb +4 -4
- data/lib/card/env.rb +9 -53
- data/lib/card/env/location.rb +15 -2
- data/lib/card/env/request_assignments.rb +24 -0
- data/lib/card/env/serialization.rb +24 -0
- data/lib/card/env/slot_options.rb +30 -0
- data/lib/card/format/error.rb +6 -1
- data/lib/card/mod/loader/set_pattern_loader.rb +5 -1
- data/lib/card/model/save_helper.rb +5 -1
- data/lib/card/set/event/delayed_event.rb +49 -9
- data/lib/card/set/event/options.rb +1 -0
- data/lib/card/set/pattern/base.rb +18 -0
- data/lib/card/subcards.rb +11 -8
- data/lib/card/subcards/add.rb +7 -4
- data/lib/card/view/cache/cache_action.rb +1 -1
- data/lib/card/view/classy.rb +9 -9
- data/lib/card/view/options/voo_api.rb +0 -8
- data/mod/account/set/all/account.rb +2 -2
- data/mod/account/spec/set/right/account_spec.rb +2 -2
- data/mod/account/spec/set/type/signup_spec.rb +1 -1
- data/mod/basic_formats/set/all/head.rb +4 -2
- data/mod/basic_formats/set/all/rss.rb +1 -1
- data/mod/bootstrap/lib/card/lazy_tab.rb +37 -0
- data/mod/bootstrap/lib/card/tab.rb +76 -0
- data/mod/bootstrap/set/all/bootstrap/dropdown.rb +0 -1
- data/mod/bootstrap/set/all/bootstrap/tabs.rb +33 -124
- data/mod/bootstrap/set/all/bootstrap/tabs/tab_panel.haml +7 -0
- data/mod/carrierwave/set/abstract/attachment.rb +1 -1
- data/mod/carrierwave/set/abstract/attachment/upload_cache.rb +1 -1
- data/mod/core/lib/card/rule.rb +227 -0
- data/mod/core/set/all/actify.rb +16 -2
- data/mod/core/set/all/assign_attributes.rb +2 -2
- data/mod/core/set/all/cache.rb +4 -0
- data/mod/core/set/all/event_conditions.rb +58 -39
- data/mod/core/set/all/fetch.rb +1 -1
- data/mod/core/set/all/fetch_helper.rb +5 -13
- data/mod/core/set/all/initialize.rb +6 -6
- data/mod/core/set/all/name_events.rb +2 -3
- data/mod/core/set/all/rename.rb +9 -5
- data/mod/core/set/all/rules.rb +3 -228
- data/mod/core/set/all/tabs.rb +4 -3
- data/mod/core/set/all/update_read_rules.rb +1 -1
- data/mod/core/set_pattern/08_type_plus_right.rb +1 -2
- data/mod/core/spec/set/all/event_conditions_spec.rb +3 -3
- data/mod/core/spec/set/all/fetch_helper_spec.rb +6 -0
- data/mod/core/spec/set/all/references_spec.rb +9 -0
- data/mod/core/spec/set/all/rules_spec.rb +1 -1
- data/mod/developer/set/right/debug.rb +13 -14
- data/mod/edit/set/all/bridge.rb +7 -7
- data/mod/edit/set/all/bridge/tab_visibility.rb +2 -2
- data/mod/follow/set/all/follow/followed_by.rb +1 -2
- data/mod/follow/set/all/follow/follower_ids.rb +15 -3
- data/mod/follow/set/all/notify.rb +1 -5
- data/mod/follow/set/type_plus_right/user/follow.rb +4 -7
- data/mod/google_analytics/set/all/google_analytics.rb +1 -1
- data/mod/history/lib/card/act.rb +1 -1
- data/mod/history/set/all/history.rb +23 -17
- data/mod/history/set/all/history/acts.rb +0 -4
- data/mod/machines/file/all_script_machine_output/file.js +69 -38418
- data/mod/machines/file/all_style_machine_output/file.css +1 -1
- data/mod/machines/file/script_html5shiv_printshiv_machine_output/file.js +1 -1
- data/mod/machines/lib/javascript/decko/filter_items.js.coffee +4 -4
- data/mod/machines/lib/javascript/decko/nest_editor_name.js.coffee +1 -1
- data/mod/machines/lib/javascript/decko/selectable_filtered_content.js.coffee +12 -0
- data/mod/machines/lib/javascript/decko/slotter.js.coffee +1 -1
- data/mod/machines/lib/stylesheets/style_cards.scss +1 -1
- data/mod/machines/set/abstract/machine/output_update.rb +12 -4
- data/mod/machines/set/self/script_decko.rb +1 -1
- data/mod/pointer/set/abstract/00_paging_params.rb +1 -3
- data/mod/pointer/set/abstract/02_pointer/events.rb +1 -0
- data/mod/recaptcha/set/all/recaptcha.rb +1 -1
- data/mod/recaptcha/set/self/admin_info.rb +2 -3
- data/mod/rules/set/type/set.rb +1 -1
- data/mod/search/set/abstract/00_filter_helper.rb +2 -4
- data/mod/search/set/abstract/02_search_params.rb +1 -1
- data/mod/search/set/abstract/03_filter.rb +2 -0
- data/mod/search/set/abstract/03_filter/selectable_filtered_content.haml +2 -0
- data/mod/search/template/abstract/search/checkbox_item.haml +2 -3
- data/mod/settings/set/right/read.rb +1 -1
- data/mod/standard/set/all/rich_html/error.rb +1 -1
- data/mod/standard/set/all/rich_html/menu.rb +1 -1
- data/mod/standard/set/all/rich_html/show.rb +8 -0
- data/mod/tinymce_editor/set/all/reference_editor/nest_editor.rb +6 -8
- metadata +13 -5
- data/lib/card/tasks/card/seed.rake +0 -0
@@ -134,6 +134,24 @@ class Card
|
|
134
134
|
end
|
135
135
|
end
|
136
136
|
end
|
137
|
+
|
138
|
+
module Helper
|
139
|
+
private
|
140
|
+
|
141
|
+
def left_type card
|
142
|
+
card.superleft&.type_name || quick_type(card.name.left_name)
|
143
|
+
end
|
144
|
+
|
145
|
+
def quick_type name
|
146
|
+
if name.present?
|
147
|
+
card = Card.fetch name, skip_modules: true, new: {}
|
148
|
+
card.include_set_modules if card.new? && name.to_name.junction?
|
149
|
+
card&.type_name
|
150
|
+
else
|
151
|
+
"RichText"
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
137
155
|
end
|
138
156
|
end
|
139
157
|
end
|
data/lib/card/subcards.rb
CHANGED
@@ -63,16 +63,19 @@ class Card
|
|
63
63
|
@keys.send method, *args
|
64
64
|
end
|
65
65
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
66
|
+
# fetch all cards first to avoid side effects
|
67
|
+
# e.g. deleting a user adds follow rules and +*account to subcards
|
68
|
+
# for deleting but deleting follow rules can remove +*account from the
|
69
|
+
# cache if it belongs to the rule cards
|
70
|
+
def cards
|
71
|
+
@keys.map do |key|
|
72
72
|
fetch_subcard key
|
73
|
-
end
|
73
|
+
end.compact
|
74
|
+
end
|
75
|
+
|
76
|
+
def each_card
|
74
77
|
cards.each do |card|
|
75
|
-
yield
|
78
|
+
yield card
|
76
79
|
end
|
77
80
|
end
|
78
81
|
|
data/lib/card/subcards/add.rb
CHANGED
@@ -73,7 +73,7 @@ class Card
|
|
73
73
|
end
|
74
74
|
|
75
75
|
def initialize_by_attributes name, attributes
|
76
|
-
Card.
|
76
|
+
Card.assign_or_newish name, attributes, local_only: true
|
77
77
|
end
|
78
78
|
|
79
79
|
# TODO: this method already exists as card instance method in
|
@@ -105,12 +105,15 @@ class Card
|
|
105
105
|
def multi_add args
|
106
106
|
args.each_pair do |key, val|
|
107
107
|
case val
|
108
|
-
when String
|
108
|
+
when String, Array, Integer
|
109
|
+
new_by_attributes key, content: val
|
109
110
|
when Card
|
110
111
|
val.name = absolutize_subcard_name key
|
111
112
|
new_by_card val
|
112
|
-
when nil
|
113
|
-
|
113
|
+
when nil
|
114
|
+
next
|
115
|
+
else
|
116
|
+
new_by_attributes key, val
|
114
117
|
end
|
115
118
|
end
|
116
119
|
end
|
@@ -113,7 +113,7 @@ class Card
|
|
113
113
|
# @return [True/False]
|
114
114
|
def clean_enough_to_cache?
|
115
115
|
# requested_view == ok_view && !card.unknown? && !card.db_content_changed?
|
116
|
-
requested_view == ok_view &&
|
116
|
+
requested_view == ok_view && card.view_cache_clean?
|
117
117
|
end
|
118
118
|
end
|
119
119
|
end
|
data/lib/card/view/classy.rb
CHANGED
@@ -97,6 +97,15 @@ class Card
|
|
97
97
|
|
98
98
|
private
|
99
99
|
|
100
|
+
def ancestor_extra_classes klass, space
|
101
|
+
if parent
|
102
|
+
parent_space = space == :self ? :self_format : :ancestor_format
|
103
|
+
parent.deep_extra_classes(klass, parent_space)
|
104
|
+
else
|
105
|
+
next_format_ancestor&.deep_extra_classes(klass, :ancestor_format)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
100
109
|
def storage_voo scope
|
101
110
|
# When we climb up the voo tree and cross a nest boundary then we can jump only
|
102
111
|
# to the root voo of the parent format. Hence we have to add classes to the root
|
@@ -117,15 +126,6 @@ class Card
|
|
117
126
|
[classes, class_list(:single_use).delete(klass)]
|
118
127
|
end
|
119
128
|
|
120
|
-
def ancestor_extra_classes klass, space
|
121
|
-
if parent
|
122
|
-
parent_space = space == :self ? :self_format : :ancestor_format
|
123
|
-
parent.deep_extra_classes(klass, parent_space)
|
124
|
-
else
|
125
|
-
next_format_ancestor&.deep_extra_classes(klass, :ancestor_format)
|
126
|
-
end
|
127
|
-
end
|
128
|
-
|
129
129
|
def ok_types space
|
130
130
|
case space
|
131
131
|
when :ancestor_format then [:public]
|
@@ -52,14 +52,6 @@ class Card
|
|
52
52
|
normalized_options.merge(view: requested_view).slice(*Options.slot_keys)
|
53
53
|
end
|
54
54
|
|
55
|
-
# def inherit key
|
56
|
-
# if live_options.key? key
|
57
|
-
# live_options[key]
|
58
|
-
# elsif (ancestor = next_ancestor)
|
59
|
-
# ancestor.inherit key
|
60
|
-
# end
|
61
|
-
# end
|
62
|
-
|
63
55
|
# ACCESSOR_HELPERS
|
64
56
|
# methods that follow the normalize_#{key} pattern are called by accessors
|
65
57
|
# (arguably that should be done during normalization!)
|
@@ -34,8 +34,8 @@ def fetch_read_rules
|
|
34
34
|
return [] if id == WagnBotID # always_ok, so not needed
|
35
35
|
|
36
36
|
([AnyoneID] + parties).each_with_object([]) do |party_id, rule_ids|
|
37
|
-
next unless
|
38
|
-
rule_ids.concat
|
37
|
+
next unless (cache = Card::Rule.read_rule_cache[party_id])
|
38
|
+
rule_ids.concat cache
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
@@ -65,7 +65,7 @@ RSpec.describe Card::Set::Right::Account do
|
|
65
65
|
|
66
66
|
it "contains deck title" do
|
67
67
|
body = @mail.parts[0].body.raw_source
|
68
|
-
expect(body).to match(Card.global_setting(:title))
|
68
|
+
expect(body).to match(Card::Rule.global_setting(:title))
|
69
69
|
end
|
70
70
|
|
71
71
|
it "contains link to verify account" do
|
@@ -111,7 +111,7 @@ RSpec.describe Card::Set::Right::Account do
|
|
111
111
|
|
112
112
|
it "contains deck title" do
|
113
113
|
body = @mail.parts[0].body.raw_source
|
114
|
-
expect(body).to match(Card.global_setting(:title))
|
114
|
+
expect(body).to match(Card::Rule.global_setting(:title))
|
115
115
|
end
|
116
116
|
|
117
117
|
it "contains password reset link" do
|
@@ -64,7 +64,7 @@ RSpec.describe Card::Set::Type::Signup do
|
|
64
64
|
it "sends email with an appropriate link" do
|
65
65
|
@mail = ActionMailer::Base.deliveries.last
|
66
66
|
body = @mail.parts[0].body.raw_source
|
67
|
-
expect(body).to match(Card.global_setting(:title))
|
67
|
+
expect(body).to match(Card::Rule.global_setting(:title))
|
68
68
|
end
|
69
69
|
|
70
70
|
it "notifies someone" do
|
@@ -1,6 +1,8 @@
|
|
1
1
|
format do
|
2
2
|
view :page_title, unknown: true, perms: :none do
|
3
|
-
|
3
|
+
title_parts = [Card::Rule.global_setting(:title)]
|
4
|
+
title_parts.unshift safe_name if card.name.present?
|
5
|
+
title_parts.join " - "
|
4
6
|
end
|
5
7
|
end
|
6
8
|
|
@@ -126,7 +128,7 @@ format :html do
|
|
126
128
|
|
127
129
|
def mod_js_configs
|
128
130
|
mod_js_config.map do |codename, js_decko_function|
|
129
|
-
config_json = escape_javascript Card.global_setting(codename)
|
131
|
+
config_json = escape_javascript Card::Rule.global_setting(codename)
|
130
132
|
"decko.#{js_decko_function}('#{config_json}')"
|
131
133
|
end
|
132
134
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class Card
|
2
|
+
class LazyTab < Tab
|
3
|
+
def url
|
4
|
+
@url ||= (config_hash? && @config[:path]) || format.path(view: view)
|
5
|
+
end
|
6
|
+
|
7
|
+
def view
|
8
|
+
@view ||= (config_hash? && @config[:view]) || @config
|
9
|
+
end
|
10
|
+
|
11
|
+
def tab_button
|
12
|
+
if url
|
13
|
+
super
|
14
|
+
else
|
15
|
+
wrap_with(:li, label, role: "presentation")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def button_attrib
|
20
|
+
@button_attrib ||= super.merge("data-url" => url.html_safe)
|
21
|
+
end
|
22
|
+
|
23
|
+
def tab_button_link
|
24
|
+
add_class button_attrib, "load" unless active?
|
25
|
+
super
|
26
|
+
end
|
27
|
+
|
28
|
+
def content
|
29
|
+
@content ||= ""
|
30
|
+
end
|
31
|
+
|
32
|
+
def tab_pane args=nil, &block
|
33
|
+
@content = yield if active? && block_given?
|
34
|
+
super
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
class Card
|
2
|
+
class Tab
|
3
|
+
attr_reader :format, :name, :label, :content, :button_attrib
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def tab_objects format, tab_hash, active_name, klass=nil
|
7
|
+
klass ||= Card::Tab
|
8
|
+
active_name ||= tab_hash.keys.first
|
9
|
+
tab_hash.map do |name, config|
|
10
|
+
klass.new format, name, active_name, config
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
delegate :add_class, :wrap_with, :unique_id, :link_to, to: :format
|
16
|
+
|
17
|
+
def initialize format, name, active_name, config
|
18
|
+
@format = format
|
19
|
+
@name = name
|
20
|
+
@active_name = active_name
|
21
|
+
@config = config
|
22
|
+
end
|
23
|
+
|
24
|
+
def tab_button
|
25
|
+
add_class button_attrib, "active" if active?
|
26
|
+
wrap_with :li, tab_button_link,
|
27
|
+
role: :presentation,
|
28
|
+
class: "nav-item tab-li-#{name}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def tab_pane args=nil
|
32
|
+
pane_attr = { role: :tabpanel, id: tab_id }
|
33
|
+
pane_attr.merge! args if args.present?
|
34
|
+
add_class pane_attr, "tab-pane tab-pane-#{name}"
|
35
|
+
add_class pane_attr, "active" if active?
|
36
|
+
wrap_with :div, content, pane_attr
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def config_hash?
|
42
|
+
@config.is_a? Hash
|
43
|
+
end
|
44
|
+
|
45
|
+
def label
|
46
|
+
@label ||= (config_hash? && @config[:title]) || name
|
47
|
+
end
|
48
|
+
|
49
|
+
def content
|
50
|
+
@content ||= config_hash? ? @config[:content] : @config
|
51
|
+
end
|
52
|
+
|
53
|
+
def button_attrib
|
54
|
+
@button_attrib ||= (config_hash? && @config[:button_attr]) || {}
|
55
|
+
end
|
56
|
+
|
57
|
+
def tab_button_link
|
58
|
+
add_class button_attrib, "nav-link"
|
59
|
+
|
60
|
+
link_to label, button_attrib.merge(
|
61
|
+
path: "##{tab_id}",
|
62
|
+
role: "tab",
|
63
|
+
"data-toggle" => "tab",
|
64
|
+
"data-tab-name" => name
|
65
|
+
)
|
66
|
+
end
|
67
|
+
|
68
|
+
def tab_id
|
69
|
+
@tab_id ||= "#{unique_id}-#{name.to_name.safe_key}"
|
70
|
+
end
|
71
|
+
|
72
|
+
def active?
|
73
|
+
name == @active_name
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -1,131 +1,40 @@
|
|
1
|
-
|
2
|
-
|
3
1
|
format :html do
|
4
|
-
# @param
|
5
|
-
#
|
2
|
+
# @param tab_hash [Hash] keys are the tab names
|
3
|
+
# Each value can be either a String or a Hash.
|
4
|
+
# If a Hash can contain the following keys:
|
5
|
+
# :title - the label to appear in the clickable tab nav.
|
6
|
+
# if title is not specified, the key is used
|
7
|
+
# :content - body of tab pane
|
8
|
+
# :button_attr - attributes for button link in tab nav.
|
9
|
+
#
|
10
|
+
# If using lazy loading (see :load below), the following options also apply
|
11
|
+
# :path - explicit path to use for tab pane
|
12
|
+
# :view - card view from which to auto-construct path (if missing, uses key)
|
13
|
+
#
|
14
|
+
# If the value is a String, it is treated as the tab content for static tabs and
|
15
|
+
# the view for lazy tabs
|
16
|
+
#
|
6
17
|
# @param active_name [String] label of the tab that should be active at the
|
18
|
+
#
|
19
|
+
# @param [Hash] args options
|
20
|
+
# @option args [String] :tab_type ('tabs') use pills or tabs
|
21
|
+
# @option args [Hash] :panel_attr html args used for the panel div
|
22
|
+
# @option args [Hash] :pane_attr html args used for the pane div
|
23
|
+
# @option args [Hash] :load. `:lazy` for lazy-loading tabs
|
24
|
+
#
|
25
|
+
# @param [Block] block content of the active tab (for lazy-loading)
|
7
26
|
# beginning (default is the first)
|
27
|
+
#
|
8
28
|
# @return [HTML] bootstrap tabs element with all content preloaded
|
9
|
-
def
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
if tab_content.is_a?(Hash)
|
18
|
-
[tab_content[:content], tab_content[:button_attr]]
|
19
|
-
else
|
20
|
-
[tab_content, {}]
|
21
|
-
end
|
22
|
-
tab_buttons += tab_button(id, tab_name, active_tab, button_attr)
|
23
|
-
tab_panes += tab_pane(id, tab_name, tab_content, active_tab, args[:pane])
|
24
|
-
end
|
25
|
-
tab_panel tab_buttons, tab_panes, tab_type
|
26
|
-
end
|
27
|
-
|
28
|
-
# @param [Hash] tabs keys are the views, values the title unless you pass a
|
29
|
-
# hash as value
|
30
|
-
# @option tabs [String] :title
|
31
|
-
# @option tabs [path] :path
|
32
|
-
# @option tabs [Symbol] :view
|
33
|
-
# @option tabs [HTML] :html if present use value as inner html for li tag and
|
34
|
-
# ignore the other tab options
|
35
|
-
# @param [String] active_name label of the tab that should be active at the
|
36
|
-
# beginning
|
37
|
-
# @param [String] active_content content of the active tab
|
38
|
-
# can also be passed via a block
|
39
|
-
# @param [Hash] args options
|
40
|
-
# @option args [String] :type ('tabs') use pills or tabs
|
41
|
-
# @option args [Hash] :panel_args html args used for the panel div
|
42
|
-
# @option args [Hash] :pane_args html args used for the pane div
|
43
|
-
# @return [HTML] bootstrap tabs element with content only for the active
|
44
|
-
# tab; other tabs get loaded via ajax when selected
|
45
|
-
def lazy_loading_tabs tabs, active_name, active_content="", args={}, &block
|
46
|
-
tab_buttons = ""
|
47
|
-
tab_panes = ""
|
48
|
-
standardize_tabs(tabs, active_name) do |tab_name, url, id, active_tab|
|
49
|
-
tab_buttons += lazy_tab_button tab_name, id, url, active_tab
|
50
|
-
tab_panes += lazy_tab_pane id, tab_name, active_tab, active_content,
|
51
|
-
args[:pane_args], &block
|
52
|
-
end
|
53
|
-
tab_type = args.delete(:type) || "tabs"
|
54
|
-
tab_panel tab_buttons, tab_panes, tab_type, args[:panel_args]
|
55
|
-
end
|
56
|
-
|
57
|
-
def lazy_tab_button tab_name, id, url, active_tab
|
58
|
-
return wrap_with(:li, tab_name, role: "presentation") unless url
|
59
|
-
tab_button(
|
60
|
-
id, tab_name, active_tab,
|
61
|
-
"data-url" => url.html_safe,
|
62
|
-
class: (active_tab ? nil : "load")
|
29
|
+
def tabs tab_hash, active_name=nil, args={}, &block
|
30
|
+
klass = args[:load] == :lazy ? Card::LazyTab : Card::Tab
|
31
|
+
args.reverse_merge!(
|
32
|
+
panel_attr: {},
|
33
|
+
pane_attr: {},
|
34
|
+
tab_type: "tabs",
|
35
|
+
block: block,
|
36
|
+
tab_objects: Card::Tab.tab_objects(self, tab_hash, active_name, klass)
|
63
37
|
)
|
64
|
-
|
65
|
-
|
66
|
-
def lazy_tab_pane id, tab_name, active_tab, active_content, args
|
67
|
-
tab_content =
|
68
|
-
if active_tab
|
69
|
-
block_given? ? yield : active_content
|
70
|
-
else
|
71
|
-
""
|
72
|
-
end
|
73
|
-
tab_pane(id, tab_name, tab_content, active_tab, args)
|
74
|
-
end
|
75
|
-
|
76
|
-
def standardize_tabs tabs, active_name
|
77
|
-
tabs.each do |tab_view_name, tab_details|
|
78
|
-
tab_title, url = tab_title_and_url(tab_details, tab_view_name)
|
79
|
-
active_tab = (active_name == tab_view_name)
|
80
|
-
yield tab_title, url, tab_id(tab_view_name), active_tab
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def tab_title_and_url tab_details, tab_view_name
|
85
|
-
if tab_details.is_a? Hash
|
86
|
-
tab_details[:html] ||
|
87
|
-
[tab_details[:title], tab_details[:path] || path(tab_details[:view])]
|
88
|
-
else
|
89
|
-
[tab_details, path(view: tab_view_name)]
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
def tab_panel tab_buttons, tab_panes, tab_type="tabs", args=nil
|
94
|
-
args ||= {}
|
95
|
-
add_class args, "tabbable"
|
96
|
-
args.reverse_merge! role: "tabpanel"
|
97
|
-
wrap_with :div, args do
|
98
|
-
[
|
99
|
-
wrap_with(:ul, tab_buttons, class: "nav nav-#{tab_type}",
|
100
|
-
role: "tablist"),
|
101
|
-
wrap_with(:div, tab_panes, class: "tab-content")
|
102
|
-
]
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
def tab_id tab_name
|
107
|
-
"#{unique_id}-#{tab_name.to_name.safe_key}"
|
108
|
-
end
|
109
|
-
|
110
|
-
def tab_button target, text, active=false, link_attr={}
|
111
|
-
add_class link_attr, "active" if active
|
112
|
-
link = tab_button_link "##{target}", text, link_attr
|
113
|
-
li_args = { role: :presentation, class: "nav-item tab-li-#{target}" }
|
114
|
-
wrap_with :li, link, li_args
|
115
|
-
end
|
116
|
-
|
117
|
-
def tab_button_link target, text, link_attr={}
|
118
|
-
add_class link_attr, "nav-link"
|
119
|
-
link_to text, link_attr.merge(
|
120
|
-
path: target, role: "tab", "data-toggle" => "tab"
|
121
|
-
)
|
122
|
-
end
|
123
|
-
|
124
|
-
def tab_pane id, tab_name, content, active=false, args=nil
|
125
|
-
pane_args = { role: :tabpanel, id: id }
|
126
|
-
pane_args.merge! args if args.present?
|
127
|
-
add_class pane_args, "tab-pane tab-pane-#{tab_name.to_name.safe_key}"
|
128
|
-
add_class pane_args, "active" if active
|
129
|
-
wrap_with :div, content, pane_args
|
38
|
+
haml :tab_panel, args
|
130
39
|
end
|
131
40
|
end
|