jenkins-bot has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/396418 )

Change subject: Update: browser window / tab title per page
......................................................................


Update: browser window / tab title per page

Bug: T180465
Change-Id: I46bd5ded51df65651045613ea0b588d48f5c1847
---
M docs/development.md
M package.json
M src/client/index.tsx
A src/common/format-doc-title.ts
M src/common/pages/about.tsx
M src/common/pages/error.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/router/route.ts
M src/common/router/router.ts
M src/server/components/html-page.tsx
M src/server/index.tsx
M test/server/components/html-page.test.ts
15 files changed, 59 insertions(+), 26 deletions(-)

Approvals:
  Jhernandez: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/docs/development.md b/docs/development.md
index 9bba644..f4e7366 100644
--- a/docs/development.md
+++ b/docs/development.md
@@ -193,6 +193,7 @@
 Marvin uses the following abbreviations:
 
 - Configuration => config
+- Document => doc
 - Parameters => params
 - Properties => props
 - Utilities => utils
diff --git a/package.json b/package.json
index c0e4eb9..ffabbd5 100644
--- a/package.json
+++ b/package.json
@@ -104,7 +104,7 @@
   "bundlesize": [
     {
       "path": "dist/public/index.*.js",
-      "maxSize": "3.8KB"
+      "maxSize": "3.9KB"
     },
     {
       "path": "dist/public/runtime.*.js",
diff --git a/src/client/index.tsx b/src/client/index.tsx
index de270a4..72b596d 100644
--- a/src/client/index.tsx
+++ b/src/client/index.tsx
@@ -5,6 +5,7 @@
 import { RouteResponse, newRouter } from "../common/router/router";
 import { SSRData } from "../common/models/ssr-data";
 import { WithContext } from "../common/components/with-context";
+import { formatDocTitle } from "../common/format-doc-title";
 import { routes } from "../common/router/routes";
 
 // Include preact/debug only in development for React DevTools integration.
@@ -25,7 +26,10 @@
   throw new Error('Missing element with "root" ID.');
 })();
 
-function renderPageRoot({ Component, props }: RouteResponse<any>) {
+function renderPageRoot({ Component, props, title }: RouteResponse<any>) {
+  // Update the window / tab title.
+  document.title = formatDocTitle(title ? title(props) : undefined);
+
   render(
     <WithContext history={history}>
       <Component {...props} />
diff --git a/src/common/format-doc-title.ts b/src/common/format-doc-title.ts
new file mode 100644
index 0000000..8591060
--- /dev/null
+++ b/src/common/format-doc-title.ts
@@ -0,0 +1,3 @@
+export function formatDocTitle(title?: string) {
+  return `${title ? `${title} - ` : ""}Marvin`;
+}
diff --git a/src/common/pages/about.tsx b/src/common/pages/about.tsx
index 24b7440..a95242c 100644
--- a/src/common/pages/about.tsx
+++ b/src/common/pages/about.tsx
@@ -84,5 +84,7 @@
         </App>
       );
     }
-  }
+  },
+
+  title: () => "About"
 };
diff --git a/src/common/pages/error.tsx b/src/common/pages/error.tsx
index 6c1bbe2..e72dd99 100644
--- a/src/common/pages/error.tsx
+++ b/src/common/pages/error.tsx
@@ -21,5 +21,7 @@
         </p>
       </Page>
     );
-  }
+  },
+
+  title: () => "Unexpected error"
 };
diff --git a/src/common/pages/not-found.tsx b/src/common/pages/not-found.tsx
index ef7fc98..ce307bb 100644
--- a/src/common/pages/not-found.tsx
+++ b/src/common/pages/not-found.tsx
@@ -21,5 +21,7 @@
         </Page>
       </App>
     );
-  }
+  },
+
+  title: () => "Not found"
 };
diff --git a/src/common/pages/style-guide.tsx b/src/common/pages/style-guide.tsx
index 089f980..408fca5 100644
--- a/src/common/pages/style-guide.tsx
+++ b/src/common/pages/style-guide.tsx
@@ -60,5 +60,7 @@
         </Page>
       </App>
     );
-  }
+  },
+
+  title: () => "Style guide"
 };
diff --git a/src/common/pages/summary.tsx b/src/common/pages/summary.tsx
index a579127..229a620 100644
--- a/src/common/pages/summary.tsx
+++ b/src/common/pages/summary.tsx
@@ -68,5 +68,7 @@
         </Page>
       </App>
     );
-  }
+  },
+
+  title: ({ summary }: Props) => summary.titleText
 };
diff --git a/src/common/pages/wiki.tsx b/src/common/pages/wiki.tsx
index df54723..e854d12 100644
--- a/src/common/pages/wiki.tsx
+++ b/src/common/pages/wiki.tsx
@@ -88,5 +88,7 @@
         </Page>
       </App>
     );
-  }
+  },
+
+  title: ({ page }: Props) => page.titleText
 };
diff --git a/src/common/router/route.ts b/src/common/router/route.ts
index 9be7cb5..f38343e 100644
--- a/src/common/router/route.ts
+++ b/src/common/router/route.ts
@@ -32,6 +32,9 @@
 
       /** A Preact view component. */
       Component: Partial<AnyComponent<Props, any>>;
