From 5b337987966940019539fd53385e79337106144d Mon Sep 17 00:00:00 2001 From: ajitsinghkaler Date: Thu, 11 Jun 2020 13:49:10 +0300 Subject: [PATCH] feat(docs-infra): created new widget for events page (#36517) Data in events page was hardcoded and it is manually moved in the table. Created a new events widget which will automatically move past and upcoming events from events.json (`aio/content/marketing/events.json`) file to the relevant table in the events tab PR Close #36517 --- aio/content/marketing/events.html | 159 +--------- aio/content/marketing/events.json | 228 ++++++++++++++ .../app/custom-elements/element-registry.ts | 4 + .../events/events.component.html | 43 +++ .../events/events.component.spec.ts | 295 ++++++++++++++++++ .../events/events.component.ts | 102 ++++++ .../custom-elements/events/events.module.ts | 15 + .../events/events.service.spec.ts | 56 ++++ .../custom-elements/events/events.service.ts | 32 ++ .../processors/createSitemap.js | 1 + .../angular-content-package/index.js | 8 +- goldens/size-tracking/aio-payloads.json | 16 +- 12 files changed, 792 insertions(+), 167 deletions(-) create mode 100644 aio/content/marketing/events.json create mode 100644 aio/src/app/custom-elements/events/events.component.html create mode 100644 aio/src/app/custom-elements/events/events.component.spec.ts create mode 100644 aio/src/app/custom-elements/events/events.component.ts create mode 100644 aio/src/app/custom-elements/events/events.module.ts create mode 100644 aio/src/app/custom-elements/events/events.service.spec.ts create mode 100644 aio/src/app/custom-elements/events/events.service.ts diff --git a/aio/content/marketing/events.html b/aio/content/marketing/events.html index d26735865b..df88a61ca2 100755 --- a/aio/content/marketing/events.html +++ b/aio/content/marketing/events.html @@ -3,162 +3,5 @@
-

Where we'll be presenting:

- - - - - - - - - - -
EventLocationDate
- -

Where we already presented:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventLocationDate
ngVikingsOslo, NorwayMay 25-26 conference, 27 workshops, 2020
ng-confSalt Lake City, UtahApril 1-3, 2020
ngIndiaDelhi, IndiaFeb 29, 2020
ReactiveConfPrague, Czech RepublicOctober 30 - November 1, 2019
- NG Rome MMXIX - Rome, ItalyOct 6th workshops, 7th conference, 2019
AngularConnectLondon, UKSeptember 19-20, 2019
NG-DEBerlin, GermanyAugust 29th workshops, 30-31 conference, 2019
ng-japanTokyo, JapanJuly 13, 2019
ngVikingsCopenhagen, DenmarkMay 26 (workshops), 27-28 (conference), 2019
ng-confSalt Lake City, UtahMay 1-3, 2019
ng-IndiaGurgaon, IndiaFebruary 23, 2019
ngAtlantaAtlanta, GeorgiaJanuary 9-12, 2019
- AngularConnect - London, United KingdomNovember 5-7, 2018
ReactiveConfPrague, Czech RepublicOctober 29-31, 2018
AngularMixOrlando, FloridaOctober 10-12, 2018
- Angular Conf Australia - Melbourne, AustraliaJun 22, 2018
ng-japanTokyo, JapanJun 16, 2018
WeAreDevelopersVienna, AustriaMay 16-18, 2018
ng-confSalt Lake City, UtahApril 18-20, 2018
ngVikingsHelsinki, FinlandMarch 1-2, 2018
ngAtlantaAtlanta, GeorgiaJanuary 30, 2018
+
diff --git a/aio/content/marketing/events.json b/aio/content/marketing/events.json new file mode 100644 index 0000000000..7fb45bbc50 --- /dev/null +++ b/aio/content/marketing/events.json @@ -0,0 +1,228 @@ +[ + { + "name": "ngVikings", + "location": "Oslo, Norway", + "linkUrl": "https://ngvikings.org/", + "tooltip": "ngVikings", + "date": { + "start": "2020-05-25", + "end": "2020-05-26" + }, + "workshopsDate": { + "start": "2020-05-27", + "end": "2020-05-27" + } + }, + { + "name": "ng-conf", + "location": "Salt Lake City, Utah", + "linkUrl": "https://ng-conf.org/", + "tooltip": "ng-conf", + "date": { + "start": "2020-04-01", + "end": "2020-04-03" + } + }, + { + "name": "ngIndia", + "location": "Delhi, India", + "linkUrl": "https://www.ng-ind.com/", + "tooltip": "ngIndia", + "date": { + "start": "2020-02-29", + "end": "2020-02-29" + } + }, + { + "name": "ReactiveConf", + "location": "Prague, Czech Republic", + "linkUrl": "https://reactiveconf.com/", + "tooltip": "ReactiveConf", + "date": { + "start": "2019-10-30", + "end": "2019-11-01" + } + }, + { + "name": "NG Rome MMXIX", + "location": "Rome, Italy", + "linkUrl": "https://ngrome.io", + "tooltip": "NG Rome MMXIX - The Italian Angular Conference", + "date": { + "start": "2019-10-07", + "end": "2019-10-07" + }, + "workshopsDate": { + "start": "2019-10-06", + "end": "2019-10-06" + } + }, + { + "name": "AngularConnect", + "location": "London, UK", + "linkUrl": "https://www.angularconnect.com/?utm_source=angular.io&utm_medium=referral", + "tooltip": "AngularConnect", + "date": { + "start": "2019-09-19", + "end": "2019-09-20" + } + }, + { + "name": "NG-DE", + "location": "Berlin, Germany", + "linkUrl": "https://ng-de.org/", + "tooltip": "NG-DE", + "date": { + "start": "2019-08-30", + "end": "2019-08-31" + }, + "workshopsDate": { + "start": "2019-08-29", + "end": "2019-08-29" + } + }, + { + "name": "ng-japan", + "location": "Tokyo, Japan", + "linkUrl": "https://ngjapan.org/", + "tooltip": "ng-japan", + "date": { + "start": "2019-07-13", + "end": "2019-07-13" + } + }, + { + "name": "ngVikings", + "location": "Copenhagen, Denmark", + "linkUrl": "https://ngvikings.org/", + "tooltip": "ngVikings", + "date": { + "start": "2019-05-27", + "end": "2019-05-28" + }, + "workshopsDate": { + "start": "2019-05-26", + "end": "2019-05-26" + } + }, + { + "name": "ng-conf", + "location": "Salt Lake City, Utah", + "linkUrl": "https://ng-conf.org/", + "tooltip": "ng-conf", + "date": { + "start": "2019-05-01", + "end": "2019-05-03" + } + }, + { + "name": "ng-India", + "location": "Gurgaon, India", + "linkUrl": "https://www.ng-ind.com/", + "tooltip": "ng-India", + "date": { + "start": "2019-02-23", + "end": "2019-02-23" + } + }, + { + "name": "ngAtlanta", + "location": "Atlanta, Georgia", + "linkUrl": "https://ng-atl.org/", + "tooltip": "ngAtlanta", + "date": { + "start": "2019-01-09", + "end": "2019-01-12" + } + }, + { + "name": "AngularConnect", + "location": "London, United Kingdom", + "linkUrl": "https://past.angularconnect.com/2018", + "tooltip": "AngularConnect", + "date": { + "start": "2018-11-05", + "end": "2018-11-07" + } + }, + { + "name": "ReactiveConf", + "location": "Prague, Czech Republic", + "linkUrl": "https://reactiveconf.com/", + "tooltip": "ReactiveConf", + "date": { + "start": "2018-10-29", + "end": "2018-10-31" + } + }, + { + "name": "AngularMix", + "location": "Orlando, Florida", + "linkUrl": "https://angularmix.com/", + "tooltip": "AngularMix", + "date": { + "start": "2018-10-10", + "end": "2018-10-12" + } + }, + { + "name": "Angular Conf Australia", + "location": "Melbourne, Australia", + "linkUrl": "https://www.angularconf.com.au/", + "tooltip": "Angular Conf Australia", + "date": { + "start": "2018-06-22", + "end": "2018-06-22" + } + }, + { + "name": "ng-japan", + "location": "Tokyo, Japan", + "linkUrl": "https://ngjapan.org/en.html", + "tooltip": "ng-japan", + "date": { + "start": "2018-06-16", + "end": "2018-06-16" + } + }, + { + "name": "WeAreDevelopers", + "location": "Vienna, Austria", + "linkUrl": "https://www.wearedevelopers.com/", + "tooltip": "WeAreDevs", + "date": { + "start": "2018-05-16", + "end": "2018-05-18" + } + }, + { + "name": "ng-conf", + "location": "Salt Lake City, Utah", + "linkUrl": "https://ng-conf.org/", + "tooltip": "ng-conf", + "date": { + "start": "2018-04-18", + "end": "2018-04-20" + } + }, + { + "name": "ngVikings", + "location": "Helsinki, Finland", + "linkUrl": "https://ngvikings.org/", + "tooltip": "ngVikings", + "date": { + "start": "2018-03-01", + "end": "2018-03-02" + } + }, + { + "name": "ngAtlanta", + "location": "Atlanta, Georgia", + "linkUrl": "https://ng-atl.org/", + "tooltip": "ngAtlanta", + "date": { + "start": "2018-01-30", + "end": "2018-01-30" + } + } +] \ No newline at end of file diff --git a/aio/src/app/custom-elements/element-registry.ts b/aio/src/app/custom-elements/element-registry.ts index 57b12bf5ea..be4036687f 100644 --- a/aio/src/app/custom-elements/element-registry.ts +++ b/aio/src/app/custom-elements/element-registry.ts @@ -40,6 +40,10 @@ export const ELEMENT_MODULE_LOAD_CALLBACKS_AS_ROUTES = [ { selector: 'live-example', loadChildren: () => import('./live-example/live-example.module').then(m => m.LiveExampleModule) + }, + { + selector: 'aio-events', + loadChildren: () => import('./events/events.module').then(m => m.EventsModule) } ]; diff --git a/aio/src/app/custom-elements/events/events.component.html b/aio/src/app/custom-elements/events/events.component.html new file mode 100644 index 0000000000..17e5f10b22 --- /dev/null +++ b/aio/src/app/custom-elements/events/events.component.html @@ -0,0 +1,43 @@ +

Where we'll be presenting:

+ + + + + + + + + + + + + + + +
EventLocationDate
{{event.name}}{{event.location}} +
+ {{getEventDates(event)}} +
+
+ +

Where we already presented:

+ + + + + + + + + + + + + + + +
EventLocationDate
{{event.name}}{{event.location}} +
+ {{getEventDates(event)}} +
+
diff --git a/aio/src/app/custom-elements/events/events.component.spec.ts b/aio/src/app/custom-elements/events/events.component.spec.ts new file mode 100644 index 0000000000..6f6f094c01 --- /dev/null +++ b/aio/src/app/custom-elements/events/events.component.spec.ts @@ -0,0 +1,295 @@ +import { EventsComponent } from './events.component'; +import { EventsService } from './events.service'; +import { Event } from './events.component'; +import { ReflectiveInjector } from '@angular/core'; +import { Subject } from 'rxjs'; + +describe('EventsComponent', () => { + let component: EventsComponent; + let injector: ReflectiveInjector; + let eventsService: TestEventService; + + beforeEach(() => { + injector = ReflectiveInjector.resolveAndCreate([ + EventsComponent, + {provide: EventsService, useClass: TestEventService }, + ]); + eventsService = injector.get(EventsService) as any; + component = injector.get(EventsComponent); + component.ngOnInit(); + }); + + it('should have no pastEvents when first created', () => { + expect(component.pastEvents).toBeUndefined(); + }); + + it('should have no upcoming when first created', () => { + expect(component.upcomingEvents).toBeUndefined(); + }); + + describe('ngOnInit', () => { + it('should have 2 upcoming events', () => { + eventsService.events.next([{ + 'location': 'Oslo, Norway', + 'tooltip': 'ngVikings', + 'linkUrl': 'https://ngvikings.org/', + 'name': 'ngVikings', + 'date': { + 'start': '2099-07-25', + 'end': '2099-07-26' + }, + 'workshopsDate': { + 'start': '2099-07-27', + 'end': '2099-07-27' + } + }, + { + 'location': 'Salt Lake City, Utah', + 'tooltip': 'ng-conf', + 'linkUrl': 'https://ng-conf.org/', + 'name': 'ng-conf ', + 'date': { + 'start': '2099-06-20', + 'end': '2099-06-20' + } + }, + { + 'location': 'Delhi, India', + 'tooltip': 'ngIndia', + 'linkUrl': 'https://www.ng-ind.com/', + 'name': 'ngIndia', + 'date': { + 'start': '2020-02-29', + 'end': '2020-02-29' + } + }]); + expect(component.upcomingEvents.length).toEqual(2); + }); + + it('should have 4 past events', () => { + eventsService.events.next([ + { + 'location': 'Salt Lake City, Utah', + 'tooltip': 'ng-conf', + 'linkUrl': 'https://ng-conf.org/', + 'name': 'ng-conf ', + 'date': { + 'start': '2099-06-20', + 'end': '2099-06-20' + } + }, + { + 'location': 'Rome, Italy', + 'tooltip': 'NG Rome MMXIX - The Italian Angular Conference', + 'linkUrl': 'https://ngrome.io', + 'name': 'NG Rome MMXIX', + 'date': { + 'start': '2019-10-07', + 'end': '2019-10-07' + }, + 'workshopsDate': { + 'start': '2019-10-06', + 'end': '2019-10-06' + } + }, + { + 'location': 'London, UK', + 'tooltip': 'AngularConnect', + 'linkUrl': 'https://www.angularconnect.com/?utm_source=angular.io&utm_medium=referral', + 'name': 'AngularConnect', + 'date': { + 'start': '2019-09-19', + 'end': '2019-09-20' + } + }, + { + 'location': 'Berlin, Germany', + 'tooltip': 'NG-DE', + 'linkUrl': 'https://ng-de.org/', + 'name': 'NG-DE', + 'date': { + 'start': '2019-08-30', + 'end': '2019-08-31' + }, + 'workshopsDate': { + 'start': '2019-08-29', + 'end': '2019-08-29' + } + }, + { + 'location': 'Oslo, Norway', + 'tooltip': 'ngVikings', + 'linkUrl': 'https://ngvikings.org/', + 'name': 'ngVikings', + 'date': { + 'start': '2018-07-26', + 'end': '2018-07-26' + }, + 'workshopsDate': { + 'start': '2018-07-27', + 'end': '2018-07-27' + } + }]); + expect(component.pastEvents.length).toEqual(4); + }); + }); + + describe('Getting event dates if no workshop date', () => { + it('should return only conference date', () => { + const datestring = component.getEventDates({ + 'location': 'Salt Lake City, Utah', + 'tooltip': 'ng-conf', + 'linkUrl': 'https://ng-conf.org/', + 'name': 'ng-conf ', + 'date': { + 'start': '2020-06-20', + 'end': '2020-06-20' + } + }); + expect(datestring).toEqual('June 20, 2020'); + }); + + it('should return only conference date with changing months if date is in two diffrent months', () => { + const datestring = component.getEventDates({ + 'location': 'Prague, Czech Republic', + 'tooltip': 'ReactiveConf', + 'linkUrl': 'https://reactiveconf.com/', + 'name': 'ReactiveConf', + 'date': { + 'start': '2019-10-30', + 'end': '2019-11-01' + } + }); + expect(datestring).toEqual('October 30 - November 1, 2019'); + }); + + it('should return only conference date with "- lastdate" if conference over multiple days', () => { + const datestring = component.getEventDates({ + 'location': 'London, UK', + 'tooltip': 'AngularConnect', + 'linkUrl': 'https://www.angularconnect.com/?utm_source=angular.io&utm_medium=referral', + 'name': 'AngularConnect', + 'date': { + 'start': '2019-09-19', + 'end': '2019-09-20' + } + }); + expect(datestring).toEqual('September 19-20, 2019'); + }); + }); + + describe('Getting event dates if workshop date', () => { + it('should return conference date with different days, workshopdate', () => { + const datestring = component.getEventDates({ + 'location': 'Oslo, Norway', + 'tooltip': 'ngVikings', + 'linkUrl': 'https://ngvikings.org/', + 'name': 'ngVikings', + 'date': { + 'start': '2020-07-25', + 'end': '2020-07-26' + }, + 'workshopsDate': { + 'start': '2020-07-27', + 'end': '2020-07-27' + } + }); + expect(datestring).toEqual('July 25-26 (conference), July 27 (workshops), 2020'); + }); + + it('should return workshop date, conference date if workshop before conf date', () => { + const datestring = component.getEventDates({ + 'location': 'Rome, Italy', + 'tooltip': 'NG Rome MMXIX - The Italian Angular Conference', + 'linkUrl': 'https://ngrome.io', + 'name': 'NG Rome MMXIX', + 'date': { + 'start': '2019-10-07', + 'end': '2019-10-07' + }, + 'workshopsDate': { + 'start': '2019-10-06', + 'end': '2019-10-06' + } + }); + expect(datestring).toEqual('October 6 (workshops), October 7 (conference), 2019'); + }); + + it('should return workshop date, conference date if workshop before conference date', () => { + const datestring = component.getEventDates({ + 'location': 'Berlin, Germany', + 'tooltip': 'NG-DE', + 'linkUrl': 'https://ng-de.org/', + 'name': 'NG-DE', + 'date': { + 'start': '2019-08-30', + 'end': '2019-08-31' + }, + 'workshopsDate': { + 'start': '2019-08-29', + 'end': '2019-08-29' + } + }); + expect(datestring).toEqual('August 29 (workshops), August 30-31 (conference), 2019'); + }); + + it('should return only conference date, wokshop date if workshop after conference', () => { + const datestring = component.getEventDates({ + 'location': 'Oslo, Norway', + 'tooltip': 'ngVikings', + 'linkUrl': 'https://ngvikings.org/', + 'name': 'ngVikings', + 'date': { + 'start': '2018-07-26', + 'end': '2018-07-26' + }, + 'workshopsDate': { + 'start': '2018-07-27', + 'end': '2018-07-27' + } + }); + expect(datestring).toEqual('July 26 (conference), July 27 (workshops), 2018'); + }); + + it('should return conference date and workshop date with different days and months, starting with confrence date', () => { + const datestring = component.getEventDates({ + 'location': 'Oslo, Norway', + 'tooltip': 'ngVikings', + 'linkUrl': 'https://ngvikings.org/', + 'name': 'ngVikings', + 'date': { + 'start': '2020-07-30', + 'end': '2020-07-31' + }, + 'workshopsDate': { + 'start': '2020-08-01', + 'end': '2020-08-02' + } + }); + expect(datestring).toEqual('July 30-31 (conference), August 1-2 (workshops), 2020'); + }); + + it('should return conference date and workshop date with different days and months, starting with workshopdate', () => { + const datestring = component.getEventDates({ + 'location': 'Oslo, Norway', + 'tooltip': 'ngVikings', + 'linkUrl': 'https://ngvikings.org/', + 'name': 'ngVikings', + 'date': { + 'start': '2020-08-01', + 'end': '2020-08-02' + }, + 'workshopsDate': { + 'start': '2020-07-30', + 'end': '2020-07-31' + } + }); + expect(datestring).toEqual('July 30-31 (workshops), August 1-2 (conference), 2020'); + }); + + }); +}); + +class TestEventService { + events = new Subject(); +} diff --git a/aio/src/app/custom-elements/events/events.component.ts b/aio/src/app/custom-elements/events/events.component.ts new file mode 100644 index 0000000000..54912a38e1 --- /dev/null +++ b/aio/src/app/custom-elements/events/events.component.ts @@ -0,0 +1,102 @@ +import { Component, OnInit } from '@angular/core'; + +import { EventsService } from './events.service'; + +const DAY = 24 * 60 * 60 * 1000; +const MONTHS = [ + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December', +]; + +type date = string; // of the format `YYYY-MM-DD`. +interface Duration { + start: date; + end: date; +} + +export interface Event { + name: string; + location: string; + linkUrl: string; + tooltip?: string; + date: Duration; + workshopsDate?: Duration; +} + +@Component({ + selector: 'aio-events', + templateUrl: 'events.component.html' +}) +export class EventsComponent implements OnInit { + + pastEvents: Event[]; + upcomingEvents: Event[]; + + constructor(private eventsService: EventsService) { } + + ngOnInit() { + this.eventsService.events.subscribe(events => { + this.pastEvents = events + .filter(event => new Date(event.date.end).getTime() < Date.now() - DAY) + .sort((l: Event, r: Event) => isBefore(l.date, r.date) ? 1 : -1); + + this.upcomingEvents = events + .filter(event => new Date(event.date.end).getTime() >= Date.now() - DAY) + .sort((l: Event, r: Event) => isBefore(l.date, r.date) ? -1 : 1); + }); + } + + getEventDates(event: Event) { + let dateString; + + // Check if there is a workshop + if (event.workshopsDate) { + const mainEventDateString = `${processDate(event.date)} (conference)`; + const workshopsDateString = `${processDate(event.workshopsDate)} (workshops)`; + const areWorkshopsBeforeEvent = isBefore(event.workshopsDate, event.date); + + dateString = areWorkshopsBeforeEvent ? + `${workshopsDateString}, ${mainEventDateString}` : + `${mainEventDateString}, ${workshopsDateString}`; + } else { + // If no work shop date create conference date string + dateString = processDate(event.date); + } + dateString = `${dateString}, ${new Date(event.date.end).getFullYear()}`; + return dateString; + } +} + +function processDate(dates: Duration) { + // Covert Date sting to date object for comparisons + const startDate = new Date(dates.start); + const endDate = new Date(dates.end); + + // Create a date string in the start like January 31 + let processedDate = `${MONTHS[startDate.getMonth()]} ${startDate.getDate()}`; + + // If they are in different months add the string '- February 2' Making the final string January 31 - February 2 + if (startDate.getMonth() !== endDate.getMonth()) { + processedDate = `${processedDate} - ${MONTHS[endDate.getMonth()]} ${endDate.getDate()}`; + } else if (startDate.getDate() !== endDate.getDate()) { + // If not add - date eg it will make // January 30-31 + processedDate = `${processedDate}-${endDate.getDate()}`; + } + + return processedDate; +} + +function isBefore(duration1: Duration, duration2: Duration): boolean { + return (duration1.start < duration2.start) || + (duration1.start === duration2.start && duration1.end < duration2.end); +} diff --git a/aio/src/app/custom-elements/events/events.module.ts b/aio/src/app/custom-elements/events/events.module.ts new file mode 100644 index 0000000000..04803e7e6a --- /dev/null +++ b/aio/src/app/custom-elements/events/events.module.ts @@ -0,0 +1,15 @@ +import { NgModule, Type } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { EventsComponent } from './events.component'; +import { EventsService } from './events.service'; +import { WithCustomElementComponent } from '../element-registry'; + +@NgModule({ + imports: [ CommonModule ], + declarations: [ EventsComponent ], + entryComponents: [ EventsComponent ], + providers: [ EventsService] +}) +export class EventsModule implements WithCustomElementComponent { + customElementComponent: Type = EventsComponent; +} diff --git a/aio/src/app/custom-elements/events/events.service.spec.ts b/aio/src/app/custom-elements/events/events.service.spec.ts new file mode 100644 index 0000000000..5102e01703 --- /dev/null +++ b/aio/src/app/custom-elements/events/events.service.spec.ts @@ -0,0 +1,56 @@ +import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; +import { Injector } from '@angular/core'; +import { TestBed } from '@angular/core/testing'; + +import { EventsService } from './events.service'; +import { Logger } from 'app/shared/logger.service'; +import { MockLogger } from 'testing/logger.service'; + +describe('EventsService', () => { + + let injector: Injector; + let eventsService: EventsService; + let httpMock: HttpTestingController; + let mockLogger: MockLogger; + + beforeEach(() => { + injector = TestBed.configureTestingModule({ + imports: [HttpClientTestingModule], + providers: [ + EventsService, + { provide: Logger, useClass: MockLogger } + ] + }); + + eventsService = injector.get(EventsService); + mockLogger = injector.get(Logger) as any; + httpMock = injector.get(HttpTestingController); + }); + + afterEach(() => httpMock.verify()); + + it('should make a single connection to the server', () => { + eventsService.events.subscribe(); + eventsService.events.subscribe(); + httpMock.expectOne('generated/events.json'); + expect().nothing(); // Prevent jasmine from complaining about no expectations. + }); + + it('should handle a failed request for `events.json`', () => { + const request = httpMock.expectOne('generated/events.json'); + request.error(new ErrorEvent('404')); + expect(mockLogger.output.error).toEqual([ + [jasmine.any(Error)] + ]); + expect(mockLogger.output.error[0][0].message).toMatch(/^generated\/events\.json request failed:/); + }); + + it('should return an empty array on a failed request for `events.json`', done => { + const request = httpMock.expectOne('generated/events.json'); + request.error(new ErrorEvent('404')); + eventsService.events.subscribe(results => { + expect(results).toEqual([]); + done(); + }); + }); +}); diff --git a/aio/src/app/custom-elements/events/events.service.ts b/aio/src/app/custom-elements/events/events.service.ts new file mode 100644 index 0000000000..c4d8ecd0e2 --- /dev/null +++ b/aio/src/app/custom-elements/events/events.service.ts @@ -0,0 +1,32 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; + +import { ConnectableObservable, Observable, of } from 'rxjs'; +import { catchError, publishLast } from 'rxjs/operators'; + +import { Event } from './events.component'; +import { CONTENT_URL_PREFIX } from 'app/documents/document.service'; +import { Logger } from 'app/shared/logger.service'; + +const eventsPath = CONTENT_URL_PREFIX + 'events.json'; + +@Injectable() +export class EventsService { + events: Observable; + + constructor(private http: HttpClient, private logger: Logger) { + this.events = this.getEvents(); + } + + private getEvents() { + const events = this.http.get(eventsPath).pipe( + catchError(error => { + this.logger.error(new Error(`${eventsPath} request failed: ${error.message}`)); + return of([]); + }), + publishLast() + ); + (events as ConnectableObservable).connect(); + return events; + } +} diff --git a/aio/tools/transforms/angular-base-package/processors/createSitemap.js b/aio/tools/transforms/angular-base-package/processors/createSitemap.js index e6d320b450..b937ebb83e 100644 --- a/aio/tools/transforms/angular-base-package/processors/createSitemap.js +++ b/aio/tools/transforms/angular-base-package/processors/createSitemap.js @@ -5,6 +5,7 @@ module.exports = function createSitemap() { 'contributors-json', 'navigation-json', 'resources-json', + 'events-json' ], ignoredPaths: [ 'file-not-found', diff --git a/aio/tools/transforms/angular-content-package/index.js b/aio/tools/transforms/angular-content-package/index.js index 65f4de1c38..47d7432ae6 100644 --- a/aio/tools/transforms/angular-content-package/index.js +++ b/aio/tools/transforms/angular-content-package/index.js @@ -82,6 +82,11 @@ module.exports = new Package('angular-content', [basePackage, contentPackage]) include: CONTENTS_PATH + '/marketing/resources.json', fileReader: 'jsonFileReader' }, + { + basePath: CONTENTS_PATH, + include: CONTENTS_PATH + '/marketing/events.json', + fileReader: 'jsonFileReader' + }, ]); collectExamples.exampleFolders.push('examples'); @@ -110,7 +115,8 @@ module.exports = new Package('angular-content', [basePackage, contentPackage]) {docTypes: ['navigation-json'], pathTemplate: '${id}', outputPathTemplate: '../${id}.json'}, {docTypes: ['contributors-json'], pathTemplate: '${id}', outputPathTemplate: '../${id}.json'}, {docTypes: ['announcements-json'], pathTemplate: '${id}', outputPathTemplate: '../${id}.json'}, - {docTypes: ['resources-json'], pathTemplate: '${id}', outputPathTemplate: '../${id}.json'} + {docTypes: ['resources-json'], pathTemplate: '${id}', outputPathTemplate: '../${id}.json'}, + {docTypes: ['events-json'], pathTemplate: '${id}', outputPathTemplate: '../${id}.json'} ]); }) diff --git a/goldens/size-tracking/aio-payloads.json b/goldens/size-tracking/aio-payloads.json index 8ebdb7da24..e41847d91e 100755 --- a/goldens/size-tracking/aio-payloads.json +++ b/goldens/size-tracking/aio-payloads.json @@ -2,8 +2,8 @@ "aio": { "master": { "uncompressed": { - "runtime-es2015": 2987, - "main-es2015": 450880, + "runtime-es2015": 3037, + "main-es2015": 450952, "polyfills-es2015": 52685 } } @@ -11,18 +11,18 @@ "aio-local": { "master": { "uncompressed": { - "runtime-es2015": 2987, - "main-es2015": 448419, - "polyfills-es2015": 52630 + "runtime-es2015": 3037, + "main-es2015": 448493, + "polyfills-es2015": 52415 } } }, "aio-local-viewengine": { "master": { "uncompressed": { - "runtime-es2015": 3097, - "main-es2015": 430239, - "polyfills-es2015": 52195 + "runtime-es2015": 3157, + "main-es2015": 430008, + "polyfills-es2015": 52415 } } }