Skip to content

Commit c3d290b

Browse files
authored
Merge branch 'develop' into fix/hover-style
2 parents 7826ba6 + 4a4f4d2 commit c3d290b

File tree

11 files changed

+40784
-24794
lines changed

11 files changed

+40784
-24794
lines changed

.eslintrc

Lines changed: 1 addition & 1 deletion
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

Lines changed: 25 additions & 19 deletions
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

Lines changed: 16 additions & 25 deletions
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/common/Button.stories.jsx

Lines changed: 9 additions & 9 deletions
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/icons.stories.jsx

Lines changed: 10 additions & 6 deletions
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/modules/IDE/components/ErrorModal.jsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,14 @@ const ErrorModal = ({ type, service, closeModal }) => {
6969
};
7070

7171
ErrorModal.propTypes = {
72-
type: PropTypes.string.isRequired,
72+
type: PropTypes.oneOf([
73+
'forceAuthentication',
74+
'staleSession',
75+
'staleProject',
76+
'oauthError'
77+
]).isRequired,
7378
closeModal: PropTypes.func.isRequired,
74-
service: PropTypes.string
79+
service: PropTypes.oneOf(['google', 'github'])
7580
};
7681

7782
ErrorModal.defaultProps = {
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import ErrorModal from './ErrorModal';
2+
3+
export default {
4+
title: 'IDE/ErrorModal',
5+
component: ErrorModal,
6+
argTypes: {
7+
closeModal: { action: 'closed' }
8+
}
9+
};
10+
11+
export const ForceAuthenticationErrorModal = {
12+
args: {
13+
type: 'forceAuthentication'
14+
}
15+
};
16+
export const StaleSessionErrorModal = {
17+
args: {
18+
type: 'staleSession'
19+
}
20+
};
21+
export const StaleProjectErrorModal = {
22+
args: {
23+
type: 'staleProject'
24+
}
25+
};
26+
export const OauthErrorModal = {
27+
args: {
28+
type: 'oauthError'
29+
}
30+
};
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import React from 'react';
2+
3+
import { render, screen } from '../../../test-utils';
4+
5+
import ErrorModal from './ErrorModal';
6+
7+
jest.mock('../../../i18n');
8+
9+
describe('<ErrorModal />', () => {
10+
it('renders type forceAuthentication', () => {
11+
render(<ErrorModal type="forceAuthentication" closeModal={jest.fn()} />);
12+
13+
expect(screen.getByText('Login')).toBeVisible();
14+
expect(screen.getByText('Sign Up')).toBeVisible();
15+
});
16+
17+
it('renders type staleSession', () => {
18+
render(<ErrorModal type="staleSession" closeModal={jest.fn()} />);
19+
20+
expect(screen.getByText('log in')).toBeVisible();
21+
});
22+
23+
it('renders type staleProject', () => {
24+
render(<ErrorModal type="staleProject" closeModal={jest.fn()} />);
25+
26+
expect(
27+
screen.getByText(
28+
'The project you have attempted to save has been saved from another window',
29+
{ exact: false }
30+
)
31+
).toBeVisible();
32+
});
33+
34+
it('renders type oauthError with service google', () => {
35+
render(
36+
<ErrorModal type="oauthError" service="google" closeModal={jest.fn()} />
37+
);
38+
39+
expect(
40+
screen.getByText('There was a problem linking your Google account', {
41+
exact: false
42+
})
43+
).toBeVisible();
44+
});
45+
46+
it('renders type oauthError with service github', () => {
47+
render(
48+
<ErrorModal type="oauthError" service="github" closeModal={jest.fn()} />
49+
);
50+
51+
expect(
52+
screen.getByText('There was a problem linking your GitHub account', {
53+
exact: false
54+
})
55+
).toBeVisible();
56+
});
57+
});

client/modules/IDE/components/SketchList.jsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,14 @@ import getSortedSketches from '../selectors/projects';
1818
import Loader from '../../App/components/loader';
1919
import Overlay from '../../App/components/Overlay';
2020
import AddToCollectionList from './AddToCollectionList';
21+
import getConfig from '../../../utils/getConfig';
2122

2223
import ArrowUpIcon from '../../../images/sort-arrow-up.svg';
2324
import ArrowDownIcon from '../../../images/sort-arrow-down.svg';
2425
import DownFilledTriangleIcon from '../../../images/down-filled-triangle.svg';
2526

27+
const ROOT_URL = getConfig('API_URL');
28+
2629
const formatDateCell = (date, mobile = false) =>
2730
dates.format(date, { showTime: !mobile });
2831

@@ -140,7 +143,13 @@ class SketchListRowBase extends React.Component {
140143
};
141144

142145
handleSketchDownload = () => {
143-
this.props.exportProjectAsZip(this.props.sketch.id);
146+
const { sketch } = this.props;
147+
const downloadLink = document.createElement('a');
148+
downloadLink.href = `${ROOT_URL}/projects/${sketch.id}/zip`;
149+
downloadLink.download = `${sketch.name}.zip`;
150+
document.body.appendChild(downloadLink);
151+
downloadLink.click();
152+
document.body.removeChild(downloadLink);
144153
};
145154

146155
handleSketchDuplicate = () => {
@@ -332,7 +341,6 @@ SketchListRowBase.propTypes = {
332341
deleteProject: PropTypes.func.isRequired,
333342
showShareModal: PropTypes.func.isRequired,
334343
cloneProject: PropTypes.func.isRequired,
335-
exportProjectAsZip: PropTypes.func.isRequired,
336344
changeProjectName: PropTypes.func.isRequired,
337345
onAddToCollection: PropTypes.func.isRequired,
338346
mobile: PropTypes.bool,

0 commit comments

Comments
 (0)