Skip to content

Commit ad036c8

Browse files
committed
Created a new component for tutorial walkthrough for modularization
1 parent a11aec9 commit ad036c8

14 files changed

+264
-186
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@
137137
"@fortawesome/react-fontawesome": "^0.1.12",
138138
"@material-ui/core": "^4.11.2",
139139
"@types/react-dom": "^17.0.14",
140+
"@types/react-router-dom": "^5.3.3",
140141
"@visx/axis": "^1.0.0",
141142
"@visx/brush": "^1.2.0",
142143
"@visx/clip-path": "^1.0.0",

src/app/components/BarGraph.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,9 @@ const BarGraph = props => {
142142

143143
return (
144144
<div className="bargraph-position">
145-
<input type="text" id ="seriesname" placeholder="Series Name" />
145+
<div className="tools-container">
146+
<input type="text" id ="seriesname" placeholder="Series Name" />
147+
</div>
146148
<button
147149
type="button"
148150
className="save-series-button"

src/app/components/ComponentMap.tsx

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -166,28 +166,32 @@ export default function ComponentMap({
166166

167167
const formatState = state => {
168168
if (state === 'stateless') return ['stateless'];
169-
170-
const result = [];
171-
const inner = arg => {
172-
if (Array.isArray(arg)) {
173-
result.push('[');
174-
arg.forEach(e => { inner(e); });
175-
result.push('] ');
176-
} else if ((typeof arg) === 'object') {
177-
result.push('{ ');
178-
Object.keys(arg).forEach((key, i, arr) => {
179-
result.push(`${key}: `);
180-
((typeof arg[key]) === 'object') ? inner(arg[key]) : result.push(arg[key]);
181-
if (i !== arr.length - 1) result.push(', ');
182-
});
183-
result.push(' } ');
184-
} else {
185-
result.push(` ${arg}, `);
186-
}
187-
};
188-
inner(state);
169+
// Something in this code below is breaking the app,
170+
// when you hover over a stateful component on the map
171+
// --------------------------------------------------------------------------------------------
172+
// const result = [];
173+
// const inner = arg => {
174+
// if (Array.isArray(arg)) {
175+
// result.push('[');
176+
// arg.forEach(e => { inner(e); });
177+
// result.push('] ');
178+
// } else if ((typeof arg) === 'object') {
179+
// result.push('{ ');
180+
// Object.keys(arg).forEach((key, i, arr) => {
181+
// result.push(`${key}: `);
182+
// ((typeof arg[key]) === 'object') ? inner(arg[key]) : result.push(arg[key]);
183+
// if (i !== arr.length - 1) result.push(', ');
184+
// });
185+
// result.push(' } ');
186+
// } else {
187+
// result.push(` ${arg}, `);
188+
// }
189+
// };
190+
// inner(state);
189191

190-
return result;
192+
// return result;
193+
// --------------------------------------------------------------------------------------------
194+
return ['stateful'];
191195
};
192196

193197
// places all nodes into a flat array

src/app/components/History.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import React, { useEffect } from 'react';
44
// formatting findDiff return data to show the changes with colors, aligns with actions.tsx
55
import { diff, formatters } from 'jsondiffpatch';
66
import * as d3 from 'd3';
7+
78
import { changeView, changeSlider } from '../actions/actions';
89

910
const defaultMargin = {
@@ -34,6 +35,7 @@ function History(props: Record<string, unknown>): JSX.Element {
3435
makeD3Tree();
3536
}, [root, currLocation]);
3637

38+
3739
function labelCurrentNode(d3root) {
3840
if (d3root.data.index === currLocation.index) {
3941
let currNode = d3root;

src/app/components/PerformanceVisx.tsx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
11
// @ts-nocheck
2-
import React, { useState } from 'react';
2+
import React, { useState, useEffect } from 'react';
33
import FormControlLabel from '@material-ui/core/FormControlLabel';
44
import { ParentSize } from '@visx/responsive';
55
import {
66
MemoryRouter as Router,
77
Route,
88
NavLink,
99
Switch,
10+
useLocation,
1011
} from 'react-router-dom';
1112
import { Component } from 'react';
1213
import { render } from 'react-dom';
14+
import { Component } from 'react';
1315
import RenderingFrequency from './RenderingFrequency';
1416
// import Switch from '@material-ui/core/Switch';
1517
import BarGraph from './BarGraph';
1618
import BarGraphComparison from './BarGraphComparison';
1719
import { useStoreContext } from '../store';
1820
// import snapshots from './snapshots';
19-
import { Component } from 'react';
2021
/* NOTES
2122
Issue - Not fully compatible with recoil apps. Reference the recoil-todo-test.
2223
Barstacks display inconsistently...however, almost always displays upon initial test app load or
@@ -58,7 +59,7 @@ const collectNodes = (snaps, componentName) => {
5859
// componentsResult.splice(0, componentsResult.length); { /* We used the .splice method here to ensure that nodeList did not accumulate with page refreshes */ }
5960
// componentsResult.push(snaps);
6061
for (let x = 0; x < snaps.length; x++) {
61-
const snapshotList = []
62+
const snapshotList = [];
6263
snapshotList.push(snaps[x]);
6364
for (let i = 0; i < snapshotList.length; i++) {
6465
const cur = snapshotList[i];
@@ -67,15 +68,15 @@ const collectNodes = (snaps, componentName) => {
6768
break;
6869
}
6970
if (cur.children && cur.children.length > 0) {
70-
for (let child of cur.children) {
71+
for (const child of cur.children) {
7172
snapshotList.push(child);
7273
}
7374
}
7475
}
7576
}
76-
//console.log('componentsResult looks like: ', componentsResult);
77+
// console.log('componentsResult looks like: ', componentsResult);
7778
return componentsResult;
78-
}
79+
};
7980
/* DATA HANDLING HELPER FUNCTIONS */
8081
const traverse = (snapshot, data, snapshots, currTotalRender = 0) => {
8182
if (!snapshot.children[0]) return;
@@ -129,7 +130,7 @@ const traverse = (snapshot, data, snapshots, currTotalRender = 0) => {
129130
const allStorage = () => {
130131
// const values = [];
131132
// const keys = Object.keys(localStorage);
132-
let values = localStorage.getItem('project')
133+
let values = localStorage.getItem('project');
133134
// values === null ? values = [] : values = JSON.parse(values) ;
134135
values = values === null ? [] : JSON.parse(values);
135136
// let i = keys.length;
@@ -171,6 +172,7 @@ const getPerfMetrics = (snapshots, snapshotsIds): {} => {
171172
/* EXPORT COMPONENT */
172173
const PerformanceVisx = (props: BarStackProps) => {
173174
// hook used to dispatch onhover action in rect
175+
174176
const {
175177
width, height, snapshots, hierarchy,
176178
} = props;
@@ -201,7 +203,7 @@ const PerformanceVisx = (props: BarStackProps) => {
201203
};
202204

203205
const renderComponentDetailsView = () => {
204-
console.log('show me snapshots', snapshots)
206+
console.log('show me snapshots', snapshots);
205207
console.log('what is heirarchy', hierarchy);
206208
console.log('this is the info for rendering frequency', data.componentData);
207209
if (hierarchy) {

src/app/components/StateRoute.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@
55
/* eslint-disable @typescript-eslint/no-var-requires */
66
/* eslint-disable max-len */
77
/* eslint-disable object-curly-newline */
8-
import React, { useState } from 'react';
8+
import React, { useState, useEffect } from 'react';
99
import {
1010
MemoryRouter as Router,
1111
Route,
1212
NavLink,
1313
Switch,
14+
useLocation,
1415
} from 'react-router-dom';
1516
import { ParentSize } from '@visx/responsive';
1617
import Tree from './Tree';

src/app/components/Tutorial.tsx

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
// @ts-nocheck
2+
import * as React from 'react';
3+
import { useState, useEffect } from 'react';
4+
import { useLocation } from 'react-router-dom';
5+
import { Steps, Hints } from 'intro.js-react';
6+
import 'intro.js/introjs.css';
7+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
8+
import {
9+
faQuestion,
10+
} from '@fortawesome/free-solid-svg-icons';
11+
12+
export default function Tutorial(): JSX.Element {
13+
const [stepsEnabled, setStepsEnabled] = useState(false);
14+
const [initialStep, setInitialStep] = useState(0);
15+
const [steps, setSteps] = useState([
16+
{
17+
title: 'Reactime Tutorial',
18+
intro: 'A performance and state managment tool for React apps.',
19+
position: 'top',
20+
},
21+
{
22+
title: 'Actions',
23+
element: '.action-container',
24+
intro: "<ul><li>Reactime records a snapshot whenever a target application's state is changed</li></ul>",
25+
position: 'right',
26+
},
27+
{
28+
element: '.individual-action',
29+
title: 'Snapshot',
30+
intro: '<ul><li>Each snapshot allows the user to jump to any previously recorded state.</li> <li>It also detects the amount of renders of each component and average time of rendering</li></ul>.',
31+
position: 'right',
32+
},
33+
{
34+
title: 'Timejump',
35+
element: '.rc-slider',
36+
intro: '<ul><li>Use the slider to go back in time to a particular state change</li><li>Click the Play button to run through each state change automatically</li></ul>',
37+
position: 'top',
38+
},
39+
{
40+
title: 'Lock Button',
41+
element: '.pause-button',
42+
intro: '<ul><li>Use button to lock Reactime to the target application\'s tab in the Chrome Browser</li></ul>',
43+
position: 'top',
44+
},
45+
{
46+
title: 'Split Button',
47+
element: '.split-button',
48+
intro: '<ul> <li>Use button to split Reactime into two windows in order to view multiple tabs simultaneously</li> </ul>',
49+
position: 'top',
50+
},
51+
{
52+
title: 'Download Button',
53+
element: '.export-button',
54+
intro: '<ul><li>Use button to download a JSON file of all snapshots</li> </ul>',
55+
position: 'top',
56+
},
57+
{
58+
title: 'Upload Button',
59+
element: '.import-button',
60+
intro: '<ul><li>Use button to upload a previously downloaded JSON file for snapshot comparisons</li></ul>',
61+
position: 'top',
62+
},
63+
{
64+
element: '.map-tab',
65+
title: 'Map Tab',
66+
intro: '<ul><li>This tab visually displays a component hierarchy tree for your app</li></ul>',
67+
position: 'bottom',
68+
},
69+
{
70+
title: 'Performance Tab',
71+
element: '.performance-tab',
72+
intro: '<ul><li>User can save a series of state snapshots and use it to analyze changes in component, render performance between current, and previous series of snapshots.</li> <li>User can save a series of state snapshots and use it to analyze changes in component render performance between current and previous series of snapshots.</li></ul>',
73+
position: 'bottom',
74+
},
75+
{
76+
title: 'History Tab',
77+
element: '.history-tab',
78+
intro: '<ul><li>This tab visually displays a history of each snapshot</li></ul>',
79+
position: 'bottom',
80+
},
81+
{
82+
title: 'Web Metrics Tab',
83+
element: '.web-metrics-tab',
84+
intro: '<ul> <li>This tab visually displays performance metrics and allows the user to gauge efficiency of their application</li></ul>',
85+
position: 'bottom',
86+
},
87+
{
88+
title: 'Tree Tab',
89+
element: '.tree-tab',
90+
intro: '<ul><li>This tab visually displays a JSON Tree containing the different components and states</li></ul>',
91+
position: 'bottom',
92+
},
93+
{
94+
title: 'Tutorial Complete',
95+
intro: '<ul><li>Please visit our official Github Repo for more information </li><br> <li><a href="https://github.com/open-source-labs/reactime" target="_blank">Reactime Github</a></li></ul>',
96+
position: 'top',
97+
},
98+
]);
99+
100+
const onExit = () => {
101+
setStepsEnabled(false);
102+
};
103+
const startIntro = () => {
104+
setStepsEnabled(true);
105+
};
106+
107+
return (
108+
<>
109+
<Steps
110+
enabled={stepsEnabled}
111+
steps={steps}
112+
initialStep={initialStep}
113+
onExit={onExit}
114+
options={{
115+
tooltipClass: 'customTooltip',
116+
scrollToElement: false,
117+
showProgress: true,
118+
showStepNumbers: true,
119+
showBullets: false,
120+
exitOnOverlayClick: false,
121+
doneLabel: 'Done',
122+
nextLabel: 'Next',
123+
hideNext: false,
124+
skipLabel: 'Skip',
125+
keyboardNavigation: true,
126+
overlayOpacity: 0.65,
127+
}}
128+
/>
129+
130+
<button
131+
className="howToUse-button"
132+
type="button"
133+
onClick={() => startIntro()}
134+
>
135+
<FontAwesomeIcon icon={faQuestion} />
136+
{' '}
137+
How to use
138+
</button>
139+
</>
140+
141+
);
142+
}

src/app/containers/ActionContainer.tsx

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// @ts-nocheck
22
import React, { useEffect } from 'react';
3+
34
import Action from '../components/Action';
45
import SwitchAppDropdown from '../components/SwitchApp';
56
import { emptySnapshots, changeView, changeSlider } from '../actions/actions';
@@ -17,7 +18,9 @@ function ActionContainer(props): JSX.Element {
1718
const {
1819
currLocation, hierarchy, sliderIndex, viewIndex, snapshots,
1920
} = tabs[currentTab];
20-
const { toggleActionContainer, actionView, setActionView } = props;
21+
const {
22+
toggleActionContainer, actionView, setActionView
23+
} = props;
2124
let actionsArr = [];
2225
const hierarchyArr: any[] = [];
2326

@@ -55,9 +58,9 @@ function ActionContainer(props): JSX.Element {
5558
});
5659
}
5760
};
58-
// the hierarchy gets set on the first click in the page
59-
// when page in refreshed we may not have a hierarchy so we need to check if hierarchy was initialized
60-
// if true invoke displayArray to display the hierarchy
61+
// the hierarchy gets set on the first click in the page
62+
// when page in refreshed we may not have a hierarchy so we need to check if hierarchy was initialized
63+
// if true invoke displayArray to display the hierarchy
6164
if (hierarchy) displayArray(hierarchy);
6265

6366
// handles keyboard presses, function passes an event and index of each action-component
@@ -122,6 +125,13 @@ function ActionContainer(props): JSX.Element {
122125
setActionView(true);
123126
}, [setActionView]);
124127

128+
const toggleRecord = () => {
129+
port.postMessage({
130+
action: 'toggleRecord',
131+
});
132+
// change color of record button or switch svg/img file
133+
};
134+
125135
// the conditional logic below will cause ActionContainer.test.tsx to fail as it cannot find the Empty button
126136
// UNLESS actionView={true} is passed into <ActionContainer /> in the beforeEach() call in ActionContainer.test.tsx
127137
return (
@@ -132,6 +142,7 @@ function ActionContainer(props): JSX.Element {
132142
<i />
133143
</a>
134144
</aside>
145+
{/* <button className="recordBtn" onClick={toggleRecord}>Record</button> */}
135146
</div>
136147
{actionView ? (
137148
<div className="action-button-wrapper">

0 commit comments

Comments
 (0)