@studyportals/fawkes 2.0.1-20 → 2.0.1-21

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.
Files changed (107) hide show
  1. package/dist/index.d.ts +1 -8
  2. package/dist/index.js +1 -3
  3. package/dist/scholarships-seo/index.d.ts +7 -7
  4. package/dist/scholarships-seo/index.js +2 -2
  5. package/dist/sitemap-generator-seo/index.d.ts +5 -0
  6. package/dist/sitemap-generator-seo/index.js +2 -1
  7. package/dist/src/common/BaseSeoIndexabilityPolicy.d.ts +13 -9
  8. package/dist/src/common/BaseSeoIndexabilityPolicy.js +18 -8
  9. package/dist/src/common/ICustomRule.d.ts +6 -0
  10. package/dist/src/common/IDependencies.d.ts +4 -0
  11. package/dist/src/common/IFilterKeyValues.d.ts +6 -0
  12. package/dist/src/common/IFilterKeyValues.js +1 -0
  13. package/dist/src/common/IIndexabilityPolicyDependencies.d.ts +8 -0
  14. package/dist/src/common/ISitemapUrlGenerator.d.ts +5 -0
  15. package/dist/src/common/ISitemapUrlGenerator.js +1 -0
  16. package/dist/src/common/RuleBasedIndexabilityPolicy.d.ts +10 -0
  17. package/dist/src/common/RuleBasedIndexabilityPolicy.js +12 -0
  18. package/dist/src/enums/DependencyTypes.d.ts +4 -0
  19. package/dist/src/enums/DependencyTypes.js +5 -0
  20. package/dist/src/enums/FilterCombinations.d.ts +9 -0
  21. package/dist/src/enums/FilterCombinations.js +10 -0
  22. package/dist/src/organisations/ISeoInfoBaseOrganisations.d.ts +1 -1
  23. package/dist/src/organisations/SearchIndexabilityManager.d.ts +2 -2
  24. package/dist/src/organisations/SeoIndexabilityPolicy.d.ts +3 -4
  25. package/dist/src/organisations/SeoIndexabilityPolicy.js +2 -2
  26. package/dist/src/organisations/SeoRuleBasedIndexabilityPolicy.d.ts +7 -8
  27. package/dist/src/organisations/SeoRuleBasedIndexabilityPolicy.js +4 -3
  28. package/dist/src/presenters/AreaPresenter.d.ts +9 -0
  29. package/dist/src/presenters/AreaPresenter.js +33 -0
  30. package/dist/src/presenters/CountryPresenter.d.ts +9 -0
  31. package/dist/src/presenters/CountryPresenter.js +36 -0
  32. package/dist/src/presenters/DisciplinePresenter.d.ts +9 -0
  33. package/dist/src/presenters/DisciplinePresenter.js +31 -0
  34. package/dist/src/presenters/fragments/IAreaFragment.d.ts +4 -0
  35. package/dist/src/presenters/fragments/IAreaFragment.js +1 -0
  36. package/dist/src/presenters/fragments/ICountryFragment.d.ts +4 -0
  37. package/dist/src/presenters/fragments/ICountryFragment.js +1 -0
  38. package/dist/src/presenters/fragments/IFragment.d.ts +4 -0
  39. package/dist/src/presenters/fragments/IFragment.js +1 -0
  40. package/dist/src/scholarships/SearchIndexabilityManager.d.ts +6 -5
  41. package/dist/src/scholarships/SearchIndexabilityManager.js +14 -11
  42. package/dist/src/scholarships/index.d.ts +0 -1
  43. package/dist/src/scholarships/index.js +0 -1
  44. package/dist/src/scholarships/policies/AreaPolicy.d.ts +10 -9
  45. package/dist/src/scholarships/policies/AreaPolicy.js +36 -16
  46. package/dist/src/scholarships/policies/CountryPolicy.d.ts +10 -6
  47. package/dist/src/scholarships/policies/CountryPolicy.js +32 -10
  48. package/dist/src/scholarships/policies/DisciplineCountryPolicy.d.ts +10 -9
  49. package/dist/src/scholarships/policies/DisciplineCountryPolicy.js +43 -15
  50. package/dist/src/scholarships/policies/DisciplinePolicy.d.ts +10 -6
  51. package/dist/src/scholarships/policies/DisciplinePolicy.js +33 -10
  52. package/dist/src/scholarships/policies/UnfilteredPolicy.d.ts +6 -5
  53. package/dist/src/scholarships/policies/UnfilteredPolicy.js +11 -6
  54. package/dist/src/scholarships/policies/UniversityCountryPolicy.d.ts +6 -5
  55. package/dist/src/scholarships/policies/UniversityCountryPolicy.js +35 -9
  56. package/dist/src/scholarships/rules/ExceptAustaliaAreasRule.d.ts +14 -0
  57. package/dist/src/scholarships/rules/ExceptAustaliaAreasRule.js +45 -0
  58. package/dist/src/scholarships/rules/SearchVolumeAreasRule.d.ts +12 -0
  59. package/dist/src/scholarships/rules/SearchVolumeAreasRule.js +34 -0
  60. package/dist/src/scholarships/rules/SearchVolumeCountriesRule.d.ts +12 -0
  61. package/dist/src/scholarships/rules/SearchVolumeCountriesRule.js +34 -0
  62. package/dist/src/scholarships/rules/SearchVolumeCountryDisciplineRule.d.ts +12 -0
  63. package/dist/src/scholarships/rules/SearchVolumeCountryDisciplineRule.js +37 -0
  64. package/dist/src/scholarships/rules/SearchVolumeDisciplinesRule.d.ts +12 -0
  65. package/dist/src/scholarships/rules/SearchVolumeDisciplinesRule.js +38 -0
  66. package/dist/src/scholarships/rules/files/search-volume.json +39334 -0
  67. package/dist/src/sitemap-generator/IOrganisation.d.ts +6 -0
  68. package/dist/src/sitemap-generator/IOrganisation.js +1 -0
  69. package/dist/src/sitemap-generator/IOrganisationsClient.d.ts +4 -0
  70. package/dist/src/sitemap-generator/IOrganisationsClient.js +1 -0
  71. package/dist/src/sitemap-generator/ISearchApiClient.d.ts +3 -0
  72. package/dist/src/sitemap-generator/ISearchApiClient.js +1 -0
  73. package/dist/src/sitemap-generator/ISitemapUrlGeneratorDependencies.d.ts +9 -0
  74. package/dist/src/sitemap-generator/ISitemapUrlGeneratorDependencies.js +1 -0
  75. package/dist/src/sitemap-generator/ISitemapUrlGeneratorManager.d.ts +4 -0
  76. package/dist/src/sitemap-generator/ISitemapUrlGeneratorManager.js +1 -0
  77. package/dist/src/sitemap-generator/SitemapUrlGeneratorManager.d.ts +8 -0
  78. package/dist/src/sitemap-generator/SitemapUrlGeneratorManager.js +20 -0
  79. package/dist/src/sitemap-generator/index.d.ts +0 -2
  80. package/dist/src/sitemap-generator/index.js +1 -2
  81. package/dist/src/types/SeoDependencies.d.ts +3 -0
  82. package/dist/src/types/SeoDependencies.js +1 -0
  83. package/package.json +16 -6
  84. package/dist/fawkes.js +0 -2
  85. package/dist/fawkes.js.map +0 -1
  86. package/dist/organisations-seo.js +0 -0
  87. package/dist/scholarships-seo.js +0 -2
  88. package/dist/scholarships-seo.js.map +0 -1
  89. package/dist/sitemap-generator-seo.js +0 -0
  90. package/dist/src/common/DisciplinePresenter.d.ts +0 -5
  91. package/dist/src/common/DisciplinePresenter.js +0 -48
  92. package/dist/src/common/IPrettyPathGenerator.d.ts +0 -3
  93. package/dist/src/common/fragments/Fragment.d.ts +0 -6
  94. package/dist/src/common/fragments/Fragment.js +0 -8
  95. package/dist/src/common/fragments/IFragment.d.ts +0 -4
  96. package/dist/src/scholarships/CustomRules.d.ts +0 -6
  97. package/dist/src/scholarships/CustomRules.js +0 -18
  98. package/dist/src/scholarships/policies/DisciplineAreaPolicy.d.ts +0 -12
  99. package/dist/src/scholarships/policies/DisciplineAreaPolicy.js +0 -34
  100. package/dist/src/sitemap-generator/CombinationType.d.ts +0 -2
  101. package/dist/src/sitemap-generator/CombinationType.js +0 -3
  102. package/dist/src/sitemap-generator/ISitemapPathGeneratorChain.d.ts +0 -4
  103. package/dist/src/sitemap-generator/SitemapPathGeneratorChain.d.ts +0 -7
  104. package/dist/src/sitemap-generator/SitemapPathGeneratorChain.js +0 -9
  105. /package/dist/src/common/{IPrettyPathGenerator.js → ICustomRule.js} +0 -0
  106. /package/dist/src/common/{fragments/IFragment.js → IDependencies.js} +0 -0
  107. /package/dist/src/{sitemap-generator/ISitemapPathGeneratorChain.js → common/IIndexabilityPolicyDependencies.js} +0 -0
