Refactor Home so that Dev section chrome is reusable across pages

This commit is contained in:
Fabio Berger
2018-10-12 15:54:44 +02:00
parent dcdc411ab7
commit de20ef1a49
14 changed files with 780 additions and 854 deletions

View File

@@ -4,10 +4,8 @@ import {
EtherscanLinkSuffixes,
Link,
MarkdownSection,
NestedSidebarMenu,
Networks,
SectionHeader,
Styles,
utils as sharedUtils,
} from '@0xproject/react-shared';
import {
@@ -21,7 +19,6 @@ import {
TypescriptMethod,
} from '@0xproject/types';
import * as _ from 'lodash';
import CircularProgress from 'material-ui/CircularProgress';
import * as React from 'react';
import * as semver from 'semver';
@@ -43,26 +40,20 @@ const networkNameToColor: { [network: string]: string } = {
[Networks.Rinkeby]: colors.darkYellow,
};
export interface DocumentationProps {
export interface DocReferenceProps {
selectedVersion: string;
availableVersions: string[];
docsInfo: DocsInfo;
sourceUrl: string;
onVersionSelected: (semver: string) => void;
docAgnosticFormat?: DocAgnosticFormat;
sidebarHeader?: React.ReactNode;
topBarHeight?: number;
}
export interface DocumentationState {
export interface DocReferenceState {
isHoveringSidebar: boolean;
}
export class Documentation extends React.Component<DocumentationProps, DocumentationState> {
public static defaultProps: Partial<DocumentationProps> = {
topBarHeight: 0,
};
constructor(props: DocumentationProps) {
export class DocReference extends React.Component<DocReferenceProps, DocReferenceState> {
constructor(props: DocReferenceProps) {
super(props);
this.state = {
isHoveringSidebar: false,
@@ -74,112 +65,25 @@ export class Documentation extends React.Component<DocumentationProps, Documenta
public componentWillUnmount(): void {
window.removeEventListener('hashchange', this._onHashChanged.bind(this), false);
}
public componentDidUpdate(prevProps: DocumentationProps, _prevState: DocumentationState): void {
public componentDidUpdate(prevProps: DocReferenceProps, _prevState: DocReferenceState): void {
if (!_.isEqual(prevProps.docAgnosticFormat, this.props.docAgnosticFormat)) {
const hash = window.location.hash.slice(1);
sharedUtils.scrollToHash(hash, sharedConstants.SCROLL_CONTAINER_ID);
}
}
public render(): React.ReactNode {
const styles: Styles = {
mainContainers: {
position: 'absolute',
top: 1,
left: 0,
bottom: 0,
right: 0,
overflowX: 'hidden',
overflowY: 'scroll',
minHeight: `calc(100vh - ${this.props.topBarHeight}px)`,
WebkitOverflowScrolling: 'touch',
},
menuContainer: {
borderColor: colors.grey300,
maxWidth: 330,
marginLeft: 20,
},
};
const sectionNameToLinks = this.props.docsInfo.getSectionNameToLinks();
const subsectionNameToLinks = this.props.docsInfo.getSubsectionNameToLinks(this.props.docAgnosticFormat);
return (
<div>
{_.isUndefined(this.props.docAgnosticFormat) ? (
this._renderLoading(styles.mainContainers)
) : (
<div style={{ width: '100%', height: '100%', backgroundColor: colors.gray40 }}>
<div
className="mx-auto max-width-4 flex"
style={{ color: colors.grey800, height: `calc(100vh - ${this.props.topBarHeight}px)` }}
>
<div
className="relative sm-hide xs-hide"
style={{ width: '36%', height: `calc(100vh - ${this.props.topBarHeight}px)` }}
>
<div
className="border-right absolute"
style={{
...styles.menuContainer,
...styles.mainContainers,
height: `calc(100vh - ${this.props.topBarHeight}px)`,
overflow: this.state.isHoveringSidebar ? 'auto' : 'hidden',
}}
onMouseEnter={this._onSidebarHover.bind(this)}
onMouseLeave={this._onSidebarHoverOff.bind(this)}
>
<NestedSidebarMenu
selectedVersion={this.props.selectedVersion}
versions={this.props.availableVersions}
sidebarHeader={this.props.sidebarHeader}
sectionNameToLinks={sectionNameToLinks}
subsectionNameToLinks={subsectionNameToLinks}
onVersionSelected={this.props.onVersionSelected}
/>
</div>
</div>
<div
className="relative col lg-col-9 md-col-9 sm-col-12 col-12"
style={{ backgroundColor: colors.white }}
>
<div
id={sharedConstants.SCROLL_CONTAINER_ID}
style={styles.mainContainers}
className="absolute px1"
>
<div id={sharedConstants.SCROLL_TOP_ID} />
{this._renderDocumentation()}
</div>
</div>
</div>
</div>
)}
</div>
);
}
private _renderLoading(mainContainersStyles: React.CSSProperties): React.ReactNode {
return (
<div className="col col-12" style={mainContainersStyles}>
<div
className="relative sm-px2 sm-pt2 sm-m1"
style={{ height: 122, top: '50%', transform: 'translateY(-50%)' }}
>
<div className="center pb2">
<CircularProgress size={40} thickness={5} />
</div>
<div className="center pt2" style={{ paddingBottom: 11 }}>
Loading documentation...
</div>
</div>
</div>
);
}
private _renderDocumentation(): React.ReactNode {
const subMenus = _.values(this.props.docsInfo.menu);
const subMenus = _.values(this.props.docsInfo.markdownMenu);
const orderedSectionNames = _.flatten(subMenus);
const typeDefinitionByName = this.props.docsInfo.getTypeDefinitionsByName(this.props.docAgnosticFormat);
const renderedSections = _.map(orderedSectionNames, this._renderSection.bind(this, typeDefinitionByName));
return renderedSections;
return (
<div>
<div id={sharedConstants.SCROLL_TOP_ID} />
{renderedSections}
</div>
);
}
private _renderSection(typeDefinitionByName: TypeDefinitionByName, sectionName: string): React.ReactNode {
const markdownVersions = _.keys(this.props.docsInfo.sectionNameToMarkdownByVersion);

View File

@@ -17,7 +17,7 @@ export class DocsInfo {
public displayName: string;
public packageName: string;
public packageUrl: string;
public menu: DocsMenu;
public markdownMenu: DocsMenu;
public typeSectionName: string;
public sections: SectionsMap;
public sectionNameToMarkdownByVersion: SectionNameToMarkdownByVersion;
@@ -25,7 +25,7 @@ export class DocsInfo {
constructor(config: DocsInfoConfig) {
this.id = config.id;
this.type = config.type;
this.menu = config.markdownMenu;
this.markdownMenu = config.markdownMenu;
this.displayName = config.displayName;
this.packageName = config.packageName;
this.packageUrl = config.packageUrl;
@@ -34,10 +34,31 @@ export class DocsInfo {
this.sectionNameToMarkdownByVersion = config.sectionNameToMarkdownByVersion;
this.contractsByVersionByNetworkId = config.contractsByVersionByNetworkId;
}
public getSubsectionNameToLinks(docAgnosticFormat?: DocAgnosticFormat): ObjectMap<ALink[]> {
const subsectionNameToLinks: ObjectMap<ALink[]> = {};
public getTypeDefinitionsByName(docAgnosticFormat: DocAgnosticFormat): { [name: string]: TypeDefinitionByName } {
if (_.isUndefined(docAgnosticFormat[this.typeSectionName])) {
return {};
}
const section = docAgnosticFormat[this.typeSectionName];
const typeDefinitionByName = _.keyBy(section.types, 'name') as any;
return typeDefinitionByName;
}
public getSectionNameToLinks(docAgnosticFormat: DocAgnosticFormat): ObjectMap<ALink[]> {
const sectionNameToLinks: ObjectMap<ALink[]> = {};
_.each(this.markdownMenu, (linkTitles, sectionName) => {
sectionNameToLinks[sectionName] = [];
_.each(linkTitles, linkTitle => {
const to = sharedUtils.getIdFromName(linkTitle);
const links = sectionNameToLinks[sectionName];
links.push({
title: linkTitle,
to,
});
});
});
if (_.isUndefined(docAgnosticFormat)) {
return subsectionNameToLinks;
return sectionNameToLinks;
}
const docSections = _.keys(this.sections);
@@ -64,7 +85,7 @@ export class DocsInfo {
title: typeName,
};
});
subsectionNameToLinks[sectionName] = typeLinks;
sectionNameToLinks[sectionName] = typeLinks;
} else if (isExportedFunctionSection) {
// Noop so that we don't have the method listed underneath itself.
} else {
@@ -88,33 +109,9 @@ export class DocsInfo {
};
});
subsectionNameToLinks[sectionName] = links;
sectionNameToLinks[sectionName] = links;
}
});
return subsectionNameToLinks;
}
public getTypeDefinitionsByName(docAgnosticFormat: DocAgnosticFormat): { [name: string]: TypeDefinitionByName } {
if (_.isUndefined(docAgnosticFormat[this.typeSectionName])) {
return {};
}
const section = docAgnosticFormat[this.typeSectionName];
const typeDefinitionByName = _.keyBy(section.types, 'name') as any;
return typeDefinitionByName;
}
public getSectionNameToLinks(): ObjectMap<ALink[]> {
const sectionNameToLinks: ObjectMap<ALink[]> = {};
_.each(this.menu, (linkTitles, sectionName) => {
sectionNameToLinks[sectionName] = [];
_.each(linkTitles, linkTitle => {
const to = sharedUtils.getIdFromName(linkTitle);
const links = sectionNameToLinks[sectionName];
links.push({
title: linkTitle,
to,
});
});
});
return sectionNameToLinks;
}
}

View File

@@ -5,7 +5,7 @@ export { DocAgnosticFormat, GeneratedDocJson } from '@0xproject/types';
export { Badge } from './components/badge';
export { Comment } from './components/comment';
export { CustomEnum } from './components/custom_enum';
export { Documentation } from './components/documentation';
export { DocReference } from './components/doc_reference';
export { Enum } from './components/enum';
export { EventDefinition } from './components/event_definition';
export { Interface } from './components/interface';

View File

@@ -95,7 +95,9 @@ export class TypeDocUtils {
if (!_.isEmpty(this._externalExportToLink)) {
this._docsInfo.sections[constants.EXTERNAL_EXPORTS_SECTION_NAME] = constants.EXTERNAL_EXPORTS_SECTION_NAME;
this._docsInfo.menu[constants.EXTERNAL_EXPORTS_SECTION_NAME] = [constants.EXTERNAL_EXPORTS_SECTION_NAME];
this._docsInfo.markdownMenu[constants.EXTERNAL_EXPORTS_SECTION_NAME] = [
constants.EXTERNAL_EXPORTS_SECTION_NAME,
];
const docSection: DocSection = {
comment: 'This package also re-exports some third-party libraries for your convenience.',
constructors: [],
@@ -119,7 +121,7 @@ export class TypeDocUtils {
case KindString.ObjectLiteral: {
sectionName = child.name;
this._docsInfo.sections[sectionName] = sectionName;
this._docsInfo.menu[sectionName] = [sectionName];
this._docsInfo.markdownMenu[sectionName] = [sectionName];
const entities = child.children;
const commentObj = child.comment;
const sectionComment = !_.isUndefined(commentObj) ? commentObj.shortText : '';
@@ -136,7 +138,7 @@ export class TypeDocUtils {
case KindString.Function: {
sectionName = child.name;
this._docsInfo.sections[sectionName] = sectionName;
this._docsInfo.menu[sectionName] = [sectionName];
this._docsInfo.markdownMenu[sectionName] = [sectionName];
const entities = [child];
const commentObj = child.comment;
const SectionComment = !_.isUndefined(commentObj) ? commentObj.shortText : '';
@@ -158,7 +160,7 @@ export class TypeDocUtils {
});
if (!_.isEmpty(typeEntities)) {
this._docsInfo.sections[constants.TYPES_SECTION_NAME] = constants.TYPES_SECTION_NAME;
this._docsInfo.menu[constants.TYPES_SECTION_NAME] = [constants.TYPES_SECTION_NAME];
this._docsInfo.markdownMenu[constants.TYPES_SECTION_NAME] = [constants.TYPES_SECTION_NAME];
const docSection = this._convertEntitiesToDocSection(typeEntities, constants.TYPES_SECTION_NAME);
docAgnosticFormat[constants.TYPES_SECTION_NAME] = docSection;
}