testimonials 0.9.0 → 0.9.1
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/AGENTS.md +1 -1
- data/CHANGELOG.md +12 -0
- data/lib/testimonials/dashboard.css +14 -0
- data/lib/testimonials/seeds.rb +22 -12
- data/lib/testimonials/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0cbc7f22314c712ecb0e1eb5d92a3d66981193bc1fc19f8664f635d381db0045
|
|
4
|
+
data.tar.gz: '020981c67a45702104ebf9cdfd9f685ffc17d44653a3476560c0fb662176e445'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1ca4a49fd102d401ae88b344c951655e68e88af3fb0da1a11819b7b600edb9ad11543feb5440a25f2127e138f4da54d9d7447a3b260a79d7e3cb59b5abcdbfb2
|
|
7
|
+
data.tar.gz: d8c94fe02b56b3e91adf3eb39e1c87e88b70d4f0d9ed4102e8058901b019f0a1c5fb4d1d02327be255c18b5ca58afedae06e7386efd58978d16d017fde1bc8d5
|
data/AGENTS.md
CHANGED
|
@@ -210,6 +210,6 @@ Conventions this codebase holds to — follow them rather than the first thing t
|
|
|
210
210
|
- **Every install shape gets a test that drops the table for real** (`test/integration/skip_nps_test.rb`, `skip_prompt_events_test.rb`), so a slipped guard raises `no such table` instead of passing quietly. Generator tests pin each migration and initializer shape and check the ERB still compiles as Ruby.
|
|
211
211
|
- **The widget is plain ES5-style JS in `lib/testimonials/widget.js`**, served by the engine, no build step, no framework. It reads its config from a JSON block on every `turbo:load`.
|
|
212
212
|
- **Display stays headless.** New display UI belongs in `examples/`, not in `app/views`.
|
|
213
|
-
- **`lib/testimonials/dashboard.css` is half shared.** Everything above the `GEM-SPECIFIC` banner is the design system all five gems in the family ship — the same tokens, the same `.page-head`/`.tabs`/`.filters`/`.card`/`.badge`/`button`, the same `.dashboard-shell` + `.record-row` + `.detail-panel` two-pane dashboard — identical in every repo apart from the `tml` prefix. Diff it against a sibling before changing it, and carry the change to the other four. Anything only this gem has goes below the banner. New dashboard markup reuses the shared class names rather than inventing a domain-specific one.
|
|
213
|
+
- **`lib/testimonials/dashboard.css` is half shared.** Everything above the `GEM-SPECIFIC` banner is the design system all five gems in the family ship — the same tokens, the same `.page-head`/`.tabs`/`.filters`/`.card`/`.badge`/`button`/`.status-switch`, the same `.dashboard-shell` + `.record-row` + `.detail-panel` two-pane dashboard — identical in every repo apart from the `tml` prefix. Diff it against a sibling before changing it, and carry the change to the other four. Anything only this gem has goes below the banner. New dashboard markup reuses the shared class names rather than inventing a domain-specific one.
|
|
214
214
|
- Every user-facing change bumps `lib/testimonials/version.rb` and adds a `CHANGELOG.md` entry that says what it costs, not only what it adds.
|
|
215
215
|
- Commit messages are prose that explains the tradeoff — read `git log` before writing one.
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.9.1
|
|
4
|
+
|
|
5
|
+
- **The demo data now teaches responsible collection.** Its testimonials cover
|
|
6
|
+
success-moment prompting, pending moderation, public consent, private
|
|
7
|
+
archiving, best lines, and the shared approval rules for text and video. The
|
|
8
|
+
promoter, passive, and detractor comments explain why the balanced sample has
|
|
9
|
+
an NPS of zero.
|
|
10
|
+
- The bundled video remains intentionally generic: it proves protected upload
|
|
11
|
+
and playback without pretending to be customer evidence. Rerunning
|
|
12
|
+
`testimonials:seed_demo` refreshes the existing demo rows and can overwrite
|
|
13
|
+
edits to them; non-demo customer records are not touched.
|
|
14
|
+
|
|
3
15
|
## 0.9.0
|
|
4
16
|
|
|
5
17
|
- **One design system across the family.** The stylesheet now opens with a
|
|
@@ -144,6 +144,19 @@
|
|
|
144
144
|
& .actions form { display: inline; }
|
|
145
145
|
& .form-actions { padding-top: 12px; }
|
|
146
146
|
|
|
147
|
+
/* Status switch: one pill holding every state a record can be in, the state it
|
|
148
|
+
is in now lit. Each other segment is a submit button, so moving a record
|
|
149
|
+
takes one click and no JavaScript; the current segment is a `type="button"`
|
|
150
|
+
so clicking it cannot re-file the record it is already filed under. Two
|
|
151
|
+
states or five, the pill sizes itself. A gem tints the lit segment with its
|
|
152
|
+
own status colour — see the `GEM-SPECIFIC` section. */
|
|
153
|
+
& .status-switch { display: inline-flex; flex: 0 0 auto; margin: 0; padding: 3px; border: 1px solid var(--tml-border); border-radius: 999px; background: var(--tml-bg); }
|
|
154
|
+
& .status-switch button { min-height: 30px; padding: 0 12px; border: 0; border-radius: 999px; background: none; color: var(--tml-muted); font-size: 13px; font-weight: 700; white-space: nowrap; transition: background .16s ease, color .16s ease; }
|
|
155
|
+
& .status-switch button:hover { border: 0; background: color-mix(in srgb, var(--tml-muted) 12%, transparent); color: var(--tml-text); }
|
|
156
|
+
& .status-switch button.current { background: var(--tml-surface); color: var(--tml-text); box-shadow: 0 1px 2px rgba(15, 23, 42, .12); cursor: default; }
|
|
157
|
+
& .status-switch button.current:hover { background: var(--tml-surface); }
|
|
158
|
+
& .panel-head .status-switch { margin-left: auto; }
|
|
159
|
+
|
|
147
160
|
& .card { overflow: hidden; border: 1px solid var(--tml-border); border-radius: 12px; background: var(--tml-surface); }
|
|
148
161
|
& .card.pad { padding: 16px; overflow: visible; }
|
|
149
162
|
& table { width: 100%; border-collapse: collapse; }
|
|
@@ -266,6 +279,7 @@
|
|
|
266
279
|
& .dashboard-detail .detail-panel { min-height: calc(100vh - 64px); }
|
|
267
280
|
& .mobile-back { display: block; flex: 0 0 auto; margin: 4px 0 10px; font-size: 13px; }
|
|
268
281
|
& .panel-head h1 { font-size: 18px; }
|
|
282
|
+
& .status-switch button { padding: 0 9px; font-size: 12px; }
|
|
269
283
|
& dl { grid-template-columns: 1fr; gap: 3px; }
|
|
270
284
|
& dd { margin-bottom: 8px; }
|
|
271
285
|
}
|
data/lib/testimonials/seeds.rb
CHANGED
|
@@ -9,8 +9,10 @@ module Testimonials
|
|
|
9
9
|
{
|
|
10
10
|
seed_id: 'approved-founder',
|
|
11
11
|
kind: 'text',
|
|
12
|
-
body: 'We
|
|
13
|
-
|
|
12
|
+
body: 'We call testimonial_prompt! after a customer completes onboarding, when the value is still ' \
|
|
13
|
+
'fresh. The prompt feels earned, and the quotes are much more specific than the ones we used ' \
|
|
14
|
+
'to request by email.',
|
|
15
|
+
best_line: 'Ask after a real success moment and the quotes become specific.',
|
|
14
16
|
rating: 5,
|
|
15
17
|
status: 'approved',
|
|
16
18
|
featured: true,
|
|
@@ -18,7 +20,7 @@ module Testimonials
|
|
|
18
20
|
consent_text: 'You can use my testimonial publicly in your marketing and sales.',
|
|
19
21
|
name: 'Maya Chen',
|
|
20
22
|
email: 'maya@example.com',
|
|
21
|
-
title_company: 'Founder,
|
|
23
|
+
title_company: 'Founder, Demo CRM',
|
|
22
24
|
source: 'widget',
|
|
23
25
|
page_url: '/onboarding/complete',
|
|
24
26
|
locale: 'en'
|
|
@@ -26,7 +28,9 @@ module Testimonials
|
|
|
26
28
|
{
|
|
27
29
|
seed_id: 'pending-operator',
|
|
28
30
|
kind: 'text',
|
|
29
|
-
body: '
|
|
31
|
+
body: 'This response has public consent, but it is still pending. That separation gives our team a ' \
|
|
32
|
+
'chance to verify the quote, choose a best line, and approve it before anything appears on the ' \
|
|
33
|
+
'wall of love.',
|
|
30
34
|
rating: 4,
|
|
31
35
|
status: 'pending',
|
|
32
36
|
featured: false,
|
|
@@ -34,7 +38,7 @@ module Testimonials
|
|
|
34
38
|
consent_text: 'You can use my testimonial publicly in your marketing and sales.',
|
|
35
39
|
name: 'Jon Bell',
|
|
36
40
|
email: 'jon@example.com',
|
|
37
|
-
title_company: 'Operations Lead,
|
|
41
|
+
title_company: 'Operations Lead, Example Co',
|
|
38
42
|
source: 'nps',
|
|
39
43
|
page_url: '/reports',
|
|
40
44
|
locale: 'en'
|
|
@@ -42,7 +46,8 @@ module Testimonials
|
|
|
42
46
|
{
|
|
43
47
|
seed_id: 'private-archive',
|
|
44
48
|
kind: 'text',
|
|
45
|
-
body: '
|
|
49
|
+
body: 'I am happy for the team to keep this feedback internally, but I did not consent to public ' \
|
|
50
|
+
'use. Archiving it keeps the learning without making it publishable.',
|
|
46
51
|
rating: 3,
|
|
47
52
|
status: 'archived',
|
|
48
53
|
featured: false,
|
|
@@ -58,8 +63,10 @@ module Testimonials
|
|
|
58
63
|
{
|
|
59
64
|
seed_id: 'approved-video',
|
|
60
65
|
kind: 'video',
|
|
61
|
-
body: '
|
|
62
|
-
|
|
66
|
+
body: 'The attached clip is intentionally generic demo media. It proves the upload, review, and ' \
|
|
67
|
+
'protected playback path; replace it with a real customer recording before using this record ' \
|
|
68
|
+
'anywhere public.',
|
|
69
|
+
best_line: 'Video follows the same consent and approval workflow as text.',
|
|
63
70
|
rating: 5,
|
|
64
71
|
status: 'approved',
|
|
65
72
|
featured: true,
|
|
@@ -67,7 +74,7 @@ module Testimonials
|
|
|
67
74
|
consent_text: 'You can use my testimonial publicly in your marketing and sales.',
|
|
68
75
|
name: 'Alex Rivera',
|
|
69
76
|
email: 'alex@example.com',
|
|
70
|
-
title_company: 'Head of Product,
|
|
77
|
+
title_company: 'Head of Product, Demo Video Co',
|
|
71
78
|
source: 'page',
|
|
72
79
|
page_url: '/testimonials/new',
|
|
73
80
|
locale: 'en'
|
|
@@ -76,9 +83,12 @@ module Testimonials
|
|
|
76
83
|
|
|
77
84
|
NPS_RESPONSES = [
|
|
78
85
|
{ seed_id: 'promoter', score: 10,
|
|
79
|
-
comment: '
|
|
80
|
-
{ seed_id: 'passive', score: 8,
|
|
81
|
-
|
|
86
|
+
comment: 'A 9 or 10 is a promoter. One promoter contributes positively to the NPS score.' },
|
|
87
|
+
{ seed_id: 'passive', score: 8,
|
|
88
|
+
comment: 'A 7 or 8 is passive. Keep the feedback, but this response does not move the NPS score.' },
|
|
89
|
+
{ seed_id: 'detractor', score: 4,
|
|
90
|
+
comment: 'A score from 0 to 6 is a detractor. With one promoter and one detractor, this demo board ' \
|
|
91
|
+
'totals 0 NPS.' }
|
|
82
92
|
].freeze
|
|
83
93
|
|
|
84
94
|
PROMPT_EVENTS = [
|
data/lib/testimonials/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: testimonials
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.9.
|
|
4
|
+
version: 0.9.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yaroslav Shmarov
|
|
@@ -152,7 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
152
152
|
- !ruby/object:Gem::Version
|
|
153
153
|
version: '0'
|
|
154
154
|
requirements: []
|
|
155
|
-
rubygems_version:
|
|
155
|
+
rubygems_version: 4.0.10
|
|
156
156
|
specification_version: 4
|
|
157
157
|
summary: 'Testimonials, reviews and NPS for Rails: in-app collection widget, public
|
|
158
158
|
collection page, triage dashboard, and a read API.'
|