From 23b0701078f0652e8e92121b24fde89fd0e29c3e Mon Sep 17 00:00:00 2001 From: Ivan Kiral Date: Tue, 7 Jun 2022 15:43:02 +0200 Subject: [PATCH 01/21] Add app description --- README.md | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/README.md b/README.md index 28e87de..48fd420 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,50 @@ For more info about the API, see the [API reference](https://kontent.ai/learn/re You can find the Delivery and other SDKs at . +## About +This section describes the application. + +### Used toolchain +This application is based on the [Create React App](https://reactjs.org/docs/create-a-new-react-app.html) using the following template `--template typescript`. + +### Model mapping +There are two types of model mapping in this application: +- content types -> component +- component -> view model + +For generating component models from content types, we have used [Kontent.ai model generator](https://github.com/Kentico/kontent-model-generator-js) tool. All generated models can be found in in [src/Models](https://github.com/Kentico/kontent-sample-app-react/tree/master/src/Models) folder. The `_project.ts` exports `projectModel` which contains information about the project structure such as project languages as well as information such as codenames about content types. Those generated models are used to obtain correctly typed objects via client in [src/Pages](https://github.com/Kentico/kontent-sample-app-react/tree/master/src/Pages). To obtain your data provide a generated DTO type into generic brackets for `items` method and content types codename from `projectModel` as a parameter of `type` method. See following example: + +```{typescript} +const query = Client.items() + .type(projectModel.contentTypes.generatedDTO.codename)... +``` + +Some models displayed in views might require a small adjustment from content types. For example, `Cafe` content type contains fields for `city` and `street` and we would like to have model containing an address in the format `city, street`. You can find an example for such a view model in `CafeModel.tsx` can be found in the `src/ViewModels` folder. To convert `Cafe` into `CafeModel` you can use function located in `src/Utilities/CafeListing.ts` + +### Filtering in product catalog +Filters in Kontent.ai are implement by using taxonomies. Filtering examples can be found in `src/Components/BrewerStoreContainer.tsx` or `src/Components/CoffeeStoreContainer.tsx`. Firstly, the taxonomies groups that contain possible values for filters are loaded in `useEffect` blocks. We store selected values for filtering in `filter` variable. Items to be displayed are then selected with functional `filter` function checking whether the item matches the filter. + +### Data fetching +This solution fetches required data directly in the pages using the [Delivery client](https://github.com/Kentico/kontent-delivery-sdk-js). For more implementation detail to setup client see `src/Client.ts`. Depending on your needs, you can use other technologies for managing application state such as: +- Context +- Redux +- Flux +- ... + +### Localization +In Kontent each language is identified by codename, in case of this project its is `en-US` and `es-ES`. + +#### Resoure strings +Not every text of the application must be stored in Kontent.ai. Some strings, such as button texts, navigation texts and so on, can be stored locally. For those texts we use [React-intl](https://formatjs.io/docs/getting-started/installation/). For every language we have created JSON file in `src/Localization` folder. As we use `React-intl` it can not parse nested JSON objects and therefore the format of files is `key:value`. To load all files from `src/Localization` folder we have prepared a script, see `src/utilities/LocalizationLoader.ts` + +#### Prefixes and Localizable Url slugs +The language prefix is obtained from URL in the `LocalizedApp.tsx` and then it is propagated via IntlProvider to the whole application. Content language is then is then adjusted in pages modifying `Client` with `languageParameter()` method to obtain items in specific language. By default it uses [language fallbacks](https://kontent.ai/learn/tutorials/manage-kontent/projects/set-up-languages/#a-language-fallbacks) set up in the project. + +You might want to request items based on the url slugs. For more information how it works in Kontent see this [link](https://kontent.ai/learn/tutorials/develop-apps/get-content/localized-content-items/#a-get-items-by-localized-url-slug). We have provided an example in this application for `src/Pages/About.tsx' page. + +### Handling 404 +For the not found resources we use prefixed 404 pages for both languages. As the content in one page should be in one language, this approach might help you to optimize SEO. If language is not set in the URL the application uses the last used language, which is set in cookies. + ## Deployment You can use eg. [surge](http://surge.sh/) to deploy your app live. Check out the step-by-step guide on our [blog](https://kontent.ai/blog/3-steps-to-rapidly-deploy-headless-single-page-app). From be2e000bdca98ebd070130d7ecaaeb00aa0ac5f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Kir=C3=A1=C4=BE?= <54802833+IvanKiral@users.noreply.github.com> Date: Tue, 14 Jun 2022 09:21:47 +0200 Subject: [PATCH 02/21] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ondřej Chrastina <9218736+Simply007@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 48fd420..e90c4c4 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ There are two types of model mapping in this application: For generating component models from content types, we have used [Kontent.ai model generator](https://github.com/Kentico/kontent-model-generator-js) tool. All generated models can be found in in [src/Models](https://github.com/Kentico/kontent-sample-app-react/tree/master/src/Models) folder. The `_project.ts` exports `projectModel` which contains information about the project structure such as project languages as well as information such as codenames about content types. Those generated models are used to obtain correctly typed objects via client in [src/Pages](https://github.com/Kentico/kontent-sample-app-react/tree/master/src/Pages). To obtain your data provide a generated DTO type into generic brackets for `items` method and content types codename from `projectModel` as a parameter of `type` method. See following example: -```{typescript} +```typescript const query = Client.items() .type(projectModel.contentTypes.generatedDTO.codename)... ``` From 19278f7ef9946f4a46821f37032190521619876b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Kir=C3=A1=C4=BE?= <54802833+IvanKiral@users.noreply.github.com> Date: Tue, 14 Jun 2022 09:23:36 +0200 Subject: [PATCH 03/21] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ondřej Chrastina <9218736+Simply007@users.noreply.github.com> --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index e90c4c4..a5bb3fb 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,8 @@ There are two types of model mapping in this application: For generating component models from content types, we have used [Kontent.ai model generator](https://github.com/Kentico/kontent-model-generator-js) tool. All generated models can be found in in [src/Models](https://github.com/Kentico/kontent-sample-app-react/tree/master/src/Models) folder. The `_project.ts` exports `projectModel` which contains information about the project structure such as project languages as well as information such as codenames about content types. Those generated models are used to obtain correctly typed objects via client in [src/Pages](https://github.com/Kentico/kontent-sample-app-react/tree/master/src/Pages). To obtain your data provide a generated DTO type into generic brackets for `items` method and content types codename from `projectModel` as a parameter of `type` method. See following example: ```typescript -const query = Client.items() +const query = Client.items() + .type(projectModel.contentTypes.generatedDTO.codename)... ``` From 566100e11d3e211ba6ce3156090250a6be623d42 Mon Sep 17 00:00:00 2001 From: Ivan Kiral Date: Thu, 16 Jun 2022 10:21:15 +0200 Subject: [PATCH 04/21] Update Readme --- README.md | 140 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 126 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 48fd420..d56746e 100644 --- a/README.md +++ b/README.md @@ -77,47 +77,159 @@ For more info about the API, see the [API reference](https://kontent.ai/learn/re You can find the Delivery and other SDKs at . ## About + This section describes the application. ### Used toolchain + This application is based on the [Create React App](https://reactjs.org/docs/create-a-new-react-app.html) using the following template `--template typescript`. -### Model mapping +### Model mapping and data fetching + There are two types of model mapping in this application: -- content types -> component -- component -> view model -For generating component models from content types, we have used [Kontent.ai model generator](https://github.com/Kentico/kontent-model-generator-js) tool. All generated models can be found in in [src/Models](https://github.com/Kentico/kontent-sample-app-react/tree/master/src/Models) folder. The `_project.ts` exports `projectModel` which contains information about the project structure such as project languages as well as information such as codenames about content types. Those generated models are used to obtain correctly typed objects via client in [src/Pages](https://github.com/Kentico/kontent-sample-app-react/tree/master/src/Pages). To obtain your data provide a generated DTO type into generic brackets for `items` method and content types codename from `projectModel` as a parameter of `type` method. See following example: +#### content type -> DTO -> component -```{typescript} -const query = Client.items() - .type(projectModel.contentTypes.generatedDTO.codename)... -``` +For generating component models from content types, we have used [Kontent.ai model generator](https://github.com/Kentico/kontent-model-generator-js) tool. All generated models can be found in [src/Models] folder. The `_project.ts` exports `projectModel` which contains information about the project structure such as project languages as well as other information such as codenames about content types. Generated models are used to obtain correctly typed objects via client. + +#### content type -> DTO -> view model -> component -Some models displayed in views might require a small adjustment from content types. For example, `Cafe` content type contains fields for `city` and `street` and we would like to have model containing an address in the format `city, street`. You can find an example for such a view model in `CafeModel.tsx` can be found in the `src/ViewModels` folder. To convert `Cafe` into `CafeModel` you can use function located in `src/Utilities/CafeListing.ts` +Some models displayed in views might require a small adjustment from content types. For example, `Cafe` content type contains fields for `city` and `street` and we would like to have model containing an address in the format `city, street`. You can find an example for such a view model in `CafeModel.tsx` that can be found in the `src/ViewModels` folder. To convert `Cafe` into `CafeModel` you can use function located in `src/Utilities/CafeListing.ts` -### Filtering in product catalog -Filters in Kontent.ai are implement by using taxonomies. Filtering examples can be found in `src/Components/BrewerStoreContainer.tsx` or `src/Components/CoffeeStoreContainer.tsx`. Firstly, the taxonomies groups that contain possible values for filters are loaded in `useEffect` blocks. We store selected values for filtering in `filter` variable. Items to be displayed are then selected with functional `filter` function checking whether the item matches the filter. +#### Data fetching + +This solution fetches data using the [Delivery client](https://github.com/Kentico/kontent-delivery-sdk-js). For more implementation detail to setup client see `src/Client.ts`. The data are fetched and stored in a `container` component and they are then passed to presentation component. For better understanding see the code example below. However, depending on your needs, you can use other technologies for managing application state such as: -### Data fetching -This solution fetches required data directly in the pages using the [Delivery client](https://github.com/Kentico/kontent-delivery-sdk-js). For more implementation detail to setup client see `src/Client.ts`. Depending on your needs, you can use other technologies for managing application state such as: - Context - Redux - Flux - ... +```typescript +const Component: React.FC = () => { + const [data, setData] = useState([] : DTOComponentProps); + + useEffect(() => { + const query = Client.items() + .type(projectModel.contentTypes.generatedDTO.codename) + ... + + const items : GeneratedDTO[] = query.ToPromise() + .then(data => data.items() + .then(items => setData(items)); + }, []); + + return ( + {data.map(item => )} + ); + ... +} +``` + +### Filtering in product catalog + +Filters in Kontent.ai are implement using taxonomies. Filtering examples can be found in `src/Components/BrewerStoreContainer.tsx` or `src/Components/CoffeeStoreContainer.tsx`. Firstly, the taxonomies groups that contain possible values for filters are loaded in `useEffect` blocks. We store selected values for filtering in `filter` variable. Items to be displayed are then selected with functional `filter` function checking whether the item matches the filter. + +```typescript +interface FilterType { + [index: string]: string[]; + filterVariable1: string[]; + filterVariable2: string[]; +} + +const Container: React.FC = () => { + const [filterVariable1, setFilterVariable1] = useState([]); + const [filterVariable2, setFilterVariable2] = useState([]); + + const [filter, setFilter] = useState({ + filterVariable1: [], + filterVariable2: [], + }); + + useEffect(() => { + Client.taxonomy('filter_variable_1') + .toPromise() + .then((response) => {setFilterVariable1(response.data.taxonomy.terms);}); + }, []); + + useEffect(() => { + Client.taxonomy('filter_variable_2') + .toPromise() + .then((response) => {setFilterVariable2(response.data.taxonomy.terms);}); + }, []); + + const matches = (coffee: Coffee): boolean => + matchesTaxonomy(coffee, filter.processings, 'filterVariable1') && + matchesTaxonomy(coffee, filter.productStatuses, 'filterVariable2'); + // To see how matchesTaxonomy can work see src/Utilities/CheckboxFilter + + const toggleFilter = (filterName: string, filterValue: string): void => { + setFilter((filter) => ({ + ...filter, + [filterName]: filter[filterName].includes(filterValue) + ? filter[filterName].filter((x: string) => x !== filterValue) + : [...filter[filterName], filterValue], + })); + };. + + return ( +
+ ... + toggleFilter('filterVariable1', event.target.id), + /> + ... + matches(coffee)) } + /> + ... +
+ ); +} +``` + ### Localization -In Kontent each language is identified by codename, in case of this project its is `en-US` and `es-ES`. + +In Kontent each language is identified by codename, in case of this project it is `en-US` and `es-ES`. #### Resoure strings + Not every text of the application must be stored in Kontent.ai. Some strings, such as button texts, navigation texts and so on, can be stored locally. For those texts we use [React-intl](https://formatjs.io/docs/getting-started/installation/). For every language we have created JSON file in `src/Localization` folder. As we use `React-intl` it can not parse nested JSON objects and therefore the format of files is `key:value`. To load all files from `src/Localization` folder we have prepared a script, see `src/utilities/LocalizationLoader.ts` +```JSON +//en-US.json +{ + "LatestArticles.title": "Latest articles", + "LatestArticles.noTitleValue": "(Article has no title)", + "LatestArticles.noTeaserValue": "(Article has no teaser image)", + "LatestArticles.noSummaryValue": "No summary filled", + ... +} +``` + #### Prefixes and Localizable Url slugs + The language prefix is obtained from URL in the `LocalizedApp.tsx` and then it is propagated via IntlProvider to the whole application. Content language is then is then adjusted in pages modifying `Client` with `languageParameter()` method to obtain items in specific language. By default it uses [language fallbacks](https://kontent.ai/learn/tutorials/manage-kontent/projects/set-up-languages/#a-language-fallbacks) set up in the project. +```typescript +const Component: React.FC = () => { + const { locale: language } = useIntl();; + + useEffect(() => { + const query = Client.items() + .type(projectModel.contentTypes.itemDTO.codename); + + if (language) { + query.languageParameter(language); + } + ... +``` + You might want to request items based on the url slugs. For more information how it works in Kontent see this [link](https://kontent.ai/learn/tutorials/develop-apps/get-content/localized-content-items/#a-get-items-by-localized-url-slug). We have provided an example in this application for `src/Pages/About.tsx' page. ### Handling 404 + For the not found resources we use prefixed 404 pages for both languages. As the content in one page should be in one language, this approach might help you to optimize SEO. If language is not set in the URL the application uses the last used language, which is set in cookies. ## Deployment From 38020482cae7d753d4add813771158646fd10834 Mon Sep 17 00:00:00 2001 From: Ivan Kiral Date: Thu, 16 Jun 2022 12:03:45 +0200 Subject: [PATCH 05/21] Remove semicolon --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d56746e..4ebb8f9 100644 --- a/README.md +++ b/README.md @@ -214,7 +214,7 @@ The language prefix is obtained from URL in the `LocalizedApp.tsx` and then it i ```typescript const Component: React.FC = () => { - const { locale: language } = useIntl();; + const { locale: language } = useIntl(); useEffect(() => { const query = Client.items() From 19a22943d8e0de6dabcef5fd0d0bea61a053fa79 Mon Sep 17 00:00:00 2001 From: Ivan Kiral Date: Thu, 16 Jun 2022 12:25:02 +0200 Subject: [PATCH 06/21] Fix typos --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 4ebb8f9..b96139c 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ There are two types of model mapping in this application: #### content type -> DTO -> component -For generating component models from content types, we have used [Kontent.ai model generator](https://github.com/Kentico/kontent-model-generator-js) tool. All generated models can be found in [src/Models] folder. The `_project.ts` exports `projectModel` which contains information about the project structure such as project languages as well as other information such as codenames about content types. Generated models are used to obtain correctly typed objects via client. +For generating component models from content types, we have used [Kontent.ai model generator](https://github.com/Kentico/kontent-model-generator-js) tool. All generated models can be found in `src/Models` folder. The `_project.ts` exports `projectModel` which contains information about the project structure such as project languages as well as other information such as codenames about content types. Generated models are used to obtain correctly typed objects via client. #### content type -> DTO -> view model -> component @@ -98,7 +98,7 @@ Some models displayed in views might require a small adjustment from content typ #### Data fetching -This solution fetches data using the [Delivery client](https://github.com/Kentico/kontent-delivery-sdk-js). For more implementation detail to setup client see `src/Client.ts`. The data are fetched and stored in a `container` component and they are then passed to presentation component. For better understanding see the code example below. However, depending on your needs, you can use other technologies for managing application state such as: +This solution fetches data using the [Delivery client](https://github.com/Kentico/kontent-delivery-sdk-js). For more implementation detail to setup client see `src/Client.ts`. The data are fetched and stored in a `container` component and they are then passed to `presentation` component. For better understanding see the code example below. However, depending on your needs, you can use other technologies for managing application state such as: - Context - Redux @@ -128,7 +128,7 @@ const Component: React.FC = () => { ### Filtering in product catalog -Filters in Kontent.ai are implement using taxonomies. Filtering examples can be found in `src/Components/BrewerStoreContainer.tsx` or `src/Components/CoffeeStoreContainer.tsx`. Firstly, the taxonomies groups that contain possible values for filters are loaded in `useEffect` blocks. We store selected values for filtering in `filter` variable. Items to be displayed are then selected with functional `filter` function checking whether the item matches the filter. +Filters in Kontent.ai are implemented using taxonomies. Filtering examples can be found in `src/Components/BrewerStoreContainer.tsx` or `src/Components/CoffeeStoreContainer.tsx`. Firstly, the taxonomies groups that contain possible values for filters are loaded in `useEffect` blocks. We store selected values for filtering in `filter` variable. Items to be displayed are then selected with functional `filter` function checking whether the item matches the filter. ```typescript interface FilterType { @@ -195,22 +195,22 @@ In Kontent each language is identified by codename, in case of this project it i #### Resoure strings -Not every text of the application must be stored in Kontent.ai. Some strings, such as button texts, navigation texts and so on, can be stored locally. For those texts we use [React-intl](https://formatjs.io/docs/getting-started/installation/). For every language we have created JSON file in `src/Localization` folder. As we use `React-intl` it can not parse nested JSON objects and therefore the format of files is `key:value`. To load all files from `src/Localization` folder we have prepared a script, see `src/utilities/LocalizationLoader.ts` +Not every text of the application must be stored in Kontent.ai. Some strings, such as button texts, navigation texts and so on, can be stored locally. For those texts we use [React-intl](https://formatjs.io/docs/getting-started/installation/). For every language we have created JSON file in `src/Localization` folder. As we use `React-intl` it can not parse nested JSON objects and therefore the format of files is `key:value`. To load all files from `src/Localization` folder we have prepared a script, see `src/utilities/LocalizationLoader.ts`. -```JSON -//en-US.json +```json +// en-US.json { "LatestArticles.title": "Latest articles", "LatestArticles.noTitleValue": "(Article has no title)", "LatestArticles.noTeaserValue": "(Article has no teaser image)", - "LatestArticles.noSummaryValue": "No summary filled", - ... + "LatestArticles.noSummaryValue": "No summary filled" + // ... } ``` #### Prefixes and Localizable Url slugs -The language prefix is obtained from URL in the `LocalizedApp.tsx` and then it is propagated via IntlProvider to the whole application. Content language is then is then adjusted in pages modifying `Client` with `languageParameter()` method to obtain items in specific language. By default it uses [language fallbacks](https://kontent.ai/learn/tutorials/manage-kontent/projects/set-up-languages/#a-language-fallbacks) set up in the project. +The language prefix is obtained from URL in the `LocalizedApp.tsx` and then it is propagated via IntlProvider to the whole application. Content language is then adjusted by modifying `Client` with `languageParameter()` method to obtain items in specific language. By default it uses [language fallbacks](https://kontent.ai/learn/tutorials/manage-kontent/projects/set-up-languages/#a-language-fallbacks) set up in the project. ```typescript const Component: React.FC = () => { From 53dd777a193c74b09dba516ef87b19535145a4ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Chrastina?= <9218736+Simply007@users.noreply.github.com> Date: Mon, 20 Jun 2022 11:11:16 +0200 Subject: [PATCH 07/21] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index b96139c..28acad8 100644 --- a/README.md +++ b/README.md @@ -130,7 +130,8 @@ const Component: React.FC = () => { Filters in Kontent.ai are implemented using taxonomies. Filtering examples can be found in `src/Components/BrewerStoreContainer.tsx` or `src/Components/CoffeeStoreContainer.tsx`. Firstly, the taxonomies groups that contain possible values for filters are loaded in `useEffect` blocks. We store selected values for filtering in `filter` variable. Items to be displayed are then selected with functional `filter` function checking whether the item matches the filter. -```typescript +```tsx + interface FilterType { [index: string]: string[]; filterVariable1: string[]; From 47e86e2d2c9a8b3fc656a45950a7b536c72f523b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Kir=C3=A1=C4=BE?= <54802833+IvanKiral@users.noreply.github.com> Date: Tue, 21 Jun 2022 11:37:21 +0200 Subject: [PATCH 08/21] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ondřej Chrastina <9218736+Simply007@users.noreply.github.com> --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 28acad8..16939f9 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,8 @@ For generating component models from content types, we have used [Kontent.ai mod #### content type -> DTO -> view model -> component -Some models displayed in views might require a small adjustment from content types. For example, `Cafe` content type contains fields for `city` and `street` and we would like to have model containing an address in the format `city, street`. You can find an example for such a view model in `CafeModel.tsx` that can be found in the `src/ViewModels` folder. To convert `Cafe` into `CafeModel` you can use function located in `src/Utilities/CafeListing.ts` +Some models displayed in views might require an adjustment from content types. For example, the `Cafe` content type contains fields for `city` and `street` and we would like to have a model containing an address in the format `city, street`. You can find an example for such a view model in `CafeModel.tsx` that can be found in the `src/ViewModels` folder. To convert `Cafe` into `CafeModel` you can use the function located in `src/Utilities/CafeListing.ts` + #### Data fetching From daf93788c009a9636d6a9070fa94f7a689bff951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Kir=C3=A1=C4=BE?= <54802833+IvanKiral@users.noreply.github.com> Date: Tue, 21 Jun 2022 11:38:13 +0200 Subject: [PATCH 09/21] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ondřej Chrastina <9218736+Simply007@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 16939f9..1e62c38 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ Some models displayed in views might require an adjustment from content types. F #### Data fetching -This solution fetches data using the [Delivery client](https://github.com/Kentico/kontent-delivery-sdk-js). For more implementation detail to setup client see `src/Client.ts`. The data are fetched and stored in a `container` component and they are then passed to `presentation` component. For better understanding see the code example below. However, depending on your needs, you can use other technologies for managing application state such as: +This solution fetches data using the [Delivery client](https://github.com/Kentico/kontent-delivery-sdk-js). For more implementation detail to set up the client see `src/Client.ts`. The data are fetched and stored in a `container` component directly in its state. Then they are passed to the `presentation` component. For a better understanding see the code example below. However, depending on your needs, you can use other technologies for managing application states such as: - Context - Redux From c16b99debcabacb296b25bae9d461b0bc8db33fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Kir=C3=A1=C4=BE?= <54802833+IvanKiral@users.noreply.github.com> Date: Tue, 21 Jun 2022 11:38:37 +0200 Subject: [PATCH 10/21] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ondřej Chrastina <9218736+Simply007@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1e62c38..89d83ce 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,7 @@ This solution fetches data using the [Delivery client](https://github.com/Kentic - Flux - ... -```typescript +```tsx const Component: React.FC = () => { const [data, setData] = useState([] : DTOComponentProps); From d894f01b2e5b2132e3f9240df41701421d1cc6fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Kir=C3=A1=C4=BE?= <54802833+IvanKiral@users.noreply.github.com> Date: Tue, 21 Jun 2022 11:38:56 +0200 Subject: [PATCH 11/21] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ondřej Chrastina <9218736+Simply007@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 89d83ce..9e2369c 100644 --- a/README.md +++ b/README.md @@ -210,7 +210,7 @@ Not every text of the application must be stored in Kontent.ai. Some strings, su } ``` -#### Prefixes and Localizable Url slugs +#### Language prefixes The language prefix is obtained from URL in the `LocalizedApp.tsx` and then it is propagated via IntlProvider to the whole application. Content language is then adjusted by modifying `Client` with `languageParameter()` method to obtain items in specific language. By default it uses [language fallbacks](https://kontent.ai/learn/tutorials/manage-kontent/projects/set-up-languages/#a-language-fallbacks) set up in the project. From 89c86974dde25e8531130b0f64a8a949f50e511e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Kir=C3=A1=C4=BE?= <54802833+IvanKiral@users.noreply.github.com> Date: Tue, 21 Jun 2022 11:39:07 +0200 Subject: [PATCH 12/21] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ondřej Chrastina <9218736+Simply007@users.noreply.github.com> --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 9e2369c..2767791 100644 --- a/README.md +++ b/README.md @@ -228,6 +228,7 @@ const Component: React.FC = () => { ... ``` +#### Localizable URL slugs You might want to request items based on the url slugs. For more information how it works in Kontent see this [link](https://kontent.ai/learn/tutorials/develop-apps/get-content/localized-content-items/#a-get-items-by-localized-url-slug). We have provided an example in this application for `src/Pages/About.tsx' page. ### Handling 404 From 8dce0c0cd7f69425df4027f855c599d4e85dcd80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Kir=C3=A1=C4=BE?= <54802833+IvanKiral@users.noreply.github.com> Date: Tue, 21 Jun 2022 11:39:20 +0200 Subject: [PATCH 13/21] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ondřej Chrastina <9218736+Simply007@users.noreply.github.com> --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 2767791..d72faf7 100644 --- a/README.md +++ b/README.md @@ -231,6 +231,7 @@ const Component: React.FC = () => { #### Localizable URL slugs You might want to request items based on the url slugs. For more information how it works in Kontent see this [link](https://kontent.ai/learn/tutorials/develop-apps/get-content/localized-content-items/#a-get-items-by-localized-url-slug). We have provided an example in this application for `src/Pages/About.tsx' page. +> The showcase is not ideal, because it is using a combination of the language prefix and localizable solution is not ideal. You should try to stick with one of the approaches. Because it is hard to define the behavior for language setting clash i.e. `//articles/`. ### Handling 404 For the not found resources we use prefixed 404 pages for both languages. As the content in one page should be in one language, this approach might help you to optimize SEO. If language is not set in the URL the application uses the last used language, which is set in cookies. From 982eca463184a76216b76992e1d15b19ba45c14d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Kir=C3=A1=C4=BE?= <54802833+IvanKiral@users.noreply.github.com> Date: Tue, 21 Jun 2022 11:39:31 +0200 Subject: [PATCH 14/21] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ondřej Chrastina <9218736+Simply007@users.noreply.github.com> --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d72faf7..bc86660 100644 --- a/README.md +++ b/README.md @@ -229,7 +229,8 @@ const Component: React.FC = () => { ``` #### Localizable URL slugs -You might want to request items based on the url slugs. For more information how it works in Kontent see this [link](https://kontent.ai/learn/tutorials/develop-apps/get-content/localized-content-items/#a-get-items-by-localized-url-slug). We have provided an example in this application for `src/Pages/About.tsx' page. +You might want to request items based on the URL slugs. For more information check out [Kontent.ai/learn tutorial](https://kontent.ai/learn/tutorials/develop-apps/get-content/localized-content-items/#a-get-items-by-localized-url-slug). We have provided an example in this application for `src/Pages/About.tsx` page. + > The showcase is not ideal, because it is using a combination of the language prefix and localizable solution is not ideal. You should try to stick with one of the approaches. Because it is hard to define the behavior for language setting clash i.e. `//articles/`. ### Handling 404 From ade3afafe05184d515911539f2a38ddd6721e1c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Kir=C3=A1=C4=BE?= <54802833+IvanKiral@users.noreply.github.com> Date: Tue, 21 Jun 2022 11:39:58 +0200 Subject: [PATCH 15/21] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ondřej Chrastina <9218736+Simply007@users.noreply.github.com> --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index bc86660..f9794f0 100644 --- a/README.md +++ b/README.md @@ -197,7 +197,9 @@ In Kontent each language is identified by codename, in case of this project it i #### Resoure strings -Not every text of the application must be stored in Kontent.ai. Some strings, such as button texts, navigation texts and so on, can be stored locally. For those texts we use [React-intl](https://formatjs.io/docs/getting-started/installation/). For every language we have created JSON file in `src/Localization` folder. As we use `React-intl` it can not parse nested JSON objects and therefore the format of files is `key:value`. To load all files from `src/Localization` folder we have prepared a script, see `src/utilities/LocalizationLoader.ts`. +Not every text of the application must be stored in Kontent.ai. Some strings, such as button texts, navigation texts, and so on, can be stored directly in the application. For those texts we use [React-intl](https://formatjs.io/docs/getting-started/installation/). For every language, there is a JSON file in `src/Localization` folder. + +> `React-intl` can not parse nested JSON objects and therefore the format of files is `key:value`. To load all files from `src/Localization` folder there is a `src/utilities/LocalizationLoader.ts` script. ```json // en-US.json From 5f69cc095c34eb871437d59865ba5958d57a3f1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Kir=C3=A1=C4=BE?= <54802833+IvanKiral@users.noreply.github.com> Date: Tue, 21 Jun 2022 11:40:16 +0200 Subject: [PATCH 16/21] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ondřej Chrastina <9218736+Simply007@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f9794f0..2b48d12 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ There are two types of model mapping in this application: #### content type -> DTO -> component -For generating component models from content types, we have used [Kontent.ai model generator](https://github.com/Kentico/kontent-model-generator-js) tool. All generated models can be found in `src/Models` folder. The `_project.ts` exports `projectModel` which contains information about the project structure such as project languages as well as other information such as codenames about content types. Generated models are used to obtain correctly typed objects via client. +Content type definitions are being generated from content types via [Kontent.ai model generator](https://github.com/Kentico/kontent-model-generator-js) tool. All generated types can be found in `src/Models` folder. The `_project.ts` contains information about the project structure such as project languages as well as other structure information such as codenames about content types. #### content type -> DTO -> view model -> component From 7f84819a71f933758615bee21c3c94f42062a064 Mon Sep 17 00:00:00 2001 From: Ivan Kiral Date: Tue, 21 Jun 2022 12:32:30 +0200 Subject: [PATCH 17/21] Update readme --- README.md | 76 ++++++++++++++++++++++++++----------------------------- 1 file changed, 36 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 2b48d12..2015502 100644 --- a/README.md +++ b/README.md @@ -76,34 +76,29 @@ For more info about the API, see the [API reference](https://kontent.ai/learn/re You can find the Delivery and other SDKs at . -## About - -This section describes the application. - -### Used toolchain +## Used toolchain This application is based on the [Create React App](https://reactjs.org/docs/create-a-new-react-app.html) using the following template `--template typescript`. -### Model mapping and data fetching +## Model mapping and data fetching There are two types of model mapping in this application: -#### content type -> DTO -> component +### content type -> DTO -> component -Content type definitions are being generated from content types via [Kontent.ai model generator](https://github.com/Kentico/kontent-model-generator-js) tool. All generated types can be found in `src/Models` folder. The `_project.ts` contains information about the project structure such as project languages as well as other structure information such as codenames about content types. +Content type definitions are being generated from content types via [Kontent.ai model generator](https://github.com/Kentico/kontent-model-generator-js) tool. All generated types can be found in `src/Models` folder. The `_project.ts` contains information about the project structure such as project languages as well as other structure information like codenames about content types. -#### content type -> DTO -> view model -> component +### content type -> DTO -> view model -> component -Some models displayed in views might require an adjustment from content types. For example, the `Cafe` content type contains fields for `city` and `street` and we would like to have a model containing an address in the format `city, street`. You can find an example for such a view model in `CafeModel.tsx` that can be found in the `src/ViewModels` folder. To convert `Cafe` into `CafeModel` you can use the function located in `src/Utilities/CafeListing.ts` +Some models displayed in views might require an adjustment from content types. For example, the `Cafe` content type contains fields for `city` and `street` and we would like to have a model containing an address in the format `city, street`. An example of such a view model is in `CafeModel.tsx` that can be found in the `src/ViewModels` folder. To convert `Cafe` into `CafeModel` the function located in `src/Utilities/CafeListing.ts` can be used. - -#### Data fetching +### Data fetching This solution fetches data using the [Delivery client](https://github.com/Kentico/kontent-delivery-sdk-js). For more implementation detail to set up the client see `src/Client.ts`. The data are fetched and stored in a `container` component directly in its state. Then they are passed to the `presentation` component. For a better understanding see the code example below. However, depending on your needs, you can use other technologies for managing application states such as: -- Context -- Redux -- Flux +- [Context](https://reactjs.org/docs/context.html) +- [Redux](https://react-redux.js.org/) +- [Flux](https://facebook.github.io/flux/) - ... ```tsx @@ -127,42 +122,42 @@ const Component: React.FC = () => { } ``` -### Filtering in product catalog +## Filtering by taxonomy -Filters in Kontent.ai are implemented using taxonomies. Filtering examples can be found in `src/Components/BrewerStoreContainer.tsx` or `src/Components/CoffeeStoreContainer.tsx`. Firstly, the taxonomies groups that contain possible values for filters are loaded in `useEffect` blocks. We store selected values for filtering in `filter` variable. Items to be displayed are then selected with functional `filter` function checking whether the item matches the filter. +Filters in Kontent.ai are implemented using taxonomies. Filtering examples can be found in `src/Components/BrewerStoreContainer.tsx` or `src/Components/CoffeeStoreContainer.tsx`. Firstly, the taxonomies groups that contain possible values for filters are loaded in `useEffect` blocks. Selected values for filtering are stored in the `filter` variable. Items to be displayed are then selected with the functional `filter` function checking whether the item matches the filter. ```tsx interface FilterType { [index: string]: string[]; - filterVariable1: string[]; - filterVariable2: string[]; + processings: string[]; + productStatuses: string[]; } const Container: React.FC = () => { - const [filterVariable1, setFilterVariable1] = useState([]); - const [filterVariable2, setFilterVariable2] = useState([]); + const [processings, setProcessings] = useState([]); + const [productStatuses, setProductStatuses] = useState([]); const [filter, setFilter] = useState({ - filterVariable1: [], - filterVariable2: [], + processings: [], + productStatuses: [], }); useEffect(() => { - Client.taxonomy('filter_variable_1') + Client.taxonomy('processings') .toPromise() - .then((response) => {setFilterVariable1(response.data.taxonomy.terms);}); + .then((response) => {setProcessings(response.data.taxonomy.terms);}); }, []); useEffect(() => { - Client.taxonomy('filter_variable_2') + Client.taxonomy('product_status') .toPromise() - .then((response) => {setFilterVariable2(response.data.taxonomy.terms);}); + .then((response) => {setProductStatuses(response.data.taxonomy.terms);}); }, []); const matches = (coffee: Coffee): boolean => - matchesTaxonomy(coffee, filter.processings, 'filterVariable1') && - matchesTaxonomy(coffee, filter.productStatuses, 'filterVariable2'); + matchesTaxonomy(coffee, filter.processings, 'processings') && + matchesTaxonomy(coffee, filter.productStatuses, 'productStatuses'); // To see how matchesTaxonomy can work see src/Utilities/CheckboxFilter const toggleFilter = (filterName: string, filterValue: string): void => { @@ -179,7 +174,7 @@ const Container: React.FC = () => { ... toggleFilter('filterVariable1', event.target.id), + onChange: (event) => toggleFilter('processings', event.target.id), /> ... { } ``` -### Localization +## Localization -In Kontent each language is identified by codename, in case of this project it is `en-US` and `es-ES`. +In Kontent each language is identified by codename, in case of this project, it is `en-US` and `es-ES`. -#### Resoure strings +### Resoure strings -Not every text of the application must be stored in Kontent.ai. Some strings, such as button texts, navigation texts, and so on, can be stored directly in the application. For those texts we use [React-intl](https://formatjs.io/docs/getting-started/installation/). For every language, there is a JSON file in `src/Localization` folder. +Not every text of the application must be stored in Kontent.ai. Some strings, such as button texts, navigation texts, and so on, can be stored directly in the application. For those texts [React-intl](https://formatjs.io/docs/getting-started/installation/) is used. For every language, there is a JSON file in `src/Localization` folder. > `React-intl` can not parse nested JSON objects and therefore the format of files is `key:value`. To load all files from `src/Localization` folder there is a `src/utilities/LocalizationLoader.ts` script. @@ -212,9 +207,9 @@ Not every text of the application must be stored in Kontent.ai. Some strings, su } ``` -#### Language prefixes +### Language prefixes -The language prefix is obtained from URL in the `LocalizedApp.tsx` and then it is propagated via IntlProvider to the whole application. Content language is then adjusted by modifying `Client` with `languageParameter()` method to obtain items in specific language. By default it uses [language fallbacks](https://kontent.ai/learn/tutorials/manage-kontent/projects/set-up-languages/#a-language-fallbacks) set up in the project. +The language prefix is obtained from the URL in the `LocalizedApp.tsx` and then it is propagated via IntlProvider to the whole application. Content language is then adjusted by modifying `Client` with `languageParameter()` method to obtain items in a specific language. By default it uses [language fallbacks](https://kontent.ai/learn/tutorials/manage-kontent/projects/set-up-languages/#a-language-fallbacks) set up in the project. ```typescript const Component: React.FC = () => { @@ -230,14 +225,15 @@ const Component: React.FC = () => { ... ``` -#### Localizable URL slugs -You might want to request items based on the URL slugs. For more information check out [Kontent.ai/learn tutorial](https://kontent.ai/learn/tutorials/develop-apps/get-content/localized-content-items/#a-get-items-by-localized-url-slug). We have provided an example in this application for `src/Pages/About.tsx` page. +### Localizable URL slugs +You might want to request items based on the URL slugs. For more information check out [Kontent.ai/learn tutorial](https://kontent.ai/learn/tutorials/develop-apps/get-content/localized-content-items/#a-get-items-by-localized-url-slug). An example in this application for this is provided in `src/Pages/About.tsx` page. > The showcase is not ideal, because it is using a combination of the language prefix and localizable solution is not ideal. You should try to stick with one of the approaches. Because it is hard to define the behavior for language setting clash i.e. `//articles/`. -### Handling 404 -For the not found resources we use prefixed 404 pages for both languages. As the content in one page should be in one language, this approach might help you to optimize SEO. If language is not set in the URL the application uses the last used language, which is set in cookies. +## Handling 404 + +For the not found resources, prefixed 404 pages are used for both languages. As the content on one page should be in one language, this approach might help you to optimize SEO. If language is not set in the URL the application uses the last used language, which is set in cookies. ## Deployment From 4b6515298b098617bb2d0ca581a9e533e9c0734b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Kir=C3=A1=C4=BE?= <54802833+IvanKiral@users.noreply.github.com> Date: Thu, 23 Jun 2022 11:26:27 +0200 Subject: [PATCH 18/21] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ondřej Chrastina <9218736+Simply007@users.noreply.github.com> --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2015502..09db15d 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,8 @@ This solution fetches data using the [Delivery client](https://github.com/Kentic ```tsx const Component: React.FC = () => { - const [data, setData] = useState([] : DTOComponentProps); + const [data, setData] = useState([]); + useEffect(() => { const query = Client.items() From 414bc0719770af420fb47ca68475f2bfa7da9b1e Mon Sep 17 00:00:00 2001 From: Ivan Kiral Date: Thu, 23 Jun 2022 11:32:21 +0200 Subject: [PATCH 19/21] Update readme to resolve nitpicks --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 09db15d..0dafbcf 100644 --- a/README.md +++ b/README.md @@ -111,9 +111,8 @@ const Component: React.FC = () => { .type(projectModel.contentTypes.generatedDTO.codename) ... - const items : GeneratedDTO[] = query.ToPromise() - .then(data => data.items() - .then(items => setData(items)); + query.ToPromise() + .then(data => setData(data.items())); }, []); return ( @@ -191,7 +190,7 @@ const Container: React.FC = () => { In Kontent each language is identified by codename, in case of this project, it is `en-US` and `es-ES`. -### Resoure strings +### Resource strings Not every text of the application must be stored in Kontent.ai. Some strings, such as button texts, navigation texts, and so on, can be stored directly in the application. For those texts [React-intl](https://formatjs.io/docs/getting-started/installation/) is used. For every language, there is a JSON file in `src/Localization` folder. From 91c3c7568981afce05cda3f9c63a91cdd3d883c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Kir=C3=A1=C4=BE?= <54802833+IvanKiral@users.noreply.github.com> Date: Mon, 27 Jun 2022 10:19:53 +0200 Subject: [PATCH 20/21] Change function to property in readme example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ondřej Chrastina <9218736+Simply007@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0dafbcf..85f89c1 100644 --- a/README.md +++ b/README.md @@ -112,7 +112,7 @@ const Component: React.FC = () => { ... query.ToPromise() - .then(data => setData(data.items())); + .then(data => setData(data.items)); }, []); return ( From 10eb94ad2d1ac591c4aec69460919108cda2238b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Chrastina?= <9218736+Simply007@users.noreply.github.com> Date: Mon, 27 Jun 2022 10:48:20 +0200 Subject: [PATCH 21/21] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 85f89c1..72afe04 100644 --- a/README.md +++ b/README.md @@ -196,7 +196,7 @@ Not every text of the application must be stored in Kontent.ai. Some strings, su > `React-intl` can not parse nested JSON objects and therefore the format of files is `key:value`. To load all files from `src/Localization` folder there is a `src/utilities/LocalizationLoader.ts` script. -```json +```jsonc // en-US.json { "LatestArticles.title": "Latest articles",