Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Table of Contents
Excerpt

The Tutorials feature enables a system administrator to create custom tutorials for specific user roles.

The tutorial system enables you to provide information, focus on a specific Abiquo UI element, and require the user to perform an action in order to continue. Thus you can streamline the process of onboarding users with your own platform walkthroughs.

Events and tracers to monitor users working with tutorials will be added in a future version.

You can easily customize the sample tutorials or design your own following the instructions below.

Enable or disable tutorials

By default in new installations, tutorials are enabled and in upgraded environments, tutorials are disabled. Sample content is available in all environments.

Abiquo displays a tutorial on login when:

  • The Enable tutorials checkbox is marked in Configuration view

  • There is tutorial content in the folder for the user’s role on the UI server

  • The user has not marked the "Don't show me again checkbox" in their browser, which sets a cookie to not show the tutorials

Users can manually open the tutorials at any time by clicking the tutorials link at the bottom of the screen.

Image Removed

Status
titleUnknown Attachment

IntroJs library

This feature is based on the IntroJs library, which has been customized to fit our requirements.

Architecture

Note

Changes to Tutorial Architecture in 3.2.2

In Abiquo 3.2.2 and above, the installation of the default Abiquo tutorials will backup the /var/www/html/ui/config/tutorials directory and replace it with a symbolic link to the /opt/abiquo/tutorials directory. However, Abiquo will read the tutorials from /var/www/html/ui/config/tutorials. You can change the symbolic link to point to your own tutorials directory, for example, /opt/abiquo/mytutorials.

The manual tutorial installation that you perform as part of the Abiquo 3.2.2 upgrade process will create a backup of the existing directory, a new default tutorials directory and a symbolic link to the default tutorials directory. You can then change this symbolic link to point to your own tutorials directory.  

'tutorials' content folder in Abiquo 3.2.2 and above

Abiquo will read the tutorials from /var/www/html/ui/config/tutorials. This will be a symbolic link to the default Abiquo tutorials content folder or to your own custom content folder.

Warning

From Abiquo 3.2.2, the default tutorials content folder has been moved to /opt/abiquo/tutorials and a symbolic link will be created from /var/www/html/ui/config/tutorials to /opt/abiquo/tutorials

Abiquo will create tutorials.backup with existing content as part of the tutorials install or upgrade process. To create your own tutorials content, create a new tutorials folder, for example, /opt/abiquo/mytutorials and create a new symbolic link from /var/www/html/ui/config/tutorials to your directory

The tutorials content folder is found under the default Abiquo install folder:

By default this will be: /opt/abiquo/tutorials/

This folder will contain a folder for each user role with a sample tutorial. 

Code Block
[root@mjspac /]# tree -d /opt/abiquo
/opt/abiquo
|...
|--- tutorials
    |-- CLOUD_ADMIN
    |-- ENTERPRISE_ADMIN
    |-- USER

To create your own tutorials content, create a new tutorials folder, for example, /opt/abiquo/mytutorials and create a new symbolic link from /var/www/html/ui/config/tutorials to your directory. For example:

Code Block
mkdir /opt/abiquo/mytutorials
ln -s /opt/abiquo/mytutorials /var/www/html/ui/config/tutorials

Apache configuration

Check the Apache configuration, which by default is at /etc/httpd/conf/httpd.conf. Within the directive /var/www/html/ui , in the Options line, you should enable FollowSymLinks by adding this as an option. 

Code Block
<Directory "/var/www/html/ui">
? ? ? ? Options MultiViews FollowSymLinks

'tutorials' content folder in Abiquo 3.2 to Abiquo 3.2.1

The tutorials content folder is found under the UI folder:

By default this will be: /var/www/html/ui/config/tutorials/

This folder will contain a folder for each user role with a sample tutorial. 

Code Block
[root@mjspac /]# tree -d /var/www/html/ui/config
/var/www/html/ui/config
|-- client-config.json
|-- tutorials
    |-- CLOUD_ADMIN
    |-- ENTERPRISE_ADMIN
    |-- USER

'{role_name}' folders

For example, for the USER role, the tutorials folder contains a USER folder. This folder contains a file named tutorials.json and then a file for each tutorial you want the user to work through. You can see the user role at the bottom of the following filesystem diagram.

