Skip to content

Commit ce73fa0

Browse files
committed
Merge remote-tracking branch 'upstream/develop' into fix/hot-reload
# Conflicts: # package-lock.json # package.json
2 parents c2b23e5 + 2da277c commit ce73fa0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+40605
-24501
lines changed

.eslintrc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"extends": ["airbnb", "prettier"],
2+
"extends": ["airbnb", "prettier", "plugin:storybook/recommended"],
33
"parser": "@babel/eslint-parser",
44
"env": {
55
"browser": true,

.storybook/main.js

+25-19
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,35 @@
1-
const path = require('path');
2-
3-
module.exports = {
1+
/** @type { import('@storybook/react-webpack5').StorybookConfig } */
2+
const config = {
43
stories: ['../client/**/*.stories.(jsx|mdx)'],
54
addons: [
6-
'@storybook/addon-actions',
7-
'@storybook/addon-docs',
8-
'@storybook/addon-knobs',
95
'@storybook/addon-links',
10-
'storybook-addon-theme-playground/dist/register'
6+
'@storybook/addon-essentials',
7+
'@storybook/addon-interactions'
118
],
12-
webpackFinal: async config => {
13-
// do mutation to the config
14-
15-
const rules = config.module.rules;
16-
17-
// modify storybook's file-loader rule to avoid conflicts with svgr
18-
const fileLoaderRule = rules.find(rule => rule.test.test('.svg'));
19-
fileLoaderRule.exclude = path.resolve(__dirname, '../client');
9+
framework: {
10+
name: '@storybook/react-webpack5',
11+
options: {}
12+
},
13+
docs: {
14+
autodocs: 'tag'
15+
},
16+
async webpackFinal(config) {
17+
// https://storybook.js.org/docs/react/builders/webpack
18+
// this modifies the existing image rule to exclude .svg files
19+
// since we want to handle those files with @svgr/webpack
20+
const imageRule = config.module.rules.find(rule => rule.test.test('.svg'))
21+
imageRule.exclude = /\.svg$/
2022

21-
// use svgr for svg files
22-
rules.push({
23+
// configure .svg files to be loaded with @svgr/webpack
24+
config.module.rules.push({
2325
test: /\.svg$/,
24-
use: ["@svgr/webpack"],
26+
use: ['@svgr/webpack']
2527
})
2628

27-
return config;
29+
return config
2830
},
2931
};
32+
33+
export default config;
34+
35+

.storybook/preview.js

+16-25
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,22 @@
11
import React from 'react';
2-
import { addDecorator, addParameters } from '@storybook/react';
3-
import { withKnobs } from "@storybook/addon-knobs";
4-
import { withThemePlayground } from 'storybook-addon-theme-playground';
5-
import { ThemeProvider } from "styled-components";
2+
import { Provider } from 'react-redux';
63

7-
import theme, { Theme } from '../client/theme';
4+
import ThemeProvider from '../client/modules/App/components/ThemeProvider';
5+
import configureStore from '../client/store';
6+
import '../client/i18n-test';
7+
import '../client/styles/build/css/main.css'
88

9-
addDecorator(withKnobs);
9+
const initialState = window.__INITIAL_STATE__;
1010

11-
const themeConfigs = Object.values(Theme).map(
12-
name => {
13-
return { name, theme: theme[name] };
14-
}
15-
);
11+
const store = configureStore(initialState);
1612

17-
addDecorator(withThemePlayground({
18-
theme: themeConfigs,
19-
provider: ThemeProvider
20-
}));
13+
export const decorators = [
14+
(Story) => (
15+
<Provider store={store}>
16+
<ThemeProvider>
17+
<Story />
18+
</ThemeProvider>
19+
</Provider>
20+
),
21+
]
2122

22-
addParameters({
23-
options: {
24-
/**
25-
* display the top-level grouping as a "root" in the sidebar
26-
*/
27-
showRoots: true,
28-
},
29-
})
30-
31-
// addDecorator(storyFn => <ThemeProvider theme={theme}>{storyFn()}</ThemeProvider>);

client/browserHistory.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { createBrowserHistory } from 'history';
2+
3+
const browserHistory = createBrowserHistory();
4+
5+
export default browserHistory;

client/common/Button.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React from 'react';
22
import PropTypes from 'prop-types';
33
import styled from 'styled-components';
4-
import { Link } from 'react-router';
4+
import { Link } from 'react-router-dom';
55

66
import { remSize, prop } from '../theme';
77

client/common/Button.stories.jsx

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
import React from 'react';
22
import { action } from '@storybook/addon-actions';
3-
import { boolean, text } from '@storybook/addon-knobs';
43

54
import Button from './Button';
65
import { GithubIcon, DropdownArrowIcon, PlusIcon } from './icons';
76

87
export default {
98
title: 'Common/Button',
10-
component: Button
9+
component: Button,
10+
args: {
11+
children: 'this is the button',
12+
label: 'submit',
13+
disabled: false
14+
}
1115
};
1216

13-
export const AllFeatures = () => (
14-
<Button
15-
disabled={boolean('disabled', false)}
16-
type="submit"
17-
label={text('label', 'submit')}
18-
>
19-
{text('children', 'this is the button')}
17+
export const AllFeatures = (args) => (
18+
<Button disabled={args.disabled} type="submit" label={args.label}>
19+
{args.children}
2020
</Button>
2121
);
2222

client/common/ButtonOrLink.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react';
2-
import { Link } from 'react-router';
2+
import { Link } from 'react-router-dom';
33
import PropTypes from 'prop-types';
44

55
/**

client/common/icons.stories.jsx

+10-6
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
import React from 'react';
2-
import { select } from '@storybook/addon-knobs';
32

43
import * as icons from './icons';
54

65
export default {
76
title: 'Common/Icons',
8-
component: icons
7+
component: icons,
8+
argTypes: {
9+
variant: {
10+
options: Object.keys(icons),
11+
control: { type: 'select' },
12+
default: icons.CircleFolderIcon
13+
}
14+
}
915
};
1016

11-
export const AllIcons = () => {
12-
const names = Object.keys(icons);
13-
14-
const SelectedIcon = icons[select('name', names, names[0])];
17+
export const Icons = (args) => {
18+
const SelectedIcon = icons[args.variant || 'CircleInfoIcon'];
1519
return <SelectedIcon />;
1620
};

client/components/Nav.jsx

+7-15
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
33
import React from 'react';
44
import { withTranslation } from 'react-i18next';
55
import { connect } from 'react-redux';
6-
import { Link, withRouter } from 'react-router';
6+
import { Link } from 'react-router-dom';
77
import { availableLanguages, languageKeyToLabel } from '../i18n';
88
import * as IDEActions from '../modules/IDE/actions/ide';
99
import * as toastActions from '../modules/IDE/actions/toast';
@@ -37,12 +37,12 @@ class Nav extends React.PureComponent {
3737
}
3838

3939
handleNew() {
40-
const { unsavedChanges, warnIfUnsavedChanges } = this.props;
40+
const { unsavedChanges } = this.props;
4141
if (!unsavedChanges) {
4242
this.props.showToast(1500);
4343
this.props.setToastText('Toast.OpenedNewSketch');
4444
this.props.newProject();
45-
} else if (warnIfUnsavedChanges && warnIfUnsavedChanges()) {
45+
} else if (window.confirm(this.props.t('Nav.WarningUnsavedChanges'))) {
4646
this.props.showToast(1500);
4747
this.props.setToastText('Toast.OpenedNewSketch');
4848
this.props.newProject();
@@ -73,11 +73,10 @@ class Nav extends React.PureComponent {
7373
}
7474

7575
handleShare() {
76-
const { username } = this.props.params;
7776
this.props.showShareModal(
7877
this.props.project.id,
7978
this.props.project.name,
80-
username
79+
this.props.project.owner.username
8180
);
8281
}
8382

@@ -351,14 +350,14 @@ Nav.propTypes = {
351350
id: PropTypes.string,
352351
name: PropTypes.string,
353352
owner: PropTypes.shape({
354-
id: PropTypes.string
353+
id: PropTypes.string,
354+
username: PropTypes.string
355355
})
356356
}),
357357
logoutUser: PropTypes.func.isRequired,
358358
showShareModal: PropTypes.func.isRequired,
359359
showErrorModal: PropTypes.func.isRequired,
360360
unsavedChanges: PropTypes.bool.isRequired,
361-
warnIfUnsavedChanges: PropTypes.func,
362361
showKeyboardShortcutModal: PropTypes.func.isRequired,
363362
cmController: PropTypes.shape({
364363
tidyCode: PropTypes.func,
@@ -374,9 +373,6 @@ Nav.propTypes = {
374373
rootFile: PropTypes.shape({
375374
id: PropTypes.string.isRequired
376375
}).isRequired,
377-
params: PropTypes.shape({
378-
username: PropTypes.string
379-
}),
380376
t: PropTypes.func.isRequired,
381377
setLanguage: PropTypes.func.isRequired,
382378
language: PropTypes.string.isRequired,
@@ -391,10 +387,6 @@ Nav.defaultProps = {
391387
},
392388
cmController: {},
393389
layout: 'project',
394-
warnIfUnsavedChanges: undefined,
395-
params: {
396-
username: undefined
397-
},
398390
editorLink: '/'
399391
};
400392

@@ -420,6 +412,6 @@ const mapDispatchToProps = {
420412
};
421413

422414
export default withTranslation()(
423-
withRouter(connect(mapStateToProps, mapDispatchToProps)(Nav))
415+
connect(mapStateToProps, mapDispatchToProps)(Nav)
424416
);
425417
export { Nav as NavComponent };

client/components/PreviewNav.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import PropTypes from 'prop-types';
22
import React from 'react';
3-
import { Link } from 'react-router';
3+
import { Link } from 'react-router-dom';
44
import { useTranslation } from 'react-i18next';
55

66
import LogoIcon from '../images/p5js-logo-small.svg';

client/components/__snapshots__/Nav.unit.test.jsx.snap

+10-3
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ exports[`Nav renders correctly 1`] = `
5757
<li
5858
class="nav__dropdown-item"
5959
>
60-
<a />
60+
<a
61+
href="/new-user/sketches"
62+
/>
6163
</li>
6264
</ul>
6365
</li>
@@ -195,7 +197,9 @@ exports[`Nav renders correctly 1`] = `
195197
<li
196198
class="nav__dropdown-item"
197199
>
198-
<a />
200+
<a
201+
href="/about"
202+
/>
199203
</li>
200204
</ul>
201205
</li>
@@ -229,6 +233,7 @@ exports[`Nav renders dashboard version 1`] = `
229233
>
230234
<a
231235
class="nav__back-link"
236+
href="/"
232237
>
233238
<test-file-stub
234239
aria-hidden="true"
@@ -447,7 +452,9 @@ exports[`Nav renders editor version 1`] = `
447452
<li
448453
class="nav__dropdown-item"
449454
>
450-
<a>
455+
<a
456+
href="/about"
457+
>
451458
About
452459
</a>
453460
</li>

client/components/createRedirectWithUsername.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react';
22
import { connect } from 'react-redux';
3-
import { browserHistory } from 'react-router';
3+
import browserHistory from '../browserHistory';
44

55
const RedirectToUser = ({ username, url = '/:username/sketches' }) => {
66
React.useEffect(() => {

client/components/mobile/Tab.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import styled from 'styled-components';
2-
import { Link } from 'react-router';
2+
import { Link } from 'react-router-dom';
33
import { prop, remSize } from '../../theme';
44

55
export default styled(Link)`

client/index.integration.test.jsx

+2-5
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
import { setupServer } from 'msw/node';
22
import { rest } from 'msw';
33
import React from 'react';
4-
import { Router, browserHistory } from 'react-router';
4+
import Routing from './routes';
55

66
import { reduxRender, act, waitFor, screen, within } from './test-utils';
77
import configureStore from './store';
8-
import routes from './routes';
98
import * as Actions from './modules/User/actions';
109
import { userResponse } from './testData/testServerResponses';
1110

1211
// setup for the app
13-
const history = browserHistory;
1412
const initialState = window.__INITIAL_STATE__;
1513
const store = configureStore(initialState);
1614

@@ -56,8 +54,7 @@ document.createRange = () => {
5654
// start testing
5755
describe('index.jsx integration', () => {
5856
// the subject under test
59-
const subject = () =>
60-
reduxRender(<Router history={history} routes={routes(store)} />, { store });
57+
const subject = () => reduxRender(<Routing />, { store });
6158

6259
// spy on this function and wait for it to be called before making assertions
6360
const spy = jest.spyOn(Actions, 'getUser');

client/index.jsx

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import React, { Suspense } from 'react';
22
import { render } from 'react-dom';
33
import { Provider } from 'react-redux';
4-
import { Router, browserHistory } from 'react-router';
4+
import { Router } from 'react-router-dom';
55

6+
import browserHistory from './browserHistory';
67
import configureStore from './store';
7-
import routes from './routes';
8+
import Routing from './routes';
89
import ThemeProvider from './modules/App/components/ThemeProvider';
910
import Loader from './modules/App/components/loader';
1011
import './i18n';
@@ -14,15 +15,16 @@ require('./styles/main.scss');
1415
// Load the p5 png logo, so that webpack will use it
1516
require('./images/p5js-square-logo.png');
1617

17-
const history = browserHistory;
1818
const initialState = window.__INITIAL_STATE__;
1919

2020
const store = configureStore(initialState);
2121

2222
const App = () => (
2323
<Provider store={store}>
2424
<ThemeProvider>
25-
<Router history={history} routes={routes(store)} />
25+
<Router history={browserHistory}>
26+
<Routing />
27+
</Router>
2628
</ThemeProvider>
2729
</Provider>
2830
);

0 commit comments

Comments
 (0)