Git Product home page Git Product logo

abraham's Introduction

Abraham

Build Status

Guide your users in the one true path.

Watercolor Sheep

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).

  • Define tour content with simple YAML files, in any/many languages.
  • Organize tours by controller and action.
  • Trigger tours automatically on page load or manually via JavaScript method.
  • Built with the Shepherd JS library. Plays nicely with Turbolinks.
  • Ships with two basic CSS themes (default & dark) — or write your own

Requirements

  • Abraham needs to know the current user to track tour views, e.g. current_user from Devise.
    • If you are using a different method to identify who is currently logged in, you can, for example, add an alias to make it work. Assuming you have a method current_foo to identify your currenly logged-in user, you can add alias_method 'current_user', 'current_foo' in the place you define current_foo.
  • Abraham is tested on Rails 5.2, 6.0, and 6.1

Installation

Add abraham to your Gemfile:

gem 'abraham'

Install the gem and run the installer:

$ bundle install
$ rails generate abraham:install
$ rails db:migrate

Install the JavaScript dependencies:

$ yarn add js-cookie@^2.2.0 shepherd.js@^6.0.0-beta

Require abraham in app/assets/javascripts/application.js

//= require abraham

Require a CSS theme in app/assets/stylesheets/application.scss

*= require abraham/theme-default

Abraham provides the following themes:

  • theme-default
  • theme-dark

Update config/abraham.yml if you choose a different theme:

defaults: &defaults
  :tour_options: '{ defaultStepOptions: { classes: "theme-dark" } }'

You can also write your own Shepherd theme based on Shepherd's default CSS.

Tell Abraham where to insert its generated JavaScript in app/views/layouts/application.html.erb, just before the closing body tag:

<%= abraham_tour %>
</body>
</html>

Defining your tours

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. (As of version 2.4.0, Abraham respects controllers organized into modules.)

config/
└── tours/
    ├── admin/
    │   └── articles/  
    │       └── edit.en.yml    
    ├── blog/
    │   ├── show.en.yml
    │   └── show.es.yml    
    └── articles/
        ├── index.en.yml
        ├── index.es.yml
        ├── show.en.yml
        └── show.es.yml

For example, per above, when a Spanish-speaking user visits /articles/, they'll see the tours defined by config/tours/articles/index.es.yml.

(Note: You must specify a locale in the filename, even if you're only supporting one language.)

Tour content

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.

In this example, we define a tour called "intro" with 3 steps:

intro:
  steps:
    1:
      text: "Welcome to your dashboard! This is where we'll highlight key information to manage your day."
    2:
      title: "Events"
      text: "If you're participating in any events today, we'll show that here."
      attachTo:
        element: ".dashboard-events"
        placement: "right"
    3:
      title: "Search"
      text: "You can find anything else by using the search bar."
      attachTo:
        element: ".navbar-primary form"
        placement: "bottom"

Abraham takes care of which buttons should appear with each step:

  • "Later" and "Continue" buttons on the first step
  • "Exit" and "Next" buttons on intermediate steps
  • "Done" button on the last step

See below for how to define custom buttons.

When you specify an attachTo element, use the placement option to choose where the callout should appear relative to that element:

  • bottom / bottom center
  • bottom left
  • bottom right
  • center / middle / middle center
  • left / middle left
  • right / middle right
  • top / top center
  • top left
  • top right

Abraham tries to be helpful when your tour steps attach to page elements that are missing:

  • 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)
  • If your tour has an intermediate step attached to a missing element, Abraham will skip that step and automatically show the next. (#6)

Automatic vs. manual tours

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:

walkthrough:
  trigger: "manual"
  steps:
    1:
      text: "This walkthrough will show you how to..."

This tour will not start automatically; instead, use the Abraham.startTour method with the tour name:

<button id="startTour">Start tour</button>

<script>
  document.querySelector("#startTour").addEventListener("click", function() {
    Abraham.startTour("walkthrough"));
  });