Code Block
[root@mjspac /]# tree /var/www/html/ui/config
/var/www/html/ui/config
|-- client-config.json
|-- tutorials
    |-- CLOUD_ADMIN
    |   |-- abiquo_concepts.json
    |   |-- appliance_library.json
    |   |-- create_infrastructure.json
    |   |-- create_tenant.json
    |   |-- deploy_first_vm.json
    |   |-- trial_license.json
    |   |-- tutorials.json
    |
    |-- ENTERPRISE_ADMIN
    |   |-- appliance_library.json
    |   |-- deploy_first_vm.json
    |   |-- enable_team.json
    |   |-- quick_ent_admin_view.json
    |   |-- tutorials.json
    |
    |-- USER
        |-- deploy_first_vm.json
        |-- quick_user_view.json
        |-- tutorials.json

To create a new tutorial, for example for a role in your environment called CLOUD_USER, create a folder in the tutorials folder called CLOUD_USER.

Code Block
[root@api tutorials]# mkdir CLOUD_USER

See Manage Roles for more information about user roles.

'tutorials.json' file

This file will contain some information about the tutorials and the list of available tutorials. The file must be named tutorials.json, otherwise it will not work. 

General attributes

Name

Type

Required

Description

Example

popupTitle

String

yes

This attribute specifies the tutorial popup title

"Abiquo tutorials"

welcomeImgUrl

String

no

This attribute specifies if you want to display pictures in the header of the main tutorials page. The path can be absolute or relative

absolute: "http://blog.interdominios.com/wp-content/2008/abiquo.png"

relative: "./config/tutorials/{image_name.extension}"

welcomeText

String

yes

This attribute is for the main tutorial page description, to describe the tutorials, the company, and so on. You can use HTML tags

"Welcome to <strong>Abiquo</strong> Here is the list of all available tutorials"

width

Number

yes

This atrribute specifies the tutorial popup width

500

moreInfoUrl

String

no

If you specify a URL, then a help icon will appear in the tutorial popup, pointing to this attribute value

"http://http://wiki.abiquo.com"

tutorials

Array

yes

This is the tutorial list array (see below for more details)

[{"name": "Deploy my first application", "file": "deploy_first_vm"}]

translationCodes

Object

no

For a multi-language tutorial popup, add this object with the label you want to translate

{}

translationCodes.
popupTitle

String

no

Add this attribute if you want the title to be translated in multi-language environments. The value must match a translation code in related multi-language files (in lang/lang_en_US_custom.json for example)

"tutorials.popupTitle"

translationCodes.
welcomeText

String

no

Add this attribute if you want the tutorial page description to be translated in multi-language environments. The value must match with a translation code in related multi-language files (in lang/lang_en_US_custom.json for example)

"tutorials.welcomeText"

Tutorials list array

Name

Type

Required

Description

Example

name

String

yes

This is the name of the tutorial you want to display

"Deploy my first virtual machine"

file

String

yes

This is the name of the file containing all tutorial information. This value must match with the tutorial file name

"deploy_first_vm"

translationCode

String

no

This is for multi-language support. By default, the text displayed for each tutorial will be the name value. You can use this attribute to specify a translation code, but be sure to add the translation code (and its translation) in all required language files, otherwise it will not work correctly.

"tutorial.deploy_first_vm"

Sample and screenshot

This is a sample of a tutorials.json file

tutorials.json
Code Block
{
    "welcomeImgUrl": "http://blog.interdominios.com/wp-content/2008/abiquo.png",
    "welcomeText": "Welcome to <strong>Abiquo</strong> Here is the list of all available tutorials",
    "width": 1000,
    "moreInfoUrl": "http://http://wiki.abiquo.com",
    "tutorials": [
        {"name": "Deploy my first application", "file":"deploy_first_vm"}
    ],
    "translationCodes":{
        "popupTitle": "tutorials.popupTitle",
        "welcomeText": "tutorials.welcomeText"
    }
}

And a screenshot of the sample tutorials popup in Abiquo

Image Removed

Status
titleUnknown Attachment

Tutorial details

We saw how to create tutorials for a group of users (by adding content for their Role). Now let's see how to create new tutorials and how to configure them.

Previously, we saw that, in the tutorials.json file, you have to specify the list of available tutorials, by specifying each tutorial name and file. So now you have to create a JSON file for each tutorial, in the same folder where the tutorials.json is located.

{tutorial_name}.json file

This file must be located in /config/tutorials/{ROLE_NAME}/ 

General attributes

Name

Type

Required

Description

Example

steps

Array

true

This is the list of tutorial steps, step attributes are listed below

