Refactor and roadmap summary pages
This commit is contained in:
@ -20,7 +20,7 @@ const FeaturedRoadmaps = () => (
|
||||
{ roadmaps
|
||||
.filter(({ featured }) => featured)
|
||||
.map(roadmap => (
|
||||
<div className="col-xl-4 col-lg-4 col-md-6 col-sm-12 col-12 grid-item-container">
|
||||
<div className="col-xl-4 col-lg-4 col-md-6 col-sm-12 col-12 grid-item-container" key={roadmap.slug}>
|
||||
<Link href={ roadmap.slug }>
|
||||
<a className="featured-block">
|
||||
<h4>{ roadmap.title }</h4>
|
||||
|
@ -1,3 +1,6 @@
|
||||
import Link from 'next/link';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import {
|
||||
SummaryContainer,
|
||||
Title,
|
||||
@ -5,6 +8,8 @@ import {
|
||||
Image,
|
||||
Header,
|
||||
Summary,
|
||||
VersionLink,
|
||||
VersionList,
|
||||
} from './style';
|
||||
|
||||
const RoadmapSummary = ({ roadmap }) => (
|
||||
@ -12,8 +17,17 @@ const RoadmapSummary = ({ roadmap }) => (
|
||||
<Header>
|
||||
<Title>{ roadmap.title }</Title>
|
||||
<Description>{ roadmap.description }</Description>
|
||||
<VersionList className="border-bottom">
|
||||
{ (roadmap.versions || []).map(versionItem => (
|
||||
<Link href={ `${roadmap.slug}/${versionItem}` } passHref key={ versionItem }>
|
||||
<VersionLink className={ classNames({
|
||||
active: versionItem === roadmap.version,
|
||||
}) }>{ versionItem } Version</VersionLink>
|
||||
</Link>
|
||||
)) }
|
||||
</VersionList>
|
||||
</Header>
|
||||
<Summary className="border-top border-bottom">
|
||||
<Summary className="border-bottom">
|
||||
<div className="container">
|
||||
<Image src={ roadmap.picture } />
|
||||
</div>
|
||||
|
@ -9,7 +9,7 @@ export const Header = styled.div`
|
||||
|
||||
export const Summary = styled.div`
|
||||
text-align: center;
|
||||
padding: 50px 0;
|
||||
padding: 0 0 50px;
|
||||
`;
|
||||
|
||||
export const Title = styled.h1`
|
||||
@ -17,10 +17,46 @@ export const Title = styled.h1`
|
||||
margin-bottom: 12px;
|
||||
font-size: 42px;
|
||||
`;
|
||||
|
||||
export const Description = styled.p`
|
||||
font-size: 19px;
|
||||
margin-bottom: 0;
|
||||
`;
|
||||
|
||||
export const Image = styled.img`
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
export const VersionList = styled.div`
|
||||
margin: 35px 0 15px;
|
||||
`;
|
||||
|
||||
export const VersionLink = styled.a`
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
padding: 5px 10px 8px;
|
||||
text-decoration: none;
|
||||
color: rgb(102, 102, 102);
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
text-transform: capitalize;
|
||||
|
||||
&.active, &.active:hover {
|
||||
color: #2d2d2d;
|
||||
|
||||
&:after {
|
||||
position: absolute;
|
||||
content: "";
|
||||
display: block;
|
||||
height: 0;
|
||||
left: 9px;
|
||||
right: 9px;
|
||||
bottom: -1px;
|
||||
border-bottom: 2px solid currentColor;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
color: #111111;
|
||||
}
|
||||
`;
|
@ -3,24 +3,39 @@
|
||||
"title": "Frontend Developer",
|
||||
"description": "Step by step guide to becoming a modern frontend developer",
|
||||
"featuredDescription": "Step by step guide to becoming a modern frontend developer in 2019",
|
||||
"slug": "/frontend",
|
||||
"slug": "/roadmaps/frontend",
|
||||
"picture": "/static/roadmaps/frontend.png",
|
||||
"featured": true
|
||||
"featured": true,
|
||||
"versions": [
|
||||
"latest",
|
||||
"2018",
|
||||
"2017"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "Backend Developer",
|
||||
"description": "Roadmap to becoming a backend developer",
|
||||
"description": "Step by step guide to becoming a modern backend developer",
|
||||
"featuredDescription": "Step by step guide to becoming a modern backend developer in 2019",
|
||||
"slug": "/backend",
|
||||
"slug": "/roadmaps/backend",
|
||||
"picture": "/static/roadmaps/backend.png",
|
||||
"featured": true
|
||||
"featured": true,
|
||||
"versions": [
|
||||
"latest",
|
||||
"2018",
|
||||
"2017"
|
||||
]
|
||||
},
|
||||
{
|
||||
"title": "DevOps Roadmap",
|
||||
"description": "Roadmap for DevOps or any other Operations Role",
|
||||
"description": "Step by step guide for DevOps or any other Operations Role",
|
||||
"featuredDescription": "Step by step guide to become an SRE or for any operations role in 2019",
|
||||
"slug": "/devops",
|
||||
"slug": "/roadmaps/devops",
|
||||
"picture": "/static/roadmaps/devops.png",
|
||||
"featured": true
|
||||
"featured": true,
|
||||
"versions": [
|
||||
"latest",
|
||||
"2018",
|
||||
"2017"
|
||||
]
|
||||
}
|
||||
]
|
@ -16,6 +16,10 @@
|
||||
background-color: #fafafa !important;
|
||||
}
|
||||
|
||||
.muted {
|
||||
color: #757575;
|
||||
}
|
||||
|
||||
.dark-link {
|
||||
font-weight: 500;
|
||||
color: #000000;
|
||||
|
26
lib/roadmap.js
Normal file
26
lib/roadmap.js
Normal file
@ -0,0 +1,26 @@
|
||||
import roadmaps from "../data/roadmaps";
|
||||
|
||||
export const getRequestedRoadmap = req => {
|
||||
// Considering it a new roadmap URL e.g. `/roadmaps/frontend`
|
||||
const currentUrl = req.url.replace(/\/$/, '');
|
||||
// Considering it a legacy URL e.g. converting `/frontend` to `roadmap.sh/roadmaps/frontend`
|
||||
const legacyUrl = `/roadmaps${currentUrl}`;
|
||||
// Get the roadmap version out of the URL e.g. `/roadmaps/frontend/2019`
|
||||
const [foundVersion = ''] = currentUrl.match(/(\d+|latest)$/) || ['latest'];
|
||||
const foundVersionRegex = new RegExp(`\/?${foundVersion}$`);
|
||||
// Remove version from the URL because slugs in roadmaps list don't have versions
|
||||
const newUrlWithoutVersion = currentUrl.replace(foundVersionRegex, '');
|
||||
const legacyUrlWithoutVersion = legacyUrl.replace(foundVersionRegex, '');
|
||||
|
||||
const urlToSlugList = [
|
||||
currentUrl,
|
||||
legacyUrl,
|
||||
newUrlWithoutVersion,
|
||||
legacyUrlWithoutVersion,
|
||||
];
|
||||
|
||||
return {
|
||||
...roadmaps.find(roadmap => urlToSlugList.includes(roadmap.slug)),
|
||||
version: foundVersion,
|
||||
};
|
||||
};
|
@ -18,6 +18,7 @@
|
||||
"@zeit/next-sass": "^1.0.1",
|
||||
"autoprefixer": "^9.6.1",
|
||||
"bootstrap": "^4.3.1",
|
||||
"classnames": "^2.2.6",
|
||||
"font-awesome": "^4.7.0",
|
||||
"next": "^9.0.4",
|
||||
"node-sass": "^4.12.0",
|
||||
|
3
pages/[fallback]/[version].js
Normal file
3
pages/[fallback]/[version].js
Normal file
@ -0,0 +1,3 @@
|
||||
import OldRoadmap from './index';
|
||||
|
||||
export default OldRoadmap;
|
@ -1,6 +1,7 @@
|
||||
import Roadmap from './roadmaps/[roadmap]';
|
||||
import roadmapsList from "../data/roadmaps.json";
|
||||
import { serverOnlyProps } from '../lib/server';
|
||||
import Error from 'next/error';
|
||||
import Roadmap from '../roadmaps/[roadmap]/index';
|
||||
import { serverOnlyProps } from '../../lib/server';
|
||||
import { getRequestedRoadmap } from '../../lib/roadmap';
|
||||
|
||||
// Fallback page to handle the old roadmap pages implementation
|
||||
const OldRoadmap = ({ roadmap }) => {
|
||||
@ -8,12 +9,12 @@ const OldRoadmap = ({ roadmap }) => {
|
||||
return <Roadmap roadmap={ roadmap } />
|
||||
}
|
||||
|
||||
return <h1>404</h1>
|
||||
return <Error status={ 404 } />;
|
||||
};
|
||||
|
||||
OldRoadmap.getInitialProps = serverOnlyProps(({ req }) => {
|
||||
return {
|
||||
roadmap: roadmapsList.find(roadmap => roadmap.slug === req.url),
|
||||
roadmap: getRequestedRoadmap(req),
|
||||
};
|
||||
});
|
||||
|
@ -1,25 +0,0 @@
|
||||
import roadmaps from "../../data/roadmaps";
|
||||
import DefaultLayout from '../../layouts/default/index';
|
||||
import PageHeader from '../../components/page-header/index';
|
||||
import { serverOnlyProps } from '../../lib/server';
|
||||
import RoadmapSummary from '../../components/roadmap-summary';
|
||||
import PageFooter from '../../components/page-footer';
|
||||
|
||||
const Roadmap = ({ roadmap }) => {
|
||||
return (
|
||||
<DefaultLayout>
|
||||
<PageHeader />
|
||||
<RoadmapSummary roadmap={ roadmap } />
|
||||
<PageFooter />
|
||||
</DefaultLayout>
|
||||
);
|
||||
};
|
||||
|
||||
Roadmap.getInitialProps = serverOnlyProps(({ req }) => {
|
||||
const normalizedUrl = req.url.replace('roadmaps/', '');
|
||||
return {
|
||||
roadmap: roadmaps.find(roadmap => roadmap.slug === normalizedUrl),
|
||||
};
|
||||
});
|
||||
|
||||
export default Roadmap;
|
3
pages/roadmaps/[roadmap]/[version].js
Normal file
3
pages/roadmaps/[roadmap]/[version].js
Normal file
@ -0,0 +1,3 @@
|
||||
import Roadmap from './index';
|
||||
|
||||
export default Roadmap;
|
24
pages/roadmaps/[roadmap]/index.js
Normal file
24
pages/roadmaps/[roadmap]/index.js
Normal file
@ -0,0 +1,24 @@
|
||||
import DefaultLayout from '../../../layouts/default';
|
||||
import { serverOnlyProps } from '../../../lib/server';
|
||||
import PageHeader from '../../../components/page-header';
|
||||
import PageFooter from '../../../components/page-footer';
|
||||
import { getRequestedRoadmap } from '../../../lib/roadmap';
|
||||
import RoadmapSummary from '../../../components/roadmap-summary';
|
||||
|
||||
const Roadmap = ({ roadmap }) => {
|
||||
return (
|
||||
<DefaultLayout>
|
||||
<PageHeader />
|
||||
<RoadmapSummary roadmap={ roadmap } />
|
||||
<PageFooter />
|
||||
</DefaultLayout>
|
||||
);
|
||||
};
|
||||
|
||||
Roadmap.getInitialProps = serverOnlyProps(({ req }) => {
|
||||
return {
|
||||
roadmap: getRequestedRoadmap(req),
|
||||
};
|
||||
});
|
||||
|
||||
export default Roadmap;
|
@ -1754,6 +1754,11 @@ class-utils@^0.3.5:
|
||||
isobject "^3.0.0"
|
||||
static-extend "^0.1.1"
|
||||
|
||||
classnames@^2.2.6:
|
||||
version "2.2.6"
|
||||
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
|
||||
integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==
|
||||
|
||||
cliui@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d"
|
||||
|
Reference in New Issue
Block a user