</script>

...or if you happen to use jQuery:

<script>
  $("#startTour").on("click", function() { Abraham.startTour('walkthrough'); })
</script>

Custom buttons

You can define custom buttons in a step like so:

my_tour:
  steps:
    1:
      text: "Welcome to my custom button tour"
      buttons:
        1:
          text: 'Show this to me later'
          action: 'cancel'
          classes: 'custom-button shepherd-button-secondary'
        2:
          text: 'Finish now'
          action: 'complete'
          classes: 'custom-button'
  • action is one of the Shepherd tour method names, i.e. cancel, next, or complete
  • classes are the CSS class names you want applied to the button

Flipper integration

If you have Flipper installed as a dependency in your project you will be able to enable or disable tours based on a flipper using the flipper_key option. This will automatically enable a tour when this flipper is active and disable it when it's inactive.

walkthrough:
  flipper_key: "name_of_flipper"
  steps:
    1:
      text: "This walkthrough will show you how to..."

If you would like to disable a tour when a flipper is active you may couple the flipper_key option with the flipper_activation option. flipper_activation supports "enabled" or "disabled" as options. If you enter something other than "enabled" or "disabled" it will use the default, which is "enabled".

walkthrough:
  flipper_key: "name_of_flipper"
  flipper_activation: "disabled"
  steps:
    1:
      text: "This walkthrough will show you how to..."

Testing your tours

Abraham loads tour definitions once when you start your server. Restart your server to see tour changes.

If you'd like to run JavaScript integrations tests without the Abraham tours getting in the way, clear the Abraham configuration in your test helper, e.g.

Rails.application.configure do
  config.abraham.tours = {}
end

Full example

We provide a small example app that implements Abraham, so you can see it in action.

Upgrading

From version 2.3.0 or earlier

Abraham 2.4.0 introduced an updated initializer that supports controllers organized into modules. Rerun the generator with these options to replace the old initializer:

$ rails generate abraham:install --skip-migration --skip-config

From version 1

Abraham v1 was built using Shepherd 1.8, v2 now uses Shepherd 6 – quite a jump, yes.

If you were using Abraham v1, you'll want to take the following steps to upgrade:

  1. Update your gem to the latest version
  2. Fix your yarn dependencies to use the right versions
  3. Shepherd no longer provides a set of themes. Abraham maintains two of the legacy themes: default and dark. You'll want to choose one of those or migrate your theme to the new Shepherd structure.
  4. Abraham now exposes the entire Shepherd configuration object, so your abraham.yml file should now fully define the tour_options value instead of default_theme
  5. There's been a slight change to initializers/abraham.rb. Replace yours with the latest.

If you have any trouble at all, please submit an issue for assistance!

Contributing

Contributions are welcome!

Create a feature branch (using git-flow) and submit as a pull request (with a base branch of develop).

Everyone interacting in Abraham's codebase, issue tracker, etc. is expected to follow the Contributor Covenent Code of Conduct.

Getting started with the source code

Abraham uses rvm with a gemset to ensure the appropriate version of Ruby and its dependencies. Make sure that's installed before you get started.

~ git clone [email protected]:actmd/abraham.git
Cloning into 'abraham'...
~ cd abraham
ruby-2.5.3 - #gemset created /Users/jon/.rvm/gems/ruby-2.5.3@abraham
ruby-2.5.3 - #generating abraham wrappers - please wait
~ bundle install
Bundle complete! 13 Gemfile dependencies, 73 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
~ yarn install

Testing

Testing locally

This Rails engine contains a test app called dummy with controller and system tests. They'll all get run with rails t.

Please note that if you change anything in the lib/generators folder (i.e. configuration, intializer, migration) you'll need to migrate the dummy app accordingly.

Final testing should be done in a standalone Rails app, following the README instructions.

To install the abraham gem with a local path:

gem 'abraham', path: '~/Workspace/abraham'

Automated testing

We use GitHub Actions to automatically test this engine with Rails 5.2, 6.0, and 6.1.

