0
Fork 0
mirror of https://github.com/verdaccio/verdaccio.git synced 2025-01-06 22:40:26 -05:00

Merge pull request #1230 from verdaccio/4.x-improvements-to-new-pacakge-sidebar

[4.x]improvements to new package sidebar
This commit is contained in:
Juan Picado @jotadeveloper 2019-02-19 23:14:59 +01:00 committed by GitHub
commit e143b7d0fe
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 94 additions and 77 deletions

View file

@ -4,12 +4,13 @@
import React, { Component } from 'react';
import { DetailContextConsumer } from '../../pages/version/index';
import Avatar from '@material-ui/core/Avatar/index';
import List from '@material-ui/core/List/index';
import ListItemText from '@material-ui/core/ListItemText/index';
import { DetailContextConsumer } from '../../pages/version/index';
import { Heading, AuthorListItem } from './styles';
class Authors extends Component<any, any> {
render() {
return (
@ -21,19 +22,19 @@ class Authors extends Component<any, any> {
);
}
renderLinkForMail(email, avatarComponent) {
renderLinkForMail(email, avatarComponent, packageName, version) {
if (!email) {
return avatarComponent;
}
return (
<a href={`mailto:${email}`} target={'_top'}>
<a href={`mailto:${email}?subject=${packageName}@${version}`} target={'_top'}>
{avatarComponent}
</a>
);
}
renderAuthor = ({ packageMeta }) => {
const { author } = packageMeta.latest;
const { author, name: packageName, version } = packageMeta.latest;
if (!author) {
return null;
@ -43,7 +44,7 @@ class Authors extends Component<any, any> {
return (
<List subheader={<Heading variant={'subheading'}>{'Author'}</Heading>}>
<AuthorListItem>
{this.renderLinkForMail(author.email, avatarComponent)}
{this.renderLinkForMail(author.email, avatarComponent, packageName, version)}
<ListItemText primary={author.name} />
</AuthorListItem>
</List>

View file

@ -11,7 +11,7 @@ import CardContent from '@material-ui/core/CardContent/index';
import { DetailContextConsumer } from '../../pages/version';
import { Content, CardWrap, Heading, Tags, Tag } from './styles';
import { CardWrap, Heading, Tags, Tag } from './styles';
import NoItems from '../NoItems';
class DepDetail extends Component<any, any> {
@ -87,27 +87,29 @@ class Dependencies extends Component<any, any> {
);
}
checkDependencyLength(dependency: Object = {}) {
return Object.keys(dependency).length > 0;
}
// $FlowFixMe
renderDependencies({ packageMeta }) {
const { latest } = packageMeta;
const { dependencies, devDependencies, peerDependencies, name } = latest;
if (dependencies || devDependencies || peerDependencies) {
return (
<Content>
<Fragment>
{dependencies && <DependencyBlock dependencies={dependencies} title={'Dependencies'} />}
{devDependencies && <DependencyBlock dependencies={devDependencies} title={'DevDependencies'} />}
{peerDependencies && <DependencyBlock dependencies={peerDependencies} title={'PeerDependencies'} />}
</Fragment>
</Content>
);
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(<DependencyBlock dependencies={selectedDepndency} key={key} title={value} />);
}
return result;
}, []);
if (dependencyList.length) {
return <Fragment>{dependencyList}</Fragment>;
}
return (
<Content>
<NoItems text={`${name} has no dependencies.`} />
</Content>
);
return <NoItems text={`${name} has no dependencies.`} />;
}
}

View file

@ -8,21 +8,16 @@ import Card from '@material-ui/core/Card/index';
import Typography from '@material-ui/core/Typography/index';
import Chip from '@material-ui/core/Chip/index';
export const Content = styled.div`
&& {
padding: 20px;
}
`;
export const CardWrap = styled(Card)`
&& {
margin: 0 0 25px;
margin: 0 0 16px;
}
`;
export const Heading = styled(Typography)`
&& {
font-weight: 700;
text-transform: capitalize;
}
`;

View file

@ -30,25 +30,31 @@ class DetailContainer extends Component<any, any> {
);
}
handleChange = (event: any, tabPosition: number) => {
event.preventDefault();
this.setState({ tabPosition });
};
// $FlowFixMe
renderTabs = ({ readMe }) => {
const { tabPosition } = this.state;
return (
<React.Fragment>
<Tabs indicatorColor={'primary'} onChange={this.handleChange} textColor={'primary'} value={tabPosition} variant={'fullWidth'}>
<Tab label={'Readme'} />
<Tab label={'Dependencies'} />
<Tab label={'Versions'} />
<Tab label={'Uplinks'} />
</Tabs>
<>
<Content>
<Tabs indicatorColor={'primary'} onChange={this.handleChange} textColor={'primary'} value={tabPosition} variant={'fullWidth'}>
<Tab label={'Readme'} />
<Tab label={'Dependencies'} />
<Tab label={'Versions'} />
<Tab label={'Uplinks'} />
</Tabs>
<br />
{tabPosition === 0 && this.renderReadme(readMe)}
{tabPosition === 1 && <Dependencies />}
{tabPosition === 2 && <Versions />}
{tabPosition === 3 && <UpLinks />}
</Content>
</React.Fragment>
</>
);
};
@ -57,11 +63,6 @@ class DetailContainer extends Component<any, any> {
return <Readme description={encodedReadme} />;
};
handleChange = (event: any, tabPosition: number) => {
event.preventDefault();
this.setState({ tabPosition });
};
}
export default DetailContainer;

View file

@ -3,7 +3,6 @@ import React, {Component} from 'react';
import Card from '@material-ui/core/Card/index';
import CardContent from '@material-ui/core/CardContent/index';
import List from '@material-ui/core/List/index';
import ListItemText from '@material-ui/core/ListItemText/index';
import ActtionBar from '../ActionBar';
import Author from '../Author';
@ -16,7 +15,7 @@ import Repository from '../Repository';
import { DetailContextConsumer } from '../../pages/version/index';
import { TitleListItem } from './styles';
import { TitleListItem, TitleListItemText } from './styles';
class DetailSidebar extends Component {
render() {
@ -51,7 +50,7 @@ class DetailSidebar extends Component {
return (
<List className={'detail-info'}>
<TitleListItem alignItems={"flex-start"}>
<ListItemText
<TitleListItemText
primary={<b>{packageName}</b>}
secondary={packageMeta.latest.description}
/>

View file

@ -6,6 +6,7 @@
import styled from 'react-emotion';
import Avatar from '@material-ui/core/Avatar/index';
import ListItem from '@material-ui/core/ListItem/index';
import ListItemText from '@material-ui/core/ListItemText/index';
import colors from '../../utils/styles/colors';
@ -17,6 +18,14 @@ export const TitleListItem = styled(ListItem)`
}
`;
export const TitleListItemText = styled(ListItemText)`
&& {
padding-left: 0;
padding-right: 0;
padding-top: 8px;
}
`;
export const TitleAvatar = styled(Avatar)`
&& {
color: ${colors.greySuperLight};

View file

@ -24,7 +24,7 @@ class Developers extends Component<Props, any> {
const { type } = this.props;
const developerType = packageMeta.latest[type];
if (!developerType || developerType.length === 0) return null;
return this.renderDevelopers(developerType);
return this.renderDevelopers(developerType, packageMeta);
}}
</DetailContextConsumer>
);
@ -34,7 +34,7 @@ class Developers extends Component<Props, any> {
this.setState((prev) => ({ visibleDevs: prev.visibleDevs + 6 }));
}
renderDevelopers = (developers) => {
renderDevelopers = (developers, packageMeta) => {
const { type } = this.props;
const { visibleDevs } = this.state;
return (
@ -42,7 +42,7 @@ class Developers extends Component<Props, any> {
<Heading variant={'subheading'}>{type}</Heading>
<Content>
{developers.slice(0, visibleDevs).map(developer => (
<Details key={developer.email}>{this.renderDeveloperDetails(developer)}</Details>
<Details key={developer.email}>{this.renderDeveloperDetails(developer, packageMeta)}</Details>
))}
{visibleDevs < developers.length &&
<Fab onClick={this.handleLoadMore} size={'small'}><Add /></Fab>
@ -52,22 +52,27 @@ class Developers extends Component<Props, any> {
);
}
renderLinkForMail(email, avatar) {
renderLinkForMail(email, avatarComponent, packageName, version) {
if(!email) {
return avatar;
return avatarComponent;
}
return (
<a href={`mailto:${email}`} target={"_top"}>
{avatar}
<a href={`mailto:${email}?subject=${packageName}@${version}`} target={"_top"}>
{avatarComponent}
</a>
);
}
renderDeveloperDetails = ({ name, avatar, email }) => {
renderDeveloperDetails = ({ name, avatar, email }, packageMeta) => {
const {
name: packageName,
version,
} = packageMeta.latest;
const avatarComponent = <Avatar aria-label={name} src={avatar} />;
return (
<Tooltip title={name}>
{this.renderLinkForMail(email, avatarComponent)}
{this.renderLinkForMail(email, avatarComponent, packageName, version)}
</Tooltip>
);
}

View file

@ -18,7 +18,6 @@ const renderTooltip = () => (
<Flag name={'nicaragua'} size={'md'} />
<Flag name={'india'} size={'md'} />
<Flag name={'brazil'} size={'md'} />
<Flag name={'pakistan'} size={'md'} />
<Flag name={'china'} size={'md'} />
<Flag name={'austria'} size={'md'} />
</Flags>

View file

@ -27,13 +27,16 @@ class Repository extends Component<any, any> {
}
renderRepository = ({packageMeta}) => {
const { repository, homepage } = packageMeta.latest;
if (!repository) {
const {
repository: {
url,
} = {},
} = packageMeta.latest;
if (!url) {
return null;
}
// we prefer homepage first, because it's more cleaner
const url = homepage || repository.url;
return (
<>
<List dense={true} subheader={<Heading variant={"subheading"}>{'Repository'}</Heading>}>

View file

@ -38,7 +38,6 @@ class UpLinks extends React.PureComponent<any> {
);
renderContent(uplinks, { name }) {
console.log(uplinks);
if (Object.keys(uplinks).length > 0) {
return (
uplinks && (

View file

@ -17,40 +17,44 @@ class Versions extends React.PureComponent<any> {
// $FlowFixMe
<DetailContextConsumer>
{({ packageMeta }) => {
return this.renderContent(packageMeta[DIST_TAGS], packageMeta.versions);
return this.renderContent(packageMeta);
}}
</DetailContextConsumer>
);
}
renderPackageList = (packages: any, isVersion: boolean = false) => (
<List>
{Object.keys(packages)
.reverse()
.map(version => (
<ListItem key={version}>
<ListItemText>{version}</ListItemText>
<Spacer />
<ListItemText>{isVersion ? `${formatDateDistance('2017-10-26T09:03:15.044Z')} ago` : packages[version]}</ListItemText>
</ListItem>
))}
</List>
);
renderPackageList = (packages: any, isVersion: boolean = false, timeMap: Object = {}) => {
return (
<List>
{Object.keys(packages)
.reverse()
.map(version => (
<ListItem key={version}>
<ListItemText>{version}</ListItemText>
<Spacer />
<ListItemText>{isVersion && timeMap[version] ? `${formatDateDistance(timeMap[version])} ago` : packages[version]}</ListItemText>
</ListItem>
))}
</List>
);
};
// $FlowFixMe
renderContent(distTags: object, versions: object) {
renderContent(packageMeta) {
const { versions = {}, time: timeMap = {}, [DIST_TAGS]: distTags = {} } = packageMeta;
return (
<>
{distTags && (
<>
<Heading variant={'subheading'}>{'Current Tags'}</Heading>
{this.renderPackageList(distTags)}
{this.renderPackageList(distTags, false, timeMap)}
</>
)}
{versions && (
<>
<Heading variant={'subheading'}>{'Version History'}</Heading>
{this.renderPackageList(versions, true)}
{this.renderPackageList(versions, true, timeMap)}
</>
)}
</>

View file

@ -1,3 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<Footer /> component should load the initial state of Footer component 1`] = `"<div class=\\"css-i0nj2g efsnl070\\"><div class=\\"css-hzfs9b efsnl071\\"><div class=\\"css-d8nsp7 efsnl072\\"> Made with<span class=\\"css-1so4oe0 efsnl077\\">♥</span>on<span class=\\"css-1ie354y efsnl074\\"><svg class=\\"efsnl075 css-1kgp95j ej4jd2o0\\"><title>Earth</title><use xlink:href=\\"[object Object]#earth\\"></use></svg><span class=\\"css-e8kfuf efsnl076\\"><svg class=\\"efsnl078 css-f1ndto ej4jd2o0\\"><title>Spain</title><use xlink:href=\\"[object Object]#spain\\"></use></svg><svg class=\\"efsnl078 css-f1ndto ej4jd2o0\\"><title>Nicaragua</title><use xlink:href=\\"[object Object]#nicaragua\\"></use></svg><svg class=\\"efsnl078 css-f1ndto ej4jd2o0\\"><title>India</title><use xlink:href=\\"[object Object]#india\\"></use></svg><svg class=\\"efsnl078 css-f1ndto ej4jd2o0\\"><title>Brazil</title><use xlink:href=\\"[object Object]#brazil\\"></use></svg><svg class=\\"efsnl078 css-f1ndto ej4jd2o0\\"><title>Pakistan</title><use xlink:href=\\"[object Object]#pakistan\\"></use></svg><svg class=\\"efsnl078 css-f1ndto ej4jd2o0\\"><title>China</title><use xlink:href=\\"[object Object]#china\\"></use></svg><svg class=\\"efsnl078 css-f1ndto ej4jd2o0\\"><title>Austria</title><use xlink:href=\\"[object Object]#austria\\"></use></svg></span></span></div><div class=\\"css-1wbzdyy efsnl073\\">Powered by<span class=\\"efsnl078 css-i15wza ej4jd2o1\\" title=\\"Verdaccio\\"><img alt=\\"Verdaccio\\" src=\\"[object Object]\\" class=\\"css-1ncdhax ej4jd2o2\\"></span>/ 4.0.0-alpha.3</div></div></div>"`;
exports[`<Footer /> component should load the initial state of Footer component 1`] = `"<div class=\\"css-i0nj2g efsnl070\\"><div class=\\"css-hzfs9b efsnl071\\"><div class=\\"css-d8nsp7 efsnl072\\"> Made with<span class=\\"css-1so4oe0 efsnl077\\">♥</span>on<span class=\\"css-1ie354y efsnl074\\"><svg class=\\"efsnl075 css-1kgp95j ej4jd2o0\\"><title>Earth</title><use xlink:href=\\"[object Object]#earth\\"></use></svg><span class=\\"css-e8kfuf efsnl076\\"><svg class=\\"efsnl078 css-f1ndto ej4jd2o0\\"><title>Spain</title><use xlink:href=\\"[object Object]#spain\\"></use></svg><svg class=\\"efsnl078 css-f1ndto ej4jd2o0\\"><title>Nicaragua</title><use xlink:href=\\"[object Object]#nicaragua\\"></use></svg><svg class=\\"efsnl078 css-f1ndto ej4jd2o0\\"><title>India</title><use xlink:href=\\"[object Object]#india\\"></use></svg><svg class=\\"efsnl078 css-f1ndto ej4jd2o0\\"><title>Brazil</title><use xlink:href=\\"[object Object]#brazil\\"></use></svg><svg class=\\"efsnl078 css-f1ndto ej4jd2o0\\"><title>China</title><use xlink:href=\\"[object Object]#china\\"></use></svg><svg class=\\"efsnl078 css-f1ndto ej4jd2o0\\"><title>Austria</title><use xlink:href=\\"[object Object]#austria\\"></use></svg></span></span></div><div class=\\"css-1wbzdyy efsnl073\\">Powered by<span class=\\"efsnl078 css-i15wza ej4jd2o1\\" title=\\"Verdaccio\\"><img alt=\\"Verdaccio\\" src=\\"[object Object]\\" class=\\"css-1ncdhax ej4jd2o2\\"></span>/ 4.0.0-alpha.3</div></div></div>"`;