rails_onboarding 0.6.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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +1351 -0
- data/Rakefile +6 -0
- data/app/assets/javascripts/rails_onboarding/admin/chart_controller.js +25 -0
- data/app/assets/javascripts/rails_onboarding/admin/filter_controller.js +49 -0
- data/app/assets/javascripts/rails_onboarding/admin/flash_controller.js +21 -0
- data/app/assets/javascripts/rails_onboarding/admin/flow_editor_controller.js +86 -0
- data/app/assets/javascripts/rails_onboarding/application.js +231 -0
- data/app/assets/javascripts/rails_onboarding/milestone_celebration_controller.js +177 -0
- data/app/assets/javascripts/rails_onboarding/milestone_dashboard_controller.js +132 -0
- data/app/assets/javascripts/rails_onboarding/milestone_detail_controller.js +34 -0
- data/app/assets/javascripts/rails_onboarding/navigation_controller.js +277 -0
- data/app/assets/javascripts/rails_onboarding/onboarding_controller.js +326 -0
- data/app/assets/javascripts/rails_onboarding/progress_controller.js +203 -0
- data/app/assets/javascripts/rails_onboarding/progressive_disclosure_controller.js +218 -0
- data/app/assets/javascripts/rails_onboarding/tooltip_controller.js +1237 -0
- data/app/assets/javascripts/rails_onboarding/tooltip_scheduler_controller.js +511 -0
- data/app/assets/javascripts/rails_onboarding/tour_controller.js +763 -0
- data/app/assets/stylesheets/rails_onboarding/accessibility.css +536 -0
- data/app/assets/stylesheets/rails_onboarding/admin.css +816 -0
- data/app/assets/stylesheets/rails_onboarding/application.css +1145 -0
- data/app/assets/stylesheets/rails_onboarding/flash_messages.css +237 -0
- data/app/assets/stylesheets/rails_onboarding/milestones.css +545 -0
- data/app/assets/stylesheets/rails_onboarding/mobile.css +856 -0
- data/app/assets/stylesheets/rails_onboarding/progressive_disclosure.css +299 -0
- data/app/assets/stylesheets/rails_onboarding/tooltips.css +468 -0
- data/app/assets/stylesheets/rails_onboarding/tour.css +495 -0
- data/app/assets/stylesheets/rails_onboarding/utilities.css +393 -0
- data/app/controllers/concerns/rails_onboarding/admin_authorization.rb +98 -0
- data/app/controllers/concerns/rails_onboarding/rate_limitable.rb +104 -0
- data/app/controllers/rails_onboarding/ab_tests_controller.rb +257 -0
- data/app/controllers/rails_onboarding/admin/ab_tests_controller.rb +121 -0
- data/app/controllers/rails_onboarding/admin/base_controller.rb +68 -0
- data/app/controllers/rails_onboarding/admin/dashboard_controller.rb +189 -0
- data/app/controllers/rails_onboarding/admin/flows_controller.rb +175 -0
- data/app/controllers/rails_onboarding/admin/users_controller.rb +366 -0
- data/app/controllers/rails_onboarding/application_controller.rb +9 -0
- data/app/controllers/rails_onboarding/milestones_controller.rb +126 -0
- data/app/controllers/rails_onboarding/onboarding_controller.rb +409 -0
- data/app/controllers/rails_onboarding/progressive_features_controller.rb +134 -0
- data/app/controllers/rails_onboarding/templates_controller.rb +162 -0
- data/app/controllers/rails_onboarding/test_sessions_controller.rb +16 -0
- data/app/controllers/rails_onboarding/tooltips_controller.rb +92 -0
- data/app/helpers/rails_onboarding/application_helper.rb +4 -0
- data/app/helpers/rails_onboarding/i18n_helper.rb +137 -0
- data/app/helpers/rails_onboarding/personalization_helper.rb +184 -0
- data/app/helpers/rails_onboarding/templates_helper.rb +253 -0
- data/app/jobs/rails_onboarding/application_job.rb +4 -0
- data/app/mailers/rails_onboarding/application_mailer.rb +6 -0
- data/app/mailers/rails_onboarding/onboarding_mailer.rb +72 -0
- data/app/models/concerns/rails_onboarding/ab_testable.rb +149 -0
- data/app/models/concerns/rails_onboarding/onboardable.rb +649 -0
- data/app/models/concerns/rails_onboarding/personalizable.rb +211 -0
- data/app/models/concerns/rails_onboarding/progressive_disclosure.rb +276 -0
- data/app/models/rails_onboarding/analytics.rb +255 -0
- data/app/models/rails_onboarding/analytics_event.rb +168 -0
- data/app/models/rails_onboarding/application_record.rb +5 -0
- data/app/models/rails_onboarding/flow.rb +41 -0
- data/app/services/rails_onboarding/milestone_service.rb +105 -0
- data/app/views/layouts/rails_onboarding/admin.html.erb +106 -0
- data/app/views/layouts/rails_onboarding/application.html.erb +65 -0
- data/app/views/rails_onboarding/ab_tests/index.html.erb +209 -0
- data/app/views/rails_onboarding/ab_tests/results.html.erb +253 -0
- data/app/views/rails_onboarding/admin/ab_tests/_ab_test_card.html.erb +24 -0
- data/app/views/rails_onboarding/admin/ab_tests/index.html.erb +57 -0
- data/app/views/rails_onboarding/admin/ab_tests/show.html.erb +41 -0
- data/app/views/rails_onboarding/admin/dashboard/index.html.erb +224 -0
- data/app/views/rails_onboarding/admin/flows/_form.html.erb +147 -0
- data/app/views/rails_onboarding/admin/flows/edit.html.erb +7 -0
- data/app/views/rails_onboarding/admin/flows/index.html.erb +125 -0
- data/app/views/rails_onboarding/admin/flows/new.html.erb +7 -0
- data/app/views/rails_onboarding/admin/flows/preview.html.erb +40 -0
- data/app/views/rails_onboarding/admin/flows/show.html.erb +114 -0
- data/app/views/rails_onboarding/admin/users/index.html.erb +180 -0
- data/app/views/rails_onboarding/admin/users/show.html.erb +187 -0
- data/app/views/rails_onboarding/milestones/index.html.erb +64 -0
- data/app/views/rails_onboarding/milestones/show.html.erb +57 -0
- data/app/views/rails_onboarding/onboarding/_custom_footer.html.erb +2 -0
- data/app/views/rails_onboarding/onboarding/_progress_indicator.html.erb +56 -0
- data/app/views/rails_onboarding/onboarding/_step_navigation.html.erb +44 -0
- data/app/views/rails_onboarding/onboarding/step.html.erb +38 -0
- data/app/views/rails_onboarding/onboarding/welcome.html.erb +37 -0
- data/app/views/rails_onboarding/onboarding_mailer/completion_email.html.erb +109 -0
- data/app/views/rails_onboarding/onboarding_mailer/completion_email.text.erb +29 -0
- data/app/views/rails_onboarding/onboarding_mailer/reminder_email.html.erb +99 -0
- data/app/views/rails_onboarding/onboarding_mailer/reminder_email.text.erb +20 -0
- data/app/views/rails_onboarding/onboarding_mailer/step_completed_email.html.erb +105 -0
- data/app/views/rails_onboarding/onboarding_mailer/step_completed_email.text.erb +19 -0
- data/app/views/rails_onboarding/onboarding_mailer/welcome_email.html.erb +74 -0
- data/app/views/rails_onboarding/onboarding_mailer/welcome_email.text.erb +17 -0
- data/app/views/rails_onboarding/shared/_flash.html.erb +25 -0
- data/app/views/rails_onboarding/shared/_milestone_badge.html.erb +22 -0
- data/app/views/rails_onboarding/shared/_milestone_celebration.html.erb +44 -0
- data/app/views/rails_onboarding/shared/_onboarding_banner.html.erb +48 -0
- data/app/views/rails_onboarding/templates/index.html.erb +255 -0
- data/config/importmap.rb +33 -0
- data/config/locales/en.yml +62 -0
- data/config/locales/es.yml +62 -0
- data/config/locales/fr.yml +62 -0
- data/config/routes.rb +79 -0
- data/lib/generators/rails_onboarding/install_generator.rb +124 -0
- data/lib/generators/rails_onboarding/templates/README +120 -0
- data/lib/generators/rails_onboarding/templates/add_analytics_to_rails_onboarding.rb +33 -0
- data/lib/generators/rails_onboarding/templates/add_milestone_tracking_to_users.rb +38 -0
- data/lib/generators/rails_onboarding/templates/add_onboarding_indexes.rb +93 -0
- data/lib/generators/rails_onboarding/templates/add_onboarding_to_users.rb +51 -0
- data/lib/generators/rails_onboarding/templates/add_robustness_fields_to_users.rb.tt +20 -0
- data/lib/generators/rails_onboarding/templates/create_rails_onboarding_flows.rb +18 -0
- data/lib/generators/rails_onboarding/templates/onboarding.css +18 -0
- data/lib/generators/rails_onboarding/templates/rails_onboarding.rb +75 -0
- data/lib/generators/rails_onboarding/update_generator.rb +73 -0
- data/lib/rails_onboarding/api_mode.rb +367 -0
- data/lib/rails_onboarding/backfill.rb +130 -0
- data/lib/rails_onboarding/background_jobs.rb +412 -0
- data/lib/rails_onboarding/caching.rb +180 -0
- data/lib/rails_onboarding/cdn_support.rb +202 -0
- data/lib/rails_onboarding/configuration/ab_testing.rb +24 -0
- data/lib/rails_onboarding/configuration/analytics.rb +29 -0
- data/lib/rails_onboarding/configuration/integrations.rb +31 -0
- data/lib/rails_onboarding/configuration/milestones.rb +92 -0
- data/lib/rails_onboarding/configuration/personalization.rb +25 -0
- data/lib/rails_onboarding/configuration/progressive_disclosure.rb +41 -0
- data/lib/rails_onboarding/configuration/rate_limiting.rb +18 -0
- data/lib/rails_onboarding/configuration/steps.rb +121 -0
- data/lib/rails_onboarding/configuration/templates.rb +85 -0
- data/lib/rails_onboarding/configuration/tooltips.rb +32 -0
- data/lib/rails_onboarding/configuration.rb +133 -0
- data/lib/rails_onboarding/configuration_errors.rb +19 -0
- data/lib/rails_onboarding/configuration_validator.rb +477 -0
- data/lib/rails_onboarding/controller_helpers.rb +153 -0
- data/lib/rails_onboarding/current.rb +13 -0
- data/lib/rails_onboarding/deprecation.rb +64 -0
- data/lib/rails_onboarding/devise_integration.rb +122 -0
- data/lib/rails_onboarding/engine.rb +245 -0
- data/lib/rails_onboarding/error_recovery.rb +173 -0
- data/lib/rails_onboarding/lazy_loading.rb +155 -0
- data/lib/rails_onboarding/multi_tenant.rb +306 -0
- data/lib/rails_onboarding/requirements_validator.rb +315 -0
- data/lib/rails_onboarding/responsive_helper.rb +218 -0
- data/lib/rails_onboarding/session_manager.rb +187 -0
- data/lib/rails_onboarding/skip_logic.rb +159 -0
- data/lib/rails_onboarding/turbo_compatibility.rb +229 -0
- data/lib/rails_onboarding/version.rb +3 -0
- data/lib/rails_onboarding.rb +44 -0
- data/lib/tasks/rails_onboarding_analytics.rake +136 -0
- data/lib/tasks/rails_onboarding_tasks.rake +162 -0
- metadata +303 -0
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
<div class="templates-index">
|
|
2
|
+
<div class="header">
|
|
3
|
+
<h1>Onboarding Templates</h1>
|
|
4
|
+
<p class="subtitle">Choose a pre-built onboarding flow to get started quickly</p>
|
|
5
|
+
</div>
|
|
6
|
+
|
|
7
|
+
<div class="templates-grid">
|
|
8
|
+
<% @templates.each do |template_key, template| %>
|
|
9
|
+
<div class="template-card" data-template-key="<%= template_key %>">
|
|
10
|
+
<div class="template-header">
|
|
11
|
+
<h2><%= template[:name] %></h2>
|
|
12
|
+
<span class="template-steps-count"><%= template[:steps]&.size || 0 %> steps</span>
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<div class="template-description">
|
|
16
|
+
<p><%= template[:description] || "A #{template_key.to_s.titleize} onboarding flow" %></p>
|
|
17
|
+
</div>
|
|
18
|
+
|
|
19
|
+
<div class="template-steps-preview">
|
|
20
|
+
<h3>Steps included:</h3>
|
|
21
|
+
<ul>
|
|
22
|
+
<% (template[:steps] || []).each do |step| %>
|
|
23
|
+
<li>
|
|
24
|
+
<span class="step-icon"><%= step[:icon] %></span>
|
|
25
|
+
<span class="step-title"><%= step[:title] %></span>
|
|
26
|
+
<% if step[:skippable] %>
|
|
27
|
+
<span class="step-badge optional">Optional</span>
|
|
28
|
+
<% else %>
|
|
29
|
+
<span class="step-badge required">Required</span>
|
|
30
|
+
<% end %>
|
|
31
|
+
</li>
|
|
32
|
+
<% end %>
|
|
33
|
+
</ul>
|
|
34
|
+
</div>
|
|
35
|
+
|
|
36
|
+
<div class="template-actions">
|
|
37
|
+
<%= link_to 'Preview', template_path(template_key), class: 'btn btn-secondary' %>
|
|
38
|
+
<%= button_to 'Use This Template', apply_template_path(template_key), method: :post, class: 'btn btn-primary' %>
|
|
39
|
+
</div>
|
|
40
|
+
</div>
|
|
41
|
+
<% end %>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
44
|
+
<div class="custom-template-section">
|
|
45
|
+
<h2>Create Custom Template</h2>
|
|
46
|
+
<p>Already have an onboarding flow configured? Save it as a custom template for future use.</p>
|
|
47
|
+
<%= button_to 'Save Current Flow as Template', '#', class: 'btn btn-outline', onclick: 'return false;' %>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<style>
|
|
52
|
+
.templates-index {
|
|
53
|
+
max-width: 1400px;
|
|
54
|
+
margin: 0 auto;
|
|
55
|
+
padding: 2rem;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.header {
|
|
59
|
+
margin-bottom: 3rem;
|
|
60
|
+
text-align: center;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.header h1 {
|
|
64
|
+
font-size: 2.5rem;
|
|
65
|
+
font-weight: bold;
|
|
66
|
+
margin-bottom: 0.5rem;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.subtitle {
|
|
70
|
+
color: #666;
|
|
71
|
+
font-size: 1.125rem;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.templates-grid {
|
|
75
|
+
display: grid;
|
|
76
|
+
grid-template-columns: repeat(auto-fill, minmax(400px, 1fr));
|
|
77
|
+
gap: 2rem;
|
|
78
|
+
margin-bottom: 3rem;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.template-card {
|
|
82
|
+
background: white;
|
|
83
|
+
border: 2px solid #e0e0e0;
|
|
84
|
+
border-radius: 12px;
|
|
85
|
+
padding: 2rem;
|
|
86
|
+
transition: all 0.3s;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.template-card:hover {
|
|
90
|
+
border-color: #007bff;
|
|
91
|
+
box-shadow: 0 4px 12px rgba(0, 123, 255, 0.1);
|
|
92
|
+
transform: translateY(-2px);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.template-header {
|
|
96
|
+
display: flex;
|
|
97
|
+
justify-content: space-between;
|
|
98
|
+
align-items: center;
|
|
99
|
+
margin-bottom: 1rem;
|
|
100
|
+
padding-bottom: 1rem;
|
|
101
|
+
border-bottom: 2px solid #f0f0f0;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.template-header h2 {
|
|
105
|
+
font-size: 1.5rem;
|
|
106
|
+
font-weight: 600;
|
|
107
|
+
margin: 0;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.template-steps-count {
|
|
111
|
+
background: #e9ecef;
|
|
112
|
+
padding: 0.25rem 0.75rem;
|
|
113
|
+
border-radius: 12px;
|
|
114
|
+
font-size: 0.875rem;
|
|
115
|
+
font-weight: 500;
|
|
116
|
+
color: #495057;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
.template-description {
|
|
120
|
+
margin-bottom: 1.5rem;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.template-description p {
|
|
124
|
+
color: #666;
|
|
125
|
+
line-height: 1.6;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.template-steps-preview h3 {
|
|
129
|
+
font-size: 1rem;
|
|
130
|
+
font-weight: 600;
|
|
131
|
+
margin-bottom: 0.75rem;
|
|
132
|
+
color: #333;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.template-steps-preview ul {
|
|
136
|
+
list-style: none;
|
|
137
|
+
padding: 0;
|
|
138
|
+
margin: 0 0 1.5rem 0;
|
|
139
|
+
max-height: 300px;
|
|
140
|
+
overflow-y: auto;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.template-steps-preview li {
|
|
144
|
+
display: flex;
|
|
145
|
+
align-items: center;
|
|
146
|
+
gap: 0.5rem;
|
|
147
|
+
padding: 0.75rem;
|
|
148
|
+
background: #f8f9fa;
|
|
149
|
+
border-radius: 6px;
|
|
150
|
+
margin-bottom: 0.5rem;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
.step-icon {
|
|
154
|
+
font-size: 1.25rem;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.step-title {
|
|
158
|
+
flex: 1;
|
|
159
|
+
font-weight: 500;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.step-badge {
|
|
163
|
+
padding: 0.125rem 0.5rem;
|
|
164
|
+
border-radius: 8px;
|
|
165
|
+
font-size: 0.75rem;
|
|
166
|
+
font-weight: 600;
|
|
167
|
+
text-transform: uppercase;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.step-badge.required {
|
|
171
|
+
background: #ffeaa7;
|
|
172
|
+
color: #856404;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.step-badge.optional {
|
|
176
|
+
background: #d1ecf1;
|
|
177
|
+
color: #0c5460;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.template-actions {
|
|
181
|
+
display: flex;
|
|
182
|
+
gap: 0.75rem;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.btn {
|
|
186
|
+
flex: 1;
|
|
187
|
+
padding: 0.75rem 1.5rem;
|
|
188
|
+
border-radius: 6px;
|
|
189
|
+
text-decoration: none;
|
|
190
|
+
text-align: center;
|
|
191
|
+
border: none;
|
|
192
|
+
cursor: pointer;
|
|
193
|
+
font-size: 0.875rem;
|
|
194
|
+
font-weight: 600;
|
|
195
|
+
transition: all 0.2s;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
.btn-primary {
|
|
199
|
+
background: #007bff;
|
|
200
|
+
color: white;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.btn-primary:hover {
|
|
204
|
+
background: #0056b3;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.btn-secondary {
|
|
208
|
+
background: #6c757d;
|
|
209
|
+
color: white;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.btn-secondary:hover {
|
|
213
|
+
background: #545b62;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.btn-outline {
|
|
217
|
+
background: transparent;
|
|
218
|
+
color: #007bff;
|
|
219
|
+
border: 2px solid #007bff;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.btn-outline:hover {
|
|
223
|
+
background: #007bff;
|
|
224
|
+
color: white;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.custom-template-section {
|
|
228
|
+
background: #f8f9fa;
|
|
229
|
+
border-radius: 12px;
|
|
230
|
+
padding: 2rem;
|
|
231
|
+
text-align: center;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.custom-template-section h2 {
|
|
235
|
+
font-size: 1.5rem;
|
|
236
|
+
font-weight: 600;
|
|
237
|
+
margin-bottom: 0.5rem;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.custom-template-section p {
|
|
241
|
+
color: #666;
|
|
242
|
+
margin-bottom: 1.5rem;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/* Mobile responsiveness */
|
|
246
|
+
@media (max-width: 768px) {
|
|
247
|
+
.templates-grid {
|
|
248
|
+
grid-template-columns: 1fr;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
.template-actions {
|
|
252
|
+
flex-direction: column;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
</style>
|
data/config/importmap.rb
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Pin Rails Onboarding JavaScript modules for Importmap
|
|
2
|
+
# These pins allow the engine's JavaScript to be loaded via importmap in the host application
|
|
3
|
+
|
|
4
|
+
# Main application bundle
|
|
5
|
+
pin "rails_onboarding/application", to: "rails_onboarding/application.js"
|
|
6
|
+
|
|
7
|
+
# Core onboarding controllers
|
|
8
|
+
pin "rails_onboarding/onboarding_controller", to: "rails_onboarding/onboarding_controller.js"
|
|
9
|
+
pin "rails_onboarding/progress_controller", to: "rails_onboarding/progress_controller.js"
|
|
10
|
+
pin "rails_onboarding/navigation_controller", to: "rails_onboarding/navigation_controller.js"
|
|
11
|
+
|
|
12
|
+
# Tooltip system controllers
|
|
13
|
+
pin "rails_onboarding/tooltip_controller", to: "rails_onboarding/tooltip_controller.js"
|
|
14
|
+
pin "rails_onboarding/tooltip_scheduler_controller", to: "rails_onboarding/tooltip_scheduler_controller.js"
|
|
15
|
+
|
|
16
|
+
# Tour and progressive disclosure
|
|
17
|
+
pin "rails_onboarding/tour_controller", to: "rails_onboarding/tour_controller.js"
|
|
18
|
+
pin "rails_onboarding/progressive_disclosure_controller", to: "rails_onboarding/progressive_disclosure_controller.js"
|
|
19
|
+
|
|
20
|
+
# Milestone system controllers
|
|
21
|
+
pin "rails_onboarding/milestone_celebration_controller", to: "rails_onboarding/milestone_celebration_controller.js"
|
|
22
|
+
pin "rails_onboarding/milestone_dashboard_controller", to: "rails_onboarding/milestone_dashboard_controller.js"
|
|
23
|
+
pin "rails_onboarding/milestone_detail_controller", to: "rails_onboarding/milestone_detail_controller.js"
|
|
24
|
+
|
|
25
|
+
# Admin controllers
|
|
26
|
+
pin "rails_onboarding/admin/chart_controller", to: "rails_onboarding/admin/chart_controller.js"
|
|
27
|
+
pin "rails_onboarding/admin/filter_controller", to: "rails_onboarding/admin/filter_controller.js"
|
|
28
|
+
pin "rails_onboarding/admin/flash_controller", to: "rails_onboarding/admin/flash_controller.js"
|
|
29
|
+
pin "rails_onboarding/admin/flow_editor_controller", to: "rails_onboarding/admin/flow_editor_controller.js"
|
|
30
|
+
|
|
31
|
+
# External dependencies (if using Stimulus from importmap)
|
|
32
|
+
# Uncomment if your host app doesn't already pin these
|
|
33
|
+
# pin "@hotwired/stimulus", to: "https://ga.jspm.io/npm:@hotwired/stimulus@3.2.2/dist/stimulus.js"
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
en:
|
|
2
|
+
rails_onboarding:
|
|
3
|
+
# Navigation
|
|
4
|
+
navigation:
|
|
5
|
+
next: "Next"
|
|
6
|
+
back: "Back"
|
|
7
|
+
skip: "Skip"
|
|
8
|
+
skip_all: "Skip All"
|
|
9
|
+
finish: "Finish"
|
|
10
|
+
restart: "Restart"
|
|
11
|
+
|
|
12
|
+
# Actions
|
|
13
|
+
actions:
|
|
14
|
+
complete: "Complete"
|
|
15
|
+
continue: "Continue"
|
|
16
|
+
get_started: "Get Started"
|
|
17
|
+
|
|
18
|
+
# Messages
|
|
19
|
+
messages:
|
|
20
|
+
welcome: "Welcome!"
|
|
21
|
+
completed: "Congratulations! You've completed the onboarding."
|
|
22
|
+
skipped: "You can explore features at your own pace."
|
|
23
|
+
restarted: "Onboarding has been restarted."
|
|
24
|
+
cannot_go_back: "Cannot go back from the first step."
|
|
25
|
+
cannot_skip: "This step cannot be skipped."
|
|
26
|
+
error: "An error occurred. Please try again."
|
|
27
|
+
validation_error: "Unable to save changes: %{errors}"
|
|
28
|
+
|
|
29
|
+
# Progress
|
|
30
|
+
progress:
|
|
31
|
+
step_of: "Step %{current} of %{total}"
|
|
32
|
+
percent_complete: "%{percent}% complete"
|
|
33
|
+
|
|
34
|
+
# Tooltips
|
|
35
|
+
tooltips:
|
|
36
|
+
dismiss: "Got it"
|
|
37
|
+
next_tip: "Next tip"
|
|
38
|
+
close: "Close"
|
|
39
|
+
|
|
40
|
+
# Milestones
|
|
41
|
+
milestones:
|
|
42
|
+
achievement_unlocked: "Achievement Unlocked!"
|
|
43
|
+
points_earned: "%{points} points earned"
|
|
44
|
+
view_all: "View all achievements"
|
|
45
|
+
|
|
46
|
+
# Errors
|
|
47
|
+
errors:
|
|
48
|
+
failed_to_save: "Failed to save your progress"
|
|
49
|
+
step_not_found: "Step not found"
|
|
50
|
+
invalid_action: "Invalid action"
|
|
51
|
+
session_expired: "Your session has expired. Please refresh the page."
|
|
52
|
+
network_error: "Network error. Please check your connection."
|
|
53
|
+
|
|
54
|
+
# Common
|
|
55
|
+
common:
|
|
56
|
+
loading: "Loading..."
|
|
57
|
+
saving: "Saving..."
|
|
58
|
+
please_wait: "Please wait..."
|
|
59
|
+
cancel: "Cancel"
|
|
60
|
+
confirm: "Confirm"
|
|
61
|
+
yes: "Yes"
|
|
62
|
+
no: "No"
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
es:
|
|
2
|
+
rails_onboarding:
|
|
3
|
+
# Navigation
|
|
4
|
+
navigation:
|
|
5
|
+
next: "Siguiente"
|
|
6
|
+
back: "Atrás"
|
|
7
|
+
skip: "Omitir"
|
|
8
|
+
skip_all: "Omitir Todo"
|
|
9
|
+
finish: "Finalizar"
|
|
10
|
+
restart: "Reiniciar"
|
|
11
|
+
|
|
12
|
+
# Actions
|
|
13
|
+
actions:
|
|
14
|
+
complete: "Completar"
|
|
15
|
+
continue: "Continuar"
|
|
16
|
+
get_started: "Comenzar"
|
|
17
|
+
|
|
18
|
+
# Messages
|
|
19
|
+
messages:
|
|
20
|
+
welcome: "¡Bienvenido!"
|
|
21
|
+
completed: "¡Felicitaciones! Has completado la integración."
|
|
22
|
+
skipped: "Puedes explorar las funciones a tu propio ritmo."
|
|
23
|
+
restarted: "La integración ha sido reiniciada."
|
|
24
|
+
cannot_go_back: "No se puede retroceder desde el primer paso."
|
|
25
|
+
cannot_skip: "Este paso no se puede omitir."
|
|
26
|
+
error: "Ocurrió un error. Por favor, inténtalo de nuevo."
|
|
27
|
+
validation_error: "No se pudieron guardar los cambios: %{errors}"
|
|
28
|
+
|
|
29
|
+
# Progress
|
|
30
|
+
progress:
|
|
31
|
+
step_of: "Paso %{current} de %{total}"
|
|
32
|
+
percent_complete: "%{percent}% completado"
|
|
33
|
+
|
|
34
|
+
# Tooltips
|
|
35
|
+
tooltips:
|
|
36
|
+
dismiss: "Entendido"
|
|
37
|
+
next_tip: "Siguiente consejo"
|
|
38
|
+
close: "Cerrar"
|
|
39
|
+
|
|
40
|
+
# Milestones
|
|
41
|
+
milestones:
|
|
42
|
+
achievement_unlocked: "¡Logro Desbloqueado!"
|
|
43
|
+
points_earned: "%{points} puntos ganados"
|
|
44
|
+
view_all: "Ver todos los logros"
|
|
45
|
+
|
|
46
|
+
# Errors
|
|
47
|
+
errors:
|
|
48
|
+
failed_to_save: "No se pudo guardar tu progreso"
|
|
49
|
+
step_not_found: "Paso no encontrado"
|
|
50
|
+
invalid_action: "Acción inválida"
|
|
51
|
+
session_expired: "Tu sesión ha expirado. Por favor, actualiza la página."
|
|
52
|
+
network_error: "Error de red. Por favor, verifica tu conexión."
|
|
53
|
+
|
|
54
|
+
# Common
|
|
55
|
+
common:
|
|
56
|
+
loading: "Cargando..."
|
|
57
|
+
saving: "Guardando..."
|
|
58
|
+
please_wait: "Por favor, espera..."
|
|
59
|
+
cancel: "Cancelar"
|
|
60
|
+
confirm: "Confirmar"
|
|
61
|
+
yes: "Sí"
|
|
62
|
+
no: "No"
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
fr:
|
|
2
|
+
rails_onboarding:
|
|
3
|
+
# Navigation
|
|
4
|
+
navigation:
|
|
5
|
+
next: "Suivant"
|
|
6
|
+
back: "Retour"
|
|
7
|
+
skip: "Passer"
|
|
8
|
+
skip_all: "Tout Passer"
|
|
9
|
+
finish: "Terminer"
|
|
10
|
+
restart: "Recommencer"
|
|
11
|
+
|
|
12
|
+
# Actions
|
|
13
|
+
actions:
|
|
14
|
+
complete: "Compléter"
|
|
15
|
+
continue: "Continuer"
|
|
16
|
+
get_started: "Commencer"
|
|
17
|
+
|
|
18
|
+
# Messages
|
|
19
|
+
messages:
|
|
20
|
+
welcome: "Bienvenue!"
|
|
21
|
+
completed: "Félicitations! Vous avez terminé l'intégration."
|
|
22
|
+
skipped: "Vous pouvez explorer les fonctionnalités à votre rythme."
|
|
23
|
+
restarted: "L'intégration a été redémarrée."
|
|
24
|
+
cannot_go_back: "Impossible de revenir en arrière depuis la première étape."
|
|
25
|
+
cannot_skip: "Cette étape ne peut pas être ignorée."
|
|
26
|
+
error: "Une erreur s'est produite. Veuillez réessayer."
|
|
27
|
+
validation_error: "Impossible d'enregistrer les modifications: %{errors}"
|
|
28
|
+
|
|
29
|
+
# Progress
|
|
30
|
+
progress:
|
|
31
|
+
step_of: "Étape %{current} sur %{total}"
|
|
32
|
+
percent_complete: "%{percent}% terminé"
|
|
33
|
+
|
|
34
|
+
# Tooltips
|
|
35
|
+
tooltips:
|
|
36
|
+
dismiss: "Compris"
|
|
37
|
+
next_tip: "Conseil suivant"
|
|
38
|
+
close: "Fermer"
|
|
39
|
+
|
|
40
|
+
# Milestones
|
|
41
|
+
milestones:
|
|
42
|
+
achievement_unlocked: "Succès Débloqué!"
|
|
43
|
+
points_earned: "%{points} points gagnés"
|
|
44
|
+
view_all: "Voir tous les succès"
|
|
45
|
+
|
|
46
|
+
# Errors
|
|
47
|
+
errors:
|
|
48
|
+
failed_to_save: "Échec de l'enregistrement de votre progression"
|
|
49
|
+
step_not_found: "Étape non trouvée"
|
|
50
|
+
invalid_action: "Action invalide"
|
|
51
|
+
session_expired: "Votre session a expiré. Veuillez actualiser la page."
|
|
52
|
+
network_error: "Erreur réseau. Veuillez vérifier votre connexion."
|
|
53
|
+
|
|
54
|
+
# Common
|
|
55
|
+
common:
|
|
56
|
+
loading: "Chargement..."
|
|
57
|
+
saving: "Enregistrement..."
|
|
58
|
+
please_wait: "Veuillez patienter..."
|
|
59
|
+
cancel: "Annuler"
|
|
60
|
+
confirm: "Confirmer"
|
|
61
|
+
yes: "Oui"
|
|
62
|
+
no: "Non"
|
data/config/routes.rb
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
RailsOnboarding::Engine.routes.draw do
|
|
2
|
+
# Test-only route for setting session in integration tests (no URL helpers needed)
|
|
3
|
+
post "test_session", to: "test_sessions#create", as: nil if Rails.env.test?
|
|
4
|
+
|
|
5
|
+
# Regular web routes. path: "" anchors the onboarding flow at the engine's
|
|
6
|
+
# mount point, so the host app's mount path alone controls the URL -
|
|
7
|
+
# `mount ... => "/onboarding"` yields /onboarding, not /onboarding/onboarding.
|
|
8
|
+
resource :onboarding, only: [ :show ], controller: "onboarding", path: "" do
|
|
9
|
+
post :next
|
|
10
|
+
post :complete
|
|
11
|
+
post :skip
|
|
12
|
+
post :back
|
|
13
|
+
post :restart
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# Tooltip routes
|
|
17
|
+
post "tooltips/dismiss", to: "tooltips#dismiss", as: :dismiss_tooltip
|
|
18
|
+
post "tooltips/show", to: "tooltips#show", as: :show_tooltip
|
|
19
|
+
post "tooltips/reset", to: "tooltips#reset", as: :reset_tooltips
|
|
20
|
+
get "tooltips/status", to: "tooltips#status", as: :tooltip_status
|
|
21
|
+
|
|
22
|
+
resources :tooltips, only: [] do
|
|
23
|
+
member do
|
|
24
|
+
post :mark_shown
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
resources :milestones, only: [ :index, :show ] do
|
|
29
|
+
collection do
|
|
30
|
+
get :recent
|
|
31
|
+
post :achieve
|
|
32
|
+
get :progress
|
|
33
|
+
post :trigger
|
|
34
|
+
get :available
|
|
35
|
+
end
|
|
36
|
+
member do
|
|
37
|
+
get :check
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Admin interface
|
|
42
|
+
namespace :admin do
|
|
43
|
+
# Dashboard
|
|
44
|
+
get "/", to: "dashboard#index", as: :dashboard
|
|
45
|
+
|
|
46
|
+
# User management
|
|
47
|
+
resources :users, only: [ :index, :show ] do
|
|
48
|
+
member do
|
|
49
|
+
post :reset_onboarding
|
|
50
|
+
post :complete_onboarding
|
|
51
|
+
post :restart_onboarding
|
|
52
|
+
end
|
|
53
|
+
collection do
|
|
54
|
+
post :bulk_action
|
|
55
|
+
get :export
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Flow editor
|
|
60
|
+
resources :flows do
|
|
61
|
+
member do
|
|
62
|
+
post :duplicate
|
|
63
|
+
post :activate
|
|
64
|
+
get :preview
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# A/B test management - tests are defined in the host app's initializer
|
|
69
|
+
# (RailsOnboarding.configuration.ab_tests), so only viewing and toggling
|
|
70
|
+
# them on/off is supported here, not creating or deleting them.
|
|
71
|
+
resources :ab_tests, only: [ :index, :show ] do
|
|
72
|
+
member do
|
|
73
|
+
post :start
|
|
74
|
+
post :stop
|
|
75
|
+
get :export
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
require "rails/generators/base"
|
|
2
|
+
require "rails/generators/migration"
|
|
3
|
+
|
|
4
|
+
module RailsOnboarding
|
|
5
|
+
module Generators
|
|
6
|
+
class InstallGenerator < Rails::Generators::Base
|
|
7
|
+
include Rails::Generators::Migration
|
|
8
|
+
|
|
9
|
+
source_root File.expand_path("templates", __dir__)
|
|
10
|
+
|
|
11
|
+
def self.next_migration_number(path)
|
|
12
|
+
@prev_migration_nr = if @prev_migration_nr
|
|
13
|
+
@prev_migration_nr + 1
|
|
14
|
+
else
|
|
15
|
+
Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
|
|
16
|
+
end
|
|
17
|
+
@prev_migration_nr.to_s
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def validate_environment
|
|
21
|
+
# Validate that we're in a Rails app
|
|
22
|
+
unless defined?(Rails)
|
|
23
|
+
raise "This generator must be run within a Rails application"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Validate template paths exist
|
|
27
|
+
validate_template_paths!
|
|
28
|
+
|
|
29
|
+
# Validate User model exists
|
|
30
|
+
validate_user_model!
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def copy_migration
|
|
34
|
+
migration_template "add_onboarding_to_users.rb",
|
|
35
|
+
"db/migrate/add_onboarding_to_users.rb"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def copy_analytics_migration
|
|
39
|
+
migration_template "add_analytics_to_rails_onboarding.rb",
|
|
40
|
+
"db/migrate/add_analytics_to_rails_onboarding.rb"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def copy_flows_migration
|
|
44
|
+
migration_template "create_rails_onboarding_flows.rb",
|
|
45
|
+
"db/migrate/create_rails_onboarding_flows.rb"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def copy_milestone_tracking_migration
|
|
49
|
+
migration_template "add_milestone_tracking_to_users.rb",
|
|
50
|
+
"db/migrate/add_milestone_tracking_to_users.rb"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def copy_onboarding_indexes_migration
|
|
54
|
+
migration_template "add_onboarding_indexes.rb",
|
|
55
|
+
"db/migrate/add_onboarding_indexes.rb"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def copy_robustness_fields_migration
|
|
59
|
+
migration_template "add_robustness_fields_to_users.rb.tt",
|
|
60
|
+
"db/migrate/add_robustness_fields_to_users.rb"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def copy_initializer
|
|
64
|
+
template "rails_onboarding.rb", "config/initializers/rails_onboarding.rb"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def add_route
|
|
68
|
+
route 'mount RailsOnboarding::Engine => "/onboarding"'
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def copy_stylesheets
|
|
72
|
+
copy_file "onboarding.css",
|
|
73
|
+
"app/assets/stylesheets/rails_onboarding_custom.css"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def display_readme
|
|
77
|
+
readme "README" if behavior == :invoke
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
private
|
|
81
|
+
|
|
82
|
+
def validate_template_paths!
|
|
83
|
+
required_templates = [
|
|
84
|
+
"add_onboarding_to_users.rb",
|
|
85
|
+
"add_analytics_to_rails_onboarding.rb",
|
|
86
|
+
"create_rails_onboarding_flows.rb",
|
|
87
|
+
"add_milestone_tracking_to_users.rb",
|
|
88
|
+
"add_onboarding_indexes.rb",
|
|
89
|
+
"add_robustness_fields_to_users.rb.tt",
|
|
90
|
+
"rails_onboarding.rb",
|
|
91
|
+
"onboarding.css",
|
|
92
|
+
"README"
|
|
93
|
+
]
|
|
94
|
+
|
|
95
|
+
missing_templates = required_templates.reject do |template|
|
|
96
|
+
File.exist?(File.join(self.class.source_root, template))
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
if missing_templates.any?
|
|
100
|
+
raise "Missing required template files: #{missing_templates.join(', ')}"
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def validate_user_model!
|
|
105
|
+
# Use destination_root in test environment, Rails.root otherwise
|
|
106
|
+
root_path = respond_to?(:destination_root) ? destination_root : Rails.root
|
|
107
|
+
user_model_path = File.join(root_path, "app/models/user.rb")
|
|
108
|
+
|
|
109
|
+
unless File.exist?(user_model_path)
|
|
110
|
+
say_status :error, "User model not found at app/models/user.rb", :red
|
|
111
|
+
say ""
|
|
112
|
+
say "RailsOnboarding requires a User model to exist.", :yellow
|
|
113
|
+
say "Please create a User model before running this generator:", :yellow
|
|
114
|
+
say ""
|
|
115
|
+
say " rails generate model User email:string", :green
|
|
116
|
+
say ""
|
|
117
|
+
raise "User model does not exist. Please create it first."
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
say_status :check, "User model found", :green
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|