Skip to content

Commit 7610b53

Browse files
committed
feat: add tour for launch
adds tour close #323
1 parent 82a8d55 commit 7610b53

25 files changed

+625
-7
lines changed

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@
113113
"react-dom": "16.13.0",
114114
"react-i18next": "11.3.3",
115115
"react-immutable-proptypes": "2.1.0",
116+
"react-joyride": "2.2.1",
116117
"react-json-view": "1.19.1",
117118
"react-loading": "2.0.3",
118119
"react-quill": "1.3.3",

public/app/config/channels.js

+1
Original file line numberDiff line numberDiff line change
@@ -71,4 +71,5 @@ module.exports = {
7171
GET_SPACE_IN_CLASSROOM_CHANNEL: 'classroom:space:get',
7272
LOAD_SPACE_IN_CLASSROOM_CHANNEL: 'classroom:space:load',
7373
GET_SPACE_TO_LOAD_IN_CLASSROOM_CHANNEL: 'classroom:space:load:get-space',
74+
TOUR_COMPLETED_CHANNEL: 'tour:complete',
7475
};

public/app/config/config.js

+9
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
const { app } = require('electron');
33
const isWindows = require('../utils/isWindows');
44

5+
const tours = {
6+
VISIT_SPACE_TOUR: 'visitSpace',
7+
SETTINGS_TOUR: 'settings',
8+
};
9+
510
// types that we support downloading
611
const DOWNLOADABLE_MIME_TYPES = [
712
// video
@@ -68,6 +73,10 @@ const buildDefaultUser = (lang = DEFAULT_LANG) => ({
6873
},
6974
favoriteSpaces: [],
7075
recentSpaces: [],
76+
tour: {
77+
[tours.VISIT_SPACE_TOUR]: false,
78+
[tours.SETTINGS_TOUR]: false,
79+
},
7180
});
7281

7382
const ANONYMOUS_USERNAME = 'Anonymous';

public/app/listeners/completeTour.js

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const { TOUR_COMPLETED_CHANNEL } = require('../config/channels');
2+
const { ERROR_GENERAL } = require('../config/errors');
3+
const logger = require('../logger');
4+
5+
const completeTour = (mainWindow, db) => async (event, { tourName }) => {
6+
try {
7+
// update user in users collection
8+
db.get('user')
9+
.set(`tour.${tourName}`, true)
10+
.write();
11+
mainWindow.webContents.send(TOUR_COMPLETED_CHANNEL);
12+
} catch (e) {
13+
logger.error(e);
14+
mainWindow.webContents.send(TOUR_COMPLETED_CHANNEL, ERROR_GENERAL);
15+
}
16+
};
17+
18+
module.exports = completeTour;

public/app/listeners/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ const loadSpaceInClassroom = require('./loadSpaceInClassroom');
5050
const setActionAccessibility = require('./setActionAccessibility');
5151
const setActionsAsEnabled = require('./setActionsAsEnabled');
5252
const windowAllClosed = require('./windowAllClosed');
53+
const completeTour = require('./completeTour');
5354

