mirror of
https://github.com/SomboChea/ui
synced 2024-12-25 13:44:31 +07:00
refactor: convert Author component to hooks (#150)
This commit is contained in:
parent
a365ec548a
commit
d2f1f1c06a
@ -1,24 +1,15 @@
|
||||
import React from 'react';
|
||||
import { mount } from 'enzyme';
|
||||
|
||||
import { DetailContext } from '../../pages/Version';
|
||||
|
||||
import Authors from './Author';
|
||||
|
||||
const mockPackageMeta = jest.fn(() => ({
|
||||
latest: {
|
||||
homepage: 'https://verdaccio.tld',
|
||||
bugs: {
|
||||
url: 'https://verdaccio.tld/bugs',
|
||||
},
|
||||
dist: {
|
||||
tarball: 'https://verdaccio.tld/download',
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('../../pages/Version', () => ({
|
||||
DetailContextConsumer: component => {
|
||||
return component.children({ packageMeta: mockPackageMeta() });
|
||||
},
|
||||
}));
|
||||
const withAuthorComponent = (packageMeta: React.ContextType<typeof DetailContext>['packageMeta']): JSX.Element => (
|
||||
<DetailContext.Provider value={{ packageMeta }}>
|
||||
<Authors />
|
||||
</DetailContext.Provider>
|
||||
);
|
||||
|
||||
describe('<Author /> component', () => {
|
||||
beforeEach(() => {
|
||||
@ -36,13 +27,12 @@ describe('<Author /> component', () => {
|
||||
url: '',
|
||||
avatar: 'https://www.gravatar.com/avatar/000000',
|
||||
},
|
||||
dist: { fileCount: 0, unpackedSize: 0 },
|
||||
},
|
||||
_uplinks: {},
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
mockPackageMeta.mockImplementation(() => packageMeta);
|
||||
|
||||
const wrapper = mount(<Authors />);
|
||||
const wrapper = mount(withAuthorComponent(packageMeta));
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
|
||||
@ -51,14 +41,13 @@ describe('<Author /> component', () => {
|
||||
latest: {
|
||||
name: 'verdaccio',
|
||||
version: '4.0.0',
|
||||
dist: { fileCount: 0, unpackedSize: 0 },
|
||||
},
|
||||
_uplinks: {},
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
mockPackageMeta.mockImplementation(() => packageMeta);
|
||||
|
||||
const wrapper = mount(<Authors />);
|
||||
expect(wrapper.html()).toEqual('');
|
||||
const wrapper = mount(withAuthorComponent(packageMeta));
|
||||
expect(wrapper.html()).toBeNull();
|
||||
});
|
||||
|
||||
test('should render the component when there is no author email', () => {
|
||||
@ -71,13 +60,12 @@ describe('<Author /> component', () => {
|
||||
url: '',
|
||||
avatar: 'https://www.gravatar.com/avatar/000000',
|
||||
},
|
||||
dist: { fileCount: 0, unpackedSize: 0 },
|
||||
},
|
||||
_uplinks: {},
|
||||
};
|
||||
|
||||
// @ts-ignore
|
||||
mockPackageMeta.mockImplementation(() => packageMeta);
|
||||
|
||||
const wrapper = mount(<Authors />);
|
||||
const wrapper = mount(withAuthorComponent(packageMeta));
|
||||
expect(wrapper.html()).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
@ -1,58 +1,44 @@
|
||||
import React, { Component, ReactNode, ReactElement } from 'react';
|
||||
import React, { FC, useContext } from 'react';
|
||||
|
||||
import Avatar from '@material-ui/core/Avatar';
|
||||
import List from '@material-ui/core/List';
|
||||
|
||||
import { DetailContextConsumer } from '../../pages/Version';
|
||||
import { DetailContext } from '../../pages/Version';
|
||||
import { Heading, AuthorListItem, AuthorListItemText } from './styles';
|
||||
import { isEmail } from '../../utils/url';
|
||||
|
||||
class Authors extends Component {
|
||||
public render(): ReactElement<HTMLElement> {
|
||||
return (
|
||||
<DetailContextConsumer>
|
||||
{context => {
|
||||
const { packageMeta } = context;
|
||||
const Authors: FC = () => {
|
||||
const { packageMeta } = useContext(DetailContext);
|
||||
|
||||
if (!packageMeta) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.renderAuthor(packageMeta);
|
||||
}}
|
||||
</DetailContextConsumer>
|
||||
);
|
||||
if (!packageMeta) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public renderLinkForMail(email: string, avatarComponent: ReactNode, packageName: string, version: string): ReactElement<HTMLElement> | ReactNode {
|
||||
if (!email || isEmail(email) === false) {
|
||||
return avatarComponent;
|
||||
}
|
||||
const { author, name: packageName, version } = packageMeta.latest;
|
||||
|
||||
return (
|
||||
<a href={`mailto:${email}?subject=${packageName}@${version}`} target={'_top'}>
|
||||
{avatarComponent}
|
||||
</a>
|
||||
);
|
||||
if (!author) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public renderAuthor = ({ latest }) => {
|
||||
const { author, name: packageName, version } = latest;
|
||||
const { email, name } = author;
|
||||
|
||||
if (!author) {
|
||||
return null;
|
||||
}
|
||||
const avatarComponent = <Avatar alt={author.name} src={author.avatar} />;
|
||||
|
||||
const avatarComponent = <Avatar alt={author.name} src={author.avatar} />;
|
||||
return (
|
||||
<List subheader={<Heading variant={'subtitle1'}>{'Author'}</Heading>}>
|
||||
<AuthorListItem button={true}>
|
||||
{this.renderLinkForMail(author.email, avatarComponent, packageName, version)}
|
||||
<AuthorListItemText primary={author.name} />
|
||||
</AuthorListItem>
|
||||
</List>
|
||||
);
|
||||
};
|
||||
}
|
||||
return (
|
||||
<List subheader={<Heading variant={'subtitle1'}>{'Author'}</Heading>}>
|
||||
<AuthorListItem button={true}>
|
||||
{!email || !isEmail(email) ? (
|
||||
avatarComponent
|
||||
) : (
|
||||
<a href={`mailto:${email}?subject=${packageName}@${version}`} target={'_top'}>
|
||||
{avatarComponent}
|
||||
</a>
|
||||
)}
|
||||
|
||||
<AuthorListItemText primary={name} />
|
||||
</AuthorListItem>
|
||||
</List>
|
||||
);
|
||||
};
|
||||
|
||||
export default Authors;
|
||||
|
@ -5,7 +5,7 @@ import Grid from '@material-ui/core/Grid';
|
||||
import HomeIcon from '@material-ui/icons/Home';
|
||||
import ListItem from '@material-ui/core/ListItem';
|
||||
|
||||
import { PackageMetaInterface } from 'types/packageMeta';
|
||||
import { PackageMetaInterface, Author as PackageAuthor } from 'types/packageMeta';
|
||||
import Tag from '../Tag';
|
||||
import fileSizeSI from '../../utils/file-size';
|
||||
import { formatDate, formatDateDistance } from '../../utils/package';
|
||||
@ -28,11 +28,6 @@ import {
|
||||
WrapperLink,
|
||||
} from './styles';
|
||||
import { isURL } from '../../utils/url';
|
||||
interface Author {
|
||||
name: string;
|
||||
avatar?: string;
|
||||
email?: string;
|
||||
}
|
||||
|
||||
interface Bugs {
|
||||
url: string;
|
||||
@ -45,7 +40,7 @@ export interface PackageInterface {
|
||||
name: string;
|
||||
version: string;
|
||||
time?: number | string;
|
||||
author: Author;
|
||||
author: PackageAuthor;
|
||||
description?: string;
|
||||
keywords?: string[];
|
||||
license?: PackageMetaInterface['latest']['license'];
|
||||
|
@ -3,12 +3,14 @@ export interface PackageMetaInterface {
|
||||
distTags?: DistTags;
|
||||
time?: Time;
|
||||
latest: {
|
||||
author?: Author;
|
||||
name: string;
|
||||
dist: {
|
||||
fileCount: number;
|
||||
unpackedSize: number;
|
||||
};
|
||||
license?: Partial<LicenseInterface> | string;
|
||||
version: string;
|
||||
};
|
||||
_uplinks: {};
|
||||
}
|
||||
@ -41,10 +43,11 @@ export interface Version {
|
||||
keywords?: string[];
|
||||
}
|
||||
|
||||
interface Author {
|
||||
export interface Author {
|
||||
name?: string;
|
||||
email?: string;
|
||||
url?: string;
|
||||
avatar?: string;
|
||||
}
|
||||
|
||||
interface Maintainer {
|
||||
|
Loading…
Reference in New Issue
Block a user