card-mod-collection 0.14.2 → 0.15.0
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/lib/card/paging_links.rb +96 -0
- data/set/abstract/items.rb +5 -203
- data/set/abstract/paging/paging.haml +12 -0
- data/set/abstract/paging/paging_views.rb +2 -12
- data/set/abstract/paging.rb +8 -0
- data/set/all/item.rb +158 -47
- data/set/all/item_assignment.rb +80 -0
- data/set/all/recursed.rb +41 -0
- metadata +10 -7
- data/set/abstract/paging/paging_links.rb +0 -92
- data/set/all/extended.rb +0 -50
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4f1fef608d54b9031f5d6184c0c8a9b9c00fd18ef81023695a007c1255c1fead
|
4
|
+
data.tar.gz: 879867adb8f43b2baa1c4ca3951ee8d033ce77c90e6835607d772a05b03f173c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0aafb06363d4fcf50451b0580b811a971b697f74b2994d3d149522126ab79f271dd2550c10a1157a89571915dd224f43a940c7e45b54d6aaac096e1c33fd82a5
|
7
|
+
data.tar.gz: 8d5c01287de77db8166125477ced1c518c1491a2ab5a03b8f966ff40a979a8aea1f573372735d182ac41531cd47169246745c005ec90b597f1d8d564c869cc9b
|
@@ -0,0 +1,96 @@
|
|
1
|
+
class Card
|
2
|
+
# generates pagination links
|
3
|
+
class PagingLinks
|
4
|
+
MAX_PAGES = 100
|
5
|
+
|
6
|
+
def initialize total_pages, current_page
|
7
|
+
@total = total_pages
|
8
|
+
@current = current_page
|
9
|
+
end
|
10
|
+
|
11
|
+
# @param window [integer] number of page links shown left and right
|
12
|
+
# of the current page
|
13
|
+
# @example: current page = 5, window = 2
|
14
|
+
# |<<|1|...|3|4|[5]|6|7|...|10|>>|
|
15
|
+
# @yield [text, page, status, options] block to build single paging link
|
16
|
+
# @yieldparam status [Symbol] :active (for current page) or :disabled
|
17
|
+
# @yieldparam page [Integer] page number, first page is 0
|
18
|
+
# @return [Array<String>]
|
19
|
+
def build window=2, &block
|
20
|
+
@render_item = block
|
21
|
+
links window
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def links window
|
27
|
+
@window_start = [@current - window, 0].max
|
28
|
+
@window_end = [@current + window, @total].min
|
29
|
+
left_part + window_part + right_part
|
30
|
+
end
|
31
|
+
|
32
|
+
# the links around the current page
|
33
|
+
def window_part
|
34
|
+
(@window_start..@window_end).map do |page|
|
35
|
+
direct_page_link page
|
36
|
+
end.compact
|
37
|
+
end
|
38
|
+
|
39
|
+
def left_part
|
40
|
+
[
|
41
|
+
previous_page_link,
|
42
|
+
(direct_page_link 0 if @window_start.positive?),
|
43
|
+
(ellipse if @window_start > 1)
|
44
|
+
].compact
|
45
|
+
end
|
46
|
+
|
47
|
+
def right_part
|
48
|
+
parts = [next_page_link]
|
49
|
+
parts.unshift direct_page_link(@total) if add_final_page?
|
50
|
+
parts.unshift ellipse if @total > @window_end + 1
|
51
|
+
parts
|
52
|
+
end
|
53
|
+
|
54
|
+
def add_final_page?
|
55
|
+
@total <= MAX_PAGES && @total > @window_end
|
56
|
+
end
|
57
|
+
|
58
|
+
def previous_page_link
|
59
|
+
paging_item '<span aria-hidden="true">«</span>', previous_page,
|
60
|
+
"aria-label" => "Previous", status: :previous
|
61
|
+
end
|
62
|
+
|
63
|
+
def next_page_link
|
64
|
+
paging_item '<span aria-hidden="true">»</span>', next_page,
|
65
|
+
"aria-label" => "Next", status: :next
|
66
|
+
end
|
67
|
+
|
68
|
+
def direct_page_link page
|
69
|
+
return unless page >= 0 && page <= @total
|
70
|
+
|
71
|
+
paging_item page + 1, page
|
72
|
+
end
|
73
|
+
|
74
|
+
def ellipse
|
75
|
+
paging_item "<span>...</span>", nil, status: :ellipses
|
76
|
+
end
|
77
|
+
|
78
|
+
def paging_item text, page, options={}
|
79
|
+
status =
|
80
|
+
if page == @current
|
81
|
+
:current
|
82
|
+
else
|
83
|
+
options.delete :status
|
84
|
+
end
|
85
|
+
@render_item.call text, page, status, options
|
86
|
+
end
|
87
|
+
|
88
|
+
def previous_page
|
89
|
+
@current.positive? ? @current - 1 : false
|
90
|
+
end
|
91
|
+
|
92
|
+
def next_page
|
93
|
+
@current < @total ? @current + 1 : false
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
data/set/abstract/items.rb
CHANGED
@@ -1,209 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
# While each of the three main methods for returning lists of items can handle arguments,
|
4
|
-
# they are most commonly used without them.
|
5
|
-
|
6
|
-
# @return [Array] list of Card::Name objects
|
7
|
-
# @param args [Hash]
|
8
|
-
# @option args [String] :content override card content
|
9
|
-
# @option args [String, Card::Name, Symbol] :context name in whose context relative items
|
10
|
-
# will be interpreted. For example. +A in context of B is interpreted as B+A
|
11
|
-
# context defaults to pointer card's name. If value is `:raw`, then name is not
|
12
|
-
# contextualized
|
13
|
-
# @option args [String, Integer] :limit max number of cards to return
|
14
|
-
# @option args [String, Integer] :offset begin after the offset-th item
|
15
|
-
def item_names args={}
|
16
|
-
context = args[:context]
|
17
|
-
item_strings(args).map do |item|
|
18
|
-
clean_item_name item, context
|
19
|
-
end.compact
|
20
|
-
end
|
21
|
-
|
22
|
-
def first_name args={}
|
23
|
-
item_names(args).first
|
24
|
-
end
|
25
|
-
|
26
|
-
def first_card args={}
|
27
|
-
return unless (name = first_name)
|
28
|
-
|
29
|
-
fetch_item_card name, args
|
30
|
-
end
|
31
|
-
|
32
|
-
def first_code
|
33
|
-
first_card&.codename
|
34
|
-
end
|
35
|
-
|
36
|
-
def first_id
|
37
|
-
first_card&.id
|
38
|
-
end
|
39
|
-
|
40
|
-
# @return [Array] list of integers (card ids of items)
|
41
|
-
# @param args [Hash] see #item_names
|
42
|
-
def item_ids args={}
|
43
|
-
item_names(args).map(&:card_id).compact
|
44
|
-
end
|
45
|
-
|
46
|
-
def item_cards args={}
|
47
|
-
standard_item_cards args
|
48
|
-
end
|
49
|
-
|
50
|
-
# @return [Array] list of Card objects
|
51
|
-
# @param args [Hash] see #item_names for additional options
|
52
|
-
# @option args [String] :complete keyword to use in searching among items
|
53
|
-
# @option args [True/False] :known_only if true, return only known cards
|
54
|
-
# @option args [String] :type name of type to be used for unknown cards
|
55
|
-
def standard_item_cards args={}
|
56
|
-
return item_cards_search(args) if args[:complete]
|
57
|
-
return known_item_cards(args) if args[:known_only]
|
58
|
-
|
59
|
-
all_item_cards args
|
60
|
-
end
|
61
|
-
|
62
|
-
# #item_name, #item_id, and #item_card each return a single item, rather than an array.
|
63
|
-
%i[name id card].each do |obj|
|
64
|
-
define_method "item_#{obj}" do |args={}|
|
65
|
-
send("item_#{obj}s", args.merge(limit: 1)).first
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
# for override, eg by json
|
70
|
-
def item_value item_name
|
71
|
-
item_name
|
72
|
-
end
|
73
|
-
|
74
|
-
# ~~~~~~~~~~~~ ALTERING ITEMS ~~~~~~~~~~~~
|
75
|
-
|
76
|
-
# set card content based on array and save card
|
77
|
-
# @param array [Array] list of strings/names (Cardish)
|
78
|
-
def items= array
|
79
|
-
self.content = array
|
80
|
-
save!
|
81
|
-
end
|
82
|
-
|
83
|
-
# append item to list (does not save)
|
84
|
-
# @param cardish [Cardish]
|
85
|
-
def << cardish
|
86
|
-
add_item cardish
|
87
|
-
end
|
88
|
-
|
89
|
-
# append item to list (does not save)
|
90
|
-
# @param cardish [String, Card::Name] item name
|
91
|
-
# @param allow_duplicates [True/False] permit duplicate items (default is False)
|
92
|
-
def add_item cardish, allow_duplicates=false
|
93
|
-
return if !allow_duplicates && include_item?(cardish)
|
94
|
-
|
95
|
-
self.content = (item_strings << cardish)
|
96
|
-
end
|
97
|
-
|
98
|
-
# append item to list and save card
|
99
|
-
# @param name [String, Card::Name] item name
|
100
|
-
def add_item! name
|
101
|
-
add_item(name) && save!
|
102
|
-
end
|
103
|
-
|
104
|
-
# remove item from list
|
105
|
-
# @param cardish [String, Card::Name] item to drop
|
106
|
-
def drop_item cardish
|
107
|
-
drop_item_name = Card::Name[cardish]
|
108
|
-
self.content = (item_names.reject { |item_name| item_name == drop_item_name })
|
1
|
+
def recursable_items?
|
2
|
+
true
|
109
3
|
end
|
110
4
|
|
111
|
-
|
112
|
-
# @param cardish [String, Card::Name] item to drop
|
113
|
-
def drop_item! cardish
|
114
|
-
drop_item cardish
|
115
|
-
save!
|
116
|
-
end
|
117
|
-
|
118
|
-
# insert item into list at specified location
|
119
|
-
# @param index [Integer] Array index in which to insert item (0 is first)
|
120
|
-
# @param name [String, Card::Name] item name
|
121
|
-
def insert_item index, name
|
122
|
-
new_names = item_names
|
123
|
-
new_names.delete name
|
124
|
-
new_names.insert index, name
|
125
|
-
self.content = new_names
|
126
|
-
end
|
127
|
-
|
128
|
-
# insert item into list at specified location and save
|
129
|
-
# @param index [Integer] Array index in which to insert item (0 is first)
|
130
|
-
# @param name [String, Card::Name] item name
|
131
|
-
def insert_item! index, name
|
132
|
-
insert_item index, name
|
133
|
-
save!
|
134
|
-
end
|
135
|
-
|
136
|
-
# ~~~~~~~~~~~~ READING ITEM HELPERS ~~~~~~~~~~~~
|
137
|
-
|
138
|
-
# Warning: the following methods, while available for use, may be subject to change
|
139
|
-
|
140
|
-
# #item_cards helpers
|
141
|
-
|
142
|
-
def item_cards_search query
|
143
|
-
Card::Query.run query.reverse_merge(referred_to_by: name, limit: 0)
|
144
|
-
end
|
145
|
-
|
146
|
-
def known_item_cards args={}
|
147
|
-
item_names(args).map { |name| Card.fetch name }.compact
|
148
|
-
end
|
149
|
-
|
150
|
-
def all_item_cards args={}
|
151
|
-
names = args[:item_names] || item_names(args)
|
152
|
-
names.map { |name| fetch_item_card name, args }
|
153
|
-
end
|
154
|
-
|
155
|
-
# TODO: support type_code and type_id. (currently type)
|
156
|
-
# uses name, because its most common use is from CQL
|
157
|
-
def item_type
|
5
|
+
def item_type_id
|
158
6
|
opt = options_card
|
159
7
|
# FIXME: need better recursion prevention
|
160
|
-
return
|
161
|
-
|
162
|
-
opt.item_type
|
163
|
-
end
|
164
|
-
|
165
|
-
def item_strings args={}
|
166
|
-
items = raw_item_strings(args[:content] || content)
|
167
|
-
return items unless args.present?
|
168
|
-
|
169
|
-
filtered_items items, limit: args[:limit], offset: args[:offset]
|
170
|
-
end
|
171
|
-
|
172
|
-
def raw_item_strings content
|
173
|
-
content.to_s.split(/\n+/).map { |i| strip_item i }
|
174
|
-
end
|
175
|
-
|
176
|
-
private
|
177
|
-
|
178
|
-
def filtered_items items, limit: 0, offset: 0
|
179
|
-
limit = limit.to_i
|
180
|
-
offset = offset.to_i
|
181
|
-
return items unless limit.positive? || offset.positive?
|
182
|
-
|
183
|
-
items[offset, (limit.zero? ? items.size : limit)] || []
|
184
|
-
end
|
185
|
-
|
186
|
-
def fetch_item_card name, args={}
|
187
|
-
Card.fetch name, new: new_unknown_item_args(args)
|
188
|
-
end
|
189
|
-
|
190
|
-
def new_unknown_item_args args
|
191
|
-
itype = args[:type] || item_type
|
192
|
-
itype ? { type: itype } : {}
|
193
|
-
end
|
194
|
-
|
195
|
-
def clean_item_name item, context
|
196
|
-
item = item.to_name
|
197
|
-
return item if context == :raw
|
198
|
-
|
199
|
-
context ||= context_card.name
|
200
|
-
item.absolute_name context
|
201
|
-
rescue Card::Error::NotFound
|
202
|
-
# eg for invalid ids or codenames
|
203
|
-
# "Invalid Item: #{item}".to_name
|
204
|
-
nil
|
205
|
-
end
|
8
|
+
return unless opt && opt != self
|
206
9
|
|
207
|
-
|
208
|
-
item.gsub(/\[\[|\]\]/, "").strip
|
10
|
+
opt.item_type_id
|
209
11
|
end
|
@@ -3,21 +3,11 @@ format :html do
|
|
3
3
|
|
4
4
|
def with_paging path_args={}
|
5
5
|
with_paging_path_args path_args do
|
6
|
-
output [yield(@paging_path_args),
|
6
|
+
output [yield(@paging_path_args), render_paging]
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
|
-
view :paging, cache: :never
|
11
|
-
return "" unless paging_needed?
|
12
|
-
|
13
|
-
<<-HTML
|
14
|
-
<nav>
|
15
|
-
<ul class="pagination paging">
|
16
|
-
#{paging_links.join}
|
17
|
-
</ul>
|
18
|
-
</nav>
|
19
|
-
HTML
|
20
|
-
end
|
10
|
+
view :paging, cache: :never, template: :haml
|
21
11
|
|
22
12
|
def paging_links
|
23
13
|
PagingLinks.new(total_pages, current_page).build do |text, page, status, options|
|
data/set/abstract/paging.rb
CHANGED
@@ -17,6 +17,10 @@ format do
|
|
17
17
|
@count_with_params ||= card.item_names.count
|
18
18
|
end
|
19
19
|
|
20
|
+
def no_results?
|
21
|
+
count_with_params.zero?
|
22
|
+
end
|
23
|
+
|
20
24
|
def total_pages
|
21
25
|
return 1 if limit.zero?
|
22
26
|
|
@@ -32,6 +36,10 @@ format do
|
|
32
36
|
{}
|
33
37
|
end
|
34
38
|
|
39
|
+
def last_item_on_page
|
40
|
+
[count_with_params, (offset + limit)].min
|
41
|
+
end
|
42
|
+
|
35
43
|
private
|
36
44
|
|
37
45
|
def contextual_param param
|
data/set/all/item.rb
CHANGED
@@ -1,84 +1,114 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# ITEM LISTS
|
2
|
+
|
3
|
+
# Note: while most methods for returning lists of items can handle arguments,
|
4
|
+
# they are most commonly used without them.
|
5
|
+
|
6
|
+
# @return [Array] list of Card::Name objects
|
7
|
+
# @param args [Hash]
|
8
|
+
# @option args [String] :content override card content
|
9
|
+
# @option args [String, Card::Name, Symbol] :context name in whose context relative items
|
10
|
+
# will be interpreted. For example. +A in context of B is interpreted as B+A
|
11
|
+
# context defaults to pointer card's name. If value is `:raw`, then name is not
|
12
|
+
# contextualized
|
13
|
+
# @option args [String, Integer] :limit max number of cards to return
|
14
|
+
# @option args [String, Integer] :offset begin after the offset-th item
|
15
|
+
def item_names args={}
|
16
|
+
context = args[:context]
|
17
|
+
item_strings(args).map do |item|
|
18
|
+
clean_item_name item, context
|
19
|
+
end.compact
|
3
20
|
end
|
4
21
|
|
5
|
-
#
|
6
|
-
|
7
|
-
|
22
|
+
# @return [Array] list of cards
|
23
|
+
# @param args [Hash] see #item_names
|
24
|
+
def item_cards args={}
|
25
|
+
standard_item_cards args
|
8
26
|
end
|
9
27
|
|
10
|
-
|
11
|
-
|
28
|
+
# @return [Array] list of integers (card ids of items)
|
29
|
+
# @param args [Hash] see #item_names
|
30
|
+
def item_ids args={}
|
31
|
+
item_names(args).map(&:card_id).compact
|
12
32
|
end
|
13
33
|
|
34
|
+
# @return [Array] of String objects
|
35
|
+
# @param args [Hash] see #item_names
|
14
36
|
def item_keys args={}
|
15
37
|
item_names(args).map do |item|
|
16
38
|
item.to_name.key
|
17
39
|
end
|
18
40
|
end
|
19
41
|
|
20
|
-
|
21
|
-
|
22
|
-
|
42
|
+
# @return [Array] of String objects
|
43
|
+
# @param args [Hash] see #item_names
|
44
|
+
def item_strings args={}
|
45
|
+
items = raw_item_strings(args[:content] || content)
|
46
|
+
return items unless args.present?
|
23
47
|
|
24
|
-
|
25
|
-
standardized_items(array).to_pointer_content
|
48
|
+
filtered_items items, limit: args[:limit], offset: args[:offset]
|
26
49
|
end
|
27
50
|
|
28
|
-
|
29
|
-
array.map { |i| standardize_item i }.reject(&:blank?)
|
30
|
-
end
|
51
|
+
# SINGLE ITEM
|
31
52
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
53
|
+
# @return [Card::Name]
|
54
|
+
# @param args [Hash] see #item_names
|
55
|
+
def first_name args={}
|
56
|
+
item_names(args).first
|
36
57
|
end
|
37
58
|
|
38
|
-
|
39
|
-
|
59
|
+
# @return [Card]
|
60
|
+
# @param args [Hash] see #item_names
|
61
|
+
def first_card args={}
|
62
|
+
return unless (name = first_name)
|
63
|
+
|
64
|
+
fetch_item_card name, args
|
40
65
|
end
|
41
66
|
|
42
|
-
|
43
|
-
|
67
|
+
# @return [Symbol]
|
68
|
+
# @param args [Hash] see #item_names
|
69
|
+
def first_code args={}
|
70
|
+
first_card(args)&.codename
|
44
71
|
end
|
45
72
|
|
46
|
-
|
47
|
-
|
48
|
-
|
73
|
+
# @return [Integer]
|
74
|
+
# @param args [Hash] see #item_names
|
75
|
+
def first_id args={}
|
76
|
+
first_name(args)&.card_id
|
49
77
|
end
|
50
78
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
79
|
+
# ITEM TYPES
|
80
|
+
|
81
|
+
# typically override EITHER #item_type_id OR #item_type_name
|
82
|
+
def item_type_id
|
83
|
+
@item_type_id ||= no_item_type_recursion { item_type_name&.card_id }
|
56
84
|
end
|
57
85
|
|
58
|
-
def
|
59
|
-
|
86
|
+
def item_type_name
|
87
|
+
@item_type_name ||= no_item_type_recursion { item_type_id&.cardname }
|
88
|
+
end
|
60
89
|
|
61
|
-
|
62
|
-
|
90
|
+
def item_type_card
|
91
|
+
item_type_id&.card
|
63
92
|
end
|
64
93
|
|
65
|
-
#
|
66
|
-
|
67
|
-
def
|
68
|
-
|
94
|
+
# MISC
|
95
|
+
|
96
|
+
def item_count args={}
|
97
|
+
item_names(args).size
|
69
98
|
end
|
70
99
|
|
71
|
-
def
|
72
|
-
|
100
|
+
def include_item? item
|
101
|
+
item_names.include? Card::Name[item]
|
73
102
|
end
|
74
103
|
|
75
|
-
|
76
|
-
|
104
|
+
# for override, eg by json
|
105
|
+
def item_value item_name
|
106
|
+
item_name
|
77
107
|
end
|
78
108
|
|
79
109
|
format do
|
80
|
-
|
81
|
-
|
110
|
+
view :count do
|
111
|
+
card.item_count
|
82
112
|
end
|
83
113
|
|
84
114
|
def nest_item cardish, options={}, &block
|
@@ -87,6 +117,12 @@ format do
|
|
87
117
|
nest cardish, options, &block
|
88
118
|
end
|
89
119
|
|
120
|
+
def item_links args={}
|
121
|
+
card.item_cards(args).map do |item_card|
|
122
|
+
nest_item item_card, view: :link
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
90
126
|
def implicit_item_view
|
91
127
|
view = voo_items_view || default_item_view
|
92
128
|
Card::View.normalize view
|
@@ -113,8 +149,8 @@ format do
|
|
113
149
|
def determine_item_view_options_type options
|
114
150
|
return if options[:type]
|
115
151
|
|
116
|
-
|
117
|
-
options[:type] =
|
152
|
+
type_name = card.item_type_name
|
153
|
+
options[:type] = type_name if type_name
|
118
154
|
end
|
119
155
|
|
120
156
|
def listing listing_cards, item_args={}
|
@@ -135,3 +171,78 @@ format :html do
|
|
135
171
|
%(<div class="item-#{item_view}">#{rendered}</div>)
|
136
172
|
end
|
137
173
|
end
|
174
|
+
|
175
|
+
private
|
176
|
+
|
177
|
+
def raw_item_strings content
|
178
|
+
content.to_s.split(/\n+/).map { |i| strip_item i }
|
179
|
+
end
|
180
|
+
|
181
|
+
# FIXME: complete should be handled at the name or string level
|
182
|
+
# (and might not really need to use Card::Query here, though it
|
183
|
+
# should in search cards)
|
184
|
+
|
185
|
+
# @return [Array] list of Card objects
|
186
|
+
# @param args [Hash] see #item_names for additional options
|
187
|
+
# @option args [String] :complete keyword to use in searching among items
|
188
|
+
# @option args [True/False] :known_only if true, return only known cards
|
189
|
+
# @option args [String] :type name of type to be used for unknown cards
|
190
|
+
def standard_item_cards args={}
|
191
|
+
return item_cards_search(args) if args[:complete]
|
192
|
+
return known_item_cards(args) if args[:known_only]
|
193
|
+
|
194
|
+
all_item_cards args
|
195
|
+
end
|
196
|
+
|
197
|
+
def no_item_type_recursion
|
198
|
+
return nil if @item_type_lookup
|
199
|
+
|
200
|
+
@item_type_lookup = true
|
201
|
+
yield
|
202
|
+
end
|
203
|
+
|
204
|
+
def item_cards_search query
|
205
|
+
Card::Query.run query.reverse_merge(referred_to_by: name, limit: 0)
|
206
|
+
end
|
207
|
+
|
208
|
+
def known_item_cards args={}
|
209
|
+
item_names(args).map { |name| Card.fetch name }.compact
|
210
|
+
end
|
211
|
+
|
212
|
+
def all_item_cards args={}
|
213
|
+
names = args[:item_names] || item_names(args)
|
214
|
+
names.map { |name| fetch_item_card name, args }
|
215
|
+
end
|
216
|
+
|
217
|
+
def fetch_item_card name, args={}
|
218
|
+
Card.fetch name, new: new_unknown_item_args(args)
|
219
|
+
end
|
220
|
+
|
221
|
+
def new_unknown_item_args args
|
222
|
+
itype = args[:type] || item_type_name
|
223
|
+
itype ? { type: itype } : {}
|
224
|
+
end
|
225
|
+
|
226
|
+
def filtered_items items, limit: 0, offset: 0
|
227
|
+
limit = limit.to_i
|
228
|
+
offset = offset.to_i
|
229
|
+
return items unless limit.positive? || offset.positive?
|
230
|
+
|
231
|
+
items[offset, (limit.zero? ? items.size : limit)] || []
|
232
|
+
end
|
233
|
+
|
234
|
+
def clean_item_name item, context
|
235
|
+
item = item.to_name
|
236
|
+
return item if context == :raw
|
237
|
+
|
238
|
+
context ||= context_card.name
|
239
|
+
item.absolute_name context
|
240
|
+
rescue Card::Error::NotFound
|
241
|
+
# eg for invalid ids or codenames
|
242
|
+
# "Invalid Item: #{item}".to_name
|
243
|
+
nil
|
244
|
+
end
|
245
|
+
|
246
|
+
def strip_item item
|
247
|
+
item.gsub(/\[\[|\]\]/, "").strip
|
248
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# set card content based on array and save card
|
2
|
+
# @param array [Array] list of strings/names (Cardish)
|
3
|
+
def items= array
|
4
|
+
self.content = array
|
5
|
+
save!
|
6
|
+
end
|
7
|
+
|
8
|
+
# append item to list (does not save)
|
9
|
+
# @param cardish [Cardish]
|
10
|
+
def << cardish
|
11
|
+
add_item cardish
|
12
|
+
end
|
13
|
+
|
14
|
+
# append item to list (does not save)
|
15
|
+
# @param cardish [String, Card::Name] item name
|
16
|
+
# @param allow_duplicates [True/False] permit duplicate items (default is False)
|
17
|
+
def add_item cardish, allow_duplicates=false
|
18
|
+
return if !allow_duplicates && include_item?(cardish)
|
19
|
+
|
20
|
+
self.content = (item_strings << cardish)
|
21
|
+
end
|
22
|
+
|
23
|
+
# append item to list and save card
|
24
|
+
# @param name [String, Card::Name] item name
|
25
|
+
def add_item! name
|
26
|
+
add_item(name) && save!
|
27
|
+
end
|
28
|
+
|
29
|
+
# remove item from list
|
30
|
+
# @param cardish [String, Card::Name] item to drop
|
31
|
+
def drop_item item
|
32
|
+
item_name = item.cardname
|
33
|
+
self.content = (item_names.reject { |i| i == item_name })
|
34
|
+
end
|
35
|
+
|
36
|
+
# remove item from list and save card
|
37
|
+
# @param cardish [String, Card::Name] item to drop
|
38
|
+
def drop_item! cardish
|
39
|
+
drop_item cardish
|
40
|
+
save!
|
41
|
+
end
|
42
|
+
|
43
|
+
# insert item into list at specified location
|
44
|
+
# @param index [Integer] Array index in which to insert item (0 is first)
|
45
|
+
# @param name [String, Card::Name] item name
|
46
|
+
def insert_item index, name
|
47
|
+
new_names = item_names
|
48
|
+
new_names.delete name
|
49
|
+
new_names.insert index, name
|
50
|
+
self.content = new_names
|
51
|
+
end
|
52
|
+
|
53
|
+
# insert item into list at specified location and save
|
54
|
+
# @param index [Integer] Array index in which to insert item (0 is first)
|
55
|
+
# @param name [String, Card::Name] item name
|
56
|
+
def insert_item! index, name
|
57
|
+
insert_item index, name
|
58
|
+
save!
|
59
|
+
end
|
60
|
+
|
61
|
+
def replace_item old, new
|
62
|
+
return unless include_item? old
|
63
|
+
|
64
|
+
drop_item old
|
65
|
+
add_item new
|
66
|
+
end
|
67
|
+
|
68
|
+
def items_content array
|
69
|
+
standardized_items(array).to_pointer_content
|
70
|
+
end
|
71
|
+
|
72
|
+
def standardized_items array
|
73
|
+
array.map { |i| standardize_item i }.reject(&:blank?)
|
74
|
+
end
|
75
|
+
|
76
|
+
def standardize_item item
|
77
|
+
Card::Name[item]
|
78
|
+
rescue Card::Error::NotFound
|
79
|
+
item
|
80
|
+
end
|
data/set/all/recursed.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
def recursed_item_cards context=nil
|
2
|
+
list = []
|
3
|
+
book = ::Set.new # avoid loops
|
4
|
+
items =
|
5
|
+
recursable_items? ? item_cards(limit: "", context: (context&.name || name)) : [self]
|
6
|
+
recurse_item_list items, list, book until items.empty?
|
7
|
+
list
|
8
|
+
end
|
9
|
+
|
10
|
+
def recursed_item_contents context=nil
|
11
|
+
recursed_item_cards(context).map(&:item_names).flatten
|
12
|
+
end
|
13
|
+
|
14
|
+
def recursable_items?
|
15
|
+
false
|
16
|
+
end
|
17
|
+
|
18
|
+
format do
|
19
|
+
delegate :recursed_item_contents, to: :card
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def recurse_item_list items, list, book
|
25
|
+
item = items.shift
|
26
|
+
return if already_recursed?(item, book)
|
27
|
+
|
28
|
+
if item.recursable_items?
|
29
|
+
# keep items in order
|
30
|
+
items.unshift(*item.item_cards.compact)
|
31
|
+
else # no further level of items
|
32
|
+
list << item
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def already_recursed? item, book
|
37
|
+
return true if book.include? item
|
38
|
+
|
39
|
+
book << item
|
40
|
+
false
|
41
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: card-mod-collection
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.15.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ethan McCutchen
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2023-01-04 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: card
|
@@ -18,14 +18,14 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - '='
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 1.
|
21
|
+
version: 1.105.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
requirements:
|
26
26
|
- - '='
|
27
27
|
- !ruby/object:Gem::Version
|
28
|
-
version: 1.
|
28
|
+
version: 1.105.0
|
29
29
|
description: ''
|
30
30
|
email:
|
31
31
|
- info@decko.org
|
@@ -33,12 +33,14 @@ executables: []
|
|
33
33
|
extensions: []
|
34
34
|
extra_rdoc_files: []
|
35
35
|
files:
|
36
|
+
- lib/card/paging_links.rb
|
36
37
|
- set/abstract/items.rb
|
37
38
|
- set/abstract/paging.rb
|
38
|
-
- set/abstract/paging/
|
39
|
+
- set/abstract/paging/paging.haml
|
39
40
|
- set/abstract/paging/paging_views.rb
|
40
|
-
- set/all/extended.rb
|
41
41
|
- set/all/item.rb
|
42
|
+
- set/all/item_assignment.rb
|
43
|
+
- set/all/recursed.rb
|
42
44
|
homepage: https://decko.org
|
43
45
|
licenses:
|
44
46
|
- GPL-3.0
|
@@ -49,6 +51,7 @@ metadata:
|
|
49
51
|
wiki_uri: https://decko.org
|
50
52
|
documentation_url: http://docs.decko.org/
|
51
53
|
card-mod: collection
|
54
|
+
card-mod-group: gem-defaults
|
52
55
|
post_install_message:
|
53
56
|
rdoc_options: []
|
54
57
|
require_paths:
|
@@ -64,7 +67,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
64
67
|
- !ruby/object:Gem::Version
|
65
68
|
version: '0'
|
66
69
|
requirements: []
|
67
|
-
rubygems_version: 3.
|
70
|
+
rubygems_version: 3.3.11
|
68
71
|
signing_key:
|
69
72
|
specification_version: 4
|
70
73
|
summary: collection (list and search)
|
@@ -1,92 +0,0 @@
|
|
1
|
-
#! no set module
|
2
|
-
|
3
|
-
# render paging links
|
4
|
-
class PagingLinks
|
5
|
-
MAX_PAGES = 100
|
6
|
-
|
7
|
-
def initialize total_pages, current_page
|
8
|
-
@total = total_pages
|
9
|
-
@current = current_page
|
10
|
-
end
|
11
|
-
|
12
|
-
# @param window [integer] number of page links shown left and right
|
13
|
-
# of the current page
|
14
|
-
# @example: current page = 5, window = 2
|
15
|
-
# |<<|1|...|3|4|[5]|6|7|...|10|>>|
|
16
|
-
# @yield [text, page, status, options] block to build single paging link
|
17
|
-
# @yieldparam status [Symbol] :active (for current page) or :disabled
|
18
|
-
# @yieldparam page [Integer] page number, first page is 0
|
19
|
-
# @return [Array<String>]
|
20
|
-
def build window=2, &block
|
21
|
-
@render_item = block
|
22
|
-
links window
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
def links window
|
28
|
-
@window_start = [@current - window, 0].max
|
29
|
-
@window_end = [@current + window, @total].min
|
30
|
-
left_part + window_part + right_part
|
31
|
-
end
|
32
|
-
|
33
|
-
# the links around the current page
|
34
|
-
def window_part
|
35
|
-
(@window_start..@window_end).map do |page|
|
36
|
-
direct_page_link page
|
37
|
-
end.compact
|
38
|
-
end
|
39
|
-
|
40
|
-
def left_part
|
41
|
-
[
|
42
|
-
previous_page_link,
|
43
|
-
(direct_page_link 0 if @window_start.positive?),
|
44
|
-
(ellipse if @window_start > 1)
|
45
|
-
].compact
|
46
|
-
end
|
47
|
-
|
48
|
-
def right_part
|
49
|
-
parts = [next_page_link]
|
50
|
-
parts.unshift direct_page_link(@total) if @total <= MAX_PAGES && @total > @window_end
|
51
|
-
parts.unshift ellipse if @total > @window_end + 1
|
52
|
-
parts
|
53
|
-
end
|
54
|
-
|
55
|
-
def previous_page_link
|
56
|
-
paging_item '<span aria-hidden="true">«</span>', previous_page,
|
57
|
-
"aria-label" => "Previous", status: :previous
|
58
|
-
end
|
59
|
-
|
60
|
-
def next_page_link
|
61
|
-
paging_item '<span aria-hidden="true">»</span>', next_page,
|
62
|
-
"aria-label" => "Next", status: :next
|
63
|
-
end
|
64
|
-
|
65
|
-
def direct_page_link page
|
66
|
-
return unless page >= 0 && page <= @total
|
67
|
-
|
68
|
-
paging_item page + 1, page
|
69
|
-
end
|
70
|
-
|
71
|
-
def ellipse
|
72
|
-
paging_item "<span>...</span>", nil, status: :ellipses
|
73
|
-
end
|
74
|
-
|
75
|
-
def paging_item text, page, options={}
|
76
|
-
status =
|
77
|
-
if page == @current
|
78
|
-
:current
|
79
|
-
else
|
80
|
-
options.delete :status
|
81
|
-
end
|
82
|
-
@render_item.call text, page, status, options
|
83
|
-
end
|
84
|
-
|
85
|
-
def previous_page
|
86
|
-
@current.positive? ? @current - 1 : false
|
87
|
-
end
|
88
|
-
|
89
|
-
def next_page
|
90
|
-
@current < @total ? @current + 1 : false
|
91
|
-
end
|
92
|
-
end
|
data/set/all/extended.rb
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
def extended_item_cards context=nil
|
2
|
-
items = item_cards limit: "", context: (context || self).name
|
3
|
-
list = []
|
4
|
-
book = ::Set.new # avoid loops
|
5
|
-
extend_item_list items, list, book until items.empty?
|
6
|
-
list
|
7
|
-
end
|
8
|
-
|
9
|
-
def extended_item_contents context=nil
|
10
|
-
extended_item_cards(context).map(&:item_names).flatten
|
11
|
-
end
|
12
|
-
|
13
|
-
format do
|
14
|
-
delegate :extended_item_contents, to: :card
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def extend_item_list items, list, book
|
20
|
-
item = items.shift
|
21
|
-
return if already_extended?(item, book)
|
22
|
-
|
23
|
-
if item.collection?
|
24
|
-
# keep items in order
|
25
|
-
items.unshift(*item.item_cards.compact)
|
26
|
-
else # no further level of items
|
27
|
-
list << item
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def already_extended? item, book
|
32
|
-
return true if book.include? item
|
33
|
-
|
34
|
-
book << item
|
35
|
-
false
|
36
|
-
end
|
37
|
-
|
38
|
-
# def extended_list context=nil
|
39
|
-
# context = (context ? context.name : name)
|
40
|
-
# args = { limit: "" }
|
41
|
-
# item_cards(args.merge(context: context)).map do |x|
|
42
|
-
# x.item_cards(args)
|
43
|
-
# end.flatten.map do |x|
|
44
|
-
# x.item_cards(args)
|
45
|
-
# end.flatten.map do |y|
|
46
|
-
# y.item_names(args)
|
47
|
-
# end.flatten
|
48
|
-
# # this could go on and on. more elegant to recurse until you don't have
|
49
|
-
# # a collection
|
50
|
-
# end
|