5455
module.exports = {
5556
loadSpace,
@@ -103,4 +104,5 @@ module.exports = {
103104
setActionAccessibility,
104105
setActionsAsEnabled,
105106
windowAllClosed,
107+
completeTour,
106108
};

public/electron.js

+5
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ const {
7474
LOAD_SPACE_IN_CLASSROOM_CHANNEL,
7575
SET_ACTION_ACCESSIBILITY_CHANNEL,
7676
SET_ACTIONS_AS_ENABLED_CHANNEL,
77+
TOUR_COMPLETED_CHANNEL,
7778
} = require('./app/config/channels');
7879
const env = require('./env.json');
7980
const {
@@ -127,6 +128,7 @@ const {
127128
setActionAccessibility,
128129
setActionsAsEnabled,
129130
windowAllClosed,
131+
completeTour,
130132
} = require('./app/listeners');
131133
const isMac = require('./app/utils/isMac');
132134

@@ -600,6 +602,9 @@ app.on('ready', async () => {
600602

601603
// called when syncing a space
602604
ipcMain.on(SYNC_SPACE_CHANNEL, syncSpace(mainWindow, db));
605+
606+
// called when a tour is closed or completed
607+
ipcMain.on(TOUR_COMPLETED_CHANNEL, completeTour(mainWindow, db));
603608
});
604609

605610
app.on('window-all-closed', () => windowAllClosed(mainWindow));

src/App.js

+2
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ import {
5959
import './App.css';
6060
import SavedSpaces from './components/SavedSpaces';
6161
import ClassroomScreen from './components/classrooms/ClassroomScreen';
62+
import Tour from './components/common/Tour';
6263

6364
const styles = () => ({
6465
toastrIcon: { marginBottom: '-20px', fontSize: '45px' },
@@ -165,6 +166,7 @@ export class App extends Component {
165166
theme={connexionStatus ? OnlineTheme(userMode) : OfflineTheme}
166167
>
167168
<Router>
169+
<Tour />
168170
<div className="app" style={{ height }}>
169171
<Switch>
170172
<Route exact path={SIGN_IN_PATH} component={SignInScreen} />

src/__snapshots__/App.test.js.snap

+1
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,7 @@ exports[`<App /> renders correctly 1`] = `
295295
}
296296
>
297297
<HashRouter>
298+
<withRouter(withI18nextTranslation(Connect(Tour))) />
298299
<div
299300
className="app"
300301
style={

src/actions/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,4 @@ export * from './syncSpace';
1111
export * from './loadSpace';
1212
export * from './exportSpace';
1313
export * from './classroom';
14+
export * from './tour';

src/actions/tour.js

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { TOUR_COMPLETED_CHANNEL } from '../config/channels';
2+
import { ERROR_GENERAL } from '../config/errors';
3+
import {
4+
INITIALIZE_TOUR,
5+
NAVIGATE_STOP_TOUR,
6+
NEXT_OR_PREV_TOUR,
7+
RESET_TOUR,
8+
RESTART_TOUR,
9+
START_TOUR,
10+
STOP_TOUR,
11+
} from '../types/tour';
12+
13+
const nextStepTour = payload => dispatch =>
14+
dispatch({
15+
type: NEXT_OR_PREV_TOUR,
16+
payload,
17+
});
18+
19+
const navigateStopTour = payload => dispatch =>
20+
dispatch({
21+
type: NAVIGATE_STOP_TOUR,
22+
payload,
23+
});
24+
25+
const stopTour = () => dispatch =>
26+
dispatch({
27+
type: STOP_TOUR,
28+
});
29+
30+
const restartTour = () => dispatch =>
31+
dispatch({
32+
type: RESTART_TOUR,
33+
});
34+
35+
const startTour = () => dispatch =>
36+
dispatch({
37+
type: START_TOUR,
38+
});
39+
40+
const initializeTour = payload => dispatch =>
41+
dispatch({
42+
type: INITIALIZE_TOUR,
43+
payload,
44+
});
45+
46+
const resetTour = () => dispatch =>
47+
dispatch({
48+
type: RESET_TOUR,
49+
});
50+
51+
const completeTour = async tourName => dispatch => {
52+
try {
53+
dispatch({
54+
type: RESET_TOUR,
55+
});
56+
window.ipcRenderer.send(TOUR_COMPLETED_CHANNEL, { tourName });
57+
window.ipcRenderer.once(TOUR_COMPLETED_CHANNEL, async (event, error) => {
58+
if (error === ERROR_GENERAL) {
59+
console.error(error);
60+
}
61+
});
62+
} catch (e) {
63+
console.error(e);
64+
}
65+
};
66+
67+
export {
68+
stopTour,
69+
nextStepTour,
70+
restartTour,
71+
startTour,
72+
navigateStopTour,
73+
resetTour,
74+
completeTour,
75+
initializeTour,
76+
};

src/components/Settings.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,11 @@ import LanguageSelect from './common/LanguageSelect';
1212
import DeveloperSwitch from './common/DeveloperSwitch';
1313
import GeolocationControl from './common/GeolocationControl';
1414
import Main from './common/Main';
15-
import { SETTINGS_MAIN_ID, SETTINGS_TITLE_ID } from '../config/selectors';
15+
import {
16+
SETTINGS_ACTIONS_CLASS,
17+
SETTINGS_MAIN_ID,
18+
SETTINGS_TITLE_ID,
19+
} from '../config/selectors';
1620
import SyncAdvancedSwitch from './space/sync/SyncAdvancedSwitch';
1721
import StudentModeSwitch from './common/StudentModeSwitch';
1822
import ActionEnabledSwitch from './common/ActionEnabledSwitch';
@@ -58,7 +62,7 @@ export class Settings extends Component {
5862
<Typography variant="h5" color="inherit" className="mt-2">
5963
{t('Actions')}
6064
</Typography>
61-
<FormGroup>
65+
<FormGroup className={SETTINGS_ACTIONS_CLASS}>
6266
<ActionEnabledSwitch />
6367
<ActionAccessibilitySwitch />
6468
</FormGroup>

src/components/VisitSpace.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import {
2727
VISIT_BUTTON_ID,
2828
VISIT_INPUT_ID,
2929
VISIT_MAIN_ID,
30+
VISIT_SPACE_INPUT,
3031
} from '../config/selectors';
3132

3233
class VisitSpace extends Component {
@@ -118,7 +119,7 @@ class VisitSpace extends Component {
118119
</Typography>
119120
<Input
120121
id={VISIT_INPUT_ID}
121-
className={classes.input}
122+
className={classNames(classes.input, VISIT_SPACE_INPUT)}
122123
required
123124
onChange={this.handleChangeSpaceId}
124125
inputProps={{

src/components/__snapshots__/Settings.test.js.snap

+3-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ exports[`<Settings /> renders correctly 1`] = `
3636
>
3737
Actions
3838
</WithStyles(ForwardRef(Typography))>
39-
<WithStyles(ForwardRef(FormGroup))>
39+
<WithStyles(ForwardRef(FormGroup))
40+
className="SettingsActions"
41+
>
4042
<withI18nextTranslation(WithStyles(Connect(ActionEnabledSwitch))) />
4143
<withI18nextTranslation(WithStyles(Connect(ActionAccessibilitySwitch))) />
4244
</WithStyles(ForwardRef(FormGroup))>

0 commit comments

Comments
 (0)