card 1.15.2 → 1.15.3
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/20150528084659_add_session_cardtype.rb +15 -0
- data/db/seed/new/card_actions.yml +342 -314
- data/db/seed/new/card_acts.yml +1 -1
- data/db/seed/new/card_changes.yml +1284 -1199
- data/db/seed/new/card_references.yml +664 -622
- data/db/seed/new/cards.yml +1355 -1278
- data/db/seed/test/fixtures/card_actions.yml +1239 -1204
- data/db/seed/test/fixtures/card_acts.yml +281 -275
- data/db/seed/test/fixtures/card_changes.yml +4127 -4022
- data/db/seed/test/fixtures/card_references.yml +1338 -1296
- data/db/seed/test/fixtures/cards.yml +2635 -2540
- data/db/version_core_cards.txt +1 -1
- data/lib/card/core_ext.rb +11 -7
- data/lib/card/format.rb +1 -1
- data/lib/card/name.rb +1 -1
- data/lib/card/set.rb +47 -47
- data/lib/card/simplecov_helper.rb +2 -2
- data/lib/card/spec_helper.rb +17 -7
- data/lib/card/view_name.rb +44 -0
- data/mod/01_core/chunk/include.rb +1 -1
- data/mod/01_core/set/all/collection.rb +90 -7
- data/mod/01_core/spec/set/all/collection_spec.rb +37 -3
- data/mod/01_history/lib/card/act.rb +15 -11
- data/mod/01_history/lib/card/action.rb +38 -38
- data/mod/01_history/set/all/history.rb +8 -4
- data/mod/02_basic_types/set/type/pointer.rb +29 -28
- data/mod/03_machines/lib/javascript/wagn_mod.js.coffee +39 -0
- data/mod/03_machines/lib/stylesheets/style_cards.scss +6 -1
- data/mod/05_email/set/all/notify.rb +47 -49
- data/mod/05_email/set/self/follow_defaults.rb +7 -7
- data/mod/05_email/set/type_plus_right/user/follow.rb +1 -1
- data/mod/05_standard/set/all/error.rb +1 -1
- data/mod/05_standard/set/all/links.rb +1 -1
- data/mod/05_standard/set/all/rich_html/content.rb +23 -21
- data/mod/05_standard/set/all/rich_html/editing.rb +64 -8
- data/mod/05_standard/set/all/rich_html/form.rb +26 -26
- data/mod/05_standard/set/all/rich_html/header.rb +2 -2
- data/mod/05_standard/set/all/rich_html/menu.rb +9 -10
- data/mod/05_standard/set/all/rich_html/toolbar.rb +100 -71
- data/mod/05_standard/set/all/rich_html/wrapper.rb +6 -0
- data/mod/05_standard/set/right/discussion.rb +3 -0
- data/mod/05_standard/set/rstar/rules.rb +5 -24
- data/mod/05_standard/set/type/cardtype.rb +31 -2
- data/mod/05_standard/set/type/session.rb +29 -0
- data/mod/05_standard/set/type/set.rb +1 -1
- data/mod/05_standard/spec/set/all/rich_html/editing_spec.rb +60 -0
- data/mod/05_standard/spec/set/all/rich_html/form_spec.rb +6 -6
- data/mod/05_standard/spec/set/type/cardtype_spec.rb +15 -1
- data/mod/06_bootstrap/lib/javascript/bootstrap_modal_wagn.js +27 -0
- data/mod/06_bootstrap/set/all/rich_bootstrap.rb +4 -3
- data/mod/06_bootstrap/set/self/bootstrap_js.rb +3 -1
- metadata +8 -2
@@ -5,7 +5,7 @@ require_dependency File.expand_path( '../reference', __FILE__ )
|
|
5
5
|
module Card::Chunk
|
6
6
|
class Include < Reference
|
7
7
|
cattr_reader :options
|
8
|
-
@@options = ::Set.new [ :inc_name, :inc_syntax, :view, :items, :type, :size, :title, :hide, :show, :structure ]
|
8
|
+
@@options = ::Set.new [ :inc_name, :inc_syntax, :view, :items, :type, :size, :title, :hide, :show, :structure, :params ]
|
9
9
|
attr_reader :options
|
10
10
|
|
11
11
|
Card::Chunk.register_class self, {
|
@@ -17,7 +17,7 @@ module ClassMethods
|
|
17
17
|
search spec.merge(:return=>'count')
|
18
18
|
end
|
19
19
|
|
20
|
-
def find_each(options = {})
|
20
|
+
def find_each(options = {})
|
21
21
|
#this is a copy from rails (3.2.16) and is needed because this is performed by a relation (ActiveRecord::Relation)
|
22
22
|
find_in_batches(options) do |records|
|
23
23
|
records.each { |record| yield record }
|
@@ -63,10 +63,10 @@ def extended_item_cards context = nil
|
|
63
63
|
items = self.item_cards(args.merge(:context=>context))
|
64
64
|
extended_list = []
|
65
65
|
already_extended = ::Set.new # avoid loops
|
66
|
-
|
66
|
+
|
67
67
|
while items.size > 0
|
68
68
|
item = items.shift
|
69
|
-
if already_extended.include? item
|
69
|
+
if already_extended.include? item
|
70
70
|
next
|
71
71
|
elsif item.item_cards == [item] # no further level of items
|
72
72
|
extended_list << item
|
@@ -103,16 +103,28 @@ def contextual_content context_card, format_args={}, view_args={}
|
|
103
103
|
end
|
104
104
|
|
105
105
|
format do
|
106
|
-
|
106
|
+
|
107
107
|
def item_links(args={})
|
108
108
|
raw(render_core).split /[,\n]/
|
109
109
|
end
|
110
|
-
|
110
|
+
|
111
|
+
def item_view args
|
112
|
+
args[:item] || (@inclusion_opts && @inclusion_opts[:view]) || default_item_view
|
113
|
+
end
|
114
|
+
|
115
|
+
def item_args args
|
116
|
+
i_args = { :view => item_view(args)}
|
117
|
+
if type = card.item_type
|
118
|
+
i_args[:type] = type
|
119
|
+
end
|
120
|
+
i_args
|
121
|
+
end
|
122
|
+
|
111
123
|
def search_params
|
112
124
|
@search_params ||= begin
|
113
125
|
p = default_search_params.clone
|
114
|
-
|
115
|
-
if focal?
|
126
|
+
|
127
|
+
if focal?
|
116
128
|
p[:offset] = params[:offset] if params[:offset]
|
117
129
|
p[:limit] = params[:limit] if params[:limit]
|
118
130
|
p.merge! params[:wql] if params[:wql]
|
@@ -144,3 +156,74 @@ format do
|
|
144
156
|
end
|
145
157
|
end
|
146
158
|
|
159
|
+
format :html do
|
160
|
+
view :tabs do |args|
|
161
|
+
tab_buttons = ''
|
162
|
+
tab_panes = ''
|
163
|
+
card.item_names.each_with_index do |item, index|
|
164
|
+
active_tab = (index == 0)
|
165
|
+
id = "#{card.cardname.safe_key}-#{item.to_name.safe_key}"
|
166
|
+
i_args = item_args(args)
|
167
|
+
if @inclusion_opts
|
168
|
+
slot_args = @inclusion_opts.clone
|
169
|
+
slot_args.delete(:view)
|
170
|
+
i_args.merge!(:slot=>slot_args)
|
171
|
+
end
|
172
|
+
url = page_path(item.to_name, i_args)
|
173
|
+
tab_buttons += tab_button( "##{id}", item, active_tab, 'data-url'=>url.html_safe, :class=>(active_tab ? nil : 'load'))
|
174
|
+
tab_content = active_tab ? nest(Card.fetch(item, :new=>{}), item_args(args)) : ''
|
175
|
+
tab_panes += tab_pane( id, tab_content, active_tab )
|
176
|
+
end
|
177
|
+
tab_panel tab_buttons, tab_panes, args[:tab_type]
|
178
|
+
end
|
179
|
+
def default_tab_args args
|
180
|
+
args[:tab_type] ||= 'tabs'
|
181
|
+
end
|
182
|
+
|
183
|
+
view :pills, :view=>:tabs
|
184
|
+
def default_pill_args args
|
185
|
+
args[:tab_type] ||= 'pills'
|
186
|
+
end
|
187
|
+
|
188
|
+
view :tabs_static do |args|
|
189
|
+
tab_buttons = ''
|
190
|
+
tab_panes = ''
|
191
|
+
card.item_cards.each_with_index do |item, index|
|
192
|
+
id = "#{card.cardname.safe_key}-#{item.cardname.safe_key}"
|
193
|
+
tab_buttons += tab_button( "##{id}", item.name, index == 0 )
|
194
|
+
tab_content = nest item, item_args(args)
|
195
|
+
tab_panes += tab_pane( id, tab_content, index == 0 )
|
196
|
+
end
|
197
|
+
tab_panel tab_buttons, tab_panes, args[:tab_type]
|
198
|
+
end
|
199
|
+
def default_tab_static_args args
|
200
|
+
args[:tab_type] ||= 'tabs'
|
201
|
+
end
|
202
|
+
|
203
|
+
view :pills_static, :view=>:tabs
|
204
|
+
def default_tab_static_args args
|
205
|
+
args[:tab_type] ||= 'pills'
|
206
|
+
end
|
207
|
+
|
208
|
+
def tab_panel tab_buttons, tab_panes, tab_type='tabs'
|
209
|
+
wrap_with :div, :role=>"tabpanel" do
|
210
|
+
[
|
211
|
+
content_tag(:ul, tab_buttons.html_safe, :class=>"nav nav-#{tab_type}", :role=>"tablist"),
|
212
|
+
content_tag(:div, tab_panes.html_safe, :class=>'tab-content')
|
213
|
+
]
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def tab_button target, text, active=false, link_attr={}
|
218
|
+
link = link_to text, target, link_attr.merge('role'=>'tab','data-toggle'=>'tab')
|
219
|
+
li_args = { :role => :presentation }
|
220
|
+
li_args[:class] = 'active' if active
|
221
|
+
content_tag :li, link, li_args
|
222
|
+
end
|
223
|
+
|
224
|
+
def tab_pane id, content, active=false
|
225
|
+
div_args = {:role => :tabpanel, :id=>id, :class=>"tab-pane #{'active' if active}"}
|
226
|
+
content_tag :div, content.html_safe, div_args
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
@@ -23,7 +23,7 @@ describe Card::Set::All::Collection do
|
|
23
23
|
expect(c.extended_list).to eq(["I'm here to be referenced to"])
|
24
24
|
end
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
describe "#extended_item_cards" do
|
28
28
|
it "returns the 'leaf cards' of a tree of pointer cards" do
|
29
29
|
Card::Auth.as_bot do
|
@@ -33,7 +33,7 @@ describe Card::Set::All::Collection do
|
|
33
33
|
expect(c.extended_item_cards).to eq([Card.fetch("Z"),Card.fetch("A")],)
|
34
34
|
end
|
35
35
|
end
|
36
|
-
|
36
|
+
|
37
37
|
describe "#extended_item_contents" do
|
38
38
|
it "returns the content of the 'leaf cards' of a tree of pointer cards" do
|
39
39
|
Card::Auth.as_bot do
|
@@ -54,7 +54,7 @@ describe Card::Set::All::Collection do
|
|
54
54
|
|
55
55
|
it "returns content even when context card is hard templated" do #why the heck is this good? -efm
|
56
56
|
context_card = Card["A"] # refers to 'Z'
|
57
|
-
|
57
|
+
|
58
58
|
Card::Auth.as_bot do
|
59
59
|
Card.create! :name => "A+*self+*structure", :content => "Banana"
|
60
60
|
end
|
@@ -62,4 +62,38 @@ describe Card::Set::All::Collection do
|
|
62
62
|
expect(c.contextual_content( context_card )).to eq("AlphaBeta")
|
63
63
|
end
|
64
64
|
end
|
65
|
+
|
66
|
+
describe 'tabs view' do
|
67
|
+
it 'renders tab panel' do
|
68
|
+
tabs = render_card :tabs, :content=>"[[A]]\n[[B]]\n[C]", :type=>'pointer'
|
69
|
+
assert_view_select tabs, 'div[role=tabpanel]' do
|
70
|
+
assert_select 'li > a[data-toggle=tab]'
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'loads only the first tab pane' do
|
75
|
+
tabs = render_card :tabs, :content=>"[[A]]\n[[B]]\n[C]", :type=>'pointer'
|
76
|
+
assert_view_select tabs, 'div[role=tabpanel]' do
|
77
|
+
assert_select 'div.tab-pane#tempo_rary-a span.card-title', 'A'
|
78
|
+
assert_select 'li > a.load[data-toggle=tab][href=#tempo_rary-b]'
|
79
|
+
assert_select 'div.tab-pane#tempo_rary-b', ''
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'handles item views' do
|
84
|
+
tabs = render_content '{{Fruit+*type+*create|tabs|name}}'
|
85
|
+
assert_view_select tabs, 'div[role=tabpanel]' do
|
86
|
+
assert_select 'div.tab-pane#fruit-Xtype-Xcreate-anyone', 'Anyone'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'handles item params' do
|
91
|
+
tabs = render_content '{{Fruit+*type+*create|tabs|name;structure:Home}}'
|
92
|
+
path = "/Anyone?#{ {:view=>:name,:slot=>{:structure=>'Home'}}.to_param}"
|
93
|
+
assert_view_select tabs, 'div[role=tabpanel]' do
|
94
|
+
assert_select "li > a[data-toggle=tab][data-url=#{path}]"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
65
99
|
end
|
@@ -4,25 +4,25 @@ class Card
|
|
4
4
|
before_save :set_actor
|
5
5
|
has_many :actions, :foreign_key=>:card_act_id, :inverse_of=> :act, :order => :id, :class_name=> "Card::Action"
|
6
6
|
belongs_to :actor, class_name: "Card"
|
7
|
-
belongs_to :card
|
7
|
+
belongs_to :card
|
8
8
|
def set_actor
|
9
9
|
self.actor_id ||= Auth.current_id
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
def self.delete_actionless
|
13
13
|
Card::Act.where(
|
14
14
|
"id NOT IN (?)",
|
15
15
|
Card::Action.pluck("card_act_id"),
|
16
16
|
).delete_all
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
def self.find_all_with_actions_on card_ids, args={}
|
20
20
|
sql = 'card_actions.card_id IN (:card_ids) AND ( (draft is not true) '
|
21
21
|
sql << ( args[:with_drafts] ? 'OR actor_id = :current_user_id)' : ')' )
|
22
22
|
vars = {:card_ids => card_ids, :current_user_id=>Card::Auth.current_id }
|
23
23
|
Card::Act.joins(:actions).where( sql, vars ).uniq.order(:id).reverse_order
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
# def actor
|
27
27
|
# Card[ actor_id ]
|
28
28
|
# end
|
@@ -30,31 +30,35 @@ class Card
|
|
30
30
|
# def card
|
31
31
|
# Card[ card_id ]
|
32
32
|
# end
|
33
|
-
|
33
|
+
|
34
34
|
def action_on card_id
|
35
|
-
actions.where( "card_id = #{
|
35
|
+
actions.where( "card_id = #{card_id} and draft is not true" ).first
|
36
|
+
end
|
37
|
+
|
38
|
+
def main_action
|
39
|
+
action_on(card_id) || actions.first
|
36
40
|
end
|
37
|
-
|
41
|
+
|
38
42
|
def elapsed_time
|
39
43
|
DateTime.new(acted_at).distance_of_time_in_words_to_now
|
40
44
|
end
|
41
|
-
|
45
|
+
|
42
46
|
def relevant_drafts_for card
|
43
47
|
drafts.select do |action|
|
44
48
|
card.included_card_ids.include?(action.card_id) || (card == action.card)
|
45
49
|
end
|
46
50
|
end
|
47
|
-
|
51
|
+
|
48
52
|
def relevant_actions_for card, with_drafts=false
|
49
53
|
actions.select do |action|
|
50
54
|
card.included_card_ids.include?(action.card_id) || (card == action.card)
|
51
55
|
end
|
52
56
|
end
|
53
|
-
|
57
|
+
|
54
58
|
private
|
55
59
|
def timestamp_attributes_for_create
|
56
60
|
super << :acted_at
|
57
61
|
end
|
58
|
-
|
62
|
+
|
59
63
|
end
|
60
64
|
end
|
@@ -1,40 +1,40 @@
|
|
1
1
|
# -*- encoding : utf-8 -*-
|
2
2
|
|
3
3
|
class Card
|
4
|
-
|
4
|
+
|
5
5
|
class Action < ActiveRecord::Base
|
6
6
|
belongs_to :card
|
7
|
-
belongs_to :act, :foreign_key=>:card_act_id, :inverse_of=>:actions
|
7
|
+
belongs_to :act, :foreign_key=>:card_act_id, :inverse_of=>:actions
|
8
8
|
has_many :changes, :foreign_key=>:card_action_id, :inverse_of=>:action, :dependent=>:delete_all
|
9
|
-
|
9
|
+
|
10
10
|
belongs_to :super_action, :class_name=> "Action", :inverse_of=>:sub_actions
|
11
11
|
has_many :sub_actions, :class_name=> "Action", :inverse_of=>:super_action
|
12
|
-
|
12
|
+
|
13
13
|
scope :created_by, lambda { |actor_id| joins(:act).where('card_acts.actor_id = ?', actor_id) }
|
14
|
-
|
15
|
-
# replace with enum if we start using rails 4
|
14
|
+
|
15
|
+
# replace with enum if we start using rails 4
|
16
16
|
TYPE = [:create, :update, :delete]
|
17
|
-
|
17
|
+
|
18
18
|
class << self
|
19
19
|
def cache
|
20
20
|
Card::Cache[Action]
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
def fetch id
|
24
24
|
cache.read(id.to_s) or begin
|
25
25
|
cache.write id.to_s, Action.find(id.to_i)
|
26
26
|
end
|
27
27
|
end
|
28
|
-
|
29
|
-
|
28
|
+
|
29
|
+
|
30
30
|
def delete_cardless
|
31
31
|
Card::Action.where( Card.where( :id=>arel_table[:card_id] ).exists.not ).delete_all
|
32
32
|
end
|
33
|
-
|
34
|
-
def delete_old
|
33
|
+
|
34
|
+
def delete_old
|
35
35
|
Card.find_each do |card|
|
36
36
|
card.delete_old_actions
|
37
|
-
end
|
37
|
+
end
|
38
38
|
Card::Act.delete_actionless
|
39
39
|
end
|
40
40
|
end
|
@@ -70,7 +70,7 @@ class Card
|
|
70
70
|
:old_cardtype => old_values[:cardtype]
|
71
71
|
}
|
72
72
|
end
|
73
|
-
|
73
|
+
|
74
74
|
def new_values
|
75
75
|
@new_values ||= {
|
76
76
|
:content => new_value_for(:db_content),
|
@@ -78,29 +78,29 @@ class Card
|
|
78
78
|
:cardtype => ( typecard = Card[new_value_for(:type_id).to_i] and typecard.name.capitalize )
|
79
79
|
}
|
80
80
|
end
|
81
|
-
|
81
|
+
|
82
82
|
def old_values
|
83
83
|
@old_values ||= {
|
84
84
|
:content => last_value_for(:db_content),
|
85
85
|
:name => last_value_for(:name),
|
86
|
-
:cardtype => ( value = last_value_for(:type_id) and
|
86
|
+
:cardtype => ( value = last_value_for(:type_id) and
|
87
87
|
typecard = Card.find(value) and typecard.name.capitalize )
|
88
88
|
}
|
89
89
|
end
|
90
|
-
|
90
|
+
|
91
91
|
def last_value_for field
|
92
92
|
ch = self.card.last_change_on(field, :before=>self) and ch.value
|
93
93
|
end
|
94
|
-
|
94
|
+
|
95
95
|
def new_value_for(field)
|
96
96
|
ch = changes.find_by_field(field) and ch.value
|
97
97
|
end
|
98
|
-
def change_for(field)
|
98
|
+
def change_for(field)
|
99
99
|
field_integer = ( field.is_a?(Integer) ? field : Card::TRACKED_FIELDS.index(field.to_s) )
|
100
100
|
changes.where 'card_changes.field = ?', field_integer
|
101
101
|
end
|
102
|
-
|
103
|
-
|
102
|
+
|
103
|
+
|
104
104
|
def new_type?
|
105
105
|
new_value_for(:type_id)
|
106
106
|
end
|
@@ -110,66 +110,66 @@ class Card
|
|
110
110
|
def new_name?
|
111
111
|
new_value_for(:name)
|
112
112
|
end
|
113
|
-
|
114
|
-
|
113
|
+
|
114
|
+
|
115
115
|
def action_type=(value)
|
116
116
|
write_attribute(:action_type, TYPE.index(value))
|
117
117
|
end
|
118
|
-
|
118
|
+
|
119
119
|
def action_type
|
120
120
|
TYPE[read_attribute(:action_type)]
|
121
121
|
end
|
122
|
-
|
122
|
+
|
123
123
|
def set_act
|
124
124
|
self.set_act ||= self.acts.last
|
125
125
|
end
|
126
|
-
|
127
|
-
def revision_nr
|
126
|
+
|
127
|
+
def revision_nr
|
128
128
|
self.card.actions.index_of(self)
|
129
129
|
end
|
130
|
-
|
130
|
+
|
131
131
|
def red?
|
132
132
|
content_diff_builder.red?
|
133
133
|
end
|
134
|
-
|
134
|
+
|
135
135
|
def green?
|
136
136
|
content_diff_builder.green?
|
137
137
|
end
|
138
|
-
|
139
|
-
|
138
|
+
|
139
|
+
|
140
140
|
# def diff
|
141
141
|
# @diff ||= { :cardtype=>type_diff, :content=>content_diff, :name=>name_diff}
|
142
142
|
# end
|
143
|
-
|
144
|
-
|
143
|
+
|
144
|
+
|
145
145
|
def name_diff opts={}
|
146
146
|
if new_name?
|
147
147
|
Card::Diff.complete old_values[:name], new_values[:name], opts
|
148
148
|
end
|
149
149
|
end
|
150
|
-
|
150
|
+
|
151
151
|
def cardtype_diff opts={}
|
152
152
|
if new_type?
|
153
153
|
Card::Diff.complete old_values[:cardtype], new_values[:cardtype], opts
|
154
154
|
end
|
155
155
|
end
|
156
|
-
|
156
|
+
|
157
157
|
def content_diff diff_type=:expanded, opts=nil
|
158
158
|
if new_content?
|
159
159
|
if diff_type == :summary
|
160
160
|
content_diff_builder(opts).summary
|
161
161
|
else
|
162
|
-
content_diff_builder(opts).complete
|
162
|
+
content_diff_builder(opts).complete
|
163
163
|
end
|
164
164
|
end
|
165
165
|
end
|
166
|
-
|
166
|
+
|
167
167
|
def content_diff_builder opts=nil
|
168
168
|
@content_diff_builder ||= begin
|
169
169
|
Card::Diff::DiffBuilder.new(old_values[:content], new_values[:content], opts || card.diff_args)
|
170
170
|
end
|
171
171
|
end
|
172
|
-
|
172
|
+
|
173
173
|
end
|
174
174
|
end
|
175
175
|
|