Releasing

Create a git-flow release:

$ git flow release start VERSION_NUMBER

Edit lib/abraham/version.rb and increase the version number.

Build the gem and push to Rubygems:

$ rake build
$ gem push pkg/abraham-VERSION_NUMBER.gem

Finish the git-flow release and push to GitHub:

$ git flow release finish
$ git push origin develop
$ git push origin master
$ git push --tags

abraham's People

Contributors

aashishpsaini avatar brotherbain avatar canderson180 avatar dependabot-preview[bot] avatar dwyerb64 avatar jabbett avatar jwarrenac avatar karthik-sivadas avatar kofronpi avatar mohitnatoo avatar scarroll32 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

abraham's Issues

Manually activate a tour (e.g. on click)

For example when hovering over the "starred items" icon on Slack, you get a nice popup as follows

screen shot 2016-12-29 at 9 11 13 am

Then when you click on the icon, the (single step) tour begins

screen shot 2016-12-29 at 9 11 20 am

The nice thing is that the "hover" step doesn't need to be there (e.g. on mobile there is no "hover") and so it works nicely on both desktop and mobile.

rails generate abraham:install not working

Is this potentially a rails 5 issue?

Output below:

rails generate abraham:install
Running via Spring preloader in process 47672
Expected boolean default value for '--markerb'; got :erb (string)
Expected string default value for '--controller'; got false (boolean)
Expected string default value for '--helper'; got true (boolean)
Expected string default value for '--assets'; got true (boolean)
Could not find generator 'abraham:install'. Maybe you meant 'rspec:install', 'koudoku:install' or 'devise:install'
Run `rails generate --help` for more options.

Issue with query selectors

Hi there,

When using specific query selectors in the "element" property in tours YML, some errors are raised for advanced selectors, eg. [id^="whatever"] or .class > #id

As specials characters like < > or quotes are escaped, it raises javascript errors.

Is there any way to either add .raw or .html_safe to this line?

attachTo: { element: "<%= step['attachTo']['element'] %>", on: "<%= step['attachTo']['placement'] %>" },

How to restart tour for user? (issue with deleting cookie)

Hi,

I'm trying to add a "reset" button to my site that would effectively restart the tour after the user has either clicked "later" or fully completed the tour. I tried deleting the abraham_histories entries with the creator_id and also tried to do Cookie.remove(COOKIE_KEY) but that's not working; I can still see the cookie with Cookie.get(). It only works if I delete the cookies through the browser, but not via JS, which makes me think I'm on the right track but missing something.

I tried Cookie.remove(COOKIE_KEY) as well as Cookie.remove(COOKIE_KEY, {path: PATH}) with different path combinations. Nothing worked. Any ideas?

Launch tour on demand

Is it possible to start tour on demand by calling a function or something?

Would it for example be possible to implement a "Launch Tour" button on a page?

Travis is not running system tests in Rails 6+

rails test seems to run all tests in Rails 5, but only runs non-system tests in Rails 6.

Travis has been reporting successful builds in Rails 6, but it turns out it has never run the full test suite.

Uncaught ReferenceError: Shepherd is not defined

After following all the steps in the Readme I got this error in my webapp:
(index):924 Uncaught ReferenceError: Shepherd is not defined
This is my abraham.yml file:

defaults: &defaults
  # Add any valid Shepherd.js configuration JSON here
  # and it will be passed into the `new Shepherd.Tour()`
  # initializer.
  :tour_options: '{ defaultStepOptions: { classes: "theme-default" } }'

development:
  <<: *defaults

test:
  <<: *defaults

production:
  <<: *defaults

All the rest, tours structure is the same as the views and I have required css and js Abraham files.

This is the gem I have in my gemfile.lock:
abraham (2.1.1)

I am using ruby 2.7 and rails 6.0

Attach tour on lazy loading elements like modals

The tour seems to check if the if the element for a tour step exist on the page.

