1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
require "pro_tacts/admin/phlex"
require "pro_tacts/admin/group_label"
require "pro_tacts/admin/layout"
require "pro_tacts/admin/list_item"
module ProTacts
module Admin
# GET /groups — every group and how many cards it lends to, with
# the create dialog riding along hidden the way the dashboard's
# does (see ContactDialog for why a popover). A group needs nothing
# to exist — no name, no lines, no members (db/migrations/
# 005_group_identity.rb) — so the dialog's one field is optional,
# and a create lands on the new group's editor, where everything
# it will hold is added.
class GroupsIndex < Phlex::HTML
# @rbs @groups: Array[Group]
# @rbs @login: String
# @rbs @notice: String?
#: (groups: Array[Group], login: String, ?notice: String?) -> void
def initialize(groups:, login:, notice: nil)
@login = login
# `Group#<=>`'s order, sorted here rather than asked of the
# store the way ContactsIndex sorts its rows: #all_groups is
# ordered by id so that a rename never moves a tag, and only
# this listing wants the reader's order.
@groups = groups.sort
@notice = notice
end
def view_template
render Layout.new(title: "Groups", login: @login, notice: @notice) do
section do
div(class: "section-head") do
h2(class: "type-label") { "groups" }
button(data_size: "sm", popovertarget: "new-group") { "add group" }
end
if @groups.empty?
p(class: "type-body-sm") { "No groups yet." }
else
ul(class: "card") do
@groups.each do |group|
render ListItem.new(
href: "/groups/#{group.id}",
trailing: members_label(group),
) { render GroupLabel.new(group:) }
end
end
end
end
new_group_dialog
end
end
private
#: (Group group) -> String
def members_label(group)
count = group.members.length
count == 1 ? "1 member" : "#{count} members"
end
#: () -> void
def new_group_dialog
dialog(id: "new-group", popover: "auto") do
header { "New group" }
form(id: "new-group-form", action: "/groups", method: "post") do
label(class: "field") do
plain "Name"
input(type: "text", name: "name", autofocus: true)
end
end
footer do
button(type: "button", popovertarget: "new-group",
popovertargetaction: "hide") { "Cancel" }
button(type: "submit", form: "new-group-form",
data: {variant: "primary"}) { "Create" }
end
end
end
end
end
end