card-mod-list 0.11.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 +7 -0
- data/db/migrate_core_cards/20160804112340_add_pointer_cards.rb +9 -0
- data/set/abstract/01_pointer.rb +10 -0
- data/set/abstract/01_pointer/events.rb +71 -0
- data/set/abstract/01_pointer/html_views.rb +123 -0
- data/set/abstract/01_pointer/html_views/autocomplete_input.haml +3 -0
- data/set/abstract/01_pointer/html_views/checkbox_input.haml +8 -0
- data/set/abstract/01_pointer/html_views/filter.rb +62 -0
- data/set/abstract/01_pointer/html_views/filter/filter_items.haml +28 -0
- data/set/abstract/01_pointer/html_views/filter/filtered_list_input.haml +21 -0
- data/set/abstract/01_pointer/html_views/list_input.haml +16 -0
- data/set/abstract/01_pointer/html_views/list_item.haml +12 -0
- data/set/abstract/01_pointer/html_views/radio_input.haml +13 -0
- data/set/abstract/01_pointer/options_api.rb +78 -0
- data/set/abstract/01_pointer/other_views.rb +102 -0
- data/set/abstract/code_pointer.rb +35 -0
- data/set/abstract/id_pointer.rb +21 -0
- data/set/all/supports_content_options.rb +7 -0
- data/set/right/content_option_view.rb +10 -0
- data/set/right/content_options.rb +23 -0
- data/set/self/content_option_view.rb +9 -0
- data/set/self/content_options.rb +9 -0
- data/set/self/input_options.rb +13 -0
- data/set/type/link_list.rb +40 -0
- data/set/type/link_list/link_list_input.haml +24 -0
- data/set/type/list.rb +16 -0
- data/set/type/nest_list.rb +46 -0
- data/set/type/nest_list/nest_list_input.haml +28 -0
- data/set/type/pointer.rb +10 -0
- metadata +116 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a0d458cf092c0f324ec963f3bbee7e8c72d0c418aa19703fdc6d76d9f501e8e6
|
4
|
+
data.tar.gz: ec7e3011dccbbc15a1be9ca841625cf61c83bfbbb6653e4f9688d3de0869aa41
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 63e316144f8954ca5df190117baefaad4b8e5183e0fd47753f0dfdaba30749df52e97d8d1868690f101994617c9b8815f4f7d1ad431496eee464da323f91822e
|
7
|
+
data.tar.gz: d55af462a1c12e8890f36584a387e23db5787dd7024a298eee4448db755d1cbf23e6199ac55e6c5e10a39fb8df9c100827ccbc7ba8592537e36de9da777ed452
|
@@ -0,0 +1,71 @@
|
|
1
|
+
event :add_and_drop_items, :prepare_to_validate, on: :save do
|
2
|
+
adds = Env.params["add_item"]
|
3
|
+
drops = Env.params["drop_item"]
|
4
|
+
Array.wrap(adds).each { |i| add_item i } if adds
|
5
|
+
Array.wrap(drops).each { |i| drop_item i } if drops
|
6
|
+
end
|
7
|
+
|
8
|
+
event :insert_item_event, :prepare_to_validate, on: :save, when: :item_to_insert do
|
9
|
+
index = Env.params["item_index"] || 0
|
10
|
+
insert_item index.to_i, item_to_insert
|
11
|
+
end
|
12
|
+
|
13
|
+
def item_to_insert
|
14
|
+
Env.params["insert_item"]
|
15
|
+
end
|
16
|
+
|
17
|
+
# If a card's type and content are updated in the same action, the new module
|
18
|
+
# will override the old module's events and functions. But this event is only
|
19
|
+
# on pointers -- other type cards do not have this event,
|
20
|
+
# Therefore if something is changed from a pointer and its content is changed
|
21
|
+
# in the same action, this event will be run and will treat the content like
|
22
|
+
# it' still pointer content. The "when" clause helps with that (but is a hack)
|
23
|
+
event :standardize_items, :prepare_to_validate,
|
24
|
+
on: :save, changed: :content, when: :still_pointer? do
|
25
|
+
items_to_content item_strings
|
26
|
+
end
|
27
|
+
|
28
|
+
def still_pointer?
|
29
|
+
type_id == PointerID
|
30
|
+
# Card.new(type_id: type_id).is_a? Abstract::Pointer
|
31
|
+
end
|
32
|
+
|
33
|
+
def changed_item_names
|
34
|
+
dropped_item_names + added_item_names
|
35
|
+
end
|
36
|
+
|
37
|
+
def dropped_item_names
|
38
|
+
return item_names if trash
|
39
|
+
return [] unless (old_content = db_content_before_act)
|
40
|
+
|
41
|
+
old_items = item_names content: old_content
|
42
|
+
old_items - item_names
|
43
|
+
end
|
44
|
+
|
45
|
+
def added_item_names
|
46
|
+
return [] if trash
|
47
|
+
return item_names unless (old_content = db_content_before_act)
|
48
|
+
|
49
|
+
old_items = item_names content: old_content
|
50
|
+
item_names - old_items
|
51
|
+
end
|
52
|
+
|
53
|
+
# TODO: refactor. many of the above could be written more elegantly with improved
|
54
|
+
# handling of :content in item_names. If content is nil here, we would expect an
|
55
|
+
# empty set of cards, but in fact we get items based on self.content.
|
56
|
+
|
57
|
+
def changed_item_cards
|
58
|
+
dropped_item_cards + added_item_cards
|
59
|
+
end
|
60
|
+
|
61
|
+
def dropped_item_cards
|
62
|
+
return [] unless db_content_before_act
|
63
|
+
|
64
|
+
all_item_cards item_names: dropped_item_names
|
65
|
+
end
|
66
|
+
|
67
|
+
def added_item_cards
|
68
|
+
return item_cards unless db_content_before_act
|
69
|
+
|
70
|
+
all_item_cards item_names: added_item_names
|
71
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
format :html do
|
2
|
+
view :core, cache: :never do
|
3
|
+
standard_pointer_core
|
4
|
+
end
|
5
|
+
|
6
|
+
view :item_cores, cache: :never do
|
7
|
+
card.known_item_cards.map do |item|
|
8
|
+
nest item, view: :core
|
9
|
+
end.join "\n"
|
10
|
+
end
|
11
|
+
|
12
|
+
def standard_pointer_core
|
13
|
+
with_paging do |paging_args|
|
14
|
+
wrap_with :div, standard_pointer_items(paging_args), class: "pointer-list"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def standard_pointer_items paging_args
|
19
|
+
pointer_items(paging_args.extract!(:limit, :offset)).join(voo.separator || "\n")
|
20
|
+
end
|
21
|
+
|
22
|
+
view :one_line_content do
|
23
|
+
item_view = implicit_item_view
|
24
|
+
item_view = item_view == "name" ? "name" : "link"
|
25
|
+
wrap_with :div, class: "pointer-list" do
|
26
|
+
# limit to first 10 items to optimize
|
27
|
+
pointer_items(view: item_view, limit: 10, offset: 0).join ", "
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def wrap_item rendered, item_view
|
32
|
+
%(<div class="pointer-item item-#{item_view}">#{rendered}</div>)
|
33
|
+
end
|
34
|
+
|
35
|
+
view :input do
|
36
|
+
_render_hidden_content_field + super()
|
37
|
+
end
|
38
|
+
|
39
|
+
def default_input_type
|
40
|
+
:list
|
41
|
+
end
|
42
|
+
|
43
|
+
view :list, cache: :never do
|
44
|
+
list_input
|
45
|
+
end
|
46
|
+
|
47
|
+
# view :nav_item do
|
48
|
+
# nav_dropdown
|
49
|
+
# end
|
50
|
+
|
51
|
+
def list_input args={}
|
52
|
+
items = items_for_input args[:item_list]
|
53
|
+
extra_class = "pointer-list-ul"
|
54
|
+
ul_classes = classy "pointer-list-editor", extra_class
|
55
|
+
haml :list_input, items: items, ul_classes: ul_classes,
|
56
|
+
options_card: options_card_name
|
57
|
+
end
|
58
|
+
|
59
|
+
%i[autocomplete checkbox radio select multiselect].each do |editor_view|
|
60
|
+
view(editor_view) { send "#{editor_view}_input" }
|
61
|
+
end
|
62
|
+
|
63
|
+
def autocomplete_input
|
64
|
+
items = items_for_input
|
65
|
+
haml :autocomplete_input, item: items.first, options_card: options_card_name
|
66
|
+
end
|
67
|
+
|
68
|
+
def checkbox_input
|
69
|
+
haml :checkbox_input, submit_on_change: @submit_on_change
|
70
|
+
end
|
71
|
+
|
72
|
+
def radio_input
|
73
|
+
haml :radio_input, submit_on_change: @submit_on_change
|
74
|
+
end
|
75
|
+
|
76
|
+
def select_input
|
77
|
+
options = { "-- Select --" => "" }.merge card.options_hash
|
78
|
+
select_tag("pointer_select-#{unique_id}",
|
79
|
+
options_for_select(options, card.item_name),
|
80
|
+
class: "pointer-select form-control")
|
81
|
+
end
|
82
|
+
|
83
|
+
def multiselect_input
|
84
|
+
select_tag "pointer_multiselect-#{unique_id}",
|
85
|
+
options_for_select(card.options_hash, card.item_names),
|
86
|
+
multiple: true, class: "pointer-multiselect form-control"
|
87
|
+
end
|
88
|
+
|
89
|
+
def add_item_modal_link
|
90
|
+
modal_link "Add Item",
|
91
|
+
size: :large,
|
92
|
+
class: "btn btn-sm btn-outline-secondary _add-item-link",
|
93
|
+
path: { view: :filter_items_modal,
|
94
|
+
item: implicit_item_view,
|
95
|
+
filter_card: filter_card.name,
|
96
|
+
slot_selector: filtered_list_slot_class,
|
97
|
+
item_selector: "_filtered-list-item",
|
98
|
+
slot: { hide: [:modal_footer] },
|
99
|
+
filter: { not_ids: not_ids_value } }
|
100
|
+
end
|
101
|
+
|
102
|
+
def not_ids_value
|
103
|
+
card.item_ids.map(&:to_s).join(",")
|
104
|
+
end
|
105
|
+
|
106
|
+
def add_item_overlay_link; end
|
107
|
+
|
108
|
+
def one_line_content
|
109
|
+
if count == 1
|
110
|
+
card.first_name
|
111
|
+
else
|
112
|
+
short_content
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
# currently only used by :list and :autocomplete. could be generalized?
|
119
|
+
def items_for_input items=nil
|
120
|
+
items ||= card.item_names context: :raw
|
121
|
+
items.empty? ? [""] : items
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
.pointer-checkbox-list
|
2
|
+
- card.options_hash.each do |option_label, option_name|
|
3
|
+
- id = "pointer-checkbox-#{option_name.to_name.key}"
|
4
|
+
- checked = card.item_names.include? option_name
|
5
|
+
.pointer-checkbox
|
6
|
+
= check_box_tag "pointer_checkbox-#{unique_id}", option_name, checked,
|
7
|
+
id: id, class: "pointer-checkbox-button #{'_submit-on-change' if submit_on_change}"
|
8
|
+
= option_label option_label, id
|
@@ -0,0 +1,62 @@
|
|
1
|
+
format :html do
|
2
|
+
view :filtered_list, unknown: true do
|
3
|
+
filtered_list_input
|
4
|
+
end
|
5
|
+
|
6
|
+
view :filter_items_modal, unknown: true, wrap: :modal do
|
7
|
+
render_filter_items
|
8
|
+
end
|
9
|
+
|
10
|
+
view :filter_items, unknown: true, wrap: :slot, template: :haml
|
11
|
+
|
12
|
+
def filtered_list_input
|
13
|
+
with_nest_mode :normal do
|
14
|
+
class_up "card-slot", filtered_list_slot_class
|
15
|
+
with_class_up "card-slot", filtered_list_slot_class do
|
16
|
+
wrap do
|
17
|
+
haml :filtered_list_input
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# NOCACHE because params alter view
|
24
|
+
view :add_selected_link, cache: :never, unknown: true do
|
25
|
+
link_to "Add Selected",
|
26
|
+
path: { filter_card: params[:filter_card] },
|
27
|
+
class: "_add-selected slotter _close-modal btn btn-primary disabled",
|
28
|
+
data: { "slot-selector": ".#{params[:slot_selector]}",
|
29
|
+
"item-selector": ".#{params[:item_selector]}",
|
30
|
+
remote: true }
|
31
|
+
end
|
32
|
+
|
33
|
+
def filtered_list_item item_card
|
34
|
+
nest_item item_card do |rendered, item_view|
|
35
|
+
wrap_item rendered, item_view
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# for override
|
40
|
+
# @return [Card] search card on which filtering is based
|
41
|
+
def filter_card
|
42
|
+
filter_card_from_params || default_filter_card
|
43
|
+
end
|
44
|
+
|
45
|
+
def default_filter_card
|
46
|
+
fcard = card.options_rule_card || Card[:all]
|
47
|
+
return fcard if fcard.respond_to? :cql_hash
|
48
|
+
|
49
|
+
fcard.fetch :referred_to_by, new: {}
|
50
|
+
end
|
51
|
+
|
52
|
+
def filter_card_from_params
|
53
|
+
return unless params[:filter_card]
|
54
|
+
Card.fetch params[:filter_card], new: {}
|
55
|
+
end
|
56
|
+
|
57
|
+
# currently actually used as a class
|
58
|
+
# (because we don't have api to override slot's id)
|
59
|
+
def filtered_list_slot_class
|
60
|
+
@filtered_list_slot_class ||= "filtered-list-#{unique_id}"
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
._filter-items.container-fluid.nodblclick._noFilterUrlUpdates
|
2
|
+
.row
|
3
|
+
= nest filter_card, view: :filter_form
|
4
|
+
._unselected.col-6.border.mt-2.px-0
|
5
|
+
= nest filter_card, view: :select_item,
|
6
|
+
items: { view: implicit_item_view },
|
7
|
+
cql: { limit: 10 }
|
8
|
+
._selected.col-6.border.mt-2.pl-0.pr-0
|
9
|
+
.selected-box
|
10
|
+
.card-header
|
11
|
+
%h5
|
12
|
+
Selected
|
13
|
+
.badge.badge-secondary
|
14
|
+
%span._selected-items 0
|
15
|
+
._selected-item-list{ style: "display:none" }
|
16
|
+
.deselector.p-2
|
17
|
+
%input#deselect-all._deselect-all{ type: "checkbox", checked: true, disabled: true }
|
18
|
+
%label{ for: "deselect-all" }
|
19
|
+
deselect
|
20
|
+
%span._selected-items 0
|
21
|
+
following
|
22
|
+
._selected-bin.p-2
|
23
|
+
._filter-help.alert.alert-secondary
|
24
|
+
Filter and select items to add them here.
|
25
|
+
.form-group
|
26
|
+
.selected-item-buttons.p-2
|
27
|
+
= button_tag "Cancel", class: "cancel-modal", data: { dismiss: :modal }
|
28
|
+
= render :add_selected_link
|
@@ -0,0 +1,21 @@
|
|
1
|
+
%div.filtered-list-editor
|
2
|
+
%ul.pointer-list.filtered-list-review._pointer-filtered-list.list-group.vertical.nopadding
|
3
|
+
- card.item_cards(context: :raw).each do |item_card|
|
4
|
+
%li._filtered-list-item.clearfix{ data: item_card.format.wrap_data(false) }
|
5
|
+
%span._handle.float-left.m-2
|
6
|
+
= icon_tag :reorder
|
7
|
+
- nest_item item_card do |rendered, view|
|
8
|
+
%span{ class: "item-#{view} float-left w-75"}
|
9
|
+
= rendered
|
10
|
+
%span.filtered-list-item-button
|
11
|
+
%button._filtered-list-item-delete.btn.btn-secondary.btn-sm.m-2{:type => "button"}
|
12
|
+
= icon_tag :remove
|
13
|
+
%br
|
14
|
+
.clearfix
|
15
|
+
= add_item_modal_link
|
16
|
+
-# "data-target": "#modal-filtered-list"
|
17
|
+
-# = modal_slot "filtered-list", "modal-lg"
|
18
|
+
|
19
|
+
// note: passing item and filter card because in some cases (eg Project+Metric on wikirate)
|
20
|
+
// the link was losing set-identifying information (type of left)
|
21
|
+
// would be preferable to have a more general solution to retain set-identifying info.
|
@@ -0,0 +1,16 @@
|
|
1
|
+
%ul{class: ul_classes}
|
2
|
+
- items.each do |item|
|
3
|
+
%li.pointer-li.mb-1
|
4
|
+
%span.input-group
|
5
|
+
.input-group-prepend.handle
|
6
|
+
%span.input-group-text
|
7
|
+
= icon_tag :reorder
|
8
|
+
= text_field_tag "pointer_item", item, class: "pointer-item-text form-control",
|
9
|
+
"data-options-card": options_card
|
10
|
+
.input-group-append
|
11
|
+
%button.pointer-item-delete.btn.btn-secondary{ type: "button"}
|
12
|
+
= icon_tag :remove
|
13
|
+
%span.input-group
|
14
|
+
%button._pointer-item-add.btn.btn-secondary{ type: "submit" }
|
15
|
+
= icon_tag "add"
|
16
|
+
add another
|
@@ -0,0 +1,12 @@
|
|
1
|
+
// TODO: delete me? Is this file in use?
|
2
|
+
|
3
|
+
%li.pointer-li.mb-1
|
4
|
+
%span.input-group
|
5
|
+
.input-group-prepend.handle
|
6
|
+
%span.input-group-text
|
7
|
+
= icon_tag :reorder
|
8
|
+
= text_field_tag "pointer_item", item, class: "pointer-item-text form-control",
|
9
|
+
"data-options-card": options_card
|
10
|
+
.input-group-append
|
11
|
+
%button.pointer-item-delete.btn.btn-secondary{:type => "button"}
|
12
|
+
= icon_tag :remove
|
@@ -0,0 +1,13 @@
|
|
1
|
+
%ul.pointer-radio-list
|
2
|
+
- options_hash = card.options_hash
|
3
|
+
- if options_hash.empty?
|
4
|
+
no options
|
5
|
+
- else
|
6
|
+
- input_name = "pointer_radio_button-#{card.key}"
|
7
|
+
- options_hash.each do |option_label, option_name|
|
8
|
+
- checked = option_name == card.item_name
|
9
|
+
- id = "pointer-radio-#{option_name.to_name.key}"
|
10
|
+
%li.pointer-radio.radio
|
11
|
+
= radio_button_tag input_name, option_name, checked,
|
12
|
+
id: id, class: "pointer-radio-button #{'_submit-on-change' if submit_on_change}"
|
13
|
+
= option_label option_label, id
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# TODO: some of this should be moved to right/options!!
|
2
|
+
# or to type/JSON?
|
3
|
+
|
4
|
+
def options_hash
|
5
|
+
json_options? ? options_card.parse_content : option_hash_from_names
|
6
|
+
end
|
7
|
+
|
8
|
+
def json_options?
|
9
|
+
options_card&.type_id == JsonID
|
10
|
+
end
|
11
|
+
|
12
|
+
def option_hash_from_names
|
13
|
+
option_names.each_with_object({}) do |name, hash|
|
14
|
+
hash[name] = name
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def option_names
|
19
|
+
if (selected_options = item_names)
|
20
|
+
(standard_option_names + selected_options).uniq
|
21
|
+
else
|
22
|
+
standard_option_names
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def option_cards
|
27
|
+
option_names.map do |name|
|
28
|
+
Card.fetch name, new: {}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def options_rule_card
|
33
|
+
rule_card :content_options
|
34
|
+
end
|
35
|
+
|
36
|
+
def standard_option_names
|
37
|
+
if json_options?
|
38
|
+
options_hash.values.map(&:to_name)
|
39
|
+
else
|
40
|
+
option_names_from_items
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def option_names_from_items
|
45
|
+
o_card = options_card
|
46
|
+
limit = o_card.try(:default_limit).to_i
|
47
|
+
o_card.item_names context: name, limit: limit
|
48
|
+
end
|
49
|
+
|
50
|
+
def options_card
|
51
|
+
options_rule_card || Card[:all]
|
52
|
+
end
|
53
|
+
|
54
|
+
def options_card_name
|
55
|
+
options_rule_card&.name&.url_key || ":all"
|
56
|
+
end
|
57
|
+
|
58
|
+
format do
|
59
|
+
def options_card_name
|
60
|
+
card.options_card_name
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
format :html do
|
65
|
+
def option_label option_name, id
|
66
|
+
%(<label for="#{id}">#{option_label_text option_name}</label>)
|
67
|
+
end
|
68
|
+
|
69
|
+
def option_view
|
70
|
+
@option_view ||= card.rule(:content_option_view) || :smart_label
|
71
|
+
end
|
72
|
+
|
73
|
+
def option_label_text option_name
|
74
|
+
return option_name unless (option_card = Card.fetch option_name)
|
75
|
+
|
76
|
+
nest option_card, view: option_view
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
# BASE views
|
2
|
+
|
3
|
+
format do
|
4
|
+
def default_limit
|
5
|
+
20
|
6
|
+
end
|
7
|
+
|
8
|
+
def item_links args={}
|
9
|
+
card.item_cards(args).map do |item_card|
|
10
|
+
subformat(item_card).render_link
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def nest_item_array
|
15
|
+
card.item_cards.map do |item|
|
16
|
+
nest_item item
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
view :core do
|
21
|
+
pointer_items.join ", "
|
22
|
+
end
|
23
|
+
|
24
|
+
def pointer_items args={}
|
25
|
+
page_args = args.extract! :limit, :offset
|
26
|
+
listing card.item_cards(page_args), args
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# JavaScript views
|
31
|
+
|
32
|
+
format :js do
|
33
|
+
view :core do
|
34
|
+
nest_item_array.join "\n\n"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Data views
|
39
|
+
|
40
|
+
format :data do
|
41
|
+
view :core do
|
42
|
+
nest_item_array
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# JSON views
|
47
|
+
|
48
|
+
format :json do
|
49
|
+
view :content do
|
50
|
+
card.item_names
|
51
|
+
end
|
52
|
+
|
53
|
+
def item_cards
|
54
|
+
card.item_cards
|
55
|
+
end
|
56
|
+
|
57
|
+
def max_depth
|
58
|
+
params[:max_depth] || 1
|
59
|
+
end
|
60
|
+
|
61
|
+
def items_for_export
|
62
|
+
card.item_cards
|
63
|
+
end
|
64
|
+
|
65
|
+
def essentials
|
66
|
+
return {} if depth > max_depth
|
67
|
+
card.item_cards.map do |item|
|
68
|
+
nest item, view: :essentials
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
view :links do
|
73
|
+
[]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# CSS views
|
78
|
+
|
79
|
+
format :css do
|
80
|
+
# generalize to all collections?
|
81
|
+
def default_item_view
|
82
|
+
:content
|
83
|
+
end
|
84
|
+
|
85
|
+
view :titled do
|
86
|
+
%(#{major_comment "STYLE GROUP: \"#{card.name}\"", '='}#{_render_core})
|
87
|
+
end
|
88
|
+
|
89
|
+
view :core do
|
90
|
+
nest_item_array.join "\n\n"
|
91
|
+
end
|
92
|
+
|
93
|
+
view :content, :core
|
94
|
+
end
|
95
|
+
|
96
|
+
# RSS views
|
97
|
+
|
98
|
+
format :rss do
|
99
|
+
def raw_feed_items
|
100
|
+
@raw_feed_items ||= card.item_cards(limit: limit, offset: offset)
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
include_set Abstract::Pointer
|
2
|
+
|
3
|
+
abstract_basket :item_codenames
|
4
|
+
|
5
|
+
# simplify api
|
6
|
+
# Self::MyCodePointerSet.add_item :my_item_codename
|
7
|
+
# instead of
|
8
|
+
# Self::MyCodePointerSet.add_to_basket :item_codenames, :my_item_codename
|
9
|
+
module ClassMethods
|
10
|
+
def add_item codename
|
11
|
+
valid_codename codename do
|
12
|
+
add_to_basket :item_codenames, codename
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def unshift_item codename
|
17
|
+
valid_codename codename do
|
18
|
+
unshift_basket :item_codenames, codename
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def valid_codename codename
|
23
|
+
if Card::Codename.exist? codename
|
24
|
+
yield
|
25
|
+
else
|
26
|
+
Rails.logger.info "unknown codename '#{codename}' added to code pointer"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def content
|
32
|
+
item_codenames.map do |codename|
|
33
|
+
Card.fetch_name codename
|
34
|
+
end.compact.to_pointer_content
|
35
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# store items as ids, not names
|
2
|
+
|
3
|
+
def standardize_item cardish
|
4
|
+
if (id = Card.fetch_id cardish)
|
5
|
+
"~#{id}"
|
6
|
+
else
|
7
|
+
Rails.logger.info "no id for '#{cardish}' added to id pointer"
|
8
|
+
nil
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def item_ids args={}
|
13
|
+
item_strings(args).map do |item|
|
14
|
+
item = standardize_item item unless item.match?(/^~/)
|
15
|
+
item.to_s.tr("~", "").to_i
|
16
|
+
end.compact
|
17
|
+
end
|
18
|
+
|
19
|
+
def item_names args={}
|
20
|
+
item_ids(args).map(&:cardname).compact
|
21
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
def default_limit
|
2
|
+
cql_limit = fetch_query.limit if respond_to?(:fetch_query)
|
3
|
+
cql_limit || 50
|
4
|
+
end
|
5
|
+
|
6
|
+
format :html do
|
7
|
+
def quick_edit
|
8
|
+
card.left.prototype_default_card.try(:show_content_options?) ? super : ""
|
9
|
+
end
|
10
|
+
|
11
|
+
def quick_editor
|
12
|
+
wrap_type_formgroup do
|
13
|
+
type_field class: "type-field rule-type-field _submit-on-select"
|
14
|
+
end +
|
15
|
+
wrap_content_formgroup do
|
16
|
+
text_field :content, class: "d0-card-content _submit-after-typing"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def visible_cardtype_groups
|
21
|
+
{ "Organize" => %w[List Pointer] }
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
setting_opts group: :editing, position: 6,
|
2
|
+
restricted_to_type: %i[list pointer session],
|
3
|
+
rule_type_editable: false,
|
4
|
+
help_text: "Label view for radio button and checkbox items. "\
|
5
|
+
"[[http://decko.org/Pointer|more]]",
|
6
|
+
applies: lambda { |prototype|
|
7
|
+
prototype.supports_content_options? &&
|
8
|
+
prototype.rule_card(:input_type)&.supports_content_option_view?
|
9
|
+
}
|
@@ -0,0 +1,9 @@
|
|
1
|
+
setting_opts group: :editing, position: 5,
|
2
|
+
restricted_to_type: %i[list pointer session],
|
3
|
+
rule_type_editable: true,
|
4
|
+
help_text: "Value options for [[List]] and [[Pointer]] and cards. "\
|
5
|
+
"Can itself be a List or a [[Search]]. "\
|
6
|
+
"[[http://decko.org/Pointer|more]]",
|
7
|
+
applies: lambda { |prototype|
|
8
|
+
prototype.rule_card(:input_type).supports_content_options?
|
9
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
include_set Abstract::Pointer
|
2
|
+
|
3
|
+
basket :options
|
4
|
+
add_to_basket :options, "radio"
|
5
|
+
add_to_basket :options, "checkbox"
|
6
|
+
add_to_basket :options, "select"
|
7
|
+
add_to_basket :options, "multiselect"
|
8
|
+
add_to_basket :options, "list"
|
9
|
+
add_to_basket :options, "filtered list"
|
10
|
+
|
11
|
+
def content
|
12
|
+
options.to_pointer_content
|
13
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
include_set Abstract::Pointer
|
2
|
+
|
3
|
+
def raw_item_strings content
|
4
|
+
reference_chunks(content).map(&:referee_name)
|
5
|
+
end
|
6
|
+
|
7
|
+
def item_titles default_to_name=true
|
8
|
+
reference_chunks.map do |chunk|
|
9
|
+
chunk.options[:title] || (default_to_name ? chunk.referee_name : nil)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
format do
|
14
|
+
def chunk_list
|
15
|
+
:references
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
format :html do
|
20
|
+
def input_type
|
21
|
+
:link_list
|
22
|
+
end
|
23
|
+
|
24
|
+
view :link_list_input, cache: :never do
|
25
|
+
link_list_input
|
26
|
+
end
|
27
|
+
|
28
|
+
def items_for_input items=nil
|
29
|
+
items ||= card.item_names context: :raw
|
30
|
+
items.empty? ? [["", ""]] : items.zip(card.item_titles(false))
|
31
|
+
end
|
32
|
+
|
33
|
+
def link_list_input args={}
|
34
|
+
items = items_for_input args[:item_list]
|
35
|
+
extra_class = "pointer-link-list-ul"
|
36
|
+
ul_classes = classy "pointer-list-editor", extra_class
|
37
|
+
haml :link_list_input, items: items, ul_classes: ul_classes,
|
38
|
+
options_card: options_card_name
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
%ul{class: ul_classes}
|
2
|
+
- items.each.with_index do |(reference, title), index|
|
3
|
+
%li.pointer-li.mb-1{"data-index": index}
|
4
|
+
%span.input-group
|
5
|
+
.input-group-prepend.handle
|
6
|
+
%span.input-group-text
|
7
|
+
= icon_tag :reorder
|
8
|
+
%span.input-group-text.text-muted.group-text-left
|
9
|
+
[[
|
10
|
+
= text_field_tag "pointer_item", reference, class: "_reference pointer-item-text form-control group-text-middle",
|
11
|
+
"data-options-card": options_card
|
12
|
+
%span.input-group-text.text-muted.group-text-middle
|
13
|
+
|
|
14
|
+
= text_field_tag "pointer_item_title", title, class: "_title pointer-item-text form-control group-text-middle"
|
15
|
+
%span.input-group-text.text-muted.group-text-right
|
16
|
+
]]
|
17
|
+
.input-group-append
|
18
|
+
%span.input-group-text.p-0
|
19
|
+
%button.pointer-item-delete.btn.btn-secondary{ type: "button"}
|
20
|
+
= icon_tag :remove
|
21
|
+
%span.input-group
|
22
|
+
%button._pointer-item-add.btn.btn-secondary{ type: "submit" }
|
23
|
+
= icon_tag "add"
|
24
|
+
add another
|
data/set/type/list.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
include_set Abstract::Pointer
|
2
|
+
|
3
|
+
def each_reference_out
|
4
|
+
item_names.each do |name|
|
5
|
+
yield(name, Card::Content::Chunk::Link::CODE)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
format :html do
|
10
|
+
view :view_list do
|
11
|
+
%i[info_bar bar box closed titled labeled].map do |view|
|
12
|
+
voo.items[:view] = view
|
13
|
+
wrap_with :p, [content_tag(:h3, "#{view} items"), render_content]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
include_set Abstract::Items
|
2
|
+
|
3
|
+
def raw_item_strings content
|
4
|
+
reference_chunks(content).map(&:referee_name)
|
5
|
+
end
|
6
|
+
|
7
|
+
def item_options
|
8
|
+
nest_chunks.map(&:raw_options)
|
9
|
+
end
|
10
|
+
|
11
|
+
def items_to_content array
|
12
|
+
items = array.map { |i| standardize_item i }.reject(&:blank?)
|
13
|
+
self.content = items.join("\n")
|
14
|
+
end
|
15
|
+
|
16
|
+
format do
|
17
|
+
def chunk_list
|
18
|
+
:references
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
format :html do
|
23
|
+
def input_type
|
24
|
+
:nest_list
|
25
|
+
end
|
26
|
+
|
27
|
+
view :nest_list_input, cache: :never do
|
28
|
+
nest_list_input
|
29
|
+
end
|
30
|
+
|
31
|
+
view :input do
|
32
|
+
_render_hidden_content_field + super()
|
33
|
+
end
|
34
|
+
|
35
|
+
def items_for_input items=nil
|
36
|
+
items ||= card.item_names context: :raw
|
37
|
+
items.empty? ? [["", ""]] : items.zip(card.item_options)
|
38
|
+
end
|
39
|
+
|
40
|
+
def nest_list_input args={}
|
41
|
+
items = items_for_input args[:item_list]
|
42
|
+
extra_class = "_nest-list-ul"
|
43
|
+
ul_classes = classy "pointer-list-editor", extra_class
|
44
|
+
haml :nest_list_input, items: items, ul_classes: ul_classes
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
%ul{class: ul_classes}
|
2
|
+
- items.each.with_index do |(reference, title), index|
|
3
|
+
%li.pointer-li.mb-1._nest-form{"data-index": index}
|
4
|
+
%span.input-group
|
5
|
+
.input-group-prepend.handle
|
6
|
+
%span.input-group-text
|
7
|
+
= icon_tag :reorder
|
8
|
+
%span.input-group-text.text-muted.group-text-left
|
9
|
+
{{
|
10
|
+
= text_field_tag "pointer_item", reference, class: "_reference pointer-item-text form-control group-text-middle"
|
11
|
+
%span.input-group-text.text-muted.group-text-middle
|
12
|
+
= "|"
|
13
|
+
= text_field_tag "pointer_item_title", title, class: "_title _nest-options pointer-item-text form-control group-text-middle"
|
14
|
+
%span.input-group-text.text-muted.group-text-right
|
15
|
+
}}
|
16
|
+
.input-group-append
|
17
|
+
%span.input-group-text.p-0
|
18
|
+
%button.btn.btn-secondary._open-nest-editor{ type: "button"}
|
19
|
+
= icon_tag :edit
|
20
|
+
.input-group-append
|
21
|
+
%span.input-group-text.p-0
|
22
|
+
%button.pointer-item-delete.btn.btn-secondary{ type: "button"}
|
23
|
+
= icon_tag :remove
|
24
|
+
|
25
|
+
%span.input-group
|
26
|
+
%button._pointer-item-add.btn.btn-secondary{ type: "submit" }
|
27
|
+
= icon_tag "add"
|
28
|
+
add another
|
data/set/type/pointer.rb
ADDED
metadata
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: card-mod-list
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.11.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ethan McCutchen
|
8
|
+
- Philipp Kühl
|
9
|
+
- Gerry Gleason
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2020-12-24 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: card
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- - '='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.101.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
requirements:
|
26
|
+
- - '='
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: 1.101.0
|
29
|
+
- !ruby/object:Gem::Dependency
|
30
|
+
name: card-mod-format
|
31
|
+
requirement: !ruby/object:Gem::Requirement
|
32
|
+
requirements:
|
33
|
+
- - '='
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: 0.11.0
|
36
|
+
type: :runtime
|
37
|
+
prerelease: false
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - '='
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 0.11.0
|
43
|
+
- !ruby/object:Gem::Dependency
|
44
|
+
name: card-mod-collection
|
45
|
+
requirement: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - '='
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: 0.11.0
|
50
|
+
type: :runtime
|
51
|
+
prerelease: false
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - '='
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 0.11.0
|
57
|
+
description: ''
|
58
|
+
email:
|
59
|
+
- info@decko.org
|
60
|
+
executables: []
|
61
|
+
extensions: []
|
62
|
+
extra_rdoc_files: []
|
63
|
+
files:
|
64
|
+
- db/migrate_core_cards/20160804112340_add_pointer_cards.rb
|
65
|
+
- set/abstract/01_pointer.rb
|
66
|
+
- set/abstract/01_pointer/events.rb
|
67
|
+
- set/abstract/01_pointer/html_views.rb
|
68
|
+
- set/abstract/01_pointer/html_views/autocomplete_input.haml
|
69
|
+
- set/abstract/01_pointer/html_views/checkbox_input.haml
|
70
|
+
- set/abstract/01_pointer/html_views/filter.rb
|
71
|
+
- set/abstract/01_pointer/html_views/filter/filter_items.haml
|
72
|
+
- set/abstract/01_pointer/html_views/filter/filtered_list_input.haml
|
73
|
+
- set/abstract/01_pointer/html_views/list_input.haml
|
74
|
+
- set/abstract/01_pointer/html_views/list_item.haml
|
75
|
+
- set/abstract/01_pointer/html_views/radio_input.haml
|
76
|
+
- set/abstract/01_pointer/options_api.rb
|
77
|
+
- set/abstract/01_pointer/other_views.rb
|
78
|
+
- set/abstract/code_pointer.rb
|
79
|
+
- set/abstract/id_pointer.rb
|
80
|
+
- set/all/supports_content_options.rb
|
81
|
+
- set/right/content_option_view.rb
|
82
|
+
- set/right/content_options.rb
|
83
|
+
- set/self/content_option_view.rb
|
84
|
+
- set/self/content_options.rb
|
85
|
+
- set/self/input_options.rb
|
86
|
+
- set/type/link_list.rb
|
87
|
+
- set/type/link_list/link_list_input.haml
|
88
|
+
- set/type/list.rb
|
89
|
+
- set/type/nest_list.rb
|
90
|
+
- set/type/nest_list/nest_list_input.haml
|
91
|
+
- set/type/pointer.rb
|
92
|
+
homepage: http://decko.org
|
93
|
+
licenses:
|
94
|
+
- GPL-3.0
|
95
|
+
metadata:
|
96
|
+
card-mod: list
|
97
|
+
post_install_message:
|
98
|
+
rdoc_options: []
|
99
|
+
require_paths:
|
100
|
+
- lib
|
101
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ">="
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '2.5'
|
106
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
requirements: []
|
112
|
+
rubygems_version: 3.0.3
|
113
|
+
signing_key:
|
114
|
+
specification_version: 4
|
115
|
+
summary: list of cards
|
116
|
+
test_files: []
|