Skip to content
This repository was archived by the owner on Oct 6, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .env.template
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
REACT_APP_KONTENT_PROJECT_ID=
# REACT_APP_KONTENT_GRAPHQL_ENDPOINT=
# REACT_APP_KONTENT_GRAPHQL_ENDPOINT=
# REACT_APP_GA_ANALYTICS_TOKEN=
2 changes: 2 additions & 0 deletions .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ jobs:
cache: 'npm'
- run: npm ci
- run: npm run build --if-present
env:
REACT_APP_GA_ANALYTICS_TOKEN: ${{ secrets.REACT_APP_GA_ANALYTICS_TOKEN }}
- name: Deploy 🚀
if: github.ref == 'refs/heads/main'
uses: JamesIves/github-pages-deploy-action@3.6.2
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

# misc
.DS_Store
.env
.env.local
.env.development.local
.env.test.local
Expand Down
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ This optional section allows you to create your own copy of the project in Konte
> ```sh
> npm i -g @kentico/kontent-backup-manager@3.0.1
> # or
> yarn global add @kentico/kontent-backup-manager
> yarn global add @kentico/kontent-backup-manager@3.0.1
>
> kbm --action=restore --projectId=<Project ID> --apiKey=<Management API key> --zipFilename=kontent-backup
> ```
Expand All @@ -67,10 +67,11 @@ This optional section allows you to create your own copy of the project in Konte

> By default, the content is loaded from a shared Kentico Kontent project. If you want to use your own clone of the project so that you can customize it and experiment with Kontent, continue to the next section.

| Variable | Required | Description |
| :--------------------------------: | :------: | :----------------------- |
| REACT_APP_KONTENT_PROJECT_ID | NO | Project identification |
| REACT_APP_KONTENT_GRAPHQL_ENDPOINT | NO | Kontent GraphQL endpoint |
| Variable | Required | Description |
| :--------------------------------: | :------: | :--------------------------------------------------------------------------------------- |
| REACT_APP_KONTENT_PROJECT_ID | NO | Project identification |
| REACT_APP_KONTENT_GRAPHQL_ENDPOINT | NO | Kontent GraphQL endpoint |
| REACT_APP_GA_ANALYTICS_TOKEN | NO | If you want to inject [Google analytics](https://developers.google.com/analytics) script |

## Content editing development

Expand Down Expand Up @@ -547,6 +548,10 @@ query PostsQuery($persona: String) {

---

## Tracking

The package is including tracking header to the requests to Kontent, which helps to identify the adoption of the source plugin and helps to analyze what happened in case of error. If you think that tracking should be optional feel free to raise the feature or pull request.

## Learn More

> This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
Expand Down
7 changes: 6 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

55 changes: 28 additions & 27 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,31 +1,7 @@
{
"name": "kontent-sample-app-graphql-react",
"name": "@kentico/kontent-sample-app-graphql-react",
"version": "0.1.0",
"private": true,
"dependencies": {
"@apollo/client": "^3.4.17",
"@kentico/kontent-delivery": "^10.4.1",
"@material-ui/core": "^4.11.4",
"@material-ui/icons": "^4.11.2",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"clsx": "^1.1.1",
"graphql": "^15.5.0",
"html-react-parser": "^1.2.6",
"lodash.camelcase": "^4.3.0",
"lodash.get": "^4.4.2",
"lodash.upperfirst": "^4.3.1",
"material-ui-image": "^3.3.2",
"prop-types": "^15.7.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-helmet-async": "^1.0.9",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",
"rxjs": "^7.0.0",
"web-vitals": "^1.0.1"
},
"homepage": "https://kentico.github.io/kontent-sample-app-graphql-react/",
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
Expand All @@ -49,5 +25,30 @@
"last 1 firefox version",
"last 1 safari version"
]
},
"dependencies": {
"@apollo/client": "^3.4.17",
"@kentico/kontent-delivery": "^10.4.1",
"@material-ui/core": "^4.11.4",
"@material-ui/icons": "^4.11.2",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"clsx": "^1.1.1",
"graphql": "^15.5.0",
"html-react-parser": "^1.2.6",
"lodash.camelcase": "^4.3.0",
"lodash.get": "^4.4.2",
"lodash.upperfirst": "^4.3.1",
"material-ui-image": "^3.3.2",
"prop-types": "^15.7.2",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-ga": "^3.3.0",
"react-helmet-async": "^1.0.9",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",
"rxjs": "^7.0.0",
"web-vitals": "^1.0.1"
}
}
}
22 changes: 16 additions & 6 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import { Router, Switch, Route } from "react-router-dom";
import React, { useState } from "react";
import ReactGA from 'react-ga';
import { createBrowserHistory } from 'history';
import { gql, useQuery } from "@apollo/client";
import get from "lodash.get";
import Post from "./Post";
import { getUrlSlug } from "./utils";
import { getUrlFromMappingByPathName } from "./utils";
import LandingPage from "./LandingPage";
import ListingPage from "./ListingPage";
import SimplePage from "./SimplePage";
Expand All @@ -18,7 +20,7 @@ import GraphQLLoader from "./components/GraphQLLoader";
import getSeo from "./utils/getSeo";
import { getListingPaginationAndFilter } from "./utils/queryString";

