From 133a5f01712b50c889542c1582038818967a4bec Mon Sep 17 00:00:00 2001 From: "Juan Picado @jotadeveloper" Date: Wed, 27 Mar 2019 23:39:06 +0100 Subject: [PATCH] chore: sync with 4.x webui --- .gitignore | 2 + src/app.js | 61 +++-- src/app.scss | 16 +- src/components/ActionBar/index.js | 109 ++++++++ src/components/ActionBar/styles.js | 24 ++ src/components/Author/index.js | 58 ++-- src/components/Author/styles.js | 21 ++ src/components/CopyToClipBoard/index.js | 22 +- src/components/CopyToClipBoard/types.js | 1 + src/components/Dependencies/index.js | 56 ++-- src/components/Dependencies/styles.js | 9 +- src/components/DetailContainer/index.js | 27 +- src/components/DetailSidebar/index.js | 105 ++++---- src/components/DetailSidebar/styles.js | 27 +- src/components/Developers/index.js | 64 +++-- src/components/Developers/styles.js | 10 +- src/components/Dist/index.js | 59 +++++ src/components/Dist/styles.js | 39 +++ src/components/Engines/img/node.png | Bin 0 -> 27565 bytes src/components/Engines/index.js | 78 ++++++ src/components/Engines/styles.js | 21 ++ src/components/Footer/index.js | 52 ++-- src/components/Header/index.js | 2 +- src/components/Help/index.js | 4 +- src/components/Icon/img/filebinary.svg | 3 + src/components/Icon/img/law.svg | 3 + src/components/Icon/img/version.svg | 6 + src/components/Icon/index.js | 7 + src/components/Icon/styles.js | 2 +- src/components/Icon/types.js | 3 + src/components/Install/img/npm.svg | 15 ++ src/components/Install/img/pnpm.svg | 1 + src/components/Install/img/yarn.svg | 1 + src/components/Install/index.js | 68 +++-- src/components/Install/styles.js | 28 ++ src/components/License/index.js | 51 ---- src/components/NoItems/index.js | 9 +- src/components/NoItems/styles.js | 12 - src/components/NotFound/index.js | 6 +- src/components/Package/index.js | 206 +++++++++------ src/components/Package/styles.js | 247 ++++++++---------- src/components/Package/types.js | 10 + src/components/PackageDetail/index.js | 31 --- .../PackageDetail/packageDetail.scss | 16 -- src/components/PackageList/index.js | 53 ++-- .../PackageSidebar/Module/index.jsx | 25 -- .../PackageSidebar/Module/style.scss | 24 -- .../ModuleContentPlaceholder/index.jsx | 11 - .../ModuleContentPlaceholder/style.scss | 8 - src/components/PackageSidebar/index.jsx | 104 -------- .../modules/Dependencies/index.jsx | 50 ---- .../modules/Dependencies/style.scss | 13 - .../PackageSidebar/modules/DistTags/index.jsx | 50 ---- .../modules/DistTags/style.scss | 13 - .../PackageSidebar/modules/Infos/index.jsx | 40 --- .../PackageSidebar/modules/Infos/style.scss | 21 -- .../PackageSidebar/modules/LastSync/index.jsx | 43 --- .../modules/LastSync/style.scss | 13 - .../Maintainers/MaintainerInfo/index.jsx | 22 -- .../Maintainers/MaintainerInfo/style.scss | 26 -- .../modules/Maintainers/index.jsx | 122 --------- .../modules/Maintainers/style.scss | 13 - .../modules/PeerDependencies/index.jsx | 18 -- src/components/Repository/img/git.png | Bin 0 -> 2383 bytes src/components/Repository/index.js | 68 +++-- src/components/Repository/styles.js | 33 +++ src/components/Search/index.js | 2 +- src/components/Tag/styles.js | 6 +- src/components/UpLinks/index.js | 35 +-- src/components/Versions/index.js | 38 +-- src/history.js | 8 +- src/index.js | 16 +- src/pages/detail/detail.scss | 25 -- src/pages/detail/index.jsx | 87 ------ src/pages/home/index.js | 8 +- src/pages/version/index.js | 29 +- src/router.js | 60 ++--- src/styles/mixins.scss | 5 +- src/utils/__setPublicPath__.js | 2 +- src/utils/api.js | 76 +++--- src/utils/asyncComponent.js | 26 +- src/utils/file-size.js | 5 + src/utils/login.js | 122 ++++----- src/utils/package.js | 31 --- src/utils/styles/colors.js | 3 + src/utils/styles/media.js | 2 +- src/utils/url.js | 8 - src/utils/windows.js | 2 +- 88 files changed, 1302 insertions(+), 1656 deletions(-) create mode 100644 src/components/ActionBar/index.js create mode 100644 src/components/ActionBar/styles.js create mode 100644 src/components/Author/styles.js create mode 100644 src/components/Dist/index.js create mode 100644 src/components/Dist/styles.js create mode 100644 src/components/Engines/img/node.png create mode 100644 src/components/Engines/index.js create mode 100644 src/components/Engines/styles.js create mode 100644 src/components/Icon/img/filebinary.svg create mode 100644 src/components/Icon/img/law.svg create mode 100644 src/components/Icon/img/version.svg create mode 100644 src/components/Install/img/npm.svg create mode 100644 src/components/Install/img/pnpm.svg create mode 100644 src/components/Install/img/yarn.svg create mode 100644 src/components/Install/styles.js delete mode 100644 src/components/License/index.js delete mode 100644 src/components/NoItems/styles.js delete mode 100644 src/components/PackageDetail/index.js delete mode 100644 src/components/PackageDetail/packageDetail.scss delete mode 100644 src/components/PackageSidebar/Module/index.jsx delete mode 100644 src/components/PackageSidebar/Module/style.scss delete mode 100644 src/components/PackageSidebar/ModuleContentPlaceholder/index.jsx delete mode 100644 src/components/PackageSidebar/ModuleContentPlaceholder/style.scss delete mode 100644 src/components/PackageSidebar/index.jsx delete mode 100644 src/components/PackageSidebar/modules/Dependencies/index.jsx delete mode 100644 src/components/PackageSidebar/modules/Dependencies/style.scss delete mode 100644 src/components/PackageSidebar/modules/DistTags/index.jsx delete mode 100644 src/components/PackageSidebar/modules/DistTags/style.scss delete mode 100644 src/components/PackageSidebar/modules/Infos/index.jsx delete mode 100644 src/components/PackageSidebar/modules/Infos/style.scss delete mode 100644 src/components/PackageSidebar/modules/LastSync/index.jsx delete mode 100644 src/components/PackageSidebar/modules/LastSync/style.scss delete mode 100644 src/components/PackageSidebar/modules/Maintainers/MaintainerInfo/index.jsx delete mode 100644 src/components/PackageSidebar/modules/Maintainers/MaintainerInfo/style.scss delete mode 100644 src/components/PackageSidebar/modules/Maintainers/index.jsx delete mode 100644 src/components/PackageSidebar/modules/Maintainers/style.scss delete mode 100644 src/components/PackageSidebar/modules/PeerDependencies/index.jsx create mode 100644 src/components/Repository/img/git.png delete mode 100644 src/pages/detail/detail.scss delete mode 100644 src/pages/detail/index.jsx create mode 100644 src/utils/file-size.js diff --git a/.gitignore b/.gitignore index df43e6d..1058c2f 100755 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. +.idea/ + # dependencies /node_modules /.pnp diff --git a/src/app.js b/src/app.js index 8888930..a546068 100644 --- a/src/app.js +++ b/src/app.js @@ -1,13 +1,17 @@ -import React, {Component, Fragment} from 'react'; +/** + * @prettier + */ + +import React, { Component, Fragment } from 'react'; import isNil from 'lodash/isNil'; import storage from './utils/storage'; -import {makeLogin, isTokenExpire} from './utils/login'; +import { makeLogin, isTokenExpire } from './utils/login'; import Loading from './components/Loading'; import LoginModal from './components/Login'; import Header from './components/Header'; -import {Container, Content} from './components/Layout'; +import { Container, Content } from './components/Layout'; import RouterApp from './router'; import API from './utils/api'; import './styles/typeface-roboto.scss'; @@ -16,7 +20,6 @@ import 'normalize.css'; import Footer from './components/Footer'; export const AppContext = React.createContext(); - export const AppContextProvider = AppContext.Provider; export const AppContextConsumer = AppContext.Consumer; @@ -39,12 +42,29 @@ export default class App extends Component { // eslint-disable-next-line no-unused-vars componentDidUpdate(_, prevState) { - const {isUserLoggedIn} = this.state; + const { isUserLoggedIn } = this.state; if (prevState.isUserLoggedIn !== isUserLoggedIn) { this.loadOnHandler(); } } + render() { + const { isLoading, isUserLoggedIn, packages, logoUrl, user, scope } = this.state; + + return ( + + {isLoading ? ( + + ) : ( + + {this.renderContent()} + + )} + {this.renderLoginModal()} + + ); + } + isUserAlreadyLoggedIn = () => { // checks for token validity const token = storage.getItem('token'); @@ -53,7 +73,7 @@ export default class App extends Component { this.handleLogout(); } else { this.setState({ - user: {username, token}, + user: { username, token }, isUserLoggedIn: true, }); } @@ -76,7 +96,7 @@ export default class App extends Component { } }; - setLoading = (isLoading) => + setLoading = isLoading => this.setState({ isLoading, }); @@ -86,7 +106,7 @@ export default class App extends Component { * Required by:
*/ handleToggleLoginModal = () => { - this.setState((prevState) => ({ + this.setState(prevState => ({ showLoginModal: !prevState.showLoginModal, error: {}, })); @@ -97,7 +117,7 @@ export default class App extends Component { * Required by:
*/ handleDoLogin = async (usernameValue, passwordValue) => { - const {username, token, error} = await makeLogin(usernameValue, passwordValue); + const { username, token, error } = await makeLogin(usernameValue, passwordValue); if (username && token) { this.setLoggedUser(username, token); @@ -123,6 +143,7 @@ export default class App extends Component { showLoginModal: false, // set isUserLoggedIn to true }); }; + /** * Logouts user * Required by:
@@ -136,24 +157,8 @@ export default class App extends Component { }); }; - render() { - const {isLoading, isUserLoggedIn, packages, logoUrl, user, scope} = this.state; - return ( - - {isLoading ? ( - - ) : ( - - {this.renderContent()} - - )} - {this.renderLoginModal()} - - ); - } - renderLoginModal = () => { - const {error, showLoginModal} = this.state; + const { error, showLoginModal } = this.state; return ( { - const {logoUrl, user, scope} = this.state; + const { logoUrl, user: { username } = {}, scope } = this.state; - return
; + return
; }; } diff --git a/src/app.scss b/src/app.scss index b4ba27f..462f8b9 100644 --- a/src/app.scss +++ b/src/app.scss @@ -1,16 +1,16 @@ -@import "./styles/variables"; +@import './styles/variables'; .alertError { - background-color: $red !important; - min-width: inherit !important; + background-color: $red !important; + min-width: inherit !important; } .alertErrorMsg { - display: flex; - align-items: center; + display: flex; + align-items: center; } .alertIcon { - opacity: 0.9; - margin-right: 8px; -} + opacity: 0.9; + margin-right: 8px; +} \ No newline at end of file diff --git a/src/components/ActionBar/index.js b/src/components/ActionBar/index.js new file mode 100644 index 0000000..a1a771a --- /dev/null +++ b/src/components/ActionBar/index.js @@ -0,0 +1,109 @@ +/* eslint-disable react/jsx-max-depth */ +/** + * @prettier + */ + +import React, { Component } from 'react'; + +import { DetailContextConsumer } from '../../pages/version/index'; +import List from '@material-ui/core/List/index'; + +import DownloadIcon from '@material-ui/icons/CloudDownload'; +import BugReportIcon from '@material-ui/icons/BugReport'; +import HomeIcon from '@material-ui/icons/Home'; +import Tooltip from '@material-ui/core/Tooltip/index'; + +import { Fab, ActionListItem } from './styles'; + +const ACTIONS = { + homepage: { + icon: , + title: 'Visit homepage', + }, + issue: { + icon: , + title: 'Open an issue', + }, + tarball: { + icon: , + title: 'Download tarball', + }, +}; + +class ActionBar extends Component { + render() { + return ( + + {context => { + return this.renderActionBar(context); + }} + + ); + } + + renderIconsWithLink(link, component) { + if (!link) { + return null; + } + return ( + + {component} + + ); + } + + renderActionBarListItems = (packageMeta) => { + const { + latest: { + bugs: { + url: issue, + } = {}, + homepage, + dist: { + tarball, + } = {}, + } = {}, + } = packageMeta; + + const actionsMap = { + homepage, + issue, + tarball, + }; + + const renderList = Object.keys(actionsMap).reduce((component, value, key) => { + const link = actionsMap[value]; + if (link) { + const fab = ( + + {ACTIONS[value]['icon']} + + ); + component.push( + + {this.renderIconsWithLink(link, fab)} + + ); + } + return component; + }, []); + + return ( + <> + + {renderList} + + + ); + }; + + renderActionBar = ({ packageMeta = {} }) => { + return ( + + {this.renderActionBarListItems(packageMeta)} + + ); + }; +} + +export default ActionBar; diff --git a/src/components/ActionBar/styles.js b/src/components/ActionBar/styles.js new file mode 100644 index 0000000..2fce31d --- /dev/null +++ b/src/components/ActionBar/styles.js @@ -0,0 +1,24 @@ +/** + * @prettier + */ +import styled from 'react-emotion'; +import { default as MuiFab } from '@material-ui/core/Fab'; +import ListItem from '@material-ui/core/ListItem/index'; + +import colors from '../../utils/styles/colors'; + +export const ActionListItem = styled(ListItem)` + && { + padding-top: 0; + padding-left: 0; + padding-right: 0; + } +`; + +export const Fab = styled(MuiFab)` + && { + background-color: ${colors.primary}; + color: ${colors.white}; + margin-right: 10px; + } +`; diff --git a/src/components/Author/index.js b/src/components/Author/index.js index 825037a..5f26c70 100644 --- a/src/components/Author/index.js +++ b/src/components/Author/index.js @@ -1,49 +1,53 @@ -/* eslint no-unused-vars: 0 */ +/** + * @prettier + */ -import React, {Component, Fragment} from 'react'; +import React, { Component } from 'react'; -import {DetailContextConsumer} from '../../pages/version/index'; -import Card from '@material-ui/core/Card/index'; -import CardContent from '@material-ui/core/CardContent/index'; -import CopyToClipBoard from '../CopyToClipBoard'; -import CardHeader from '@material-ui/core/CardHeader/index'; -import Avatar from '@material-ui/core/Avatar'; -import CardActions from '@material-ui/core/CardActions'; -import Typography from '@material-ui/core/Typography/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 { render() { return ( - {(context) => { + {context => { return this.renderAuthor(context); }} ); } - renderAuthor = ({packageMeta}) => { - const {author} = packageMeta.latest; + renderLinkForMail(email, avatarComponent, packageName, version) { + if (!email) { + return avatarComponent; + } + return ( + + {avatarComponent} + + ); + } + + renderAuthor = ({ packageMeta }) => { + const { author, name: packageName, version } = packageMeta.latest; if (!author) { return null; } + const avatarComponent = ; return ( - - {this.renderAvatar(author)} - - ); - }; - - renderAvatar = ({name, email, url, avatar}) => { - return ( - - - - {name} - - + {'Author'}}> + + {this.renderLinkForMail(author.email, avatarComponent, packageName, version)} + + + ); }; } diff --git a/src/components/Author/styles.js b/src/components/Author/styles.js new file mode 100644 index 0000000..ae02d23 --- /dev/null +++ b/src/components/Author/styles.js @@ -0,0 +1,21 @@ +/** + * @prettier + * @flow + */ + +import styled from 'react-emotion'; +import ListItem from '@material-ui/core/ListItem/index'; +import Typography from '@material-ui/core/Typography/index'; + +export const Heading = styled(Typography)` + && { + font-weight: 700; + text-transform: capitalize; + } +`; +export const AuthorListItem = styled(ListItem)` + && { + padding-left: 0; + padding-right: 0; + } +`; diff --git a/src/components/CopyToClipBoard/index.js b/src/components/CopyToClipBoard/index.js index 513a3d1..0209665 100644 --- a/src/components/CopyToClipBoard/index.js +++ b/src/components/CopyToClipBoard/index.js @@ -7,14 +7,14 @@ import React from 'react'; import FileCopy from '@material-ui/icons/FileCopy'; import Tooltip from '@material-ui/core/Tooltip/index'; -import type {Node} from 'react'; -import {IProps} from './types'; +import type { Node } from 'react'; +import { IProps } from './types'; -import {ClipBoardCopy, ClipBoardCopyText, CopyIcon} from './styles'; -import {copyToClipBoardUtility} from '../../utils/cli-utils'; -import {TEXT} from '../../utils/constants'; +import { ClipBoardCopy, ClipBoardCopyText, CopyIcon } from './styles'; +import { copyToClipBoardUtility } from '../../utils/cli-utils'; +import { TEXT } from '../../utils/constants'; -const CopyToClipBoard = ({text}: IProps): Node => { +const CopyToClipBoard = ({ text, children }: IProps): Node => { const renderToolTipFileCopy = () => ( @@ -22,9 +22,17 @@ const CopyToClipBoard = ({text}: IProps): Node => { ); + + const renderText = children => { + if (children) { + return {children}; + } + + return {text}; + }; return ( - {text} + {renderText(children)} {renderToolTipFileCopy()} ); diff --git a/src/components/CopyToClipBoard/types.js b/src/components/CopyToClipBoard/types.js index 50115e6..36edbed 100644 --- a/src/components/CopyToClipBoard/types.js +++ b/src/components/CopyToClipBoard/types.js @@ -5,4 +5,5 @@ export interface IProps { text: string; + children?: any; } diff --git a/src/components/Dependencies/index.js b/src/components/Dependencies/index.js index 8dce80c..eebb66b 100644 --- a/src/components/Dependencies/index.js +++ b/src/components/Dependencies/index.js @@ -10,7 +10,9 @@ import { withRouter } from 'react-router-dom'; 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 { constructor(props: any) { @@ -26,7 +28,7 @@ class DepDetail extends Component { render() { const { name, version } = this.state; const tagText = `${name}@${version}`; - return ; + return ; } handleOnClick = () => { @@ -34,20 +36,13 @@ class DepDetail extends Component { const { onLoading, history } = this.props; onLoading(); - history.push(`/-/web/version/${name}`); + history.push(`/-/web/detail/${name}`); }; } const WrappDepDetail = withRouter(DepDetail); class DependencyBlock extends Component { - renderTags = (deps: any, enableLoading: any) => - deps.map(dep => { - const [name, version] = dep; - - return ; - }); - render() { const { dependencies, title } = this.props; const deps = Object.entries(dependencies); @@ -59,7 +54,7 @@ class DependencyBlock extends Component { return ( - {title} + {`${title} (${deps.length})`} {this.renderTags(deps, enableLoading)} @@ -68,6 +63,13 @@ class DependencyBlock extends Component { ); } + + renderTags = (deps: any, enableLoading: any) => + deps.map(dep => { + const [name, version] = dep; + + return ; + }); } class Dependencies extends Component { @@ -85,23 +87,29 @@ class Dependencies extends Component { ); } + checkDependencyLength(dependency: Object = {}) { + return Object.keys(dependency).length > 0; + } + // $FlowFixMe renderDependencies({ packageMeta }) { const { latest } = packageMeta; - // console.log('renderDependencies', latest); - const { dependencies, devDependencies, peerDependencies } = latest; - // console.log('dependencies', dependencies); - // console.log('devDependencies', devDependencies); + const { dependencies, devDependencies, peerDependencies, name } = latest; - return ( - - - {dependencies && } - {devDependencies && } - {peerDependencies && } - - - ); + 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; + }, []); + + if (dependencyList.length) { + return {dependencyList}; + } + return ; } } diff --git a/src/components/Dependencies/styles.js b/src/components/Dependencies/styles.js index 69c346e..3a55ed8 100644 --- a/src/components/Dependencies/styles.js +++ b/src/components/Dependencies/styles.js @@ -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; } `; diff --git a/src/components/DetailContainer/index.js b/src/components/DetailContainer/index.js index 708d4e3..d01514e 100644 --- a/src/components/DetailContainer/index.js +++ b/src/components/DetailContainer/index.js @@ -30,25 +30,31 @@ class DetailContainer extends Component { ); } + handleChange = (event: any, tabPosition: number) => { + event.preventDefault(); + this.setState({ tabPosition }); + }; + // $FlowFixMe renderTabs = ({ readMe }) => { const { tabPosition } = this.state; return ( - - - - - - - + <> + + + + + + +
{tabPosition === 0 && this.renderReadme(readMe)} {tabPosition === 1 && } {tabPosition === 2 && } {tabPosition === 3 && }
-
+ ); }; @@ -57,11 +63,6 @@ class DetailContainer extends Component { return ; }; - - handleChange = (event: any, tabPosition: number) => { - event.preventDefault(); - this.setState({ tabPosition }); - }; } export default DetailContainer; diff --git a/src/components/DetailSidebar/index.js b/src/components/DetailSidebar/index.js index d31fcd3..eb7e42a 100644 --- a/src/components/DetailSidebar/index.js +++ b/src/components/DetailSidebar/index.js @@ -1,17 +1,23 @@ import React, {Component} from 'react'; -import { DetailContextConsumer } from '../../pages/version/index'; -import Typography from '@material-ui/core/Typography/index'; -import Grid from '@material-ui/core/Grid/index'; +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 Install from '../Install'; -import { Content } from './styles'; -import Authors from '../Author'; -import License from '../License'; -import Repository from '../Repository'; +import ActtionBar from '../ActionBar'; +import Author from '../Author'; import Developers from '../Developers'; +import Dist from '../Dist'; +import Engine from '../Engines'; +import Install from '../Install'; +import Repository from '../Repository'; -class DetailSidebar extends Component { + +import { DetailContextConsumer } from '../../pages/version/index'; + +import { TitleListItem, TitleListItemText } from './styles'; + +class DetailSidebar extends Component { render() { return ( @@ -20,43 +26,36 @@ class DetailSidebar extends Component { ); }; - renderSideBar = ({packageMeta, packageName}) => { + renderSideBar = ({packageName, packageMeta}) => { return ( - - - +
+ + {this.renderTitle(packageName, packageMeta)} - - + {this.renderActionBar()} {this.renderCopyCLI()} - - - {this.renderSecondLevel(8)} - - - {this.renderMaintainers()} - - - {this.renderContributors()} - - {this.renderRepository()} - - - + {this.renderEngine()} + {this.renderDist()} + {this.renderAuthor()} + {this.renderMaintainers()} + {this.renderContributors()} + + +
); } renderTitle = (packageName, packageMeta) => { return ( - <> - - {packageName} - - - {packageMeta.latest.description} - - + + + {packageName}} + secondary={packageMeta.latest.description} + /> + + ); } @@ -72,31 +71,25 @@ class DetailSidebar extends Component { return ; } - renderSecondLevel = (spacing = 24) => { - return ( - - {this.renderAuthor()} - - ); - } - renderRepository = () => { return ; } renderAuthor = () => { - return ( - <> - - - - - - - - ); + return ; + } + + renderEngine = () => { + return ; + } + + renderDist = () => { + return ; + } + + renderActionBar = () => { + return ; } } - export default DetailSidebar; diff --git a/src/components/DetailSidebar/styles.js b/src/components/DetailSidebar/styles.js index 0cdcde2..bda5acc 100644 --- a/src/components/DetailSidebar/styles.js +++ b/src/components/DetailSidebar/styles.js @@ -4,11 +4,32 @@ */ 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'; -export const Content = styled.div` +export const TitleListItem = styled(ListItem)` && { - padding: 10px; - background-color: ${colors.white}; + padding-left: 0; + padding-right: 0; + padding-bottom: 0; + } +`; + +export const TitleListItemText = styled(ListItemText)` + && { + padding-left: 0; + padding-right: 0; + padding-top: 8px; + } +`; + +export const TitleAvatar = styled(Avatar)` + && { + color: ${colors.greySuperLight}; + background-color: ${colors.primary}; + text-transform: capitalize; } `; diff --git a/src/components/Developers/index.js b/src/components/Developers/index.js index d311bc2..31aad5f 100644 --- a/src/components/Developers/index.js +++ b/src/components/Developers/index.js @@ -1,11 +1,12 @@ import React, {Component} from 'react'; -import { DetailContextConsumer } from '../../pages/version'; -import Card from '@material-ui/core/Card'; import Avatar from '@material-ui/core/Avatar'; import Tooltip from '@material-ui/core/Tooltip'; import Add from '@material-ui/icons/Add'; -import { Details, Heading, Content, CardContent, Fab } from './styles'; + +import { DetailContextConsumer } from '../../pages/version'; + +import { Details, Heading, Content, Fab } from './styles'; interface Props { type: 'contributors' | 'maintainers' @@ -23,44 +24,59 @@ class Developers extends Component { 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); }}
); }; - renderDevelopers = (developers) => { + handleLoadMore = () => { + this.setState((prev) => ({ visibleDevs: prev.visibleDevs + 6 })); + } + + renderDevelopers = (developers, packageMeta) => { const { type } = this.props; const { visibleDevs } = this.state; return ( - - - {type} - - {developers.slice(0, visibleDevs).map(developer => ( -
{this.renderDeveloperDetails(developer)}
- ))} - {visibleDevs < developers.length && - - } -
-
-
+ <> + {type} + + {developers.slice(0, visibleDevs).map(developer => ( +
{this.renderDeveloperDetails(developer, packageMeta)}
+ ))} + {visibleDevs < developers.length && + + } +
+ ); } - renderDeveloperDetails= ({name, avatar }) => { + renderLinkForMail(email, avatarComponent, packageName, version) { + if(!email) { + return avatarComponent; + } + return ( + + {avatarComponent} + + ); + } + + renderDeveloperDetails = ({ name, avatar, email }, packageMeta) => { + const { + name: packageName, + version, + } = packageMeta.latest; + + const avatarComponent = ; return ( - + {this.renderLinkForMail(email, avatarComponent, packageName, version)} ); } - handleLoadMore = () => { - this.setState((prev) => ({ visibleDevs: prev.visibleDevs + 6 })); - } - } diff --git a/src/components/Developers/styles.js b/src/components/Developers/styles.js index 3c89c0f..ef8afcd 100644 --- a/src/components/Developers/styles.js +++ b/src/components/Developers/styles.js @@ -7,8 +7,6 @@ import Typography from '@material-ui/core/Typography'; import { default as MuiFab } from '@material-ui/core/Fab'; import colors from '../../utils/styles/colors'; -import { default as MuiCardContent } from '@material-ui/core/CardContent/index'; - export const Details = styled('span')` display: flex; flex-direction: column; @@ -16,7 +14,7 @@ export const Details = styled('span')` `; export const Content = styled('div')` - margin: -5px; + margin: 10px 0 10px 0; display: flex; flex-wrap: wrap; > * { @@ -24,12 +22,6 @@ export const Content = styled('div')` } `; -export const CardContent = styled(MuiCardContent)` - && { - padding-bottom: 20px; - } -`; - export const Heading = styled(Typography)` && { font-weight: 700; diff --git a/src/components/Dist/index.js b/src/components/Dist/index.js new file mode 100644 index 0000000..27463a6 --- /dev/null +++ b/src/components/Dist/index.js @@ -0,0 +1,59 @@ +/** + * @prettier + */ + +/* eslint-disable */ +import React, { Component } from 'react'; +import List from '@material-ui/core/List/index'; + +import { DetailContextConsumer } from '../../pages/version/index'; + +import { Heading, DistListItem, DistChips, DownloadButton } from './styles'; +import fileSizeSI from '../../utils/file-size'; + +class Dist extends Component { + render() { + return ( + + {context => { + return this.renderDist(context); + }} + + ); + } + + renderChips(dist, license) { + const distDict = { + 'file-count': dist.fileCount, + size: dist.unpackedSize && fileSizeSI(dist.unpackedSize), + license, + }; + + const chipsList = Object.keys(distDict).reduce((componentList, title, key) => { + const value = distDict[title]; + if (value) { + const label = ( + + {title.split('-').join(' ')}: {value} + + ); + componentList.push(); + } + return componentList; + }, []); + + return chipsList; + } + + renderDist = ({ packageMeta }) => { + const { dist = {}, license } = packageMeta.latest; + + return ( + {'Latest Distribution'}}> + {this.renderChips(dist, license)} + + ); + }; +} + +export default Dist; diff --git a/src/components/Dist/styles.js b/src/components/Dist/styles.js new file mode 100644 index 0000000..82c65d4 --- /dev/null +++ b/src/components/Dist/styles.js @@ -0,0 +1,39 @@ +/** + * @prettier + */ + +import styled from 'react-emotion'; +import { default as MuiFab } from '@material-ui/core/Fab/index'; +import Chip from '@material-ui/core/Chip/index'; +import ListItem from '@material-ui/core/ListItem/index'; +import Typography from '@material-ui/core/Typography/index'; + +import colors from '../../utils/styles/colors'; + +export const Heading = styled(Typography)` + && { + font-weight: 700; + text-transform: capitalize; + } +`; + +export const DistListItem = styled(ListItem)` + && { + padding-left: 0; + padding-right: 0; + } +`; + +export const DistChips = styled(Chip)` + && { + margin-right: 5px; + text-transform: capitalize; + } +`; + +export const DownloadButton = styled(MuiFab)` + && { + background-color: ${colors.primary}; + color: ${colors.white}; + } +`; diff --git a/src/components/Engines/img/node.png b/src/components/Engines/img/node.png new file mode 100644 index 0000000000000000000000000000000000000000..e1412ad02c02f23166eb68e99623be230088974c GIT binary patch literal 27565 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, + 'NPM-version': , +} + +class Engine extends Component { + render() { + return ( + + {(context) => { + return this.renderEngine(context); + }} + + ); + }; + + renderEngine = ({packageMeta}) => { + const { engines } = packageMeta.latest; + if (!engines) { + return null; + } + + const engineDict = { + 'node-JS': engines.node, + 'NPM-version': engines.npm + } + + const items = Object.keys(engineDict).reduce((markup, text, key) => { + const heading = engineDict[text] + if (heading){ + markup.push( + + {this.renderListItems(heading, text)} + + ); + } + return markup; + }, []); + + if (items.length < 1) { + return null; + } + + return ( + + {items} + + ); + } + + renderListItems = (heading, text) => { + return ( + {text.split('-').join(' ')}}> + + { ICONS[text] } + + + + ); + } +} + +export default Engine; diff --git a/src/components/Engines/styles.js b/src/components/Engines/styles.js new file mode 100644 index 0000000..7905dcb --- /dev/null +++ b/src/components/Engines/styles.js @@ -0,0 +1,21 @@ +/** + * @prettier + * @flow + */ + +import styled from 'react-emotion'; +import ListItem from '@material-ui/core/ListItem/index'; +import Typography from '@material-ui/core/Typography/index'; + +export const Heading = styled(Typography)` + && { + font-weight: 700; + text-transform: capitalize; + } +`; + +export const EngineListItem = styled(ListItem)` + && { + padding-left: 0; + } +`; diff --git a/src/components/Footer/index.js b/src/components/Footer/index.js index f60901e..b8ad369 100644 --- a/src/components/Footer/index.js +++ b/src/components/Footer/index.js @@ -3,53 +3,35 @@ * @flow */ -import React from "react"; -import type { Element } from "react"; +import React from 'react'; +import type { Element } from 'react'; -import { version } from "../../../package.json"; -import { - Wrapper, - Left, - Right, - Earth, - Flags, - Love, - Flag, - Logo, - Inner, - ToolTip -} from "./styles"; -import { goToVerdaccioWebsite } from "../../utils/windows.js"; +import { version } from '../../../../package.json'; +import { Wrapper, Left, Right, Earth, Flags, Love, Flag, Logo, Inner, ToolTip } from './styles'; +import { goToVerdaccioWebsite } from '../../utils/windows.js'; const renderTooltip = () => ( - + - - - - - - - + + + + + + ); -const POWERED_LABEL = "Powered by"; -const MADEWITH_LABEL = " Made with"; -const ON_LABEL = "on"; -const HEARTH_EMOJI = "♥"; +const POWERED_LABEL = 'Powered by'; +const MADEWITH_LABEL = ' Made with'; +const ON_LABEL = 'on'; +const HEARTH_EMOJI = '♥'; const renderRight = () => ( {POWERED_LABEL} - + {`/ ${version}`} ); diff --git a/src/components/Header/index.js b/src/components/Header/index.js index 1b8c8bf..f1f1248 100644 --- a/src/components/Header/index.js +++ b/src/components/Header/index.js @@ -127,7 +127,7 @@ class Header extends Component { renderLogo = (): Node => { const { logo } = this.props; - if (logo) { + if (logo !== '') { return {'logo'}; } else { return ; diff --git a/src/components/Help/index.js b/src/components/Help/index.js index 49b679a..d553135 100644 --- a/src/components/Help/index.js +++ b/src/components/Help/index.js @@ -35,8 +35,8 @@ const Help = (): Node => { {'To publish your first package just:'} - {renderHeadingClipboardSegments('1. Login', `$ npm adduser --registry ${registryUrl}`)} - {renderHeadingClipboardSegments('2. Publish', `$ npm publish --registry ${registryUrl}`)} + {renderHeadingClipboardSegments('1. Login', `npm adduser --registry ${registryUrl}`)} + {renderHeadingClipboardSegments('2. Publish', `npm publish --registry ${registryUrl}`)} {'3. Refresh this page.'} diff --git a/src/components/Icon/img/filebinary.svg b/src/components/Icon/img/filebinary.svg new file mode 100644 index 0000000..f891b36 --- /dev/null +++ b/src/components/Icon/img/filebinary.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/components/Icon/img/law.svg b/src/components/Icon/img/law.svg new file mode 100644 index 0000000..499148d --- /dev/null +++ b/src/components/Icon/img/law.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/src/components/Icon/img/version.svg b/src/components/Icon/img/version.svg new file mode 100644 index 0000000..6a0eb92 --- /dev/null +++ b/src/components/Icon/img/version.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/components/Icon/index.js b/src/components/Icon/index.js index c44c861..ae78da3 100644 --- a/src/components/Icon/index.js +++ b/src/components/Icon/index.js @@ -19,8 +19,11 @@ import austria from './img/austria.svg'; import spain from './img/spain.svg'; import earth from './img/earth.svg'; import verdaccio from './img/verdaccio.svg'; +import filebinary from './img/filebinary.svg'; +import law from './img/law.svg'; import license from './img/license.svg'; import time from './img/time.svg'; +import version from './img/version.svg'; export const Icons: $Shape = { // flags @@ -33,8 +36,12 @@ export const Icons: $Shape = { austria, earth, verdaccio, + // other icons + filebinary, + law, license, time, + version, }; const Icon = ({ className, name, size = 'sm', img = false, pointer = false, ...props }: IProps): Node => { diff --git a/src/components/Icon/styles.js b/src/components/Icon/styles.js index 0454d4c..fd3455f 100644 --- a/src/components/Icon/styles.js +++ b/src/components/Icon/styles.js @@ -21,7 +21,7 @@ const getSize = (size: string) => { default: return ` width: 14px; - height: 14px; + height: 16px; `; } }; diff --git a/src/components/Icon/types.js b/src/components/Icon/types.js index 5301ddd..5b2adf6 100644 --- a/src/components/Icon/types.js +++ b/src/components/Icon/types.js @@ -17,6 +17,9 @@ export interface IIconsMap { verdaccio: string; license: string; time: string; + law: string; + version: string; + filebinary: string; [key: string]: string; } diff --git a/src/components/Install/img/npm.svg b/src/components/Install/img/npm.svg new file mode 100644 index 0000000..5df8177 --- /dev/null +++ b/src/components/Install/img/npm.svg @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/src/components/Install/img/pnpm.svg b/src/components/Install/img/pnpm.svg new file mode 100644 index 0000000..b3549a4 --- /dev/null +++ b/src/components/Install/img/pnpm.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/Install/img/yarn.svg b/src/components/Install/img/yarn.svg new file mode 100644 index 0000000..86edb18 --- /dev/null +++ b/src/components/Install/img/yarn.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/Install/index.js b/src/components/Install/index.js index 44a16d2..e28d1f5 100644 --- a/src/components/Install/index.js +++ b/src/components/Install/index.js @@ -1,46 +1,58 @@ -import React, {Component} from 'react'; +/** + * @prettier + */ + +import React, { Component } from 'react'; + +import List from '@material-ui/core/List/index'; +import ListItemText from '@material-ui/core/ListItemText/index'; import { DetailContextConsumer } from '../../pages/version/index'; -import Card from '@material-ui/core/Card/index'; -import CardContent from '@material-ui/core/CardContent/index'; import CopyToClipBoard from '../CopyToClipBoard'; -import Button from '@material-ui/core/Button'; -import CardActions from '@material-ui/core/CardActions'; -class Install extends Component { +import { Heading, InstallItem, PackageMangerAvatar } from './styles'; +// logos of package managers +import npm from './img/npm.svg'; +import pnpm from './img/pnpm.svg'; +import yarn from './img/yarn.svg'; + +class Install extends Component { render() { return ( - {(context) => { + {context => { return this.renderCopyCLI(context); }} ); + } + + renderCopyCLI = ({ packageName }) => { + return ( + <> + {'Installation'}}>{this.renderListItems(packageName)} + + ); }; - renderCopyCLI = ({packageName}) => { + renderListItems = packageName => { return ( - - - - - - - {this.renderDownloadButton()} - - - + <> + + + } secondary={'Install using NPM'} /> + + + + } secondary={'Install using Yarn'} /> + + + + } secondary={'Install using PNPM'} /> + + ); - } - - renderDownloadButton = () => { - return ( - - ); - } + }; } - export default Install; diff --git a/src/components/Install/styles.js b/src/components/Install/styles.js new file mode 100644 index 0000000..654368d --- /dev/null +++ b/src/components/Install/styles.js @@ -0,0 +1,28 @@ +/** + * @prettier + * @flow + */ + +import styled from 'react-emotion'; +import Typography from '@material-ui/core/Typography/index'; +import ListItem from '@material-ui/core/ListItem/index'; +import Avatar from '@material-ui/core/Avatar/index'; + +export const Heading = styled(Typography)` + && { + font-weight: 700; + text-transform: capitalize; + } +`; + +export const InstallItem = styled(ListItem)` + && { + padding: 0; + } +`; + +export const PackageMangerAvatar = styled(Avatar)` + && { + border-radius: 0px; + } +`; diff --git a/src/components/License/index.js b/src/components/License/index.js deleted file mode 100644 index f7c3c4c..0000000 --- a/src/components/License/index.js +++ /dev/null @@ -1,51 +0,0 @@ -/* eslint no-unused-vars: 0 */ - -import React, {Component, Fragment} from 'react'; - -import { DetailContextConsumer } from '../../pages/version/index'; -import Card from '@material-ui/core/Card/index'; -import CardContent from '@material-ui/core/CardContent/index'; -import Avatar from '@material-ui/core/Avatar'; -import Notes from '@material-ui/icons/Notes'; -import Typography from "@material-ui/core/Typography/index"; - -class License extends Component { - render() { - return ( - - {(context) => { - return this.renderAuthor(context); - }} - - ); - }; - - renderAuthor = ({packageMeta}) => { - const { license } = packageMeta.latest; - if (!license) { - return null; - } - - return ( - - - {this.renderLicense(license)} - - - ); - } - - renderLicense = (license) => { - return ( - - - - {license} - - - ); - } -} - - -export default License; diff --git a/src/components/NoItems/index.js b/src/components/NoItems/index.js index 1e48a91..e8fd6e5 100644 --- a/src/components/NoItems/index.js +++ b/src/components/NoItems/index.js @@ -4,13 +4,14 @@ */ import React from 'react'; +import Typography from '@material-ui/core/Typography/index'; + import { IProps } from './types'; -import { Wrapper } from './styles'; const NoItems = ({ text }: IProps) => ( - -

{text}

-
+ + {text} + ); export default NoItems; diff --git a/src/components/NoItems/styles.js b/src/components/NoItems/styles.js deleted file mode 100644 index 1a0085d..0000000 --- a/src/components/NoItems/styles.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @prettier - * @flow - */ - -import styled from 'react-emotion'; - -export const Wrapper = styled.div` - && { - margin: 5em 0; - } -`; diff --git a/src/components/NotFound/index.js b/src/components/NotFound/index.js index 2d7b82a..39bf395 100644 --- a/src/components/NotFound/index.js +++ b/src/components/NotFound/index.js @@ -10,6 +10,8 @@ import Typography from '@material-ui/core/Typography/index'; import { Wrapper, Inner, EmptyPackage, Heading, Card, List } from './styles'; import PackageImg from './img/package.svg'; +export const NOT_FOUND_TEXT = "Sorry, we couldn't find it..."; + // eslint-disable-next-line react/prop-types const NotFound = ({ history, width }) => { const handleGoTo = to => () => { @@ -42,7 +44,9 @@ const NotFound = ({ history, width }) => { - {"Sorry, we couldn't find it..."} + + {NOT_FOUND_TEXT} + {renderSubTitle()} {renderList()} diff --git a/src/components/Package/index.js b/src/components/Package/index.js index a2456db..6dbb45a 100644 --- a/src/components/Package/index.js +++ b/src/components/Package/index.js @@ -2,104 +2,160 @@ * @prettier * @flow */ - import React from 'react'; import type { Element } from 'react'; -import { spacing } from '../../utils/styles/mixings'; + +import BugReport from '@material-ui/icons/BugReport'; +import Grid from '@material-ui/core/Grid/index'; +import HomeIcon from '@material-ui/icons/Home'; +import ListItem from '@material-ui/core/ListItem/index'; +import Tooltip from '@material-ui/core/Tooltip/index'; import Tag from '../Tag'; +import fileSizeSI from '../../utils/file-size'; import { formatDate, formatDateDistance } from '../../utils/package'; - import { IProps } from './types'; + import { - WrapperLink, - Header, - MainInfo, - Name, - Version, - Overview, - Published, - OverviewItem, - Description, - Icon, - Text, - Details, - Avatar, Author, - Field, - Content, - Footer, + Avatar, + Description, + Details, + GridRightAligned, + Icon, + IconButton, + OverviewItem, + PackageList, + PackageListItem, + PackageListItemText, + PackageTitle, + Published, + TagContainer, + Text, + WrapperLink, } from './styles'; -const getInitialsName = (name: string) => - name - .split(' ') - .reduce((accumulator, currentValue) => accumulator.charAt(0) + currentValue.charAt(0), '') - .toUpperCase(); +const Package = ({ + author: { name: authorName, avatar: authorAvatar }, + bugs: { url } = {}, + description, + dist: { unpackedSize } = {}, + homepage, + keywords = [], + license, + name: packageName, + time, + version, +}: IProps): Element => { + // + const renderVersionInfo = () => + version && ( + + + {`v${version}`} + + ); -const Package = ({ name: label, version, time, author: { name, avatar }, description, license, keywords = [] }: IProps): Element => { - const renderMainInfo = () => ( - - {label} - {`v${version}`} - - ); + const renderAuthorInfo = () => + authorName && ( + + +
+ +
+
+ ); - const renderAuthorInfo = () => ( - - - {!avatar && getInitialsName(name)} - -
- -
-
- ); + const renderFileSize = () => + unpackedSize && ( + + + {fileSizeSI(unpackedSize)} + + ); const renderLicenseInfo = () => license && ( - + {license} ); - const renderPublishedInfo = () => ( - - - {`Published on ${formatDate(time)} •`} - {`${formatDateDistance(time)} ago`} - - ); - - const renderDescription = () => - description && ( - - {description} - + const renderPublishedInfo = () => + time && ( + + + {`Published on ${formatDate(time)} •`} + {`${formatDateDistance(time)} ago`} + ); + const renderHomePageLink = () => + homepage && ( + + + + {/* eslint-disable-next-line react/jsx-max-depth */} + + + + + ); + + const renderBugsLink = () => + url && ( + + + + {/* eslint-disable-next-line react/jsx-max-depth */} + + + + + ); + + const renderPrimaryComponent = () => { + return ( + + + + {/* eslint-disable-next-line react/jsx-max-depth */} + {packageName} + + + + {renderHomePageLink()} + {renderBugsLink()} + + + ); + }; + + const renderSecondaryComponent = () => { + const tags = keywords.sort().map((keyword, index) => {keyword}); + return ( + <> + {description} + {tags.length > 0 && {tags}} + + ); + }; + return ( - -
- {renderMainInfo()} - - {renderLicenseInfo()} - {renderPublishedInfo()} - -
- - {renderAuthorInfo()} - {renderDescription()} - - {keywords.length > 0 && ( -
- {keywords.sort().map((keyword, index) => ( - {keyword} - ))} -
- )} -
+ + + + + + {renderAuthorInfo()} + {renderVersionInfo()} + {renderPublishedInfo()} + {renderFileSize()} + {renderLicenseInfo()} + + ); }; + export default Package; diff --git a/src/components/Package/styles.js b/src/components/Package/styles.js index 6390f07..eaa4860 100644 --- a/src/components/Package/styles.js +++ b/src/components/Package/styles.js @@ -3,126 +3,68 @@ * @flow */ -import styled, { css } from 'react-emotion'; +import styled from 'react-emotion'; import { Link } from 'react-router-dom'; -import { default as Photo } from '@material-ui/core/Avatar'; -import { default as Ico } from '../Icon'; -import mq from '../../utils/styles/media'; -import { ellipsis } from '../../utils/styles/mixings'; -import colors from '../../utils/styles/colors'; +import Grid from '@material-ui/core/Grid/index'; +import List from '@material-ui/core/List/index'; +import ListItem from '@material-ui/core/ListItem/index'; +import ListItemText from '@material-ui/core/ListItemText/index'; +import MuiIconButton from '@material-ui/core/IconButton/index'; +import Photo from '@material-ui/core/Avatar'; +import Typography from '@material-ui/core/Typography/index'; +import { breakpoints } from '../../utils/styles/media'; +import Ico from '../Icon'; import Label from '../Label'; - -// HEADER -export const Header = styled.div` - && { - display: flex; - flex-direction: column; - padding: 0 0 5px 0; - } -`; - -export const Name = styled.span` - && { - ${ellipsis('50%')}; - } -`; - -export const MainInfo = styled.span` - && { - font-size: 16px; - font-weight: 600; - line-height: 30px; - flex: 1; - color: #3a8bff; - padding: 0 10px 0 0; - overflow: hidden; - display: flex; - align-items: center; - :hover { - ${Name} { - text-decoration: underline; - } - } - } -`; +import colors from '../../utils/styles/colors'; export const OverviewItem = styled.span` && { display: flex; align-items: center; - margin: 0 0 5px 0; - color: ${colors.greyLight}; - } -`; - -export const Overview = styled.span` - && { - position: relative; - display: flex; - flex-direction: column; - } -`; - -export const Version = styled.span` - && { + margin: 0 0 0 16px; + color: ${colors.greyLight2}; font-size: 12px; - padding: 0 0 0 10px; - margin: 0 0 0 5px; - color: #9f9f9f; - position: relative; - ${ellipsis('100%')}; - :before { - content: '•'; - position: absolute; - left: 0; + @media (max-width: ${breakpoints.medium}px) { + &:nth-child(3) { + display: none; + } + } + @media (max-width: ${breakpoints.small}px) { + &:nth-child(4) { + display: none; + } } } `; export const Icon = styled(Ico)` && { - margin: 1px 5px 0 0; - fill: ${colors.greyLight}; + margin: 2px 10px 0px 0; + fill: ${colors.greyLight2}; } `; export const Published = styled.span` && { - display: none; - color: ${colors.greyLight}; - ${({ modifiers }) => modifiers}; - } -`; - -// Content -export const Field = styled.div` - && { - padding: 0 0 5px 0; - } -`; - -export const Content = styled.div` - && { - ${Field} { - :last-child { - padding: 0; - } - } + color: ${colors.greyLight2}; + margin: 0px 5px 0px 0px; } `; export const Text = styled(Label)` && { - color: #908ba1; + font-size: 12px; + font-weight: 500; + color: ${colors.greyLight2}; } `; export const Details = styled.span` && { margin-left: 5px; - line-height: 14px; + line-height: 1.5; display: flex; flex-direction: column; } @@ -137,63 +79,88 @@ export const Author = styled.div` export const Avatar = styled(Photo)` && { - width: 30px; - height: 30px; - background: #4b5e40; - font-size: 15px; + width: 20px; + height: 20px; } `; -export const Description = styled.div` - && { - margin: 5px 0; - } -`; - -// Footer -export const Footer = styled.div` - && { - display: none; - padding: 5px 0 0 0; - } -`; - -// Container export const WrapperLink = styled(Link)` && { - font-size: 12px; - background-color: white; - margin: 0 0 15px 0; - transition: box-shadow 0.15s; - box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.15); - border-radius: 3px; - padding: 10px; text-decoration: none; - display: block; - color: #2f273c; - ${mq.medium(css` - ${Header} { - flex-direction: row; - justify-content: space-between; - align-items: center; - } - ${OverviewItem} { - margin: 0 0 0 10px; - } - ${Overview} { - flex-direction: row; - ${OverviewItem} { - :first-child { - margin: 0; - } - } - } - ${Footer} { - display: block; - } - ${Published} { - display: inline-block; - } - `)}; } `; + +export const PackageTitle = styled.span` + && { + font-weight: 600; + font-size: 20px; + display: block; + margin-bottom: 12px; + color: ${colors.eclipse}; + cursor: pointer; + + &:hover { + color: ${colors.black}; + } + + @media (max-width: ${breakpoints.small}px) { + font-size: 14px; + margin-bottom: 8px; + } + } +`; + +export const GridRightAligned = styled(Grid)` + && { + text-align: right; + } +`; + +export const PackageList = styled(List)` + && { + padding: 12px 0 12px 0; + + &:hover { + background-color: ${colors.greyLight3}; + } + } +`; + +export const IconButton = styled(MuiIconButton)` + && { + padding: 6px; + + svg { + font-size: 16px; + } + } +`; + +export const TagContainer = styled.span` + && { + margin-top: 8px; + margin-bottom: 12px; + display: block; + @media (max-width: ${breakpoints.medium}px) { + display: none; + } + } +`; + +export const PackageListItem = styled(ListItem)` + && { + padding-top: 0; + } +`; + +export const PackageListItemText = styled(ListItemText)` + && { + padding-right: 0; + } +`; + +export const Description = styled(Typography)` + color: ${colors.greyDark2}; + font-size: 14px; + padding-right: 0; +`; diff --git a/src/components/Package/types.js b/src/components/Package/types.js index f39ea33..365a159 100644 --- a/src/components/Package/types.js +++ b/src/components/Package/types.js @@ -11,6 +11,9 @@ export interface IProps { description?: string; keywords?: string[]; license?: string; + homepage: string; + bugs: IBugs; + dist: IDist; } export interface IAuthor { @@ -18,3 +21,10 @@ export interface IAuthor { avatar: string; email: string; } + +export interface IBugs { + url: string; +} +export interface IDist { + unpackedSize: number; +} diff --git a/src/components/PackageDetail/index.js b/src/components/PackageDetail/index.js deleted file mode 100644 index 493e98f..0000000 --- a/src/components/PackageDetail/index.js +++ /dev/null @@ -1,31 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import isNil from 'lodash/isNil'; - -import Readme from '../Readme'; - -import classes from './packageDetail.scss'; - -const displayState = (description) => { - return !isNil(description) ? : ''; -}; - -const PackageDetail = ({packageName, readMe}) => { - return ( -
-

- {packageName} -

-
- {displayState(readMe)} -
-
- ); -}; - -PackageDetail.propTypes = { - readMe: PropTypes.string, - packageName: PropTypes.string.isRequired, -}; - -export default PackageDetail; diff --git a/src/components/PackageDetail/packageDetail.scss b/src/components/PackageDetail/packageDetail.scss deleted file mode 100644 index c918115..0000000 --- a/src/components/PackageDetail/packageDetail.scss +++ /dev/null @@ -1,16 +0,0 @@ -@import '../../styles/variables'; -@import '../../styles/mixins'; - -.pkgDetail { - .title { - font-size: $font-size-xxl; - font-weight: $font-weight-semibold; - margin: 0 0 40px; - padding-bottom: 5px; - @include border-bottom-default($greyGainsboro); - } - - .readme { - margin-bottom: 5em; - } -} diff --git a/src/components/PackageList/index.js b/src/components/PackageList/index.js index 70d66e6..db869eb 100644 --- a/src/components/PackageList/index.js +++ b/src/components/PackageList/index.js @@ -1,9 +1,11 @@ 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'; @@ -12,28 +14,6 @@ export default class PackageList extends React.Component { packages: PropTypes.array, }; - renderPackages = () => { - return ( - - {this.renderList()} - - ); - } - - renderList = () => { - const { packages } = this.props; - return ( - packages.map((pkg, i) => { - const { name, version, description, time, keywords } = pkg; - const author = formatAuthor(pkg.author); - const license = formatLicense(pkg.license); - return ( - - ); - }) - ); - } - render() { return (
@@ -46,7 +26,32 @@ export default class PackageList extends React.Component { hasPackages() { const {packages} = this.props; - return packages.length > 0; } + + renderPackages = () => { + return ( + + {this.renderList()} + + ); + } + + renderList = () => { + const { packages } = this.props; + return ( + packages.map((pkg, i) => { + const { name, version, description, time, keywords, dist, homepage, bugs } = pkg; + const author = pkg.author; + // TODO: move format license to API side. + const license = formatLicense(pkg.license); + return ( + + {i !== 0 && } + + + ); + }) + ); + } } diff --git a/src/components/PackageSidebar/Module/index.jsx b/src/components/PackageSidebar/Module/index.jsx deleted file mode 100644 index ba2409d..0000000 --- a/src/components/PackageSidebar/Module/index.jsx +++ /dev/null @@ -1,25 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -import classes from './style.scss'; - -export default function Module({title, description, children, className}) { - return ( -
-

- {title} - {description && {description}} -

-
- {children} -
-
- ); -} - -Module.propTypes = { - title: PropTypes.string.isRequired, - description: PropTypes.string, - children: PropTypes.any.isRequired, - className: PropTypes.string, -}; diff --git a/src/components/PackageSidebar/Module/style.scss b/src/components/PackageSidebar/Module/style.scss deleted file mode 100644 index 80164c7..0000000 --- a/src/components/PackageSidebar/Module/style.scss +++ /dev/null @@ -1,24 +0,0 @@ -@import '../../../styles/variables'; -@import '../../../styles/mixins'; - -.module { - - margin-bottom: 10px; - - .moduleTitle { - display: flex; - align-items: flex-end; - font-size: $font-size-lg; - margin: 0 0 10px; - padding: 5px 0; - font-weight: $font-weight-semibold; - @include border-bottom-default($greyGainsboro); - - span { // description - font-size: $font-size-sm; - color: $greyChateau; - margin-left: auto; - font-weight: $font-weight-light; - } - } -} diff --git a/src/components/PackageSidebar/ModuleContentPlaceholder/index.jsx b/src/components/PackageSidebar/ModuleContentPlaceholder/index.jsx deleted file mode 100644 index 4df6744..0000000 --- a/src/components/PackageSidebar/ModuleContentPlaceholder/index.jsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -import classes from './style.scss'; - -export default function ModuleContentPlaceholder({text}) { - return

{text}

; -} -ModuleContentPlaceholder.propTypes = { - text: PropTypes.string.isRequired, -}; diff --git a/src/components/PackageSidebar/ModuleContentPlaceholder/style.scss b/src/components/PackageSidebar/ModuleContentPlaceholder/style.scss deleted file mode 100644 index 7980ba7..0000000 --- a/src/components/PackageSidebar/ModuleContentPlaceholder/style.scss +++ /dev/null @@ -1,8 +0,0 @@ -@import '../../../styles/variables'; - -.emptyPlaceholder { - text-align: center; - margin: 20px 0; - font-size: $font-size-base; - color: $greyChateau; -} diff --git a/src/components/PackageSidebar/index.jsx b/src/components/PackageSidebar/index.jsx deleted file mode 100644 index 19db617..0000000 --- a/src/components/PackageSidebar/index.jsx +++ /dev/null @@ -1,104 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import get from 'lodash/get'; -import LastSync from './modules/LastSync'; -import DistTags from './modules/DistTags'; -import Maintainers from './modules/Maintainers'; -import Dependencies from './modules/Dependencies'; -import PeerDependencies from './modules/PeerDependencies'; -import Infos from './modules/Infos'; - -import { - formatLicense, - formatRepository, - getLastUpdatedPackageTime, - getRecentReleases, -} from '../../utils/package'; -import API from '../../utils/api'; -import {DIST_TAGS} from '../../../lib/constants'; - -export default class PackageSidebar extends React.Component { - state = {}; - - static propTypes = { - packageName: PropTypes.string.isRequired, - }; - - constructor(props) { - super(props); - this.loadPackageData = this.loadPackageData.bind(this); - } - - async componentDidMount() { - const { packageName } = this.props; - await this.loadPackageData(packageName); - } - - async loadPackageData(packageName) { - let packageMeta; - - try { - packageMeta = await API.request(`sidebar/${packageName}`, 'GET'); - } catch (err) { - this.setState({ - failed: true, - }); - } - - this.setState({ - packageMeta, - }); - } - - render() { - const { packageMeta } = this.state; - - if (packageMeta) { - const {time, _uplinks} = packageMeta; - - // Infos component - const license = formatLicense(get(packageMeta, 'latest.license', null)); - const repository = formatRepository( - get(packageMeta, 'latest.repository', null) - ); - const homepage = get(packageMeta, 'latest.homepage', null); - - // dist-tags - const distTags = packageMeta[DIST_TAGS]; - - // Lastsync component - const recentReleases = getRecentReleases(time); - const lastUpdated = getLastUpdatedPackageTime(_uplinks); - - // Dependencies component - const dependencies = get(packageMeta, 'latest.dependencies', {}); - const peerDependencies = get(packageMeta, 'latest.peerDependencies', {}); - - // Maintainers component - return ( - - ); - } - return ( - - ); - } -} diff --git a/src/components/PackageSidebar/modules/Dependencies/index.jsx b/src/components/PackageSidebar/modules/Dependencies/index.jsx deleted file mode 100644 index d2bb778..0000000 --- a/src/components/PackageSidebar/modules/Dependencies/index.jsx +++ /dev/null @@ -1,50 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import Module from '../../Module'; - -import {getDetailPageURL} from '../../../../utils/url'; -import ModuleContentPlaceholder from '../../ModuleContentPlaceholder'; - -import classes from './style.scss'; - -export const NO_DEPENDENCIES = 'Zero Dependencies!'; -export const DEP_ITEM_CLASS = 'dependency-item'; - -const renderDependenciesList = (dependencies, dependenciesList) => { - return ( -
    - {dependenciesList.map((dependenceName, index) => { - return ( -
  • - {dependenceName} - {index < dependenciesList.length - 1 && {', '}} -
  • - ); - })} -
- ); -}; - -const Dependencies = ({dependencies = {}, title = 'Dependencies'}) => { - const dependenciesList = Object.keys(dependencies); - return ( - - {dependenciesList.length > 0 ? ( - renderDependenciesList(dependencies, dependenciesList) - ) : ( - - )} - - ); -}; - -Dependencies.propTypes = { - dependencies: PropTypes.object, - title: PropTypes.string, -}; - -export default Dependencies; diff --git a/src/components/PackageSidebar/modules/Dependencies/style.scss b/src/components/PackageSidebar/modules/Dependencies/style.scss deleted file mode 100644 index 8c8f84a..0000000 --- a/src/components/PackageSidebar/modules/Dependencies/style.scss +++ /dev/null @@ -1,13 +0,0 @@ -@import '../../../../styles/variables'; - -.dependenciesModule { - li { - display: inline-block; - font-size: $font-size-sm; - line-height: $line-height-xxs; - - a { - color: inherit; - } - } -} diff --git a/src/components/PackageSidebar/modules/DistTags/index.jsx b/src/components/PackageSidebar/modules/DistTags/index.jsx deleted file mode 100644 index 48f8cd1..0000000 --- a/src/components/PackageSidebar/modules/DistTags/index.jsx +++ /dev/null @@ -1,50 +0,0 @@ -import React from 'react'; -import propTypes from 'prop-types'; -import Module from '../../Module'; -import ModuleContentPlaceholder from '../../ModuleContentPlaceholder'; - -import classes from './style.scss'; - -const renderDistTags = (distTags) => { - - const tags = Object.entries(distTags); - - return ( -
    - {tags.map((tagItem) => { - const [tag, version] = tagItem; - - return ( -
  • - {tag} - {version} -
  • - ); - })} -
- ); -}; - -const DistTags = ({distTags = {}}) => { - const hasTags = Object.keys(distTags).length > 0; - - return ( - - {hasTags ? ( - renderDistTags(distTags) - ) : ( - - )} - - ); -}; - -DistTags.propTypes = { - distTags: propTypes.object, -}; - -export default DistTags; diff --git a/src/components/PackageSidebar/modules/DistTags/style.scss b/src/components/PackageSidebar/modules/DistTags/style.scss deleted file mode 100644 index f7823cc..0000000 --- a/src/components/PackageSidebar/modules/DistTags/style.scss +++ /dev/null @@ -1,13 +0,0 @@ -@import '../../../../styles/variables'; - -.releasesModule { - li { - display: flex; - font-size: $font-size-sm; - line-height: $line-height-xs; - - span:last-child { - margin-left: auto; - } - } -} diff --git a/src/components/PackageSidebar/modules/Infos/index.jsx b/src/components/PackageSidebar/modules/Infos/index.jsx deleted file mode 100644 index 14733b8..0000000 --- a/src/components/PackageSidebar/modules/Infos/index.jsx +++ /dev/null @@ -1,40 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import Module from '../../Module'; -import ModuleContentPlaceholder from '../../ModuleContentPlaceholder'; - -import classes from './style.scss'; - -const renderSection = (title, url) => ( -
  • - {title} - - {url} - -
  • -); - -const Infos = ({homepage, repository, license}) => { - const showInfo = homepage || repository || license; - return ( - - {showInfo ? ( -
      - {homepage && renderSection('Homepage', homepage)} - {repository && renderSection('Repository', repository)} - {license && ( -
    • - {'License'} - {license} -
    • )} -
    ) : } -
    ); -}; - -Infos.propTypes = { - homepage: PropTypes.string, - repository: PropTypes.string, - license: PropTypes.string, -}; - -export default Infos; diff --git a/src/components/PackageSidebar/modules/Infos/style.scss b/src/components/PackageSidebar/modules/Infos/style.scss deleted file mode 100644 index 13c8aa2..0000000 --- a/src/components/PackageSidebar/modules/Infos/style.scss +++ /dev/null @@ -1,21 +0,0 @@ -@import '../../../../styles/variables'; -@import '../../../../styles/mixins'; - -.infosModule { - li { - display: flex; - font-size: $font-size-sm; - line-height: $line-height-xs; - - a { - color: inherit; - max-width: 150px; - @include ellipsis; - } - - a:last-child, - span:last-child { - margin-left: auto; - } - } -} diff --git a/src/components/PackageSidebar/modules/LastSync/index.jsx b/src/components/PackageSidebar/modules/LastSync/index.jsx deleted file mode 100644 index 3730b8e..0000000 --- a/src/components/PackageSidebar/modules/LastSync/index.jsx +++ /dev/null @@ -1,43 +0,0 @@ -import React from 'react'; -import propTypes from 'prop-types'; -import Module from '../../Module'; -import ModuleContentPlaceholder from '../../ModuleContentPlaceholder'; - -import classes from './style.scss'; - -const renderRecentReleases = (recentReleases) => ( -
      - {recentReleases.map((versionInfo) => { - const {version, time} = versionInfo; - return ( -
    • - {version} - {time} -
    • - ); - })} -
    -); - -const LastSync = ({recentReleases = [], lastUpdated = ''}) => { - return ( - - {recentReleases.length ? ( - renderRecentReleases(recentReleases) - ) : ( - - )} - - ); -}; - -LastSync.propTypes = { - recentReleases: propTypes.array, - lastUpdated: propTypes.string, -}; - -export default LastSync; diff --git a/src/components/PackageSidebar/modules/LastSync/style.scss b/src/components/PackageSidebar/modules/LastSync/style.scss deleted file mode 100644 index f7823cc..0000000 --- a/src/components/PackageSidebar/modules/LastSync/style.scss +++ /dev/null @@ -1,13 +0,0 @@ -@import '../../../../styles/variables'; - -.releasesModule { - li { - display: flex; - font-size: $font-size-sm; - line-height: $line-height-xs; - - span:last-child { - margin-left: auto; - } - } -} diff --git a/src/components/PackageSidebar/modules/Maintainers/MaintainerInfo/index.jsx b/src/components/PackageSidebar/modules/Maintainers/MaintainerInfo/index.jsx deleted file mode 100644 index 5975e30..0000000 --- a/src/components/PackageSidebar/modules/Maintainers/MaintainerInfo/index.jsx +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; - -import classes from './style.scss'; - -const MaintainerInfo = ({title, name, avatar}) => { - const avatarDescription = `${title} ${name}'s avatar`; - return ( -
    - {avatarDescription} - {name} -
    - ); -}; - -MaintainerInfo.propTypes = { - title: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - avatar: PropTypes.string.isRequired, -}; - -export default MaintainerInfo; diff --git a/src/components/PackageSidebar/modules/Maintainers/MaintainerInfo/style.scss b/src/components/PackageSidebar/modules/Maintainers/MaintainerInfo/style.scss deleted file mode 100644 index dc1805d..0000000 --- a/src/components/PackageSidebar/modules/Maintainers/MaintainerInfo/style.scss +++ /dev/null @@ -1,26 +0,0 @@ -@import '../../../../../styles/variables'; -@import '../../../../../styles/mixins'; - -.maintainer { - display: flex; - line-height: $line-height-xl; - cursor: default; - - &:not(:last-child) { - margin-bottom: 10px; - } - - img { - width: 30px; - height: 30px; - margin-right: 10px; - border-radius: 100%; - flex-shrink: 0; - } - - span { - font-size: $font-size-sm; - flex-shrink: 1; - @include ellipsis; - } -} diff --git a/src/components/PackageSidebar/modules/Maintainers/index.jsx b/src/components/PackageSidebar/modules/Maintainers/index.jsx deleted file mode 100644 index bbdea22..0000000 --- a/src/components/PackageSidebar/modules/Maintainers/index.jsx +++ /dev/null @@ -1,122 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import get from 'lodash/get'; -import filter from 'lodash/filter'; -import size from 'lodash/size'; -import has from 'lodash/has'; -import uniqBy from 'lodash/uniqBy'; - -import Module from '../../Module'; -import MaintainerInfo from './MaintainerInfo'; -import ModuleContentPlaceholder from '../../ModuleContentPlaceholder'; - -import classes from './style.scss'; - -const CONTRIBUTORS_TO_SHOW = 5; - -export default class Maintainers extends React.Component { - static propTypes = { - packageMeta: PropTypes.object.isRequired, - }; - - state = {}; - - constructor(props) { - super(props); - this.handleShowAllContributors = this.handleShowAllContributors.bind(this); - } - - get author() { - return get(this, 'props.packageMeta.latest.author'); - } - - get contributors() { - const contributors = get(this, 'props.packageMeta.latest.contributors', {}); - return filter(contributors, (contributor) => { - return ( - contributor.name !== get(this, 'author.name') && - contributor.email !== get(this, 'author.email') - ); - }); - } - - get showAllContributors() { - const { showAllContributors } = this.state; - return showAllContributors || size(this.contributors) <= 5; - } - - get uniqueContributors() { - if (!this.contributors) { - return []; - } - - return uniqBy(this.contributors, (contributor) => contributor.name).slice( - 0, - CONTRIBUTORS_TO_SHOW - ); - } - - handleShowAllContributors() { - this.setState({ - showAllContributors: true, - }); - } - - renderContributors() { - if (!this.contributors) return null; - - return (this.showAllContributors - ? this.contributors - : this.uniqueContributors - ).map((contributor, index) => { - return ( - - ); - }); - } - - renderAuthorAndContributors(author) { - return ( -
    -
      - {author && - author.name && ( - - )} - {this.renderContributors()} -
    - {!this.showAllContributors && ( - - )} -
    - ); - } - - render() { - const contributors = this.renderContributors(); - return ( - - {contributors.length || has(this.author, 'name') ? ( - this.renderAuthorAndContributors(this.author) - ) : ( - - )} - - ); - } -} diff --git a/src/components/PackageSidebar/modules/Maintainers/style.scss b/src/components/PackageSidebar/modules/Maintainers/style.scss deleted file mode 100644 index 6294904..0000000 --- a/src/components/PackageSidebar/modules/Maintainers/style.scss +++ /dev/null @@ -1,13 +0,0 @@ -@import '../../../../styles/variables'; - -.maintainersModule { - .showAllContributors { - cursor: pointer; - width: 100%; - background: none; - border: none; - font-size: $font-size-sm; - text-align: center; - padding: 10px 0; - } -} diff --git a/src/components/PackageSidebar/modules/PeerDependencies/index.jsx b/src/components/PackageSidebar/modules/PeerDependencies/index.jsx deleted file mode 100644 index 287073f..0000000 --- a/src/components/PackageSidebar/modules/PeerDependencies/index.jsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import Dependencies from '../Dependencies'; - -export const TITLE = 'Peer Dependencies'; - -const PeerDependencies = ({dependencies = {}, title = TITLE}) => { - return ( - - ); -}; - -PeerDependencies.propTypes = { - dependencies: PropTypes.object, - title: PropTypes.string, -}; - -export default PeerDependencies; diff --git a/src/components/Repository/img/git.png b/src/components/Repository/img/git.png new file mode 100644 index 0000000000000000000000000000000000000000..51f4ae5404fc79be09e69171bfc9d34d48810297 GIT binary patch literal 2383 zcmb_edr(tX8b3FeJQNAIb;Tf>)JL(q3J4vLirl*vi*Kow20-DLSS9|3^Zwk7&^dy0_BKc76X2>}!()lOlVnV}tr z%7&jSS|mYX4~n%NS=f@&X(b^Q(N+N%0zF~9g{A- zZfSW+-Hr{m9%u8|2k$3dtage|2Sl;$h{sF(-i|c>B<|Qtz%K^PbRz=513=(`{A&g* z;RKU3B@gTnOaDvupQ!DT9hv|fD?ePvQ@0F%CkIDtqH+r6-`Pof?+-KO$>7G7NXXf@Nusk$YC-Nu- z23d{+;0ha8oHXp(O9h@TmW@CbU`rV z;l_K-qf92mZ;_k&oa6Cfm$b0End8ChmVX)f^pq##^aeu^Al9jBsZfODGUaf3a1>BU z#)l8$FxyesvmRxYX%&I`xjrI)@}}{Yz?WIexeH}QYZaSD3*0t5$8`+Ut3z}uuEv_l zb~=$F*(jZi!&FC0jtaAaNV1^#;yj+uX?0ZYbnwg26}mtz%iwT$HXX)ck)u$l7-(c|flTERxKM;g%Wl*nxU4yuBeLE+%mLQk3j#Q<_)GxC!`o6owL0SxvRSsR*zM_= zM;TNgl4km?o7x7!8}u>19+UmMGd!jky3e24KfUA+5jayP8JB}vti|+79AKDU-2xDY zqn+Hu(=dH4_b`}DuK6stpXcU@G9Z(UVjJC3;j2(CH&^;lDwRFv=gGOes*l+Q;vj%R z1CjmXXlAdvD}6z?*_cB>EeMeU3vbyDzxWD8a=-Y{)zbaNRsI}cXmGi}n|<>UAbYG9 z;xUVTfTo<;jjje( z<5@yEyyg^r9lW4kDOmWi7F$h4OvgW4*hR#{_R2TkNomGiT2@BGExcp}eH{5=tvPPr znrdcAhi9x>Cm;X5CI-$%(YABf@VI-Er7q>WS-MM&t|)rN1|93ssE#gv_%ypPosiRO zHauI2pZ{7#4Cak`9Bm+Eea_1Ri=F@QCrUo01C6qy1LOxLv(y%#4Rb1Cchij&G zr#4JZU%q$h=`k1i`eKFEX0D35ZPMpXFU?6-DzEpNF}+yks$ZJ7-sJd`US6|5H&c)= z?g+u?LxEVi_P~Y{L{FuKKRsbd!pg{zU6$E&)tT=G*E)_wv{c$(%`Lu27Pz|UsdXoo zog#W>2g$8C_+Cx>O@=}tkFwdxlOcOdgU!`~l$ABWSbdW+ZsxSDuMA~-A?WTkY=Uc%5xpg0$kgN=(W^ez> zH_0Zh@CX}tY3=ThcqDg~OVlqDK(!IiGN zC}T7iq-;&)B2ASvfD#5%fx7n~mIN!?Q47j>Zp`9ZwCvXL{U~GNpN-6MZ!^s|bb5-u zl{43z!4-)KlMrXIEQx3vDV*3C+$6xH%iJ^_k9EUe041;&y!qhF5f0HAh zFXfj)ECZw`K31%^WqqQaPbqdu$R@JyV3>73;@C#tjq&C3al~h1#r9#_?ZT-$)5Nk^ zmUQOPgk&zS|FArSgk}Pw6l3UjcW!>`-=XfV0hI_S$2b4{BL82 z2k(D``e93+SzOn9`ydHEt@(u*!(K_su{EJ|-OXKk#a^R&C_m@uwUJZEka5TH48ge_ vp%EL>Wi@Nxn8V*2x$L2D+u#MyDSqcb+P#5YHS3sP9I$26&gfeklTQ2-d^Cga literal 0 HcmV?d00001 diff --git a/src/components/Repository/index.js b/src/components/Repository/index.js index ded0216..68c2239 100644 --- a/src/components/Repository/index.js +++ b/src/components/Repository/index.js @@ -1,61 +1,59 @@ -/* eslint no-unused-vars: 0 */ /* eslint react/jsx-max-depth: 0 */ -import React, {Component, Fragment} from 'react'; +import React, {Component} from 'react'; +import Avatar from '@material-ui/core/Avatar'; +import List from '@material-ui/core/List'; +import ListItemText from '@material-ui/core/ListItemText'; import { DetailContextConsumer } from '../../pages/version/index'; -import Card from '@material-ui/core/Card/index'; -import CardContent from '@material-ui/core/CardContent/index'; -import Grid from '@material-ui/core/Grid/index'; -import GitHub from '../../icons/GitHub'; import CopyToClipBoard from '../CopyToClipBoard'; -import BugReport from '@material-ui/icons/BugReport'; -import CardActions from '@material-ui/core/CardActions/index'; -import Button from '@material-ui/core/Button'; -import {GridRepo} from './styles'; + +import { Heading, GithubLink, RepositoryListItem } from './styles'; +import git from './img/git.png'; class Repository extends Component { render() { return ( {(context) => { - return this.renderAuthor(context); + return this.renderRepository(context); }} ); }; - renderAuthor = ({packageMeta}) => { - const { repository, bugs } = packageMeta.latest; - if (!repository) { + renderRepositoryText(url) { + return ({url}); + } + + renderRepository = ({packageMeta}) => { + const { + repository: { + url, + } = {}, + } = packageMeta.latest; + + if (!url) { return null; } return ( - - - - {this.renderRepository(repository, bugs)} - - - - - - - + <> + {'Repository'}}> + + + + + + ); } - - renderRepository = ({url, type}, bugs) => { + + renderContent(url) { return ( - - - - - - - - + + {this.renderRepositoryText(url)} + ); } } diff --git a/src/components/Repository/styles.js b/src/components/Repository/styles.js index 8533347..12eddd1 100644 --- a/src/components/Repository/styles.js +++ b/src/components/Repository/styles.js @@ -5,9 +5,42 @@ import styled from 'react-emotion'; import Grid from '@material-ui/core/Grid/index'; +import ListItem from '@material-ui/core/ListItem/index'; +import Typography from '@material-ui/core/Typography/index'; + +import Github from '../../icons/GitHub'; +import colors from '../../utils/styles/colors'; + +export const Heading = styled(Typography)` + && { + font-weight: 700; + text-transform: capitalize; + } +`; export const GridRepo = styled(Grid)` && { align-items: center; } `; + +export const GithubLink = styled('a')` + && { + color: ${colors.primary}; + } +`; + +export const GithubLogo = styled(Github)` + && { + font-size: 40px; + color: ${colors.primary}; + background-color: ${colors.greySuperLight}; + } +`; + +export const RepositoryListItem = styled(ListItem)` + && { + padding-left: 0; + padding-right: 0; + } +`; diff --git a/src/components/Search/index.js b/src/components/Search/index.js index 7fcc752..a013c71 100644 --- a/src/components/Search/index.js +++ b/src/components/Search/index.js @@ -100,7 +100,7 @@ export class Search extends Component { case 'enter': this.setState({ search: '' }); // $FlowFixMe - history.push(`/-/web/version/${suggestionValue}`); + history.push(`/-/web/detail/${suggestionValue}`); break; } }; diff --git a/src/components/Tag/styles.js b/src/components/Tag/styles.js index a6eea8f..cd624ed 100644 --- a/src/components/Tag/styles.js +++ b/src/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/components/UpLinks/index.js b/src/components/UpLinks/index.js index 13bf1d3..8756a07 100644 --- a/src/components/UpLinks/index.js +++ b/src/components/UpLinks/index.js @@ -1,13 +1,15 @@ /** * @prettier */ - -import { DetailContextConsumer } from '../../pages/version/index'; -import { formatDateDistance } from '../../utils/package'; -import { Heading, Spacer, ListItemText } from './styles'; +import React from 'react'; import List from '@material-ui/core/List/index'; import ListItem from '@material-ui/core/ListItem/index'; -import React from 'react'; + +import { DetailContextConsumer } from '../../pages/version/index'; +import NoItems from '../NoItems'; +import { formatDateDistance } from '../../utils/package'; + +import { Heading, Spacer, ListItemText } from './styles'; class UpLinks extends React.PureComponent { render() { @@ -15,7 +17,7 @@ class UpLinks extends React.PureComponent { // $FlowFixMe {({ packageMeta }) => { - return this.renderContent(packageMeta._uplinks); + return this.renderContent(packageMeta._uplinks, packageMeta.latest); }} ); @@ -35,15 +37,18 @@ class UpLinks extends React.PureComponent { ); - renderContent(uplinks) { - return ( - uplinks && ( - <> - {'Uplinks'} - {this.renderUpLinksList(uplinks)} - - ) - ); + renderContent(uplinks, { name }) { + if (Object.keys(uplinks).length > 0) { + return ( + uplinks && ( + <> + {'Uplinks'} + {this.renderUpLinksList(uplinks)} + + ) + ); + } + return ; } } diff --git a/src/components/Versions/index.js b/src/components/Versions/index.js index 7dfe711..73496cf 100644 --- a/src/components/Versions/index.js +++ b/src/components/Versions/index.js @@ -17,40 +17,44 @@ class Versions extends React.PureComponent { // $FlowFixMe {({ packageMeta }) => { - return this.renderContent(packageMeta[DIST_TAGS], packageMeta.versions); + return this.renderContent(packageMeta); }} ); } - renderPackageList = (packages: any, isVersion: boolean = false) => ( - - {Object.keys(packages) - .reverse() - .map(version => ( - - {version} - - {isVersion ? `${formatDateDistance('2017-10-26T09:03:15.044Z')} ago` : packages[version]} - - ))} - - ); + renderPackageList = (packages: any, isVersion: boolean = false, timeMap: Object = {}) => { + return ( + + {Object.keys(packages) + .reverse() + .map(version => ( + + {version} + + {isVersion && timeMap[version] ? `${formatDateDistance(timeMap[version])} ago` : packages[version]} + + ))} + + ); + }; // $FlowFixMe - renderContent(distTags: object, versions: object) { + renderContent(packageMeta) { + const { versions = {}, time: timeMap = {}, [DIST_TAGS]: distTags = {} } = packageMeta; + return ( <> {distTags && ( <> {'Current Tags'} - {this.renderPackageList(distTags)} + {this.renderPackageList(distTags, false, timeMap)} )} {versions && ( <> {'Version History'} - {this.renderPackageList(versions, true)} + {this.renderPackageList(versions, true, timeMap)} )} diff --git a/src/history.js b/src/history.js index d000bcb..f8407b0 100644 --- a/src/history.js +++ b/src/history.js @@ -2,14 +2,8 @@ * @prettier */ -import {createBrowserHistory} from 'history'; +import { createBrowserHistory } from 'history'; const history = createBrowserHistory(); -// Listen for changes to the current location. -history.listen((location, action) => { - // location is an object like window.location - console.log('====>', action, location.pathname, location.state); -}); - export default history; diff --git a/src/index.js b/src/index.js index c1c9331..136c63c 100644 --- a/src/index.js +++ b/src/index.js @@ -1,12 +1,14 @@ -import React from "react"; -import ReactDOM from "react-dom"; -import { AppContainer } from "react-hot-loader"; +import './utils/__setPublicPath__'; -import App from "./app"; +import React from 'react'; +import ReactDOM from 'react-dom'; +import {AppContainer} from 'react-hot-loader'; -const rootNode = document.getElementById("root"); +import App from './app'; -const renderApp = Component => { +const rootNode = document.getElementById('root'); + +const renderApp = (Component) => { ReactDOM.render( @@ -18,7 +20,7 @@ const renderApp = Component => { renderApp(App); if (module.hot) { - module.hot.accept("./app", () => { + module.hot.accept('./app', () => { renderApp(App); }); } diff --git a/src/pages/detail/detail.scss b/src/pages/detail/detail.scss deleted file mode 100644 index 849a7f6..0000000 --- a/src/pages/detail/detail.scss +++ /dev/null @@ -1,25 +0,0 @@ -@import '../../styles/variables'; -@import '../../styles/mixins'; - -.twoColumn { - @include container-size; - display: flex; - - > div { - &:first-child { - flex-shrink: 1; - min-width: 300px; - width: 100%; - } - } - - > aside { - &:last-child { - margin-left: auto; - - padding-left: 15px; - flex-shrink: 0; - width: 285px; - } - } -} diff --git a/src/pages/detail/index.jsx b/src/pages/detail/index.jsx deleted file mode 100644 index bc526a4..0000000 --- a/src/pages/detail/index.jsx +++ /dev/null @@ -1,87 +0,0 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import isEmpty from 'lodash/isEmpty'; - -import PackageDetail from '../../components/PackageDetail'; -import NotFound from '../../components/NotFound'; -import Spinner from '../../components/Spinner'; -import API from '../../utils/api'; - -import classes from './detail.scss'; -import PackageSidebar from '../../components/PackageSidebar/index'; - -export default class Detail extends Component { - static propTypes = { - match: PropTypes.object, - isUserLoggedIn: PropTypes.bool, - }; - - state = { - readMe: '', - notFound: false, - }; - - getPackageName(props = this.props) { - const params = props.match.params; - return `${(params.scope && '@' + params.scope + '/') || ''}${ - params.package - }`; - } - - get packageName() { - return this.getPackageName(); - } - - async componentDidMount() { - await this.loadPackageInfo(this.packageName); - } - - componentDidUpdate(prevProps) { - const { isUserLoggedIn, match } = this.props; - const condition1 = prevProps.isUserLoggedIn !== isUserLoggedIn; - const condition2 = - prevProps.match.params.package !== match.params.package; - if (condition1 || condition2) { - const packageName = this.getPackageName(this.props); - this.loadPackageInfo(packageName); - } - } - - async loadPackageInfo(packageName) { - this.setState({ - readMe: '', - }); - - try { - const resp = await API.request(`package/readme/${packageName}`, 'GET'); - this.setState({ - readMe: resp, - notFound: false, - }); - } catch (err) { - this.setState({ - notFound: true, - }); - } - } - - render() { - const { notFound, readMe } = this.state; - - if (notFound) { - return ( -
    - -
    - ); - } else if (isEmpty(readMe)) { - return ; - } - return ( -
    - - -
    - ); - } -} diff --git a/src/pages/home/index.js b/src/pages/home/index.js index 94530f8..e2661b3 100644 --- a/src/pages/home/index.js +++ b/src/pages/home/index.js @@ -1,4 +1,4 @@ -import React, {Component} from 'react'; +import React, { Component } from 'react'; import PropTypes from 'prop-types'; import PackageList from '../../components/PackageList'; @@ -10,10 +10,10 @@ class Home extends Component { }; render() { - const {packages} = this.props; + const { packages } = this.props; return ( -
    - +
    +
    ); } diff --git a/src/pages/version/index.js b/src/pages/version/index.js index e40ff3f..ad7cefb 100644 --- a/src/pages/version/index.js +++ b/src/pages/version/index.js @@ -3,13 +3,14 @@ * @flow */ -import React, {Component} from 'react'; +import React, { Component } from 'react'; import Grid from '@material-ui/core/Grid/index'; import Loading from '../../components/Loading'; import DetailContainer from '../../components/DetailContainer'; import DetailSidebar from '../../components/DetailSidebar'; -import {callDetailPage} from '../../utils/calls'; -import {getRouterPackageName} from '../../utils/package'; +import { callDetailPage } from '../../utils/calls'; +import { getRouterPackageName } from '../../utils/package'; +import NotFound from '../../components/NotFound'; export const DetailContext = React.createContext(); @@ -35,9 +36,9 @@ class VersionPage extends Component { /* eslint no-unused-vars: 0 */ async componentDidUpdate(nextProps: any, prevState: any) { - const {packageName} = this.state; + const { packageName } = this.state; if (packageName !== prevState.packageName) { - const {readMe, packageMeta} = await callDetailPage(packageName); + const { readMe, packageMeta } = await callDetailPage(packageName); this.setState({ readMe, packageMeta, @@ -49,7 +50,7 @@ class VersionPage extends Component { } static getDerivedStateFromProps(nextProps: any, prevState: any) { - const {match} = nextProps; + const { match } = nextProps; const packageName = getRouterPackageName(match); if (packageName !== prevState.packageName) { @@ -70,7 +71,7 @@ class VersionPage extends Component { } async loadPackageInfo() { - const {packageName} = this.state; + const { packageName } = this.state; // FIXME: use utility document.title = `Verdaccio - ${packageName}`; @@ -79,7 +80,7 @@ class VersionPage extends Component { }); try { - const {readMe, packageMeta} = await callDetailPage(packageName); + const { readMe, packageMeta } = await callDetailPage(packageName); this.setState({ readMe, packageMeta, @@ -103,11 +104,15 @@ class VersionPage extends Component { }; render() { - const {isLoading, packageMeta, readMe, packageName} = this.state; + const { isLoading, packageMeta, readMe, packageName } = this.state; - if (isLoading === false) { + if (isLoading) { + return ; + } else if (!packageMeta) { + return ; + } else { return ( - + {this.renderDetail()} @@ -118,8 +123,6 @@ class VersionPage extends Component { ); - } else { - return ; } } diff --git a/src/router.js b/src/router.js index 915d919..53aaeb8 100644 --- a/src/router.js +++ b/src/router.js @@ -5,19 +5,17 @@ /* eslint react/jsx-max-depth:0 */ -import React, { Component, Fragment } from "react"; -import { Router, Route, Switch } from "react-router-dom"; -import { AppContextConsumer } from "./app"; +import React, { Component, Fragment } from 'react'; +import { Router, Route, Switch } from 'react-router-dom'; +import { AppContextConsumer } from './app'; -// import {asyncComponent} from '../others/utils/asyncComponent'; -import history from "./history"; -import Header from "./components/Header"; -import HomePage from "./pages/home"; -import NotFound from './components/NotFound' -// const NotFound = asyncComponent(() => import("./components/NotFound")); -// const DetailPackage = asyncComponent(() => import("./pages/detail")); -// const VersionPackage = asyncComponent(() => import("./pages/version")); -// const HomePage = asyncComponent(() => import("./pages/home")); +import { asyncComponent } from './utils/asyncComponent'; +import history from './history'; +import Header from './components/Header'; + +const NotFound = asyncComponent(() => import('./components/NotFound')); +const VersionPackage = asyncComponent(() => import('./pages/version')); +const HomePage = asyncComponent(() => import('./pages/home')); class RouterApp extends Component { render() { @@ -26,11 +24,9 @@ class RouterApp extends Component { {this.renderHeader()} - - {/* - - - */} + + + @@ -44,15 +40,7 @@ class RouterApp extends Component { return ( {function renderConsumerVersionPage({ logoUrl, scope, user }) { - return ( -
    - ); + return
    ; }} ); @@ -62,21 +50,7 @@ class RouterApp extends Component { return ( {function renderConsumerVersionPage({ isUserLoggedIn, packages }) { - return ( - - ); - }} - - ); - }; - - renderDetailPage = (routerProps: any) => { - return ( - - {function renderConsumerVersionPage({ isUserLoggedIn }) { - return ( - - ); + return ; }} ); @@ -86,9 +60,7 @@ class RouterApp extends Component { return ( {function renderConsumerVersionPage({ isUserLoggedIn }) { - return ( - - ); + return ; }} ); diff --git a/src/styles/mixins.scss b/src/styles/mixins.scss index 17bcb83..2b2bc0e 100644 --- a/src/styles/mixins.scss +++ b/src/styles/mixins.scss @@ -37,9 +37,10 @@ } @mixin container-size { - margin-left: auto; - margin-right: auto; @media screen and (min-width: $break-lg) { max-width: $break-lg; + width: 100%; + margin-left: auto; + margin-right: auto; } } diff --git a/src/utils/__setPublicPath__.js b/src/utils/__setPublicPath__.js index ad0f2d9..f528199 100644 --- a/src/utils/__setPublicPath__.js +++ b/src/utils/__setPublicPath__.js @@ -1,3 +1,3 @@ if (!__DEBUG__) { - __webpack_public_path__ = window.VERDACCIO_API_URL.replace(/\/verdaccio\/$/, '/static/'); // eslint-disable-line + __webpack_public_path__ = window.VERDACCIO_API_URL.replace(/\/verdaccio\/$/, '/static/') // eslint-disable-line } diff --git a/src/utils/api.js b/src/utils/api.js index 2d23a67..20b0faf 100644 --- a/src/utils/api.js +++ b/src/utils/api.js @@ -2,48 +2,48 @@ import storage from './storage'; class API { request(url, method = 'GET', options = {}) { - if (!window.VERDACCIO_API_URL) { - throw new Error('VERDACCIO_API_URL is not defined!'); - } + if (!window.VERDACCIO_API_URL) { + throw new Error('VERDACCIO_API_URL is not defined!'); + } - const token = storage.getItem('token'); - if (token) { - if (!options.headers) options.headers = {}; + const token = storage.getItem('token'); + if (token) { + if (!options.headers) options.headers = {}; - options.headers.authorization = `Bearer ${token}`; - } + options.headers.authorization = `Bearer ${token}`; + } - if (!['http://', 'https://', '//'].some((prefix) => url.startsWith(prefix))) { - url = window.VERDACCIO_API_URL + url; - } + if (!['http://', 'https://', '//'].some((prefix) => url.startsWith(prefix))) { + url = window.VERDACCIO_API_URL + url; + } - /** - * Handles response according to content type - * @param {object} response - * @returns {promise} - */ - function handleResponseType(response) { - if (response.headers) { - const contentType = response.headers.get('Content-Type'); - if (contentType.includes('application/pdf')) { - return Promise.all([response.ok, response.blob()]); - } - if (contentType.includes('application/json')) { - return Promise.all([response.ok, response.json()]); - } - // it includes all text types - if (contentType.includes('text/')) { - return Promise.all([response.ok, response.text()]); + /** + * Handles response according to content type + * @param {object} response + * @returns {promise} + */ + function handleResponseType(response) { + if (response.headers) { + const contentType = response.headers.get('Content-Type'); + if (contentType.includes('application/pdf')) { + return Promise.all([response.ok, response.blob()]); + } + if (contentType.includes('application/json')) { + return Promise.all([response.ok, response.json()]); + } + // it includes all text types + if (contentType.includes('text/')) { + return Promise.all([response.ok, response.text()]); + } } } - } - return new Promise((resolve, reject) => { - fetch(url, { - method, - credentials: 'same-origin', - ...options, - }) + return new Promise((resolve, reject) => { + fetch(url, { + method, + credentials: 'same-origin', + ...options, + }) .then(handleResponseType) .then(([responseOk, body]) => { if (responseOk) { @@ -52,11 +52,11 @@ class API { reject(body); } }) - .catch((error) => { + .catch(error => { reject(error); }); - }); - } + }); + } } export default new API(); diff --git a/src/utils/asyncComponent.js b/src/utils/asyncComponent.js index 6ffa7b1..7aadf71 100644 --- a/src/utils/asyncComponent.js +++ b/src/utils/asyncComponent.js @@ -1,24 +1,32 @@ +/** + * @prettier + */ + import React from 'react'; export function asyncComponent(getComponent) { return class AsyncComponent extends React.Component { static Component = null; - state = {Component: AsyncComponent.Component}; + state = { Component: AsyncComponent.Component }; componentDidMount() { - const {Component} = this.state; - + const { Component } = this.state; if (!Component) { - getComponent().then(({default: Component}) => { - AsyncComponent.Component = Component; - /* eslint react/no-did-mount-set-state:0 */ - this.setState({Component}); - }); + getComponent() + .then(({ default: Component }) => { + AsyncComponent.Component = Component; + /* eslint react/no-did-mount-set-state:0 */ + this.setState({ Component }); + }) + .catch(err => { + console.error(err); + }); } } render() { - const {Component} = this.state; + const { Component } = this.state; if (Component) { + // eslint-disable-next-line verdaccio/jsx-spread return ; } diff --git a/src/utils/file-size.js b/src/utils/file-size.js new file mode 100644 index 0000000..5281a57 --- /dev/null +++ b/src/utils/file-size.js @@ -0,0 +1,5 @@ +export default function fileSizeSI(a, b, c, d, e) { + return (b = Math, c = b.log, d = 1e3, e = c(a) / c(d) | 0, a / b.pow(d, e)).toFixed(2) + + ' ' + (e ? 'kMGTPEZY'[--e] + 'B' : 'Bytes'); +}; + diff --git a/src/utils/login.js b/src/utils/login.js index 0dfe646..a51083d 100644 --- a/src/utils/login.js +++ b/src/utils/login.js @@ -1,76 +1,70 @@ -import isString from "lodash/isString"; -import isNumber from "lodash/isNumber"; -import isEmpty from "lodash/isEmpty"; -import { Base64 } from "js-base64"; -import API from "./api"; - -const HEADERS = { - JSON: "application/json", - JSON_CHARSET: "application/json; charset=utf-8", - OCTET_STREAM: "application/octet-stream; charset=utf-8", - TEXT_CHARSET: "text/plain; charset=utf-8", - GZIP: "gzip" -}; +import isString from 'lodash/isString'; +import isNumber from 'lodash/isNumber'; +import isEmpty from 'lodash/isEmpty'; +import {Base64} from 'js-base64'; +import API from './api'; +import {HEADERS} from '../../lib/constants'; export function isTokenExpire(token) { - if (!isString(token)) { - return true; - } + if (!isString(token)) { + return true; + } - let [, payload] = token.split("."); + let [,payload] = token.split('.'); - if (!payload) { - return true; - } + if (!payload) { + return true; + } - try { - payload = JSON.parse(Base64.decode(payload)); - } catch (error) { - // eslint-disable-next-line - console.error("Invalid token:", error, token); - return true; - } + try { + payload = JSON.parse(Base64.decode(payload)); + } catch (error) { + // eslint-disable-next-line + console.error('Invalid token:', error, token); + return true; + } - if (!payload.exp || !isNumber(payload.exp)) { - return true; - } - // Report as expire before (real expire time - 30s) - const jsTimestamp = payload.exp * 1000 - 30000; - const expired = Date.now() >= jsTimestamp; + if (!payload.exp || !isNumber(payload.exp)) { + return true; + } + // Report as expire before (real expire time - 30s) + const jsTimestamp = (payload.exp * 1000) - 30000; + const expired = Date.now() >= jsTimestamp; - return expired; + return expired; } + export async function makeLogin(username, password) { - // checks isEmpty - if (isEmpty(username) || isEmpty(password)) { - const error = { - title: "Unable to login", - type: "error", - description: "Username or password can't be empty!" - }; - return { error }; - } + // checks isEmpty + if (isEmpty(username) || isEmpty(password)) { + const error = { + title: 'Unable to login', + type: 'error', + description: 'Username or password can\'t be empty!', + }; + return {error}; + } - try { - const response = await API.request("login", "POST", { - body: JSON.stringify({ username, password }), - headers: { - Accept: HEADERS.JSON, - "Content-Type": HEADERS.JSON - } - }); - const result = { - username: response.username, - token: response.token - }; - return result; - } catch (e) { - const error = { - title: "Unable to login", - type: "error", - description: e.error - }; - return { error }; - } + try { + const response = await API.request('login', 'POST', { + body: JSON.stringify({username, password}), + headers: { + Accept: HEADERS.JSON, + 'Content-Type': HEADERS.JSON, + }, + }); + const result = { + username: response.username, + token: response.token, + }; + return result; + } catch (e) { + const error = { + title: 'Unable to login', + type: 'error', + description: e.error, + }; + return {error}; + } } diff --git a/src/utils/package.js b/src/utils/package.js index b3d18e1..3e26213 100644 --- a/src/utils/package.js +++ b/src/utils/package.js @@ -4,7 +4,6 @@ import format from 'date-fns/format'; import distanceInWordsToNow from 'date-fns/distance_in_words_to_now'; export const TIMEFORMAT = 'DD.MM.YYYY, HH:mm:ss'; -export const DEFAULT_USER = 'Anonymous'; /** * Formats license field for webui. @@ -39,36 +38,6 @@ export function formatRepository(repository) { } -/** - * Formats author field for webui. - * @see https://docs.npmjs.com/files/package.json#author - */ -export function formatAuthor(author) { - let authorDetails = { - name: DEFAULT_USER, - email: '', - avatar: '', - }; - - if (isString(author)) { - authorDetails = { - ...authorDetails, - name: author ? author : authorDetails.name, - }; - } - - if (isObject(author)) { - authorDetails = { - ...authorDetails, - name: author.name ? author.name : authorDetails.name, - email: author.email ? author.email : authorDetails.email, - avatar: author.avatar ? author.avatar : authorDetails.avatar, - }; - } - - return authorDetails; -} - /** * For component * @param {array} uplinks diff --git a/src/utils/styles/colors.js b/src/utils/styles/colors.js index 4cd495f..fecfa9c 100644 --- a/src/utils/styles/colors.js +++ b/src/utils/styles/colors.js @@ -10,7 +10,10 @@ const colors = { grey: '#808080', greySuperLight: '#f5f5f5', greyLight: '#d3d3d3', + greyLight2: '#908ba1', + greyLight3: '#f3f4f240', greyDark: '#a9a9a9', + greyDark2: '#586069', greyChateau: '#95989a', greyGainsboro: '#e3e3e3', greyAthens: '#d3dddd', diff --git a/src/utils/styles/media.js b/src/utils/styles/media.js index 3240d70..1c74025 100644 --- a/src/utils/styles/media.js +++ b/src/utils/styles/media.js @@ -1,6 +1,6 @@ import { css } from 'emotion'; -const breakpoints = { +export const breakpoints = { small: 576, medium: 768, large: 1024, diff --git a/src/utils/url.js b/src/utils/url.js index 5346870..d704be5 100644 --- a/src/utils/url.js +++ b/src/utils/url.js @@ -2,11 +2,3 @@ export function getRegistryURL() { // Don't add slash if it's not a sub directory return `${location.origin}${location.pathname === '/' ? '' : location.pathname}`; } - -/** - * Get specified package detail page url - * @param {string} packageName - */ -export function getDetailPageURL(packageName) { - return `${getRegistryURL()}/-/web/version/${packageName}`; -} diff --git a/src/utils/windows.js b/src/utils/windows.js index 2a15a2c..9fb3b37 100644 --- a/src/utils/windows.js +++ b/src/utils/windows.js @@ -1,3 +1,3 @@ export function goToVerdaccioWebsite() { - window.open('https://www.verdaccio.org/', '_blank'); + window.open('https://www.verdaccio.org/', '_blank'); }