Skip to content

Commit

Permalink
📝 Add documentation for the onboarding system
Browse files Browse the repository at this point in the history
  • Loading branch information
emilijadunoska committed Sep 5, 2024
1 parent e2fb735 commit 5e40b73
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 6 deletions.
1 change: 1 addition & 0 deletions frontend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ libraries. Also try to learn and keep up with their best practices and guideline
- **React**: Efficient and robust user interface management.
- **Redux**: Efficient and robust state management.
- **Material UI**: Good looking user interface design and responsive layout.
- **React Joyride**: For the Onboarding tours. For a detailed documentation of the Onboarding system of ESID, refer to the [Onboarding documentation](docs/onboarding-tours-documentation.md)

## Guidelines

Expand Down
122 changes: 122 additions & 0 deletions frontend/docs/onboarding-tours-documentation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
<!--
SPDX-FileCopyrightText: 2024 German Aerospace Center (DLR)
SPDX-License-Identifier: CC-BY-4.0
-->

# Documentation for the Onboarding system of ESID

## Table of Contents

- [Introduction](#introduction)
- [Onboarding System Structure](#onboarding-system-structure)
- [Tour Structure](#tour-structure)
- [Adding a New Tour](#adding-a-new-tour)
- [Resources](#resources)

## Introduction

This documentation explains the structure of the Onboarding system and provides instructions on how to add new tours. The onboarding system is designed to guide new users through ESID's functionalities.

## Onboarding System Structure

The onboarding system consists of the following components:

- **Welcome Modal**: displays an overview of ESID through slides and illustrations on the user's first visit.
- **Onboarding Tours**: built using the React Joyride library. These tours can be accessed by clicking on the different tour chips in the information button in the top bar or from the last slide of the welcome modal. Currently, the onboarding system includes the following tours:
- District map
- Scenario
- Line chart
- Filters
- Parameters

## Tour Structure

The onboarding system uses a modular approach, where each tour is represented as a separate **chip**. This allows for interactive and feature-specific tours rather than a single, static tour.

Each tour consist of a series of steps, each associated with a specific UI element. Example of a tour object:

```
tours: {
districtMap: {
title: 'Map',
steps: {
step1: {
target: '#sidebar-root',
title: 'Step 1',
content: 'The map shows an overview of all rural and urban districts in Germany. You can select a different district by clicking on it and display case data for specific regions. ',
disableBeacon: true,
spotlightClicks: true,
showProgress: true,
placement: 'right-start',
},
step2: {
target: '#sidebar-root',
title: 'Step 2',
content: 'To get a more detailed overview, you can zoom in or out of the map using the plus or minus symbol or the mouse wheel. You can reset the map to its default view using the "Reset" button.',
disableBeacon: true,
spotlightClicks: true,
showProgress: true,
placement: 'right',
},
...
}
}
}
```

## Adding a New Tour

This section explains how to add a new tour.

### 1. Update Tour Types

In `types/tours.ts`, add the new tour type to the `TourType` union. Example:

```typescript
export type TourType = 'districtMap' | 'scenario' | 'lineChart' | 'filter' | 'parameters' | 'newTour';
```

### 2. Define the Tour steps

Tour content is managed through localization files. To add a new tour:

- Open the localization files: `en-onboarding.json5` and `de-onboarding.json5`
- Add the new tour data to the tours object in both files.

Translations must be done manually for each language in each file.

### 3. Add tour data to the Redux store

Update the `UserOnboardingSlice` to include the new tour data.

### 4. Update the Tour Chips List

Modify the `TourChipList.tsx` component to include the new tour.

### 5. Implement Necessary Logic in Tour Steps

The `TourSteps.tsx` file contains the core logic for managing tour steps and executing tours.

- For interactive tours that require manual control of the step index (known as Joyride controlled tours), use `useEffect` hooks to manage the step index.

Make sure to add or update comments in `TourSteps.tsx` to document the new tour’s functionality and integration. Documented code will help future developers in understanding the implementation.

For more details on implementing tours with Joyride, refer to the [Joyride documentation](https://docs.react-joyride.com) and check out this [CodeSandbox example](https://codesandbox.io/p/devbox/rough-currying-c0xm7q?file=%2Fsrc%2FControlled%2Findex.tsx%3A48%2C43) for a practical demonstration.

### 6. Test the New Tour

To make sure that the new tour functions correctly:

1. Add the `debug` prop to the Joyride component to view detailed logs and inspect the behavior of the tour.
2. Test the tour to confirm that all steps are displayed properly and the tour progresses as expected.

Note: Unit tests for Joyride tours are currently not implemented, so thorough manual testing is essential.

### 7. Update the Documentation

Once you've added a new tour or made other significant changes, make sure to update this documentation so it stays up to date.

# Resources

- [React Joyride](https://docs.react-joyride.com)
- [CodeSandbox example](https://codesandbox.io/p/devbox/rough-currying-c0xm7q?file=%2Fsrc%2FControlled%2Findex.tsx%3A48%2C43)
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import IconButton from '@mui/material/IconButton';
import Typography from '@mui/material/Typography';
import CloseIcon from '@mui/icons-material/Close';
import {useTranslation} from 'react-i18next';
import TourChips from './TourComponents/TourChipsList';
import TourChipsList from './TourComponents/TourChipsList';
import LinearProgress from '@mui/material/LinearProgress';

interface TopBarPopoverProps {
Expand Down Expand Up @@ -81,7 +81,7 @@ export default function TopBarPopover(props: TopBarPopoverProps): JSX.Element {
<CloseIcon data-testid='close-info-button' />
</IconButton>
<Box mt={4}>
<TourChips />
<TourChipsList />
</Box>
<Box mt={4}>
<LinearProgress
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ interface State {
}

/**
* This component manages the joyride onboarding tour steps.
* To see debug messages in the console, set the debug flag to true in the joyride component below.
* This component contains the core logic for managing tour steps and executing tours using the Joyride library.
* To see debug messages in the console, set the debug flag to true in the joyride component props below.
*/
export default function TourSteps(): JSX.Element {
const [state, setState] = useState<State>({
Expand All @@ -49,7 +49,7 @@ export default function TourSteps(): JSX.Element {
const scenarioList = useAppSelector((state) => state.scenarioList.scenarios);

const previousSimulationStart = useRef(simulationStart); // To keep track of the previous simulation start date for the scenario controlled tour.
const savedUserDataSelection = useRef<null | DataSelection>(null); // To keep track of the original data selection before starting the tour.
const savedUserDataSelection = useRef<null | DataSelection>(null); // To keep track of the original data selection before starting any tour.

/**
* This useMemo gets the localized tour steps and returns them as an array of step objects to use in the Joyride component.
Expand Down Expand Up @@ -167,7 +167,7 @@ export default function TourSteps(): JSX.Element {
dispatch(selectScenario(savedUserDataSelection.current?.scenario || 0)); // Restore the original selected scenario in the data selection
savedUserDataSelection.current = null; // Reset the saved preferences after the tour is completed

// If the tour was finished and not skipped, mark as completed
// If the tour was finished and not skipped or closed, mark as completed
if (status === STATUS.FINISHED && activeTour) {
dispatch(setTourCompleted({tour: activeTour, completed: true}));
}
Expand Down

0 comments on commit 5e40b73

Please sign in to comment.