card 1.101.0 → 1.101.1
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.
- 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/lib/card/query.rb
CHANGED
@@ -37,12 +37,13 @@ class Card
|
|
37
37
|
require "card/query/clause"
|
38
38
|
require "card/query/card_query"
|
39
39
|
require "card/query/sql_statement"
|
40
|
+
|
40
41
|
# Card::Query::CardQuery
|
41
|
-
# After conversion,
|
42
|
+
# After conversion, @attributes is a Hash where the key is the attribute
|
42
43
|
# and the value is the attribute type:
|
43
44
|
# { id: :basic, name: :basic, key: :basic ...}
|
44
45
|
# This is used for rapid attribute type lookups in the interpretation phase.
|
45
|
-
|
46
|
+
@attributes = {
|
46
47
|
# Each of the "basic" fields corresponds directly to a database field.
|
47
48
|
# their values are translated fairly directly into SQL-safe values.
|
48
49
|
# (These are referred to as "properties" in CQL documentation. Need to
|
@@ -87,6 +88,8 @@ class Card
|
|
87
88
|
DEFAULT_ORDER_DIRS = { update: "desc", relevance: "desc" }.freeze
|
88
89
|
|
89
90
|
class << self
|
91
|
+
attr_accessor :attributes
|
92
|
+
|
90
93
|
def new statement, comment=nil
|
91
94
|
Query::CardQuery.new statement, comment
|
92
95
|
end
|
@@ -106,5 +109,7 @@ class Card
|
|
106
109
|
txt
|
107
110
|
end
|
108
111
|
end
|
112
|
+
|
113
|
+
delegate :attributes, to: :class
|
109
114
|
end
|
110
115
|
end
|
@@ -29,7 +29,7 @@ class Card
|
|
29
29
|
def interpret_as_content? key
|
30
30
|
# eg "match" is both operator and attribute;
|
31
31
|
# interpret as attribute when "match" is key
|
32
|
-
OPERATORS.key?(key.to_s) && !
|
32
|
+
OPERATORS.key?(key.to_s) && !Query.attributes[key]
|
33
33
|
end
|
34
34
|
|
35
35
|
def interpret_as_modifier? key, val
|
@@ -43,7 +43,7 @@ class Card
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def interpret_attributes attribute, val
|
46
|
-
attribute_type =
|
46
|
+
attribute_type = Query.attributes[attribute]
|
47
47
|
if (method = INTERPRET_METHOD[attribute_type])
|
48
48
|
send method, attribute, val
|
49
49
|
else
|
@@ -16,10 +16,9 @@ class Card
|
|
16
16
|
def sort val
|
17
17
|
return nil unless full?
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
sort_by val, item, sort_field
|
19
|
+
interpret_sort_hash val do |value, item, sort_field|
|
20
|
+
sort_by value, item, sort_field
|
21
|
+
end
|
23
22
|
end
|
24
23
|
|
25
24
|
def sort_by val, item, sort_field
|
@@ -95,6 +94,15 @@ class Card
|
|
95
94
|
s.interpret val
|
96
95
|
s
|
97
96
|
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
def interpret_sort_hash val
|
101
|
+
val = val.symbolize_keys
|
102
|
+
item = val.delete(:item) || "left"
|
103
|
+
sort_field = val[:return] || "db_content"
|
104
|
+
yield val, item, sort_field
|
105
|
+
end
|
98
106
|
end
|
99
107
|
end
|
100
108
|
end
|
@@ -10,17 +10,20 @@ class Card
|
|
10
10
|
def ensure_set &block
|
11
11
|
set_module = yield
|
12
12
|
set_module = card_set_module_const_get(set_module) unless set_module.is_a?(Module)
|
13
|
-
|
14
|
-
|
15
|
-
if e.message =~ /uninitialized constant (?:Card::Set::)?(.+)$/
|
16
|
-
define_set Regexp.last_match(1)
|
17
|
-
end
|
13
|
+
rescue NameError => error
|
14
|
+
define_set_from_error error
|
18
15
|
# try again - there might be another submodule that doesn't exist
|
19
16
|
ensure_set(&block)
|
20
17
|
else
|
21
18
|
set_module.extend Card::Set
|
22
19
|
end
|
23
20
|
|
21
|
+
def define_set_from_error error
|
22
|
+
match = error.message.match(/uninitialized constant (?:Card::Set::)?(.+)$/)
|
23
|
+
return unless match
|
24
|
+
define_set match[1]
|
25
|
+
end
|
26
|
+
|
24
27
|
def attachment name, args
|
25
28
|
include_set Abstract::Attachment
|
26
29
|
add_attributes name, "remote_#{name}_url".to_sym,
|
@@ -23,13 +23,21 @@ class Card
|
|
23
23
|
if condition == :when
|
24
24
|
validate_when_value val
|
25
25
|
else
|
26
|
-
|
27
|
-
|
26
|
+
validate_standard_condition_value condition, val
|
27
|
+
end
|
28
|
+
end
|
28
29
|
|
29
|
-
|
30
|
-
|
30
|
+
def validate_standard_condition_value condition, val
|
31
|
+
invalid = invalid_condition_values condition, val
|
32
|
+
return if invalid.empty?
|
33
|
+
|
34
|
+
raise ArgumentError,
|
35
|
+
"invalid option#{'s' if invalid.size > 1} '#{invalid}' "\
|
31
36
|
"for condition '#{condition}' in event '#{@event}'"
|
32
|
-
|
37
|
+
end
|
38
|
+
|
39
|
+
def invalid_condition_values condition, val
|
40
|
+
Array.wrap(val) - Api::OPTIONS[condition]
|
33
41
|
end
|
34
42
|
|
35
43
|
def validate_when_value val
|
data/lib/card/set/format.rb
CHANGED
@@ -106,20 +106,27 @@ class Card
|
|
106
106
|
|
107
107
|
def register_set_format format_class, mod
|
108
108
|
if all_set?
|
109
|
-
|
109
|
+
register_all_set_format format_class, mod
|
110
110
|
else
|
111
|
-
|
112
|
-
# ready to include dynamically in set members' format singletons
|
113
|
-
format_hash = modules[format_type][format_class] ||= {}
|
114
|
-
format_hash[shortname] ||= []
|
115
|
-
format_hash[shortname] << mod
|
111
|
+
register_standard_set_format format_class, mod
|
116
112
|
end
|
117
113
|
end
|
118
114
|
|
119
115
|
# make mod ready to include in base (non-set-specific) format classes
|
120
|
-
def
|
121
|
-
modules[:base_format]
|
122
|
-
|
116
|
+
def register_all_set_format format_class, mod
|
117
|
+
add_to_array_val modules[:base_format], format_class, mod
|
118
|
+
end
|
119
|
+
|
120
|
+
def register_standard_set_format format_class, mod
|
121
|
+
format_type = abstract_set? ? :abstract_format : :nonbase_format
|
122
|
+
# ready to include dynamically in set members' format singletons
|
123
|
+
format_hash = modules[format_type][format_class] ||= {}
|
124
|
+
add_to_array_val format_hash, shortname, mod
|
125
|
+
end
|
126
|
+
|
127
|
+
def add_to_array_val hash, key, val
|
128
|
+
hash[key] ||= []
|
129
|
+
hash[key] << val
|
123
130
|
end
|
124
131
|
|
125
132
|
class << self
|
data/lib/card/set/trait.rb
CHANGED
@@ -28,7 +28,7 @@ class Card
|
|
28
28
|
|
29
29
|
def add_attributes *args
|
30
30
|
Card.set_specific_attributes ||= []
|
31
|
-
Card.set_specific_attributes += args.map(&:
|
31
|
+
Card.set_specific_attributes += args.map(&:to_sym)
|
32
32
|
Card.set_specific_attributes.uniq!
|
33
33
|
end
|
34
34
|
|
@@ -37,14 +37,11 @@ class Card
|
|
37
37
|
Card::Set.traits[mod] || Card::Set.traits[mod] = {}
|
38
38
|
end
|
39
39
|
|
40
|
-
def add_traits
|
41
|
-
|
42
|
-
|
40
|
+
def add_traits traits, options
|
41
|
+
mod_traits = get_traits self
|
42
|
+
new_opts = new_trait_opts options
|
43
43
|
|
44
|
-
|
45
|
-
new_opts[:default_content] = options[:default] if options[:default]
|
46
|
-
|
47
|
-
args.each do |trait|
|
44
|
+
traits.each do |trait|
|
48
45
|
define_trait_card trait, new_opts
|
49
46
|
define_trait_reader trait if options[:reader]
|
50
47
|
define_trait_writer trait if options[:writer]
|
@@ -53,6 +50,12 @@ class Card
|
|
53
50
|
end
|
54
51
|
end
|
55
52
|
|
53
|
+
def new_trait_opts options
|
54
|
+
%i[type default_content].each_with_object({}).each do |key, hash|
|
55
|
+
hash[key] = options[key] if options[key]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
56
59
|
def define_trait_card trait, opts
|
57
60
|
define_method "#{trait}_card" do
|
58
61
|
fetch trait.to_sym, new: opts.clone, eager_cache: true
|
data/lib/card/subcards/add.rb
CHANGED
@@ -14,6 +14,8 @@ class Card
|
|
14
14
|
# add 'spoiler', content: 'John Snow is a Targaryen'
|
15
15
|
# add card_obj, delayed: true
|
16
16
|
|
17
|
+
include Args
|
18
|
+
|
17
19
|
def << value
|
18
20
|
add value
|
19
21
|
end
|
@@ -61,7 +63,7 @@ class Card
|
|
61
63
|
end
|
62
64
|
|
63
65
|
def new_by_attributes name, attributes={}
|
64
|
-
attributes
|
66
|
+
attributes = attributes&.symbolize_keys || {}
|
65
67
|
absolute_name = absolutize_subcard_name name
|
66
68
|
subcard_args = extract_subcard_args! attributes
|
67
69
|
card = initialize_by_attributes absolute_name, attributes
|
@@ -75,31 +77,8 @@ class Card
|
|
75
77
|
Card.assign_or_newish name, attributes, local_only: true
|
76
78
|
end
|
77
79
|
|
78
|
-
# TODO: this method already exists as card instance method in
|
79
|
-
# tracked_attributes.rb. Find a place for it where its accessible
|
80
|
-
# for both. There is one important difference. The keys are symbols
|
81
|
-
# here instead of strings
|
82
|
-
def extract_subcard_args! args
|
83
|
-
subcards = args.delete(:subcards) || {}
|
84
|
-
if (subfields = args.delete(:subfields))
|
85
|
-
subfields.each_pair do |key, value|
|
86
|
-
subcards[normalize_subfield_key(key)] = value
|
87
|
-
end
|
88
|
-
end
|
89
|
-
args.keys.each do |key|
|
90
|
-
subcards[key] = args.delete(key) if key =~ /^\+/
|
91
|
-
end
|
92
|
-
subcards
|
93
|
-
end
|
94
|
-
|
95
80
|
private
|
96
81
|
|
97
|
-
# ensure a leading '+'
|
98
|
-
def normalize_subfield_key key
|
99
|
-
key = Card::Codename.name(key) if key.is_a?(Symbol) && Card::Codename.exist?(key)
|
100
|
-
key.to_name.prepend_joint
|
101
|
-
end
|
102
|
-
|
103
82
|
# Handles hash with several subcards
|
104
83
|
def multi_add args
|
105
84
|
args.each_pair do |key, val|
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class Card
|
2
|
+
class Subcards
|
3
|
+
# Handling shared subcard args processing
|
4
|
+
module Args
|
5
|
+
def extract_subcard_args! args
|
6
|
+
safe_subcard_args args do |subcards|
|
7
|
+
extract_explicit_subfields subcards, args
|
8
|
+
extract_implicit_subfields subcards, args
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
# FIXME: the following should be handled before it gets this far
|
15
|
+
def safe_subcard_args args
|
16
|
+
subcards = args.delete(:subcards) || {}
|
17
|
+
yield subcards
|
18
|
+
subcards.try(:to_unsafe_h) || subcards
|
19
|
+
end
|
20
|
+
|
21
|
+
def extract_explicit_subfields subcards, args
|
22
|
+
return unless (subfields = args.delete :subfields)
|
23
|
+
|
24
|
+
subfields.each_pair do |key, value|
|
25
|
+
subcards[normalize_subfield_key(key)] = value
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# ensure a leading '+'
|
30
|
+
def normalize_subfield_key key
|
31
|
+
key = Card::Codename.name(key) if key.is_a?(Symbol) && Card::Codename.exist?(key)
|
32
|
+
key.to_name.prepend_joint
|
33
|
+
end
|
34
|
+
|
35
|
+
def extract_implicit_subfields subcards, args
|
36
|
+
args.each_key do |key|
|
37
|
+
subcards[key.to_s] = args.delete(key) if key.to_s.match?(/^\+/)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -14,17 +14,22 @@ class Card
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
def log_file_action path
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
17
|
+
def log_file_action path, &block
|
18
|
+
if File.exist?(path) && !@force
|
19
|
+
log_file_exists path
|
20
|
+
else
|
21
|
+
execute_and_log_file_action path, &block
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def execute_and_log_file_action path
|
26
|
+
status = File.exist?(path) ? "overridden" : "created"
|
27
|
+
yield
|
28
|
+
color_puts status, :green, path
|
29
|
+
end
|
26
30
|
|
27
|
-
|
31
|
+
def log_file_exists path
|
32
|
+
color_puts "file exists (use 'force=true' to override)", :yellow, path
|
28
33
|
end
|
29
34
|
|
30
35
|
# insert content into a file at a given line number
|
data/lib/card/view/options.rb
CHANGED
@@ -30,7 +30,8 @@ class Card
|
|
30
30
|
:nest_syntax, # full nest syntax
|
31
31
|
:wrap, # wrap the nest with a wrapper
|
32
32
|
:show, # render these views when optional
|
33
|
-
:hide
|
33
|
+
:hide, # do not render these views when optional
|
34
|
+
:unknown # view to use if nested card is unknown
|
34
35
|
], # show/hide can be view (Symbol), list of views (Array),
|
35
36
|
# or comma separated views (String)
|
36
37
|
# NOTE: although show and hide are in this non-inheriting group, they are
|
data/lib/card/view/permission.rb
CHANGED
@@ -28,11 +28,22 @@ class Card
|
|
28
28
|
format.view_setting setting_name, view
|
29
29
|
end
|
30
30
|
|
31
|
-
#
|
32
|
-
#
|
31
|
+
# views for unknown cards can be configured in view definitions
|
32
|
+
# or render/nest options (the latter take precedence)
|
33
33
|
def alter_unknown
|
34
|
+
return if card.known?
|
35
|
+
|
36
|
+
unknown_from_options || unknown_from_view_definition
|
37
|
+
end
|
38
|
+
|
39
|
+
def unknown_from_options
|
40
|
+
unknown.to_sym if unknown.present?
|
41
|
+
end
|
42
|
+
|
43
|
+
def unknown_from_view_definition
|
34
44
|
setting = setting(:unknown)
|
35
|
-
return if setting == true
|
45
|
+
return if setting == true # use original view
|
46
|
+
|
36
47
|
setting.is_a?(Symbol) ? setting : format.view_for_unknown(requested_view)
|
37
48
|
end
|
38
49
|
|
data/lib/cardio.rb
CHANGED
@@ -39,70 +39,17 @@ module Cardio
|
|
39
39
|
@cache ||= ::Rails.cache
|
40
40
|
end
|
41
41
|
|
42
|
+
# TODO: many of these defaults should be in mods!
|
42
43
|
def default_configs
|
43
|
-
|
44
|
-
read_only:
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
delaying: nil,
|
50
|
-
|
51
|
-
recaptcha_public_key: nil, # deprecated; use recaptcha_site_key instead
|
52
|
-
recaptcha_private_key: nil, # deprecated; use recaptcha_secret_key instead
|
53
|
-
recaptcha_proxy: nil,
|
54
|
-
recaptcha_site_key: nil,
|
55
|
-
recaptcha_secret_key: nil,
|
56
|
-
recaptcha_minimum_score: 0.5,
|
57
|
-
|
58
|
-
google_analytics_key: nil,
|
59
|
-
|
60
|
-
override_host: nil,
|
61
|
-
override_protocol: nil,
|
62
|
-
|
63
|
-
no_authentication: false,
|
64
|
-
files_web_path: "files",
|
65
|
-
|
66
|
-
max_char_count: 200,
|
67
|
-
max_depth: 20,
|
68
|
-
email_defaults: nil,
|
69
|
-
|
70
|
-
token_expiry: 2.days,
|
71
|
-
acts_per_page: 10,
|
72
|
-
space_last_in_multispace: true,
|
73
|
-
closed_search_limit: 10,
|
74
|
-
paging_limit: 20,
|
75
|
-
|
76
|
-
non_createable_types: [%w[signup setting set session bootswatch_skin customized_bootswatch_skin]], # FIXME
|
77
|
-
view_cache: false,
|
78
|
-
rss_enabled: false,
|
79
|
-
double_click: :signed_in,
|
80
|
-
|
81
|
-
encoding: "utf-8",
|
82
|
-
request_logger: false,
|
83
|
-
performance_logger: false,
|
84
|
-
sql_comments: true,
|
85
|
-
|
86
|
-
file_storage: :local,
|
87
|
-
file_buckets: {},
|
88
|
-
file_default_bucket: nil,
|
89
|
-
protocol_and_host: nil,
|
90
|
-
|
91
|
-
rich_text_editor: :tinymce,
|
92
|
-
|
93
|
-
persistent_cache: true,
|
94
|
-
prepopulate_cache: false,
|
95
|
-
machine_refresh: :cautious, # options: eager, cautious, never
|
96
|
-
compress_javascript: true,
|
97
|
-
|
98
|
-
allow_irreversible_admin_tasks: false,
|
99
|
-
raise_all_rendering_errors: false,
|
100
|
-
rescue_all_in_controller: true,
|
101
|
-
navbox_match_start_only: true,
|
44
|
+
defaults_from_yaml.merge(
|
45
|
+
read_only: !ENV["DECKO_READ_ONLY"].nil?,
|
46
|
+
load_strategy: (ENV["REPO_TMPSETS"] || ENV["TMPSETS"] ? :tmp_files : :eval)
|
47
|
+
)
|
48
|
+
end
|
102
49
|
|
103
|
-
|
104
|
-
|
105
|
-
|
50
|
+
def defaults_from_yaml
|
51
|
+
filename = File.expand_path "cardio/defaults.yml", __dir__
|
52
|
+
YAML.load_file filename
|
106
53
|
end
|
107
54
|
|
108
55
|
def set_config config
|
@@ -136,10 +83,6 @@ module Cardio
|
|
136
83
|
config.watchable_dirs["#{mod_path}/set"] = [:rb]
|
137
84
|
end
|
138
85
|
|
139
|
-
def read_only?
|
140
|
-
!ENV["DECKO_READ_ONLY"].nil?
|
141
|
-
end
|
142
|
-
|
143
86
|
# In production mode set_config gets called twice.
|
144
87
|
# The second call overrides all deck config settings
|
145
88
|
# so don't change settings here if they already exist
|