testimonials 0.7.8 → 0.7.9
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 +15 -0
- data/README.md +22 -0
- data/app/controllers/testimonials/nps_responses_controller.rb +7 -0
- data/app/views/testimonials/nps_responses/index.html.erb +4 -4
- data/lib/generators/testimonials/install/install_generator.rb +13 -2
- data/lib/generators/testimonials/install/templates/create_testimonials_tables.rb.tt +2 -0
- data/lib/generators/testimonials/install/templates/{initializer.rb → initializer.rb.tt} +8 -0
- data/lib/generators/testimonials/nps/nps_generator.rb +37 -0
- data/lib/generators/testimonials/nps/templates/create_testimonials_nps_responses.rb.tt +20 -0
- data/lib/generators/testimonials/tenant/templates/add_tenant_to_testimonials.rb.tt +6 -2
- data/lib/testimonials/seeds.rb +2 -1
- data/lib/testimonials/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 746c0b7bc1421a8aadfbbbd7e9d41cb4aabc81ff0c6afa60669e4d9c06e963b0
|
|
4
|
+
data.tar.gz: 3914ba53cef25fcb6f541e6b4176e1d6135205cb37cdcc05b289125d456f1bbb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 55f8694212e3f1395481121efd0f67c8474e9422173ba63e9b05cf66f40320b340301a1be39537cfbeb8ce17292b289d4f73247b2a05742e52f79b1bad6d47ae
|
|
7
|
+
data.tar.gz: 1a57a1aa934adc3d3b92199d922effc5ec36d66dc9138f819b1b153f754431c5e5bd7bea4f21e65fe51bb725d732e648acf7f389f8168ac277f174e220130b19
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.7.9
|
|
4
|
+
|
|
5
|
+
- NPS is now optional at install time. `bin/rails generate testimonials:install
|
|
6
|
+
--skip-nps` leaves out the `testimonials_nps_responses` table and writes
|
|
7
|
+
`config.nps = false`, so an app that only wants testimonials carries neither
|
|
8
|
+
the table nor the NPS tab. `bin/rails generate testimonials:nps` adds the
|
|
9
|
+
table later, mirroring the `testimonials:tenant` upgrade path.
|
|
10
|
+
- The guard is `config.nps`, not table introspection — nothing checks the
|
|
11
|
+
schema at runtime and nothing touches the database at boot. Consequently
|
|
12
|
+
`/testimonials/nps_responses` now 404s when `config.nps` is false instead of
|
|
13
|
+
still serving history; flip the flag back to read old responses. The
|
|
14
|
+
dashboard nav already hid the tab, so only a typed URL reached it.
|
|
15
|
+
- `testimonials:seed_demo` skips NPS rows when the flow is off, and the
|
|
16
|
+
`testimonials:tenant` migration skips the NPS table when it isn't there.
|
|
17
|
+
|
|
3
18
|
## 0.7.8
|
|
4
19
|
|
|
5
20
|
- The NPS dashboard now says what the score means. The card carries the band
|
data/README.md
CHANGED
|
@@ -33,6 +33,15 @@ bin/rails db:migrate
|
|
|
33
33
|
The generator writes the initializer, the migration, and mounts the engine at
|
|
34
34
|
`/testimonials`. Nothing renders until the widget is opened.
|
|
35
35
|
|
|
36
|
+
Don't want NPS? Install without it — no table, no dashboard tab, no prompt:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
bin/rails generate testimonials:install --skip-nps
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Changed your mind later: `bin/rails generate testimonials:nps`, migrate, and
|
|
43
|
+
set `config.nps = true`.
|
|
44
|
+
|
|
36
45
|
Optional demo data:
|
|
37
46
|
|
|
38
47
|
```bash
|
|
@@ -242,16 +251,29 @@ throttle would allow it. Detractors (0–6) trigger `on_detractor`, which pairs
|
|
|
242
251
|
well with [ideasbugs](https://github.com/yshmarov/ideasbugs). Your score and
|
|
243
252
|
every response live at `/testimonials/nps_responses`.
|
|
244
253
|
|
|
254
|
+
| 1. One question, eleven taps | 2. The reason, optional |
|
|
255
|
+
| --- | --- |
|
|
256
|
+
|  |  |
|
|
257
|
+
| Ten seconds of work, and "Not now" is always there. | The comment is where the actionable half lives. Promoters go straight on to the testimonial form. |
|
|
258
|
+
|
|
245
259
|
The score is `% promoters − % detractors`, from −100 to +100, and the dashboard
|
|
246
260
|
reads it against the usual benchmarks so nobody has to go and google them:
|
|
247
261
|
below 0 needs work, 0–29 is good, 30–69 is great, 70 and up is world-class. A
|
|
248
262
|
scale under the number shows where you sit, and under 30 responses the card
|
|
249
263
|
says the sample is too thin to read much into.
|
|
250
264
|
|
|
265
|
+
<img src="https://raw.githubusercontent.com/yshmarov/testimonials/main/docs/screenshots/nps-dashboard.jpg" alt="The NPS dashboard: a score of 41 badged Great, a scale marking where it sits between −100 and +100, promoter/passive/detractor counts, and the collapsed panel explaining the formula and the benchmarks" width="820">
|
|
266
|
+
|
|
251
267
|
`/testimonials/nps/new` is the same question on its own page — the link for an
|
|
252
268
|
email campaign, where there is no app session to prompt inside of. A promoter
|
|
253
269
|
who scores 9–10 gets the testimonial form right there on the page.
|
|
254
270
|
|
|
271
|
+
NPS is optional. `config.nps = false` — what `--skip-nps` writes at install —
|
|
272
|
+
turns off the prompt, the public page, the `/api/stats` score and the dashboard
|
|
273
|
+
tab, and `/testimonials/nps_responses` then 404s. Turning it off on an install
|
|
274
|
+
that has the table hides existing responses along with everything else; flip it
|
|
275
|
+
back to read them.
|
|
276
|
+
|
|
255
277
|
## The public pages
|
|
256
278
|
|
|
257
279
|
Two standalone, self-styled pages for people outside the app — drop either link
|
|
@@ -8,6 +8,9 @@ module Testimonials
|
|
|
8
8
|
layout :testimonials_admin_layout
|
|
9
9
|
|
|
10
10
|
before_action :require_admin
|
|
11
|
+
# An install run with --skip-nps has no table behind these pages, and the
|
|
12
|
+
# nav already hides the tab whenever config.nps is off.
|
|
13
|
+
before_action :require_nps
|
|
11
14
|
before_action :set_response, only: :show
|
|
12
15
|
|
|
13
16
|
def index
|
|
@@ -31,6 +34,10 @@ module Testimonials
|
|
|
31
34
|
|
|
32
35
|
private
|
|
33
36
|
|
|
37
|
+
def require_nps
|
|
38
|
+
head :not_found unless Testimonials.config.nps
|
|
39
|
+
end
|
|
40
|
+
|
|
34
41
|
def set_response
|
|
35
42
|
@response = NpsResponse.for_tenant(current_tenant).find(params[:id])
|
|
36
43
|
end
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
<div class="page-head">
|
|
4
4
|
<h1><%= t('testimonials.dashboard.nps', default: 'NPS') %></h1>
|
|
5
|
-
<%# The shareable NPS page, same idea as the testimonial one.
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
<% if Testimonials.config.public_collection
|
|
5
|
+
<%# The shareable NPS page, same idea as the testimonial one. config.nps is
|
|
6
|
+
already true here — the controller 404s otherwise — so only the public
|
|
7
|
+
switch is left to check. %>
|
|
8
|
+
<% if Testimonials.config.public_collection %>
|
|
9
9
|
<a class="button share-link" href="<%= nps_collection_url %>" target="_blank" rel="noopener"
|
|
10
10
|
title="<%= nps_collection_url %>">
|
|
11
11
|
🔗 <%= t('testimonials.dashboard.nps_page', default: 'Ask for NPS scores') %>
|
|
@@ -12,8 +12,15 @@ module Testimonials
|
|
|
12
12
|
|
|
13
13
|
desc 'Installs testimonials: config initializer, migration, and engine mount.'
|
|
14
14
|
|
|
15
|
+
# NPS is the one part of the gem an app can genuinely not want. Skipping
|
|
16
|
+
# it leaves out the table and writes `config.nps = false`, so nothing
|
|
17
|
+
# ever reaches a table that isn't there — no runtime introspection, no
|
|
18
|
+
# boot-time database call. `testimonials:nps` adds it later.
|
|
19
|
+
class_option :skip_nps, type: :boolean, default: false,
|
|
20
|
+
desc: 'Leave out the NPS table and turn the NPS flow off'
|
|
21
|
+
|
|
15
22
|
def create_initializer
|
|
16
|
-
|
|
23
|
+
template 'initializer.rb.tt', 'config/initializers/testimonials.rb'
|
|
17
24
|
end
|
|
18
25
|
|
|
19
26
|
def create_migration_file
|
|
@@ -29,8 +36,12 @@ module Testimonials
|
|
|
29
36
|
say "\ntestimonials installed. Run `rails db:migrate`, then add", :green
|
|
30
37
|
say '`<%= testimonials_tag %>` before </body> in your layout.'
|
|
31
38
|
say 'Triage testimonials at /testimonials (development only until you set config.authorize_admin).'
|
|
32
|
-
|
|
39
|
+
samples = options[:skip_nps] ? 'testimonials' : 'testimonials and NPS'
|
|
40
|
+
say "Optional: run `bin/rails testimonials:seed_demo` for sample #{samples}."
|
|
33
41
|
say "Collect from outside the app via /testimonials/new.\n"
|
|
42
|
+
return unless options[:skip_nps]
|
|
43
|
+
|
|
44
|
+
say 'Installed without NPS. Add it later with `bin/rails generate testimonials:nps`.', :yellow
|
|
34
45
|
end
|
|
35
46
|
|
|
36
47
|
private
|
|
@@ -27,6 +27,7 @@ class CreateTestimonialsTables < ActiveRecord::Migration<%= migration_version %>
|
|
|
27
27
|
add_index :testimonials_testimonials, %i[tenant status]
|
|
28
28
|
add_index :testimonials_testimonials, %i[tenant status consent_given]
|
|
29
29
|
|
|
30
|
+
<% unless options[:skip_nps] -%>
|
|
30
31
|
create_table :testimonials_nps_responses do |t|
|
|
31
32
|
t.integer :score, null: false
|
|
32
33
|
t.text :comment
|
|
@@ -42,6 +43,7 @@ class CreateTestimonialsTables < ActiveRecord::Migration<%= migration_version %>
|
|
|
42
43
|
end
|
|
43
44
|
add_index :testimonials_nps_responses, %i[tenant score]
|
|
44
45
|
|
|
46
|
+
<% end -%>
|
|
45
47
|
create_table :testimonials_prompt_events do |t|
|
|
46
48
|
t.string :kind, null: false
|
|
47
49
|
t.string :action, null: false
|
|
@@ -84,7 +84,15 @@ Testimonials.configure do |config|
|
|
|
84
84
|
# config.public_api = false
|
|
85
85
|
|
|
86
86
|
# NPS surveys. Promoters (9–10) are offered the testimonial form right away.
|
|
87
|
+
<% if options[:skip_nps] -%>
|
|
88
|
+
# Installed with --skip-nps, so there is no testimonials_nps_responses table
|
|
89
|
+
# and the NPS flow, dashboard tab and public page stay off. To add it later:
|
|
90
|
+
# `bin/rails generate testimonials:nps && bin/rails db:migrate`, then flip
|
|
91
|
+
# this to true.
|
|
92
|
+
config.nps = false
|
|
93
|
+
<% else -%>
|
|
87
94
|
# config.nps = true
|
|
95
|
+
<% end -%>
|
|
88
96
|
# config.nps_reprompt_after = 90.days
|
|
89
97
|
|
|
90
98
|
# Called with each saved Testimonial or NpsResponse — notify Slack, email…
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails/generators'
|
|
4
|
+
require 'rails/generators/active_record'
|
|
5
|
+
|
|
6
|
+
module Testimonials
|
|
7
|
+
module Generators
|
|
8
|
+
# For apps that installed with --skip-nps and later want the 0–10 survey:
|
|
9
|
+
# creates the testimonials_nps_responses table. A full install already has
|
|
10
|
+
# it. Additive and safe — nothing reads the table until config.nps is true.
|
|
11
|
+
#
|
|
12
|
+
# bin/rails generate testimonials:nps && bin/rails db:migrate
|
|
13
|
+
class NpsGenerator < Rails::Generators::Base
|
|
14
|
+
include ActiveRecord::Generators::Migration
|
|
15
|
+
|
|
16
|
+
source_root File.expand_path('templates', __dir__)
|
|
17
|
+
|
|
18
|
+
desc 'Adds the NPS responses table for an install that skipped it.'
|
|
19
|
+
|
|
20
|
+
def create_migration_file
|
|
21
|
+
migration_template 'create_testimonials_nps_responses.rb.tt',
|
|
22
|
+
'db/migrate/create_testimonials_nps_responses.rb'
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def post_install
|
|
26
|
+
say "\nNPS table queued. Run `rails db:migrate`, then set", :green
|
|
27
|
+
say 'config.nps = true in config/initializers/testimonials.rb to turn the flow on.'
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def migration_version
|
|
33
|
+
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class CreateTestimonialsNpsResponses < ActiveRecord::Migration<%= migration_version %>
|
|
4
|
+
def change
|
|
5
|
+
create_table :testimonials_nps_responses do |t|
|
|
6
|
+
t.integer :score, null: false
|
|
7
|
+
t.text :comment
|
|
8
|
+
t.string :author_id
|
|
9
|
+
t.string :name
|
|
10
|
+
t.string :email
|
|
11
|
+
t.string :page_url
|
|
12
|
+
t.string :user_agent
|
|
13
|
+
t.string :locale
|
|
14
|
+
t.string :tenant # opaque per-tenant key; nil = single global collection
|
|
15
|
+
|
|
16
|
+
t.timestamps
|
|
17
|
+
end
|
|
18
|
+
add_index :testimonials_nps_responses, %i[tenant score]
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -3,13 +3,17 @@
|
|
|
3
3
|
class AddTenantToTestimonials < ActiveRecord::Migration<%= migration_version %>
|
|
4
4
|
def change
|
|
5
5
|
add_column :testimonials_testimonials, :tenant, :string
|
|
6
|
-
add_column :testimonials_nps_responses, :tenant, :string
|
|
7
6
|
add_column :testimonials_prompt_events, :tenant, :string
|
|
8
7
|
|
|
9
8
|
add_index :testimonials_testimonials, %i[tenant status]
|
|
10
9
|
add_index :testimonials_testimonials, %i[tenant status consent_given]
|
|
11
|
-
add_index :testimonials_nps_responses, %i[tenant score]
|
|
12
10
|
add_index :testimonials_prompt_events, %i[tenant author_id kind]
|
|
13
11
|
add_index :testimonials_prompt_events, %i[tenant visitor_token kind]
|
|
12
|
+
|
|
13
|
+
# An install run with --skip-nps has no NPS table to add the column to.
|
|
14
|
+
return unless table_exists?(:testimonials_nps_responses)
|
|
15
|
+
|
|
16
|
+
add_column :testimonials_nps_responses, :tenant, :string
|
|
17
|
+
add_index :testimonials_nps_responses, %i[tenant score]
|
|
14
18
|
end
|
|
15
19
|
end
|
data/lib/testimonials/seeds.rb
CHANGED
|
@@ -90,7 +90,8 @@ module Testimonials
|
|
|
90
90
|
def self.load!(tenant: nil)
|
|
91
91
|
{
|
|
92
92
|
testimonials: load_testimonials!(tenant: tenant),
|
|
93
|
-
|
|
93
|
+
# An install run with --skip-nps has no table to seed into.
|
|
94
|
+
nps_responses: (Testimonials.config.nps ? load_nps_responses!(tenant: tenant) : []),
|
|
94
95
|
prompt_events: load_prompt_events!(tenant: tenant)
|
|
95
96
|
}
|
|
96
97
|
end
|
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.7.
|
|
4
|
+
version: 0.7.9
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Yaroslav Shmarov
|
|
@@ -97,7 +97,9 @@ files:
|
|
|
97
97
|
- config/routes.rb
|
|
98
98
|
- lib/generators/testimonials/install/install_generator.rb
|
|
99
99
|
- lib/generators/testimonials/install/templates/create_testimonials_tables.rb.tt
|
|
100
|
-
- lib/generators/testimonials/install/templates/initializer.rb
|
|
100
|
+
- lib/generators/testimonials/install/templates/initializer.rb.tt
|
|
101
|
+
- lib/generators/testimonials/nps/nps_generator.rb
|
|
102
|
+
- lib/generators/testimonials/nps/templates/create_testimonials_nps_responses.rb.tt
|
|
101
103
|
- lib/generators/testimonials/tenant/templates/add_tenant_to_testimonials.rb.tt
|
|
102
104
|
- lib/generators/testimonials/tenant/tenant_generator.rb
|
|
103
105
|
- lib/tasks/testimonials_tasks.rake
|