@treely/strapi-slices 5.11.2 → 5.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ContextProvider/ContextProvider.d.ts +1 -2
- package/dist/constants/strapi.d.ts +1 -0
- package/dist/index.d.ts +6 -3
- package/dist/integrations/strapi/getAllSlugsFromStrapi.d.ts +10 -0
- package/dist/integrations/strapi/getStaticPathsFromStrapi.d.ts +1 -0
- package/dist/integrations/strapi/getStaticPropsFromStrapi.d.ts +1 -0
- package/dist/integrations/strapi/getStrapiCollectionType.d.ts +10 -0
- package/dist/integrations/strapi/getStrapiSingleType.d.ts +8 -0
- package/dist/models/Locale.d.ts +3 -1
- package/dist/models/LocalizedEntity.d.ts +7 -0
- package/dist/models/strapi/StrapiGlobal.d.ts +2 -0
- package/dist/strapi-slices.cjs.development.js +207 -35
- package/dist/strapi-slices.cjs.development.js.map +1 -1
- package/dist/strapi-slices.cjs.production.min.js +1 -1
- package/dist/strapi-slices.cjs.production.min.js.map +1 -1
- package/dist/strapi-slices.esm.js +207 -38
- package/dist/strapi-slices.esm.js.map +1 -1
- package/dist/utils/getMessages.d.ts +142 -0
- package/package.json +1 -1
- package/src/components/ContextProvider/ContextProvider.tsx +3 -5
- package/src/components/MinimalProviders/MinimalProviders.tsx +2 -8
- package/src/components/portfolio/SmallCheckout/SmallCheckout.tsx +33 -24
- package/src/constants/strapi.ts +2 -0
- package/src/index.tsx +8 -2
- package/src/integrations/strapi/getAllSlugsFromStrapi.test.ts +33 -0
- package/src/integrations/strapi/getAllSlugsFromStrapi.ts +50 -0
- package/src/integrations/strapi/getPortfolioProjects.test.ts +24 -0
- package/src/integrations/strapi/getPortfolioProjects.ts +25 -5
- package/src/integrations/strapi/getStaticPathsFromStrapi.ts +1 -0
- package/src/integrations/strapi/getStaticPropsFromStrapi.ts +1 -0
- package/src/integrations/strapi/getStrapiCollectionType.test.ts +65 -0
- package/src/integrations/strapi/getStrapiCollectionType.ts +61 -0
- package/src/integrations/strapi/getStrapiSingleType.test.ts +53 -0
- package/src/integrations/strapi/getStrapiSingleType.ts +50 -0
- package/src/models/Locale.ts +3 -1
- package/src/models/LocalizedEntity.ts +9 -0
- package/src/models/strapi/StrapiGlobal.ts +2 -0
- package/src/test/strapiMocks/minimalGlobalData.ts +1 -0
- package/src/utils/getMessages.ts +18 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
declare const getMessages: (locale: string) => {
|
|
2
|
+
'unit.formatter.tonsCo2': string;
|
|
3
|
+
'unit.formatter.tonsCo2PerYear': string;
|
|
4
|
+
'sections.timeline.backgroundShapes': string;
|
|
5
|
+
'sections.timeline.showMoreButton': string;
|
|
6
|
+
'sections.textCarousel.moveRight': string;
|
|
7
|
+
'sections.textCarousel.moveLeft': string;
|
|
8
|
+
'sections.shopCheckout.intro.price': string;
|
|
9
|
+
'sections.shopCheckout.contributionValue.label.EUR': string;
|
|
10
|
+
'sections.shopCheckout.contributionValue.label.CHF': string;
|
|
11
|
+
'sections.shopCheckout.contributionValue.unit.EUR': string;
|
|
12
|
+
'sections.shopCheckout.contributionValue.unit.CHF': string;
|
|
13
|
+
'sections.shopCheckout.contributionValue.validation.empty': string;
|
|
14
|
+
'sections.shopCheckout.contributionValue.validation.tooLow.EUR': string;
|
|
15
|
+
'sections.shopCheckout.contributionValue.validation.tooLow.CHF': string;
|
|
16
|
+
'sections.shopCheckout.contributionValue.validation.tooHigh': string;
|
|
17
|
+
'sections.shopCheckout.summary.kg': string;
|
|
18
|
+
'sections.shopCheckout.summary.price': string;
|
|
19
|
+
'sections.shopCheckout.summary.price.taxNotIncluded': string;
|
|
20
|
+
'sections.shopCheckout.summary.price.taxIncluded': string;
|
|
21
|
+
'sections.shopCheckout.submit': string;
|
|
22
|
+
'sections.projectsMap.link.text': string;
|
|
23
|
+
'sections.projectFacts.projectInfo.value': string;
|
|
24
|
+
'projects.projectFacts.properties.area': string;
|
|
25
|
+
'sections.glossary.copyButtonLabel': string;
|
|
26
|
+
'sections.glossary.copySuccessMessage': string;
|
|
27
|
+
'sections.glossary.copyFailureMessage': string;
|
|
28
|
+
'sections.customerQuoteCard.more': string;
|
|
29
|
+
'sections.customerCard.more': string;
|
|
30
|
+
'sections.cta.backgroundShapesDark': string;
|
|
31
|
+
'sections.cta.backgroundShapesLight': string;
|
|
32
|
+
'sections.comparison.backgroundShapes': string;
|
|
33
|
+
'portfolio.smallCheckout.price.taxNotIncluded': string;
|
|
34
|
+
'portfolio.smallCheckout.price.taxIncluded': string;
|
|
35
|
+
'portfolio.smallCheckout.contributionValueCurrency.label.CHF': string;
|
|
36
|
+
'portfolio.smallCheckout.contributionValueCurrency.label.EUR': string;
|
|
37
|
+
'portfolio.smallCheckout.contributionValueCurrency.unit.EUR': string;
|
|
38
|
+
'portfolio.smallCheckout.contributionValueCurrency.unit.CHF': string;
|
|
39
|
+
'portfolio.smallCheckout.contributionValueCurrency.validation.tooLow.CHF': string;
|
|
40
|
+
'portfolio.smallCheckout.contributionValueCurrency.validation.tooLow.EUR': string;
|
|
41
|
+
'portfolio.smallCheckout.contributionValueCurrency.validation.empty': string;
|
|
42
|
+
'portfolio.smallCheckout.contributionValueCurrency.validation.tooHigh': string;
|
|
43
|
+
'portfolio.smallCheckout.contributionValueKgs.label': string;
|
|
44
|
+
'portfolio.smallCheckout.submitButton': string;
|
|
45
|
+
'portfolio.smallCheckout.cta.title': string;
|
|
46
|
+
'portfolio.smallCheckout.cta.subTitle': string;
|
|
47
|
+
'portfolio.smallCheckout.cta.button': string;
|
|
48
|
+
'features.projectInfo.projectInfo.value': string;
|
|
49
|
+
'features.projectInfo.properties.area': string;
|
|
50
|
+
'features.projectInfo.properties.location': string;
|
|
51
|
+
'features.projectInfo.properties.start': string;
|
|
52
|
+
'features.projectInfo.properties.timeSpan': string;
|
|
53
|
+
'features.projectInfo.properties.projectType': string;
|
|
54
|
+
'features.projectInfo.properties.projectDeveloper': string;
|
|
55
|
+
'features.projectInfo.properties.verificationStandard.label': string;
|
|
56
|
+
'features.projectInfo.properties.verificationStandard.value.SilvaconsultFCSISO14': string;
|
|
57
|
+
'features.projectInfo.properties.verificationStandard.value.MfKWCH': string;
|
|
58
|
+
'features.projectInfo.properties.forecastedAmountYear.label': string;
|
|
59
|
+
'features.projectInfo.properties.riskBuffer': string;
|
|
60
|
+
'features.projectInfo.properties.year': string;
|
|
61
|
+
'components.portfolioProjectCard.text.yes': string;
|
|
62
|
+
'components.portfolioProjectCard.text.some': string;
|
|
63
|
+
'components.portfolioProjectCard.text.no': string;
|
|
64
|
+
'components.portfolioProjectCard.text.notYet': string;
|
|
65
|
+
'features.portfolio.documentsDownloadList.projectDocuments': string;
|
|
66
|
+
'features.portfolio.documentsDownloadList.downloadDocument': string;
|
|
67
|
+
'components.creditsAvailableBadge.text.yes': string;
|
|
68
|
+
'components.creditsAvailableBadge.text.some': string;
|
|
69
|
+
'components.creditsAvailableBadge.text.no': string;
|
|
70
|
+
'components.creditsAvailableBadge.text.notYet': string;
|
|
71
|
+
} | {
|
|
72
|
+
'unit.formatter.tonsCo2': string;
|
|
73
|
+
'unit.formatter.tonsCo2PerYear': string;
|
|
74
|
+
'sections.timeline.backgroundShapes': string;
|
|
75
|
+
'sections.timeline.showMoreButton': string;
|
|
76
|
+
'sections.textCarousel.moveRight': string;
|
|
77
|
+
'sections.textCarousel.moveLeft': string;
|
|
78
|
+
'sections.shopCheckout.intro.price': string;
|
|
79
|
+
'sections.shopCheckout.contributionValue.label.EUR': string;
|
|
80
|
+
'sections.shopCheckout.contributionValue.label.CHF': string;
|
|
81
|
+
'sections.shopCheckout.contributionValue.unit.EUR': string;
|
|
82
|
+
'sections.shopCheckout.contributionValue.unit.CHF': string;
|
|
83
|
+
'sections.shopCheckout.contributionValue.validation.empty': string;
|
|
84
|
+
'sections.shopCheckout.contributionValue.validation.tooLow.EUR': string;
|
|
85
|
+
'sections.shopCheckout.contributionValue.validation.tooLow.CHF': string;
|
|
86
|
+
'sections.shopCheckout.contributionValue.validation.tooHigh': string;
|
|
87
|
+
'sections.shopCheckout.summary.kg': string;
|
|
88
|
+
'sections.shopCheckout.summary.price': string;
|
|
89
|
+
'sections.shopCheckout.summary.price.taxNotIncluded': string;
|
|
90
|
+
'sections.shopCheckout.summary.price.taxIncluded': string;
|
|
91
|
+
'sections.shopCheckout.submit': string;
|
|
92
|
+
'sections.projectsMap.link.text': string;
|
|
93
|
+
'sections.projectFacts.projectInfo.value': string;
|
|
94
|
+
'projects.projectFacts.properties.area': string;
|
|
95
|
+
'sections.glossary.copyButtonLabel': string;
|
|
96
|
+
'sections.glossary.copySuccessMessage': string;
|
|
97
|
+
'sections.glossary.copyFailureMessage': string;
|
|
98
|
+
'sections.customerQuoteCard.more': string;
|
|
99
|
+
'sections.customerCard.more': string;
|
|
100
|
+
'sections.cta.backgroundShapes': string;
|
|
101
|
+
'sections.cta.backgroundShapesLight': string;
|
|
102
|
+
'sections.comparison.backgroundShapes': string;
|
|
103
|
+
'portfolio.smallCheckout.price.taxNotIncluded': string;
|
|
104
|
+
'portfolio.smallCheckout.price.taxIncluded': string;
|
|
105
|
+
'portfolio.smallCheckout.contributionValueCurrency.label.CHF': string;
|
|
106
|
+
'portfolio.smallCheckout.contributionValueCurrency.label.EUR': string;
|
|
107
|
+
'portfolio.smallCheckout.contributionValueCurrency.unit.EUR': string;
|
|
108
|
+
'portfolio.smallCheckout.contributionValueCurrency.unit.CHF': string;
|
|
109
|
+
'portfolio.smallCheckout.contributionValueCurrency.validation.tooLow.CHF': string;
|
|
110
|
+
'portfolio.smallCheckout.contributionValueCurrency.validation.tooLow.EUR': string;
|
|
111
|
+
'portfolio.smallCheckout.contributionValueCurrency.validation.empty': string;
|
|
112
|
+
'portfolio.smallCheckout.contributionValueCurrency.validation.tooHigh': string;
|
|
113
|
+
'portfolio.smallCheckout.contributionValueKgs.label': string;
|
|
114
|
+
'portfolio.smallCheckout.submitButton': string;
|
|
115
|
+
'portfolio.smallCheckout.cta.title': string;
|
|
116
|
+
'portfolio.smallCheckout.cta.subTitle': string;
|
|
117
|
+
'portfolio.smallCheckout.cta.button': string;
|
|
118
|
+
'features.projectInfo.projectInfo.value': string;
|
|
119
|
+
'features.projectInfo.properties.area': string;
|
|
120
|
+
'features.projectInfo.properties.location': string;
|
|
121
|
+
'features.projectInfo.properties.start': string;
|
|
122
|
+
'features.projectInfo.properties.timeSpan': string;
|
|
123
|
+
'features.projectInfo.properties.projectType': string;
|
|
124
|
+
'features.projectInfo.properties.projectDeveloper': string;
|
|
125
|
+
'features.projectInfo.properties.verificationStandard.label': string;
|
|
126
|
+
'features.projectInfo.properties.verificationStandard.value.SilvaconsultFCSISO14': string;
|
|
127
|
+
'features.projectInfo.properties.verificationStandard.value.MfKWCH': string;
|
|
128
|
+
'features.projectInfo.properties.forecastedAmountYear.label': string;
|
|
129
|
+
'features.projectInfo.properties.riskBuffer': string;
|
|
130
|
+
'features.projectInfo.properties.year': string;
|
|
131
|
+
'components.portfolioProjectCard.text.yes': string;
|
|
132
|
+
'components.portfolioProjectCard.text.some': string;
|
|
133
|
+
'components.portfolioProjectCard.text.no': string;
|
|
134
|
+
'components.portfolioProjectCard.text.notYet': string;
|
|
135
|
+
'features.portfolio.documentsDownloadList.projectDocuments': string;
|
|
136
|
+
'features.portfolio.documentsDownloadList.downloadDocument': string;
|
|
137
|
+
'components.creditsAvailableBadge.text.yes': string;
|
|
138
|
+
'components.creditsAvailableBadge.text.some': string;
|
|
139
|
+
'components.creditsAvailableBadge.text.no': string;
|
|
140
|
+
'components.creditsAvailableBadge.text.notYet': string;
|
|
141
|
+
};
|
|
142
|
+
export default getMessages;
|
package/package.json
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import React, { createContext } from 'react';
|
|
2
2
|
import { createIntl, createIntlCache } from 'react-intl';
|
|
3
|
-
import rootMessagesDe from '../../rootMessages.de';
|
|
4
|
-
import rootMessagesEn from '../../rootMessages.en';
|
|
5
|
-
import Locale from '../../models/Locale';
|
|
6
3
|
import { Global } from '@emotion/react';
|
|
7
4
|
import { GLOBAL_STYLE } from '../../constants/globalStyle';
|
|
5
|
+
import getMessages from '../../utils/getMessages';
|
|
8
6
|
|
|
9
7
|
const cache = createIntlCache();
|
|
10
8
|
|
|
@@ -12,7 +10,7 @@ const intlFactory = (locale: string) =>
|
|
|
12
10
|
createIntl(
|
|
13
11
|
{
|
|
14
12
|
locale,
|
|
15
|
-
messages:
|
|
13
|
+
messages: getMessages(locale),
|
|
16
14
|
},
|
|
17
15
|
cache
|
|
18
16
|
);
|
|
@@ -21,7 +19,7 @@ export const IntlContext = createContext(intlFactory('en'));
|
|
|
21
19
|
|
|
22
20
|
export interface ContextProviderProps {
|
|
23
21
|
children: React.ReactNode;
|
|
24
|
-
locale:
|
|
22
|
+
locale: string;
|
|
25
23
|
}
|
|
26
24
|
|
|
27
25
|
export const ContextProvider: React.FC<ContextProviderProps> = ({
|
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { FONT_CUSTOMIZATIONS } from '../../constants/fontCustomizations';
|
|
3
|
-
import rootMessagesDe from '../../rootMessages.de';
|
|
4
|
-
import rootMessagesEn from '../../rootMessages.en';
|
|
5
3
|
import { BoemlyThemeProvider } from 'boemly';
|
|
6
4
|
import { IntlProvider } from 'react-intl';
|
|
7
|
-
|
|
8
|
-
const messages = {
|
|
9
|
-
en: rootMessagesEn,
|
|
10
|
-
de: rootMessagesDe,
|
|
11
|
-
};
|
|
5
|
+
import getMessages from '../../utils/getMessages';
|
|
12
6
|
|
|
13
7
|
interface MinimalProvidersProps {
|
|
14
8
|
locale: string;
|
|
@@ -16,7 +10,7 @@ interface MinimalProvidersProps {
|
|
|
16
10
|
}
|
|
17
11
|
|
|
18
12
|
const MinimalProviders = ({ children, locale }: MinimalProvidersProps) => (
|
|
19
|
-
<IntlProvider messages={
|
|
13
|
+
<IntlProvider messages={getMessages(locale)} locale={locale}>
|
|
20
14
|
<BoemlyThemeProvider fonts={FONT_CUSTOMIZATIONS}>
|
|
21
15
|
{children}
|
|
22
16
|
</BoemlyThemeProvider>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useCallback, useContext
|
|
1
|
+
import React, { useCallback, useContext } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
BoemlyFormControl,
|
|
4
4
|
Box,
|
|
@@ -29,6 +29,17 @@ import { CDN_URI, FPM_API_URI } from '../../../constants/api';
|
|
|
29
29
|
import StrapiLinkButton from '../../StrapiLinkButton';
|
|
30
30
|
import SmallCheckoutForm from '../../../models/forms/SmallCheckoutForm';
|
|
31
31
|
|
|
32
|
+
const calculateTaxIncludedValue = (
|
|
33
|
+
values: SmallCheckoutForm,
|
|
34
|
+
taxInPercent: number
|
|
35
|
+
) => {
|
|
36
|
+
const value = parseInt(values.contributionValueCurrency);
|
|
37
|
+
|
|
38
|
+
if (isNaN(value)) return 0;
|
|
39
|
+
|
|
40
|
+
return value + value * (taxInPercent / 100);
|
|
41
|
+
};
|
|
42
|
+
|
|
32
43
|
export interface SmallCheckoutProps {
|
|
33
44
|
batchId: string;
|
|
34
45
|
pricePerKg: number;
|
|
@@ -55,9 +66,6 @@ const SmallCheckout = ({
|
|
|
55
66
|
}: SmallCheckoutProps) => {
|
|
56
67
|
const { formatNumber, formatMessage, locale } = useContext(IntlContext);
|
|
57
68
|
const { push } = useRouter();
|
|
58
|
-
const [contributionValue, setContributionValue] = useState<number>(
|
|
59
|
-
initialContributionValue
|
|
60
|
-
);
|
|
61
69
|
|
|
62
70
|
const validateForm = useCallback(
|
|
63
71
|
(values: SmallCheckoutForm) => {
|
|
@@ -79,7 +87,7 @@ const SmallCheckout = ({
|
|
|
79
87
|
|
|
80
88
|
return errors;
|
|
81
89
|
},
|
|
82
|
-
[locale]
|
|
90
|
+
[currency, locale]
|
|
83
91
|
);
|
|
84
92
|
|
|
85
93
|
const onSubmit = async ({ contributionValueCurrency }: SmallCheckoutForm) => {
|
|
@@ -148,6 +156,7 @@ const SmallCheckout = ({
|
|
|
148
156
|
touched,
|
|
149
157
|
handleSubmit,
|
|
150
158
|
setValues,
|
|
159
|
+
values,
|
|
151
160
|
}: FormikProps<SmallCheckoutForm>) => (
|
|
152
161
|
<Form onSubmit={handleSubmit}>
|
|
153
162
|
<Flex gap="4">
|
|
@@ -162,7 +171,6 @@ const SmallCheckout = ({
|
|
|
162
171
|
value: field.value || '',
|
|
163
172
|
onChange: (e) => {
|
|
164
173
|
const value = e.target.valueAsNumber;
|
|
165
|
-
setContributionValue(value);
|
|
166
174
|
|
|
167
175
|
setValues({
|
|
168
176
|
contributionValueCurrency: value.toString(),
|
|
@@ -231,24 +239,25 @@ const SmallCheckout = ({
|
|
|
231
239
|
</Field>
|
|
232
240
|
</Box>
|
|
233
241
|
</Flex>
|
|
234
|
-
{
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
{
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
242
|
+
{values.contributionValueCurrency &&
|
|
243
|
+
taxInPercent &&
|
|
244
|
+
taxInPercent > 0 && (
|
|
245
|
+
<Text size="smLowNormal" mt="2">
|
|
246
|
+
{formatMessage(
|
|
247
|
+
{ id: 'portfolio.smallCheckout.price.taxIncluded' },
|
|
248
|
+
{
|
|
249
|
+
number: formatNumber(
|
|
250
|
+
calculateTaxIncludedValue(values, taxInPercent),
|
|
251
|
+
{
|
|
252
|
+
style: 'currency',
|
|
253
|
+
currency,
|
|
254
|
+
maximumFractionDigits: 2,
|
|
255
|
+
}
|
|
256
|
+
),
|
|
257
|
+
}
|
|
258
|
+
)}
|
|
259
|
+
</Text>
|
|
260
|
+
)}
|
|
252
261
|
|
|
253
262
|
<Spacer height="4" />
|
|
254
263
|
|
package/src/constants/strapi.ts
CHANGED
package/src/index.tsx
CHANGED
|
@@ -31,8 +31,8 @@ import StrapiPageProps from './models/strapi/StrapiPageProps';
|
|
|
31
31
|
import StrapiPortfolio from './models/strapi/StrapiPortfolio';
|
|
32
32
|
import StrapiPortfolioCard from './models/strapi/StrapiPortfolioCard';
|
|
33
33
|
import StrapiProject from './models/strapi/StrapiProject';
|
|
34
|
-
import StrapiProjectProps from './models/strapi/StrapiProjectProps';
|
|
35
34
|
import StrapiProjectCard from './models/strapi/StrapiProjectCard';
|
|
35
|
+
import StrapiProjectProps from './models/strapi/StrapiProjectProps';
|
|
36
36
|
import StrapiQuoteCard from './models/strapi/StrapiQuoteCard';
|
|
37
37
|
import StrapiShapesCard from './models/strapi/StrapiShapesCard';
|
|
38
38
|
import StrapiTextCardWithIcons from './models/strapi/StrapiTextCardWithIcons';
|
|
@@ -45,9 +45,12 @@ import PageMetadata from './models/PageMetadata';
|
|
|
45
45
|
import PageProps from './models/PageProps';
|
|
46
46
|
import PortfolioProject from './models/PortfolioProject';
|
|
47
47
|
|
|
48
|
+
import getAllSlugsFromStrapi from './integrations/strapi/getAllSlugsFromStrapi';
|
|
48
49
|
import getPortfolioProjects from './integrations/strapi/getPortfolioProjects';
|
|
49
50
|
import getStaticPathsFromStrapi from './integrations/strapi/getStaticPathsFromStrapi';
|
|
50
51
|
import getStaticPropsFromStrapi from './integrations/strapi/getStaticPropsFromStrapi';
|
|
52
|
+
import getStrapiCollectionType from './integrations/strapi/getStrapiCollectionType';
|
|
53
|
+
import getStrapiSingleType from './integrations/strapi/getStrapiSingleType';
|
|
51
54
|
|
|
52
55
|
import mergeGlobalAndStrapiBlogPostData from './utils/mergeGlobalAndStrapiBlogPostData';
|
|
53
56
|
import mergeGlobalAndStrapiCustomerStoryData from './utils/mergeGlobalAndStrapiCustomerStoryData';
|
|
@@ -70,9 +73,12 @@ export {
|
|
|
70
73
|
strapiMediaUrl,
|
|
71
74
|
|
|
72
75
|
// Integrations
|
|
76
|
+
getAllSlugsFromStrapi,
|
|
73
77
|
getPortfolioProjects,
|
|
74
78
|
getStaticPathsFromStrapi,
|
|
75
79
|
getStaticPropsFromStrapi,
|
|
80
|
+
getStrapiCollectionType,
|
|
81
|
+
getStrapiSingleType,
|
|
76
82
|
};
|
|
77
83
|
|
|
78
84
|
export type {
|
|
@@ -110,8 +116,8 @@ export type {
|
|
|
110
116
|
StrapiPortfolio,
|
|
111
117
|
StrapiPortfolioCard,
|
|
112
118
|
StrapiProject,
|
|
113
|
-
StrapiProjectProps,
|
|
114
119
|
StrapiProjectCard,
|
|
120
|
+
StrapiProjectProps,
|
|
115
121
|
StrapiQuoteCard,
|
|
116
122
|
StrapiShapesCard,
|
|
117
123
|
StrapiTextCardWithIcons,
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import MockAxios from 'jest-mock-axios';
|
|
2
|
+
import getAllSlugsFromStrapi from './getAllSlugsFromStrapi';
|
|
3
|
+
import StrapiPage from '../../models/strapi/StrapiPage';
|
|
4
|
+
import { strapiPageMock } from '../../test/strapiMocks/strapiPage';
|
|
5
|
+
|
|
6
|
+
describe('The getAllSlugsFromStrapi function', () => {
|
|
7
|
+
afterEach(() => {
|
|
8
|
+
MockAxios.reset();
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
it('returns all slugs and creates a fallback for locales that dont have a translation', async () => {
|
|
12
|
+
const slugsPromise = getAllSlugsFromStrapi<StrapiPage>('/api/pages', [
|
|
13
|
+
'en',
|
|
14
|
+
'de',
|
|
15
|
+
'hu',
|
|
16
|
+
]);
|
|
17
|
+
|
|
18
|
+
// This page is avaliable in 'de' and 'en'
|
|
19
|
+
MockAxios.mockResponseFor(
|
|
20
|
+
{ url: '/api/pages' },
|
|
21
|
+
{ data: { data: [strapiPageMock] } }
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
const slugs = await slugsPromise;
|
|
25
|
+
|
|
26
|
+
expect(slugs).toStrictEqual([
|
|
27
|
+
{ locale: 'en', slug: strapiPageMock.attributes.slug },
|
|
28
|
+
{ locale: 'de', slug: strapiPageMock.attributes.slug },
|
|
29
|
+
// Fallback for 'hu' gets created
|
|
30
|
+
{ locale: 'hu', slug: strapiPageMock.attributes.slug },
|
|
31
|
+
]);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import strapiClient from './strapiClient';
|
|
2
|
+
import {
|
|
3
|
+
STRAPI_DEFAULT_PAGE_SIZE,
|
|
4
|
+
STRAPI_FALLBACK_LOCALE,
|
|
5
|
+
} from '../../constants/strapi';
|
|
6
|
+
import IStrapiResponse from '../../models/strapi/IStrapiResponse';
|
|
7
|
+
import IStrapiData from '../../models/strapi/IStrapiData';
|
|
8
|
+
import LocalizedEntity from '../../models/LocalizedEntity';
|
|
9
|
+
|
|
10
|
+
interface Options {
|
|
11
|
+
filters?: Record<string, any>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
type Slug = { slug: string; locale: string };
|
|
15
|
+
|
|
16
|
+
const getAllSlugsFromStrapi = async <T extends LocalizedEntity<'slug'>>(
|
|
17
|
+
path: string,
|
|
18
|
+
locales: string[],
|
|
19
|
+
{ filters = {} }: Options = { filters: {} }
|
|
20
|
+
): Promise<Slug[]> => {
|
|
21
|
+
const params: Record<string, any> = {
|
|
22
|
+
locale: 'all',
|
|
23
|
+
'pagination[pageSize]': STRAPI_DEFAULT_PAGE_SIZE,
|
|
24
|
+
filters,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const { data } = await strapiClient.get<IStrapiResponse<IStrapiData<T>[]>>(
|
|
28
|
+
path,
|
|
29
|
+
{ params }
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
const slugs: Slug[] = data.data.map((page) => ({
|
|
33
|
+
slug: page.attributes.slug,
|
|
34
|
+
locale: page.attributes.locale,
|
|
35
|
+
}));
|
|
36
|
+
|
|
37
|
+
const fallBackSlugs: Slug[] = locales.flatMap((locale) =>
|
|
38
|
+
slugs
|
|
39
|
+
.filter((slug) => slug.locale === STRAPI_FALLBACK_LOCALE)
|
|
40
|
+
.map((slug) => ({ ...slug, locale }))
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
const nonFallbackSlugs = slugs.filter(
|
|
44
|
+
(p) => p.locale !== STRAPI_FALLBACK_LOCALE
|
|
45
|
+
);
|
|
46
|
+
|
|
47
|
+
return [...fallBackSlugs, ...nonFallbackSlugs];
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export default getAllSlugsFromStrapi;
|
|
@@ -19,6 +19,30 @@ describe('The getPortfolioProjects function', () => {
|
|
|
19
19
|
{ url: '/projects' },
|
|
20
20
|
{ data: { data: [strapiProjectMock] } }
|
|
21
21
|
);
|
|
22
|
+
MockAxios.mockResponseFor({ url: '/projects' }, { data: { data: [] } });
|
|
23
|
+
|
|
24
|
+
const projects = await projectsPromise;
|
|
25
|
+
|
|
26
|
+
expect(projects.length).toBe(1);
|
|
27
|
+
expect(projects[0]).toStrictEqual({
|
|
28
|
+
...fpmProjectMock,
|
|
29
|
+
slug: strapiProjectMock.attributes.slug,
|
|
30
|
+
creditsAvailable: strapiProjectMock.attributes.creditsAvailable,
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('returns the FPM project in english if no localized version is available', async () => {
|
|
35
|
+
const projectsPromise = getPortfolioProjects('de');
|
|
36
|
+
|
|
37
|
+
MockAxios.mockResponseFor(
|
|
38
|
+
{ url: '/public/projects' },
|
|
39
|
+
{ data: [fpmProjectMock] }
|
|
40
|
+
);
|
|
41
|
+
MockAxios.mockResponseFor({ url: '/projects' }, { data: { data: [] } });
|
|
42
|
+
MockAxios.mockResponseFor(
|
|
43
|
+
{ url: '/projects' },
|
|
44
|
+
{ data: { data: [strapiProjectMock] } }
|
|
45
|
+
);
|
|
22
46
|
|
|
23
47
|
const projects = await projectsPromise;
|
|
24
48
|
|
|
@@ -9,6 +9,8 @@ import FPMProject from '../../models/fpm/FPMProject';
|
|
|
9
9
|
import fpmClient from '../fpmClient';
|
|
10
10
|
import strapiClient from './strapiClient';
|
|
11
11
|
|
|
12
|
+
const FALLBACK_LOCALE = 'en';
|
|
13
|
+
|
|
12
14
|
const getPortfolioProjects = async (
|
|
13
15
|
locale: string = 'en',
|
|
14
16
|
preview: boolean = false
|
|
@@ -23,7 +25,11 @@ const getPortfolioProjects = async (
|
|
|
23
25
|
params.publicationState = 'preview';
|
|
24
26
|
}
|
|
25
27
|
|
|
26
|
-
const [
|
|
28
|
+
const [
|
|
29
|
+
{ data: fpmProjects },
|
|
30
|
+
{ data: strapiProjectsLocalized },
|
|
31
|
+
{ data: strapiProjectsEnglish },
|
|
32
|
+
] = await Promise.all([
|
|
27
33
|
fpmClient.get<FPMProject[]>('/public/projects'),
|
|
28
34
|
strapiClient.get<IStrapiResponse<IStrapiData<StrapiProject>[]>>(
|
|
29
35
|
'/projects',
|
|
@@ -31,13 +37,27 @@ const getPortfolioProjects = async (
|
|
|
31
37
|
params,
|
|
32
38
|
}
|
|
33
39
|
),
|
|
40
|
+
strapiClient.get<IStrapiResponse<IStrapiData<StrapiProject>[]>>(
|
|
41
|
+
'/projects',
|
|
42
|
+
{
|
|
43
|
+
params: { ...params, locale: FALLBACK_LOCALE },
|
|
44
|
+
}
|
|
45
|
+
),
|
|
34
46
|
]);
|
|
35
47
|
|
|
48
|
+
const strapiProjects = new Map<string, IStrapiData<StrapiProject>>();
|
|
49
|
+
|
|
50
|
+
for (const project of [
|
|
51
|
+
...strapiProjectsEnglish.data,
|
|
52
|
+
...strapiProjectsLocalized.data,
|
|
53
|
+
]) {
|
|
54
|
+
if (project.attributes.fpmProjectId) {
|
|
55
|
+
strapiProjects.set(project.attributes.fpmProjectId, project);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
36
59
|
return fpmProjects.map((fpmProject: FPMProject) => {
|
|
37
|
-
const strapiProject = strapiProjects.
|
|
38
|
-
(sp: IStrapiData<StrapiProject>) =>
|
|
39
|
-
sp.attributes.fpmProjectId === fpmProject.id
|
|
40
|
-
);
|
|
60
|
+
const strapiProject = strapiProjects.get(fpmProject.id);
|
|
41
61
|
|
|
42
62
|
const toReturn: PortfolioProject = fpmProject;
|
|
43
63
|
|
|
@@ -9,6 +9,7 @@ interface Options {
|
|
|
9
9
|
filters?: Record<string, any>;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
/** @deprecated Migrate to getStrapiSingleType or getStrapiCollectionType */
|
|
12
13
|
const getStaticPropsFromStrapi = async (
|
|
13
14
|
path: string,
|
|
14
15
|
{ locale = 'en', slug, preview = false, filters = {} }: Options
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import MockAxios from 'jest-mock-axios';
|
|
2
|
+
import getStrapiCollectionType from './getStrapiCollectionType';
|
|
3
|
+
import StrapiPage from '../../models/strapi/StrapiPage';
|
|
4
|
+
import { strapiPageMock } from '../../test/strapiMocks/strapiPage';
|
|
5
|
+
|
|
6
|
+
describe('The getStrapiCollectionType function', () => {
|
|
7
|
+
const germanStrapiPageMock = {
|
|
8
|
+
...strapiPageMock,
|
|
9
|
+
attributes: {
|
|
10
|
+
...strapiPageMock.attributes,
|
|
11
|
+
locale: 'de',
|
|
12
|
+
title: 'Über uns',
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
afterEach(() => {
|
|
17
|
+
MockAxios.reset();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('returns the localized versions if available', async () => {
|
|
21
|
+
const pages = getStrapiCollectionType<StrapiPage, 'slug'>(
|
|
22
|
+
'/api/pages',
|
|
23
|
+
'slug',
|
|
24
|
+
{ locale: 'de' }
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
MockAxios.mockResponseFor(
|
|
28
|
+
{ url: '/api/pages' },
|
|
29
|
+
{ data: { data: [strapiPageMock, germanStrapiPageMock] } }
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
const page = await pages;
|
|
33
|
+
|
|
34
|
+
expect(page).toStrictEqual([
|
|
35
|
+
expect.objectContaining({
|
|
36
|
+
attributes: expect.objectContaining({ title: 'Über uns' }),
|
|
37
|
+
}),
|
|
38
|
+
]);
|
|
39
|
+
|
|
40
|
+
expect(page).toHaveLength(1);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('returns the english versions if no localized version is available', async () => {
|
|
44
|
+
const pages = getStrapiCollectionType<StrapiPage, 'slug'>(
|
|
45
|
+
'/api/pages',
|
|
46
|
+
'slug',
|
|
47
|
+
{ locale: 'de' }
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
MockAxios.mockResponseFor(
|
|
51
|
+
{ url: '/api/pages' },
|
|
52
|
+
{ data: { data: [strapiPageMock] } }
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const page = await pages;
|
|
56
|
+
|
|
57
|
+
expect(page).toStrictEqual([
|
|
58
|
+
expect.objectContaining({
|
|
59
|
+
attributes: expect.objectContaining({ title: 'About us' }),
|
|
60
|
+
}),
|
|
61
|
+
]);
|
|
62
|
+
|
|
63
|
+
expect(page).toHaveLength(1);
|
|
64
|
+
});
|
|
65
|
+
});
|