Extract AOE specific texts as messages.json
This commit is contained in:
@@ -18,10 +18,25 @@ interface Params {
|
||||
page: string;
|
||||
}
|
||||
|
||||
const useQuery = () => {
|
||||
return new URLSearchParams(useLocation().search);
|
||||
const useFetch = <D extends unknown>(url: string): D | undefined => {
|
||||
const [data, setData] = React.useState<D>();
|
||||
|
||||
React.useEffect(() => {
|
||||
fetch(url)
|
||||
.then((response) => response.json())
|
||||
.then((data: D) => {
|
||||
setData(data);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error(`fetch ${url} failed. Did the file exist?`, error);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
const useQuery = () => new URLSearchParams(useLocation().search);
|
||||
|
||||
const RouterWithPageParam = ({
|
||||
items,
|
||||
releases,
|
||||
@@ -60,30 +75,12 @@ interface Data {
|
||||
}
|
||||
|
||||
export default function App() {
|
||||
const [data, setData] = React.useState<Data>();
|
||||
const [messages, setMessages] = React.useState<Messages>();
|
||||
const data = useFetch<Data>(`${process.env.PUBLIC_URL}/rd.json`);
|
||||
const messages = useFetch<Messages>(
|
||||
`${process.env.PUBLIC_URL}/messages.json`
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
fetch(`${process.env.PUBLIC_URL}/rd.json`)
|
||||
.then((response) => response.json())
|
||||
.then((data: Data) => {
|
||||
setData(data);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("fetch data", error);
|
||||
});
|
||||
|
||||
fetch(`${process.env.PUBLIC_URL}/messages.json`)
|
||||
.then((response) => response.json())
|
||||
.then((messages: Messages) => {
|
||||
setMessages(messages);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("fetch messages", error);
|
||||
});
|
||||
}, []);
|
||||
|
||||
if (data && messages) {
|
||||
if (data) {
|
||||
const { items, releases } = data;
|
||||
return (
|
||||
<MessagesProvider messages={messages}>
|
||||
|
||||
@@ -22,14 +22,22 @@ const Footer: React.FC<Props> = ({ items, pageName }) => {
|
||||
!isMobileViewport() && getItemPageNames(items).includes(pageName),
|
||||
})}
|
||||
>
|
||||
<Branding
|
||||
modifier="footer"
|
||||
logoContent={
|
||||
<img src={assetUrl("logo.svg")} width="150px" height="60px" alt="" />
|
||||
}
|
||||
>
|
||||
<span className="footnote">{footerFootnote}</span>
|
||||
</Branding>
|
||||
{footerFootnote && (
|
||||
<Branding
|
||||
modifier="footer"
|
||||
logoContent={
|
||||
<img
|
||||
src={assetUrl("logo.svg")}
|
||||
width="150px"
|
||||
height="60px"
|
||||
alt=""
|
||||
/>
|
||||
}
|
||||
>
|
||||
<span className="footnote">{footerFootnote}</span>
|
||||
</Branding>
|
||||
)}
|
||||
|
||||
<FooterEnd />
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from "react";
|
||||
import classNames from "classnames";
|
||||
import SocialIcon from "../SocialIcon/SocialIcon";
|
||||
import SocialLink from "../SocialLink/SocialLink";
|
||||
import "./footerend.scss";
|
||||
import { useMessages } from "../../context/MessagesContext";
|
||||
|
||||
@@ -9,7 +9,7 @@ interface Props {
|
||||
}
|
||||
|
||||
const FooterEnd: React.FC<Props> = ({ modifier }) => {
|
||||
const { socialIcons } = useMessages();
|
||||
const { socialLinks, legalInformationLink } = useMessages();
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -18,26 +18,33 @@ const FooterEnd: React.FC<Props> = ({ modifier }) => {
|
||||
})}
|
||||
>
|
||||
<div className="footer-social">
|
||||
<div className="footer-social__label">
|
||||
<p>Follow us:</p>
|
||||
</div>
|
||||
<div className="footer-social__links">
|
||||
{socialIcons.map(({ href, iconName }) => (
|
||||
<SocialIcon href={href} iconName={iconName} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="footer-copyright">
|
||||
<p>
|
||||
<a
|
||||
href="https://www.aoe.com/en/imprint.html"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Legal Information
|
||||
</a>
|
||||
</p>
|
||||
{socialLinks && (
|
||||
<>
|
||||
<div className="footer-social__label">
|
||||
<p>Follow us:</p>
|
||||
</div>
|
||||
<div className="footer-social__links">
|
||||
{socialLinks.map(({ href, iconName }) => (
|
||||
<SocialLink href={href} iconName={iconName} key={iconName} />
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{legalInformationLink && (
|
||||
<div className="footer-copyright">
|
||||
<p>
|
||||
<a
|
||||
href={legalInformationLink}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Legal Information
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -7,10 +7,12 @@ import Search from "../Search/Search";
|
||||
import { radarNameShort } from "../../config";
|
||||
import { useHistory } from "react-router-dom";
|
||||
import qs from "query-string";
|
||||
import { useMessages } from "../../context/MessagesContext";
|
||||
|
||||
export default function Header({ pageName }: { pageName: string }) {
|
||||
const [searchOpen, setSearchOpen] = useState(false);
|
||||
const [search, setSearch] = useState("");
|
||||
const { pageHelp } = useMessages();
|
||||
const history = useHistory();
|
||||
const searchRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
@@ -49,12 +51,14 @@ export default function Header({ pageName }: { pageName: string }) {
|
||||
return (
|
||||
<Branding logoContent={<LogoLink small={smallLogo} />}>
|
||||
<div className="nav">
|
||||
<div className="nav__item">
|
||||
<Link pageName="help-and-about-tech-radar" className="icon-link">
|
||||
<span className="icon icon--question icon-link__icon" />
|
||||
How to Use {radarNameShort}?
|
||||
</Link>
|
||||
</div>
|
||||
{pageHelp && (
|
||||
<div className="nav__item">
|
||||
<Link pageName="help-and-about-tech-radar" className="icon-link">
|
||||
<span className="icon icon--question icon-link__icon" />
|
||||
How to Use {radarNameShort}?
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
<div className="nav__item">
|
||||
<Link pageName="overview" className="icon-link">
|
||||
<span className="icon icon--overview icon-link__icon" />
|
||||
|
||||
@@ -3,141 +3,68 @@ import HeroHeadline from "../HeroHeadline/HeroHeadline";
|
||||
import Fadeable from "../Fadeable/Fadeable";
|
||||
import SetTitle from "../SetTitle";
|
||||
import { radarName } from "../../config";
|
||||
import { useMessages } from "../../context/MessagesContext";
|
||||
|
||||
export default function PageHelp({
|
||||
leaving,
|
||||
onLeave,
|
||||
}: {
|
||||
interface Props {
|
||||
leaving: boolean;
|
||||
onLeave: () => void;
|
||||
}) {
|
||||
return (
|
||||
<Fadeable leaving={leaving} onLeave={onLeave}>
|
||||
<SetTitle title={"How to use the " + radarName} />
|
||||
<HeroHeadline>How to use the {radarName}</HeroHeadline>
|
||||
<div className="fullpage-content">
|
||||
<h3>Introduction</h3>
|
||||
<p>
|
||||
Technology is moving fast and new technologies and innovations appear
|
||||
continuously.
|
||||
</p>
|
||||
<p>
|
||||
It's essential for a development and technology company such as AOE to
|
||||
constantly improve and keep track with the latest useful innovations.
|
||||
It is important to openly look for innovations and new technologies
|
||||
and to question established technologies and methods every now and
|
||||
then.
|
||||
</p>
|
||||
<p>
|
||||
But, it is also important to wisely choose which technologies to use
|
||||
in our daily work and in the different projects we are carrying out.
|
||||
As we all know: There is no silver bullet.
|
||||
</p>
|
||||
<h3>What is the {radarName}</h3>
|
||||
<p>
|
||||
The Tech Radar is an overview of different technologies - from
|
||||
languages, frameworks, tools and patterns to platforms - that we
|
||||
consider "new or mentionable". The radar therefore doesn't provide an
|
||||
overview of all established technologies - but it focuses on items
|
||||
that have recently gained in importance or changed.
|
||||
</p>
|
||||
<h3>How it is created</h3>
|
||||
<p>
|
||||
The items in the technology radar are raised by the different teams
|
||||
and therefore a lot of the items are related to the work and
|
||||
challenges the teams face in the different projects. In fact, we don't
|
||||
include anything on the radar, which we haven't already tried
|
||||
ourselves at least once.
|
||||
</p>
|
||||
<p>
|
||||
There have been a lot of valuable discussions in different expert
|
||||
groups about the classification and details of each of technologies
|
||||
and innovations. And the result of all this can be found in the latest
|
||||
technology radar.
|
||||
</p>
|
||||
<h3>How should it be used</h3>
|
||||
<p>
|
||||
The radar acts as an overview of technologies that we think everyone
|
||||
in the teams should currently know about.
|
||||
</p>
|
||||
<p>
|
||||
Its goal is to act as a guide and inspiration for the daily work in
|
||||
the teams. Its purpose is also to provide helpful information and a
|
||||
bird's-eye perspective - so that decisions can be taken with a much
|
||||
deeper understanding of the subject matter. This results in
|
||||
more-informed and better-aligned decisions.
|
||||
</p>
|
||||
<p>
|
||||
We also hope that developers outside of AOE find the information in
|
||||
our technology overview inspirational.
|
||||
</p>
|
||||
<p>
|
||||
We group or categorize the items in 4 quadrants - (sometimes, when
|
||||
it's not 100% clear where a item belongs, we choose the best fit).
|
||||
</p>
|
||||
<p>The quadrants are:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>Languages and Frameworks:</strong> We've placed development
|
||||
languages (such as Scala or Golang) here, as well as more low-level
|
||||
development frameworks (such as Play or Symfony), which are useful
|
||||
for implementing custom software of all kinds.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Tools:</strong> Here we put different software tools - from
|
||||
small helpers to bigger software projects
|
||||
</li>
|
||||
<li>
|
||||
<strong>Methods and Patterns:</strong> Patterns are so important,
|
||||
and a lot of them are valid for a long time (compared to some tools
|
||||
or frameworks). So, this is the category where we put information on
|
||||
methods and patterns concerning development, continuous x, testing,
|
||||
organization, architecture, etc.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Platforms and Services</strong> (including AOE internal
|
||||
Services): Here we include infrastructure platforms and services. We
|
||||
also use this category to communicate news about AOE services that
|
||||
we want all AOE teams to be aware of.
|
||||
</li>
|
||||
</ul>
|
||||
<p>Each of the items is classified in one of these rings:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>Adopt:</strong> We can clearly recommend this technology. We
|
||||
have used it for longer period of time in many teams and it has
|
||||
proven to be stable and useful.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Trial:</strong> We have used it with success and recommend
|
||||
to have a closer look at the technology in this ring. The goal of
|
||||
items here is to look at them more closely, with the goal to bring
|
||||
them to the adopt level.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Assess:</strong> We have tried it out and we find it
|
||||
promising. We recommend having a look at these items when you face a
|
||||
specific need for the technology in your project.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Hold:</strong> This category is a bit special. Unlike the
|
||||
others, we recommend to stop doing or using something. That does not
|
||||
mean that they are bad and it often might be ok to use them in
|
||||
existing projects. But we move things here if we think we shouldn't
|
||||
do them anymore - because we see better options or alternatives now.
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
Contributions and source code of the radar are on github:{" "}
|
||||
<a
|
||||
href="https://github.com/AOEpeople/aoe_technology_radar"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
AOE Tech Radar on Github
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</Fadeable>
|
||||
);
|
||||
}
|
||||
|
||||
const PageHelp: React.FC<Props> = ({ leaving, onLeave }) => {
|
||||
const { pageHelp } = useMessages();
|
||||
|
||||
if (pageHelp) {
|
||||
const { paragraphs, quadrants, rings, sourcecodeLink } = pageHelp;
|
||||
return (
|
||||
<Fadeable leaving={leaving} onLeave={onLeave}>
|
||||
<SetTitle title={"How to use the " + radarName} />
|
||||
<HeroHeadline>How to use the {radarName}</HeroHeadline>
|
||||
<div className="fullpage-content">
|
||||
{paragraphs.map(({ headline, values }) => (
|
||||
<React.Fragment key={headline}>
|
||||
<h3>{headline}</h3>
|
||||
{values.map((element, index) => (
|
||||
<p key={index}>{element}</p>
|
||||
))}
|
||||
</React.Fragment>
|
||||
))}
|
||||
|
||||
<p>The quadrants are:</p>
|
||||
<ul>
|
||||
{quadrants.map(({ name, description }) => (
|
||||
<li key={name}>
|
||||
<strong>{name}:</strong> {description}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
<p>Each of the items is classified in one of these rings:</p>
|
||||
<ul>
|
||||
{rings.map(({ name, description }) => (
|
||||
<li key={name}>
|
||||
<strong>{name}:</strong> {description}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
|
||||
{sourcecodeLink && (
|
||||
<p>
|
||||
{`${sourcecodeLink.description} `}
|
||||
<a
|
||||
href={sourcecodeLink.href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{sourcecodeLink.name}
|
||||
</a>
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</Fadeable>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
export default PageHelp;
|
||||
|
||||
@@ -24,7 +24,7 @@ export interface Props {
|
||||
iconName: keyof typeof icons;
|
||||
}
|
||||
|
||||
const SocialIcon: React.FC<Props> = ({ href, iconName }) => {
|
||||
const SocialLink: React.FC<Props> = ({ href, iconName }) => {
|
||||
const Icon = icons[iconName];
|
||||
|
||||
if (Icon) {
|
||||
@@ -39,8 +39,8 @@ const SocialIcon: React.FC<Props> = ({ href, iconName }) => {
|
||||
</a>
|
||||
);
|
||||
}
|
||||
console.log(`The icon is unknown: ${iconName}`);
|
||||
console.error(`The iconname is unknown: ${iconName}`);
|
||||
return null;
|
||||
};
|
||||
|
||||
export default SocialIcon;
|
||||
export default SocialLink;
|
||||
@@ -1,5 +1,5 @@
|
||||
import { createContext, FC, useContext } from "react";
|
||||
import { Props as SocialIcon } from "../../components/SocialIcon/SocialIcon";
|
||||
import { Props as SocialLink } from "../../components/SocialLink/SocialLink";
|
||||
|
||||
interface Quadrant {
|
||||
name: string;
|
||||
@@ -11,24 +11,32 @@ interface Ring {
|
||||
description: string;
|
||||
}
|
||||
|
||||
interface Paragraph {
|
||||
headline: string;
|
||||
values: string[];
|
||||
}
|
||||
|
||||
interface PageHelp {
|
||||
introduction: string[];
|
||||
whatIsTheRadar: string[];
|
||||
howItIsCreated: string[];
|
||||
howShouldItBeUsed: string[];
|
||||
paragraphs: Paragraph[];
|
||||
quadrants: Quadrant[];
|
||||
rings: Ring[];
|
||||
sourcecodeLink?: {
|
||||
href: string;
|
||||
name: string;
|
||||
description: string;
|
||||
};
|
||||
}
|
||||
|
||||
export interface Messages {
|
||||
footerFootnote: string;
|
||||
socialIcons: SocialIcon[];
|
||||
pageHelp: PageHelp;
|
||||
footerFootnote?: string;
|
||||
socialLinks?: SocialLink[];
|
||||
legalInformationLink?: string;
|
||||
pageHelp?: PageHelp;
|
||||
}
|
||||
|
||||
const MessagesContext = createContext<Messages | undefined>(undefined);
|
||||
|
||||
export const MessagesProvider: FC<{ messages: Messages }> = ({
|
||||
export const MessagesProvider: FC<{ messages?: Messages }> = ({
|
||||
messages,
|
||||
children,
|
||||
}) => (
|
||||
@@ -42,5 +50,5 @@ export const useMessages = () => {
|
||||
if (context === undefined) {
|
||||
throw new Error("useMessages must be used within a MessagesProvider");
|
||||
}
|
||||
return context;
|
||||
return context || {};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user