[{"intro":"Welcome to Abiquo's first tutorial"}]

-

-

-

-

-

As you can see, for now the only attribute should be the steps one, in future releases we will probably add more attributes to improve this feature

Step attributes

Name

Type

Required

Dependency*

Description

Example

Screenshot

intro

String

true

-

This is the only required element and it can be used alone. This is the text displayed to explain the current step.
You can use HTML tags to improve user experience. If you don't specify the element attribute, the step will be added in the middle of the screen: this can be used for the first or final step, for example

Info

Unique line

You have to put the entire value on a single line. If you are using HTML tags, use <br> to add some space


"Welcome to <strong>Abiquo</strong><br>The objective of this tutorial is to help you deploy your first <strong>virtual machine</strong><br>You will see that it's very easy and quick :)<br><strong>Let's start!</strong>"


translationCode

String

no

-

This is for multi-language support. By default, the text displayed for each description will be the intro value. You can use this attribute to specify a translation code, but be sure to add the translation code (and its translation) in all required language files, otherwise it will not work correctly.

"tutorial.step.1"


element

String

no

-

The javascript library is designed to highlight a specific UI element, and add a description of this element. This attribute is used to select an HTML element to highlight. Be careful of the following format restrictions:

  • Start with '#', indicating that we are searching element by id

  • Use '\\' to prevent '-' and '.', because most element IDs are composite names, and these two characters must be escaped

See #How to find the element id/name

-------------------------------------------------------------------------------------------------------

IMPORTANT: element by name

