@websolutespa/bom-mixer-models 1.5.0 → 1.5.2
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/CHANGELOG.md +16 -0
- package/dist/index.d.ts +71 -5
- package/dist/index.js +43 -13
- package/dist/index.mjs +42 -13
- package/package.json +1 -1
- package/src/checkout/checkout.service.ts +43 -43
- package/src/index.ts +1 -0
- package/src/label/label.service.ts +1 -1
- package/src/page/page.service.ts +4 -4
- package/src/route/route.service.ts +4 -4
- package/src/structured_data/structured_data.ts +108 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @websolutespa/bom-mixer-models
|
|
2
2
|
|
|
3
|
+
## 1.5.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Added: StructuredData
|
|
8
|
+
- Updated dependencies
|
|
9
|
+
- @websolutespa/bom-core@0.6.2
|
|
10
|
+
|
|
11
|
+
## 1.5.1
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- Added: defaultMarket, defaultLocale
|
|
16
|
+
- Updated dependencies [dad63747]
|
|
17
|
+
- @websolutespa/bom-core@0.6.1
|
|
18
|
+
|
|
3
19
|
## 1.5.0
|
|
4
20
|
|
|
5
21
|
### Minor Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -301,10 +301,10 @@ declare function getRoutesForTemplates(templates: string[], market?: string, loc
|
|
|
301
301
|
[key: string]: string;
|
|
302
302
|
}>;
|
|
303
303
|
declare function getStaticPathsForSchema(schema: string): Promise<StaticPath[]>;
|
|
304
|
-
declare function getBreadcrumbFromSegments(segments: ICategory[], market
|
|
305
|
-
declare function getRouteLinkTree(market
|
|
306
|
-
declare function newRouteLink(category: ICategory, route
|
|
307
|
-
declare function categoryToRouteLink(routes: IRoute[], categories: ICategory[], category: ICategory, locale
|
|
304
|
+
declare function getBreadcrumbFromSegments(segments: ICategory[], market: string, locale: string): Promise<IRouteLink[]>;
|
|
305
|
+
declare function getRouteLinkTree(market: string, locale: string): Promise<IRouteLink | undefined>;
|
|
306
|
+
declare function newRouteLink(category: ICategory, route: IRoute | undefined, locale: string): IRouteLink;
|
|
307
|
+
declare function categoryToRouteLink(routes: IRoute[], categories: ICategory[], category: ICategory, locale: string): IRouteLink;
|
|
308
308
|
declare function resolveRoute(route: IRoute & {
|
|
309
309
|
splat?: string;
|
|
310
310
|
}): string;
|
|
@@ -337,4 +337,70 @@ type IModelStore = {
|
|
|
337
337
|
[key: string]: IQuerable<IEntity>;
|
|
338
338
|
};
|
|
339
339
|
|
|
340
|
-
|
|
340
|
+
type StructuredDataPerson = {
|
|
341
|
+
'@type': 'Person';
|
|
342
|
+
name: string;
|
|
343
|
+
url: string;
|
|
344
|
+
};
|
|
345
|
+
type StructuredDataPerformingGroup = {
|
|
346
|
+
'@type': 'PerformingGroup';
|
|
347
|
+
name: string;
|
|
348
|
+
};
|
|
349
|
+
type StructuredDataOffer = {
|
|
350
|
+
'@type': 'Offer';
|
|
351
|
+
url: string;
|
|
352
|
+
price: number;
|
|
353
|
+
priceCurrency: string;
|
|
354
|
+
validFrom?: Date | string;
|
|
355
|
+
};
|
|
356
|
+
type StructuredDataAddress = {
|
|
357
|
+
'@type': 'PostalAddress';
|
|
358
|
+
addressCountry?: string;
|
|
359
|
+
addressLocality: string;
|
|
360
|
+
addressRegion?: string;
|
|
361
|
+
postalCode: string;
|
|
362
|
+
streetAddress: string;
|
|
363
|
+
};
|
|
364
|
+
type StructuredDataPlace = {
|
|
365
|
+
'@type': 'Place';
|
|
366
|
+
name: string;
|
|
367
|
+
address: StructuredDataAddress;
|
|
368
|
+
};
|
|
369
|
+
type StructuredDataOrganization = {
|
|
370
|
+
'@type': 'Organization';
|
|
371
|
+
address?: StructuredDataAddress;
|
|
372
|
+
alumni?: StructuredDataPerson[];
|
|
373
|
+
email?: string;
|
|
374
|
+
faxNumber?: string;
|
|
375
|
+
member?: StructuredDataOrganization[];
|
|
376
|
+
name: string;
|
|
377
|
+
telephone?: string;
|
|
378
|
+
url?: string;
|
|
379
|
+
};
|
|
380
|
+
type StructuredDataArticle = {
|
|
381
|
+
'@context': 'https://schema.org';
|
|
382
|
+
'@type': 'Article' | 'BlogPosting' | 'NewsArticle';
|
|
383
|
+
author: (StructuredDataPerson | StructuredDataOrganization)[];
|
|
384
|
+
dateModified: Date | string;
|
|
385
|
+
datePublished: Date | string;
|
|
386
|
+
headline: string;
|
|
387
|
+
image: string[];
|
|
388
|
+
};
|
|
389
|
+
type StructuredDataEvent = {
|
|
390
|
+
'@context': 'https://schema.org';
|
|
391
|
+
'@type': 'Event';
|
|
392
|
+
name: string;
|
|
393
|
+
description: string;
|
|
394
|
+
startDate: Date | string;
|
|
395
|
+
endDate: Date | string;
|
|
396
|
+
location?: StructuredDataPlace;
|
|
397
|
+
image?: string[];
|
|
398
|
+
offers?: StructuredDataOffer;
|
|
399
|
+
performer?: StructuredDataPerformingGroup;
|
|
400
|
+
organizer?: StructuredDataOrganization;
|
|
401
|
+
};
|
|
402
|
+
type StructuredDataKeys = 'article';
|
|
403
|
+
type StructuredDataCollections = Record<StructuredDataKeys, string[]>;
|
|
404
|
+
declare function resolveStructuredData(page: IPage, types?: StructuredDataCollections): string | undefined;
|
|
405
|
+
|
|
406
|
+
export { IAddress, IAddressOptions, IAppProps, IApplication, IApplicationProps, ICartAddItem, ICartItem, ICheckout, ICheckoutDelivery, ICheckoutDiscount, ICheckoutInfo, ICheckoutItem, ICheckoutPartial, ICheckoutPayment, ICheckoutPaymentRedirect, ICheckoutStore, ICompanyAddress, IFeatureType, IKeyedList, ILazyComponent, ILazyComponentFunc, ILazyComponentProps, ILazyFuncProps, ILazyModules, ILazyProps, ILazyStaticProps, ILazyStaticPropsFunc, ILazyableProps, ILazyedProps, ILink, IList, IModelStore, IOrder, IOrderDetail, IOrderStatus, IOrderStatusValue, ISiteMap, IUser, IUserAddress, IUserChangePassword, IUserForgot, IUserLogin, IUserRegister, LAZY_PROPS, PartialPageProps, StaticPath, StructuredDataAddress, StructuredDataArticle, StructuredDataCollections, StructuredDataEvent, StructuredDataKeys, StructuredDataOffer, StructuredDataOrganization, StructuredDataPerformingGroup, StructuredDataPerson, StructuredDataPlace, categoryToRouteLink, findManyPages, findOnePage, getBreadcrumbFromSegments, getCategories, getCategory, getCountries, getCountry, getDecoratedComponents, getDeliveries, getErrorPageLayout, getFeatureType, getFeatureTypes, getInfo, getItems, getLabel, getLabels, getLayout, getListByKeys, getLists, getLocale, getLocaleFromProps, getLocales, getMarket, getMarkets, getMenu, getMenus, getOrder, getOrders, getPage, getPageCategory, getPageProps, getPageRoutes, getPayment, getPayments, getProvince, getProvinces, getRegion, getRegions, getRoute, getRouteLinkTree, getRoutes, getRoutesForSchemas, getRoutesForTemplates, getSegments, getSiteMapIndex, getSiteMapIndexProps, getSiteMapXML, getSiteMapXMLProps, getSiteMapXSL, getSiteMapXSLProps, getStaticPathsForSchema, getStores, newRouteLink, resolveLabel, resolveRoute, resolveStructuredData, routeInterceptor, routeRevalidateHandler, setDiscountCode, updateCheckout, withLazyProps };
|
package/dist/index.js
CHANGED
|
@@ -78,6 +78,7 @@ __export(src_exports, {
|
|
|
78
78
|
newRouteLink: () => newRouteLink,
|
|
79
79
|
resolveLabel: () => resolveLabel,
|
|
80
80
|
resolveRoute: () => resolveRoute,
|
|
81
|
+
resolveStructuredData: () => resolveStructuredData,
|
|
81
82
|
routeInterceptor: () => routeInterceptor,
|
|
82
83
|
routeRevalidateHandler: () => routeRevalidateHandler,
|
|
83
84
|
setDiscountCode: () => setDiscountCode,
|
|
@@ -215,7 +216,7 @@ async function getStaticPathsForSchema(schema) {
|
|
|
215
216
|
});
|
|
216
217
|
return routes.map((x) => ({ params: { id: x.page.toString(), market: x.market, locale: x.locale } }));
|
|
217
218
|
}
|
|
218
|
-
async function getBreadcrumbFromSegments(segments, market
|
|
219
|
+
async function getBreadcrumbFromSegments(segments, market, locale) {
|
|
219
220
|
const routes = await getRoutes({
|
|
220
221
|
where: {
|
|
221
222
|
market: {
|
|
@@ -242,7 +243,7 @@ async function getBreadcrumbFromSegments(segments, market = "ww", locale = "en")
|
|
|
242
243
|
});
|
|
243
244
|
return tree;
|
|
244
245
|
}
|
|
245
|
-
async function getRouteLinkTree(market
|
|
246
|
+
async function getRouteLinkTree(market, locale) {
|
|
246
247
|
const store = await (0, import_bom_mixer_store5.getStore)();
|
|
247
248
|
const routes = await store.route.findMany({
|
|
248
249
|
where: {
|
|
@@ -264,7 +265,7 @@ async function getRouteLinkTree(market = "ww", locale = "en") {
|
|
|
264
265
|
}
|
|
265
266
|
return void 0;
|
|
266
267
|
}
|
|
267
|
-
function newRouteLink(category, route, locale
|
|
268
|
+
function newRouteLink(category, route, locale) {
|
|
268
269
|
const href = route && route.id ? route.id.toString() : "/";
|
|
269
270
|
const id = route?.page || category.id;
|
|
270
271
|
const media = category.media || route?.media;
|
|
@@ -281,7 +282,7 @@ function newRouteLink(category, route, locale = "en") {
|
|
|
281
282
|
};
|
|
282
283
|
return routeLink;
|
|
283
284
|
}
|
|
284
|
-
function categoryToRouteLink(routes, categories, category, locale
|
|
285
|
+
function categoryToRouteLink(routes, categories, category, locale) {
|
|
285
286
|
const route = routes.find(
|
|
286
287
|
(r) => r.category === category.id
|
|
287
288
|
);
|
|
@@ -1112,7 +1113,7 @@ async function getPage(schema, id, market, locale) {
|
|
|
1112
1113
|
const currentRoute = routes.find((x) => x.market === market && x.locale === locale);
|
|
1113
1114
|
const alternates = routes.filter((x) => x.market !== market || x.locale !== locale);
|
|
1114
1115
|
const segments = await getSegments(page);
|
|
1115
|
-
const breadcrumb = await getBreadcrumbFromSegments(segments, market, locale);
|
|
1116
|
+
const breadcrumb = currentRoute ? await getBreadcrumbFromSegments(segments, currentRoute.market, currentRoute.locale) : [];
|
|
1116
1117
|
const parentRoute = breadcrumb.length > 1 ? breadcrumb[breadcrumb.length - 2] : void 0;
|
|
1117
1118
|
return {
|
|
1118
1119
|
...page,
|
|
@@ -1188,9 +1189,7 @@ async function getPageCategory(schema, page, market, locale) {
|
|
|
1188
1189
|
}
|
|
1189
1190
|
}
|
|
1190
1191
|
async function getErrorPageLayout() {
|
|
1191
|
-
const
|
|
1192
|
-
const defaultLocale = "en";
|
|
1193
|
-
const layout = await getLayout(defaultMarket, defaultLocale);
|
|
1192
|
+
const layout = await getLayout(import_bom_core3.defaultMarket, import_bom_core3.defaultLocale);
|
|
1194
1193
|
const title = resolveLabel(layout.labels, "notfound.title");
|
|
1195
1194
|
const abstract = resolveLabel(layout.labels, "notfound.abstract");
|
|
1196
1195
|
const page = {
|
|
@@ -1342,14 +1341,14 @@ async function getSiteMapXML(origin, marketId, localeId) {
|
|
|
1342
1341
|
let locales = await getLocales();
|
|
1343
1342
|
markets = markets.filter((x) => x.isActive !== false);
|
|
1344
1343
|
locales = locales.filter((x) => x.isActive !== false);
|
|
1345
|
-
const
|
|
1346
|
-
const
|
|
1347
|
-
const defaultMarketLocale =
|
|
1344
|
+
const defaultMarket2 = markets.find((x) => marketId ? x.id === marketId : x.isDefault) || markets[0];
|
|
1345
|
+
const defaultLocale2 = locales.find((x) => localeId ? x.id === localeId : x.isDefault) || locales[0];
|
|
1346
|
+
const defaultMarketLocale = defaultMarket2 && defaultMarket2.defaultLanguage ? defaultMarket2.defaultLanguage : defaultLocale2.id;
|
|
1348
1347
|
const routes = await getRoutes();
|
|
1349
1348
|
const isCanonicalRoute = marketId && localeId ? (route) => {
|
|
1350
|
-
return route.market ===
|
|
1349
|
+
return route.market === defaultMarket2.id && route.locale === defaultLocale2.id;
|
|
1351
1350
|
} : (route) => {
|
|
1352
|
-
return route.market ===
|
|
1351
|
+
return route.market === defaultMarket2.id && route.locale === defaultMarketLocale;
|
|
1353
1352
|
};
|
|
1354
1353
|
const getCanonicalAlternates = marketId && localeId ? (canonical) => {
|
|
1355
1354
|
return [];
|
|
@@ -1585,6 +1584,36 @@ var getSiteMapXSLProps = async (context) => {
|
|
|
1585
1584
|
props: {}
|
|
1586
1585
|
};
|
|
1587
1586
|
};
|
|
1587
|
+
|
|
1588
|
+
// src/structured_data/structured_data.ts
|
|
1589
|
+
var DefaultStructuredDataCollections = {
|
|
1590
|
+
article: ["news_detail"]
|
|
1591
|
+
};
|
|
1592
|
+
function resolveStructuredData(page, types = DefaultStructuredDataCollections) {
|
|
1593
|
+
let schema = null;
|
|
1594
|
+
const json = null;
|
|
1595
|
+
const pageType = page.template || page.schema || "";
|
|
1596
|
+
if (types.article.includes(pageType)) {
|
|
1597
|
+
schema = {
|
|
1598
|
+
"@context": "https://schema.org",
|
|
1599
|
+
"@type": "NewsArticle",
|
|
1600
|
+
headline: page.title,
|
|
1601
|
+
image: page.media ? [page.media.src] : [],
|
|
1602
|
+
datePublished: page.createdAt,
|
|
1603
|
+
dateModified: page.updatedAt,
|
|
1604
|
+
author: [{
|
|
1605
|
+
"@type": "Organization",
|
|
1606
|
+
name: "WebsiteName"
|
|
1607
|
+
// 'Autorità del bacino distrettuale dell\'Appennino Centrale',
|
|
1608
|
+
// url: 'https://twitter.com/autoritadac',
|
|
1609
|
+
}]
|
|
1610
|
+
};
|
|
1611
|
+
}
|
|
1612
|
+
if (json) {
|
|
1613
|
+
return JSON.stringify(json);
|
|
1614
|
+
}
|
|
1615
|
+
return void 0;
|
|
1616
|
+
}
|
|
1588
1617
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1589
1618
|
0 && (module.exports = {
|
|
1590
1619
|
IOrderStatus,
|
|
@@ -1645,6 +1674,7 @@ var getSiteMapXSLProps = async (context) => {
|
|
|
1645
1674
|
newRouteLink,
|
|
1646
1675
|
resolveLabel,
|
|
1647
1676
|
resolveRoute,
|
|
1677
|
+
resolveStructuredData,
|
|
1648
1678
|
routeInterceptor,
|
|
1649
1679
|
routeRevalidateHandler,
|
|
1650
1680
|
setDiscountCode,
|
package/dist/index.mjs
CHANGED
|
@@ -127,7 +127,7 @@ async function getStaticPathsForSchema(schema) {
|
|
|
127
127
|
});
|
|
128
128
|
return routes.map((x) => ({ params: { id: x.page.toString(), market: x.market, locale: x.locale } }));
|
|
129
129
|
}
|
|
130
|
-
async function getBreadcrumbFromSegments(segments, market
|
|
130
|
+
async function getBreadcrumbFromSegments(segments, market, locale) {
|
|
131
131
|
const routes = await getRoutes({
|
|
132
132
|
where: {
|
|
133
133
|
market: {
|
|
@@ -154,7 +154,7 @@ async function getBreadcrumbFromSegments(segments, market = "ww", locale = "en")
|
|
|
154
154
|
});
|
|
155
155
|
return tree;
|
|
156
156
|
}
|
|
157
|
-
async function getRouteLinkTree(market
|
|
157
|
+
async function getRouteLinkTree(market, locale) {
|
|
158
158
|
const store = await getStore5();
|
|
159
159
|
const routes = await store.route.findMany({
|
|
160
160
|
where: {
|
|
@@ -176,7 +176,7 @@ async function getRouteLinkTree(market = "ww", locale = "en") {
|
|
|
176
176
|
}
|
|
177
177
|
return void 0;
|
|
178
178
|
}
|
|
179
|
-
function newRouteLink(category, route, locale
|
|
179
|
+
function newRouteLink(category, route, locale) {
|
|
180
180
|
const href = route && route.id ? route.id.toString() : "/";
|
|
181
181
|
const id = route?.page || category.id;
|
|
182
182
|
const media = category.media || route?.media;
|
|
@@ -193,7 +193,7 @@ function newRouteLink(category, route, locale = "en") {
|
|
|
193
193
|
};
|
|
194
194
|
return routeLink;
|
|
195
195
|
}
|
|
196
|
-
function categoryToRouteLink(routes, categories, category, locale
|
|
196
|
+
function categoryToRouteLink(routes, categories, category, locale) {
|
|
197
197
|
const route = routes.find(
|
|
198
198
|
(r) => r.category === category.id
|
|
199
199
|
);
|
|
@@ -992,7 +992,7 @@ async function getOrder(id, market, locale) {
|
|
|
992
992
|
}
|
|
993
993
|
|
|
994
994
|
// src/page/page.service.ts
|
|
995
|
-
import { asServerProps } from "@websolutespa/bom-core";
|
|
995
|
+
import { asServerProps, defaultLocale, defaultMarket } from "@websolutespa/bom-core";
|
|
996
996
|
import { getStore as getStore12 } from "@websolutespa/bom-mixer-store";
|
|
997
997
|
async function findOnePage(schema, id, params) {
|
|
998
998
|
const store = await getStore12();
|
|
@@ -1024,7 +1024,7 @@ async function getPage(schema, id, market, locale) {
|
|
|
1024
1024
|
const currentRoute = routes.find((x) => x.market === market && x.locale === locale);
|
|
1025
1025
|
const alternates = routes.filter((x) => x.market !== market || x.locale !== locale);
|
|
1026
1026
|
const segments = await getSegments(page);
|
|
1027
|
-
const breadcrumb = await getBreadcrumbFromSegments(segments, market, locale);
|
|
1027
|
+
const breadcrumb = currentRoute ? await getBreadcrumbFromSegments(segments, currentRoute.market, currentRoute.locale) : [];
|
|
1028
1028
|
const parentRoute = breadcrumb.length > 1 ? breadcrumb[breadcrumb.length - 2] : void 0;
|
|
1029
1029
|
return {
|
|
1030
1030
|
...page,
|
|
@@ -1100,8 +1100,6 @@ async function getPageCategory(schema, page, market, locale) {
|
|
|
1100
1100
|
}
|
|
1101
1101
|
}
|
|
1102
1102
|
async function getErrorPageLayout() {
|
|
1103
|
-
const defaultMarket = "ww";
|
|
1104
|
-
const defaultLocale = "en";
|
|
1105
1103
|
const layout = await getLayout(defaultMarket, defaultLocale);
|
|
1106
1104
|
const title = resolveLabel(layout.labels, "notfound.title");
|
|
1107
1105
|
const abstract = resolveLabel(layout.labels, "notfound.abstract");
|
|
@@ -1254,14 +1252,14 @@ async function getSiteMapXML(origin, marketId, localeId) {
|
|
|
1254
1252
|
let locales = await getLocales();
|
|
1255
1253
|
markets = markets.filter((x) => x.isActive !== false);
|
|
1256
1254
|
locales = locales.filter((x) => x.isActive !== false);
|
|
1257
|
-
const
|
|
1258
|
-
const
|
|
1259
|
-
const defaultMarketLocale =
|
|
1255
|
+
const defaultMarket2 = markets.find((x) => marketId ? x.id === marketId : x.isDefault) || markets[0];
|
|
1256
|
+
const defaultLocale2 = locales.find((x) => localeId ? x.id === localeId : x.isDefault) || locales[0];
|
|
1257
|
+
const defaultMarketLocale = defaultMarket2 && defaultMarket2.defaultLanguage ? defaultMarket2.defaultLanguage : defaultLocale2.id;
|
|
1260
1258
|
const routes = await getRoutes();
|
|
1261
1259
|
const isCanonicalRoute = marketId && localeId ? (route) => {
|
|
1262
|
-
return route.market ===
|
|
1260
|
+
return route.market === defaultMarket2.id && route.locale === defaultLocale2.id;
|
|
1263
1261
|
} : (route) => {
|
|
1264
|
-
return route.market ===
|
|
1262
|
+
return route.market === defaultMarket2.id && route.locale === defaultMarketLocale;
|
|
1265
1263
|
};
|
|
1266
1264
|
const getCanonicalAlternates = marketId && localeId ? (canonical) => {
|
|
1267
1265
|
return [];
|
|
@@ -1497,6 +1495,36 @@ var getSiteMapXSLProps = async (context) => {
|
|
|
1497
1495
|
props: {}
|
|
1498
1496
|
};
|
|
1499
1497
|
};
|
|
1498
|
+
|
|
1499
|
+
// src/structured_data/structured_data.ts
|
|
1500
|
+
var DefaultStructuredDataCollections = {
|
|
1501
|
+
article: ["news_detail"]
|
|
1502
|
+
};
|
|
1503
|
+
function resolveStructuredData(page, types = DefaultStructuredDataCollections) {
|
|
1504
|
+
let schema = null;
|
|
1505
|
+
const json = null;
|
|
1506
|
+
const pageType = page.template || page.schema || "";
|
|
1507
|
+
if (types.article.includes(pageType)) {
|
|
1508
|
+
schema = {
|
|
1509
|
+
"@context": "https://schema.org",
|
|
1510
|
+
"@type": "NewsArticle",
|
|
1511
|
+
headline: page.title,
|
|
1512
|
+
image: page.media ? [page.media.src] : [],
|
|
1513
|
+
datePublished: page.createdAt,
|
|
1514
|
+
dateModified: page.updatedAt,
|
|
1515
|
+
author: [{
|
|
1516
|
+
"@type": "Organization",
|
|
1517
|
+
name: "WebsiteName"
|
|
1518
|
+
// 'Autorità del bacino distrettuale dell\'Appennino Centrale',
|
|
1519
|
+
// url: 'https://twitter.com/autoritadac',
|
|
1520
|
+
}]
|
|
1521
|
+
};
|
|
1522
|
+
}
|
|
1523
|
+
if (json) {
|
|
1524
|
+
return JSON.stringify(json);
|
|
1525
|
+
}
|
|
1526
|
+
return void 0;
|
|
1527
|
+
}
|
|
1500
1528
|
export {
|
|
1501
1529
|
IOrderStatus,
|
|
1502
1530
|
LAZY_PROPS,
|
|
@@ -1556,6 +1584,7 @@ export {
|
|
|
1556
1584
|
newRouteLink,
|
|
1557
1585
|
resolveLabel,
|
|
1558
1586
|
resolveRoute,
|
|
1587
|
+
resolveStructuredData,
|
|
1559
1588
|
routeInterceptor,
|
|
1560
1589
|
routeRevalidateHandler,
|
|
1561
1590
|
setDiscountCode,
|
package/package.json
CHANGED
|
@@ -30,22 +30,22 @@ export async function getDeliveries(checkout: ICheckoutPartial, market: string,
|
|
|
30
30
|
'name': 'In-store pick up',
|
|
31
31
|
'abstract': 'Conveniently collect from your nearest shop at no extra charge',
|
|
32
32
|
'price': 0,
|
|
33
|
-
'fullPrice': 0
|
|
33
|
+
'fullPrice': 0,
|
|
34
34
|
},
|
|
35
35
|
{
|
|
36
36
|
'id': 2,
|
|
37
37
|
'name': 'Courier delivery',
|
|
38
38
|
'abstract': 'Packaged goods are delivered by our trusted forwarder.',
|
|
39
39
|
'price': 81,
|
|
40
|
-
'fullPrice': 81
|
|
40
|
+
'fullPrice': 81,
|
|
41
41
|
},
|
|
42
42
|
{
|
|
43
43
|
'id': 3,
|
|
44
44
|
'name': 'In-home courier delivery',
|
|
45
45
|
'abstract': 'Packaged goods are delivered inside at front door. <br>White glove delivery, unpacking, assembly, or removal of debris is optional on request.',
|
|
46
46
|
'price': 156,
|
|
47
|
-
'fullPrice': 156
|
|
48
|
-
}
|
|
47
|
+
'fullPrice': 156,
|
|
48
|
+
},
|
|
49
49
|
];
|
|
50
50
|
}
|
|
51
51
|
|
|
@@ -65,10 +65,10 @@ export async function getStores(checkout: ICheckoutPartial, market: string, loca
|
|
|
65
65
|
'timetable': [],
|
|
66
66
|
'position': {
|
|
67
67
|
'latitude': 0.0,
|
|
68
|
-
'longitude': 0.0
|
|
68
|
+
'longitude': 0.0,
|
|
69
69
|
},
|
|
70
70
|
'distance': 151.84174300013095,
|
|
71
|
-
'rank': 1
|
|
71
|
+
'rank': 1,
|
|
72
72
|
}, {
|
|
73
73
|
'id': 7430,
|
|
74
74
|
'category': { 'id': 'store_category_distributor', 'name': 'Mixer Distributor' },
|
|
@@ -82,10 +82,10 @@ export async function getStores(checkout: ICheckoutPartial, market: string, loca
|
|
|
82
82
|
'timetable': [],
|
|
83
83
|
'position': {
|
|
84
84
|
'latitude': 0.0,
|
|
85
|
-
'longitude': 0.0
|
|
85
|
+
'longitude': 0.0,
|
|
86
86
|
},
|
|
87
87
|
'distance': 170.6551472799284,
|
|
88
|
-
'rank': 2
|
|
88
|
+
'rank': 2,
|
|
89
89
|
}, {
|
|
90
90
|
'id': 325,
|
|
91
91
|
'category': { 'id': 'store_category_distributor', 'name': 'Mixer Distributor' },
|
|
@@ -100,10 +100,10 @@ export async function getStores(checkout: ICheckoutPartial, market: string, loca
|
|
|
100
100
|
'timetable': [],
|
|
101
101
|
'position': {
|
|
102
102
|
'latitude': 0.0,
|
|
103
|
-
'longitude': 0.0
|
|
103
|
+
'longitude': 0.0,
|
|
104
104
|
},
|
|
105
105
|
'distance': 196.0600048738732,
|
|
106
|
-
'rank': 3
|
|
106
|
+
'rank': 3,
|
|
107
107
|
}];
|
|
108
108
|
}
|
|
109
109
|
|
|
@@ -115,72 +115,72 @@ export async function getPayments(checkout: ICheckoutPartial, market: string, lo
|
|
|
115
115
|
'name': 'Alipay',
|
|
116
116
|
'media': {
|
|
117
117
|
'type': 'image',
|
|
118
|
-
'src': '/assets/payment/alipay.svg'
|
|
119
|
-
}
|
|
118
|
+
'src': '/assets/payment/alipay.svg',
|
|
119
|
+
},
|
|
120
120
|
},
|
|
121
121
|
{
|
|
122
122
|
'id': 'amex',
|
|
123
123
|
'name': 'American Express',
|
|
124
124
|
'media': {
|
|
125
125
|
'type': 'image',
|
|
126
|
-
'src': '/assets/payment/american-express.svg'
|
|
127
|
-
}
|
|
126
|
+
'src': '/assets/payment/american-express.svg',
|
|
127
|
+
},
|
|
128
128
|
},
|
|
129
129
|
{
|
|
130
130
|
'id': 'apple-pay',
|
|
131
131
|
'name': 'Apple Pay',
|
|
132
132
|
'media': {
|
|
133
133
|
'type': 'image',
|
|
134
|
-
'src': '/assets/payment/apple-pay.svg'
|
|
135
|
-
}
|
|
134
|
+
'src': '/assets/payment/apple-pay.svg',
|
|
135
|
+
},
|
|
136
136
|
},
|
|
137
137
|
{
|
|
138
138
|
'id': 'bank-transfer',
|
|
139
139
|
'name': 'Bank Transfer',
|
|
140
140
|
'media': {
|
|
141
141
|
'type': 'image',
|
|
142
|
-
'src': '/assets/payment/bank-transfer.svg'
|
|
143
|
-
}
|
|
142
|
+
'src': '/assets/payment/bank-transfer.svg',
|
|
143
|
+
},
|
|
144
144
|
},
|
|
145
145
|
{
|
|
146
146
|
'id': 'cbc',
|
|
147
147
|
'name': 'CBC',
|
|
148
148
|
'media': {
|
|
149
149
|
'type': 'image',
|
|
150
|
-
'src': '/assets/payment/cbc.svg'
|
|
151
|
-
}
|
|
150
|
+
'src': '/assets/payment/cbc.svg',
|
|
151
|
+
},
|
|
152
152
|
},
|
|
153
153
|
{
|
|
154
154
|
'id': 'direct-debit',
|
|
155
155
|
'name': 'Direct Debit',
|
|
156
156
|
'media': {
|
|
157
157
|
'type': 'image',
|
|
158
|
-
'src': '/assets/payment/direct-debit.svg'
|
|
159
|
-
}
|
|
158
|
+
'src': '/assets/payment/direct-debit.svg',
|
|
159
|
+
},
|
|
160
160
|
},
|
|
161
161
|
{
|
|
162
162
|
'id': 'googlepay',
|
|
163
163
|
'name': 'Google Pay',
|
|
164
164
|
'media': {
|
|
165
165
|
'type': 'image',
|
|
166
|
-
'src': '/assets/payment/googlepay.svg'
|
|
167
|
-
}
|
|
166
|
+
'src': '/assets/payment/googlepay.svg',
|
|
167
|
+
},
|
|
168
168
|
},
|
|
169
169
|
{
|
|
170
170
|
'id': 'ideal',
|
|
171
171
|
'name': 'iDEAL',
|
|
172
172
|
'media': {
|
|
173
173
|
'type': 'image',
|
|
174
|
-
'src': '/assets/payment/ideal.svg'
|
|
175
|
-
}
|
|
174
|
+
'src': '/assets/payment/ideal.svg',
|
|
175
|
+
},
|
|
176
176
|
},
|
|
177
177
|
{
|
|
178
178
|
'id': 'maestro',
|
|
179
179
|
'name': 'Maestro',
|
|
180
180
|
'media': {
|
|
181
181
|
'type': 'image',
|
|
182
|
-
'src': '/assets/payment/maestro.svg'
|
|
183
|
-
}
|
|
182
|
+
'src': '/assets/payment/maestro.svg',
|
|
183
|
+
},
|
|
184
184
|
},
|
|
185
185
|
{
|
|
186
186
|
'id': 'mastercard',
|
|
@@ -188,32 +188,32 @@ export async function getPayments(checkout: ICheckoutPartial, market: string, lo
|
|
|
188
188
|
'abstract': '<p>You can use your Mastercard credit card. The 3DS authentication procedure will be used when the order is concluded, and you will be redirected to the bank\'s web page. To complete the order, follow the required steps.</p>',
|
|
189
189
|
'media': {
|
|
190
190
|
'type': 'image',
|
|
191
|
-
'src': '/assets/payment/mastercard.svg'
|
|
192
|
-
}
|
|
191
|
+
'src': '/assets/payment/mastercard.svg',
|
|
192
|
+
},
|
|
193
193
|
},
|
|
194
194
|
{
|
|
195
195
|
'id': 'mybank',
|
|
196
196
|
'name': 'MyBank',
|
|
197
197
|
'media': {
|
|
198
198
|
'type': 'image',
|
|
199
|
-
'src': '/assets/payment/mybank.svg'
|
|
200
|
-
}
|
|
199
|
+
'src': '/assets/payment/mybank.svg',
|
|
200
|
+
},
|
|
201
201
|
},
|
|
202
202
|
{
|
|
203
203
|
'id': 'paypal',
|
|
204
204
|
'name': 'PayPal',
|
|
205
205
|
'media': {
|
|
206
206
|
'type': 'image',
|
|
207
|
-
'src': '/assets/payment/paypal.svg'
|
|
208
|
-
}
|
|
207
|
+
'src': '/assets/payment/paypal.svg',
|
|
208
|
+
},
|
|
209
209
|
},
|
|
210
210
|
{
|
|
211
211
|
'id': 'trustly',
|
|
212
212
|
'name': 'Trustly',
|
|
213
213
|
'media': {
|
|
214
214
|
'type': 'image',
|
|
215
|
-
'src': '/assets/payment/trustly.svg'
|
|
216
|
-
}
|
|
215
|
+
'src': '/assets/payment/trustly.svg',
|
|
216
|
+
},
|
|
217
217
|
},
|
|
218
218
|
{
|
|
219
219
|
'id': 'visa',
|
|
@@ -221,16 +221,16 @@ export async function getPayments(checkout: ICheckoutPartial, market: string, lo
|
|
|
221
221
|
'abstract': '<p>You can use your Visa credit card. The 3DS authentication procedure will be used when the order is concluded, and you will be redirected to the bank\'s web page. To complete the order, follow the required steps.</p>',
|
|
222
222
|
'media': {
|
|
223
223
|
'type': 'image',
|
|
224
|
-
'src': '/assets/payment/visa.svg'
|
|
225
|
-
}
|
|
224
|
+
'src': '/assets/payment/visa.svg',
|
|
225
|
+
},
|
|
226
226
|
},
|
|
227
227
|
{
|
|
228
228
|
'id': 'wechatpay',
|
|
229
229
|
'name': 'WeChat Pay',
|
|
230
230
|
'media': {
|
|
231
231
|
'type': 'image',
|
|
232
|
-
'src': '/assets/payment/wechatpay.svg'
|
|
233
|
-
}
|
|
232
|
+
'src': '/assets/payment/wechatpay.svg',
|
|
233
|
+
},
|
|
234
234
|
},
|
|
235
235
|
{
|
|
236
236
|
'id': 'wire-transfer',
|
|
@@ -238,9 +238,9 @@ export async function getPayments(checkout: ICheckoutPartial, market: string, lo
|
|
|
238
238
|
'abstract': '<p>The order confirmation will contain a summary of the total amount to be paid and the details of the bank to which the payment is to be made..</p><p> Once the payment has been made, the order will be activated and the delivery terms indicated for the various items ordered will apply. The successful completion of the payment will be communicated by email to the email address indicated during registration.</p>',
|
|
239
239
|
'media': {
|
|
240
240
|
'type': 'image',
|
|
241
|
-
'src': '/assets/payment/wire-transfer.svg'
|
|
242
|
-
}
|
|
243
|
-
}
|
|
241
|
+
'src': '/assets/payment/wire-transfer.svg',
|
|
242
|
+
},
|
|
243
|
+
},
|
|
244
244
|
];
|
|
245
245
|
}
|
|
246
246
|
|
package/src/index.ts
CHANGED
|
@@ -20,7 +20,7 @@ export function resolveLabel(labels: ILabel[], id: string): string {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
/*
|
|
23
|
-
export function localizedLabel(labels: Label[], id: string, locale: string
|
|
23
|
+
export function localizedLabel(labels: Label[], id: string, locale: string, defaultLocale: string): Promise<Label> {
|
|
24
24
|
const label = labels.find(x => x.id === id);
|
|
25
25
|
if (label) {
|
|
26
26
|
return store.localizeValue(label, locale, defaultLocale);
|
package/src/page/page.service.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ICategorized, ICategory, IEquatable, ILayout, IPage, IPageResult, IRoute, IRouteLink, PageProps, QueryParams, SchemaType, asServerProps } from '@websolutespa/bom-core';
|
|
1
|
+
import { ICategorized, ICategory, IEquatable, ILayout, IPage, IPageResult, IRoute, IRouteLink, PageProps, QueryParams, SchemaType, asServerProps, defaultLocale, defaultMarket } from '@websolutespa/bom-core';
|
|
2
2
|
import { getStore } from '@websolutespa/bom-mixer-store';
|
|
3
3
|
import { getSegments } from '../category/category.service';
|
|
4
4
|
import { resolveLabel } from '../label/label.service';
|
|
@@ -41,7 +41,9 @@ export async function getPage<T extends ICategorized = ICategorized>(schema: str
|
|
|
41
41
|
const currentRoute = routes.find((x: IRoute) => x.market === market && x.locale === locale);
|
|
42
42
|
const alternates = routes.filter((x: IRoute) => x.market !== market || x.locale !== locale);
|
|
43
43
|
const segments: ICategory[] = await getSegments(page);
|
|
44
|
-
const breadcrumb: IRouteLink[] =
|
|
44
|
+
const breadcrumb: IRouteLink[] = currentRoute ?
|
|
45
|
+
await getBreadcrumbFromSegments(segments, currentRoute.market, currentRoute.locale) :
|
|
46
|
+
[];
|
|
45
47
|
const parentRoute: IRouteLink | undefined = breadcrumb.length > 1 ? breadcrumb[breadcrumb.length - 2] : undefined;
|
|
46
48
|
return {
|
|
47
49
|
...page,
|
|
@@ -116,8 +118,6 @@ export async function getPageCategory<T extends IPage>(schema: string, page?: IP
|
|
|
116
118
|
}
|
|
117
119
|
|
|
118
120
|
export async function getErrorPageLayout(): Promise<{ layout: ILayout, page: IPage }> {
|
|
119
|
-
const defaultMarket = 'ww';
|
|
120
|
-
const defaultLocale = 'en';
|
|
121
121
|
const layout = await getLayout(defaultMarket, defaultLocale);
|
|
122
122
|
// console.log('getErrorPageLayout', layout);
|
|
123
123
|
const title = resolveLabel(layout.labels, 'notfound.title');
|
|
@@ -79,7 +79,7 @@ export async function getStaticPathsForSchema(schema: string): Promise<StaticPat
|
|
|
79
79
|
return routes.map((x: any) => ({ params: { id: x.page.toString(), market: x.market, locale: x.locale } }));
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
-
export async function getBreadcrumbFromSegments(segments: ICategory[], market: string
|
|
82
|
+
export async function getBreadcrumbFromSegments(segments: ICategory[], market: string, locale: string): Promise<IRouteLink[]> {
|
|
83
83
|
const routes: IRoute[] = await getRoutes({
|
|
84
84
|
where: {
|
|
85
85
|
market: {
|
|
@@ -107,7 +107,7 @@ export async function getBreadcrumbFromSegments(segments: ICategory[], market: s
|
|
|
107
107
|
return tree;
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
-
export async function getRouteLinkTree(market: string
|
|
110
|
+
export async function getRouteLinkTree(market: string, locale: string): Promise<IRouteLink | undefined> {
|
|
111
111
|
const store = await getStore<IModelStore>();
|
|
112
112
|
// console.log('getRouteLinkTree.store');
|
|
113
113
|
const routes = await store.route.findMany({
|
|
@@ -133,7 +133,7 @@ export async function getRouteLinkTree(market: string = 'ww', locale: string = '
|
|
|
133
133
|
return undefined;
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
export function newRouteLink(category: ICategory, route
|
|
136
|
+
export function newRouteLink(category: ICategory, route: IRoute | undefined, locale: string): IRouteLink {
|
|
137
137
|
const href = (route && route.id) ? route.id.toString() : '/';
|
|
138
138
|
const id = route?.page || category.id;
|
|
139
139
|
const media = category.media || route?.media;
|
|
@@ -151,7 +151,7 @@ export function newRouteLink(category: ICategory, route?: IRoute, locale: string
|
|
|
151
151
|
return routeLink;
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
export function categoryToRouteLink(routes: IRoute[], categories: ICategory[], category: ICategory, locale: string
|
|
154
|
+
export function categoryToRouteLink(routes: IRoute[], categories: ICategory[], category: ICategory, locale: string): IRouteLink {
|
|
155
155
|
const route = routes.find(r =>
|
|
156
156
|
r.category === category.id
|
|
157
157
|
);
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { IPage } from '@websolutespa/bom-core';
|
|
2
|
+
|
|
3
|
+
export type StructuredDataPerson = {
|
|
4
|
+
'@type': 'Person';
|
|
5
|
+
name: string;
|
|
6
|
+
url: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export type StructuredDataPerformingGroup = {
|
|
10
|
+
'@type': 'PerformingGroup';
|
|
11
|
+
name: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type StructuredDataOffer = {
|
|
15
|
+
'@type': 'Offer';
|
|
16
|
+
url: string;
|
|
17
|
+
price: number;
|
|
18
|
+
priceCurrency: string;
|
|
19
|
+
// availability: 'https://schema.org/InStock',
|
|
20
|
+
validFrom?: Date | string;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type StructuredDataAddress = {
|
|
24
|
+
'@type': 'PostalAddress';
|
|
25
|
+
addressCountry?: string;
|
|
26
|
+
addressLocality: string;
|
|
27
|
+
addressRegion?: string;
|
|
28
|
+
postalCode: string;
|
|
29
|
+
streetAddress: string;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export type StructuredDataPlace = {
|
|
33
|
+
'@type': 'Place';
|
|
34
|
+
name: string;
|
|
35
|
+
address: StructuredDataAddress;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export type StructuredDataOrganization = {
|
|
39
|
+
'@type': 'Organization';
|
|
40
|
+
address?: StructuredDataAddress;
|
|
41
|
+
alumni?: StructuredDataPerson[];
|
|
42
|
+
email?: string;
|
|
43
|
+
faxNumber?: string;
|
|
44
|
+
member?: StructuredDataOrganization[];
|
|
45
|
+
name: string;
|
|
46
|
+
telephone?: string;
|
|
47
|
+
url?: string;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export type StructuredDataArticle = {
|
|
51
|
+
'@context': 'https://schema.org';
|
|
52
|
+
'@type': 'Article' | 'BlogPosting' | 'NewsArticle';
|
|
53
|
+
author: (StructuredDataPerson | StructuredDataOrganization)[];
|
|
54
|
+
dateModified: Date | string;
|
|
55
|
+
datePublished: Date | string;
|
|
56
|
+
headline: string;
|
|
57
|
+
image: string[];
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export type StructuredDataEvent = {
|
|
61
|
+
'@context': 'https://schema.org';
|
|
62
|
+
'@type': 'Event';
|
|
63
|
+
name: string;
|
|
64
|
+
description: string;
|
|
65
|
+
startDate: Date | string;
|
|
66
|
+
endDate: Date | string;
|
|
67
|
+
/*
|
|
68
|
+
eventAttendanceMode: 'https://schema.org/OfflineEventAttendanceMode',
|
|
69
|
+
eventStatus: 'https://schema.org/EventScheduled',
|
|
70
|
+
*/
|
|
71
|
+
location?: StructuredDataPlace,
|
|
72
|
+
image?: string[],
|
|
73
|
+
offers?: StructuredDataOffer,
|
|
74
|
+
performer?: StructuredDataPerformingGroup,
|
|
75
|
+
organizer?: StructuredDataOrganization;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export type StructuredDataKeys = 'article';
|
|
79
|
+
export type StructuredDataCollections = Record<StructuredDataKeys, string[]>;
|
|
80
|
+
|
|
81
|
+
const DefaultStructuredDataCollections: StructuredDataCollections = {
|
|
82
|
+
article: ['news_detail'],
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export function resolveStructuredData(page: IPage, types: StructuredDataCollections = DefaultStructuredDataCollections): string | undefined {
|
|
86
|
+
let schema = null;
|
|
87
|
+
const json: {} | null = null;
|
|
88
|
+
const pageType = page.template || page.schema || '';
|
|
89
|
+
if (types.article.includes(pageType)) {
|
|
90
|
+
schema = {
|
|
91
|
+
'@context': 'https://schema.org',
|
|
92
|
+
'@type': 'NewsArticle',
|
|
93
|
+
headline: page.title,
|
|
94
|
+
image: page.media ? [page.media.src] : [],
|
|
95
|
+
datePublished: page.createdAt,
|
|
96
|
+
dateModified: page.updatedAt,
|
|
97
|
+
author: [{
|
|
98
|
+
'@type': 'Organization',
|
|
99
|
+
name: 'WebsiteName', // 'Autorità del bacino distrettuale dell\'Appennino Centrale',
|
|
100
|
+
// url: 'https://twitter.com/autoritadac',
|
|
101
|
+
}],
|
|
102
|
+
} as StructuredDataArticle;
|
|
103
|
+
}
|
|
104
|
+
if (json) {
|
|
105
|
+
return JSON.stringify(json);
|
|
106
|
+
}
|
|
107
|
+
return undefined;
|
|
108
|
+
}
|