+
+      /** The document title shown in the browser window's title bar or tab. */
+      title?: (props: Props) => string | undefined;
     }
   | {
       getInitialProps?: undefined;
@@ -43,6 +46,8 @@
       status?: number;
 
       Component: Partial<AnyComponent<undefined, any>>;
+
+      title?: () => string | undefined;
     };
 
 export interface PageModule<Params, Props> {
diff --git a/src/common/router/router.ts b/src/common/router/router.ts
index 0e5f69f..21326c2 100644
--- a/src/common/router/router.ts
+++ b/src/common/router/router.ts
@@ -9,11 +9,12 @@
   chunkName?: string;
   status: number;
   Component: AnyComponent<Props, any>;
+  title?: (props: Props) => string | undefined;
   props: Props;
 }
 
-interface RequestPageModule {
-  (name: string): Promise<PageModule<any, any>>;
+interface RequestPageModule<Params, Props> {
+  (name: string): Promise<PageModule<Params, Props>>;
 }
 
 function getInitialProps<Params, Props>(
@@ -36,7 +37,7 @@
 }
 
 function respond<Params, Props>(
-  requestPageModule: RequestPageModule,
+  requestPageModule: RequestPageModule<Params, Props>,
   route: Route<Params>,
   params: Params
 ): Promise<RouteResponse<Props>> {
@@ -49,7 +50,8 @@
       chunkName: `pages/${route.page}`,
       status: (response && response.status) || module.default.status || 200,
       Component: module.default.Component as AnyComponent<Props, any>,
-      props: (response && response.data) as Props
+      props: (response && response.data) as Props,
+      title: module.default.title
     }))
   );
 }
@@ -61,7 +63,8 @@
   return Promise.resolve({
     status: notFoundPage.status,
     Component: notFoundPage.Component,
-    props
+    props,
+    title: notFoundPage.title
   });
 }
 
@@ -78,12 +81,17 @@
 
   const status = error instanceof FetchError ? error.status : errorPage.status;
   const props: ErrorProps = { error };
-  return Promise.resolve({ status, Component: errorPage.Component, props });
+  return Promise.resolve({
+    status,
+    Component: errorPage.Component,
+    props,
+    title: errorPage.title
+  });
 }
 
 export function newRouter(
   routes: Route<any>[],
-  requestPageModule: RequestPageModule = requestPageModuleChunk
+  requestPageModule: RequestPageModule<any, any> = requestPageModuleChunk
 ) {
   return {
     route(path: string): Promise<RouteResponse<any>> {
diff --git a/src/server/components/html-page.tsx 
b/src/server/components/html-page.tsx
index 12fcdb6..8c5f32b 100644
--- a/src/server/components/html-page.tsx
+++ b/src/server/components/html-page.tsx
@@ -23,7 +23,7 @@
   : undefined;
 
 export default function HTMLPage({
-  title = "",
+  title,
   chunkName,
   ssrData,
   children
@@ -49,7 +49,7 @@
         <meta charSet="utf-8" />
         <meta http-equiv="x-ua-compatible" content="ie=edge" />
         <meta name="viewport" content="width=device-width, initial-scale=1" />
-        <title>{title ? `${title} - ` : ""}Marvin</title>
+        <title>{title}</title>
         {/* Preload the stylesheet before the scripts */}
         <link rel="preload" href={style} as="style" />
         <link rel="stylesheet" href={style} />
diff --git a/src/server/index.tsx b/src/server/index.tsx
index efcc6c8..efb75bb 100644
--- a/src/server/index.tsx
+++ b/src/server/index.tsx
@@ -7,6 +7,7 @@
 import { routes } from "../common/router/routes";
 import { SERVER_PORT, SERVER_URL } from "../common/assets/config";
 import ErrorPage from "../common/pages/error";
+import { formatDocTitle } from "../common/format-doc-title";
 import HTMLPage from "./components/html-page";
 
 const server = express();
@@ -19,18 +20,17 @@
 
 server.use("/public", express.static("dist/public"));
 
-function render({ chunkName, Component, props }: RouteResponse<any>) {
+function render({ chunkName, Component, props, title }: RouteResponse<any>) {
+  const docTitle = formatDocTitle(title ? title(props) : undefined);
   // When an unexpected error occurs, forbid client re-rendering so that the
   // original error can be shown.
   const forceSSR = Component === ErrorPage.Component;
-  return (
-    "<!doctype html>" + // eslint-disable-line prefer-template
-    renderToString(
-      <HTMLPage title="" chunkName={chunkName} ssrData={{ forceSSR }}>
-        <Component {...props} />
-      </HTMLPage>
-    )
+  const html = renderToString(
+    <HTMLPage title={docTitle} chunkName={chunkName} ssrData={{ forceSSR }}>
+      <Component {...props} />
+    </HTMLPage>
   );
+  return `<!doctype html>${html}`;
 }
 
 const router = newRouter(routes);
diff --git a/test/server/components/html-page.test.ts 
b/test/server/components/html-page.test.ts
index ef48709..ecaf5f1 100644
--- a/test/server/components/html-page.test.ts
+++ b/test/server/components/html-page.test.ts
@@ -25,7 +25,7 @@
       ssrData: { forceSSR: false }
     });
     const html = render(vNode);
-    const expected = "<title>Test - Marvin</title>";
+    const expected = "<title>Test</title>";
     assert.ok(
       html.includes(expected),
       `Could not find \n\n${expected}\n\nin\n\n${html}`

-- 
To view, visit https://gerrit.wikimedia.org/r/396418
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I46bd5ded51df65651045613ea0b588d48f5c1847
Gerrit-PatchSet: 1
Gerrit-Project: marvin
Gerrit-Branch: master
Gerrit-Owner: Niedzielski <[email protected]>
Gerrit-Reviewer: Jhernandez <[email protected]>
Gerrit-Reviewer: Sniedzielski <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to