Skip to content

Building a Lesson

Adam Hooper edited this page Sep 1, 2020 · 22 revisions

Lesson format

Lessons are written in a restricted HTML format. Each is a series of "sections" each of which can have a sequence of "steps." Each step can highlight some element on the page to indicate to the user what to do, and must provide a small JavaScript function that tests whether the user has completed the step.

Lesson html files are stored in /server/lessons The file /server/lessons/my_lesson.html is accessible as /lessons/my_lesson on the app. Anything in the /server/lessons/hidden folder is accessible (without hidden in the URL) but not displayed on the lesson index page. Each directory in /server/courses/ defines a series of lessons grouped together into a "course" and these are available as e.g. /courses/intro-to-data-journalism/charts-intro

When a user first navigates to my_lesson it will create a new workflow and set it to the initial state. When the user visits the same lesson URL thereafter they will see this workflow in whatever state it was left in.

Lesson Structure

Minimally, each lesson must have a <header>, which is the introduction page, and a <footer> which is the conclusion page. This is the simplest valid lesson html:

<header>
  <h1>Your first lesson!</h1>
  <p>Here's what you will learn</p>
</header>

<footer>
  <h2>You're done!</h2>
  <p>Thanks for playing.</p>
</footer>

You will probably also want some pages in between which guide the user through specific steps. This is accomplished by adding one or more <section> elements between the <header> and <footer>. Each section must have an <h2> tag specifying the section title. Optionally, use <ol class="steps"> to specify the individual steps that the user will perform within each section. There are various other classes available for formatting, such as instructions and instruction-detail.

<section>
  <h2>Averages</h2>
  <p>
    One of the first things you can do with data is describe or summarize it. The average is one way of computing a "typical" value.
  </p>

  <h3 class="instructions">Do these things now:</h3>

  <ol class="steps">
    <li>
      Click <kbd>Add Step</kbd> and type <kbd>Calculate</kbd> into the search box.
    </li>
    <li>
      Set the operation to <kbd>Average</kbd>
      <p class="instruction-detail">Click the orange "play" button to apply each edit.</p>
    </li>
    <li>
      Select columns 2012 to 2016
    </li>
  </ol>
</section>

Highlights

The optional data-highlight attribute on the step <li> element defines an element of the UI to highlight to show the user what to do.

  <li data-highlight='[{"type":"Module","index":1,"name":"Calculate"}]'>
    Click <kbd>Add Step</kbd> and type <kbd>Calculate</kbd> into the search box.
  </li>

data-highlight currently supports the following types of highlights:

  • Module highlights the Add Module button (either at the end of the stack or at the optional index) and also highlights the name of the module in the menu.
  • WfModule highlights a previously applied module, indexed by name or number
  • WfModuleContextButton allows highlighting of the notes or collapsed button.

See LessonHighlight.js for details/implementation.

Tests

The data-test attribute on the step <li> element defines a small JavaScript function that determines whether the user has completed the step. It should test the state of the workflow. For example, to check whether the user has added a module,

  <li data-test="return workflow.tabs[0].wfModuleSlugs[1] === 'calculate'">
    Click <kbd>Add Step</kbd> and type <kbd>Calculate</kbd> into the search box.
  </li>

This checks if the second module on the first tab has a slug (id_name) of calculate. To check whether a parameter has a particular value,

  <li  data-test="return workflow.tabs[0].wfModules[1].params.colnames==='Continent'">
    Select the "Continent" column.
  </li>

For the structure of the workflow object, see DoneHelpers.js

If data-test is omitted, the user will not be able to "complete" the section, meaning all step checkmarks appear and the next button highlights.

Initial Workflow

It's often helpful to have a lesson start with some modules loaded. This is accomplished by adding a script element to the lesson HTML with a JSON- or YAML-formatted workflow description:

<script id="initialWorkflow">
tabs:
- name: Lesson
  wfModules:
  - module: loadurl
    params:
      url: './file.csv'
    collapse: true
    note: 'This step is the best one'
</script>

You can define any number of modules (specified by their slug/id_name) on any number of tabs, and their initial parameters. The collapse and note fields are optional, but can really help clarify the workflow for users. Any module which does a fetch will be automatically fetched when the lesson first opens.

Module development process

1. Write lesson copy

Leave the data-test attributes all-empty.

Verify with outside people: does this lesson make sense? Iterate on it. Incorporate their feedback. When are we done?

Get the slug right. We cannot edit it later.

2. Write the data-test attributes

We know we are done when:

  • The dev can finish the lesson from scratch.
  • Data files are in directories named after the lesson slug. (e.g., courses/my-course/my-lesson/data.csv)
  • After finishing the lesson from scratch, there are no errors in the Chrome console.
  • The dev is confident there is no way the data-test attributes will produce errors in the Chrome console.
  • Zero data-test attributes include JSON.parse(). (If they do, fix the module with migrate_params(): https://www.pivotaltracker.com/story/show/163134383)
  • Zero data-test attributes test for menu/radio params with integer values. (If they do, fix the module with a migrate_params(): https://www.pivotaltracker.com/story/show/164280455)
  • Zero data-test attributes assign global variables. If there's an x = ..., it must start with const x = ....

Pivotal: mark as Finished.

3. Edit for HTML, grammar and style

Get one of us (not the author) to grammar-check. Best is to once-over, then pair with the original author to commit all changes together.

  • Check the slug agrees with other lessons' slugs (e.g., no "the-")
  • Check that all links are descriptive nouns. Tips for good link text
  • Check that sentences are concise. Use active voice, nix adjectives, nix redundancies, etc. Tips for writing concisely
  • Check that HTML does not have spaces after opening tags or before closing tags (e.g., <a href="blah"> NO </a>)
  • Check that HTML does not use any invalid class names
  • Check that HTML does not use any invalid attributes (e.g., className)
  • Check that HTML does not use any <br> tags
  • Check that every HTML <img>; has an alt= attribute
  • Check that every HTML & (in the JavaScript) is written, &amp;
  • Check that every HTML image loads

4. Test "as a user"

Someone else with Workbench runs through the entire lesson.

Checklist:

  • Is the slug correct?
  • Are the links to data sources correct in the instructions?
  • Are the links to data sources correct in the lesson pre-loaded data?
  • Can the user find instructions for how to generate the load-data URL? (e.g., link to API documentation)
  • Are data sets in any tabs (there may be more than one) loading?
  • Can we complete the lesson? Are required Workbench features missing?
  • Does any step get finished too "early"?
  • Is the Console error-free in (Chrome/Firefox Developer Tools)?

Pivotal: Accept. If there are errors, Reject.