Commit 044c1d3f authored by Viacheslav Pavlov's avatar Viacheslav Pavlov

Documentation display

parent e52c6bb0
// constants
import {RECEIVE_ARTICLE, RECEIVE_MENU} from 'cms/constants';
import {RECEIVE_ARTICLE, RECEIVE_DOCUMENTATION, RECEIVE_MENU} from 'cms/constants';
// model
import Article from 'model/cms/Article';
import Menu from 'model/cms/Menu';
import ADoc from 'model/cms/ADoc';
// service
import CmsService from 'service/genesys/CmsService';
import AsciiDocService from 'service/genesys/AsciiDocService';
const receiveArticle = (slug: string, article: Article) => ({
type: RECEIVE_ARTICLE,
......@@ -16,6 +18,16 @@ export const loadArticle = (locale: string, slug: string) => (dispatch) => {
.then((article) => dispatch(receiveArticle(slug, article)));
};
const receiveDocumentation = (slug: string, documentation: ADoc) => ({
type: RECEIVE_DOCUMENTATION,
payload: {slug, documentation},
});
export const loadDocumentation = (slug: string) => (dispatch) => {
AsciiDocService.viewDoc(slug)
.then((article) => dispatch(receiveDocumentation(slug, article)));
};
const receiveMenu = (menuKey: string, menuItem: Menu) => ({
type: RECEIVE_MENU,
payload: {menuKey, menuItem},
......
export const RECEIVE_ARTICLE = 'cms/public/RECEIVE_ARTICLE';
export const RECEIVE_DOCUMENTATION = 'cms/public/RECEIVE_DOCUMENTATION';
export const RECEIVE_MENU = 'cms/public/RECEIVE_MENU';
import {RECEIVE_ARTICLE, RECEIVE_MENU} from 'cms/constants';
import { RECEIVE_ARTICLE, RECEIVE_DOCUMENTATION, RECEIVE_MENU } from 'cms/constants';
import update from 'immutability-helper';
const INITIAL_STATE: {
articles: any,
documentations: any,
menus: any,
} = {
articles: {},
documentations: {},
menus: {},
};
......@@ -19,6 +21,13 @@ export default function listPublic(state = INITIAL_STATE, action: { type?: strin
[slug]: {$set: article},
},
});
} case RECEIVE_DOCUMENTATION: {
const {slug, documentation} = action.payload;
return update(state, {
documentations: {
[slug]: {$set: documentation},
},
});
}
case RECEIVE_MENU: {
const {menuKey, menuItem} = action.payload;
......
import ContentPage from 'cms/ui/ContentPage';
import DocumentationPage from 'cms/ui/DocumentationPage';
const publicRoutes = [
......@@ -10,6 +11,10 @@ const publicRoutes = [
path: '/content/:slug',
component: ContentPage,
},
{
path: '/documentation/:slug',
component: DocumentationPage,
},
];
export {publicRoutes as cmsPublicRoutes};
import * as React from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import { translate } from 'react-i18next';
// Actions
import {loadDocumentation} from 'cms/actions/public';
// Model
import ADoc from 'model/cms/ADoc';
// UI
import PageLayout from 'ui/layout/PageLayout';
import ContentHeader from 'ui/common/heading/ContentHeader';
import DocumentationSection from './c/DocumentationSection';
import Grid from '@material-ui/core/Grid';
interface IDocumentationPageProps {
slug: string;
t: any;
i18n: any;
documentation: ADoc;
loadDocumentation: (slug: string) => void;
}
class ContentPage extends React.Component<IDocumentationPageProps> {
protected static needs = [
({ params, state }) => loadDocumentation(params.slug),
];
public componentWillMount() {
const { slug, documentation, loadDocumentation } = this.props;
if (!documentation) {
loadDocumentation(slug);
}
}
public componentWillReceiveProps(nextProps) {
const { slug, documentation, loadDocumentation } = nextProps;
if (!documentation) {
loadDocumentation(slug);
}
}
public render() {
const {documentation} = this.props;
return (
<PageLayout withFooter>
{ documentation &&
<Grid container>
<ContentHeader title={ documentation.title } />
<DocumentationSection documentation={ documentation }/>
</Grid>
}
</PageLayout>
);
}
}
const mapStateToProps = (state, ownProps) => ({
slug: ownProps.match.params.slug,
documentation: state.cms.public.documentations[ownProps.match.params.slug],
});
const mapDispatchToProps = (dispatch) => bindActionCreators({
loadDocumentation,
}, dispatch);
export default translate()(connect(mapStateToProps, mapDispatchToProps)(ContentPage));
import * as React from 'react';
import withStyles from '@material-ui/core/styles/withStyles';
import ADoc from 'model/cms/ADoc';
import Grid from '@material-ui/core/Grid';
import GridContainer from 'ui/layout/GridContainer';
const styles = (theme) => ({
/*tslint:disable*/
root: {
width: '100%',
minHeight: 'calc(100vh - 365px)',
margin: 0,
'& > p': {
fontFamily: 'Roboto-Light',
fontSize: '24px',
color: '#4d4c46',
lineHeight: '36px',
margin: 0,
},
'& > h3': {
fontSize: '24px',
marginTop: '28px',
paddingBottom: '6px',
},
'& > ul': {
marginTop: '30px',
padding: 0,
paddingLeft: '11px',
},
'& > ul > li': {
fontFamily: 'Roboto-Regular',
fontSize: '18px',
lineHeight: '30px',
},
'& > div': {
width: '100%',
}
},
white: {
backgroundColor: 'white',
},
content: {
width: '100%',
boxSizing: 'border-box' as 'border-box',
fontFamily: 'arial, sans-serif',
fontSize: '16px',
lineHeight: 1.4285,
color: '#000',
'& p': {
margin: '0 0 11px',
color: '#4d4c46',
marginTop: '20px',
marginBottom: '0',
fontFamily: 'Roboto-Regular',
'&:first-child': {
[theme.breakpoints.down('sm')]: {
lineHeight: '26px',
fontSize: '20px',
marginTop: '33px',
paddingRight: 0,
},
},
},
'& h2': {
fontSize: '34px',
marginTop: '-78px',
},
'& h3': {
fontSize: '24px',
marginTop: '-89px',
},
'& h4': {
fontSize: '20px',
marginTop: '-72px',
},
'& h2, & h3, & h4': {
marginBottom: '11px',
fontWeight: 700,
lineHeight: '1.1',
color: 'inherit',
paddingTop: '100px',
},
'& img': {
display: 'inline-block' as 'inline-block',
verticalAlign: 'middle' as 'middle',
maxWidth: '100%',
height: 'auto' as 'auto',
textAlign: 'center' as 'center',
border: '0',
},
'& table': {
wordWrap: 'break-word' as 'break-word',
tableLayout: 'fixed' as 'fixed',
'& th': {
textAlign: 'left' as 'left',
}
},
'& caption': {
paddingTop: '8px',
paddingBottom: '8px',
color: '#777777',
textAlign: 'left' as 'left',
},
'& code': {
padding: '2px 4px',
fontSize: '90%',
color: '#c7254e',
backgroundColor: '#f9f2f4',
borderRadius: '4px',
fontFamily: 'Menlo, Monaco, Consolas, "Courier New", monospace',
},
'& pre': {
display: 'block' as 'block',
padding: '10.5px',
margin: '0 0 11px',
fontSize: '15px',
lineHeight: '1.428571429',
wordBreak: 'break-all' as 'break-all',
wordWrap: 'break-word' as 'break-word',
color: '#333333',
backgroundColor: '#f5f5f5',
border: 'none',
overflow: 'auto' as 'auto',
fontFamily: ' Menlo, Monaco, Consolas, "Courier New", monospace',
'& > code': {
padding: 0,
color: 'inherit' as 'inherit',
whiteSpace: 'pre-wrap' as 'pre-wrap',
backgroundColor: 'transparent' as 'transparent',
},
'& .key': {
color: '#808 !important',
'& .delimeter': {
color: '#606 !important',
},
},
'& .string': {
color: '#d20 !important',
'& .delimeter': {
color: '#d1 !important',
},
},
'& .value': {
color: '#088 !important',
},
'& .integer, & .float': {
color: '#099 !important',
},
},
'& > .sect1': {
'& > h2': {
marginTop: '-78px',
paddingTop: '100px',
overflowWrap: 'break-word' as 'break-word',
wordWrap: 'break-word' as 'break-word',
}
}
},
toc: {
width: 'calc(100% - 1rem)',
marginLeft: '1rem',
}
/*tslint:enable*/
});
interface IDocumentationSectionProps extends React.ClassAttributes<any> {
documentation: ADoc;
classes: any;
}
class DocumentationSection extends React.Component<IDocumentationSectionProps> {
public render() {
const {documentation, classes} = this.props;
return(
<GridContainer className={ `${classes.root} container-spacing-vertical` }>
<Grid item sm={ 12 } md={ 9 } className={ classes.white } >
<div className={ classes.content } dangerouslySetInnerHTML={ {__html: documentation.content} }/>
</Grid>
<Grid item sm={ 12 } md={ 3 }>
<div className={ `${classes.toc} ${classes.white}` } dangerouslySetInnerHTML={ {__html: documentation.toc} }/>
</Grid>
</GridContainer>
);
}
}
export default withStyles(styles)(DocumentationSection);
/*
* Defined in Swagger as '#/definitions/ADoc'
*/
class ADoc {
public content: string;
public footer: string;
public header: string;
public title: string;
public toc: string;
}
export default ADoc;
import * as UrlTemplate from 'url-template';
import { axiosBackend } from 'utilities/requestUtils';
import ADoc from 'model/cms/ADoc';
const URL_GET_IMAGE = UrlTemplate.parse(`/api/v1/cms/d/images/{imageName}`);
const URL_VIEW_SECTION = UrlTemplate.parse(`/api/v1/cms/d/sections/{documentName}`);
const URL_VIEW_DOC = UrlTemplate.parse(`/api/v1/cms/d/{documentName}`);
/*
* Defined in Swagger as 'asciiDoc'
*/
class AsciiDocService {
/**
* getImage at /api/v1/cms/d/images/{imageName}
*
* @param imageName imageName
*/
public static getImage(imageName: string): Promise<string> {
const apiUrl = URL_GET_IMAGE.expand({imageName});
// console.log(`Fetching from ${apiUrl}`);
const content = { /* No content in request body */ };
return axiosBackend({
url: apiUrl,
method: 'GET',
...content,
}).then(({ data }) => data as string);
}
/**
* viewSection at /api/v1/cms/d/sections/{documentName}
*
* @param documentName documentName
*/
public static viewSection(documentName: string): Promise<ADoc> {
const apiUrl = URL_VIEW_SECTION.expand({documentName});
// console.log(`Fetching from ${apiUrl}`);
const content = { /* No content in request body */ };
return axiosBackend({
url: apiUrl,
method: 'GET',
...content,
}).then(({ data }) => data as ADoc);
}
/**
* viewDoc at /api/v1/cms/d/{documentName}
*
* @param documentName documentName
*/
public static viewDoc(documentName: string): Promise<ADoc> {
const apiUrl = URL_VIEW_DOC.expand({documentName});
// console.log(`Fetching from ${apiUrl}`);
const content = { /* No content in request body */ };
return axiosBackend({
url: apiUrl,
method: 'GET',
...content,
}).then(({ data }) => data as ADoc);
}
}
export default AsciiDocService;
......@@ -107,11 +107,11 @@ const PUBLIC_MENUS = [
],
},
{
to: '/documentation', // TODO
to: '/documentation',
label: 'public.menu.documentation',
subMenus: [
{
to: '/documentation/api', // TODO
to: '/documentation/apis',
label: 'public.menu.api',
},
{
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment