abraham 2.2.0 → 2.3.0.beta

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d6094c0e5929d5da7e61f12bd1e60a11e450a05e2c3b99afc349b0b7d847edca
4
- data.tar.gz: 2b6df2f7d73f7b0c312b13ca3bc5adf16452437f1fd97faea90468093193f5fa
3
+ metadata.gz: 5872e5ab9e3d24a4133de7b4127934eba2b36688eac51eb4f29bfdd9c7a0f1ff
4
+ data.tar.gz: ead10365b2cdf82e9f9e49f7ee55d9525731093b0b1b6faafe720b789766c977
5
5
  SHA512:
6
- metadata.gz: 978175580bd5132ea570ea0c14421f6ac0def8ca523ce5dfea730c3934c49180c6f9909fd35f161190afddf02aade22c9d447cb74546c419d8cd143e77129d3e
7
- data.tar.gz: 9c46128409adfc46ed76abe7f07601d4e5035c63641c13e50b747e51a2e532910326ed77f63f7b2406feb4f5930feb8dbdbe10e5b660f858409f1ce7cf8f186c
6
+ metadata.gz: 810d59a5b7d8f35d787d65fec4e42c46cb27edc7228272aa337adb31ddf9a4f35167610046f99861af51ccd0a65dea2bd77d32ac41f8fd07ed5f349516faa8b4
7
+ data.tar.gz: bfe6c59e405805b0e98938480037fc5a2c40ef4ae965558060ac4767cbc522890b131f634a190847b92d759b9facd7ba472d4f67b8a0b32eb183f660164f7487
data/README.md CHANGED
@@ -6,12 +6,13 @@ _Guide your users in the one true path._
6
6
 
