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

refactor: package list [WIP]

This commit is contained in:
Ayush Sharma 2019-02-24 22:40:32 +01:00
parent c518b94978
commit aec337719e
11 changed files with 158 additions and 50 deletions

View file

@ -7,6 +7,8 @@ import _ from 'lodash';
import { addScope, addGravatarSupport, deleteProperties, sortByName, parseReadme } from '../../../lib/utils';
import { allow } from '../../middleware';
import { DIST_TAGS, HEADER_TYPE, HEADERS, HTTP_STATUS } from '../../../lib/constants';
import { generateGravatarUrl } from '../../../utils/user';
import { formatAuthor } from '../../../webui/utils/package';
import logger from '../../../lib/logger';
import type { Router } from 'express';
import type { IAuth, $ResponseExtend, $RequestExtend, $NextFunctionVer, IStorageHandler, $SidebarPackage } from '../../../../types';
@ -41,12 +43,18 @@ function addPackageWebApi(route: Router, storage: IStorageHandler, auth: IAuth,
throw err;
}
async function processPermissionsPackages(packages) {
async function processPermissionsPackages(packages = []) {
const permissions = [];
for (const pkg of packages) {
const packgesCopy = packages.slice();
for (const pkg of packgesCopy) {
const pkgCopy = { ...pkg };
pkgCopy.author = formatAuthor(pkg.author);
try {
if (await checkAllow(pkg.name, req.remote_user)) {
permissions.push(pkg);
if (config.web) {
pkgCopy.author.avatar = generateGravatarUrl(pkgCopy.author.email, config.web.gravatar);
}
permissions.push(pkgCopy);
}
} catch (err) {
logger.logger.error({ name: pkg.name, error: err }, 'permission process for @{name} has failed: @{error}');

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" id="filebinary">
<path d="M8.5 1H1c-.55 0-1 .45-1 1v12c0 .55.45 1 1 1h10c.55 0 1-.45 1-1V4.5L8.5 1zM11 14H1V2h7l3 3v9zM5 6.98L3.5 8.5 5 10l-.5 1L2 8.5 4.5 6l.5.98zM7.5 6L10 8.5 7.5 11l-.5-.98L8.5 8.5 7 7l.5-1z"></path>
</svg>

After

Width:  |  Height:  |  Size: 265 B

View file

@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" id="law">
<path fill-rule="evenodd" d="M7 4c-.83 0-1.5-.67-1.5-1.5S6.17 1 7 1s1.5.67 1.5 1.5S7.83 4 7 4zm7 6c0 1.11-.89 2-2 2h-1c-1.11 0-2-.89-2-2l2-4h-1c-.55 0-1-.45-1-1H8v8c.42 0 1 .45 1 1h1c.42 0 1 .45 1 1H3c0-.55.58-1 1-1h1c0-.55.58-1 1-1h.03L6 5H5c0 .55-.45 1-1 1H3l2 4c0 1.11-.89 2-2 2H2c-1.11 0-2-.89-2-2l2-4H1V5h3c0-.55.45-1 1-1h4c.55 0 1 .45 1 1h3v1h-1l2 4zM2.5 7L1 10h3L2.5 7zM13 10l-1.5-3-1.5 3h3z"></path>
</svg>

After

Width:  |  Height:  |  Size: 464 B

View file

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 16" height="16" width="14" id="version">
<path fill-rule="evenodd" d="M13 3H7c-.55 0-1 .45-1 1v8c0 .55.45 1 1 1h6c.55 0 1-.45 1-1V4c0-.55-.45-1-1-1zm-1 8H8V5h4v6zM4 4h1v1H4v6h1v1H4c-.55 0-1-.45-1-1V5c0-.55.45-1 1-1zM1 5h1v1H1v4h1v1H1c-.55 0-1-.45-1-1V6c0-.55.45-1 1-1z"></path>
</svg>

After

Width:  |  Height:  |  Size: 344 B

View file

@ -20,7 +20,10 @@ import spain from './img/spain.svg';
import earth from './img/earth.svg';
import verdaccio from './img/verdaccio.svg';
import license from './img/license.svg';
import law from './img/law.svg';
import time from './img/time.svg';
import version from './img/version.svg';
import filebinary from './img/filebinary.svg';
export const Icons: $Shape<IIconsMap> = {
// flags
@ -35,6 +38,9 @@ export const Icons: $Shape<IIconsMap> = {
verdaccio,
license,
time,
law,
version,
filebinary,
};
const Icon = ({ className, name, size = 'sm', img = false, pointer = false, ...props }: IProps): Node => {

View file

@ -21,7 +21,7 @@ const getSize = (size: string) => {
default:
return `
width: 14px;
height: 14px;
height: 16px;
`;
}
};

View file

@ -9,15 +9,21 @@ import React from 'react';
import type { Element } from 'react';
import { spacing } from '../../utils/styles/mixings';
import Grid from '@material-ui/core/Grid';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemText from '@material-ui/core/ListItemText';
import ListItemAvatar from '@material-ui/core/ListItemAvatar';
import Avatar2 from '@material-ui/core/Avatar';
import Typography from '@material-ui/core/Typography';
import Divider from '@material-ui/core/Divider';
import IconButton from '@material-ui/core/IconButton';
import BugReport from '@material-ui/icons/BugReport';
import Tooltip from '@material-ui/core/Tooltip';
import HomeIcon from '@material-ui/icons/Home';
import BookmarkBorder from '@material-ui/icons/BookmarkBorder';
import Tag from '../Tag';
import fileSizeSI from '../../utils/file-size';
import { formatDate, formatDateDistance } from '../../utils/package';
import { IProps } from './types';
@ -39,7 +45,9 @@ import {
Field,
Content,
Footer,
PackageName,
} from './styles';
import { fontWeight } from '../../utils/styles/sizes';
const getInitialsName = (name: string) =>
name
@ -47,36 +55,48 @@ const getInitialsName = (name: string) =>
.reduce((accumulator, currentValue) => accumulator.charAt(0) + currentValue.charAt(0), '')
.toUpperCase();
const Package = ({ name: label, version, time, author: { name, avatar }, description, license, keywords = [] }: IProps): Element<WrapperLink> => {
const renderMainInfo = () => (
<MainInfo>
<Name>{label}</Name>
<Version>{`v${version}`}</Version>
</MainInfo>
);
const renderAuthorInfo = () => (
<Author>
<Avatar alt={name} src={avatar}>
{!avatar && getInitialsName(name)}
</Avatar>
<Details>
<Text text={name} weight={'bold'} />
</Details>
</Author>
const Package = ({ name: label, version, dist: { unpackedSize } = {}, time, author: { name, avatar }, description, license, keywords = [] }: IProps): Element<WrapperLink> => {
console.log(unpackedSize);
const renderVersionInfo = () => version && (
<OverviewItem>
<Icon name={'version'} />
{`v${version}`}
</OverviewItem>
);
const renderAuthorInfo = () => {
return (
<Author>
<Avatar alt={name} src={avatar} style={{ width: '20px', height: '20px' }} />
<Details>
<Text text={name} />
</Details>
</Author>
);
<<<<<<< HEAD
};
=======
}
const renderFileSize = () => unpackedSize && (
<OverviewItem>
<Icon name={'filebinary'} />
{fileSizeSI(unpackedSize)}
</OverviewItem>
);
>>>>>>> b4b8d6b0... wip
const renderLicenseInfo = () =>
license && (
<OverviewItem>
<Icon modifiers={spacing('margin', '4px', '5px', '0px', '0px')} name={'license'} pointer={true} />
<Icon name={'law'} />
{license}
</OverviewItem>
);
const renderPublishedInfo = () => (
<OverviewItem>
<Icon name={'time'} pointer={true} />
<Icon name={'time'} />
<Published modifiers={spacing('margin', '0px', '5px', '0px', '0px')}>{`Published on ${formatDate(time)}`}</Published>
{`${formatDateDistance(time)} ago`}
</OverviewItem>
@ -111,26 +131,62 @@ const Package = ({ name: label, version, time, author: { name, avatar }, descrip
// )}
// </WrapperLink>
// );
const tags = keywords.sort().map((keyword, index) => (
<Tag style={{ color: '#485A3E' }} key={index}>
{keyword}
</Tag>
));
return (
<List>
<List style={{ padding: '12px 0 12px 0'}}>
<ListItem alignItems="flex-start">
<ListItemAvatar>
{/* <ListItemAvatar>
<Avatar2 alt="Remy Sharp" src="/static/images/avatar/1.jpg" />
</ListItemAvatar>
<ListItemText
primary={label}
</ListItemAvatar> */}
<ListItemText component="div" style={{ paddingRight: 0}}
primary={
<Grid item xs={12} container>
<Grid item xs>
<PackageName>{label}</PackageName>
</Grid>
<Grid item xs style={{ textAlign: "right" }}>
<Tooltip title="Visit homepage" aria-label="Add">
<IconButton aria-label="Report" style={{ padding: '6px' }}>
<HomeIcon fontSize="small" style={{ fontSize: '16px' }} />
</IconButton>
</Tooltip>
<Tooltip title="Open an issue" aria-label="Add">
<IconButton aria-label="Report" style={{ padding: '6px' }}>
<BugReport fontSize="small" style={{ fontSize: '16px' }} />
</IconButton>
</Tooltip>
<Tooltip title="Pin it" aria-label="Add">
<IconButton aria-label="Report" style={{ padding: '6px' }}>
<BookmarkBorder fontSize="small" style={{ fontSize: '16px' }} />
</IconButton>
</Tooltip>
</Grid>
</Grid>
}
secondary={
<React.Fragment>
<Typography component="span" color="textPrimary">
{name}
<Typography component="span" style={{ color: '#586069', fontSize: '14px', paddingRight: 0 }}>
{description}
</Typography>
{description}
{tags.length > 0 && <span style={{ marginTop: '8px', display: 'block' }}>
{tags}
</span>}
</React.Fragment>
}
/>
</ListItem>
<Divider></Divider>
<ListItem alignItems="flex-start">
{renderAuthorInfo()}
{renderVersionInfo()}
{renderPublishedInfo()}
{renderFileSize()}
{renderLicenseInfo()}
</ListItem>
</List>
);
};

View file

@ -52,8 +52,9 @@ export const OverviewItem = styled.span`
&& {
display: flex;
align-items: center;
margin: 0 0 5px 0;
color: ${colors.greyLight};
margin: 0 0 0 16px;
color: #908ba1;
font-size: 16px;
}
`;
@ -83,15 +84,14 @@ export const Version = styled.span`
export const Icon = styled(Ico)`
&& {
margin: 1px 5px 0 0;
fill: ${colors.greyLight};
margin: 0px 10px 0px 0;
fill: #908ba1;
}
`;
export const Published = styled.span`
&& {
display: none;
color: ${colors.greyLight};
color: #908ba1;
${({ modifiers }) => modifiers};
}
`;
@ -178,7 +178,7 @@ export const WrapperLink = styled(Link)`
align-items: center;
}
${OverviewItem} {
margin: 0 0 0 10px;
margin: 0 0 0 0;
}
${Overview} {
flex-direction: row;
@ -197,3 +197,22 @@ export const WrapperLink = styled(Link)`
`)};
}
`;
/**
* Ayush's style
*/
export const PackageName = styled.span`
&& {
font-weight: 600;
font-size: 20px;
display: block;
margin-bottom: 12px;
color: #414141;
cursor: pointer;
&:hover {
color: black;
}
}
`;

View file

@ -1,9 +1,10 @@
import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import Divider from '@material-ui/core/Divider';
import Package from '../Package';
import Help from '../Help';
import { formatAuthor, formatLicense } from '../../utils/package';
import { formatLicense } from '../../utils/package';
import classes from './packageList.scss';
@ -24,11 +25,14 @@ export default class PackageList extends React.Component {
const { packages } = this.props;
return (
packages.map((pkg, i) => {
const { name, version, description, time, keywords } = pkg;
const author = formatAuthor(pkg.author);
const { name, version, description, time, keywords, dist } = pkg;
const author = pkg.author;
const license = formatLicense(pkg.license);
return (
<Package key={i} {...{ name, version, author, description, license, time, keywords }} />
<React.Fragment key={i}>
{i !== 0 && <Divider style={{ margin: 0 }}></Divider>}
<Package {...{ name, dist, version, author, description, license, time, keywords }} />
</React.Fragment>
);
})
);

View file

@ -11,10 +11,10 @@ export const Wrapper = styled.span`
vertical-align: middle;
line-height: 22px;
border-radius: 2px;
color: #9f9f9f;
background-color: hsla(0, 0%, 51%, 0.1);
color: #485a3e;
background-color: #f3f4f2;
padding: 0.22rem 0.4rem;
margin: 5px 10px 0 0;
margin: 8px 8px 0 0;
${ellipsis('300px')};
}
`;

View file

@ -47,13 +47,17 @@ export function formatAuthor(author) {
let authorDetails = {
name: DEFAULT_USER,
email: '',
avatar: '',
};
if (!author) {
return authorDetails;
}
if (isString(author)) {
authorDetails = {
...authorDetails,
name: author ? author : authorDetails.name,
email: author.email ? author.email : authorDetails.email,
};
}
@ -61,8 +65,7 @@ export function formatAuthor(author) {
authorDetails = {
...authorDetails,
name: author.name ? author.name : authorDetails.name,
email: author.email ? author.email : authorDetails.email,
avatar: author.avatar ? author.avatar : authorDetails.avatar,
email: author.email ? author.email: authorDetails.email,
};
}