@studyportals/fawkes 7.3.5 → 7.4.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.
@@ -11,7 +11,7 @@ export declare class ProgrammeStructuredDataFactory extends SearchStructuredData
11
11
  private regionalDataPriority;
12
12
  protected getRating(card: IProgrammeCard): ReviewRatingDTO | undefined;
13
13
  protected getOfferData(card: IProgrammeCard): Promise<OfferDTO | undefined>;
14
- protected buildStructuredDataForCard(entity: EntityDTO<IProgrammeCard>): Course;
14
+ protected buildStructuredDataForCard(entity: EntityDTO<IProgrammeCard>): Course | undefined;
15
15
  private getCourseMode;
16
16
  private getCourseWorkload;
17
17
  private getCourseStartDate;
@@ -35,12 +35,15 @@ export class ProgrammeStructuredDataFactory extends SearchStructuredDataFactory
35
35
  return;
36
36
  }
37
37
  return {
38
- price: await this.currencyConversionService.convert(tuition.getAmount(), tuition.getCurrency(), 'USD'),
38
+ price: Math.round(await this.currencyConversionService.convert(tuition.getAmount(), tuition.getCurrency(), 'USD')),
39
39
  category: 'tuition',
40
40
  validFrom: timing ? timing.getStartDate().getDate() : undefined
41
41
  };
42
42
  }
