Niedzielski has uploaded a new change for review. (
https://gerrit.wikimedia.org/r/388069 )
Change subject: Chore: refactor page modules
......................................................................
Chore: refactor page modules
- Rename PageModule to PageComponents.
- Add PageModule type that is an ES6 module with a default export of
type PageComponent.
Bug: T177236
Change-Id: Ib80dc40548bddec1b1fdc36c1e8a68a2350809f5
---
M src/common/pages/about.tsx
M src/common/pages/home.tsx
M src/common/pages/not-found.tsx
M src/common/pages/style-guide.tsx
M src/common/pages/summary.tsx
M src/common/pages/wiki.tsx
M src/common/routers/route.ts
M src/common/routers/router.ts
8 files changed, 300 insertions(+), 269 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/marvin refs/changes/69/388069/1
diff --git a/src/common/pages/about.tsx b/src/common/pages/about.tsx
index a906239..11524b7 100644
--- a/src/common/pages/about.tsx
+++ b/src/common/pages/about.tsx
@@ -12,78 +12,80 @@
subtitle: string;
}
-export class Component extends PreactComponent<undefined, State> {
- constructor() {
- super();
- this.state = { subtitle: "" };
- }
+export default {
+ Component: class extends PreactComponent<undefined, State> {
+ constructor() {
+ super();
+ this.state = { subtitle: "" };
+ }
- componentDidMount() {
- // todo: figure out a common way across entry points for defining
- // configuration variables that common code could consume. The server has
- // server specific vars in config.ts and this here for example are used
only
- // on DOM capable envs (componentDidMount will only fire on DOM capable
- // environments). It would be ideal if we had a common place with
- // configuration for common code. We need to also take into account
UglifyJS
- // and the dead code elimination when using DefinePlugin, so that we can
- // leverage it to remove dev-only code in production builds
- // (see https://webpack.js.org/guides/tree-shaking/#minify-the-output)
- //
- // Fill the subtitle on the DOM-capable env with the information embedded
in
- // the assets by webpack#DefinePlugin
- const env = process.env.NODE_ENV;
- const subtitle = `Version ${VERSION}; Env: ${env}`;
- this.setState({ subtitle });
- }
+ componentDidMount() {
+ // todo: figure out a common way across entry points for defining
+ // configuration variables that common code could consume. The server has
+ // server specific vars in config.ts and this here for example are used
+ // only on DOM capable envs (componentDidMount will only fire on DOM
+ // capable environments). It would be ideal if we had a common place with
+ // configuration for common code. We need to also take into account
+ // UglifyJS and the dead code elimination when using DefinePlugin, so
that
+ // we can leverage it to remove dev-only code in production builds
+ // (see https://webpack.js.org/guides/tree-shaking/#minify-the-output)
+ //
+ // Fill the subtitle on the DOM-capable env with the information embedded
+ // in the assets by webpack#DefinePlugin
+ const env = process.env.NODE_ENV;
+ const subtitle = `Version ${VERSION}; Env: ${env}`;
+ this.setState({ subtitle });
+ }
- render(_props: void, { subtitle }: State): JSX.Element {
- const links = [
- {
- href: "https://phabricator.wikimedia.org/tag/marvin/",
- text: "Task/Bug tracker"
- },
- {
- href: "https://phabricator.wikimedia.org/diffusion/MARV/",
- text: "Code repository (Wikimedia Phabricator)"
- },
- {
- href: "https://github.com/wikimedia/marvin",
- text: "Github mirror"
- },
- {
- href:
-
"https://www.mediawiki.org/wiki/Reading/Web/Projects/NewMobileWebsite",
- text: "Documentation on MediaWiki.org"
- },
- {
- href: "https://github.com/wikimedia/marvin/tree/master/docs",
- text: "Technical documentation on Github.com"
- }
- ];
- return (
- <App>
- <Page title="About Marvin" subtitle={subtitle}>
- <p>
- Marvin is in early stages of development.<br /> For more
information
- see the following links:
- </p>
- <ul>
- {links.map(({ href, text }) => (
- <li>
- <Link href={href}>{text}</Link>
- </li>
- ))}
- </ul>
- <p>
- If you want to chat, you can find us in{" "}
- <code>#wikimedia-mobile</code> on freenode. Or you can send an
email
- to the{" "}
- <a href="https://lists.wikimedia.org/mailman/listinfo/mobile-l">
- mobile-l mailing list
- </a>.
- </p>
- </Page>
- </App>
- );
+ render(_props: void, { subtitle }: State): JSX.Element {
+ const links = [
+ {
+ href: "https://phabricator.wikimedia.org/tag/marvin/",
+ text: "Task/Bug tracker"
+ },
+ {
+ href: "https://phabricator.wikimedia.org/diffusion/MARV/",
+ text: "Code repository (Wikimedia Phabricator)"
+ },
+ {
+ href: "https://github.com/wikimedia/marvin",
+ text: "Github mirror"
+ },
+ {
+ href:
+
"https://www.mediawiki.org/wiki/Reading/Web/Projects/NewMobileWebsite",
+ text: "Documentation on MediaWiki.org"
+ },
+ {
+ href: "https://github.com/wikimedia/marvin/tree/master/docs",
+ text: "Technical documentation on Github.com"
+ }
+ ];
+ return (
+ <App>
+ <Page title="About Marvin" subtitle={subtitle}>
+ <p>
+ Marvin is in early stages of development.<br /> For more
+ information see the following links:
+ </p>
+ <ul>
+ {links.map(({ href, text }) => (
+ <li>
+ <Link href={href}>{text}</Link>
+ </li>
+ ))}
+ </ul>
+ <p>
+ If you want to chat, you can find us in{" "}
+ <code>#wikimedia-mobile</code> on freenode. Or you can send an
+ email to the{" "}
+ <a href="https://lists.wikimedia.org/mailman/listinfo/mobile-l">
+ mobile-l mailing list
+ </a>.
+ </p>
+ </Page>
+ </App>
+ );
+ }
}
-}
+};
diff --git a/src/common/pages/home.tsx b/src/common/pages/home.tsx
index c4657fe..78ac04c 100644
--- a/src/common/pages/home.tsx
+++ b/src/common/pages/home.tsx
@@ -13,106 +13,110 @@
import { PageTitleID } from "../models/page/title";
import Link from "../components/link";
-export const Component = (): JSX.Element => {
- const testSummaries = [
- {
- title: "Banana",
- text: "With landscape image"
- },
- {
- title: "Cucumber",
- text: "With portrait image"
- },
- {
- title: "Plaintext",
- text: "Without image"
- },
- {
- title: "Bill_&_Ted's_Excellent_Adventure",
- text: "With two paragraphs, unencoded path, and styled title"
- }
- ];
- const testPages = [
- {
- title: "Ice_cream",
- text: "A normal article"
- },
- {
- title: "Cake_(disambiguation)",
- text: "Disambiguation"
- },
- {
- title: "Cheese_cake",
- text: "Redirect"
- },
- {
- title: "Carrot cake",
- text: "Encoding redirect"
- },
- {
- title: "Ice_cream_cake",
- revision: "24242119",
- text: "An arbitrary revision"
- }
- ];
- return (
- <App>
- <Page title="Welcome" subtitle="">
- <p>Hello world!</p>
- <p>Here are some test links for the time being:</p>
- <ul>
- <li>
- <Link href={home.toPath()}>Home</Link>
- </li>
- <li>
- <Link href={about.toPath()}>About</Link>
- </li>
- <li>
- <Link href={styleGuide.toPath()}>Style Guide</Link>
- </li>
- <li>
- <Link href="/404">404</Link>
- </li>
- </ul>
+const testSummaries = [
+ {
+ title: "Banana",
+ text: "With landscape image"
+ },
+ {
+ title: "Cucumber",
+ text: "With portrait image"
+ },
+ {
+ title: "Plaintext",
+ text: "Without image"
+ },
+ {
+ title: "Bill_&_Ted's_Excellent_Adventure",
+ text: "With two paragraphs, unencoded path, and styled title"
+ }
+];
- <h3>Pages</h3>
- <ul>
- <li>
- {/* todo: this should always appear as with the unvisited color or
- be a button. */}
- <Link href={randomWiki.toPath()}>A random page</Link>
- </li>
- {testPages.map(
- ({
- title,
- revision,
- text
- }: {
- title: PageTitleID | string;
- revision?: string;
- text: string;
- }) => (
- <li>
- <Link href={wiki.toPath({ title, revision })}>{text}</Link>
- </li>
- )
- )}
- </ul>
+const testPages = [
+ {
+ title: "Ice_cream",
+ text: "A normal article"
+ },
+ {
+ title: "Cake_(disambiguation)",
+ text: "Disambiguation"
+ },
+ {
+ title: "Cheese_cake",
+ text: "Redirect"
+ },
+ {
+ title: "Carrot cake",
+ text: "Encoding redirect"
+ },
+ {
+ title: "Ice_cream_cake",
+ revision: "24242119",
+ text: "An arbitrary revision"
+ }
+];
- <h3>Summaries</h3>
- <ul>
- <li>
- {/* todo: this should always appear as with the unvisited color or
- be a button. */}
- <Link href={randomSummary.toPath()}>A random summary</Link>
- </li>
- {testSummaries.map(({ title, text }) => (
+export default {
+ Component(): JSX.Element {
+ return (
+ <App>
+ <Page title="Welcome" subtitle="">
+ <p>Hello world!</p>
+ <p>Here are some test links for the time being:</p>
+ <ul>
<li>
- <Link href={summary.toPath({ title })}>{text}</Link>
+ <Link href={home.toPath()}>Home</Link>
</li>
- ))}
- </ul>
- </Page>
- </App>
- );
+ <li>
+ <Link href={about.toPath()}>About</Link>
+ </li>
+ <li>
+ <Link href={styleGuide.toPath()}>Style Guide</Link>
+ </li>
+ <li>
+ <Link href="/404">404</Link>
+ </li>
+ </ul>
+
+ <h3>Pages</h3>
+ <ul>
+ <li>
+ {/* todo: this should always appear as with the unvisited color
or
+ be a button. */}
+ <Link href={randomWiki.toPath()}>A random page</Link>
+ </li>
+ {testPages.map(
+ ({
+ title,
+ revision,
+ text
+ }: {
+ title: PageTitleID | string;
+ revision?: string;
+ text: string;
+ }) => (
+ <li>
+ <Link href={wiki.toPath({ title, revision })}>{text}</Link>
+ </li>
+ )
+ )}
+ </ul>
+
+ <h3>Summaries</h3>
+ <ul>
+ <li>
+ {/* todo: this should always appear as with the unvisited color
or
+ be a button. */}
+ <Link href={randomSummary.toPath()}>A random summary</Link>
+ </li>
+ {testSummaries.map(({ title, text }) => (
+ <li>
+ <Link href={summary.toPath({ title })}>{text}</Link>
+ </li>
+ ))}
+ </ul>
+ </Page>
+ </App>
+ );
+ }
};
diff --git a/src/common/pages/not-found.tsx b/src/common/pages/not-found.tsx
index ba87615..15c599e 100644
--- a/src/common/pages/not-found.tsx
+++ b/src/common/pages/not-found.tsx
@@ -11,10 +11,14 @@
0: string;
}
-export const status: number = 404;
+export default {
+ status: 404,
-export const Component = (): JSX.Element => (
- <App>
- <p>Not found</p>
- </App>
-);
+ Component(): JSX.Element {
+ return (
+ <App>
+ <p>Not found</p>
+ </App>
+ );
+ }
+};
diff --git a/src/common/pages/style-guide.tsx b/src/common/pages/style-guide.tsx
index 6d584af..089f980 100644
--- a/src/common/pages/style-guide.tsx
+++ b/src/common/pages/style-guide.tsx
@@ -11,52 +11,54 @@
facilis ab suscipit quos deleniti similique officia cumque, dignissimos iusto
laudantium facere sint fuga vero iste vel asperiores beatae aliquam!`;
-export function Component(): JSX.Element {
- return (
- <App>
- <h1 style={{ margin: "var(--double-space)", textAlign: "center" }}>
- Style guide
- </h1>
+export default {
+ Component(): JSX.Element {
+ return (
+ <App>
+ <h1 style={{ margin: "var(--double-space)", textAlign: "center" }}>
+ Style guide
+ </h1>
- <Card header={<h3>Header</h3>}>
- <Header />
- </Card>
- <Card header={<h3>Card</h3>}>
- <p>{lorem}</p>
- </Card>
- <Card header={<h3>Card w/ footer</h3>} footer="This, is a footer">
- <p>{lorem}</p>
- </Card>
- <Card header={<h3>Content typography</h3>}>
- <Content>
- <h1>Heading 1</h1>
+ <Card header={<h3>Header</h3>}>
+ <Header />
+ </Card>
+ <Card header={<h3>Card</h3>}>
<p>{lorem}</p>
- <h2>Heading 2</h2>
+ </Card>
+ <Card header={<h3>Card w/ footer</h3>} footer="This, is a footer">
<p>{lorem}</p>
- <h3>Heading 3</h3>
+ </Card>
+ <Card header={<h3>Content typography</h3>}>
+ <Content>
+ <h1>Heading 1</h1>
+ <p>{lorem}</p>
+ <h2>Heading 2</h2>
+ <p>{lorem}</p>
+ <h3>Heading 3</h3>
+ <p>{lorem}</p>
+ <h4>Heading 4</h4>
+ <p>{lorem}</p>
+ <h5>Heading 5</h5>
+ <p>{lorem}</p>
+ <h6>Heading 6</h6>
+ <p>{lorem}</p>
+ <p>{lorem}</p>
+ <blockquote>{lorem}</blockquote>
+ <p>This is a separator:</p>
+ <Separator />
+ <p>The end</p>
+ </Content>
+ </Card>
+ <Page title="Page template" subtitle="This is the subtitle of the
page">
<p>{lorem}</p>
- <h4>Heading 4</h4>
+ </Page>
+ <Page title="Page template, no subtitle">
<p>{lorem}</p>
- <h5>Heading 5</h5>
+ </Page>
+ <Page title="Page template, w/ footer" footer="Hello, footer world">
<p>{lorem}</p>
- <h6>Heading 6</h6>
- <p>{lorem}</p>
- <p>{lorem}</p>
- <blockquote>{lorem}</blockquote>
- <p>This is a separator:</p>
- <Separator />
- <p>The end</p>
- </Content>
- </Card>
- <Page title="Page template" subtitle="This is the subtitle of the page">
- <p>{lorem}</p>
- </Page>
- <Page title="Page template, no subtitle">
- <p>{lorem}</p>
- </Page>
- <Page title="Page template, w/ footer" footer="Hello, footer world">
- <p>{lorem}</p>
- </Page>
- </App>
- );
-}
+ </Page>
+ </App>
+ );
+ }
+};
diff --git a/src/common/pages/summary.tsx b/src/common/pages/summary.tsx
index adc5012..a22a766 100644
--- a/src/common/pages/summary.tsx
+++ b/src/common/pages/summary.tsx
@@ -26,24 +26,29 @@
summary: PageSummaryModel;
}
-export const getInitialProps = (
- params: Params = {}
-): Promise<HttpResponse<Props>> =>
- request(
- params.title === undefined ? { random: true } : { titlePath: params.title }
- ).then(({ status, data }) => ({
- status,
- data: { summary: data }
- }));
+export default {
+ getInitialProps(params: Params = {}): Promise<HttpResponse<Props>> {
+ return request(
+ params.title === undefined
+ ? { random: true }
+ : { titlePath: params.title }
+ ).then(({ status, data }) => ({
+ status,
+ data: { summary: data }
+ }));
+ },
-export const Component = ({ summary }: Props): JSX.Element => (
- <App>
- <Page
- title={<ContentHeader titleHTML={summary.titleHTML} />}
- subtitle={summary.descriptionText}
- footer={<ContentFooter lastModified={summary.lastModified} />}
- >
- <PageSummary summary={summary} />
- </Page>
- </App>
-);
+ Component({ summary }: Props): JSX.Element {
+ return (
+ <App>
+ <Page
+ title={<ContentHeader titleHTML={summary.titleHTML} />}
+ subtitle={summary.descriptionText}
+ footer={<ContentFooter lastModified={summary.lastModified} />}
+ >
+ <PageSummary summary={summary} />
+ </Page>
+ </App>
+ );
+ }
+};
diff --git a/src/common/pages/wiki.tsx b/src/common/pages/wiki.tsx
index 602b18b..934f976 100644
--- a/src/common/pages/wiki.tsx
+++ b/src/common/pages/wiki.tsx
@@ -30,29 +30,32 @@
page: PageModel;
}
-export const getInitialProps = (
- params: Params = {}
-): Promise<HttpResponse<Props>> =>
- requestPage(
- params.title === undefined
- ? { random: true }
- : {
- titlePath: params.title,
- revision:
- params.revision === undefined
- ? undefined
- : parseInt(params.revision, 10)
- }
- ).then(({ status, data }) => ({ status, data: { page: data } }));
+export default {
+ getInitialProps(params: Params = {}): Promise<HttpResponse<Props>> {
+ return requestPage(
+ params.title === undefined
+ ? { random: true }
+ : {
+ titlePath: params.title,
+ revision:
+ params.revision === undefined
+ ? undefined
+ : parseInt(params.revision, 10)
+ }
+ ).then(({ status, data }) => ({ status, data: { page: data } }));
+ },
-export const Component = ({ page }: Props): JSX.Element => (
- <App>
- <Page
- title={<ContentHeader titleHTML={page.titleHTML} />}
- subtitle={page.descriptionText}
- footer={<ContentFooter lastModified={page.lastModified} />}
- >
- <ContentPage sections={page.sections} />
- </Page>
- </App>
-);
+ Component({ page }: Props): JSX.Element {
+ return (
+ <App>
+ <Page
+ title={<ContentHeader titleHTML={page.titleHTML} />}
+ subtitle={page.descriptionText}
+ footer={<ContentFooter lastModified={page.lastModified} />}
+ >
+ <ContentPage sections={page.sections} />
+ </Page>
+ </App>
+ );
+ }
+};
diff --git a/src/common/routers/route.ts b/src/common/routers/route.ts
index 9653621..197aecd 100644
--- a/src/common/routers/route.ts
+++ b/src/common/routers/route.ts
@@ -25,7 +25,7 @@
* pages/ subdirectory should implicitly implement this interface or typing
will
* fail in routers/api.
*/
-export type PageModule<
+export type PageComponent<
Params extends RouteParams | undefined = undefined,
Props = undefined
> =
@@ -54,6 +54,13 @@
Component: AnyComponent<undefined, any>;
};
+export interface PageModule<
+ Params extends RouteParams | undefined = undefined,
+ Props = undefined
+> {
+ default: PageComponent<Params, Props>;
+}
+
/** A plain configuration used to generate a Route. */
export interface RouteConfig<
Params extends RouteParams | undefined = undefined,
diff --git a/src/common/routers/router.ts b/src/common/routers/router.ts
index 79d5b4b..0d40836 100644
--- a/src/common/routers/router.ts
+++ b/src/common/routers/router.ts
@@ -1,6 +1,7 @@
import { AnyComponent } from "../components/preact-utils";
import {
AnyRoute,
+ PageComponent,
PageModule,
Route,
RouteParams
@@ -19,7 +20,7 @@
}
function getInitialProps<Params extends RouteParams | undefined, Props>(
- module: PageModule<Params, Props>,
+ module: PageComponent<Params, Props>,
params: Params
): Promise<HttpResponse<Props> | void> {
return module.getInitialProps
@@ -32,10 +33,13 @@
params: Params
): Promise<RouteResponse<Props>> {
return route.importModule().then((module: PageModule<Params, Props>) =>
- getInitialProps(module, params).then((response: HttpResponse<Props>) => ({
+ getInitialProps(
+ module.default,
+ params
+ ).then((response: HttpResponse<Props>) => ({
chunkName: route.chunkName,
- status: (response && response.status) || module.status || 200,
- Component: module.Component as AnyComponent<Props, any>,
+ status: (response && response.status) || module.default.status || 200,
+ Component: module.default.Component as AnyComponent<Props, any>,
props: response && response.data
}))
);
--
To view, visit https://gerrit.wikimedia.org/r/388069
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: Ib80dc40548bddec1b1fdc36c1e8a68a2350809f5
Gerrit-PatchSet: 1
Gerrit-Project: marvin
Gerrit-Branch: master
Gerrit-Owner: Niedzielski <[email protected]>
Gerrit-Reviewer: Sniedzielski <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits