diff --git a/src/api/web/endpoint/package.js b/src/api/web/endpoint/package.js index aaf24ad3a..3081f9f03 100644 --- a/src/api/web/endpoint/package.js +++ b/src/api/web/endpoint/package.js @@ -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}'); diff --git a/src/webui/components/Icon/img/filebinary.svg b/src/webui/components/Icon/img/filebinary.svg new file mode 100644 index 000000000..f891b36fe --- /dev/null +++ b/src/webui/components/Icon/img/filebinary.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/webui/components/Icon/img/law.svg b/src/webui/components/Icon/img/law.svg new file mode 100644 index 000000000..499148d2b --- /dev/null +++ b/src/webui/components/Icon/img/law.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/webui/components/Icon/img/version.svg b/src/webui/components/Icon/img/version.svg new file mode 100644 index 000000000..6a0eb92a2 --- /dev/null +++ b/src/webui/components/Icon/img/version.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/webui/components/Icon/index.js b/src/webui/components/Icon/index.js index c44c86103..239616e5c 100644 --- a/src/webui/components/Icon/index.js +++ b/src/webui/components/Icon/index.js @@ -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 = { // flags @@ -35,6 +38,9 @@ export const Icons: $Shape = { verdaccio, license, time, + law, + version, + filebinary, }; const Icon = ({ className, name, size = 'sm', img = false, pointer = false, ...props }: IProps): Node => { diff --git a/src/webui/components/Icon/styles.js b/src/webui/components/Icon/styles.js index 0454d4c37..fd3455f09 100644 --- a/src/webui/components/Icon/styles.js +++ b/src/webui/components/Icon/styles.js @@ -21,7 +21,7 @@ const getSize = (size: string) => { default: return ` width: 14px; - height: 14px; + height: 16px; `; } }; diff --git a/src/webui/components/Package/index.js b/src/webui/components/Package/index.js index 1cd9e1670..7f6bca976 100644 --- a/src/webui/components/Package/index.js +++ b/src/webui/components/Package/index.js @@ -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 => { - const renderMainInfo = () => ( - - {label} - {`v${version}`} - - ); - - const renderAuthorInfo = () => ( - - - {!avatar && getInitialsName(name)} - -
- -
-
+const Package = ({ name: label, version, dist: { unpackedSize } = {}, time, author: { name, avatar }, description, license, keywords = [] }: IProps): Element => { + console.log(unpackedSize); + const renderVersionInfo = () => version && ( + + + {`v${version}`} + + ); + + const renderAuthorInfo = () => { + return ( + + +
+ +
+
+ ); +<<<<<<< HEAD + }; +======= + } + + const renderFileSize = () => unpackedSize && ( + + + {fileSizeSI(unpackedSize)} + ); +>>>>>>> b4b8d6b0... wip const renderLicenseInfo = () => license && ( - + {license} ); const renderPublishedInfo = () => ( - + {`Published on ${formatDate(time)} •`} {`${formatDateDistance(time)} ago`} @@ -111,26 +131,62 @@ const Package = ({ name: label, version, time, author: { name, avatar }, descrip // )} //
// ); + const tags = keywords.sort().map((keyword, index) => ( + + {keyword} + + )); return ( - + - + {/* - - */} + + + {label} + + + + + + + + + + + + + + + + + + + + } secondary={ - - {name} + + {description} - {description} + {tags.length > 0 && + {tags} + } } /> - + + {renderAuthorInfo()} + {renderVersionInfo()} + {renderPublishedInfo()} + {renderFileSize()} + {renderLicenseInfo()} + ); }; diff --git a/src/webui/components/Package/styles.js b/src/webui/components/Package/styles.js index b8ee02f1e..0ae468d74 100644 --- a/src/webui/components/Package/styles.js +++ b/src/webui/components/Package/styles.js @@ -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; + } + } +`; diff --git a/src/webui/components/PackageList/index.js b/src/webui/components/PackageList/index.js index 70d66e656..ab607e40a 100644 --- a/src/webui/components/PackageList/index.js +++ b/src/webui/components/PackageList/index.js @@ -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 ( - + + {i !== 0 && } + + ); }) ); diff --git a/src/webui/components/Tag/styles.js b/src/webui/components/Tag/styles.js index a6eea8f92..cd624ed7e 100644 --- a/src/webui/components/Tag/styles.js +++ b/src/webui/components/Tag/styles.js @@ -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')}; } `; diff --git a/src/webui/utils/package.js b/src/webui/utils/package.js index b3d18e1fb..1bf7e71fe 100644 --- a/src/webui/utils/package.js +++ b/src/webui/utils/package.js @@ -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, }; }