Unverified Commit a254a23c authored by Andrey Azov's avatar Andrey Azov Committed by GitHub
Browse files

Update dependencies (#488)

Major updates:
- React from v 16 to v 17
- react-spring from v 8 to v 9
- husky to 6.0.0
- faker (one major version bump)
- eslint-config-prettier

Temporarily added dependency on dotenv-webpack (latest version) to prevent Storybook from crashing.
parent 129dd934
Pipeline #150971 passed with stages
in 5 minutes and 40 seconds
......@@ -3,7 +3,6 @@ module.exports = {
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:react/recommended',
'prettier/@typescript-eslint', // Uses eslint-config-prettier to disable rules that conflict with prettier
'plugin:prettier/recommended' // Displays prettier errors as ESLint errors. This has to be the last in this array (not yet sure why).
],
plugins: ['react-hooks'],
......
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
cd src/ensembl
npx --no-install lint-staged --config .lintstagedrc.json
{
"*.{ts,tsx}": [
"eslint --max-warnings=0",
"manage-licence-header add",
"prettier --write"
],
"*.{scss}": [
"stylelint",
"prettier --write"
]
}
This diff is collapsed.
......@@ -13,6 +13,7 @@
"author": "EMBL-EBI",
"license": "MIT",
"scripts": {
"prepare": "cd ../.. && husky install src/ensembl/.husky",
"copy-dotenv": "test ! -f .env && (cp .env.example .env; echo '.env file created') || true",
"start": "npm install --no-save && npm run serve:dev",
"serve:dev": "npm run copy-dotenv && webpack serve --config ./webpack/webpack.config.js --env dev",
......@@ -31,140 +32,125 @@
"test:watch": "jest --watch",
"coverage": "jest --coverage"
},
"lint-staged": {
"*.{ts,tsx}": [
"eslint --max-warnings=0",
"manage-licence-header add",
"prettier --write"
],
"*.{scss}": [
"stylelint",
"prettier --write"
]
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"dependencies": {
"@apollo/client": "3.2.3",
"@reduxjs/toolkit": "1.4.0",
"@sentry/browser": "5.25.0",
"classnames": "2.2.6",
"@apollo/client": "3.3.15",
"@reduxjs/toolkit": "1.5.1",
"@sentry/browser": "6.3.0",
"classnames": "2.3.1",
"comlink": "4.3.0",
"connected-react-router": "6.8.0",
"core-js": "3.6.5",
"d3": "6.2.0",
"connected-react-router": "6.9.1",
"core-js": "3.11.0",
"d3": "6.7.0",
"dotenv": "8.2.0",
"ensembl-genome-browser": "https://raw.githubusercontent.com/Ensembl/ensembl-genome-browser-assets/master/assets-80f51620ed443c640cdfd6b5aebd505b.tar.gz",
"graphql": "15.3.0",
"lodash": "4.17.20",
"query-string": "6.13.5",
"react": "16.14.0",
"graphql": "15.5.0",
"lodash": "4.17.21",
"query-string": "7.0.0",
"react": "17.0.2",
"react-cookie": "4.0.3",
"react-dom": "16.13.1",
"react-ga": "3.1.2",
"react-redux": "7.2.1",
"react-dom": "17.0.2",
"react-ga": "3.3.0",
"react-redux": "7.2.3",
"react-router": "5.2.0",
"react-router-dom": "5.2.0",
"react-spring": "8.0.27",
"react-spring": "9.1.2",
"redux": "4.0.5",
"redux-observable": "1.2.0",
"rxjs": "6.6.3",
"rxjs": "6.6.7",
"typesafe-actions": "5.1.0",
"what-input": "5.2.10"
},
"devDependencies": {
"@babel/core": "7.13.8",
"@babel/core": "7.13.16",
"@babel/plugin-proposal-class-properties": "7.13.0",
"@babel/plugin-proposal-nullish-coalescing-operator": "7.13.8",
"@babel/plugin-proposal-object-rest-spread": "7.13.8",
"@babel/plugin-proposal-optional-chaining": "7.13.8",
"@babel/plugin-proposal-optional-chaining": "7.13.12",
"@babel/plugin-syntax-dynamic-import": "7.8.3",
"@babel/plugin-transform-modules-commonjs": "7.13.8",
"@babel/preset-env": "7.13.9",
"@babel/preset-react": "7.12.13",
"@babel/preset-env": "7.13.15",
"@babel/preset-react": "7.13.13",
"@babel/preset-typescript": "7.13.0",
"@storybook/addon-essentials": "6.2.0-rc.8",
"@storybook/addons": "6.2.0-rc.8",
"@storybook/builder-webpack5": "6.2.0-rc.8",
"@storybook/react": "6.2.0-rc.8",
"@storybook/theming": "6.2.0-rc.8",
"@storybook/addon-essentials": "6.2.8",
"@storybook/addons": "6.2.8",
"@storybook/builder-webpack5": "6.2.8",
"@storybook/react": "6.2.8",
"@storybook/theming": "6.2.8",
"@svgr/webpack": "5.5.0",
"@testing-library/jest-dom": "5.11.6",
"@testing-library/react": "11.2.2",
"@testing-library/user-event": "12.2.2",
"@types/classnames": "2.2.10",
"@types/d3": "5.16.3",
"@types/faker": "5.1.2",
"@types/jest": "26.0.14",
"@types/lodash": "4.14.162",
"@types/node": "14.11.8",
"@types/prettier": "2.1.2",
"@types/react": "16.9.52",
"@types/react-dom": "16.9.8",
"@types/react-redux": "7.1.9",
"@types/react-router-dom": "5.1.6",
"@testing-library/jest-dom": "5.12.0",
"@testing-library/react": "11.2.6",
"@testing-library/user-event": "13.1.5",
"@types/classnames": "2.3.1",
"@types/d3": "6.3.0",
"@types/faker": "5.5.3",
"@types/jest": "26.0.22",
"@types/lodash": "4.14.168",
"@types/node": "14.14.41",
"@types/prettier": "2.2.3",
"@types/react": "17.0.3",
"@types/react-dom": "17.0.3",
"@types/react-redux": "7.1.16",
"@types/react-router-dom": "5.1.7",
"@types/react-router-hash-link": "1.2.1",
"@types/redux-mock-store": "1.0.2",
"@types/webpack-env": "1.16.0",
"@typescript-eslint/eslint-plugin": "4.16.1",
"@typescript-eslint/parser": "4.16.1",
"@typescript-eslint/eslint-plugin": "4.22.0",
"@typescript-eslint/parser": "4.22.0",
"babel-core": "7.0.0-bridge.0",
"babel-jest": "26.6.3",
"babel-loader": "8.2.2",
"babel-plugin-react-remove-properties": "0.3.0",
"compression-webpack-plugin": "7.1.2",
"connect-history-api-fallback": "1.6.0",
"copy-webpack-plugin": "8.1.0",
"css-loader": "5.1.4",
"css-minimizer-webpack-plugin": "1.3.0",
"eslint": "7.11.0",
"eslint-config-prettier": "6.12.0",
"eslint-plugin-prettier": "3.1.4",
"eslint-plugin-react": "7.21.4",
"eslint-plugin-react-hooks": "4.1.2",
"faker": "5.4.0",
"copy-webpack-plugin": "8.1.1",
"css-loader": "5.2.4",
"css-minimizer-webpack-plugin": "2.0.0",
"dotenv-webpack": "7.0.2",
"eslint": "7.24.0",
"eslint-config-prettier": "8.2.0",
"eslint-plugin-prettier": "3.4.0",
"eslint-plugin-react": "7.23.2",
"eslint-plugin-react-hooks": "4.2.0",
"faker": "5.5.3",
"file-loader": "6.2.0",
"fork-ts-checker-webpack-plugin": "6.2.0",
"fork-ts-checker-webpack-plugin": "6.2.4",
"gh-pages": "3.1.0",
"html-webpack-plugin": "5.3.1",
"husky": "4.3.0",
"husky": "6.0.0",
"identity-obj-proxy": "3.0.0",
"image-webpack-loader": "7.0.1",
"jest": "26.5.3",
"jest": "26.6.3",
"jest-fetch-mock": "3.0.3",
"jest-transform-stub": "2.0.0",
"koa": "2.13.0",
"koa": "2.13.1",
"koa-connect": "2.1.0",
"koa-proxy": "1.0.0-alpha.3",
"koa-static": "5.0.0",
"licence-manager": "git+https://github.com/Ensembl/ensembl-licence-manager.git#36b534d28ff26d345b4ba4da0cbc18e1e0f7a6b7",
"lint-staged": "10.4.0",
"mini-css-extract-plugin": "1.3.9",
"lint-staged": "10.5.4",
"mini-css-extract-plugin": "1.5.0",
"node-sass": "5.0.0",
"postcss": "8.2.8",
"postcss": "8.2.12",
"postcss-loader": "5.2.0",
"postcss-preset-env": "6.7.0",
"prettier": "2.1.2",
"prettier": "2.2.1",
"redux-mock-store": "1.5.4",
"rimraf": "3.0.2",
"sass-loader": "11.0.1",
"source-map-loader": "2.0.1",
"style-loader": "2.0.0",
"stylelint": "13.7.2",
"stylelint": "13.12.0",
"stylelint-config-recommended-scss": "4.2.0",
"stylelint-scss": "3.18.0",
"stylelint-scss": "3.19.0",
"stylelint-webpack-plugin": "2.1.1",
"ts-multipick": "1.0.0",
"typescript": "4.0.3",
"webpack": "5.28.0",
"webpack-bundle-analyzer": "4.4.0",
"webpack-cli": "4.5.0",
"webpack-dev-server": "3.11.2",
"typescript": "4.2.4",
"webpack": "5.35.0",
"webpack-bundle-analyzer": "4.4.1",
"webpack-cli": "4.6.0",
"webpack-dev-server": "4.0.0-beta.2",
"webpack-merge": "5.7.3",
"workbox-webpack-plugin": "6.1.2",
"workbox-webpack-plugin": "6.1.5",
"worker-loader": "3.0.8"
},
"browserslist": [
......
......@@ -37,7 +37,17 @@ const BrowserCog = (props: BrowserCogProps) => {
const toggleCog = useCallback(() => {
if (cogActivated === false) {
updateSelectedCog(trackId);
// Wrapping updateSelectedCog in a setTimeout below is a cheap workaround for the way we currently keep track
// of which BrowserTrackConfig is open.
// Imagine a user clicks on one cog (to open one BrowserTrackConfig), and then clicks on another cog.
// This will trigger two events that we are tracking: 1) click on a new cog; 2) click outside the opened BrowserTrackConfig.
// Using the setTimeout to bump the execution of updateSelectedCog to the end of the queue,
// we allow the time for the click outside the opened BrowserTrackConfig to get registered and for the component to get closed
// before dispatching the action that will open the BrowserTrackConfig for the newly clicked cog.
// (In the future, we should probably review how the state of the cogs is maintained. Does it even need to be in redux?)
setTimeout(() => {
updateSelectedCog(trackId);
}, 0);
analyticsTracking.trackEvent({
category: 'track_settings',
......@@ -73,7 +83,7 @@ const BrowserCog = (props: BrowserCogProps) => {
setTrackConfigAnimation(false);
}, [cogActivated]);
const transitions = useTransition(showTrackConfig, null, {
const transition = useTransition(showTrackConfig, {
config: { duration: 100 },
enter: { opacity: 1 },
from: { opacity: 0 },
......@@ -90,10 +100,10 @@ const BrowserCog = (props: BrowserCogProps) => {
image={cogIconConfig.icon}
/>
</div>
{transitions.map(({ item, key, props: style }) => {
{transition((style, item) => {
return (
item && (
<animated.div key={key} style={style}>
<animated.div key="browserTrackConfig" style={style}>
<BrowserTrackConfig
onClose={() => props.updateSelectedCog(null)}
/>
......
......@@ -32,7 +32,7 @@ describe('<BrowserCogList />', () => {
const defaultProps = {
browserActivated: true,
browserCogList: 0,
browserCogTrackList: { 'track:gc': faker.random.number() },
browserCogTrackList: { 'track:gc': faker.datatype.number() },
trackConfigNames: {},
trackConfigLabel: {},
selectedCog: faker.lorem.words(),
......
......@@ -26,9 +26,9 @@ import { BrowserLocationIndicator } from './BrowserLocationIndicator';
import { ChrLocation } from '../browserState';
const chrName = faker.lorem.word();
const startPosition = faker.random.number({ min: 1, max: 1000000 });
const startPosition = faker.datatype.number({ min: 1, max: 1000000 });
const endPosition =
startPosition + faker.random.number({ min: 1000, max: 1000000 });
startPosition + faker.datatype.number({ min: 1000, max: 1000000 });
const props = {
location: [chrName, startPosition, endPosition] as ChrLocation,
......
......@@ -39,12 +39,12 @@ jest.mock('src/shared/components/overlay/Overlay', () => () => (
));
const browserNavIconStates: BrowserNavIconStates = {
[BrowserNavAction.NAVIGATE_UP]: faker.random.boolean(),
[BrowserNavAction.NAVIGATE_RIGHT]: faker.random.boolean(),
[BrowserNavAction.NAVIGATE_DOWN]: faker.random.boolean(),
[BrowserNavAction.NAVIGATE_LEFT]: faker.random.boolean(),
[BrowserNavAction.ZOOM_OUT]: faker.random.boolean(),
[BrowserNavAction.ZOOM_IN]: faker.random.boolean()
[BrowserNavAction.NAVIGATE_UP]: faker.datatype.boolean(),
[BrowserNavAction.NAVIGATE_RIGHT]: faker.datatype.boolean(),
[BrowserNavAction.NAVIGATE_DOWN]: faker.datatype.boolean(),
[BrowserNavAction.NAVIGATE_LEFT]: faker.datatype.boolean(),
[BrowserNavAction.ZOOM_OUT]: faker.datatype.boolean(),
[BrowserNavAction.ZOOM_IN]: faker.datatype.boolean()
};
describe('BrowserNavBarControls', () => {
......
......@@ -97,8 +97,10 @@ describe('<BrowserRegionEditor />', () => {
it('validates region input on submit', () => {
const [stick] = initialChrLocation;
const locationStartInput = getCommaSeparatedNumber(faker.random.number());
const locationEndInput = getCommaSeparatedNumber(faker.random.number());
const locationStartInput = getCommaSeparatedNumber(
faker.datatype.number()
);
const locationEndInput = getCommaSeparatedNumber(faker.datatype.number());
const { container } = render(<BrowserRegionEditor {...defaultProps} />);
const [firstInput, secondInput] = container.querySelectorAll('input');
......@@ -129,8 +131,10 @@ describe('<BrowserRegionEditor />', () => {
jest.restoreAllMocks();
});
const locationStartInput = getCommaSeparatedNumber(faker.random.number());
const locationEndInput = getCommaSeparatedNumber(faker.random.number());
const locationStartInput = getCommaSeparatedNumber(
faker.datatype.number()
);
const locationEndInput = getCommaSeparatedNumber(faker.datatype.number());
const startError = 'start error message';
const endError = 'end error message';
const mockValidationMessages = createRegionValidationMessages();
......@@ -208,8 +212,10 @@ describe('<BrowserRegionEditor />', () => {
});
describe('on validation success', () => {
const locationStartInput = getCommaSeparatedNumber(faker.random.number());
const locationEndInput = getCommaSeparatedNumber(faker.random.number());
const locationStartInput = getCommaSeparatedNumber(
faker.datatype.number()
);
const locationEndInput = getCommaSeparatedNumber(faker.datatype.number());
const regionId = faker.lorem.words();
beforeEach(() => {
......
......@@ -66,7 +66,7 @@ describe('browserHelper', () => {
error_code: null,
error_message: startError,
is_valid: false,
value: faker.random.number()
value: faker.datatype.number()
}
};
const invalidEndInfo: Partial<RegionValidationResponse> = {
......@@ -74,7 +74,7 @@ describe('browserHelper', () => {
error_code: null,
error_message: endError,
is_valid: false,
value: faker.random.number()
value: faker.datatype.number()
}
};
const mockValidationMessages = createRegionValidationMessages(); // all error messages are null by default
......
......@@ -46,7 +46,7 @@ const regionObjectId = `${genomeId}:region:${region}`;
const createRandomPreviouslyViewedObject = (): PreviouslyViewedObject => ({
genome_id: faker.random.word(),
object_id: `${faker.random.word()}:gene:${faker.random.uuid()}`,
object_id: `${faker.random.word()}:gene:${faker.datatype.uuid()}`,
object_type: 'gene',
label: faker.random.word()
});
......
......@@ -31,11 +31,11 @@ const middlewares = [thunk];
const mockStore = configureMockStore(middlewares);
const trackPanelProperties: TrackPanelStateForGenome = {
isTrackPanelModalOpened: faker.random.boolean(),
isTrackPanelModalOpened: faker.datatype.boolean(),
selectedTrackPanelTab: TrackSet.GENOMIC,
trackPanelModalView: faker.lorem.word(),
highlightedTrackId: faker.lorem.word(),
isTrackPanelOpened: faker.random.boolean(),
isTrackPanelOpened: faker.datatype.boolean(),
collapsedTrackIds: [faker.lorem.word()],
bookmarks: [],
previouslyViewedObjects: []
......
......@@ -28,7 +28,7 @@ import CheckboxGrid, {
const createCheckboxData = (options: CheckboxGridOption[]) => {
const id = faker.lorem.word();
const label = faker.lorem.word();
const isChecked = faker.random.boolean();
const isChecked = faker.datatype.boolean();
options.push({
id,
......
......@@ -27,7 +27,7 @@ import CheckboxWithRadios, {
const onChange = jest.fn();
const createOption = () => ({
value: faker.random.uuid(),
value: faker.datatype.uuid(),
label: faker.random.words(5)
});
......
......@@ -25,7 +25,7 @@ import CheckboxWithSelects, {
} from './CheckboxWithSelects';
const createOption = (isSelected = false) => ({
value: faker.random.uuid(),
value: faker.datatype.uuid(),
label: faker.random.words(5),
isSelected
});
......
......@@ -113,15 +113,15 @@ describe('<CheckboxWithTextfields />', () => {
});
it('displays N number of file details based on the files prop', () => {
const files = Array(faker.random.number(10)).fill(mockReadFile);
const files = Array(faker.datatype.number(10)).fill(mockReadFile);
const { container } = renderCheckboxWithTextfields({ files: files });
expect(container.querySelectorAll('.filename').length).toBe(files.length);
});
it('calls the onFilesChange when a file is removed', async () => {
const files = Array(faker.random.number(10) || 1).fill(mockReadFile);
const randomNumber = faker.random.number(files.length - 1);
const files = Array(faker.datatype.number(10) || 1).fill(mockReadFile);
const randomNumber = faker.datatype.number(files.length - 1);
const { container } = renderCheckboxWithTextfields({ files: files });
const removeIcon = container
......
......@@ -15,7 +15,7 @@
*/
import React from 'react';
import { connect } from 'react-redux';
import { useSelector } from 'react-redux';
import { Link } from 'react-router-dom';
import { useQuery, gql } from '@apollo/client';
......@@ -28,7 +28,6 @@ import { getGenomeExampleFocusObjects } from 'src/shared/state/genome/genomeSele
import { CircleLoader } from 'src/shared/components/loader/Loader';
import { RootState } from 'src/store';
import { ExampleFocusObject } from 'src/shared/state/genome/genomeTypes';
import styles from './ExampleLinks.scss';
......@@ -37,11 +36,6 @@ type ExampleGene = {
symbol: string;
};
type ExampleLinksProps = {
activeGenomeId: string | null;
exampleEntities: ExampleFocusObject[];
};
const QUERY = gql`
query Gene($genomeId: String!, $geneId: String!) {
gene(byId: { genome_id: $genomeId, stable_id: $geneId }) {
......@@ -53,11 +47,12 @@ const QUERY = gql`
`;
// NOTE: the component currently handles only example gene
const ExampleLinks = (props: ExampleLinksProps) => {
const exampleGeneId = props.exampleEntities.find(
({ type }) => type === 'gene'
)?.id;
const { activeGenomeId } = props;
const ExampleLinks = () => {
const activeGenomeId = useSelector(getEntityViewerActiveGenomeId);
const exampleEntities = useSelector((state: RootState) =>
getGenomeExampleFocusObjects(state, activeGenomeId || '')
);
const exampleGeneId = exampleEntities.find(({ type }) => type === 'gene')?.id;
const { loading, data, error } = useQuery<{ gene: ExampleGene }>(QUERY, {
variables: { geneId: exampleGeneId, genomeId: activeGenomeId },
skip: !exampleGeneId || !activeGenomeId
......@@ -84,7 +79,7 @@ const ExampleLinks = (props: ExampleLinksProps) => {
objectId: data.gene.unversioned_stable_id
});
const path = urlHelper.entityViewer({
genomeId: props.activeGenomeId,
genomeId: activeGenomeId,
entityId: featureIdInUrl
});
......@@ -98,15 +93,4 @@ const ExampleLinks = (props: ExampleLinksProps) => {
);
};
const mapStateToProps = (state: RootState) => {
const activeGenomeId = getEntityViewerActiveGenomeId(state);
const exampleEntities = activeGenomeId
? getGenomeExampleFocusObjects(state, activeGenomeId)
: [];
return {
activeGenomeId,
exampleEntities
};
};
export default connect(mapStateToProps)(ExampleLinks);
export default ExampleLinks;
......@@ -22,7 +22,7 @@ import classNames from 'classnames';
import { Pick2 } from 'ts-multipick';
import * as urlFor from 'src/shared/helpers/urlHelper';
import { getProductAminoAcidLength } from 'src/content/app/entity-viewer/shared/helpers/entity-helpers.ts';
import { getProductAminoAcidLength } from 'src/content/app/entity-viewer/shared/helpers/entity-helpers';
import { toggleExpandedProtein } from 'src/content/app/entity-viewer/state/gene-view/proteins/geneViewProteinsSlice';
import { getExpandedTranscriptIds } from 'src/content/app/entity-viewer/state/gene-view/proteins/geneViewProteinsSelectors';
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment