card 1.101.0 → 1.101.1
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/config/locales/en.yml +9 -6
- data/db/migrate_core_cards/data/decko_logo.svg +1 -59
- data/lib/card.rb +3 -0
- data/lib/card/content/diff/result.rb +40 -29
- data/lib/card/env.rb +2 -2
- data/lib/card/model/save_helper.rb +16 -182
- data/lib/card/model/save_helper/save_arguments.rb +94 -0
- data/lib/card/model/save_helper/save_helper_helper.rb +93 -0
- data/lib/card/name/all.rb +125 -0
- data/lib/card/name/all/class_methods.rb +28 -0
- data/lib/card/name/all/descendants.rb +46 -0
- data/lib/card/name/all/parts.rb +67 -0
- data/lib/card/query.rb +7 -2
- data/lib/card/query/card_query/interpretation.rb +2 -2
- data/lib/card/query/card_query/sorting.rb +12 -4
- data/lib/card/query/sql_statement.rb +1 -1
- data/lib/card/set/advanced_api.rb +8 -5
- data/lib/card/set/event/options.rb +13 -5
- data/lib/card/set/format.rb +16 -9
- data/lib/card/set/trait.rb +11 -8
- data/lib/card/subcards/add.rb +3 -24
- data/lib/card/subcards/args.rb +42 -0
- data/lib/card/tasks/card/file_card_creator/output_helper.rb +15 -10
- data/lib/card/view/options.rb +2 -1
- data/lib/card/view/permission.rb +14 -3
- data/lib/cardio.rb +9 -66
- data/lib/cardio/defaults.yml +70 -0
- data/lib/cardio/migration.rb +1 -1
- data/mod/core/set/all/assign_attributes.rb +8 -21
- data/mod/core/set/all/initialize.rb +9 -9
- data/mod/core/set/all/name_events.rb +3 -1
- data/mod/core/set/all/references.rb +2 -2
- data/mod/{settings → core}/set/right/autoname.rb +0 -0
- data/mod/{settings → core}/set/self/autoname.rb +0 -0
- data/mod/core/set/type/cardtype.rb +28 -0
- data/mod/{standard → core}/spec/set/type/cardtype_spec.rb +3 -24
- data/mod/standard/file/logo/image-original.svg +1 -59
- metadata +16 -27
- data/config/initializers/uuid_state_file.rb +0 -3
- data/mod/Modfile +0 -4
- data/mod/core/set/all/name.rb +0 -229
- data/mod/core/spec/set/all/name_spec.rb +0 -11
- data/mod/standard/set/all/rich_html/html_views/info.rb +0 -84
- data/mod/standard/set/type/cardtype.rb +0 -119
data/mod/Modfile
DELETED
data/mod/core/set/all/name.rb
DELETED
@@ -1,229 +0,0 @@
|
|
1
|
-
require "uuid"
|
2
|
-
|
3
|
-
module ClassMethods
|
4
|
-
def uniquify_name name, rename=:new
|
5
|
-
return name unless Card.exists? name
|
6
|
-
uniq_name = generate_alternative_name name
|
7
|
-
return uniq_name unless rename == :old
|
8
|
-
rename!(name, uniq_name)
|
9
|
-
name
|
10
|
-
end
|
11
|
-
|
12
|
-
def generate_alternative_name name
|
13
|
-
uniq_name = "#{name} 1"
|
14
|
-
uniq_name.next! while Card.exists?(uniq_name)
|
15
|
-
uniq_name
|
16
|
-
end
|
17
|
-
|
18
|
-
def rename! oldname, newname
|
19
|
-
Card[oldname].update! name: newname, update_referers: true
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def name
|
24
|
-
@name ||= left_id ? Card::Lexicon.lex_to_name([left_id, right_id]) : super.to_name
|
25
|
-
end
|
26
|
-
|
27
|
-
def key
|
28
|
-
@key ||= left_id ? name.key : super
|
29
|
-
end
|
30
|
-
|
31
|
-
def name= newname
|
32
|
-
@name = superize_name newname.to_name
|
33
|
-
self.key = @name.key
|
34
|
-
update_subcard_names @name
|
35
|
-
write_attribute :name, (@name.simple? ? @name.s : nil)
|
36
|
-
assign_side_ids
|
37
|
-
@name
|
38
|
-
end
|
39
|
-
|
40
|
-
def assign_side_ids
|
41
|
-
if name.simple?
|
42
|
-
self.left_id = self.right_id = nil
|
43
|
-
else
|
44
|
-
assign_side_id :left_id=, :left_name
|
45
|
-
assign_side_id :right_id=, :right_name
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
# assigns left_id and right_id based on names.
|
50
|
-
# if side card is new, id is temporarily stored as -1
|
51
|
-
def assign_side_id side_id_equals, side_name
|
52
|
-
side_id = Card::Lexicon.id(name.send(side_name)) || -1
|
53
|
-
send side_id_equals, side_id
|
54
|
-
end
|
55
|
-
|
56
|
-
def superize_name cardname
|
57
|
-
return cardname unless @supercard
|
58
|
-
|
59
|
-
@supercard.subcards.rename key, cardname.key
|
60
|
-
update_superleft cardname
|
61
|
-
@supercard.name.relative? ? cardname : cardname.absolute_name(@supercard.name)
|
62
|
-
end
|
63
|
-
|
64
|
-
def update_superleft cardname
|
65
|
-
@superleft = @supercard if cardname.field_of? @supercard.name
|
66
|
-
end
|
67
|
-
|
68
|
-
def key= newkey
|
69
|
-
return if newkey == key
|
70
|
-
update_cache_key key do
|
71
|
-
write_attribute :key, (name.simple? ? newkey : nil)
|
72
|
-
@key = newkey
|
73
|
-
end
|
74
|
-
clean_patterns
|
75
|
-
@key
|
76
|
-
end
|
77
|
-
|
78
|
-
def clean_patterns
|
79
|
-
return unless patterns?
|
80
|
-
reset_patterns
|
81
|
-
patterns
|
82
|
-
end
|
83
|
-
|
84
|
-
def update_cache_key oldkey
|
85
|
-
yield
|
86
|
-
was_in_cache = Card.cache.soft.delete oldkey
|
87
|
-
Card.write_to_soft_cache self if was_in_cache
|
88
|
-
end
|
89
|
-
|
90
|
-
def update_subcard_names new_name, name_to_replace=nil
|
91
|
-
return unless @subcards
|
92
|
-
subcards.each do |subcard|
|
93
|
-
update_subcard_name subcard, new_name, name_to_replace if subcard.new?
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
def update_subcard_name subcard, new_name, name_to_replace
|
98
|
-
name_to_replace ||= name_to_replace_for_subcard subcard, new_name
|
99
|
-
subcard.name = subcard.name.swap name_to_replace, new_name.s
|
100
|
-
subcard.update_subcard_names new_name, name # needed? shouldn't #name= trigger this?
|
101
|
-
end
|
102
|
-
|
103
|
-
def name_to_replace_for_subcard subcard, new_name
|
104
|
-
# if subcard has a relative name like +C
|
105
|
-
# and self is a subcard as well that changed from +B to A+B then
|
106
|
-
# +C should change to A+B+C. #replace doesn't work in this case
|
107
|
-
# because the old name +B is not a part of +C
|
108
|
-
if subcard.name.starts_with_joint? && new_name.parts.first.present?
|
109
|
-
"".to_name
|
110
|
-
else
|
111
|
-
name
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
def autoname name
|
116
|
-
if Card.exists?(name) || Director.include?(name)
|
117
|
-
autoname name.next
|
118
|
-
else
|
119
|
-
name
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
# FIXME: use delegations and include all name functions
|
124
|
-
delegate :simple?, :compound?, :junction?, to: :name
|
125
|
-
|
126
|
-
def left *args
|
127
|
-
case
|
128
|
-
when simple? then nil
|
129
|
-
when superleft then superleft
|
130
|
-
when name_is_changing? && name.to_name.trunk_name == name_before_act.to_name
|
131
|
-
nil # prevent recursion when, eg, renaming A+B to A+B+C
|
132
|
-
else
|
133
|
-
Card.fetch name.left, *args
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
def right *args
|
138
|
-
Card.fetch(name.right, *args) unless simple?
|
139
|
-
end
|
140
|
-
|
141
|
-
def [] *args
|
142
|
-
case args[0]
|
143
|
-
when Integer, Range
|
144
|
-
fetch_name = Array.wrap(name.parts[args[0]]).compact.join Card::Name.joint
|
145
|
-
Card.fetch(fetch_name, args[1] || {}) unless simple?
|
146
|
-
else
|
147
|
-
super
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
def trunk *args
|
152
|
-
simple? ? self : left(*args)
|
153
|
-
end
|
154
|
-
|
155
|
-
def tag *args
|
156
|
-
simple? ? self : Card.fetch(name.right, *args)
|
157
|
-
end
|
158
|
-
|
159
|
-
def left_or_new args={}
|
160
|
-
left(args) || Card.new(args.merge(name: name.left))
|
161
|
-
end
|
162
|
-
|
163
|
-
# NOTE: for all these helpers, method returns *all* fields/children/descendants.
|
164
|
-
# (Not just those current user has permission to read.)
|
165
|
-
|
166
|
-
def fields
|
167
|
-
field_ids.map { |id| Card[id] }
|
168
|
-
end
|
169
|
-
|
170
|
-
def field_names
|
171
|
-
field_ids.map { |id| Card::Name[id] }
|
172
|
-
end
|
173
|
-
|
174
|
-
def field_ids
|
175
|
-
child_ids :left
|
176
|
-
end
|
177
|
-
|
178
|
-
def each_child
|
179
|
-
child_ids.each do |id|
|
180
|
-
(child = Card[id]) && yield(child)
|
181
|
-
# check should not be needed (remove after fixing data problems)
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
# eg, A+B is a child of A and B
|
186
|
-
def child_ids side=nil
|
187
|
-
return [] unless id
|
188
|
-
side ||= name.simple? ? :part : :left_id
|
189
|
-
Auth.as_bot do
|
190
|
-
Card.search({ side => id, return: :id, limit: 0 }, "children of #{name}")
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
def each_descendant &block
|
195
|
-
each_child do |child|
|
196
|
-
yield child
|
197
|
-
child.each_descendant(&block)
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
def right_id= cardish
|
202
|
-
write_card_or_id :right_id, cardish
|
203
|
-
end
|
204
|
-
|
205
|
-
def left_id= cardish
|
206
|
-
write_card_or_id :left_id, cardish
|
207
|
-
end
|
208
|
-
|
209
|
-
def write_card_or_id attribute, cardish
|
210
|
-
when_id_exists(cardish) { |id| write_attribute attribute, id }
|
211
|
-
end
|
212
|
-
|
213
|
-
def when_id_exists cardish, &block
|
214
|
-
if (card_id = Card.id cardish)
|
215
|
-
yield card_id
|
216
|
-
elsif cardish.is_a? Card
|
217
|
-
with_id_after_store cardish, &block
|
218
|
-
else
|
219
|
-
yield cardish # eg nil
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
# subcards are usually saved after super cards;
|
224
|
-
# after_store forces it to save the subcard first
|
225
|
-
# and callback afterwards
|
226
|
-
def with_id_after_store subcard
|
227
|
-
add_subcard subcard
|
228
|
-
subcard.director.after_store { |card| yield card.id }
|
229
|
-
end
|
@@ -1,11 +0,0 @@
|
|
1
|
-
# -*- encoding : utf-8 -*-
|
2
|
-
|
3
|
-
RSpec.describe Card::Set::All::Name do
|
4
|
-
describe "#each_descendants" do
|
5
|
-
it "finds descendants" do
|
6
|
-
descendants_of_a = []
|
7
|
-
Card["A"].each_descendant { |card| descendants_of_a << card.name }
|
8
|
-
expect(descendants_of_a).to include("A+B+C")
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
@@ -1,84 +0,0 @@
|
|
1
|
-
format :html do
|
2
|
-
view :type, unknown: true do
|
3
|
-
link_to_card card.type_card, nil, class: "cardtype"
|
4
|
-
end
|
5
|
-
|
6
|
-
view :change do
|
7
|
-
voo.show :title_link
|
8
|
-
voo.hide :menu
|
9
|
-
wrap do
|
10
|
-
[_render_title,
|
11
|
-
_render_menu,
|
12
|
-
_render_last_action]
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
view :last_action do
|
17
|
-
act = card.last_act
|
18
|
-
return unless act
|
19
|
-
|
20
|
-
action = act.action_on card.id
|
21
|
-
return unless action
|
22
|
-
|
23
|
-
action_verb =
|
24
|
-
case action.action_type
|
25
|
-
when :create then "added"
|
26
|
-
when :delete then "deleted"
|
27
|
-
else
|
28
|
-
link_to_view :history, "edited", class: "last-edited", rel: "nofollow"
|
29
|
-
end
|
30
|
-
|
31
|
-
%(
|
32
|
-
<span class="last-update">
|
33
|
-
#{action_verb} #{_render_acted_at} ago by
|
34
|
-
#{subformat(card.last_actor)._render_link}
|
35
|
-
</span>
|
36
|
-
)
|
37
|
-
end
|
38
|
-
|
39
|
-
view :type_info do
|
40
|
-
return unless card.type_code != :basic
|
41
|
-
|
42
|
-
wrap_with :span, class: "type-info float-right" do
|
43
|
-
link_to_card card.type_name, nil, class: "navbar-link"
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
view :view_list do
|
48
|
-
%i[bar box info_bar open closed titled labeled content content_panel].map do |v|
|
49
|
-
wrap_with :p, [content_tag(:h3, v), render(v, show: :menu)]
|
50
|
-
end.flatten.join ""
|
51
|
-
end
|
52
|
-
|
53
|
-
view :demo do
|
54
|
-
frame do
|
55
|
-
[
|
56
|
-
view_select,
|
57
|
-
wrap_with(:div, view_demo, class: "demo-slot")
|
58
|
-
]
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
def demo_view
|
63
|
-
Env.params[:demo_view] || :core
|
64
|
-
end
|
65
|
-
|
66
|
-
def view_demo
|
67
|
-
wrap(true) do
|
68
|
-
render demo_view
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def view_select
|
73
|
-
card_form :get, success: { view: :demo } do
|
74
|
-
select_tag :demo_view, options_for_select(all_views, demo_view),
|
75
|
-
class: "_submit-on-select"
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
def all_views
|
80
|
-
Card::Set::Format::AbstractFormat::ViewDefinition.views
|
81
|
-
.slice(*self.class.ancestors)
|
82
|
-
.values.map(&:keys).flatten.uniq
|
83
|
-
end
|
84
|
-
end
|
@@ -1,119 +0,0 @@
|
|
1
|
-
def related_sets with_self=false
|
2
|
-
sets = []
|
3
|
-
sets << ["#{name}+*type", Card::Set::Type.label(name)] if known?
|
4
|
-
sets + super
|
5
|
-
end
|
6
|
-
|
7
|
-
format :html do
|
8
|
-
view :type, unknown: true do
|
9
|
-
link_to_card card.type_card, nil, class: "cardtype"
|
10
|
-
end
|
11
|
-
|
12
|
-
def type_formgroup args={}
|
13
|
-
if card.cards_of_type_exist?
|
14
|
-
wrap_with :div, tr(:cards_exist, cardname: safe_name)
|
15
|
-
else
|
16
|
-
super
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
view :add_link do
|
21
|
-
add_link
|
22
|
-
end
|
23
|
-
|
24
|
-
view :add_button do
|
25
|
-
add_link class: "btn btn-secondary"
|
26
|
-
end
|
27
|
-
|
28
|
-
def add_link opts={}
|
29
|
-
voo.title ||= tr(:add_card, cardname: safe_name)
|
30
|
-
link_to render_title, add_link_opts(opts)
|
31
|
-
end
|
32
|
-
|
33
|
-
def add_link_opts opts
|
34
|
-
modal = opts.delete :modal
|
35
|
-
modal = true if modal.nil?
|
36
|
-
opts[:path] = add_path(modal ? :new_in_modal : :new)
|
37
|
-
modal ? modal_link_opts(opts) : opts
|
38
|
-
end
|
39
|
-
|
40
|
-
view :add_url do
|
41
|
-
card_url _render_add_path
|
42
|
-
end
|
43
|
-
|
44
|
-
def add_path view
|
45
|
-
path_args = { mark: card.name }
|
46
|
-
process_voo_params(path_args) if voo.params
|
47
|
-
if view == :new
|
48
|
-
path_args[:action] = :new
|
49
|
-
else
|
50
|
-
path_args[:action] = :type
|
51
|
-
path_args[:view] = view
|
52
|
-
end
|
53
|
-
path path_args
|
54
|
-
end
|
55
|
-
|
56
|
-
# don't cache because it depends on update permission for another card
|
57
|
-
view :configure_link, cache: :never, perms: ->(fmt) { fmt.can_configure? } do
|
58
|
-
configure_link
|
59
|
-
end
|
60
|
-
|
61
|
-
def can_configure?
|
62
|
-
Card.fetch(card, :type, :structure, new: {}).ok? :update
|
63
|
-
end
|
64
|
-
|
65
|
-
view :configure_button, cache: :never, denial: :blank,
|
66
|
-
perms: ->(fmt) { fmt.can_configure? } do
|
67
|
-
configure_link "btn btn-secondary"
|
68
|
-
end
|
69
|
-
|
70
|
-
def configure_link css_class=nil
|
71
|
-
return "" unless Card.fetch(card, :type, :structure, new: {}).ok? :update
|
72
|
-
|
73
|
-
voo.title ||= tr(:configure_card, cardname: safe_name.pluralize)
|
74
|
-
title = _render_title
|
75
|
-
link_to_card card, title, path: { view: :bridge, bridge: { tab: :rules_tab },
|
76
|
-
set: Card::Name[safe_name, :type] },
|
77
|
-
class: css_classes("configure-type-link ml-3", css_class)
|
78
|
-
end
|
79
|
-
|
80
|
-
private
|
81
|
-
|
82
|
-
def process_voo_params path_args
|
83
|
-
context = ((@parent&.card) || card).name
|
84
|
-
Rack::Utils.parse_nested_query(voo.params).each do |key, value|
|
85
|
-
value = value.to_name.absolute(context) if value
|
86
|
-
key = key.to_name.absolute(context)
|
87
|
-
path_args[key] = value
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def cards_of_type_exist?
|
93
|
-
!new_card? && Card.where(trash: false, type_id: id).exists?
|
94
|
-
end
|
95
|
-
|
96
|
-
def create_ok?
|
97
|
-
Card.new(type_id: id).ok? :create
|
98
|
-
end
|
99
|
-
|
100
|
-
def was_cardtype?
|
101
|
-
type_id_before_act == Card::CardtypeID
|
102
|
-
end
|
103
|
-
|
104
|
-
event :check_for_cards_of_type, after: :validate_delete do
|
105
|
-
errors.add :cardtype, tr(:cards_exist, cardname: name) if cards_of_type_exist?
|
106
|
-
end
|
107
|
-
|
108
|
-
event :check_for_cards_of_type_when_type_changed,
|
109
|
-
:validate, changing: :type, when: :was_cardtype? do
|
110
|
-
if cards_of_type_exist?
|
111
|
-
errors.add :cardtype, tr(:error_cant_alter, name: name_before_act)
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
event :validate_cardtype_name, :validate, on: :save, changed: :name do
|
116
|
-
if %r{[<>/]}.match?(name)
|
117
|
-
errors.add :name, tr(:error_invalid_character_in_cardtype, banned: "<, >, /")
|
118
|
-
end
|
119
|
-
end
|