card-mod-edit 0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/set/all/bridge.rb +64 -0
- data/set/all/bridge/bridge.haml +8 -0
- data/set/all/bridge/bridge_pills.rb +47 -0
- data/set/all/bridge/follow_section.rb +37 -0
- data/set/all/bridge/related_section.rb +34 -0
- data/set/all/bridge/tab_views.rb +41 -0
- data/set/all/bridge/tab_visibility.rb +53 -0
- data/set/all/edit_content.rb +60 -0
- data/set/all/edit_inline.rb +56 -0
- data/set/all/edit_name.rb +58 -0
- data/set/all/edit_type.rb +101 -0
- data/set/all/editing.rb +91 -0
- data/set/all/editor.rb +56 -0
- data/set/all/form.rb +245 -0
- data/set/all/form_buttons.rb +64 -0
- data/set/all/form_elements.rb +71 -0
- data/set/all/formgroup.rb +37 -0
- data/set/all/new.rb +188 -0
- data/set/all/overlay_guide.haml +7 -0
- data/set/all/overlay_guide.rb +9 -0
- data/set/all/template_nest.rb +42 -0
- data/set/type/list.rb +15 -0
- data/set/type/plain_text.rb +13 -0
- data/set/type/pointer.rb +11 -0
- metadata +71 -0
@@ -0,0 +1,101 @@
|
|
1
|
+
format :html do
|
2
|
+
view :edit_type, cache: :never, perms: :update do
|
3
|
+
frame do
|
4
|
+
_render_edit_type_form
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
view :edit_type_form, cache: :never, perms: :update, wrap: :slot do
|
9
|
+
card_form :update, success: edit_type_success do
|
10
|
+
[type_formgroup, render_new_buttons]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def edit_type_success
|
15
|
+
{ view: :core }
|
16
|
+
end
|
17
|
+
|
18
|
+
view :edit_type_row do
|
19
|
+
return _render_bridge_type_formgroup if voo.visible?(:type_form) { false }
|
20
|
+
|
21
|
+
edit_row_fixed_width "Type", link_to_card(card.type), :bridge_type_formgroup
|
22
|
+
end
|
23
|
+
|
24
|
+
view :bridge_type_formgroup, unknown: true, wrap: :slot do
|
25
|
+
type_formgroup href: path(mark: card.id,
|
26
|
+
view: :edit_form,
|
27
|
+
assign: true,
|
28
|
+
slot: { show: :type_form }),
|
29
|
+
class: "live-type-field slotter",
|
30
|
+
'data-remote': true,
|
31
|
+
'data-slot-selector': ".card-slot.edit_form-view"
|
32
|
+
end
|
33
|
+
|
34
|
+
view :type_formgroup do
|
35
|
+
type_formgroup
|
36
|
+
end
|
37
|
+
|
38
|
+
def type_formgroup args={}
|
39
|
+
add_class args, "type-field"
|
40
|
+
wrap_type_formgroup do
|
41
|
+
type_field args
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def wrap_type_formgroup
|
46
|
+
formgroup "Type", input: "type", class: "type-formgroup", help: false do
|
47
|
+
output [yield, hidden_field_tag(:assign, true)]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def type_field args={}
|
52
|
+
typelist = Auth.createable_types
|
53
|
+
current_type = type_field_current_value args, typelist
|
54
|
+
template.select_tag "card[type]", type_field_options(current_type),
|
55
|
+
args.merge("data-select2-id": "#{unique_id}-#{Time.now.to_i}")
|
56
|
+
end
|
57
|
+
|
58
|
+
def type_field_options current_type
|
59
|
+
types = grouped_types(current_type)
|
60
|
+
|
61
|
+
if types.size == 1
|
62
|
+
options_for_select types.flatten[1], current_type
|
63
|
+
else
|
64
|
+
grouped_options_for_select types, current_type
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def grouped_types current_type
|
69
|
+
groups = Hash.new { |h, k| h[k] = [] }
|
70
|
+
allowed = ::Set.new Auth.createable_types
|
71
|
+
allowed << current_type if current_type
|
72
|
+
|
73
|
+
visible_cardtype_groups.each_pair do |name, items|
|
74
|
+
if name == "Custom"
|
75
|
+
Auth.createable_types.each do |type|
|
76
|
+
groups["Custom"] << type unless ::Card::Set::Self::Cardtype::GROUP_MAP[type]
|
77
|
+
end
|
78
|
+
else
|
79
|
+
items.each do |i|
|
80
|
+
groups[name] << i if allowed.include?(i)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
groups
|
85
|
+
end
|
86
|
+
|
87
|
+
def visible_cardtype_groups
|
88
|
+
::Card::Set::Self::Cardtype::GROUP
|
89
|
+
end
|
90
|
+
|
91
|
+
def type_field_current_value args, typelist
|
92
|
+
return if args.delete :no_current_type
|
93
|
+
|
94
|
+
if !card.new_card? && !typelist.include?(card.type_name)
|
95
|
+
# current type should be an option on existing cards,
|
96
|
+
# regardless of create perms
|
97
|
+
typelist.push(card.type_name).sort!
|
98
|
+
end
|
99
|
+
card.type_name_or_default
|
100
|
+
end
|
101
|
+
end
|
data/set/all/editing.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
format :html do
|
2
|
+
###---( TOP_LEVEL (used by menu) NEW / EDIT VIEWS )
|
3
|
+
view :bridge, perms: :update, unknown: true, cache: :never, wrap: :bridge do
|
4
|
+
with_nest_mode :edit do
|
5
|
+
add_name_context
|
6
|
+
voo.show :help
|
7
|
+
wrap true, breadcrumb_data("Editing", "edit") do
|
8
|
+
bridge_parts
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
view :cardboard, :bridge
|
14
|
+
|
15
|
+
def bridge_parts
|
16
|
+
voo.show! :edit_type_row
|
17
|
+
|
18
|
+
[
|
19
|
+
frame_help,
|
20
|
+
_render_edit_name_row(home_view: :edit_name_row),
|
21
|
+
# home_view is necessary for cancel to work correctly.
|
22
|
+
# it seems a little strange to have to think about home_view here,
|
23
|
+
# but the issue is that something currently has to happen prior to the
|
24
|
+
# render to get voo.slot_options to have the write home view in
|
25
|
+
# the slot wrap. I think this would probably best be handled as an
|
26
|
+
# option to #wrap that triggers a new heir voo
|
27
|
+
_render_edit_form
|
28
|
+
]
|
29
|
+
end
|
30
|
+
|
31
|
+
def edit_success
|
32
|
+
# for override
|
33
|
+
end
|
34
|
+
|
35
|
+
def edit_view_hidden
|
36
|
+
# for override
|
37
|
+
end
|
38
|
+
|
39
|
+
view :edit_buttons do
|
40
|
+
button_formgroup do
|
41
|
+
wrap_with "div", class: "d-flex" do
|
42
|
+
[standard_submit_button, edit_cancel_button, delete_button]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# TODO: add undo functionality
|
48
|
+
view :just_deleted, unknown: true do
|
49
|
+
wrap { "#{render_title} deleted" }
|
50
|
+
end
|
51
|
+
|
52
|
+
view :edit_rules, cache: :never, unknown: true do
|
53
|
+
nest current_set_card, view: :bridge_rules_tab
|
54
|
+
end
|
55
|
+
|
56
|
+
view :edit_structure, cache: :never do
|
57
|
+
return unless card.structure
|
58
|
+
|
59
|
+
nest card.structure_rule_card, view: :edit
|
60
|
+
# FIXME: this stuff:
|
61
|
+
# slot: {
|
62
|
+
# cancel_slot_selector: ".card-slot.related-view",
|
63
|
+
# cancel_path: card.format.path(view: :edit), hide: :edit_toolbar,
|
64
|
+
# hidden: { success: { view: :open, "slot[subframe]" => true } }
|
65
|
+
# }
|
66
|
+
# }
|
67
|
+
end
|
68
|
+
|
69
|
+
view :edit_nests, cache: :never do
|
70
|
+
frame do
|
71
|
+
with_nest_mode :edit do
|
72
|
+
multi_card_edit
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# FIXME: - view can recurse. temporarily turned off
|
78
|
+
#
|
79
|
+
# view :edit_nest_rules, cache: :never do
|
80
|
+
# return ""#
|
81
|
+
# view = args[:rule_view] || :field_related_rules
|
82
|
+
# frame do
|
83
|
+
# # with_nest_mode :edit do
|
84
|
+
# nested_fields.map do |name, _options|
|
85
|
+
# nest Card.fetch(name.to_name.trait(:self)),
|
86
|
+
# view: :titled, title: name, rule_view: view,
|
87
|
+
# hide: :set_label, show: :rule_navbar
|
88
|
+
# end
|
89
|
+
# end
|
90
|
+
# end
|
91
|
+
end
|
data/set/all/editor.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
|
2
|
+
Self::InputOptions.add_to_basket :options, "text area"
|
3
|
+
Self::InputOptions.add_to_basket :options, "text field"
|
4
|
+
|
5
|
+
format :html do
|
6
|
+
def input_type
|
7
|
+
voo.input_type.present? ? voo.input_type : input_type_from_rule
|
8
|
+
end
|
9
|
+
|
10
|
+
def input_type_from_rule
|
11
|
+
card.rule(:input_type)&.gsub(/[\[\]]/, "")&.tr(" ", "_")
|
12
|
+
end
|
13
|
+
|
14
|
+
def input_method input_type
|
15
|
+
"#{input_type}_input"
|
16
|
+
end
|
17
|
+
|
18
|
+
# core view of card is input
|
19
|
+
def input_defined_by_card
|
20
|
+
with_card input_type do |input_card|
|
21
|
+
nest input_card, view: :core
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# move somewhere more accessible?
|
26
|
+
def with_card mark
|
27
|
+
return nil unless (card = Card[mark])
|
28
|
+
|
29
|
+
yield card
|
30
|
+
rescue Card::Error::CodenameNotFound
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
|
34
|
+
view :input, unknown: true do
|
35
|
+
try(input_method(input_type)) ||
|
36
|
+
input_defined_by_card ||
|
37
|
+
send(input_method(default_input_type))
|
38
|
+
end
|
39
|
+
|
40
|
+
def default_input_type
|
41
|
+
:rich_text
|
42
|
+
end
|
43
|
+
|
44
|
+
def rich_text_input
|
45
|
+
send "#{Cardio.config.rich_text_editor || :text_area}_editor_input"
|
46
|
+
end
|
47
|
+
|
48
|
+
def text_area_input
|
49
|
+
text_area :content, rows: 5, class: "d0-card-content",
|
50
|
+
"data-card-type-code" => card.type_code
|
51
|
+
end
|
52
|
+
|
53
|
+
def text_field_input
|
54
|
+
text_field :content, class: classy("d0-card-content")
|
55
|
+
end
|
56
|
+
end
|
data/set/all/form.rb
ADDED
@@ -0,0 +1,245 @@
|
|
1
|
+
format :html do
|
2
|
+
# FIELDSET VIEWS
|
3
|
+
|
4
|
+
# sometimes multiple card formgroups, sometimes just one
|
5
|
+
view :content_formgroups, cache: :never do
|
6
|
+
wrap_with :fieldset, edit_slot, class: classy("card-editor", "editor")
|
7
|
+
end
|
8
|
+
|
9
|
+
view :name_formgroup do
|
10
|
+
formgroup "Name", input: "name", help: false do
|
11
|
+
raw name_field
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# single card content formgroup, labeled with "Content"
|
16
|
+
view :content_formgroup, unknown: true, cache: :never do
|
17
|
+
wrap_content_formgroup { content_field }
|
18
|
+
end
|
19
|
+
|
20
|
+
view :edit_in_form, cache: :never, perms: :update, unknown: true do
|
21
|
+
reset_form
|
22
|
+
@in_multi_card_editor = true
|
23
|
+
edit_slot
|
24
|
+
end
|
25
|
+
|
26
|
+
view :conflict_tracker, cache: :never, unknown: true do
|
27
|
+
return unless card&.real?
|
28
|
+
|
29
|
+
card.last_action_id_before_edit = card.last_action_id
|
30
|
+
hidden_field :last_action_id_before_edit, class: "current_revision_id"
|
31
|
+
end
|
32
|
+
|
33
|
+
def wrap_content_formgroup
|
34
|
+
formgroup("Content", input: :content, help: false,
|
35
|
+
class: classy("card-editor")) { yield }
|
36
|
+
end
|
37
|
+
|
38
|
+
def button_formgroup
|
39
|
+
wrap_with :div, class: classy("form-group") do
|
40
|
+
wrap_with :div, yield
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def name_field
|
45
|
+
# value needed because otherwise gets wrong value if there are updates
|
46
|
+
text_field :name, value: card.name, autocomplete: "off"
|
47
|
+
end
|
48
|
+
|
49
|
+
def content_field
|
50
|
+
with_nest_mode :normal do
|
51
|
+
# by changing nest mode to normal, we ensure that editors (eg image
|
52
|
+
# previews) can render core views.
|
53
|
+
output [_render_conflict_tracker, _render_input]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# SAMPLE editor view for override
|
58
|
+
# view :input do
|
59
|
+
# text_area :content, rows: 5, class: "d0-card-content"
|
60
|
+
# end
|
61
|
+
|
62
|
+
def edit_slot
|
63
|
+
case
|
64
|
+
when inline_nests_editor? then _render_core
|
65
|
+
when multi_card_editor? then multi_card_edit(true)
|
66
|
+
when in_multi_card_editor? then editor_in_multi_card
|
67
|
+
else single_card_edit_field
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# test: render nests within a normal rendering of the card's content?
|
72
|
+
# (as opposed to a standardized form)
|
73
|
+
def inline_nests_editor?
|
74
|
+
voo.input_type == :inline_nests
|
75
|
+
end
|
76
|
+
|
77
|
+
# test: are we opening a new multi-card form?
|
78
|
+
def multi_card_editor?
|
79
|
+
voo.structure || voo.edit_structure || # structure configured in voo
|
80
|
+
card.structure || # structure in card rule
|
81
|
+
edit_fields? # list of fields in card rule
|
82
|
+
end
|
83
|
+
|
84
|
+
# override and return true to optimize
|
85
|
+
def edit_fields?
|
86
|
+
edit_fields.present?
|
87
|
+
end
|
88
|
+
|
89
|
+
# test: are we already within a multi-card form?
|
90
|
+
def in_multi_card_editor?
|
91
|
+
@in_multi_card_editor.present?
|
92
|
+
end
|
93
|
+
|
94
|
+
def single_card_edit_field
|
95
|
+
if voo.show?(:type_formgroup) || voo.show?(:name_formgroup)
|
96
|
+
_render_content_formgroup # use formgroup for consistency
|
97
|
+
else
|
98
|
+
editor_wrap(:content) { content_field }
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def editor_in_multi_card
|
103
|
+
add_junction_class
|
104
|
+
formgroup render_title,
|
105
|
+
input: "content", help: true, class: classy("card-editor") do
|
106
|
+
[content_field, (form.hidden_field(:type_id) if card.new_card?)]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def multi_card_edit fields_only=false
|
111
|
+
field_configs = edit_field_configs fields_only
|
112
|
+
return structure_link if field_configs.empty?
|
113
|
+
|
114
|
+
field_configs.map do |name, options|
|
115
|
+
nest name, options || {}
|
116
|
+
end.join "\n"
|
117
|
+
end
|
118
|
+
|
119
|
+
def structure_link
|
120
|
+
# LOCALIZE
|
121
|
+
structured = link_to_card card.structure_rule_card, "structured"
|
122
|
+
"<label>Content</label>"\
|
123
|
+
"<p><em>Uneditable; content is #{structured} without nests</em></p>"
|
124
|
+
end
|
125
|
+
|
126
|
+
# @param [Hash|Array] fields either an array with field names and/or field
|
127
|
+
# cards or a hash with the fields as keys and a hash with nest options as
|
128
|
+
# values
|
129
|
+
def process_edit_fields fields
|
130
|
+
fields.map do |field, opts|
|
131
|
+
field_nest field, opts
|
132
|
+
end.join "\n"
|
133
|
+
end
|
134
|
+
###
|
135
|
+
|
136
|
+
# If you use subfield cards to render a form for a new card
|
137
|
+
# then the subfield cards should be created on the new card not the existing
|
138
|
+
# card that build the form
|
139
|
+
|
140
|
+
def form
|
141
|
+
@form ||= inherit(:form) || new_form
|
142
|
+
end
|
143
|
+
|
144
|
+
def new_form
|
145
|
+
@form_root = true unless parent&.form_root
|
146
|
+
instantiate_builder(form_prefix, card, {})
|
147
|
+
end
|
148
|
+
|
149
|
+
def reset_form
|
150
|
+
@form = new_form
|
151
|
+
end
|
152
|
+
|
153
|
+
def form_prefix
|
154
|
+
case
|
155
|
+
when explicit_form_prefix then explicit_form_prefix # configured
|
156
|
+
when simple_form? then "card" # simple form
|
157
|
+
when parent.card.name == card.name then parent.form_prefix # card nests self
|
158
|
+
else edit_in_form_prefix
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def simple_form?
|
163
|
+
form_root? || !form_root || !parent
|
164
|
+
end
|
165
|
+
|
166
|
+
def edit_in_form_prefix
|
167
|
+
"#{parent.form_prefix}[subcards][#{card.name.from form_context.card.name}]"
|
168
|
+
end
|
169
|
+
|
170
|
+
def explicit_form_prefix
|
171
|
+
inherit :explicit_form_prefix
|
172
|
+
end
|
173
|
+
|
174
|
+
def form_context
|
175
|
+
form_root? || !form_root ? self : parent
|
176
|
+
end
|
177
|
+
|
178
|
+
def form_root?
|
179
|
+
@form_root == true
|
180
|
+
end
|
181
|
+
|
182
|
+
def form_root
|
183
|
+
return self if @form_root
|
184
|
+
|
185
|
+
parent ? parent.form_root : nil
|
186
|
+
end
|
187
|
+
|
188
|
+
def card_form action, opts={}
|
189
|
+
@form_root = true
|
190
|
+
hidden = hidden_form_tags action, opts
|
191
|
+
form_for card, card_form_opts(action, opts) do |cform|
|
192
|
+
@form = cform
|
193
|
+
hidden + output(yield(cform))
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def hidden_form_tags _action, opts
|
198
|
+
success = opts.delete :success
|
199
|
+
success_tags success
|
200
|
+
end
|
201
|
+
|
202
|
+
# @param action [Symbol] :create or :update
|
203
|
+
# @param opts [Hash] html options
|
204
|
+
# @option opts [Boolean] :redirect (false) if true form is no "slotter"
|
205
|
+
def card_form_opts action, opts={}
|
206
|
+
url, action = card_form_url_and_action action
|
207
|
+
html_opts = card_form_html_opts action, opts
|
208
|
+
form_opts = { url: url, html: html_opts }
|
209
|
+
form_opts[:remote] = true unless html_opts.delete(:redirect)
|
210
|
+
form_opts
|
211
|
+
end
|
212
|
+
|
213
|
+
def card_form_html_opts action, opts={}
|
214
|
+
add_class opts, "card-form"
|
215
|
+
add_class opts, "slotter" unless opts[:redirect] || opts[:no_slotter]
|
216
|
+
add_class opts, "autosave" if action == :update
|
217
|
+
opts
|
218
|
+
end
|
219
|
+
|
220
|
+
def card_form_url_and_action action
|
221
|
+
case action
|
222
|
+
when Symbol then [path(action: action), action]
|
223
|
+
when Hash then [path(action), action[:action]]
|
224
|
+
# for when non-action path args are required
|
225
|
+
else
|
226
|
+
raise Card::Error, "unsupported #card_form_url action: #{action}"
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
def editor_wrap type=nil
|
231
|
+
html_class = "editor"
|
232
|
+
html_class << " #{type}-editor" if type
|
233
|
+
wrap_with :div, class: html_class do
|
234
|
+
yield
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
# FIELD VIEWS
|
239
|
+
|
240
|
+
def add_junction_class
|
241
|
+
return unless card.name.junction?
|
242
|
+
|
243
|
+
class_up "card-editor", "RIGHT-#{card.name.tag_name.safe_key}"
|
244
|
+
end
|
245
|
+
end
|