0
Fork 0
mirror of https://github.com/verdaccio/verdaccio.git synced 2025-01-13 22:48:31 -05:00

chore: add sidebar experiment

This commit is contained in:
Juan Picado @jotadeveloper 2019-01-13 19:34:52 +01:00
parent 8a168760f5
commit b6a8dd37d0
No known key found for this signature in database
GPG key ID: 18AC54485952D158
14 changed files with 280 additions and 43 deletions

View file

@ -160,7 +160,8 @@
"webpack-cli": "3.1.1", "webpack-cli": "3.1.1",
"webpack-dev-server": "3.1.14", "webpack-dev-server": "3.1.14",
"webpack-merge": "4.1.4", "webpack-merge": "4.1.4",
"whatwg-fetch": "3.0.0" "whatwg-fetch": "3.0.0",
"xss": "1.0.3"
}, },
"keywords": [ "keywords": [
"private", "private",

View file

@ -0,0 +1,49 @@
import React, {Component} from 'react';
import { DetailContextConsumer } from '../../pages/version/index';
import Readme from '../Readme';
import {preventXSS} from '../../utils/sec-utils';
import Tabs from '@material-ui/core/Tabs/index';
import Tab from '@material-ui/core/Tab/index';
import { Content } from './styles';
class DetailContainer extends Component<any, any> {
state = {
tabPosition: 0,
};
render() {
return (
<DetailContextConsumer>
{(context) => {
return this.renderTabs(context);
}}
</DetailContextConsumer>
);
};
renderTabs = ({readMe}) => {
const { tabPosition } = this.state;
return (
<React.Fragment>
<Tabs indicatorColor={'primary'} onChange={this.handleChange} textColor={'primary'} value={tabPosition} variant={'fullWidth'}>
<Tab label={'Readme'} />
<Tab label={'Dependencies'} />
<Tab label={'Versions'} />
<Tab label={'Uplinks'} />
</Tabs>
{tabPosition === 0 && this.renderReadme(readMe)}
</React.Fragment>
);
}
renderReadme = (readMe) => {
const encodedReadme = preventXSS(readMe);
return (<Content><Readme description={encodedReadme}></Readme></Content>);
}
}
export default DetailContainer;

View file

@ -0,0 +1,12 @@
/**
* @prettier
* @flow
*/
import styled from 'react-emotion';
export const Content = styled.div`
&& {
padding: 20px;
}
`;

View file

@ -0,0 +1,12 @@
/**
* @prettier
* @flow
*/
import type { Node } from 'react';
export interface IProps {
children: Node;
open: boolean;
onClose: () => void;
}

View file

@ -0,0 +1,75 @@
/* eslint react/jsx-max-depth: 0 */
import React, {Component} from 'react';
import { DetailContextConsumer } from '../../pages/version/index';
// import Paper from '@material-ui/core/Paper/index';
import Typography from '@material-ui/core/Typography/index';
import Grid from '@material-ui/core/Grid/index';
// import CardHeader from '@material-ui/core/CardHeader';
import Card from '@material-ui/core/Card/index';
import CardContent from '@material-ui/core/CardContent/index';
import { Content } from './styles';
import CopyToClipBoard from '../CopyToClipBoard';
import Button from '@material-ui/core/Button';
import CardActions from '@material-ui/core/CardActions';
// import Paper from '@material-ui/core/Paper/index';
class DetailSidebar extends Component<any, any> {
render() {
return (
<DetailContextConsumer>
{(context) => {
return this.renderSideBar(context);
}}
</DetailContextConsumer>
);
};
renderSideBar = ({packageMeta, packageName}) => {
return (
<React.Fragment>
{this.renderDescription(packageMeta, packageName)}
<Content>
<Grid container={true} spacing={24}>
<Grid item={true} xs={12}>
<Typography color={"textPrimary"} gutterBottom={true} variant={'title'}>
{packageName}
</Typography>
<Typography color={"textSecondary"} gutterBottom={true} variant={'subtitle2'}>
{packageMeta.latest.description}
</Typography>
</Grid>
<Grid item={true} xs={12}>
<Card>
<CardContent>
<CopyToClipBoard text={`npm install ${packageName}`} />
<CopyToClipBoard text={`pnpm install ${packageName}`} />
<CopyToClipBoard text={`yarn add ${packageName}`} />
<CardActions>
<Button color={"primary"} variant={"contained"}>
{'Download Tarball'}
</Button>
</CardActions>
</CardContent>
</Card>
</Grid>
</Grid>
</Content>
</React.Fragment>
);
}
renderDescription = (packageMeta) => {
console.log('packageMeta', packageMeta);
return (
<React.Fragment>
</React.Fragment>
);
}
}
export default DetailSidebar;

View file

@ -0,0 +1,14 @@
/**
* @prettier
* @flow
*/
import styled from 'react-emotion';
import colors from '../../utils/styles/colors';
export const Content = styled.div`
&& {
padding: 10px;
background-color: ${colors.white};
}
`;

View file

@ -0,0 +1,12 @@
/**
* @prettier
* @flow
*/
import type { Node } from 'react';
export interface IProps {
children: Node;
open: boolean;
onClose: () => void;
}

View file

@ -7,7 +7,7 @@ import styled, { css } from 'react-emotion';
export const Content = styled.div` export const Content = styled.div`
&& { && {
background-color: #fff; background-color: #ffffff;
flex: 1; flex: 1;
position: relative; position: relative;
} }

View file

@ -80,7 +80,7 @@ const Package = ({ name: label, version, time, author: { name, avatar }, descrip
); );
return ( return (
<Wrapper className={'package'} to={`detail/${label}`}> <Wrapper className={'package'} to={`version/${label}`}>
<Header> <Header>
{renderMainInfo()} {renderMainInfo()}
<Overview> <Overview>

View file

@ -1,9 +1,21 @@
/**
* @prettier
* @flow
*/
import React, { Component } from 'react'; import React, { Component } from 'react';
import API from '../../utils/api'; import API from '../../utils/api';
import Grid from '@material-ui/core/Grid/index';
import Loading from '../../components/Loading'; import Loading from '../../components/Loading';
import DetailContainer from '../../components/DetailContainer';
import DetailSidebar from '../../components/DetailSidebar';
export const DetailContext = React.createContext();
export const DetailContextProvider = DetailContext.Provider;
export const DetailContextConsumer = DetailContext.Consumer;
class VersionPage extends Component<any, any> { class VersionPage extends Component<any, any> {
state = { state = {
readMe: '', readMe: '',
packageMeta: null, packageMeta: null,
@ -18,6 +30,8 @@ class VersionPage extends Component<any, any> {
async loadPackageInfo() { async loadPackageInfo() {
const { match } = this.props; const { match } = this.props;
const packageName = match.params.package; const packageName = match.params.package;
// FIXME: use utility
document.title = `Verdaccio - ${packageName}`;
this.setState({ this.setState({
readMe: '', readMe: '',
@ -41,11 +55,34 @@ class VersionPage extends Component<any, any> {
} }
render() { render() {
const {isLoading} = this.state; const { isLoading, packageMeta, readMe } = this.state;
const { match } = this.props;
const packageName = match.params.package;
if (isLoading === false) {
return ( return (
<div>{isLoading && <Loading />}</div> <DetailContextProvider value={{ packageMeta, readMe, packageName }}>
<Grid className={'container content'} container={true} spacing={0}>
<Grid item={true} xs={8}>
{this.renderDetail()}
</Grid>
<Grid item={true} xs={4}>
{this.renderSidebar()}
</Grid>
</Grid>
</DetailContextProvider>
); );
} else {
return <Loading />;
}
}
renderDetail() {
return <DetailContainer />;
}
renderSidebar() {
return <DetailSidebar />;
} }
} }

View file

@ -3,7 +3,7 @@
:global { :global {
.container { .container {
padding: 15px; padding: 0px 15px;
flex: 1; flex: 1;
@include container-size; @include container-size;

View file

@ -0,0 +1,12 @@
/**
* @prettier
* @flow
*/
// $FlowFixMe
import parseXSS from 'xss';
export function preventXSS(text: string) {
const encodedText = parseXSS(text);
return encodedText;
}

View file

@ -8,7 +8,7 @@ const colors = {
white: '#fff', white: '#fff',
red: '#d32f2f', red: '#d32f2f',
grey: '#808080', grey: '#808080',
greySuperLight: '#f5f5f5',
greyLight: '#d3d3d3', greyLight: '#d3d3d3',
greyDark: '#a9a9a9', greyDark: '#a9a9a9',
greyChateau: '#95989a', greyChateau: '#95989a',

View file

@ -3594,6 +3594,11 @@ cssesc@^2.0.0:
resolved "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" resolved "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703"
integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg== integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==
cssfilter@0.0.10:
version "0.0.10"
resolved "https://registry.npmjs.org/cssfilter/-/cssfilter-0.0.10.tgz#c6d2672632a2e5c83e013e6864a42ce8defd20ae"
integrity sha1-xtJnJjKi5cg+AT5oZKQs6N79IK4=
cssnano-preset-default@^4.0.6: cssnano-preset-default@^4.0.6:
version "4.0.6" version "4.0.6"
resolved "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.6.tgz#92379e2a6db4a91c0ea727f5f556eeac693eab6a" resolved "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.6.tgz#92379e2a6db4a91c0ea727f5f556eeac693eab6a"
@ -13417,6 +13422,14 @@ xregexp@4.0.0:
resolved "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz#e698189de49dd2a18cc5687b05e17c8e43943020" resolved "https://registry.npmjs.org/xregexp/-/xregexp-4.0.0.tgz#e698189de49dd2a18cc5687b05e17c8e43943020"
integrity sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg== integrity sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg==
xss@1.0.3:
version "1.0.3"
resolved "https://registry.npmjs.org/xss/-/xss-1.0.3.tgz#d04bd2558fd6c29c46113824d5e8b2a910054e23"
integrity sha512-LTpz3jXPLUphMMmyufoZRSKnqMj41OVypZ8uYGzvjkMV9C1EdACrhQl/EM8Qfh5htSAuMIQFOejmKAZGkJfaCg==
dependencies:
commander "^2.9.0"
cssfilter "0.0.10"
xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1:
version "4.0.1" version "4.0.1"
resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" resolved "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"