Repository: reactioncommerce/reaction-next-starterkit (js)

Issue:
Tags: Tag Listing Page (TLP) title should come from tag's display name
# Title on the tag listing page

### Summary description

As a Reaction 2.0 Admin User, I can set a Slug, and Display Title (on Tag Listing Page), independently of Tag name.

The tag's display title, as entered in by an Admin in this ticket https://github.com/reactioncommerce/reaction/issues/4844.

### Rationale for why this feature is necessary

A title is needed for better SEO and context for customers

### Expected use cases

- Better SEO
- Better user context for the tag page

### Expected Work

Tag title should be displayed on the Storefront's Tag Listing Page and it should also be set as the page's title (the title that is displayed in the tab of the browser).

Designs: https://app.zeplin.io/project/5afc82f5e8d73e250ff9d855/dashboard?tag=Product%20Grid



Pull request:
feat(tlp title): add tag listing page's display title
Resolves #445 
Impact: **minor**
Type: **feature**

## Issue
- Add the Display Title to the Tag Landing Page (called `ProductGridPage`)


## Solution
- Create `ProductGridTitle` component that takes a tag object and displays the tag object's `displayTitle`

<img width="1440" alt="screen shot 2018-12-05 at 3 31 19 pm" src="https://user-images.githubusercontent.com/3673236/49551123-de229980-f8a2-11e8-963c-39122eea8cf9.png">
 in code)

## Breaking changes
None. If a tag doesn't have a displayTitle, the component will not render.

## Testing
1. Test a tag listing page with a title
2. Test a tag listing page without a title
3. Test with this PR https://github.com/reactioncommerce/reaction/pull/4856

## Post-merge
Add Display Titles to some Tags in the Sample Catalog, for testing.

Patch:
diff --git a/src/components/ProductGridTitle/ProductGridTitle.js b/src/components/ProductGridTitle/ProductGridTitle.js
new file mode 100644
index 00000000..b26de68f
--- /dev/null
+++ b/src/components/ProductGridTitle/ProductGridTitle.js
@@ -0,0 +1,36 @@
+import React, { Component } from "react";
+import PropTypes from "prop-types";
+import { withStyles } from "@material-ui/core/styles";
+import Typography from "@material-ui/core/Typography";
+
+const styles = (theme) => ({
+  gridTitle: {
+    color: theme.palette.reaction.coolGrey500,
+    fontWeight: theme.typography.fontWeightMedium,
+    margin: "30px 0",
+    textAlign: "center"
+  }
+});
+
+@withStyles(styles, { name: "SkProductGridTitle" })
+export default class ProductGridTitle extends Component {
+  static propTypes = {
+    classes: PropTypes.object,
+    displayTitle: PropTypes.string
+  };
+
+  static defaultProps = {
+    classes: {},
+    displayTitle: ""
+  };
+
+  render() {
+    const { classes, displayTitle } = this.props;
+
+    if (!displayTitle) return null;
+
+    return (
+      <Typography className={classes.gridTitle} component="h1" variant="title">{displayTitle}</Typography>
+    );
+  }
+}
diff --git a/src/components/ProductGridTitle/index.js b/src/components/ProductGridTitle/index.js
new file mode 100644
index 00000000..e2849394
--- /dev/null
+++ b/src/components/ProductGridTitle/index.js
@@ -0,0 +1,1 @@
+export { default } from "./ProductGridTitle";
diff --git a/src/containers/tags/tagFragment.gql b/src/containers/tags/tagFragment.gql
index dcdd3938..fadf8809 100644
--- a/src/containers/tags/tagFragment.gql
+++ b/src/containers/tags/tagFragment.gql
@@ -6,4 +6,5 @@ fragment TagInfo on Tag {
   isTopLevel
   subTagIds
   heroMediaUrl
+  displayTitle
 }
diff --git a/src/pages/tag.js b/src/pages/tag.js
index 61da319a..d46a34d2 100644
--- a/src/pages/tag.js
+++ b/src/pages/tag.js
@@ -7,6 +7,7 @@ import withTag from "containers/tags/withTag";
 import Breadcrumbs from "components/Breadcrumbs";
 import ProductGrid from "components/ProductGrid";
 import ProductGridHero from "components/ProductGridHero";
+import ProductGridTitle from "components/ProductGridTitle";
 import trackProductListViewed from "lib/tracking/trackProductListViewed";
 
 @withTag
@@ -106,6 +107,9 @@ export default class TagGridPage extends Component {
           meta={[{ name: "description", content: shop && shop.description }]}
         />
         <Breadcrumbs isTagGrid={true} tag={tag} tags={tags} />
+        {
+          tag && tag.displayTitle && <ProductGridTitle displayTitle={tag.displayTitle} />
+        }
         <ProductGridHero tag={tag} />
         <ProductGrid
           catalogItems={catalogItems}


Test patch:
diff --git a/src/components/ProductGridTitle/ProductGridTitle.test.js b/src/components/ProductGridTitle/ProductGridTitle.test.js
new file mode 100644
index 00000000..dbbdf9b0
--- /dev/null
+++ b/src/components/ProductGridTitle/ProductGridTitle.test.js
@@ -0,0 +1,36 @@
+import React from "react";
+import renderer from "react-test-renderer";
+import { Provider } from "mobx-react";
+import { MuiThemeProvider } from "@material-ui/core/styles";
+import theme from "custom/reactionTheme";
+import ProductGridTitle from "./ProductGridTitle";
+
+const uiStore = {
+  appConfig: {
+    publicRuntimeConfig: {
+      placeholderImageUrls: {
+        productGrid: ""
+      }
+    }
+  }
+};
+
+test("snapshot of a tag with a displayTitle", () => {
+  const component = renderer.create(<MuiThemeProvider theme={theme}>
+    <Provider uiStore={uiStore}>
+      <ProductGridTitle displayTitle={"Test Title"} />
+    </Provider>
+  </MuiThemeProvider>);
+  const tree = component.toJSON();
+  expect(tree).toMatchSnapshot();
+});
+
+test("snapshop of tag without a displayTitle", () => {
+  const component = renderer.create(<MuiThemeProvider theme={theme}>
+    <Provider uiStore={uiStore}>
+      <ProductGridTitle displayTitle={""} />
+    </Provider>
+  </MuiThemeProvider>);
+  const tree = component.toJSON();
+  expect(tree).toMatchSnapshot();
+});
diff --git a/src/components/ProductGridTitle/__snapshots__/ProductGridTitle.test.js.snap b/src/components/ProductGridTitle/__snapshots__/ProductGridTitle.test.js.snap
new file mode 100644
index 00000000..1c6ecaaa
--- /dev/null
+++ b/src/components/ProductGridTitle/__snapshots__/ProductGridTitle.test.js.snap
@@ -0,0 +1,11 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`snapshop of tag without a displayTitle 1`] = `null`;
+
+exports[`snapshot of a tag with a displayTitle 1`] = `
+<h1
+  className="MuiTypography-root-2 MuiTypography-title-8 SkProductGridTitle-gridTitle-1"
+>
+  Test Title
+</h1>
+`;