To identify an element by its name, use the following identifyElementBy attribute. Then specify the element attribute with its exact name (you don't need to use # or \\)

-------------------------------------------------------------------------------------------------------

HTML element example: <a id="element.id" name="element_name">I'm a simple link</a>

Search by id

element: "#element\\.id"

Search by name

element: "element_name",
identifyElementBy: "name" 


"#virtualdatacenters\\.tab"

identifyElementBy

String

no

-

This attribute is used to specify that the element should be identified by something other than the id. At the moment, name is the only option.

If you don't use this attribute (default behavior), the element will be identified by id.

name


subElement

Object

no

-

This attribute is used to specify another view element, different from the element to receive the user interaction (see actionType). The format should be as in the element format.

Example

  • element: a vapp element in Virtual Datacenter view

  • subElement: the enter button, this button should receive the user click action



subElement.
element

String

required if

subElement

  • Same as parent element attribute, it's used to specify the id or the name of the subElement which receives the user interaction

"#vdc\\.vapp\\.enter\\-0"

subElement.
getElementBy

String

required if

subElement

This attribute is used to specify that the sub-element should be identified by something other than the id. At the moment, name is the only option.

If you don't use this attribute (default behavior), the sub-element will be identified by id.

name


actionType

String

required if

element

This attribute can control the user action before going to the next step. If you don't specify it, the Next button will always be active and the interaction with the user will be poor.

The actionType can have three values:

  • "onclick": this value specifies that the user needs to click the element (or subElement) in order to go to the next step.

  • "ondblclick": this value specifies that the user needs to double click the element (or subElement) in order to go to the next step.

  • "{event.name}": you can specify an event type to wait for, and automatically go to the next step. For example, when you are creating a virtual appliance, you want to wait for 'virtualAppliance.created' to continue. These events are dispatched in the clientUi, and displayed at the end of this document in the #List of clientUi events

"onclick"


position

String

required if

element

This attribute is for positioning the description element related to the element. Values can be:

  • left

  • right

  • top

  • bottom

"bottom"

(In the previous element screenshot, you can see that the description is placed at the bottom of selected element)


blockPrevious

Boolean

no

-

By default, in the description zone, you have three buttons: Exit, Previous and Next. All buttons are available for each step (except Previous in the first step and Next in the last step). With this attribute, you can block the Previous button in specific steps, which can be useful in some cases, for example, when you ask the user to click a button to change the a main view, and you don't want the user to go back to the previous view.

You can also block the Next button, for details, please see the actionType attribute



delayBeforeNextItem

Number

no

-

This attribute can be used to add a timeout before going to the next step. When the library goes to the next step, the next element should exist in the view, otherwise the tutorial will fail. This attribute is very helpful when you are changing the current view and it's necessary to wait until the next element is retrieved from the database and loaded.

The value is in milliseconds

1000


skipStep

Object

no

-

Some steps can be skipped, for example, if the user already did the tutorial, or if a step needs an element to be created, but the element already exists.

"skipStep":{
"existingElement":"vapp",
"identifyElementBy":"name",
"stepsToSkip":2
}


skipStep.
existingElement

String

required if

skipStep

This attribute is to check if an element exists. You can specify the element name or id (check the identifyElementBy attribute)

"vapp"


skipStep.
identifyElementBy

String

required if

skipStep

Use this attribute to specify if the existingElement should be located by name or by id

"name"


skipStep.
stepsToSkip

Number

required if

skipStep

Specify the number of steps to skip if the existingElement is located (the minimum is 1, means to skip this step and go to the next one)

2


-

-

-

-

-

-


Sample

Here you can find a sample of a tutorial file

Tutorial sample file
Code Block
{
    "steps" : [
        {
            "intro": "Welcome to <strong>Abiquo</strong><br>The objective of this tutorial is to help you deploy your first <strong>virtual machine</strong><br>You will see that it's very easy and quick :)<br><strong>Let's start!</strong>"
        },
        {
            "element": "#virtualdatacenters\\.tab",
            "intro": "In the <strong>Virtual Datacenter</strong> section, you will manage all you virtual infrastructure, let's begin by clicking this icon<br><br><span style='color: orange'><strong>Action Needed:</strong></span><br><i>Click the <strong>'Virtual Datacenters'</strong> icon to continue</i>",
            "position": "bottom",
            "actionType": "onclick",
            "blockPrevious": true
        },
        {
            "element": "#virtual\\-datacenter\\-list\\-container",
            "intro": "This is the list of available <strong>virtual datacenters</strong>, each of them contains some virtual appliances<br>",
            "position": "right",
            "translationCode":"tutorial.step.1"
        },
        {
            "element": "#vdc\\-0",
            "intro": "Select the 'vdc' virtual datacenter in order to continue with virtual appliance creation<br><br><span style='color: orange'><strong>Action Needed:</strong></span><br><i>Select the <strong>'vdc'</strong> virtual datacenter</i>",
            "position": "right",
            "actionType": "onclick",
            "delayBeforeNextItem": 1000
        },
        {
            "element": "#create\\.vapp",
            "intro": "You can now create a virtual appliance, which contains virtual machines you'll want to deploy<br><br><span style='color: orange'><strong>Action Needed:</strong></span><br><i>Click the '+' button</i>",
            "position": "left",
            "actionType": "onclick",
            "skipStep":{
                "existingElement":"vapp",
                "identifyElementBy":"name",
                "stepsToSkip":2
            }
        },
        {
            "element": "#newVirtualApplianceForm",
            "intro": "Fill all required fields and then click the 'Save' button to create the <strong>virtual appliance</strong><br>",
            "position": "left",
            "actionType":"virtualAppliance.created",
            "blockPrevious": true
        },
        {
            "element": "#vdc\\.vapp\\.list",
            "intro": "The <strong>virtual appliance</strong> has been created and you can find it in this list<br>",
            "position": "top",
            "blockPrevious": true
        },
        {
            "element": "#vdc\\.vapp\\-0",
            "subElement": "#vdc\\.vapp\\.enter\\-0",
            "intro": "The virtual appliance contains your virtual machines, you need to add at least one to deploy it<br><br><span style='color: orange'><strong>Action Needed:</strong></span><br><i>Click the 'enter' button</i>",
            "position": "top",
            "actionType": "onclick",
            "delayBeforeNextItem":300
        },
        {
            "element": "#vapp\\.vmTemplate\\.list",
            "intro": "A <strong>virtual machine</strong> is based on a </strong>virtual machine template, here you can find all the available template</strong><br>",
            "position": "right",
            "blockPrevious": true
        },
        {
            "element": "#vapp\\.vmTemplate\\-0",
            "intro": "Let's use this template, please double click on it to use it as a virtual machine (<strong>note:</strong> you can also drag&drop the template into the virtual machine list on the right)<br><br><span style='color: orange'><strong>Action Needed:</strong></span><br><i>Double click the 'm0n0wall' virtual machine template</i>",
            "position": "right",
            "actionType": "ondblclick",
            "skipStep":{
                "existingElement":"#vapp\\.vm\\-0",
                "identifyElementBy": "id"
            }
        },
        {
            "element": "#vapp\\.vm\\.list",
            "intro": "The virtual machine has been created and now ready to be deployed<br>",
            "position": "left"
        },
        {
            "element": "#vapp\\.deploy",
            "intro": "Now you just have to click the <strong>Deploy Virtual Appliance</strong> button in order to deploy all virtual machines<br><br><span style='color: orange'><strong>Action Needed:</strong></span><br><i>Click the 'Deploy Virtual Appliance' button to continue</i>",
            "position": "left",
            "actionType": "onclick",
            "delayBeforeNextItem":1000
        },
        {
            "element": "#vapp\\.vm\\-0",
            "intro": "You can see that the virtual machine is being deployed, it will be deployed once the state is 'DEPLOYED'<br>",
            "position": "right"
        },
        {
            "intro": "You can see that the virtual machine is being deployed, you have successfully completed this tutorial<br><br><span style='color: green'><strong>Tutorial completed:</strong></span><br><i>You have deployed your first virtual machine</i>"
        }
    ]
}

List of clientUi events

Here you can find some most useful clientUI events

  • allocationRule.created

  • allocationRule.edited

  • allocationRule.deleted

  • volume.created

  • volume.edited

  • volume.deleted

  • category.created

  • category.edited

  • category.deleted

  • templateDefinitions.created

  • templateDefinitions.deleted

  • virtualDatacenter.created

  • virtualDatacenter.edited

  • virtualDatacenter.deleted

  • virtualAppliance.created

  • virtualAppliance.edited

  • virtualAppliance.deleted

  • user.created

  • user.edited

  • user.deleted

  • storagePools.created

  • storagePools.edited

  • storagePools.deleted

  • storageDevices.created

  • storageDevices.edited

  • storageDevices.deleted

  • physicalMachine.created

  • physicalMachine.discovered

  • physicalMachine.edited

  • physicalMachine.deleted

  • racks.created

  • racks.edited

  • racks.deleted

  • virtualmachine.created

  • virtualMachine.edited

  • virtualMachine.deleted

  • scope.created

  • scope.edited

  • scope.deleted

  • role.created

  • role.edited

  • role.deleted

  • remoteServices.created

  • remoteServices.edited

  • remoteServices.deleted

  • networkServiceType.created

  • networkServiceType.edited

  • networkServiceType.deleted

  • networks.created

  • networks.edited

  • networks.deleted

  • publicip.created

  • publicip.edited

  • publicip.deleted

  • enterprise.created

  • enterprise.edited

  • enterprise.deleted

  • datacenter.created

  • datacenter.edited

  • datacenter.deleted

  • license.created

  • license.requested

How to find the element id/name

You can find an element's id or name using your browser. The following sections explain how to do this on Chrome and Firefox, but you can use another browser, inline UI analyzer or whatever software you want.

Chrome

First, open the clientUI in your browser and then press CTRL + ALT + i to open the Developer tools.

Image RemovedImage Added

Then click Elements tab, then the inspector icon and select the element that you want to find out the id/name of.

Image RemovedImage Added

In this example, you can see that the element has the id = vapp.vm-0 so you can use it as the element attribute.

Firefox

First, open the clienUI clientUI in your browser and then press F12 to open the Developer tools.

Image RemovedImage Added

Then click Inspector tab, then the  inspector icon and select the element you want to know its id/name

Image RemovedImage Added

In this example, you can see that the element has the id = vapp.vm-0 so you can use it as the element attribute.

...

To determine if this issue affects your system, you can open the browser JavaScript console and look for the following error message:

Uncaught TypeError: Cannot read property 'offsetWidth' of null

If you see this error, you can easily work around it by adding a delay attribute to the tutorial element step.

...

If the 'Next' button is not enabled and the error described above is shown, simply add delayBeforeNextItem attribute to the element, specifying a delay in milliseconds. For example:

Virtualdatacenter's element
Code Block
languagehtml/xml
        {
            "element": "#virtualdatacenters\\.tab",
            "intro": "In the <strong>Virtual datacenter</strong> section, you will manage all your virtual infrastructure. Let's begin by clicking this icon<br><br><span style='color: orange'><strong>Action needed:</strong></span><br><i>Click the <strong>'Virtual datacenters'</strong> icon to continue</i>",
            "position": "bottom",
            "actionType": "onclick",
            "blockPrevious": true,
			"delayBeforeNextItem": 1000
        },

This will be enough to resolve the issue.

It is up to you specify a suitable delay value depending on the screen and tutorial step, but it would be better to set higher delays than lower ones in order to avoid problems.