export default function App() {
export default function App(props) {
const homePageQuery = gql`
query HomePageQuery($codename: String!) {
post_All {
Expand Down Expand Up @@ -165,7 +167,7 @@ export default function App() {
});

return mappings.reduce((result, item) => {
result[getUrlSlug(item.slug)] = {
result[[].concat(item.slug).join("/")] = {
navigationCodename: item.navigationCodename,
navigationType: item.navigationType,
contentCodename: item.contentCodename,
Expand Down Expand Up @@ -211,16 +213,24 @@ export default function App() {
return <GraphQLLoader error={error} loading={loading} />;
}

const history = createBrowserHistory();
if (props.initializeAnalytics) {
history.listen(location => {
ReactGA.set({ page: location.pathname });
ReactGA.pageview(location.pathname);
});
}

return (
<Router>
<Router history={history} basename={process.env.PUBLIC_URL}>
<Switch>
<Route path="/" render={renderPage} />
</Switch>
</Router>
);

function renderPage({ location }) {
const navigationItem = mappings[getUrlSlug(location.pathname)];
const navigationItem = getUrlFromMappingByPathName(mappings, location.pathname);

if (!navigationItem) {
if (process.env.NODE_ENV === "development") {
Expand Down
4 changes: 2 additions & 2 deletions src/components/RichText.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { makeStyles, Typography, useTheme } from "@material-ui/core";
import get from "lodash.get";
import { Image, Link } from ".";
import { getUrlFromMapping } from "../utils";
import { getUrlFromMappingByCodename } from "../utils";
import RichTextComponent from "./RichTextComponent";

const useStyles = makeStyles((theme) => ({
Expand Down Expand Up @@ -84,7 +84,7 @@ function RichText(props) {
);
}}
resolveLink={(link, mappings, domNode, domToReact) => {
const url = getUrlFromMapping(mappings, link._system_.codename);
const url = getUrlFromMappingByCodename(mappings, link._system_.codename);
if (url) {
return (
<Link href={url}>
Expand Down
12 changes: 9 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import React from 'react';
import ReactDOM from 'react-dom';
import ReactGA from 'react-ga';
import App from './App';
import { HelmetProvider } from 'react-helmet-async';
import { ApolloClient, ApolloProvider, InMemoryCache } from '@apollo/client';

import { name, version } from "../package.json";

const GQL_ENDPOINT = process.env.REACT_APP_KONTENT_GRAPHQL_ENDPOINT || "https://graphql.kontent.ai";
const PROJECT_ID = process.env.REACT_APP_KONTENT_PROJECT_ID || "ad25961e-f934-01dc-e1fa-f4dd41b84df2";

const GA_TOKEN = process.env.REACT_APP_GA_ANALYTICS_TOKEN;

const client = new ApolloClient({
cache: new InMemoryCache({
Expand All @@ -21,13 +22,18 @@ const client = new ApolloClient({
// }
}),
uri: `${GQL_ENDPOINT}/${PROJECT_ID}`,
headers: {
'X-KC-SOURCE': `${name};${version}`
}
});

GA_TOKEN && ReactGA.initialize(GA_TOKEN);

ReactDOM.render(
<React.StrictMode>
<HelmetProvider>
<ApolloProvider client={client}>
<App />
<App initializeAnalytics={!!GA_TOKEN}/>
</ApolloProvider>
</HelmetProvider>
</React.StrictMode>,
Expand Down
16 changes: 15 additions & 1 deletion src/utils/getUrlFromMapping.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
export default function getUrlFromMapping(mappings, codename) {
export function getUrlFromMappingByCodename(mappings, codename) {
return Object.keys(mappings).find(key => mappings[key].navigationCodename === codename);
}

export function getUrlFromMappingByPathName(mappings, pathname) {
debugger;

let unifiedPath = pathname;

if (pathname.startsWith(process.env.PUBLIC_URL)) {
unifiedPath = pathname.replace(process.env.PUBLIC_URL, "");
}

unifiedPath = unifiedPath.startsWith("/") ? unifiedPath.substring(1) : unifiedPath;

return mappings[unifiedPath];
}
6 changes: 5 additions & 1 deletion src/utils/getUrlSlug.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,9 @@ export default function getUrlSlug(slugPartsArrayOrString) {
const slugParts = [].concat(slugPartsArrayOrString);
const slug = slugParts.join("/");

return slug.startsWith("/") ? slug : `/${slug}`
if (!slug || slug === "/") {
return process.env.PUBLIC_URL || "/"
}

return process.env.PUBLIC_URL + (slug.startsWith("/") ? slug : `/${slug}`)
}
5 changes: 3 additions & 2 deletions src/utils/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import getUrlFromMapping from "./getUrlFromMapping";
import { getUrlFromMappingByCodename, getUrlFromMappingByPathName } from "./getUrlFromMapping";
import kontentImageLoader from "./kontentImageLoader";
import srcIsKontentAsset from "./srcIsKontentAsset";
import getUrlSlug from "./getUrlSlug";

export {
getUrlFromMapping,
getUrlFromMappingByCodename,
getUrlFromMappingByPathName,
kontentImageLoader,
srcIsKontentAsset,
getUrlSlug,
Expand Down