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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: a7bdfc901290eeb41d413810325770cbb1a84550f5904ac31f040199bb6ea867
|
4
|
+
data.tar.gz: 2bc78ed7d0e52c36cb1780cdf094d42923c5cc8acaffcfd860895b09cdad6e42
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 837208fbdc76eabc11fc0994c0f6287266479d4e157ec7468eb6333bd628b897c11413a829c35d2bd44b68ce08f06365c9b63f38f717d9ae6695713c927d85cb
|
7
|
+
data.tar.gz: 1fd91ea28bfbdc343dbf7f240b102e32e6d0249531ed212643d07b9f2bfbce262d553c55bc278dd23f98a4f5475a5697c30bb48de67e18924f72815b4fde06e7
|
data/set/all/bridge.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
format :html do
|
2
|
+
BRIDGE_TABS = { "Account" => :account_tab,
|
3
|
+
"Guide" => :guide_tab,
|
4
|
+
"Engage" => :engage_tab,
|
5
|
+
"History" => :history_tab,
|
6
|
+
"Related" => :related_tab,
|
7
|
+
"Rules" => :rules_tab }.freeze
|
8
|
+
|
9
|
+
wrapper :bridge do
|
10
|
+
class_up "modal-dialog", "no-gaps"
|
11
|
+
voo.hide! :modal_footer
|
12
|
+
wrap_with_modal size: :full, title: bridge_breadcrumbs do
|
13
|
+
haml :bridge
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def bridge_tabs
|
18
|
+
wrap do
|
19
|
+
tabs(visible_bridge_tabs, bridge_tab, load: :lazy) { _render bridge_tab }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def bridge_tab
|
24
|
+
@bridge_tab ||= bridge_param :tab
|
25
|
+
end
|
26
|
+
|
27
|
+
def bridge_param key
|
28
|
+
params.dig(:bridge, key)&.to_sym || try("default_bridge_#{key}")
|
29
|
+
end
|
30
|
+
|
31
|
+
def bridge_breadcrumbs
|
32
|
+
<<-HTML.strip_heredoc
|
33
|
+
<nav aria-label="breadcrumb">
|
34
|
+
<ol class="breadcrumb _bridge-breadcrumb">
|
35
|
+
<li class="breadcrumb-item">#{card.name}</li>
|
36
|
+
<li class="breadcrumb-item active">Edit</li>
|
37
|
+
</ol>
|
38
|
+
</nav>
|
39
|
+
HTML
|
40
|
+
end
|
41
|
+
|
42
|
+
def bridge_link_opts opts={}
|
43
|
+
opts[:"data-slot-selector"] = bridge_slot_selector
|
44
|
+
opts[:remote] = true
|
45
|
+
add_class opts, "slotter"
|
46
|
+
opts.bury :path, :layout, :overlay
|
47
|
+
opts[:path][:view] ||= :content
|
48
|
+
opts
|
49
|
+
end
|
50
|
+
|
51
|
+
def bridge_slot_selector
|
52
|
+
".bridge-main > .overlay-container > .card-slot._bottomlay-slot," \
|
53
|
+
".bridge-main > ._overlay-container-placeholder > .card-slot"
|
54
|
+
end
|
55
|
+
|
56
|
+
def default_bridge_tab
|
57
|
+
show_guide_tab? ? :guide_tab : :engage_tab
|
58
|
+
end
|
59
|
+
|
60
|
+
def breadcrumb_data title, html_class=nil
|
61
|
+
html_class ||= title.underscore
|
62
|
+
{ "data-breadcrumb": title, "data-breadcrumb-class": html_class }
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
format :html do
|
2
|
+
BRIDGE_PILL_UL_CLASSES =
|
3
|
+
"nav nav-pills _auto-single-select bridge-pills flex-column".freeze
|
4
|
+
|
5
|
+
BRIDGE_PILL_LI_CLASSES = "nav-item".freeze
|
6
|
+
|
7
|
+
def bridge_pills items
|
8
|
+
list_tag class: BRIDGE_PILL_UL_CLASSES, items: { class: BRIDGE_PILL_LI_CLASSES } do
|
9
|
+
items
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def bridge_pill_items data, breadcrumb
|
14
|
+
data.map do |text, field, extra_opts|
|
15
|
+
opts = bridge_pill_item_opts breadcrumb, extra_opts, text
|
16
|
+
mark = opts.delete(:mark) == :absolute ? field : [card, field]
|
17
|
+
link_to_card mark, text, opts
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def bridge_pill_item_opts breadcrumb, extra_opts, text
|
22
|
+
opts = bridge_link_opts.merge("data-toggle": "pill")
|
23
|
+
opts.merge! breadcrumb_data(breadcrumb)
|
24
|
+
|
25
|
+
if extra_opts
|
26
|
+
classes = extra_opts.delete :class
|
27
|
+
add_class opts, classes if classes
|
28
|
+
opts.deep_merge! extra_opts
|
29
|
+
end
|
30
|
+
opts["data-cy"] = "#{text.to_name.key}-pill"
|
31
|
+
add_class opts, "nav-link"
|
32
|
+
opts
|
33
|
+
end
|
34
|
+
|
35
|
+
def bridge_pill_sections tab_name
|
36
|
+
wrap_with :ul, class: BRIDGE_PILL_UL_CLASSES do
|
37
|
+
yield.map { |args| bridge_pill_section(tab_name, *args) }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def bridge_pill_section tab_name, title, items
|
42
|
+
wrap_with(:h6, title, class: "ml-1 mt-3") +
|
43
|
+
wrap_each_with(:li, class: BRIDGE_PILL_LI_CLASSES) do
|
44
|
+
bridge_pill_items(items, tab_name)
|
45
|
+
end.html_safe
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
format :html do
|
2
|
+
def follow_section
|
3
|
+
return unless show_follow?
|
4
|
+
|
5
|
+
wrap_with :div, class: "mb-3" do
|
6
|
+
[follow_button_group, followers_bridge_link, follow_overview_button]
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def follow_button_group
|
11
|
+
wrap_with :div, class: "btn-group btn-group-sm follow-btn-group" do
|
12
|
+
[follow_button, follow_advanced]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def follow_overview_button
|
17
|
+
link_to_card [Auth.current, :follow], "all followed cards",
|
18
|
+
bridge_link_opts(class: "btn btn-sm btn-secondary",
|
19
|
+
"data-cy": "follow-overview")
|
20
|
+
end
|
21
|
+
|
22
|
+
def follow_advanced
|
23
|
+
opts = bridge_link_opts(class: "btn btn-sm btn-primary",
|
24
|
+
path: { view: :overlay_rule },
|
25
|
+
"data-cy": "follow-advanced")
|
26
|
+
opts[:path].delete :layout
|
27
|
+
link_to_card card.follow_rule_card(Auth.current.name, new: {}),
|
28
|
+
icon_tag("more_horiz"), opts
|
29
|
+
end
|
30
|
+
|
31
|
+
def followers_bridge_link
|
32
|
+
cnt = card.followers_count
|
33
|
+
link_to_card card.name.field(:followers), "#{cnt} follower#{'s' unless cnt == 1}",
|
34
|
+
bridge_link_opts(class: "btn btn-sm ml-2 btn-secondary slotter",
|
35
|
+
remote: true, "data-cy": "followers")
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
format :html do
|
2
|
+
RELATED_ITEMS =
|
3
|
+
{
|
4
|
+
"by name" => [["children", :children],
|
5
|
+
["mates", :mates]],
|
6
|
+
# FIXME: optimize,
|
7
|
+
"by content" => [["links out", :links_to],
|
8
|
+
["links in", :linked_to_by],
|
9
|
+
["nests", :nests],
|
10
|
+
["nested by", :nested_by],
|
11
|
+
["references out", :refers_to],
|
12
|
+
["references in", :referred_to_by]]
|
13
|
+
# ["by edit", [["creator", :creator],
|
14
|
+
# ["editors", :editors],
|
15
|
+
# ["last edited", :last_edited]]]
|
16
|
+
}.freeze
|
17
|
+
|
18
|
+
def related_by_name_items
|
19
|
+
pills = []
|
20
|
+
if card.name.junction?
|
21
|
+
pills += card.name.ancestors.map { |a| [a, a, { mark: :absolute }] }
|
22
|
+
end
|
23
|
+
pills += RELATED_ITEMS["by name"]
|
24
|
+
pills
|
25
|
+
end
|
26
|
+
|
27
|
+
def related_by_content_items
|
28
|
+
RELATED_ITEMS["by content"]
|
29
|
+
end
|
30
|
+
|
31
|
+
def related_by_type_items
|
32
|
+
[["#{card.type} cards", [card.type, :type, :by_name], mark: :absolute]]
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
format :html do
|
2
|
+
view :engage_tab, wrap: { div: { class: "m-3 mt-4 _engage-tab" } }, cache: :never do
|
3
|
+
[render_follow_section, discussion_section].compact
|
4
|
+
end
|
5
|
+
|
6
|
+
view :history_tab, wrap: :slot do
|
7
|
+
class_up "d0-card-body", "history-slot"
|
8
|
+
voo.hide :act_legend
|
9
|
+
acts_bridge_layout card.history_acts
|
10
|
+
end
|
11
|
+
|
12
|
+
view :related_tab do
|
13
|
+
bridge_pill_sections "Related" do
|
14
|
+
%w[name content type].map do |section_name|
|
15
|
+
["by #{section_name}", send("related_by_#{section_name}_items")]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
view :rules_tab, unknown: true do
|
21
|
+
class_up "card-slot", "flex-column"
|
22
|
+
wrap do
|
23
|
+
nest current_set_card, view: :bridge_rules_tab
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
view :follow_section, wrap: :slot, cache: :never do
|
28
|
+
follow_section
|
29
|
+
end
|
30
|
+
|
31
|
+
view :guide_tab, unknown: true do
|
32
|
+
render_guide
|
33
|
+
end
|
34
|
+
|
35
|
+
def discussion_section
|
36
|
+
return unless show_discussion?
|
37
|
+
|
38
|
+
field_nest(:discussion, view: :titled, title: "Discussion", show: :comment_box,
|
39
|
+
hide: [:menu])
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
format :html do
|
2
|
+
def visible_bridge_tabs
|
3
|
+
BRIDGE_TABS.select do |_title, view|
|
4
|
+
send "show_#{view}?"
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def show_engage_tab?
|
11
|
+
return unless card.real?
|
12
|
+
|
13
|
+
show_follow? || show_discussion?
|
14
|
+
end
|
15
|
+
|
16
|
+
def show_account_tab?
|
17
|
+
false
|
18
|
+
end
|
19
|
+
|
20
|
+
def show_history_tab?
|
21
|
+
card.real?
|
22
|
+
end
|
23
|
+
|
24
|
+
def show_related_tab?
|
25
|
+
card.real?
|
26
|
+
end
|
27
|
+
|
28
|
+
def show_rules_tab?
|
29
|
+
true
|
30
|
+
end
|
31
|
+
|
32
|
+
def show_guide_tab?
|
33
|
+
guide.present?
|
34
|
+
end
|
35
|
+
|
36
|
+
def show_discussion?
|
37
|
+
d_card = discussion_card
|
38
|
+
return unless d_card
|
39
|
+
|
40
|
+
permission_task = d_card.new_card? ? :update : :read
|
41
|
+
d_card.ok? permission_task
|
42
|
+
end
|
43
|
+
|
44
|
+
def discussion_card?
|
45
|
+
card.junction? && card.name.tag_name.key == :discussion.cardname.key
|
46
|
+
end
|
47
|
+
|
48
|
+
def discussion_card
|
49
|
+
return if card.new_card? || discussion_card?
|
50
|
+
|
51
|
+
card.fetch :discussion, skip_modules: true, new: {}
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
format :html do
|
2
|
+
view :edit_form, wrap: :slot do
|
3
|
+
voo.show :edit_type_row
|
4
|
+
with_nest_mode :edit do
|
5
|
+
edit_form
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def edit_form
|
10
|
+
voo.hide :edit_type_row
|
11
|
+
form_opts = edit_form_opts.reverse_merge success: edit_success
|
12
|
+
card_form(:update, form_opts) do
|
13
|
+
[
|
14
|
+
edit_view_hidden,
|
15
|
+
_render_edit_type_row(home_view: :edit_type_row),
|
16
|
+
# home_view is necessary for cancel to work correctly.
|
17
|
+
# it seems a little strange to have to think about home_view here,
|
18
|
+
# but the issue is that something currently has to happen prior to the
|
19
|
+
# render to get voo.slot_options to have the write home view in
|
20
|
+
# the slot wrap. Id think this would probably best be handled as an
|
21
|
+
# option to #wrap that triggers a new heir voo
|
22
|
+
_render_content_formgroups,
|
23
|
+
_render_edit_buttons
|
24
|
+
]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
view :edit, perms: :update, unknown: true, cache: :never,
|
29
|
+
wrap: { modal: { footer: "",
|
30
|
+
size: :edit_modal_size,
|
31
|
+
title: :render_title,
|
32
|
+
menu: :edit_modal_menu } } do
|
33
|
+
add_name_context
|
34
|
+
with_nest_mode :edit do
|
35
|
+
voo.show :help
|
36
|
+
voo.hide :save_button
|
37
|
+
wrap true do
|
38
|
+
[
|
39
|
+
frame_help,
|
40
|
+
_render_edit_form
|
41
|
+
]
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def edit_modal_size
|
47
|
+
:large
|
48
|
+
end
|
49
|
+
|
50
|
+
def edit_modal_menu
|
51
|
+
wrap_with_modal_menu do
|
52
|
+
[close_modal_window, render_bridge_link]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def edit_form_opts
|
57
|
+
# for override
|
58
|
+
{ "data-slot-selector": "modal-origin", "data-slot-error-selector": ".card-slot" }
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
format :html do
|
2
|
+
view :edit_inline, perms: :update, unknown: true, cache: :never, wrap: :slot do
|
3
|
+
voo.hide :name_formgroup, :type_formgroup
|
4
|
+
with_nest_mode :edit do
|
5
|
+
card_form :update, success: edit_success do
|
6
|
+
[
|
7
|
+
edit_view_hidden,
|
8
|
+
_render_content_formgroups,
|
9
|
+
_render_edit_inline_buttons
|
10
|
+
]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
view :edit_name_row do
|
16
|
+
edit_row_fixed_width "Name", card.name, :name_form
|
17
|
+
end
|
18
|
+
|
19
|
+
view :edit_inline_buttons do
|
20
|
+
button_formgroup do
|
21
|
+
wrap_with "div", class: "d-flex" do
|
22
|
+
[standard_save_button, cancel_in_place_button, delete_button]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# TODO: better styling for this so that is reusable
|
28
|
+
# At the moment it is used for the name and type field in the bridge
|
29
|
+
# (with fixed 50px width for the title column) and
|
30
|
+
# for password and email for accounts (with fixed 75px width for the title column)
|
31
|
+
# The view is very similar to labeled but with fixed edit link on the right
|
32
|
+
# and a fixed width for the labels so that the content column is aligned
|
33
|
+
# There is also the problem that label and content are not vertically aligned
|
34
|
+
view :edit_row do
|
35
|
+
edit_row_fixed_width render_title, render_core, :edit_inline, 75
|
36
|
+
end
|
37
|
+
|
38
|
+
def edit_row_fixed_width title, content, edit_view, width=50
|
39
|
+
class_up "card-slot", "d-flex"
|
40
|
+
wrap do
|
41
|
+
["<label class='w-#{width}px'>#{title}</label>",
|
42
|
+
content,
|
43
|
+
edit_inline_link(edit_view, align: :right)]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def edit_inline_link view=:edit_inline, align: :left
|
48
|
+
align = align == :left ? "ml-2" : "ml-auto"
|
49
|
+
link_to_view view, menu_icon, class: "#{align} edit-link", "data-cy": "edit-link"
|
50
|
+
end
|
51
|
+
|
52
|
+
def cancel_in_place_button args={}
|
53
|
+
args.reverse_merge! class: "cancel-button btn-sm", href: path
|
54
|
+
cancel_button args
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
format :html do
|
2
|
+
# note: depends on js with selector ".edit_name-view .card-form"
|
3
|
+
view :edit_name, perms: :update do
|
4
|
+
frame { name_form }
|
5
|
+
end
|
6
|
+
|
7
|
+
# note: depends on js with selector ".name_form-view .card-form"
|
8
|
+
view :name_form, perms: :update, wrap: :slot, cache: :never do
|
9
|
+
name_form :edit_name_row
|
10
|
+
end
|
11
|
+
|
12
|
+
def name_form success_view=nil
|
13
|
+
card_form({ action: :update, id: card.id },
|
14
|
+
# "main-success" => "REDIRECT",
|
15
|
+
"data-update-origin": "true",
|
16
|
+
success: edit_name_success(success_view)) do
|
17
|
+
[hidden_edit_name_fields,
|
18
|
+
_render_name_formgroup,
|
19
|
+
rename_confirmation_alert,
|
20
|
+
edit_name_buttons]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def edit_name_success view=nil
|
25
|
+
success = { id: "_self" }
|
26
|
+
success[:view] = view if view
|
27
|
+
success
|
28
|
+
end
|
29
|
+
|
30
|
+
def hidden_edit_name_fields
|
31
|
+
hidden_tags old_name: card.name, card: { update_referers: false }
|
32
|
+
end
|
33
|
+
|
34
|
+
def edit_name_buttons
|
35
|
+
button_formgroup do
|
36
|
+
[rename_and_update_button, rename_button, standard_cancel_button]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# LOCALIZE
|
41
|
+
def rename_and_update_button
|
42
|
+
submit_button text: "Rename and Update", disable_with: "Renaming",
|
43
|
+
class: "renamer-updater"
|
44
|
+
end
|
45
|
+
|
46
|
+
def rename_button
|
47
|
+
button_tag "Rename", data: { disable_with: "Renaming" }, class: "renamer"
|
48
|
+
end
|
49
|
+
|
50
|
+
# LOCALIZE
|
51
|
+
def rename_confirmation_alert
|
52
|
+
msg = "<h5>Are you sure you want to rename <em>#{safe_name}</em>?</h5>"
|
53
|
+
msg << %(<h6>This may change names referred to by other cards.</h6>)
|
54
|
+
msg << %(<p>You may choose to <em>update or ignore</em> the referers.</p>)
|
55
|
+
msg << hidden_field_tag(:referers, 1)
|
56
|
+
alert("warning", false, false, class: "hidden-alert") { msg }
|
57
|
+
end
|
58
|
+
end
|