43
43
  buildStructuredDataForCard(entity) {
44
+ const offer = this.constructOffer(entity.offer);
45
+ if (!offer)
46
+ return undefined;
44
47
  const card = entity.card;
45
48
  return {
46
49
  "@type": "Course",
@@ -52,7 +55,7 @@ export class ProgrammeStructuredDataFactory extends SearchStructuredDataFactory
52
55
  "name": card.getUniversityLink().getDescription(),
53
56
  "url": `https://${window.location.host}${card.getUniversityLink().getUrl()}`
54
57
  },
55
- "offers": this.constructOffer(entity.offer),
58
+ "offers": offer,
56
59
  "aggregateRating": this.constructAggregateRating(entity.reviewRating),
57
60
  "hasCourseInstance": {
58
61
  "@type": "CourseInstance",
@@ -1,12 +1,12 @@
1
- import { SearchResultsPage, WithContext, Offer, AggregateRating, Thing, FAQPage } from "schema-dts";
2
- import { ReviewRatingDTO } from "./dto/ReviewRatingDTO";
3
- import { OfferDTO } from "./dto/OfferDTO";
4
- import { EntityDTO } from "./dto/EntityDTO";
5
- import { FAQItemDto } from "./dto/FAQItemDto";
6
- import { BreadcrumbDTO } from "./dto/BreadcrumbDTO";
1
+ import { SearchResultsPage, WithContext, Offer, AggregateRating, Thing, FAQPage } from 'schema-dts';
2
+ import { ReviewRatingDTO } from './dto/ReviewRatingDTO';
3
+ import { OfferDTO } from './dto/OfferDTO';
4
+ import { EntityDTO } from './dto/EntityDTO';
5
+ import { FAQItemDto } from './dto/FAQItemDto';
6
+ import { BreadcrumbDTO } from './dto/BreadcrumbDTO';
7
7
  export declare abstract class SearchStructuredDataFactory<TCard> {
8
8
  buildStructuredData(title: string, description: string, cards: TCard[], faqItems?: FAQItemDto[], breadcrumbs?: BreadcrumbDTO[]): Promise<WithContext<SearchResultsPage>>;
9
- protected abstract buildStructuredDataForCard(entity: EntityDTO<TCard>): Thing;
9
+ protected abstract buildStructuredDataForCard(entity: EntityDTO<TCard>): Thing | undefined;
10
10
  /**
11
11
  * Get the rating for a card.
12
12
  * This method should be overridden by subclasses to provide the specific rating logic.
@@ -25,7 +25,6 @@ export declare abstract class SearchStructuredDataFactory<TCard> {
25
25
  * @protected
26
26
  */
27
27
  protected getOfferData(card: TCard): Promise<OfferDTO | undefined>;
28
- private constructOptionalPageAggregateRating;
29
28
  private constructOptionalPageOffers;
30
29
  protected constructOptionalFaqPage(faqItems: FAQItemDto[]): FAQPage | undefined;
31
30
  private constructOptionalBreadcrumbs;
@@ -12,14 +12,16 @@ export class SearchStructuredDataFactory {
12
12
  offersData.push(offer);
13
13
  entities.push({ card, offer, reviewRating });
14
14
  }
15
+ const mainEntities = entities
16
+ .map(entity => this.buildStructuredDataForCard(entity))
17
+ .filter(entity => entity !== undefined);
15
18
  const data = {
16
- "@context": "https://schema.org",
17
- "@type": "SearchResultsPage",
18
- "name": title,
19
+ '@context': 'https://schema.org',
20
+ '@type': 'SearchResultsPage',
21
+ 'name': title,
19
22
  description,
20
- "mainEntity": entities.map(entity => this.buildStructuredDataForCard(entity))
23
+ 'mainEntity': mainEntities
21
24
  };
22
- data.aggregateRating = this.constructOptionalPageAggregateRating(ratings);
23
25
  data.offers = this.constructOptionalPageOffers(offersData);
24
26
  data.hasPart = this.constructOptionalFaqPage(faqItems);
25
27
  data.breadcrumb = this.constructOptionalBreadcrumbs(breadcrumbs);
@@ -49,18 +51,6 @@ export class SearchStructuredDataFactory {
49
51
  async getOfferData(card) {
50
52
  return undefined;
51
53
  }
52
- constructOptionalPageAggregateRating(ratings) {
53
- if (ratings.length <= 0)
54
- return;
55
- let totalQuantity = 0;
56
- let totalRatingValue = 0;
57
- for (const rating of ratings) {
58
- totalQuantity += rating.quantity;
59
- totalRatingValue += rating.rating;
60
- }
61
- const totalAverageRating = Math.round((totalRatingValue / ratings.length) * 10) / 10;
62
- return this.constructAggregateRating({ rating: totalAverageRating, quantity: totalQuantity });
63
- }
64
54
  constructOptionalPageOffers(offersData) {
65
55
  if (offersData.length <= 0)
66
56
  return;
@@ -77,15 +67,15 @@ export class SearchStructuredDataFactory {
77
67
  totalPrice += offer.price;
78
68
  }
79
69
  return {
80
- "@type": "AggregateOffer",
81
- "lowPrice": Math.max(minPrice, 0),
82
- "highPrice": maxPrice,
83
- "priceCurrency": "USD",
84
- "offerCount": offersData.length,
85
- "priceSpecification": {
86
- "@type": "PriceSpecification",
87
- "price": Math.round(totalPrice / offersData.length),
88
- "priceCurrency": "USD"
70
+ '@type': 'AggregateOffer',
71
+ 'lowPrice': Math.max(minPrice, 0),
72
+ 'highPrice': maxPrice,
73
+ 'priceCurrency': 'USD',
74
+ 'offerCount': offersData.length,
75
+ 'priceSpecification': {
76
+ '@type': 'PriceSpecification',
77
+ 'price': Math.round(totalPrice / offersData.length),
78
+ 'priceCurrency': 'USD'
89
79
  }
90
80
  };
91
81
  }
@@ -93,13 +83,13 @@ export class SearchStructuredDataFactory {
93
83
  if (faqItems.length <= 0)
94
84
  return;
95
85
  return {
96
- "@type": "FAQPage",
97
- "mainEntity": faqItems.map(item => ({
98
- "@type": "Question",
99
- "name": item.question,
100
- "acceptedAnswer": {
101
- "@type": "Answer",
102
- "text": this.stripHtmlWithListRetain(item.answer)
86
+ '@type': 'FAQPage',
87
+ 'mainEntity': faqItems.map(item => ({
88
+ '@type': 'Question',
89
+ 'name': item.question,
90
+ 'acceptedAnswer': {
91
+ '@type': 'Answer',
92
+ 'text': this.stripHtmlWithListRetain(item.answer)
103
93
  }
104
94
  }))
105
95
  };
@@ -108,13 +98,13 @@ export class SearchStructuredDataFactory {
108
98
  if (breadcrumbs.length <= 0)
109
99
  return;
110
100
  return {
111
- "@type": "BreadcrumbList",
112
- "itemListElement": breadcrumbs.map((breadcrumb) => ({
113
- "@type": "ListItem",
114
- "@id": `${breadcrumb.url}#listitem#thing`,
115
- "name": breadcrumb.name,
116
- "position": breadcrumb.position,
117
- "item": breadcrumb.url
101
+ '@type': 'BreadcrumbList',
102
+ 'itemListElement': breadcrumbs.map((breadcrumb) => ({
103
+ '@type': 'ListItem',
104
+ '@id': `${breadcrumb.url}#listitem#thing`,
105
+ 'name': breadcrumb.name,
106
+ 'position': breadcrumb.position,
107
+ 'item': breadcrumb.url
118
108
  }))
119
109
  };
120
110
  }
@@ -122,23 +112,23 @@ export class SearchStructuredDataFactory {
122
112
  if (!reviewRating)
123
113
  return;
124
114
  return {
125
- "@type": "AggregateRating",
126
- "ratingValue": reviewRating.rating,
127
- "reviewCount": reviewRating.quantity,
128
- "bestRating": 5,
129
- "worstRating": 1
115
+ '@type': 'AggregateRating',
116
+ 'ratingValue': reviewRating.rating,
117
+ 'reviewCount': reviewRating.quantity,
118
+ 'bestRating': 5,
119
+ 'worstRating': 1
130
120
  };
131
121
  }
132
122
  constructOffer(offerData) {
133
123
  if (!offerData)
134
124
  return;
135
125
  return {
136
- "@type": "Offer",
137
- "price": offerData.price,
138
- "priceCurrency": "USD",
139
- "availability": "https://schema.org/InStock",
140
- "validFrom": offerData.validFrom ? offerData.validFrom.toISOString().split('T')[0] : undefined,
141
- "category": "tuition"
126
+ '@type': 'Offer',
127
+ 'price': offerData.price,
128
+ 'priceCurrency': 'USD',
129
+ 'availability': 'https://schema.org/InStock',
130
+ 'validFrom': offerData.validFrom ? offerData.validFrom.toISOString().split('T')[0] : undefined,
131
+ 'category': 'tuition'
142
132
  };
143
133
  }
144
134
  stripHtmlWithListRetain(html) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@studyportals/fawkes",
3
- "version": "7.3.5",
3
+ "version": "7.4.0",
4
4
  "description": "A package to centralize SEO related logic for SBLP and Sitemap Generator.",
5
5
  "files": [
6
6
  "./dist"
@@ -15,7 +15,7 @@
15
15
  "publish-major": "npm run prepare-deployment && npm version major && npm publish",
16
16
  "publish-beta": "npm run prepare-deployment && npm version prerelease && npm publish --tag beta --access=public",
17
17
  "publish-patch": "npm run prepare-deployment && npm version patch && npm publish",
18
- "publish-minor": "npm run prepare-deployment && npm version minor && npm publish",
18
+ "publish-minor": "npm run prepare-deployment && npm publish",
19
19
  "prepare": "husky install",
20
20
  "test": "vitest run --coverage",
21
21
  "test:dev": "vitest --coverage tests/programmes",
@@ -90,9 +90,9 @@
90
90
  "ts-loader": "^9.5.2"
91
91
  },
92
92
  "dependencies": {
93
- "@studyportals/domain-client": "^6.2.0",
93
+ "@studyportals/domain-client": "^6.3.0",
94
94
  "@studyportals/ranking-api-interface": "^1.3.12",
95
- "@studyportals/search-filters": "^4.9.1",
95
+ "@studyportals/search-filters": "^5.1.0",
96
96
  "@studyportals/static-domain-data": "^6.1.0"
97
97
  },
98
98
  "optionalDependencies": {
@@ -1 +0,0 @@
1
- export * from '../src/structured-data';
@@ -1 +0,0 @@
1
- export * from '../src/structured-data';
@@ -1 +0,0 @@
1
- export * from '../src/structured-data';
@@ -1 +0,0 @@
1
- export * from '../src/structured-data';