7
7
  ![Watercolor Sheep](https://upload.wikimedia.org/wikipedia/commons/e/e4/Watercolor_Sheep_Drawing.jpg)
8
8
 
9
- Abraham injects dynamically-generated [Shepherd](https://shepherdjs.dev/) JavaScript code into your Rails application whenever a user should see a guided tour. Skip a tour, and we'll try again next time; complete a tour, and it won't show up again.
9
+ Abraham makes it easy to show guided tours to users of your Rails application. When Abraham shows a tour, it keeps track of whether the user has completed it (so it doesn't get shown again) or dismissed it for later (so it reappears in a future user session).
10
10
 
11
11
  * Define tour content with simple YAML files, in any/many languages.
12
12
  * Organize tours by controller and action.
13
- * Plays nicely with Turbolinks.
14
- * Ships with two basic CSS themes (default & dark) -- or write your own
13
+ * Trigger tours automatically on page load or manually via JavaScript method.
14
+ * Built with the [Shepherd JS](https://shepherdjs.dev/) library. Plays nicely with Turbolinks.
15
+ * Ships with two basic CSS themes (default & dark) — or write your own
15
16
 
16
17
  ## Requirements
17
18
 
@@ -38,7 +39,7 @@ $ rails db:migrate
38
39
  Install the JavaScript dependencies:
39
40
 
40
41
  ```
41
- $ yarn add jquery@^3.4.0 js-cookie@^2.2.0 shepherd.js@^6.0.0-beta
42
+ $ yarn add js-cookie@^2.2.0 shepherd.js@^6.0.0-beta
42
43
  ```
43
44
 
44
45
  Require `abraham` in `app/assets/javascripts/application.js`
@@ -77,7 +78,7 @@ Tell Abraham where to insert its generated JavaScript in `app/views/layouts/appl
77
78
 
78
79
  ## Defining your tours
79
80
 
80
- Define your tours in the `config/tours` directory. Its directory structure should mirror your application's controllers, and the tour files should mirror your actions/views.
81
+ Define your tours in the `config/tours` directory corresponding to the views defined in your application. Its directory structure mirrors your application's controllers, and the tour files mirror your actions/views.
81
82
 
82
83
  ```
83
84
  config/
@@ -92,11 +93,15 @@ config/
92
93
  └── show.es.yml
93
94
  ```
94
95
 
95
- NB: You must specify a locale in the filename, even if you're only supporting one language.
96
+ For example, per above, when a Spanish-speaking user visits `/articles/`, they'll see the tours defined by `config/tours/articles/index.es.yml`.
97
+
98
+ (Note: You must specify a locale in the filename, even if you're only supporting one language.)
96
99
 
97
100
  ### Tour content
98
101
 
99
- A tour is composed of a series of steps. A step may have a title and must have a description. You may attach a step to a particular element on the page, and place the callout in a particular position (see below).
102
+ Within a tour file, each tour is composed of a series of **steps**. A step may have a `title` and must have `text`. You may attach a step to a particular element on the page, and place the callout in a particular position.
103
+
104
+ In this example, we define a tour called "intro" with 3 steps:
100
105
 
101
106
  ```yaml
102
107
  intro:
@@ -129,7 +134,7 @@ When you specify an `attachTo` element, use the `placement` option to choose whe
129
134
  * `bottom left`
130
135
  * `bottom right`
131
136
  * `center` / `middle` / `middle center`
132
- * `left` / `middle left'
137
+ * `left` / `middle left`
133
138
  * `right` / `middle right`
134
139
  * `top` / `top center`
135
140
  * `top left`
@@ -140,6 +145,38 @@ Abraham tries to be helpful when your tour steps attach to page elements that ar
140
145
  * If your first step is attached to a particular element, and that element is not present on the page, the tour won't start. ([#28](https://github.com/actmd/abraham/issues/28))
141
146
  * If your tour has an intermediate step attached to a missing element, Abraham will skip that step and automatically show the next. ([#6](https://github.com/actmd/abraham/issues/6))
142
147
 
148
+ ### Automatic vs. manual tours
149
+
150
+ By default, Abraham will automatically start a tour that the current user hasn't seen yet. You can instead define a tour to be triggered manually using the `trigger` option:
151
+
152
+ ```yml
153
+ walkthrough:
154
+ trigger: "manual"
155
+ steps:
156
+ 1:
157
+ text: "This walkthrough will show you how to..."
158
+ ```
159
+
160
+ This tour will not start automatically; instead, use the `Abraham.startTour` method with the tour name:
161
+
162
+ ```
163
+ <button id="startTour">Start tour</button>
164
+
165
+ <script>
166
+ document.querySelector("#startTour").addEventListener("click", function() {
167
+ Abraham.startTour("walkthrough"));
168
+ });
169
+ </script>
170
+ ```
171
+
172
+ ...or if you happen to use jQuery:
173
+
174
+ ```
175
+ <script>
176
+ $("#startTour").on("click", function() { Abraham.startTour('walkthrough'); })
177
+ </script>
178
+ ```
179
+
143
180
  ### Testing your tours
144
181
 
145
182
  Abraham loads tour definitions once when you start your server. Restart your server to see tour changes.
@@ -154,11 +191,11 @@ end
154
191
 
155
192
  ## Full example
156
193
 
157
- We provide a [small example app](https://github.com/actmd/abraham-example) that implements abraham, so you can see it in action.
194
+ We provide a [small example app](https://github.com/actmd/abraham-example) that implements Abraham, so you can see it in action.
158
195
 
159
196
  ## Upgrading from version 1
160
197
 
161
- Abraham v1 was built using Shepherd 1.8, v2 now uses Shepherd 6 -- quite a jump, yes.
198
+ Abraham v1 was built using Shepherd 1.8, v2 now uses Shepherd 6 quite a jump, yes.
162
199
 
163
200
  If you were using Abraham v1, you'll want to take the following steps to upgrade:
164
201
 
@@ -1,7 +1,28 @@
1
1
  //= require js-cookie/src/js.cookie
2
2
  //= require shepherd.js/dist/js/shepherd
3
3
 
4
+ var Abraham = new Object();
5
+
6
+ Abraham.tours = {};
7
+ Abraham.incompleteTours = [];
8
+ Abraham.startTour = function(tourName) {
9
+ if (!Shepherd.activeTour) {
10
+ Abraham.tours[tourName].start();
11
+ }
12
+ };
13
+ Abraham.startNextIncompleteTour = function() {
14
+ if (Abraham.incompleteTours.length) {
15
+ Abraham.tours[Abraham.incompleteTours[0]].checkAndStart();
16
+ }
17
+ };
18
+
19
+ document.addEventListener("DOMContentLoaded", Abraham.startNextIncompleteTour);
20
+ document.addEventListener("turbolinks:load", Abraham.startNextIncompleteTour);
21
+
4
22
  document.addEventListener('turbolinks:before-cache', function() {
5
23
  // Remove visible product tours
6
24
  document.querySelectorAll(".shepherd-element").forEach(function(el) { el.remove() });
25
+ // Clear Abraham data
26
+ Abraham.tours = {};
27
+ Abraham.incompleteTours = [];
7
28
  });
@@ -4,23 +4,31 @@ module AbrahamHelper
4
4
  def abraham_tour
5
5
  # Do we have tours for this controller/action in the user's locale?
6
6
  tours = Rails.configuration.abraham.tours["#{controller_name}.#{action_name}.#{I18n.locale}"]
7
-
7
+ # Otherwise, default to the default locale
8
8
  tours ||= Rails.configuration.abraham.tours["#{controller_name}.#{action_name}.#{I18n.default_locale}"]
9
9
 
10
10
  if tours
11
+ # Have any automatic tours been completed already?
11
12
  completed = AbrahamHistory.where(
12
13
  creator_id: current_user.id,
13
14
  controller_name: controller_name,
14
15
  action_name: action_name
15
16
  )
16
- remaining = tours.keys - completed.map(&:tour_name)
17
17
 
18
- if remaining.any?
19
- # Generate the javascript snippet for the next remaining tour
20
- render(partial: "application/abraham",
21
- locals: { tour_name: remaining.first,
22
- steps: tours[remaining.first]["steps"] })
18
+ tour_keys_completed = completed.map(&:tour_name)
19
+ tour_keys = tours.keys
20
+
21
+ tour_html = ''
22
+
23
+ tour_keys.each do |key|
24
+ tour_html += render(partial: "application/abraham",
25
+ locals: { tour_name: key,
26
+ tour_completed: tour_keys_completed.include?(key),
27
+ trigger: tours[key]["trigger"],
28
+ steps: tours[key]["steps"] })
23
29
  end
30
+
31
+ tour_html.html_safe
24
32
  end
25
33
  end
26
34
 
@@ -1,7 +1,8 @@
1
1
  <script>
2
- var tour = new Shepherd.Tour(<%= Rails.configuration.abraham.tour_options.html_safe unless Rails.configuration.abraham.tour_options.nil? %>);
2
+ Abraham.tours["<%= tour_name %>"] = new Shepherd.Tour(<%= Rails.configuration.abraham.tour_options.html_safe unless Rails.configuration.abraham.tour_options.nil? %>);
3
3
 
4
- tour.on("complete", function() {
4
+ <% if trigger != 'manual' %>
5
+ Abraham.tours["<%= tour_name %>"].on("complete", function() {
5
6
  // Make AJAX call to save history of tour completion
6
7
  return fetch("/abraham_histories/", {
7
8
  method: "POST",
@@ -15,12 +16,13 @@
15
16
  });
16
17
  });
17
18
 
18
- tour.on("cancel", function() {
19
+ Abraham.tours["<%= tour_name %>"].on("cancel", function() {
19
20
  Cookies.set('<%= abraham_cookie_prefix %>-<%= tour_name %>', 'later', { domain: '<%= abraham_domain %>' });
20
21
  });
22
+ <% end %>
21
23
 
22
24
  <% steps.each_with_index do |(key, step), index| %>
23
- tour.addStep({
25
+ Abraham.tours["<%= tour_name %>"].addStep({
24
26
  id: 'step-<%= key %>',
25
27
  <% if step.key?('title') %>
26
28
  title: "<%= step['title'] %>",
@@ -34,35 +36,40 @@
34
36
  },
35
37
  <% end %>
36
38
  buttons: [
37
- <% if index == 0 %>
38
- { text: '<%= t('abraham.later') %>', action: tour.cancel, classes: 'shepherd-button-secondary' },
39
- { text: '<%= t('abraham.continue') %>', action: tour.next }
39
+ <% if index == steps.size - 1 %>
40
+ { text: '<%= t('abraham.done') %>', action: Abraham.tours["<%= tour_name %>"].complete }
40
41
  <% else %>
41
- <% if index == steps.size - 1 %>
42
- { text: '<%= t('abraham.done') %>', action: tour.complete }
43
- <% else %>
44
- { text: '<%= t('abraham.exit') %>', action: tour.cancel, classes: 'shepherd-button-secondary' },
45
- { text: '<%= t('abraham.next') %>', action: tour.next }
46
- <% end %>
42
+ <% if index == 0 %>
43
+ { text: '<%= t('abraham.later') %>', action: Abraham.tours["<%= tour_name %>"].cancel, classes: 'shepherd-button-secondary' },
44
+ { text: '<%= t('abraham.continue') %>', action: Abraham.tours["<%= tour_name %>"].next }
45
+ <% else %>
46
+ { text: '<%= t('abraham.exit') %>', action: Abraham.tours["<%= tour_name %>"].cancel, classes: 'shepherd-button-secondary' },
47
+ { text: '<%= t('abraham.next') %>', action: Abraham.tours["<%= tour_name %>"].next }
48
+ <% end %>
47
49
  <% end %>
48
50
  ]
49
51
  });
50
52
  <% end %>
51
53
 
52
- tour.start = function (start) {
53
- return function () {
54
- // Don't start the tour if the user dismissed it once this session
55
- var tourMayStart = !Cookies.get('<%= abraham_cookie_prefix %>-<%= tour_name %>', {domain: '<%= abraham_domain %>'});
56
- <% if steps.first[1]['attachTo'] %>
57
- // Don't start the tour if the first step's element is missing
58
- tourMayStart = tourMayStart && document.querySelector("<%= steps.first[1]['attachTo']['element'] %>");
59
- <% end %>
60
-
61
- if (tourMayStart) {
62
- start();
54
+ <% if trigger != "manual" %>
55
+ Abraham.tours["<%= tour_name %>"].checkAndStart = function (start) {
56
+ return function () {
57
+ // Don't start the tour if the user dismissed it once this session
58
+ var tourMayStart = !Cookies.get('<%= abraham_cookie_prefix %>-<%= tour_name %>', {domain: '<%= abraham_domain %>'});
59
+ <% if steps.first[1]['attachTo'] %>
60
+ // Don't start the tour if the first step's element is missing
61
+ tourMayStart = tourMayStart && document.querySelector("<%= steps.first[1]['attachTo']['element'] %>");
62
+ <% end %>
63
+
64
+ if (tourMayStart) {
65
+ start();
66
+ }
63
67
  }
64
- }
65
- }(tour.start)
68
+ }(Abraham.tours["<%= tour_name %>"].start)
69
+
70
+ <% if !tour_completed %>
71
+ Abraham.incompleteTours.push("<%= tour_name %>");
72
+ <% end %>
73
+ <% end %>
66
74
 
67
- tour.start()
68
75
  </script>
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Abraham
4
- VERSION = "2.2.0"
4
+ VERSION = "2.3.0.beta"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: abraham
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.3.0.beta
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Abbett
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-15 00:00:00.000000000 Z
11
+ date: 2021-04-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sassc-rails
@@ -126,9 +126,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
126
126
  version: '0'
127
127
  required_rubygems_version: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - ">="
129
+ - - ">"
130
130
  - !ruby/object:Gem::Version
131
- version: '0'
131
+ version: 1.3.1
132
132
  requirements: []
133
133
  rubygems_version: 3.0.8
134
134
  signing_key: