patternplate-client
Version:
Universal javascript client application for patternplate
168 lines (148 loc) • 4.27 kB
JavaScript
import React, {PropTypes as t} from 'react';
import {sortBy} from 'lodash';
import CSSTransitionGroup from 'react-transition-group/CSSTransitionGroup';
import Markdown from '../common/markdown';
import Message from '../common/message';
import urlQuery from '../../utils/url-query';
import getIdByPathname from '../../utils/get-id-by-pathname';
import PatternFolder from '../pattern/pattern-folder';
import PatternSection from '../pattern/pattern-section';
import navigate from '../../utils/navigate';
export default Content;
const sortTypes = ['folder', 'pattern'];
const rateType = item => sortTypes.indexOf(item.type);
function Content(props) {
const {base, config, location} = props;
const {hierarchy} = config;
const {pathname} = urlQuery.parse(location.pathname);
const id = getIdByPathname(pathname, props.base);
const fragments = id.split('/');
const depth = fragments.length - 1;
const up = depth > 0 ? fragments.slice(0, fragments.length - 1).join('/') : '';
const item = navigate(id, props.navigation);
if (!item) {
return (
<div className="application-container application-container--pattern">
<div className="not-found-section">
<Markdown source={getNotFoundSource(id)}/>
</div>
</div>
);
}
const itemDefaults = {base, location};
const items = sortBy(sortBy(getItems(item, hierarchy, itemDefaults, props.hide), 'name'), rateType);
return (
<div className="application-container application-container--pattern">
{
item.type === 'folder' &&
<PatternFolder
id={id}
location={location}
items={items}
up={up}
base={base}
/>
}
{
item.type === 'pattern' &&
<PatternSection
id={id}
data={props.pattern}
navigation={props.navigation}
config={props.config}
location={location}
type={item.type}
onDataRequest={props.onLoad}
base={base}
/>
}
<CSSTransitionGroup
component="aside"
transitionName="pattern-content-transition"
className="messages"
transitionEnterTimeout={300}
transitionLeaveTimeout={300}
>
{
props.messages.map(message => {
return (
<Message
id={message.id}
key={message.id}
type={message.type}
title={message.subject}
body={message.body || message.stack}
pattern={String(message.pattern).trim()}
payload={message.payload}
retry={message.retry}
file={message.file}
timestamp={message.timestamp}
onDismiss={props.onDismiss}
onRetry={props.onRetry}
location={location}
base={base}
/>
);
})
}
</CSSTransitionGroup>
</div>
);
}
Content.propTypes = {
base: t.string.isRequired,
config: t.object.isRequired,
hide: t.bool.isRequired,
location: t.shape({
pathname: t.string.isRequired
}).isRequired,
navigation: t.object.isRequired,
onDismiss: t.func.isRequired,
onLoad: t.func.isRequired,
onRetry: t.func.isRequired,
pattern: t.object.isRequired,
messages: t.array.isRequired
};
function getItemName(item, hierarchy) {
if (item.type === 'pattern') {
return item.manifest.displayName || item.manifest.name || item.id;
}
const configured = hierarchy[item.id] || {};
return configured.displayName || item.id;
}
function getNotFoundSource(id) {
return `
# Pattern not found
We looked everywhere and could not find pattern \`${id}\`.
You might want to navigate back to [Home](/) or use the search.
---
Help us to make this message more helpful on [GitHub](https://github.com/sinnerschrader/patternplate)
`;
}
function getItems(root, hierarchy, defaults, hide) {
if (root.type !== 'folder') {
return [];
}
return Object.values(root.children)
.map(selectPatternData(hierarchy, defaults, hide))
.filter(item => item.type !== 'pattern' || item.display);
}
function selectPatternData(hierarchy, defaults, hide) {
return child => {
const amend = child.type === 'pattern' ?
{
version: child.manifest.version,
flag: child.manifest.flag,
tags: child.manifest.tags,
display: hide ? child.manifest.display !== false : true
} :
{};
return {
...defaults,
id: child.id,
name: getItemName(child, hierarchy),
type: child.type,
...amend
};
};
}