Cleanup and file reorganization

This commit is contained in:
Tom Raithel
2017-02-20 19:33:39 +01:00
parent 6cfd53a47a
commit 9f33c7a8ca
30 changed files with 176 additions and 446 deletions

18
common/config.js Normal file
View File

@@ -0,0 +1,18 @@
export const getPageNames = (radar) => {
return [
'index',
'overview',
'help',
'foo/bar',
]
}
const mappings = {
'languages-and-frameworks': 'Languages & Frameworks',
'methods-and-patterns': 'Methods & Patterns',
'platforms-and-aoe-services': 'Platforms and AOE Services',
'tools': 'Tools',
};
const formatRelease = (release) => moment(release, 'YYYY-MM-DD').format('MMM YYYY');

View File

@@ -1,3 +1,4 @@
import { outputFile } from 'fs-extra';
import path from 'path'; import path from 'path';
import { walk } from 'walk'; import { walk } from 'walk';
@@ -13,10 +14,6 @@ export const staticPath = (...pathInSrc) => (
relativePath('static-pages', ...pathInSrc) relativePath('static-pages', ...pathInSrc)
); );
export const templatesPath = (...pathInSrc) => (
relativePath('templates', ...pathInSrc)
);
export const stylesPath = (...pathInSrc) => ( export const stylesPath = (...pathInSrc) => (
relativePath('styles', ...pathInSrc) relativePath('styles', ...pathInSrc)
); );
@@ -37,10 +34,6 @@ export const getAllMarkdownFiles = (folder) => (
getAllFiles(folder, isMarkdownFile) getAllFiles(folder, isMarkdownFile)
); );
export const getAllPugFiles = (folder) => (
getAllFiles(folder, isPugFile)
);
const getAllFiles = (folder, predicate) => ( const getAllFiles = (folder, predicate) => (
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
const walker = walk(folder, { followLinks: false }); const walker = walk(folder, { followLinks: false });
@@ -69,4 +62,14 @@ const getAllFiles = (folder, predicate) => (
const isMarkdownFile = (name) => name.match(/\.md$/); const isMarkdownFile = (name) => name.match(/\.md$/);
const isPugFile = (name) => name.match(/\.pug$/); export const save = (html, fileName) => (
new Promise((resolve, reject) => (
outputFile(distPath(fileName), html, (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
})
))
);

View File

@@ -7,11 +7,6 @@ import {
distPath, distPath,
getAllMarkdownFiles, getAllMarkdownFiles,
} from './file'; } from './file';
import {
item as itemTemplate,
quadrant as quadrantTemplate,
vars,
} from './template';
export const createRadar = async (tree) => { export const createRadar = async (tree) => {
const fileNames = (await getAllMarkdownFiles(radarPath())); const fileNames = (await getAllMarkdownFiles(radarPath()));
@@ -182,50 +177,6 @@ const revisionCreatesNewHistoryEntry = (revision) => {
typeof revision.ring !== 'undefined'; typeof revision.ring !== 'undefined';
}; };
export const outputRadar = ({ items }) => {
const quadrants = groupByQuadrants(items);
Object.entries(quadrants).map(([quadrantName, quadrant]) => (
outputQuadrantPage(quadrantName, quadrant)
));
return Promise.all(
items.map(async (item) => {
// Object.entries(quadrant).map(([itemName, item]) => (
new Promise((resolve, reject) => {
outputFile(distPath(item.quadrant, `${item.name}.html`), itemTemplate(vars({
itemsInRing: quadrants[item.quadrant][item.ring],
item,
})), (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
})
})
// ))
})
);
};
const outputQuadrantPage = (quadrantName, quadrant) => (
new Promise((resolve, reject) => {
outputFile(distPath(`${quadrantName}.html`), quadrantTemplate(vars({
quadrantName,
quadrant,
})), (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
})
})
)
const flagWithIsNew = (items, allReleases) => ( const flagWithIsNew = (items, allReleases) => (
items.map((item) => ({ items.map((item) => ({
...item, ...item,

View File

@@ -1,10 +0,0 @@
import React from 'react';
import HeroHeadline from './HeroHeadline';
export default function PageOverview() {
return (
<div>
Overview
</div>
);
}

25
js/client.js Normal file
View File

@@ -0,0 +1,25 @@
import React from 'react'
import { render } from 'react-dom'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import App from './components/App'
const appReducer = (state = {}, action) => {
return state;
}
// Grab the state from a global variable injected into the server-generated HTML
const preloadedState = window.__TECHRADAR__;
// Allow the passed state to be garbage-collected
delete window.__TECHRADAR__;
// Create Redux store with initial state
const store = createStore(appReducer, preloadedState)
render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
)

View File

@@ -0,0 +1,9 @@
import React from 'react';
export default function({ children }) {
return (
<div className="headline-group">
{children}
</div>
);
}

View File

@@ -0,0 +1,86 @@
import React from 'react';
import classNames from 'classnames';
import HeadlineGroup from './HeadlineGroup';
import HeroHeadline from './HeroHeadline';
const rings = ['all', 'assess', 'trial', 'hold', 'adopt'];
class PageOverview extends React.Component {
constructor(...args) {
super(...args);
this.state = {
ring: rings[0],
};
}
handleRingClick = (ring) => (e) => {
e.preventDefault();
this.setState({
...this.state,
ring,
});
}
isRingActive(ringName) {
return this.state.ring === ringName;
}
render() {
return (
<div>
<HeadlineGroup>
<HeroHeadline>Technologies Overview</HeroHeadline>
</HeadlineGroup>
<div className="filter">
<div className="nav">
{
rings.map(ringName => (
<div className="nav__item" key={ringName}>
<a
className={classNames('badge badge--big', {
'badge--empty': !this.isRingActive(ringName),
[`badge--${ringName}`]: this.isRingActive(ringName),
})}
onClick={this.handleRingClick(ringName)}
href="#"
>
{ringName}
</a>
</div>
))
}
</div>
</div>
<div className="letter-index">
<div className="letter-index__group">
<div className="letter-index__letter">B</div>
<div className="letter-index__items">
<div className="item-list">
<div className="item-list__list">
<a className="item item--big item--no-leading-border item--no-trailing-border" href="/platforms-and-aoe-services/bar.html">
<div className="split split--overview">
<div className="split__left">
<div className="item__title">Bar</div>
</div>
<div className="split__right">
<div className="nav">
<div className="nav__item">Platforms and AOE Services</div>
<div className="nav__item"><span className="badge badge--assess">assess</span></div>
</div>
</div>
</div>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default PageOverview;

View File

@@ -1,18 +0,0 @@
import filter from './filter';
import details from './details';
import applyPjax from './pjax';
const enhanceComponent = (selector, enhancer, fromPjax = false) => {
const $filter = [].slice.call(document.querySelectorAll(selector));
$filter.map((e) => enhancer(e, fromPjax));
}
const enhanceComponents = (fromPjax) => {
enhanceComponent('.js--filter', filter, fromPjax);
enhanceComponent('.js--details', details, fromPjax);
}
applyPjax();
enhanceComponents();
document.addEventListener("pjax:success", () => enhanceComponents(true));

View File

@@ -1,30 +1,14 @@
import { outputFile } from 'fs-extra';
import React from 'react'; import React from 'react';
import { renderToString } from 'react-dom/server'; import { renderToString } from 'react-dom/server';
import { createStore } from 'redux'; import { createStore } from 'redux';
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import { distPath } from './file'; import App from './components/App';
import App from '../components/App';
const appReducer = (state = {}, action) => { const appReducer = (state = {}, action) => {
return state; return state;
} }
const getPageNames = (radar) => {
return [
'index',
'overview',
'help',
'foo/bar',
]
}
export const renderApp = (radar) => {
const pageNames = getPageNames(radar);
pageNames.map(pageName => renderPage(radar, pageName))
}
export const renderPage = (radar, pageName) => { export const renderPage = (radar, pageName) => {
// Create a new Redux store instance // Create a new Redux store instance
const store = createStore(appReducer, { const store = createStore(appReducer, {
@@ -43,10 +27,10 @@ export const renderPage = (radar, pageName) => {
const preloadedState = store.getState() const preloadedState = store.getState()
// Send the rendered page back to the client // Send the rendered page back to the client
const fullHtml = renderFullPage(html, preloadedState); return renderFullPage(html, preloadedState);
// Save file // Save file
save(fullHtml, pageName); // return save(fullHtml, pageName);
} }
const renderFullPage = (html, preloadedState) => { const renderFullPage = (html, preloadedState) => {
@@ -59,34 +43,10 @@ const renderFullPage = (html, preloadedState) => {
<body> <body>
<div id="root">${html}</div> <div id="root">${html}</div>
<script> <script>
window.__PRELOADED_STATE__ = ${JSON.stringify(preloadedState)} window.__TECHRADAR__ = ${JSON.stringify(preloadedState)}
</script> </script>
<script src="/bundle.js"></script> <script src="/bundle.js"></script>
</body> </body>
</html> </html>
<!doctype html>
<html>
<head>
<title>Redux Universal Example</title>
</head>
<body>
<script src="/static/bundle.js"></script>
</body>
</html>
` `
} }
const save = (html, pageName) => (
new Promise((resolve, reject) => (
outputFile(distPath(`${pageName}.html`), html, (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
})
))
);

View File

@@ -24,22 +24,20 @@
"babel-preset-latest": "6.22.0", "babel-preset-latest": "6.22.0",
"babel-preset-react": "6.23.0", "babel-preset-react": "6.23.0",
"babel-preset-stage-0": "6.22.0", "babel-preset-stage-0": "6.22.0",
"classnames": "2.2.5",
"front-matter": "2.1.2", "front-matter": "2.1.2",
"fs-extra": "2.0.0", "fs-extra": "2.0.0",
"live-server": "1.2.0", "live-server": "1.2.0",
"marked": "0.3.6", "marked": "0.3.6",
"moment": "2.17.1", "moment": "2.17.1",
"pjax": "0.2.4",
"postcss-cli": "2.6.0", "postcss-cli": "2.6.0",
"postcss-css-variables": "0.6.0", "postcss-css-variables": "0.6.0",
"postcss-easy-import": "2.0.0", "postcss-easy-import": "2.0.0",
"postcss-nested": "1.0.0", "postcss-nested": "1.0.0",
"pug": "2.0.0-beta9",
"react": "15.4.2", "react": "15.4.2",
"react-dom": "15.4.2", "react-dom": "15.4.2",
"react-redux": "5.0.2", "react-redux": "5.0.2",
"redux": "3.6.0", "redux": "3.6.0",
"vue": "2.1.10",
"walk": "2.3.9", "walk": "2.3.9",
"webpack": "2.2.0" "webpack": "2.2.0"
} }

View File

@@ -1,14 +0,0 @@
extends ../templates/default-page.pug
block vars
- var noLogo=true
- var title="How to Use Technology Radar"
block content
.headline-group
h1.hero-headline
| How to Use Technology Radar
.markdown
h2 What are quadrants?
p
| TODO

View File

@@ -1,35 +0,0 @@
extends ../templates/default-page.pug
block vars
- var title='AOE Technology Radar'
block content
.headline-group
.hero-headline
| Technology Radar
span.hero-headline__alt
= ' '
= formatRelease(releases[releases.length - 1])
div.quadrant-grid
each quadrant, quadrantName in groupByQuadrants(items)
.quadrant-grid__quadrant
.quadrant-section
.quadrant-section__header
.split
.split__left
h4.headline= translate(quadrantName)
.split__right
a.icon-link(href=`/${quadrantName}.html`)
span.icon.icon--pie.icon-link__icon
| Quadrant Overview
.quadrant-section__rings
each items, ringName in quadrant
.quadrant-section__ring
.ring-list
.ring-list__header
span(class=`badge badge--${ringName}`)
= ringName
each item in items
span.ring-list__item
a.link(href='/' + quadrantName + '/' + item.name + '.html')
= item.title

View File

@@ -1,59 +0,0 @@
extends ../templates/default-page.pug
block vars
- var noLogo=true
- var title='Technologies Overview'
block content
.js--filter(
data-index=JSON.stringify(groupByFirstLetter(items))
)
.headline-group
.hero-headline
| Technologies Overview
.filter
.nav
.nav__item
a.badge.badge--big(
href='#'
v-on:click="setRing('all')"
v-bind:class=`ring === 'all' ? 'badge--neutral' : ''`
) all
each _, ringName in groupByRing(items)
.nav__item
a.badge.badge--big.badge--empty(
href='#'
v-on:click=`setRing('${ringName}')`
v-bind:class=`ring === '${ringName}' ? 'badge--${ringName}' : ''`
)= ringName
div.letter-index
each indexItems, letter in groupByFirstLetter(items)
.letter-index__group(
v-if=`isGroupVisible('${letter}')`
)
.letter-index__letter= letter
.letter-index__items
.item-list
.item-list__list
each item in indexItems
a.item.item--big.item--no-leading-border.item--no-trailing-border(
href=`/${item.quadrant}/${item.name}.html`
v-if=`isRingVisible('${item.ring}')`
)
.split.split--overview
.split__left
.item__title
= item.title
if item.isNew
= ' '
span.is-new new
if item.info
.item__info= item.info
.split__right
.nav
.nav__item
= translate(item.quadrant)
.nav__item
span(class=`badge badge--${item.ring}`)
= item.ring

View File

@@ -20,7 +20,7 @@
padding: 0 20px; padding: 0 20px;
} }
&--neutral { &--all {
background: var(--color-gray-normal); background: var(--color-gray-normal);
border-color: var(--color-gray-normal); border-color: var(--color-gray-normal);
} }

View File

@@ -2,7 +2,7 @@ import { copy } from 'fs-extra';
import { import {
assetsPath, assetsPath,
distPath, distPath,
} from './file'; } from '../common/file';
copy(assetsPath(), distPath('assets'), (err) => { copy(assetsPath(), distPath('assets'), (err) => {
if (err) { if (err) {

View File

@@ -2,16 +2,26 @@ import {
createRadar, createRadar,
groupByQuadrants, groupByQuadrants,
outputRadar, outputRadar,
} from './radar'; } from '../common/radar';
import { import { save } from '../common/file';
renderApp, import { getPageNames } from '../common/config';
} from './static'; import { renderPage } from '../js/server';
(async () => { (async () => {
try { try {
const radar = await createRadar(); const radar = await createRadar();
renderApp(radar);
getPageNames(radar).map((pageName) => {
const pageHtml = renderPage(radar, pageName);
console.log(pageHtml);
save(pageHtml, `${pageName}.html`);
});
// pages.map((pageHtml) => {
// save(pageHtml, `${pageName}.html`)
// });
// console.log(pages);
// outputRadar(radar); // outputRadar(radar);
// const radarByQuadrants = groupByQuadrants(radar); // const radarByQuadrants = groupByQuadrants(radar);

View File

@@ -1,5 +1,5 @@
import { emptyDir } from 'fs-extra'; import { emptyDir } from 'fs-extra';
import { distPath } from './file'; import { distPath } from '../common/file';
var distDir = distPath(); var distDir = distPath();

View File

@@ -1,42 +0,0 @@
import { outputFile } from 'fs-extra';
import pug from 'pug';
import frontmatter from 'front-matter';
import marked from 'marked';
import {
staticPath,
distPath,
getAllPugFiles,
} from './file';
import {
vars,
} from './template';
export const createStatic = async (radar) => {
const paths = await getAllPugFiles(staticPath());
const fileNames = getPlainFileNames(paths);
return renderStaticPages(radar, fileNames);
return fileNames;
};
const getPlainFileNames = (paths) => (
paths.map((fileName) => {
const [ nameWithSuffix ] = fileName.split('/').slice(-1);
return nameWithSuffix.substr(0, nameWithSuffix.length - 4);
})
)
const renderStaticPages = (radar, fileNames) => (
Promise.all(fileNames.map((name) => (
new Promise((resolve, reject) => (
outputFile(distPath(`${name}.html`), pug.renderFile(staticPath(`${name}.pug`), vars({
...radar,
})), (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
})
))
)))
);

View File

@@ -1,6 +1,6 @@
import pug from 'pug'; import pug from 'pug';
import moment from 'moment'; import moment from 'moment';
import { relativePath } from './file'; import { relativePath } from '../common/file';
import { import {
groupByQuadrants, groupByQuadrants,
groupByFirstLetter, groupByFirstLetter,

View File

@@ -1,41 +0,0 @@
extends layout.pug
block body
.page
.page__header
.branding
if noLogo
.branding__backlink
a.icon-link.icon-link--primary.icon-link--big(href='/')
span.icon.icon--back.icon-link__icon
| AOE Technology Radar
if !noLogo
a.branding__logo(href='/')
img(src='/assets/logo.svg')
.branding__content
.nav
.nav__item
a.icon-link(href='/howto.html')
span.icon.icon--question.icon-link__icon
| How to Use Technology Radar?
.nav__item
a.icon-link(href='/overview.html')
span.icon.icon--overview.icon-link__icon
| Technologies Overview
.nav__item
a.icon-link(href='#todo')
span.icon.icon--search.icon-link__icon
| Search
.page__content
block content
if !noFooter
.page__footer
.branding
span.branding__logo
img(src='/assets/logo.svg')
.branding__content
span.footnote
| AOE is a leading provider of Enterprise Open Source web solutions.
| Using current agile development methods, more than 250+ developers
| and consultants in 8 global locations develop customized Open Source
| solutions for global companies and corporations.

View File

@@ -1,72 +0,0 @@
extends default-page.pug
block vars
- var noLogo=true
- var noFooter=true
- var title=item.title
block content
.item-page.js--details(data-items=JSON.stringify(itemsInRing))
.item-page__nav
.item-page__nav__inner
.item-page__header(v-bind:style="navHeader.style")
h3.headline
= translate(item.quadrant)
.item-list
.item-list__header(v-bind:style="navHeader.style")
.split
.split__left
span(class=`badge badge--big badge--${item.ring}`)
= item.ring
.split__right
a.icon-link(href=`/${item.quadrant}.html`)
span.icon.icon--pie.icon-link__icon
| Quadrant Overview
.item-list__list
each ringItem, i in itemsInRing
a.item(
class=`${ringItem.name === item.name ? 'is-active' : ''}`
href=`/${ringItem.quadrant}/${ringItem.name}.html`
v-bind:style=`items[${i}].style`
)
.item__title= ringItem.title
if ringItem.info
.item__info= ringItem.info
.item-page__content(v-bind:style="background.style")
.item-page__content__inner(v-bind:style="text.style")
.item-page__header
.split
.split__left
h1.hero-headline.hero-headline--inverse
= item.title
.split__right
span(class=`badge badge--big badge--${item.ring}`)
= item.ring
.markdown
!= item.body
//-
a(href='/' + item.quadrant + '.html')= translate(item.quadrant)
h1 #{item.title}
= ' '
small #{item.ring}
hr
h4= item.revisions[0].version
h5 New: #{item.isNew ? 'YES' : 'NO'}
h5 Feature: #{item.isFeatured ? 'YES' : 'NO'}
section
!= item.revisions[0].body
hr
ul
each revision, index in item.revisions
if index > 0
li
h3
= revision.version
= ' '
= revision.ring
!= revision.body

View File

@@ -1,10 +0,0 @@
block vars
html
head
title #{title} - AOE Tech Radar
link(rel='stylesheet', href='/styles.css')
body
.js--body
block body
block scripts
script(src='/bundle.js')

View File

@@ -1,24 +0,0 @@
extends default-page.pug
block vars
- var noLogo=true
- var title=`${translate(quadrantName)}`
block content
.headline-group
h1.hero-headline
= translate(quadrantName)
.quadrant-section
.quadrant-section__rings
each items, ringName in quadrant
.quadrant-section__ring
.item-list
.item-list__header
span(class=`badge badge--big badge--${ringName}`)
= ringName
.item-list__list
each ringItem in items
a.item.item--no-leading-border(href=`/${ringItem.quadrant}/${ringItem.name}.html`)
.item__title= ringItem.title
if ringItem.info
.item__info= ringItem.info

View File

@@ -2,23 +2,18 @@ var path = require('path');
module.exports = { module.exports = {
entry: { entry: {
bundle: './js/radar.js', bundle: './js/client.js',
}, },
output: { output: {
path: path.join(__dirname, 'dist'), path: path.join(__dirname, 'dist'),
filename: '[name].js', filename: '[name].js',
}, },
resolve: {
alias: {
'vue$': 'vue/dist/vue.common.js'
}
},
module: { module: {
rules: [ rules: [
{ {
test: /\.js?$/, test: /\.js?$/,
include: [ include: [
path.resolve(__dirname, "js") path.resolve(__dirname, "js"),
], ],
loader: "babel-loader", loader: "babel-loader",