diff --git a/package.json b/package.json
index 0bb6ec8..605286e 100644
--- a/package.json
+++ b/package.json
@@ -27,7 +27,7 @@
"@types/node": "12.7.8",
"@types/react": "16.9.2",
"@types/react-dom": "16.9.0",
- "@types/react-router-dom": "4.3.5",
+ "@types/react-router-dom": "5.1.0",
"@types/validator": "10.11.3",
"@typescript-eslint/parser": "2.3.2",
"@verdaccio/babel-preset": "2.0.0",
@@ -85,10 +85,9 @@
"react": "16.10.0",
"react-autosuggest": "9.4.3",
"react-dom": "16.10.0",
+ "react-router-dom": "5.1.2",
"react-emotion": "9.2.12",
"react-hot-loader": "4.12.11",
- "react-router": "5.0.1",
- "react-router-dom": "5.0.1",
"resolve-url-loader": "3.1.0",
"rimraf": "3.0.0",
"source-map-loader": "0.2.4",
diff --git a/src/components/Dependencies/Dependencies.test.tsx b/src/components/Dependencies/Dependencies.test.tsx
new file mode 100644
index 0000000..3f26ccf
--- /dev/null
+++ b/src/components/Dependencies/Dependencies.test.tsx
@@ -0,0 +1,92 @@
+import React from 'react';
+import { render } from '@testing-library/react';
+import { HashRouter } from 'react-router-dom';
+
+import { DetailContextProvider } from '../../pages/Version';
+
+import Dependencies from './Dependencies';
+
+describe(' component', () => {
+ test('Renders a message when there are no dependencies', () => {
+ // Given
+ const packageMeta = {
+ latest: {
+ name: 'verdaccio',
+ version: '4.0.0',
+ author: {
+ name: 'verdaccio user',
+ email: 'verdaccio.user@verdaccio.org',
+ url: '',
+ avatar: 'https://www.gravatar.com/avatar/000000',
+ },
+ dist: { fileCount: 0, unpackedSize: 0 },
+ dependencies: {},
+ devDependencies: {},
+ peerDependencies: {},
+ },
+ _uplinks: {},
+ };
+
+ // When
+ const { getByText } = render(
+
+
+
+ );
+
+ // Then
+ expect(getByText('verdaccio has no dependencies.')).toBeDefined();
+ });
+
+ test('Renders a link to each dependency', () => {
+ // Given
+ const packageMeta = {
+ latest: {
+ name: 'verdaccio',
+ version: '4.0.0',
+ author: {
+ name: 'verdaccio user',
+ email: 'verdaccio.user@verdaccio.org',
+ url: '',
+ avatar: 'https://www.gravatar.com/avatar/000000',
+ },
+ dist: { fileCount: 0, unpackedSize: 0 },
+ dependencies: {
+ react: '16.9.0',
+ 'react-dom': '16.9.0',
+ },
+ devDependencies: {
+ 'babel-core': '7.0.0-beta6',
+ },
+ peerDependencies: {
+ 'styled-components': '5.0.0',
+ },
+ },
+ _uplinks: {},
+ };
+
+ // When
+ const { getByText } = render(
+
+
+
+
+
+ );
+
+ // Then
+ // FIXME: currently MaterialUI chips do not support the children
+ // prop, therefore it is impossible to use proper links for
+ // dependencies. Those are for now clickable spans
+
+ expect(getByText('dependencies (2)')).toBeDefined();
+ expect(getByText('react@16.9.0').tagName).toBe('SPAN');
+ expect(getByText('react-dom@16.9.0').tagName).toBe('SPAN');
+
+ expect(getByText('devDependencies (1)')).toBeDefined();
+ expect(getByText('babel-core@7.0.0-beta6').tagName).toBe('SPAN');
+
+ expect(getByText('peerDependencies (1)')).toBeDefined();
+ expect(getByText('styled-components@5.0.0').tagName).toBe('SPAN');
+ });
+});
diff --git a/src/components/Dependencies/Dependencies.tsx b/src/components/Dependencies/Dependencies.tsx
index 33011ef..a11a6fc 100644
--- a/src/components/Dependencies/Dependencies.tsx
+++ b/src/components/Dependencies/Dependencies.tsx
@@ -1,117 +1,78 @@
-import React, { Component, Fragment, ReactElement } from 'react';
-import { withRouter, RouteComponentProps } from 'react-router-dom';
+import React, { useContext } from 'react';
+import { useHistory } from 'react-router-dom';
import CardContent from '@material-ui/core/CardContent';
-import { DetailContextConsumer, VersionPageConsumerProps } from '../../pages/Version';
+import { PackageDependencies } from '../../../types/packageMeta';
+import { DetailContext } from '../../pages/Version';
import NoItems from '../NoItems';
import { CardWrap, Heading, Tags, Tag } from './styles';
-type DepDetailProps = {
- name: string;
- version: string;
- onLoading?: () => void;
-} & RouteComponentProps;
-
-interface DepDetailState {
- name: string;
- version: string;
+interface DependencyBlockProps {
+ title: string;
+ dependencies: PackageDependencies;
}
-class DepDetail extends Component {
- constructor(props: DepDetailProps) {
- super(props);
- const { name, version } = this.props;
+const DependencyBlock: React.FC = ({ title, dependencies }) => {
+ const { enableLoading } = useContext(DetailContext);
+ const history = useHistory();
- this.state = {
- name,
- version,
- };
- }
+ const deps = Object.entries(dependencies);
- public render(): ReactElement {
- const { name, version } = this.state;
- const tagText = `${name}@${version}`;
- return ;
- }
+ function handleClick(name: string): void {
+ enableLoading && enableLoading();
- private handleOnClick = () => {
- const { name } = this.state;
- const { onLoading, history } = this.props;
-
- onLoading && onLoading();
history.push(`/-/web/detail/${name}`);
- };
+ }
+
+ return (
+
+
+ {`${title} (${deps.length})`}
+
+ {deps.map(([name, version]) => (
+ // eslint-disable-next-line
+ handleClick(name)} />
+ ))}
+
+
+
+ );
+};
+
+function hasKeys(object?: { [key: string]: any }): boolean {
+ return !!object && Object.keys(object).length > 0;
}
-const WrapperDependencyDetail = withRouter(DepDetail);
+const Dependencies: React.FC<{}> = () => {
+ const { packageMeta } = useContext(DetailContext);
-class DependencyBlock extends Component<{ title: string; dependencies: [] }> {
- public render(): ReactElement {
- const { dependencies, title } = this.props;
- const deps = Object.entries(dependencies) as [];
+ if (!packageMeta) {
+ throw new Error('packageMeta is required at DetailContext');
+ }
+ const { latest } = packageMeta;
+ // FIXME: add dependencies to package meta type
+ // @ts-ignore
+ const { dependencies, devDependencies, peerDependencies, name } = latest;
+ const dependencyMap = { dependencies, devDependencies, peerDependencies };
+ const hasDependencies = hasKeys(dependencies) || hasKeys(devDependencies) || hasKeys(peerDependencies);
+
+ if (hasDependencies) {
return (
-
- {({ enableLoading }) => {
- return (
-
-
- {`${title} (${deps.length})`}
- {this.renderTags(deps, enableLoading)}
-
-
- );
- }}
-
+ <>
+ {Object.entries(dependencyMap).map(([dependencyType, dependencies]) => {
+ if (!dependencies || Object.keys(dependencies).length === 0) {
+ return null;
+ }
+
+ return ;
+ })}
+ >
);
}
- private renderTags = (deps: [], enableLoading?: () => void) =>
- deps.map(dep => {
- const [name, version] = dep as [string, string];
-
- return ;
- });
-}
-
-class Dependencies extends Component {
- public render(): ReactElement {
- return (
-
- {packageMeta => {
- return this.renderDependencies(packageMeta as VersionPageConsumerProps);
- }}
-
- );
- }
-
- private checkDependencyLength(dependency: Record = {}): boolean {
- return Object.keys(dependency).length > 0;
- }
-
- private renderDependencies({ packageMeta }): ReactElement {
- const { latest } = packageMeta;
- const { dependencies, devDependencies, peerDependencies, name } = latest;
-
- const dependencyMap = { dependencies, devDependencies, peerDependencies };
-
- const dependencyList = Object.keys(dependencyMap).reduce(
- (result, value, key) => {
- const selectedDepndency = dependencyMap[value];
- if (selectedDepndency && this.checkDependencyLength(selectedDepndency)) {
- result.push();
- }
- return result;
- },
- [] as JSX.Element[]
- );
-
- if (dependencyList.length) {
- return {dependencyList};
- }
- return ;
- }
-}
+ return ;
+};
export default Dependencies;
diff --git a/types/packageMeta.ts b/types/packageMeta.ts
index 67cb902..6528eef 100644
--- a/types/packageMeta.ts
+++ b/types/packageMeta.ts
@@ -48,3 +48,7 @@ export interface Author {
url?: string;
avatar?: string;
}
+
+export interface PackageDependencies {
+ [key: string]: string;
+}
diff --git a/yarn.lock b/yarn.lock
index 390461a..3b14c1f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1676,10 +1676,10 @@
dependencies:
"@types/react" "*"
-"@types/react-router-dom@4.3.5":
- version "4.3.5"
- resolved "https://registry.verdaccio.org/@types%2freact-router-dom/-/react-router-dom-4.3.5.tgz#72f229967690c890d00f96e6b85e9ee5780db31f"
- integrity sha512-eFajSUASYbPHg2BDM1G8Btx+YqGgvROPIg6sBhl3O4kbDdYXdFdfrgQFf/pcBuQVObjfT9AL/dd15jilR5DIEA==
+"@types/react-router-dom@5.1.0":
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.1.0.tgz#8baa84a7fa8c8e7797fb3650ca51f93038cb4caf"
+ integrity sha512-YCh8r71pL5p8qDwQf59IU13hFy/41fDQG/GeOI3y+xmD4o0w3vEPxE8uBe+dvOgMoDl0W1WUZsWH0pxc1mcZyQ==
dependencies:
"@types/history" "*"
"@types/react" "*"
@@ -10946,23 +10946,23 @@ react-lifecycles-compat@^3.0.4:
resolved "https://registry.verdaccio.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"
integrity sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==
-react-router-dom@5.0.1:
- version "5.0.1"
- resolved "https://registry.verdaccio.org/react-router-dom/-/react-router-dom-5.0.1.tgz#ee66f4a5d18b6089c361958e443489d6bab714be"
- integrity sha512-zaVHSy7NN0G91/Bz9GD4owex5+eop+KvgbxXsP/O+iW1/Ln+BrJ8QiIR5a6xNPtrdTvLkxqlDClx13QO1uB8CA==
+react-router-dom@5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.1.2.tgz#06701b834352f44d37fbb6311f870f84c76b9c18"
+ integrity sha512-7BPHAaIwWpZS074UKaw1FjVdZBSVWEk8IuDXdB+OkLb8vd/WRQIpA4ag9WQk61aEfQs47wHyjWUoUGGZxpQXew==
dependencies:
"@babel/runtime" "^7.1.2"
history "^4.9.0"
loose-envify "^1.3.1"
prop-types "^15.6.2"
- react-router "5.0.1"
+ react-router "5.1.2"
tiny-invariant "^1.0.2"
tiny-warning "^1.0.0"
-react-router@5.0.1:
- version "5.0.1"
- resolved "https://registry.verdaccio.org/react-router/-/react-router-5.0.1.tgz#04ee77df1d1ab6cb8939f9f01ad5702dbadb8b0f"
- integrity sha512-EM7suCPNKb1NxcTZ2LEOWFtQBQRQXecLxVpdsP4DW4PbbqYWeRiLyV/Tt1SdCrvT2jcyXAXmVTmzvSzrPR63Bg==
+react-router@5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.1.2.tgz#6ea51d789cb36a6be1ba5f7c0d48dd9e817d3418"
+ integrity sha512-yjEuMFy1ONK246B+rsa0cUam5OeAQ8pyclRDgpxuSCrAlJ1qN9uZ5IgyKC7gQg0w8OM50NXHEegPh/ks9YuR2A==
dependencies:
"@babel/runtime" "^7.1.2"
history "^4.9.0"