support_desk 0.1.0 → 0.1.2
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/CHANGELOG.md +36 -0
- data/README.md +11 -1
- data/app/helpers/support_desk/engine_helper.rb +40 -4
- data/app/views/chats/slots/_inbox_top.html.erb +9 -3
- data/lib/support_desk/models/desk.rb +6 -0
- data/lib/support_desk/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c258a259ca701d1c8850126370d587f1297eba3429ec0649912258596ac3789d
|
|
4
|
+
data.tar.gz: 48684ab7f4b23e2d76e2c17839bf602900e4e22123ef41400595546caedcdcf4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 70aa54f8c81942b81f10e00b7259825ca003b71bafb127fac498cb8325562207abd1a5a76628d41163c78e04ee3ca5bd5833d1bdd40b4b8756bd7a136225fec2
|
|
7
|
+
data.tar.gz: 65cddb6b49effbb1898a91c06cc44ce7944215c2139ce885580ec79faabd7c682693b171b589b756f7cab9fb1cb0f4b07df8532872e68b9ab3ddcfdeb2f9a9e2
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,42 @@ All notable changes to this project are documented here.
|
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [0.1.2] - 2026-09-16
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
- **0.1.1 shipped without the thing it was released for.** The gem published
|
|
11
|
+
to rubygems as 0.1.1 was built from a tree that predated the merge, so
|
|
12
|
+
`SupportDesk::Desk` never declared `verified: true` and no desk was ever
|
|
13
|
+
badged — while the release notes said it was. The repository was correct
|
|
14
|
+
the whole time; only the package was wrong, which is the worst shape for
|
|
15
|
+
this kind of mistake because nothing in git looks off.
|
|
16
|
+
|
|
17
|
+
`SupportDesk::Desk.chat_verified?` now returns true, and a test asserts it
|
|
18
|
+
against the loaded class rather than the source file, so a package built
|
|
19
|
+
from the wrong tree fails instead of shipping quietly.
|
|
20
|
+
|
|
21
|
+
## [0.1.1] - 2026-09-16
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- **The desk is an official account.** `SupportDesk::Desk` now declares
|
|
26
|
+
`acts_as_messager verified: true` (chats 0.3.0), so chats badges it
|
|
27
|
+
wherever it names a messager: the grouped inbox row and the case thread's
|
|
28
|
+
header. A requester can tell the real desk from anyone who simply called
|
|
29
|
+
themselves "Soporte" without reading the name carefully — which matters
|
|
30
|
+
more here than anywhere else in a product, because the desk is the one
|
|
31
|
+
counterpart that legitimately asks people for account details. The badge
|
|
32
|
+
is chats' own; recolour it with the `--chats-verified` CSS variable or
|
|
33
|
+
replace it with `Chats.configure { |c| c.verified_badge = … }`.
|
|
34
|
+
- **The inbox door is badged too.** The door that stands in for the desk's
|
|
35
|
+
inbox row before a requester has written now carries the same mark, so the
|
|
36
|
+
badge reads as a property of the account rather than of having already
|
|
37
|
+
written to us. It still never INSERTs a desk (`support_desk_record` is a
|
|
38
|
+
find-or-stand-in, never `SupportDesk.desk`, whose first call in a process
|
|
39
|
+
creates the row), and it costs no query of its own: the door's avatar and
|
|
40
|
+
its badge share one memoised lookup per render, pinned by a query-count
|
|
41
|
+
test.
|
|
42
|
+
|
|
7
43
|
## [0.1.0] - 2026-09-16
|
|
8
44
|
|
|
9
45
|
First release: the whole core of a support desk, on top of `chats` 0.2.
|
data/README.md
CHANGED
|
@@ -7,6 +7,16 @@
|
|
|
7
7
|
|
|
8
8
|
`support_desk` gives your Rails app a **support desk**: tickets that are real conversations. Somebody asks for help about something in your app (a ride, an order, a withdrawal) or about nothing in particular, your desk answers, humans sign the answers, and your team works a queue.
|
|
9
9
|
|
|
10
|
+
Here is the whole thing — the kind of support desk a DoorDash, an Uber Eats or a Grab needs — running on a made-up delivery app called Pepperbox. These are the **bundled views**, unmodified, themed by the host with a handful of CSS variables:
|
|
11
|
+
|
|
12
|
+
| One row, every case | Pick a topic | Which order? |
|
|
13
|
+
|:---:|:---:|:---:|
|
|
14
|
+
|  |  |  |
|
|
15
|
+
| **Say what happened** | **Signed by a human** | **The agent queue** |
|
|
16
|
+
|  |  |  |
|
|
17
|
+
| **The whole case** | **Notes stay inside** | **Hand it over** |
|
|
18
|
+
|  |  |  |
|
|
19
|
+
|
|
10
20
|
It is a product gem on the [`chats`](https://github.com/rameerez/chats) kernel: chats owns the transcript, realtime, attachments, read state and moderation; `support_desk` owns the case — topics, assignment, SLA clocks, events and the console API.
|
|
11
21
|
|
|
12
22
|
Every app eventually needs a support inbox, and everyone rebuilds the same ticket table, the same "assigned to me" tab, the same "which order is this about?" picker and the same email bridge. `support_desk` is that whole rebuild, done once, done right, on top of the messaging you already have.
|
|
@@ -458,7 +468,7 @@ with_support_config(reply_policy: :assignee_only) { … }
|
|
|
458
468
|
|
|
459
469
|
After checking out the repo, run `bundle install`, then `bundle exec rake ci`. The dummy app lives in `test/dummy` and mounts all three surfaces the way a real host does: the requester engine at `/messages/support`, `chats` at `/messages`, and the turnkey console at `/admin/support` — plus the same console again inside a host-owned `madmin` namespace, because "the console uses only the public API" is a claim that needs a second implementation to be worth anything.
|
|
460
470
|
|
|
461
|
-
`chats` is the kernel this gem is a product on and the two are developed in lockstep, so the Gemfile points at a sibling checkout (`../chats`)
|
|
471
|
+
`chats` is the kernel this gem is a product on and the two are developed in lockstep, so the Gemfile points at a sibling checkout (`../chats`) whenever this gem needs a `chats` that is not on rubygems yet. It currently requires `chats` ~> 0.3 (the `verified:` messager option).
|
|
462
472
|
|
|
463
473
|
## Contributing
|
|
464
474
|
|
|
@@ -105,21 +105,57 @@ module SupportDesk
|
|
|
105
105
|
!viewer.support_tickets.exists?
|
|
106
106
|
end
|
|
107
107
|
|
|
108
|
+
# The desk RECORD for +desk_key+, resolved WITHOUT ever creating one.
|
|
109
|
+
#
|
|
110
|
+
# `SupportDesk.desk` is memoised for the life of the process, but its
|
|
111
|
+
# first call in that process INSERTs (`Desk.for` is find-or-create), and
|
|
112
|
+
# this renders on an inbox that may have nothing to do with support: a
|
|
113
|
+
# page view is not a reason to write a row.
|
|
114
|
+
#
|
|
115
|
+
# Before anybody has ever written there is no row, so this hands back an
|
|
116
|
+
# UNSAVED stand-in carrying the key. `name`, `display_name` and `avatar`
|
|
117
|
+
# all answer from configuration, so it renders exactly like the real
|
|
118
|
+
# thing — the same "null object that still renders" the topic tree uses.
|
|
119
|
+
# That keeps the door's badge a property of the ACCOUNT rather than of
|
|
120
|
+
# whether the table happens to have a row yet, and it means
|
|
121
|
+
# `Chats.config.verified_badge` is always handed a SupportDesk::Desk and
|
|
122
|
+
# never a Class.
|
|
123
|
+
#
|
|
124
|
+
# Memoised per view instance, so the door's avatar and its badge cost ONE
|
|
125
|
+
# query between them rather than one each.
|
|
126
|
+
def support_desk_record(desk_key = :default)
|
|
127
|
+
key = desk_key.to_s
|
|
128
|
+
@support_desk_records ||= {}
|
|
129
|
+
@support_desk_records[key] ||= SupportDesk::Desk.find_by(key: key) || SupportDesk::Desk.new(key: key)
|
|
130
|
+
end
|
|
131
|
+
|
|
108
132
|
# The desk's face. Once the desk has a row it is just another chats
|
|
109
133
|
# messager, so chats draws it; before that (nobody has ever written to
|
|
110
134
|
# it) an initials disc from `config.name`.
|
|
111
135
|
#
|
|
112
|
-
# It never CREATES the desk
|
|
113
|
-
# nothing to do with support, and a page view is not a reason to INSERT.
|
|
136
|
+
# It never CREATES the desk — see support_desk_record.
|
|
114
137
|
def support_desk_avatar(desk_key = :default, css_class: "chats-avatar")
|
|
115
|
-
desk =
|
|
116
|
-
return chats_messager_avatar(desk, css_class: css_class) if desk
|
|
138
|
+
desk = support_desk_record(desk_key)
|
|
139
|
+
return chats_messager_avatar(desk, css_class: css_class) if desk.persisted?
|
|
117
140
|
|
|
118
141
|
name = SupportDesk.config.desk(desk_key).name
|
|
119
142
|
initials = name.to_s.split.first(2).filter_map { |word| word[0] }.join.upcase
|
|
120
143
|
tag.span(initials.presence || "?", class: "#{css_class} chats-avatar--initials", "aria-hidden": true)
|
|
121
144
|
end
|
|
122
145
|
|
|
146
|
+
# The desk's official-account badge (chats' `verified:` option), for the
|
|
147
|
+
# door — the entry that stands in for the desk's own inbox row before the
|
|
148
|
+
# requester has written.
|
|
149
|
+
#
|
|
150
|
+
# chats badges that real row from the moment it exists, so without this
|
|
151
|
+
# somebody would see an unbadged "Soporte" before their first case and a
|
|
152
|
+
# badged one after, which makes the mark read as a property of having
|
|
153
|
+
# written to us rather than of the account. Renders nothing if a host
|
|
154
|
+
# ever declares its desk unverified.
|
|
155
|
+
def support_desk_badge(desk_key = :default)
|
|
156
|
+
chats_verified_badge(support_desk_record(desk_key))
|
|
157
|
+
end
|
|
158
|
+
|
|
123
159
|
# Where a case is read and answered: its chats conversation. Falls back
|
|
124
160
|
# to the engine's own ticket URL (which redirects to the same place) for
|
|
125
161
|
# the one case that has no conversation yet, so a link is never dead.
|
|
@@ -9,16 +9,22 @@
|
|
|
9
9
|
Locals come from chats' inbox (viewer:, inbox:). Renders nothing under
|
|
10
10
|
:when_tickets or :never, and nothing once there is a real row to show. %>
|
|
11
11
|
<% if support_inbox_door?(viewer) %>
|
|
12
|
+
<% desk_key = viewer.class.try(:support_desk_key) || :default %>
|
|
12
13
|
<%= support_desk_styles %>
|
|
13
14
|
<ul class="chats-inbox__list support-desk-inbox-door">
|
|
14
15
|
<li class="chats-row">
|
|
15
16
|
<%= link_to support_desk_routes.root_path, class: "chats-row__link" do %>
|
|
16
|
-
<%= support_desk_avatar(
|
|
17
|
+
<%= support_desk_avatar(desk_key) %>
|
|
17
18
|
|
|
18
19
|
<span class="chats-row__body">
|
|
19
20
|
<span class="chats-row__top">
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
<%# Same shape chats gives its own rows: the name ellipsizes, the
|
|
22
|
+
official-account badge beside it always shows. %>
|
|
23
|
+
<span class="chats-row__name">
|
|
24
|
+
<span class="chats-row__title">
|
|
25
|
+
<%= SupportDesk.config.desk(desk_key).name %>
|
|
26
|
+
</span>
|
|
27
|
+
<%= support_desk_badge(desk_key) %>
|
|
22
28
|
</span>
|
|
23
29
|
</span>
|
|
24
30
|
<span class="chats-row__bottom">
|
|
@@ -9,6 +9,11 @@ module SupportDesk
|
|
|
9
9
|
# one. Its conversations collapse into a single grouped inbox row, so
|
|
10
10
|
# somebody with four open tickets sees "Soporte" once, not four times.
|
|
11
11
|
#
|
|
12
|
+
# It is also a VERIFIED messager: a desk is the official voice of the
|
|
13
|
+
# product, and the person writing to it should be able to tell that from
|
|
14
|
+
# an impostor without reading the name carefully. chats badges it wherever
|
|
15
|
+
# it shows a messager's name.
|
|
16
|
+
#
|
|
12
17
|
# SupportDesk.desk # the :default desk, memoised
|
|
13
18
|
# SupportDesk.desk(:billing) # another one
|
|
14
19
|
#
|
|
@@ -20,6 +25,7 @@ module SupportDesk
|
|
|
20
25
|
acts_as_messager notifications: false,
|
|
21
26
|
blockable: false,
|
|
22
27
|
inbox: :grouped,
|
|
28
|
+
verified: true,
|
|
23
29
|
group_path: ->(_viewer) { SupportDesk.root_path }
|
|
24
30
|
|
|
25
31
|
has_many :tickets,
|
data/lib/support_desk/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: support_desk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- rameerez
|
|
@@ -55,14 +55,14 @@ dependencies:
|
|
|
55
55
|
requirements:
|
|
56
56
|
- - "~>"
|
|
57
57
|
- !ruby/object:Gem::Version
|
|
58
|
-
version: '0.
|
|
58
|
+
version: '0.3'
|
|
59
59
|
type: :runtime
|
|
60
60
|
prerelease: false
|
|
61
61
|
version_requirements: !ruby/object:Gem::Requirement
|
|
62
62
|
requirements:
|
|
63
63
|
- - "~>"
|
|
64
64
|
- !ruby/object:Gem::Version
|
|
65
|
-
version: '0.
|
|
65
|
+
version: '0.3'
|
|
66
66
|
- !ruby/object:Gem::Dependency
|
|
67
67
|
name: globalid
|
|
68
68
|
requirement: !ruby/object:Gem::Requirement
|