@@ -1,8 +1,12 @@
1
- import { BaseSeoIndexabilityPolicy } from '@/common/BaseSeoIndexabilityPolicy';
2
- import { ISeoFilterState } from '@/common/ISeoFilterState';
3
- import { ISeoInfoBase } from '@/common/ISeoInfoBase';
4
- export declare class CountryPolicy extends BaseSeoIndexabilityPolicy {
5
- constructor(seoInfoBase: ISeoInfoBase, filterState: ISeoFilterState);
1
+ import { FilterCombinations } from '../../enums/FilterCombinations';
2
+ import { ICustomRule } from '../../common/ICustomRule';
3
+ import { SeoDependencies } from '../../types/SeoDependencies';
4
+ import { RuleBasedIndexabilityPolicy } from '../../common/RuleBasedIndexabilityPolicy';
5
+ import { ISeoIndexabilityPolicy } from '../../common/ISeoIndexabilityPolicy';
6
+ export declare class CountryPolicy extends RuleBasedIndexabilityPolicy implements ISeoIndexabilityPolicy {
7
+ protected rules: ICustomRule[];
8
+ constructor(dependencies: SeoDependencies);
6
9
  protected matchesFilters(): Promise<boolean>;
7
- generatePaths(): string[];
10
+ generateUrls(): Promise<string[]>;
11
+ get filterCombination(): FilterCombinations;
8
12
  }
@@ -1,17 +1,39 @@
1
1
  import { FilterKey } from '@studyportals/search-filters';
2
- import { BaseSeoIndexabilityPolicy } from '@/common/BaseSeoIndexabilityPolicy';
3
- export class CountryPolicy extends BaseSeoIndexabilityPolicy {
4
- constructor(seoInfoBase, filterState) {
5
- super(seoInfoBase, filterState);
2
+ import { FilterCombinations } from '../../enums/FilterCombinations';
3
+ import { SearchVolumeCountriesRule } from '../rules/SearchVolumeCountriesRule';
4
+ import { RuleBasedIndexabilityPolicy } from '../../common/RuleBasedIndexabilityPolicy';
5
+ import { CountryPresenter } from '../../presenters/CountryPresenter';
6
+ export class CountryPolicy extends RuleBasedIndexabilityPolicy {
7
+ rules = [
8
+ SearchVolumeCountriesRule.getInstance()
9
+ ];
10
+ constructor(dependencies) {
11
+ super(dependencies);
6
12
  }
7
13
  async matchesFilters() {
8
- const singleCountrySelected = await this.seoInfoBase.singleSelectionFor(FilterKey.COUNTRY, this.filterState);
9
- const onlyCountrySelected = await this.seoInfoBase.selectionOnlyFor([
14
+ const { seoInfoBase, filterState } = this.dependencies;
15
+ const singleCountrySelected = await seoInfoBase.singleSelectionFor(FilterKey.COUNTRY, filterState);
16
+ const onlyCountrySelected = await seoInfoBase.selectionOnlyFor([
10
17
  FilterKey.COUNTRY
11
- ], this.filterState);
12
- return singleCountrySelected && onlyCountrySelected;
18
+ ], filterState);
19
+ const countrySelected = seoInfoBase.getFilterOptionValueBy(FilterKey.COUNTRY, filterState);
20
+ const hasSearchVolume = this.checksEveryRuleForSearch({
21
+ [FilterKey.COUNTRY]: countrySelected ?? undefined
22
+ });
23
+ return singleCountrySelected
24
+ && onlyCountrySelected
25
+ && hasSearchVolume;
13
26
  }
14
- generatePaths() {
15
- throw new Error('Method not implemented.');
27
+ generateUrls() {
28
+ const countryFragments = CountryPresenter.getInstance().getFragments();
29
+ const paths = countryFragments
30
+ .filter(country => this.checksEveryRuleForSitemap({
31
+ [FilterKey.COUNTRY]: country.id
32
+ }))
33
+ .map(country => country.path);
34
+ return Promise.resolve(paths);
35
+ }
36
+ get filterCombination() {
37
+ return FilterCombinations.COUNTRY;
16
38
  }
17
39
  }
@@ -1,11 +1,12 @@
1
- import { BaseSeoIndexabilityPolicy } from '@/common/BaseSeoIndexabilityPolicy';
2
- import { ISeoSearchApplicationState } from '@/common/ISeoSearchApplicationState';
3
- import { ISeoFilterState } from '@/common/ISeoFilterState';
4
- import { ISeoInfoBase } from '@/common/ISeoInfoBase';
5
- import { ISeoIndexabilityPolicy } from '@/common/ISeoIndexabilityPolicy';
6
- export declare class DisciplineCountryPolicy extends BaseSeoIndexabilityPolicy implements ISeoIndexabilityPolicy {
7
- private applicationState;
8
- constructor(seoInfoBase: ISeoInfoBase, filterState: ISeoFilterState, applicationState: ISeoSearchApplicationState);
1
+ import { ISeoIndexabilityPolicy } from '../../common/ISeoIndexabilityPolicy';
2
+ import { FilterCombinations } from '../../enums/FilterCombinations';
3
+ import { SeoDependencies } from '../../types/SeoDependencies';
4
+ import { RuleBasedIndexabilityPolicy } from '../../common/RuleBasedIndexabilityPolicy';
5
+ import { ICustomRule } from '../../common/ICustomRule';
6
+ export declare class DisciplineCountryPolicy extends RuleBasedIndexabilityPolicy implements ISeoIndexabilityPolicy {
7
+ protected rules: ICustomRule[];
8
+ constructor(dependencies: SeoDependencies);
9
9
  protected matchesFilters(): Promise<boolean>;
10
- generatePaths(): string[];
10
+ generateUrls(): Promise<string[]>;
11
+ get filterCombination(): FilterCombinations;
11
12
  }
@@ -1,26 +1,54 @@
1
1
  import { FilterKey } from '@studyportals/search-filters';
2
- import { BaseSeoIndexabilityPolicy } from '@/common/BaseSeoIndexabilityPolicy';
3
- import { CustomRules } from '../CustomRules';
4
- export class DisciplineCountryPolicy extends BaseSeoIndexabilityPolicy {
5
- applicationState;
6
- constructor(seoInfoBase, filterState, applicationState) {
7
- super(seoInfoBase, filterState);
8
- this.applicationState = applicationState;
2
+ import { FilterCombinations } from '../../enums/FilterCombinations';
3
+ import { RuleBasedIndexabilityPolicy } from '../../common/RuleBasedIndexabilityPolicy';
4
+ import { SearchVolumeCountriesDisciplinesRule } from '../rules/SearchVolumeCountryDisciplineRule';
5
+ import { CountryPresenter } from '../../presenters/CountryPresenter';
6
+ export class DisciplineCountryPolicy extends RuleBasedIndexabilityPolicy {
7
+ rules = [
8
+ SearchVolumeCountriesDisciplinesRule.getInstance()
9
+ ];
10
+ constructor(dependencies) {
11
+ super(dependencies);
9
12
  }
10
13
  async matchesFilters() {
11
- const singleDisciplineSelected = await this.seoInfoBase.singleSelectionFor(FilterKey.DISCIPLINES, this.filterState);
12
- const singleCountrySelected = await this.seoInfoBase.singleSelectionFor(FilterKey.COUNTRY, this.filterState);
13
- const onlyDisciplineAndCountrySelected = await this.seoInfoBase.selectionOnlyFor([
14
+ const { seoInfoBase, filterState, applicationState } = this.dependencies;
15
+ if (!applicationState) {
16
+ throw new Error('Application State dependencies are missing.');
17
+ }
18
+ const singleDisciplineSelected = await seoInfoBase.singleSelectionFor(FilterKey.DISCIPLINES, filterState);
19
+ const singleCountrySelected = await seoInfoBase.singleSelectionFor(FilterKey.COUNTRY, filterState);
20
+ const onlyDisciplineAndCountrySelected = await seoInfoBase.selectionOnlyFor([
14
21
  FilterKey.DISCIPLINES,
15
22
  FilterKey.COUNTRY
16
- ], this.filterState);
17
- const hasEnoughResults = CustomRules.hasMoreThan31Results(this.applicationState);
23
+ ], filterState);
24
+ const countrySelected = seoInfoBase.getFilterOptionValueBy(FilterKey.COUNTRY, filterState);
25
+ const disciplineSelected = seoInfoBase.getFilterOptionValueBy(FilterKey.DISCIPLINES, filterState);
26
+ const hasSearchVolume = this.checksEveryRuleForSearch({
27
+ [FilterKey.COUNTRY]: countrySelected ?? undefined,
28
+ [FilterKey.DISCIPLINES]: disciplineSelected ?? undefined
29
+ });
18
30
  return singleDisciplineSelected
19
31
  && singleCountrySelected
20
32
  && onlyDisciplineAndCountrySelected
21
- && hasEnoughResults;
33
+ && hasSearchVolume;
22
34
  }
23
- generatePaths() {
24
- throw new Error('Method not implemented.');
35
+ generateUrls() {
36
+ const paths = [];
37
+ const countryFragments = CountryPresenter.getInstance().getFragments();
38
+ const disciplineFragments = CountryPresenter.getInstance().getFragments();
39
+ countryFragments.forEach(country => {
40
+ disciplineFragments.forEach(discipline => {
41
+ if (this.checksEveryRuleForSitemap({
42
+ [FilterKey.COUNTRY]: country.id,
43
+ [FilterKey.DISCIPLINES]: discipline.id
44
+ })) {
45
+ paths.push(`${country.path}/${discipline.path}`);
46
+ }
47
+ });
48
+ });
49
+ return Promise.resolve(paths);
50
+ }
51
+ get filterCombination() {
52
+ return FilterCombinations.DISCIPLINE_COUNTRY;
25
53
  }
26
54
  }
@@ -1,8 +1,12 @@
1
- import { BaseSeoIndexabilityPolicy } from '@/common/BaseSeoIndexabilityPolicy';
2
- import { ISeoFilterState } from '@/common/ISeoFilterState';
3
- import { ISeoInfoBase } from '@/common/ISeoInfoBase';
4
- export declare class DisciplinePolicy extends BaseSeoIndexabilityPolicy {
5
- constructor(seoInfoBase: ISeoInfoBase, filterState: ISeoFilterState);
1
+ import { SeoDependencies } from '../../types/SeoDependencies';
2
+ import { ICustomRule } from '../../common/ICustomRule';
3
+ import { ISeoIndexabilityPolicy } from '../../common/ISeoIndexabilityPolicy';
4
+ import { FilterCombinations } from '../../enums/FilterCombinations';
5
+ import { RuleBasedIndexabilityPolicy } from '../../common/RuleBasedIndexabilityPolicy';
6
+ export declare class DisciplinePolicy extends RuleBasedIndexabilityPolicy implements ISeoIndexabilityPolicy {
7
+ protected rules: ICustomRule[];
8
+ constructor(dependencies: SeoDependencies);
6
9
  protected matchesFilters(): Promise<boolean>;
7
- generatePaths(): string[];
10
+ generateUrls(): Promise<string[]>;
11
+ get filterCombination(): FilterCombinations;
8
12
  }
@@ -1,17 +1,40 @@
1
1
  import { FilterKey } from '@studyportals/search-filters';
2
- import { BaseSeoIndexabilityPolicy } from '@/common/BaseSeoIndexabilityPolicy';
3
- export class DisciplinePolicy extends BaseSeoIndexabilityPolicy {
4
- constructor(seoInfoBase, filterState) {
5
- super(seoInfoBase, filterState);
2
+ import { DisciplinePresenter } from '../../presenters/DisciplinePresenter';
3
+ import { SearchVolumeDisciplinesRule } from '../../scholarships/rules/SearchVolumeDisciplinesRule';
4
+ import { FilterCombinations } from '../../enums/FilterCombinations';
5
+ import { RuleBasedIndexabilityPolicy } from '../../common/RuleBasedIndexabilityPolicy';
6
+ export class DisciplinePolicy extends RuleBasedIndexabilityPolicy {
7
+ rules;
8
+ constructor(dependencies) {
9
+ super(dependencies);
10
+ this.rules = [
11
+ SearchVolumeDisciplinesRule.getInstance(),
12
+ ];
6
13
  }
7
14
  async matchesFilters() {
8
- const singleDisciplineSelected = await this.seoInfoBase.singleSelectionFor(FilterKey.DISCIPLINES, this.filterState);
9
- const onlyDisciplineSelected = await this.seoInfoBase.selectionOnlyFor([
15
+ const { seoInfoBase, filterState } = this.dependencies;
16
+ const singleDisciplineSelected = await seoInfoBase.singleSelectionFor(FilterKey.DISCIPLINES, filterState);
17
+ const onlyDisciplineSelected = await seoInfoBase.selectionOnlyFor([
10
18
  FilterKey.DISCIPLINES
11
- ], this.filterState);
12
- return singleDisciplineSelected && onlyDisciplineSelected;
19
+ ], filterState);
20
+ const disciplineSelected = seoInfoBase.getFilterOptionValueBy(FilterKey.DISCIPLINES, filterState);
21
+ const hasSearchVolume = this.checksEveryRuleForSearch({
22
+ [FilterKey.DISCIPLINES]: disciplineSelected ?? undefined
23
+ });
24
+ return singleDisciplineSelected
25
+ && onlyDisciplineSelected
26
+ && hasSearchVolume;
13
27
  }
14
- generatePaths() {
15
- throw new Error('Method not implemented.');
28
+ generateUrls() {
29
+ const disciplineFragments = DisciplinePresenter.getInstance().getFragments();
30
+ const paths = disciplineFragments
31
+ .filter(discipline => this.checksEveryRuleForSitemap({
32
+ [FilterKey.DISCIPLINES]: discipline.id
33
+ }))
34
+ .map(discipline => discipline.path);
35
+ return Promise.resolve(paths);
36
+ }
37
+ get filterCombination() {
38
+ return FilterCombinations.DISCIPLINE;
16
39
  }
17
40
  }
@@ -1,8 +1,9 @@
1
- import { ISeoInfoBase } from '@/common/ISeoInfoBase';
2
- import { ISeoFilterState } from '@/common/ISeoFilterState';
3
- import { BaseSeoIndexabilityPolicy } from '@/common/BaseSeoIndexabilityPolicy';
1
+ import { BaseSeoIndexabilityPolicy } from '../../common/BaseSeoIndexabilityPolicy';
2
+ import { SeoDependencies } from '../../types/SeoDependencies';
3
+ import { FilterCombinations } from '../../enums/FilterCombinations';
4
4
  export declare class UnfilteredPolicy extends BaseSeoIndexabilityPolicy {
5
- constructor(seoInfoBase: ISeoInfoBase, filterState: ISeoFilterState);
5
+ constructor(dependencies: SeoDependencies);
6
6
  protected matchesFilters(): Promise<boolean>;
7
- generatePaths(): string[];
7
+ generateUrls(): Promise<string[]>;
8
+ get filterCombination(): FilterCombinations;
8
9
  }
@@ -1,12 +1,17 @@
1
- import { BaseSeoIndexabilityPolicy } from '@/common/BaseSeoIndexabilityPolicy';
1
+ import { BaseSeoIndexabilityPolicy } from '../../common/BaseSeoIndexabilityPolicy';
2
+ import { FilterCombinations } from '../../enums/FilterCombinations';
2
3
  export class UnfilteredPolicy extends BaseSeoIndexabilityPolicy {
3
- constructor(seoInfoBase, filterState) {
4
- super(seoInfoBase, filterState);
4
+ constructor(dependencies) {
5
+ super(dependencies);
5
6
  }
6
7
  async matchesFilters() {
7
- return Promise.resolve(this.seoInfoBase.getSelectionTypeCount(this.filterState) === 0);
8
+ const { seoInfoBase, filterState } = this.dependencies;
9
+ return Promise.resolve(seoInfoBase.getSelectionTypeCount(filterState) === 0);
8
10
  }
9
- generatePaths() {
10
- throw new Error('Method not implemented.');
11
+ generateUrls() {
12
+ return Promise.resolve(['/']);
13
+ }
14
+ get filterCombination() {
15
+ return FilterCombinations.UNFILTERED;
11
16
  }
12
17
  }
@@ -1,8 +1,9 @@
1
- import { BaseSeoIndexabilityPolicy } from '@/common/BaseSeoIndexabilityPolicy';
2
- import { ISeoFilterState } from '@/common/ISeoFilterState';
3
- import { ISeoInfoBase } from '@/common/ISeoInfoBase';
1
+ import { BaseSeoIndexabilityPolicy } from '../../common/BaseSeoIndexabilityPolicy';
2
+ import { FilterCombinations } from '../../enums/FilterCombinations';
3
+ import { SeoDependencies } from '../../types/SeoDependencies';
4
4
  export declare class UniversityCountryPolicy extends BaseSeoIndexabilityPolicy {
5
- constructor(seoInfoBase: ISeoInfoBase, filterState: ISeoFilterState);
5
+ constructor(dependencies: SeoDependencies);
6
6
  protected matchesFilters(): Promise<boolean>;
7
- generatePaths(): string[];
7
+ generateUrls(): Promise<string[]>;
8
+ get filterCombination(): FilterCombinations;
8
9
  }
@@ -1,21 +1,47 @@
1
1
  import { FilterKey } from '@studyportals/search-filters';
2
- import { BaseSeoIndexabilityPolicy } from '@/common/BaseSeoIndexabilityPolicy';
2
+ import { BaseSeoIndexabilityPolicy } from '../../common/BaseSeoIndexabilityPolicy';
3
+ import { FilterCombinations } from '../../enums/FilterCombinations';
4
+ import { CountryPresenter } from '../../presenters/CountryPresenter';
3
5
  export class UniversityCountryPolicy extends BaseSeoIndexabilityPolicy {
4
- constructor(seoInfoBase, filterState) {
5
- super(seoInfoBase, filterState);
6
+ constructor(dependencies) {
7
+ super(dependencies);
6
8
  }
7
9
  async matchesFilters() {
8
- const singleUniversitySelected = await this.seoInfoBase.singleSelectionFor(FilterKey.ORGANISATIONS, this.filterState);
9
- const singleCountrySelected = await this.seoInfoBase.singleSelectionFor(FilterKey.COUNTRY, this.filterState);
10
- const onlyUniversityAndDisciplineSelected = await this.seoInfoBase.selectionOnlyFor([
10
+ const { seoInfoBase, filterState } = this.dependencies;
11
+ const singleUniversitySelected = await seoInfoBase.singleSelectionFor(FilterKey.ORGANISATIONS, filterState);
12
+ const singleCountrySelected = await seoInfoBase.singleSelectionFor(FilterKey.COUNTRY, filterState);
13
+ const onlyUniversityAndDisciplineSelected = await seoInfoBase.selectionOnlyFor([
11
14
  FilterKey.ORGANISATIONS,
12
15
  FilterKey.COUNTRY
13
- ], this.filterState);
16
+ ], filterState);
14
17
  return singleUniversitySelected
15
18
  && singleCountrySelected
16
19
  && onlyUniversityAndDisciplineSelected;
17
20
  }
18
- generatePaths() {
19
- throw new Error('Method not implemented.');
21
+ async generateUrls() {
22
+ const { searchApiClient, organisationsClient } = this.dependencies;
23
+ if (!searchApiClient || !organisationsClient) {
24
+ throw new Error('Search API Client or Organisation Client dependencies are missing.');
25
+ }
26
+ const organisationIds = await searchApiClient.getOrganisationIds();
27
+ const organisations = await organisationsClient.getOrganisations(organisationIds);
28
+ const isoToPath = new Map();
29
+ const countries = CountryPresenter.getInstance().getFragments();
30
+ countries.forEach(country => {
31
+ isoToPath.set(country.id, country.path);
32
+ });
33
+ const paths = [];
34
+ organisations.forEach(org => {
35
+ org.countryIsoCodes.forEach(iso => {
36
+ const countryVirtualPath = isoToPath.get(iso);
37
+ if (countryVirtualPath) {
38
+ paths.push(`/${countryVirtualPath}/${org.virtualPath}`);
39
+ }
40
+ });
41
+ });
42
+ return Promise.resolve(paths);
43
+ }
44
+ get filterCombination() {
45
+ return FilterCombinations.UNIVERSITY_COUNTRY;
20
46
  }
21
47
  }
@@ -0,0 +1,14 @@
1
+ import { ICustomRule } from "../../common/ICustomRule";
2
+ import { IFilterKeyValues } from "../../common/IFilterKeyValues";
3
+ export declare class ExceptAustraliaAreasRule implements ICustomRule {
4
+ private areasPresenter;
5
+ private static instance;
6
+ private australiaCountryId;
7
+ private constructor();
8
+ static getInstance(): ExceptAustraliaAreasRule;
9
+ forSearch(filterSet: IFilterKeyValues): boolean;
10
+ forSitemapGenerator(filterKeyValues: IFilterKeyValues): boolean;
11
+ getName(): string;
12
+ private isNotAustralia;
13
+ private doesNotBelongToAustralia;
14
+ }
@@ -0,0 +1,45 @@
1
+ import { AreaPresenter } from "../../presenters/AreaPresenter";
2
+ import { FilterKey } from "@studyportals/search-filters";
3
+ export class ExceptAustraliaAreasRule {
4
+ areasPresenter;
5
+ static instance;
6
+ australiaCountryId = 202;
7
+ constructor() {
8
+ this.areasPresenter = AreaPresenter.getInstance();
9
+ }
10
+ static getInstance() {
11
+ if (!ExceptAustraliaAreasRule.instance) {
12
+ ExceptAustraliaAreasRule.instance = new ExceptAustraliaAreasRule();
13
+ }
14
+ return ExceptAustraliaAreasRule.instance;
15
+ }
16
+ forSearch(filterSet) {
17
+ const value = filterSet[FilterKey.AREA];
18
+ if (!value) {
19
+ return false;
20
+ }
21
+ return this.doesNotBelongToAustralia(value);
22
+ }
23
+ forSitemapGenerator(filterKeyValues) {
24
+ const value = filterKeyValues[FilterKey.COUNTRY];
25
+ if (!value) {
26
+ throw new Error(`Invalid filter provided or undefined value.`);
27
+ }
28
+ return this.isNotAustralia(value);
29
+ }
30
+ getName() {
31
+ return 'ExceptAustraliaAreasRule';
32
+ }
33
+ isNotAustralia(countryId) {
34
+ return countryId !== this.australiaCountryId.toString();
35
+ }
36
+ doesNotBelongToAustralia(filterId) {
37
+ const areas = this.areasPresenter.getFragments();
38
+ const foundArea = areas.find((area) => area.id === filterId);
39
+ // TODO: This condition is not correct, decide what to do
40
+ if (!foundArea) {
41
+ return false;
42
+ }
43
+ return foundArea.countryId !== this.australiaCountryId.toString();
44
+ }
45
+ }
@@ -0,0 +1,12 @@
1
+ import { ICustomRule } from "../../common/ICustomRule";
2
+ import { IFilterKeyValues } from "../../common/IFilterKeyValues";
3
+ export declare class SearchVolumeAreasRule implements ICustomRule {
4
+ private static instance;
5
+ private areasWithNoSearchVolume;
6
+ private constructor();
7
+ static getInstance(): SearchVolumeAreasRule;
8
+ forSearch(filterSet: IFilterKeyValues): boolean;
9
+ forSitemapGenerator(filterSet: IFilterKeyValues): boolean;
10
+ getName(): string;
11
+ private hasSearchVolume;
12
+ }
@@ -0,0 +1,34 @@
1
+ import { FilterKey } from "@studyportals/search-filters";
2
+ export class SearchVolumeAreasRule {
3
+ static instance;
4
+ areasWithNoSearchVolume;
5
+ constructor() {
6
+ this.areasWithNoSearchVolume = [3579, 995];
7
+ }
8
+ static getInstance() {
9
+ if (!SearchVolumeAreasRule.instance) {
10
+ SearchVolumeAreasRule.instance = new SearchVolumeAreasRule();
11
+ }
12
+ return SearchVolumeAreasRule.instance;
13
+ }
14
+ forSearch(filterSet) {
15
+ const value = filterSet[FilterKey.AREA];
16
+ if (!value) {
17
+ return false;
18
+ }
19
+ return this.hasSearchVolume(value);
20
+ }
21
+ forSitemapGenerator(filterSet) {
22
+ const value = filterSet[FilterKey.AREA];
23
+ if (!value) {
24
+ throw new Error(`Invalid filter provided or undefined value.`);
25
+ }
26
+ return this.hasSearchVolume(value);
27
+ }
28
+ getName() {
29
+ return 'SearchVolumeAreasRule';
30
+ }
31
+ hasSearchVolume(areaId) {
32
+ return !this.areasWithNoSearchVolume.includes(Number(areaId));
33
+ }
34
+ }
@@ -0,0 +1,12 @@
1
+ import { ICustomRule } from "../../common/ICustomRule";
2
+ import { IFilterKeyValues } from "../../common/IFilterKeyValues";
3
+ export declare class SearchVolumeCountriesRule implements ICustomRule {
4
+ private static instance;
5
+ private countriesWithNoSearchVolume;
6
+ private constructor();
7
+ static getInstance(): SearchVolumeCountriesRule;
8
+ forSearch(filterSet: IFilterKeyValues): boolean;
9
+ forSitemapGenerator(filterSet: IFilterKeyValues): boolean;
10
+ getName(): string;
11
+ private hasSearchVolume;
12
+ }
@@ -0,0 +1,34 @@
1
+ import { FilterKey } from "@studyportals/search-filters";
2
+ export class SearchVolumeCountriesRule {
3
+ static instance;
4
+ countriesWithNoSearchVolume;
5
+ constructor() {
6
+ this.countriesWithNoSearchVolume = [122, 107, 18];
7
+ }
8
+ static getInstance() {
9
+ if (!SearchVolumeCountriesRule.instance) {
10
+ SearchVolumeCountriesRule.instance = new SearchVolumeCountriesRule();
11
+ }
12
+ return SearchVolumeCountriesRule.instance;
13
+ }
14
+ forSearch(filterSet) {
15
+ const value = filterSet[FilterKey.COUNTRY];
16
+ if (!value) {
17
+ return false;
18
+ }
19
+ return this.hasSearchVolume(value);
20
+ }
21
+ forSitemapGenerator(filterSet) {
22
+ const value = filterSet[FilterKey.COUNTRY];
23
+ if (!value) {
24
+ return false;
25
+ }
26
+ return this.hasSearchVolume(value);
27
+ }
28
+ getName() {
29
+ return 'SearchVolumeCountriesRule';
30
+ }
31
+ hasSearchVolume(countryId) {
32
+ return !this.countriesWithNoSearchVolume.includes(Number(countryId));
33
+ }
34
+ }
@@ -0,0 +1,12 @@
1
+ import { ICustomRule } from "../../common/ICustomRule";
2
+ import { IFilterKeyValues } from "../../common/IFilterKeyValues";
3
+ export declare class SearchVolumeCountriesDisciplinesRule implements ICustomRule {
4
+ private static instance;
5
+ private combinationsWithSearchVolume;
6
+ private constructor();
7
+ static getInstance(): SearchVolumeCountriesDisciplinesRule;
8
+ forSearch(filterSet: IFilterKeyValues): boolean;
9
+ forSitemapGenerator(filterSet: IFilterKeyValues): boolean;
10
+ getName(): string;
11
+ private hasSearchVolume;
12
+ }
@@ -0,0 +1,37 @@
1
+ import searchVolume from './files/search-volume.json';
2
+ import { FilterKey } from "@studyportals/search-filters";
3
+ export class SearchVolumeCountriesDisciplinesRule {
4
+ static instance;
5
+ combinationsWithSearchVolume;
6
+ constructor() {
7
+ this.combinationsWithSearchVolume = new Set(searchVolume.map(({ ci, di }) => `${ci},${di}`));
8
+ }
9
+ static getInstance() {
10
+ if (!SearchVolumeCountriesDisciplinesRule.instance) {
11
+ SearchVolumeCountriesDisciplinesRule.instance = new SearchVolumeCountriesDisciplinesRule();
12
+ }
13
+ return SearchVolumeCountriesDisciplinesRule.instance;
14
+ }
15
+ forSearch(filterSet) {
16
+ const countryValue = filterSet[FilterKey.COUNTRY];
17
+ const disciplineValue = filterSet[FilterKey.DISCIPLINES];
18
+ if (!countryValue || !disciplineValue) {
19
+ return false;
20
+ }
21
+ return this.hasSearchVolume(countryValue, disciplineValue);
22
+ }
23
+ forSitemapGenerator(filterSet) {
24
+ const countryValue = filterSet[FilterKey.COUNTRY];
25
+ const disciplineValue = filterSet[FilterKey.DISCIPLINES];
26
+ if (!countryValue || !disciplineValue) {
27
+ throw new Error(`SitemapGenerator: Invalid filter provided or undefined value.`);
28
+ }
29
+ return this.hasSearchVolume(countryValue, disciplineValue);
30
+ }
31
+ getName() {
32
+ return 'SearchVolumeCountriesDisciplinesRule';
33
+ }
34
+ hasSearchVolume(countryId, disciplineId) {
35
+ return this.combinationsWithSearchVolume.has(`${countryId},${disciplineId}`);
36
+ }
37
+ }
@@ -0,0 +1,12 @@
1
+ import { ICustomRule } from "../../common/ICustomRule";
2
+ import { IFilterKeyValues } from "../../common/IFilterKeyValues";
3
+ export declare class SearchVolumeDisciplinesRule implements ICustomRule {
4
+ private static instance;
5
+ private disciplinesWithNoSearchVolume;
6
+ private constructor();
7
+ static getInstance(): SearchVolumeDisciplinesRule;
8
+ forSearch(filterSet: IFilterKeyValues): boolean;
9
+ forSitemapGenerator(filterSet: IFilterKeyValues): boolean;
10
+ getName(): string;
11
+ private hasSearchVolume;
12
+ }
@@ -0,0 +1,38 @@
1
+ import { FilterKey } from "@studyportals/search-filters";
2
+ export class SearchVolumeDisciplinesRule {
3
+ static instance;
4
+ disciplinesWithNoSearchVolume;
5
+ constructor() {
6
+ this.disciplinesWithNoSearchVolume = [
7
+ 243, 415, 405, 379, 269, 413,
8
+ 408, 274, 411, 401, 381, 390,
9
+ 410, 412, 130
10
+ ];
11
+ }
12
+ static getInstance() {
13
+ if (!SearchVolumeDisciplinesRule.instance) {
14
+ SearchVolumeDisciplinesRule.instance = new SearchVolumeDisciplinesRule();
15
+ }
16
+ return SearchVolumeDisciplinesRule.instance;
17
+ }
18
+ forSearch(filterSet) {
19
+ const value = filterSet[FilterKey.DISCIPLINES];
20
+ if (!value) {
21
+ return false;
22
+ }
23
+ return this.hasSearchVolume(value);
24
+ }
25
+ forSitemapGenerator(filterSet) {
26
+ const value = filterSet[FilterKey.DISCIPLINES];
27
+ if (!value) {
28
+ throw new Error(`Invalid filter provided or undefined value.`);
29
+ }
30
+ return this.hasSearchVolume(value);
31
+ }
32
+ getName() {
33
+ return 'SearchVolumeDisciplinesRule';
34
+ }
35
+ hasSearchVolume(disciplineId) {
36
+ return !this.disciplinesWithNoSearchVolume.includes(Number(disciplineId));
37
+ }
38
+ }