What if the application happens to load some partials by javascript, for example a modal that does not exist on page right away. So how to implement a tour for modal content?

Automatically skip a step if its attachTo.element isn't on the page

Shepherd.js will insert raw, unstyled content into your page if a step's attachTo.element isn't present. Beyond the disappointing user experience, this also makes tours brittle because they have to be so tightly coupled with whatever particular dynamic elements are visible to a user.

There is an undocumented showOn option in Shepherd (usage example) that will let us check first whether the element is present. If not, we can skip to the next step.

I propose we make this behavior Abraham's default.

ERROR in ./node_modules/abraham/cli.js 1:0 Module parse failed: Unexpected character '#' (1:0)

Not sure if this is more a webpack issue than with abraham, but I'm getting the error:

ERROR in ./node_modules/abraham/cli.js 1:0
Module parse failed: Unexpected character '#' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders

#!/usr/bin/env node
| 'use strict';

The tour works fine in my application, but this error is constantly in the console and I'm having issues with builds because of it. I've tried a webpack loader as suggested in webpack/webpack#4603, however that's not working so I wondered if anyone had come across this and there was a fix?

Implement in-browser system tests

Now that Abraham is configured for Rails 5.1 support, it'll be easier to beef up our test coverage, specifically testing that Abraham's generated JavaScript functions within a browser using now-built-in Capybara.

How to achieve multi pages tours alike redirecting from one page to another?

I want to show multiple Pop-up modal on different pages when user completed its registration. For instance, when user visits home page, shown up first pop-up modal, then user clicks 'Next' button on popup, it should be display other page pop-up modal and so on. how to achieve that functionality ?

Thanks in advance.

using js-cookie@^3.1 instead of js-cookie@^2.2.0

In our app we use js-cookie@^3.1, and when i tried to down grade to version 2.2, my app doesn't function correctly.
so i want to keep using js-cookie@^3.1
i fixed this by:
In gems/abraham-2.5.1/app/assets/javascripts/abraham/index.js i changed
//= require js-cookie/src/js.cookie
to:
//= require js-cookie/dist/js.cookie

js-cookie/dist/js.cookie is the default path for version 3.1
i would like to ask , is there a way to do that without modifying the gem?

Web UI?

Thanks for this gem - it looks great. Wondering if you've thought about building out any kind of web ui for managing the tours (rather than yaml). It'd be great to let non-technical members of my team create/manage tours. There are a million SaaS offerings for this out there, but they're 1) expensive and 2) not great.

Just wondering what thought has been given to this before I go ahead and start building in this direction myself.

Don't start a tour if the first step's attachTo isn't present

Related to #6... while we want to keep a tour going if an intermediate step is missing, most tours don't make sense if the first step gets skipped.

I'd like to add a check to our start method wrapper that confirms the first step's attachTo element is present on the page, should the first step have an attachTo value.

Rails 5.1 support

Hi @jabbett
Tried out this gem today and blown away (really impressed).
I forked it and changed the rails dependency for it to work with rails 5.1:

See abraham.gemspec line 20.

s.add_dependency 'rails', '~> 5.0', '>= 5.0.0.1'

Question: access to the full Shepherd API?

The Abraham documentation talks about steps, and the example has element and placement

   title: "Events"
      text: "If you're participating in any events today, we'll show that here."
      attachTo:
        element: ".dashboard-events"
        placement: "right"

The Shepherd API offers many other options on the Step object, including popperOptions, highlightClass, arrow etc.

Does Abraham support all of these options?

https://shepherdjs.dev/docs/

Update documentation for Rails 7

Would be helpful to update installation/config documentation to Rails 7 standards. I tried installing this morning on a rails 7 app and couldn't get it working. I ultimately uninstalled everything, but I would still love to use the gem once the documentation adapts to a rails 7 environment.

If user has more than one unviewed tour, show them both?

As we've used Abraham in our software for a while now, we're at the point of adding new features to pages that already have introductory tours. We want new users to learn about all the features, and we want old users to learn about the new features.

Currently, there two ways for that play out:

  1. Include the new feature tour content in a second, feature-specific tour. Existing users who have seen the introductory tour only see the new feature-specific one. New users see the intro tour first (without the new feature mentioned) and then have to revisit the same page later to see the second tour.
  2. Include the new feature tour content in both the introductory tour AND a second, feature-specific tour. Existing users who have seen the introductory tour only see the new feature-specific one. New users see the same content duplicated in both the introductory tour and when they revisit the same page later, in the second, feature-specific tour.

Neither is a great user experience.

There are a few ways we could improve this:

  1. Abraham shows a user all unseen tour content for a page. This approach would benefit from developers writing several smaller tours on a per-callout basis that would naturally string together, rather than large cohesive tours.
  2. We add some notion of a "release date" for each tour. Tours with a release date would only get shown if the user had visited the page some time before the release. Of course, this requires Abraham knowing more about the user than just their current_user.id, which may not be desirable or possible in all cases.

Anyhow, open to suggestions!

Uncaught SyntaxError: Identifier 'tour' has already been declared

In v2, I switched from "var" to "const" to define the tour object.

When you navigate between tour-enabled pages with Turbolinks, you'll get the JS error:

Uncaught SyntaxError: Identifier 'tour' has already been declared

We need to fix this for Turbolinks users.

How to handle controllers with the same name?

Hi there,

Thanks for making Abraham :)

My issue is that I have some namespaced controllers / actions with the same name, eg. :

  • User::Dashboard#index
  • Admin::Dashboard#index

Namespaces aren't taken into account in Abraham so I had put my yml file inside tours/dashboard/index.en.yml which results in the tour displaying in both dashboards.

I've tried changing the initializer to take subfolders like tours/admin/dashboard/index.en.yml into account but with no luck, Abraham doesn't recognize the controller.

Any clue?

Thanks

Provide full configuration of underlying Shepherd.Tour JS component

Right now, the shepherd component is initialized like this:

  var tour = new Shepherd.Tour({
    defaults: {
      classes: '<%= Rails.configuration.abraham.default_theme %>'
    }
  });

It would be great to be able to use all of Shepherd.js options.

Maybe it would be easier to do with PORO Abrahamah tours rather than yml files, just suggesting :)

Use another id than current_user's one

Hi there,

Thanks for the great job with Abraham. I was wondering if there was any possibility to pass in some other model id to a tour? Not just the user's one via current_user?

Thanks,

Thomas

Custom buttons and actions

Hi. Thank you for porting shepherd to Rails!

I have a question

I see that shepherd shows that buttons with custom actions can be included in tour steps, e.g.:

buttons: [
{
action() {
return this.back();
},
text: 'Back'
},

(from their demo page at https://shepherdjs.dev/)

I can't figure out how to do this with Abraham. I suspect I'm not using the correct syntax, but it's not clear to me what the correct one would be (shepherd's vanilla syntax doesn't seem to work for me).

Sourcemap errors

Is anyone else getting sourcemap errors in development? I think I have following the install instructions correctly but am seeing this error in my Rails logs

ActionController::RoutingError (No route matches [GET] "/assets/shepherd.js.map"):

actionpack (5.2.5) lib/action_dispatch/middleware/debug_exceptions.rb:65:in `call'
rollbar (3.0.1) lib/rollbar/middleware/rails/show_exceptions.rb:22:in `call_with_rollbar'
rack-contrib (2.1.0) lib/rack/contrib/response_headers.rb:17:in `call'
meta_request (0.7.0) lib/meta_request/middlewares/headers.rb:16:in `call'
actionpack (5.2.5) lib/action_dispatch/middleware/show_exceptions.rb:33:in `call'
railties (5.2.5) lib/rails/rack/logger.rb:38:in `call_app'
railties (5.2.5) lib/rails/rack/logger.rb:26:in `block in call'
etc

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.