From 6762089e7cfa411557bf83a63322498d4494e10a Mon Sep 17 00:00:00 2001 From: ijz953 Date: Wed, 13 Mar 2019 01:03:16 -0400 Subject: [PATCH 01/19] docs: update events page with upcoming events --- .../ngrx.io/content/marketing/events.html | 66 +++++++++++++++---- 1 file changed, 53 insertions(+), 13 deletions(-) diff --git a/projects/ngrx.io/content/marketing/events.html b/projects/ngrx.io/content/marketing/events.html index 5f1756cec3..7eb0738c9d 100755 --- a/projects/ngrx.io/content/marketing/events.html +++ b/projects/ngrx.io/content/marketing/events.html @@ -13,19 +13,49 @@

Events

- ngAtlanta - Atlanta, Georgia - January 9 - 12, 2019 + Open Source 101 + Columbia, South Carolina + April 18th, 2019 + + + ng-conf + Salt Lake City, Utah + May 1 - 3rd, 2019 - ng-India - Gurgaon, India - February 23, 2019 + ngVikings + Copenhagen, Denmark + May 26 - 28th, 2019 - ng-conf - Salt Lake City, Utah - May 1 - 3, 2019 + REFACTR.TECH + Atlanta, Georgia + June 5 - 7th, 2019 + + + AngularUP + Tel Aviv, Israel + June 12th, 2019 + + + NG-MY + Kuala Lumpur, Malaysia + July 6 - 7th, 2019 + + + ngDenver + Denver, Colorado + August 1 - 2nd, 2019 + + + AngularConnect + London, United Kingdom + September 19 - 20th, 2019 + + + NG-Rome + Rome, Italy + October 7th, 2019 @@ -46,22 +76,22 @@

Events

DevFestATL - Atlanta, GA + Atlanta, Georgia September 22nd, 2018 Framework Summit - Park City, UT + Park City, Utah September 22nd, 2018 DevFestATL - Atlanta, GA + Atlanta, Georgia October 2 - 3rd, 2018 AngularMix - Use the discount code "RYAN" or "ROBERTS" to receive $50 off your registration! - Orlando, FL + Orlando, Florida October 10 - 12th, 2018 @@ -69,6 +99,16 @@

Events

Excel, London November 6 - 7th, 2018 + + ngAtlanta + Atlanta, Georgia + January 9 - 12th, 2019 + + + ng-India + Gurgaon, India + February 23rd, 2019 + From 6a8ddfe429e7651ab01f93ba2521f8ba7ba086e0 Mon Sep 17 00:00:00 2001 From: ijz953 Date: Wed, 13 Mar 2019 02:17:55 -0400 Subject: [PATCH 02/19] docs: abstract events table into a component to prevent need to update based on passing date --- .../ngrx.io/content/marketing/events.html | 112 +----------------- .../contributor/event-list.component.spec.ts | 105 ++++++++++++++++ .../app/custom-elements/element-registry.ts | 4 + .../events/event-list.component.ts | 76 ++++++++++++ .../events/event-list.module.ts | 13 ++ .../app/custom-elements/events/event.model.ts | 16 +++ 6 files changed, 217 insertions(+), 109 deletions(-) create mode 100644 projects/ngrx.io/src/app/custom-elements/contributor/event-list.component.spec.ts create mode 100644 projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts create mode 100644 projects/ngrx.io/src/app/custom-elements/events/event-list.module.ts create mode 100644 projects/ngrx.io/src/app/custom-elements/events/event.model.ts diff --git a/projects/ngrx.io/content/marketing/events.html b/projects/ngrx.io/content/marketing/events.html index 7eb0738c9d..3fe5d662aa 100755 --- a/projects/ngrx.io/content/marketing/events.html +++ b/projects/ngrx.io/content/marketing/events.html @@ -2,113 +2,7 @@

Events

-

Upcoming Events presenting about NgRx:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventLocationDate
Open Source 101Columbia, South CarolinaApril 18th, 2019
ng-confSalt Lake City, UtahMay 1 - 3rd, 2019
ngVikingsCopenhagen, DenmarkMay 26 - 28th, 2019
REFACTR.TECHAtlanta, GeorgiaJune 5 - 7th, 2019
AngularUPTel Aviv, IsraelJune 12th, 2019
NG-MYKuala Lumpur, MalaysiaJuly 6 - 7th, 2019
ngDenverDenver, ColoradoAugust 1 - 2nd, 2019
AngularConnectLondon, United KingdomSeptember 19 - 20th, 2019
NG-RomeRome, ItalyOctober 7th, 2019
-

Past Events:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventLocationDate
NgColombiaMedellín, ColombiaSeptember 6 - 7th, 2018
DevFestATLAtlanta, GeorgiaSeptember 22nd, 2018
Framework SummitPark City, UtahSeptember 22nd, 2018
DevFestATLAtlanta, GeorgiaOctober 2 - 3rd, 2018
AngularMix - Use the discount code "RYAN" or "ROBERTS" to receive $50 off your registration!Orlando, FloridaOctober 10 - 12th, 2018
AngularConnectExcel, LondonNovember 6 - 7th, 2018
ngAtlantaAtlanta, GeorgiaJanuary 9 - 12th, 2019
ng-IndiaGurgaon, IndiaFebruary 23rd, 2019
+
diff --git a/projects/ngrx.io/src/app/custom-elements/contributor/event-list.component.spec.ts b/projects/ngrx.io/src/app/custom-elements/contributor/event-list.component.spec.ts new file mode 100644 index 0000000000..4ecb04612c --- /dev/null +++ b/projects/ngrx.io/src/app/custom-elements/contributor/event-list.component.spec.ts @@ -0,0 +1,105 @@ +import { ReflectiveInjector } from '@angular/core'; + +import { of } from 'rxjs'; + +import { ContributorGroup } from './contributors.model'; +import { ContributorListComponent } from './contributor-list.component'; +import { ContributorService } from './contributor.service'; +import { LocationService } from 'app/shared/location.service'; + +// Testing the component class behaviors, independent of its template +// Let e2e tests verify how it displays. +describe('ContributorListComponent', () => { + + let component: ContributorListComponent; + let injector: ReflectiveInjector; + let contributorService: TestContributorService; + let locationService: TestLocationService; + let contributorGroups: ContributorGroup[]; + + beforeEach(() => { + injector = ReflectiveInjector.resolveAndCreate([ + ContributorListComponent, + {provide: ContributorService, useClass: TestContributorService }, + {provide: LocationService, useClass: TestLocationService } + ]); + + locationService = injector.get(LocationService); + contributorService = injector.get(ContributorService); + contributorGroups = contributorService.testContributors; + }); + + it('should select the first group when no query string', () => { + component = getComponent(); + expect(component.selectedGroup).toBe(contributorGroups[0]); + }); + + it('should select the first group when query string w/o "group" property', () => { + locationService.searchResult = { foo: 'GDE' }; + component = getComponent(); + expect(component.selectedGroup).toBe(contributorGroups[0]); + }); + + it('should select the first group when query group not found', () => { + locationService.searchResult = { group: 'foo' }; + component = getComponent(); + expect(component.selectedGroup).toBe(contributorGroups[0]); + }); + + it('should select the GDE group when query group is "GDE"', () => { + locationService.searchResult = { group: 'GDE' }; + component = getComponent(); + expect(component.selectedGroup).toBe(contributorGroups[1]); + }); + + it('should select the GDE group when query group is "gde" (case insensitive)', () => { + locationService.searchResult = { group: 'gde' }; + component = getComponent(); + expect(component.selectedGroup).toBe(contributorGroups[1]); + }); + + it('should set the query to the "GDE" group when user selects "GDE"', () => { + component = getComponent(); + component.selectGroup('GDE'); + expect(locationService.searchResult['group']).toBe('GDE'); + }); + + it('should set the query to the first group when user selects unknown name', () => { + component = getComponent(); + component.selectGroup('GDE'); // a legit group that isn't the first + + component.selectGroup('foo'); // not a legit group name + expect(locationService.searchResult['group']).toBe('Angular'); + }); + + //// Test Helpers //// + function getComponent(): ContributorListComponent { + const comp = injector.get(ContributorListComponent); + comp.ngOnInit(); + return comp; + } + + interface SearchResult { [index: string]: string; }; + + class TestLocationService { + searchResult: SearchResult = {}; + search = jasmine.createSpy('search').and.callFake(() => this.searchResult); + setSearch = jasmine.createSpy('setSearch') + .and.callFake((label: string, result: SearchResult) => { + this.searchResult = result; + }); + } + + class TestContributorService { + testContributors = getTestData(); + contributors = of(this.testContributors); + } + + function getTestData(): ContributorGroup[] { + return [ + // Not interested in the contributors data in these tests + { name: 'Angular', order: 0, contributors: [] }, + { name: 'GDE', order: 1, contributors: [] }, + ]; + } +}); diff --git a/projects/ngrx.io/src/app/custom-elements/element-registry.ts b/projects/ngrx.io/src/app/custom-elements/element-registry.ts index d83e70a726..c969c3f1c9 100644 --- a/projects/ngrx.io/src/app/custom-elements/element-registry.ts +++ b/projects/ngrx.io/src/app/custom-elements/element-registry.ts @@ -17,6 +17,10 @@ export const ELEMENT_MODULE_PATHS_AS_ROUTES = [ selector: 'aio-contributor-list', loadChildren: './contributor/contributor-list.module#ContributorListModule', }, + { + selector: 'aio-event-list', + loadChildren: './events/event-list.module#EventListModule', + }, { selector: 'aio-file-not-found-search', loadChildren: diff --git a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts new file mode 100644 index 0000000000..a98381e15e --- /dev/null +++ b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts @@ -0,0 +1,76 @@ +import { Component, Input } from '@angular/core'; +import { Event, DisplayEvent } from './event.model'; + +@Component({ + selector: `aio-event-list`, + template: ` +

Upcoming Events presenting about NgRx:

+ + + + + + + + + + + + + + + +
EventLocationDate
{{upcomingEvent.name}}{{upcomingEvent.location}}{{upcomingEvent.dateRangeString}}
+

Past Events:

+ + + + + + + + + + + + + + + +
EventLocationDate
{{pastEvent.name}}{{pastEvent.location}}{{pastEvent.dateRangeString}}
+` +}) +export class EventListComponent { + upcomingEvents: DisplayEvent[]; + pastEvents: DisplayEvent[]; + + @Input() set events(value: Event[]) { + const displayEvents: DisplayEvent[] = value.map(event => { + const startDate = event.startDate ? new Date(event.startDate) : undefined; + const endDate = new Date(event.endDate); + return { + ...event, + startDate, + endDate, + dateRangeString: EventListComponent.getDateRange(startDate, endDate) + }; + }); + const currentDate = new Date(); + this.upcomingEvents = displayEvents.filter(event => event.endDate >= currentDate); + this.pastEvents = displayEvents.filter(event => event.endDate < currentDate); + } + + private static getDateRange(startDate: Date | undefined, endDate: Date): string { + if (!startDate || startDate === endDate) { + return endDate.toLocaleDateString('en-us', { year: 'numeric', month: 'long', day: 'numeric' }); + } else { + if (startDate.getMonth() === endDate.getMonth()) { + return startDate.toLocaleString('en-us', { month: 'long' }) + ' ' + startDate.getUTCDate() + ' - ' + endDate.getUTCDate() + ', ' + startDate.getUTCFullYear(); + } else if (startDate.getUTCFullYear() === endDate.getUTCFullYear()) { + return startDate.toLocaleString('en-us', { month: 'long' }) + ' ' + startDate.getUTCDate() + ' - ' + endDate.toLocaleString('en-us', { month: 'long' }) + ' ' + endDate.getUTCDate() + ', ' + startDate.getUTCFullYear(); + } else { + return startDate.toDateString() + ' - ' + endDate.toDateString(); + } + } + } +} diff --git a/projects/ngrx.io/src/app/custom-elements/events/event-list.module.ts b/projects/ngrx.io/src/app/custom-elements/events/event-list.module.ts new file mode 100644 index 0000000000..bc061f7462 --- /dev/null +++ b/projects/ngrx.io/src/app/custom-elements/events/event-list.module.ts @@ -0,0 +1,13 @@ +import { NgModule, Type } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { WithCustomElementComponent } from '../element-registry'; +import { EventListComponent } from './event-list.component'; + +@NgModule({ + imports: [ CommonModule ], + declarations: [ EventListComponent ], + entryComponents: [ EventListComponent ] +}) +export class EventListModule implements WithCustomElementComponent { + customElementComponent: Type = EventListComponent; +} diff --git a/projects/ngrx.io/src/app/custom-elements/events/event.model.ts b/projects/ngrx.io/src/app/custom-elements/events/event.model.ts new file mode 100644 index 0000000000..0b4a5860c2 --- /dev/null +++ b/projects/ngrx.io/src/app/custom-elements/events/event.model.ts @@ -0,0 +1,16 @@ +export interface Event { + name: string; + url: string; + location: string; + startDate?: string; + endDate: string; +} + +export interface DisplayEvent { + name: string; + url: string; + location: string; + startDate?: Date, + endDate: Date + dateRangeString: string; +} From eed504929fe68b4db8ffc6dcc5385be2de12ce98 Mon Sep 17 00:00:00 2001 From: ijz953 Date: Wed, 13 Mar 2019 02:44:54 -0400 Subject: [PATCH 03/19] docs: Add events to the event-list events input --- projects/ngrx.io/content/marketing/events.html | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/projects/ngrx.io/content/marketing/events.html b/projects/ngrx.io/content/marketing/events.html index 3fe5d662aa..11ddc879c3 100755 --- a/projects/ngrx.io/content/marketing/events.html +++ b/projects/ngrx.io/content/marketing/events.html @@ -3,6 +3,22 @@

Events

From 4dcccc5bb7802b5cdc2d09cea6b65165c7e89b59 Mon Sep 17 00:00:00 2001 From: ijz953 Date: Wed, 13 Mar 2019 03:06:24 -0400 Subject: [PATCH 04/19] docs: add tests for event-list component --- .../contributor/event-list.component.spec.ts | 105 ------------------ .../events/event-list.component.spec.ts | 75 +++++++++++++ .../events/event-list.component.ts | 6 +- 3 files changed, 78 insertions(+), 108 deletions(-) delete mode 100644 projects/ngrx.io/src/app/custom-elements/contributor/event-list.component.spec.ts create mode 100644 projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts diff --git a/projects/ngrx.io/src/app/custom-elements/contributor/event-list.component.spec.ts b/projects/ngrx.io/src/app/custom-elements/contributor/event-list.component.spec.ts deleted file mode 100644 index 4ecb04612c..0000000000 --- a/projects/ngrx.io/src/app/custom-elements/contributor/event-list.component.spec.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { ReflectiveInjector } from '@angular/core'; - -import { of } from 'rxjs'; - -import { ContributorGroup } from './contributors.model'; -import { ContributorListComponent } from './contributor-list.component'; -import { ContributorService } from './contributor.service'; -import { LocationService } from 'app/shared/location.service'; - -// Testing the component class behaviors, independent of its template -// Let e2e tests verify how it displays. -describe('ContributorListComponent', () => { - - let component: ContributorListComponent; - let injector: ReflectiveInjector; - let contributorService: TestContributorService; - let locationService: TestLocationService; - let contributorGroups: ContributorGroup[]; - - beforeEach(() => { - injector = ReflectiveInjector.resolveAndCreate([ - ContributorListComponent, - {provide: ContributorService, useClass: TestContributorService }, - {provide: LocationService, useClass: TestLocationService } - ]); - - locationService = injector.get(LocationService); - contributorService = injector.get(ContributorService); - contributorGroups = contributorService.testContributors; - }); - - it('should select the first group when no query string', () => { - component = getComponent(); - expect(component.selectedGroup).toBe(contributorGroups[0]); - }); - - it('should select the first group when query string w/o "group" property', () => { - locationService.searchResult = { foo: 'GDE' }; - component = getComponent(); - expect(component.selectedGroup).toBe(contributorGroups[0]); - }); - - it('should select the first group when query group not found', () => { - locationService.searchResult = { group: 'foo' }; - component = getComponent(); - expect(component.selectedGroup).toBe(contributorGroups[0]); - }); - - it('should select the GDE group when query group is "GDE"', () => { - locationService.searchResult = { group: 'GDE' }; - component = getComponent(); - expect(component.selectedGroup).toBe(contributorGroups[1]); - }); - - it('should select the GDE group when query group is "gde" (case insensitive)', () => { - locationService.searchResult = { group: 'gde' }; - component = getComponent(); - expect(component.selectedGroup).toBe(contributorGroups[1]); - }); - - it('should set the query to the "GDE" group when user selects "GDE"', () => { - component = getComponent(); - component.selectGroup('GDE'); - expect(locationService.searchResult['group']).toBe('GDE'); - }); - - it('should set the query to the first group when user selects unknown name', () => { - component = getComponent(); - component.selectGroup('GDE'); // a legit group that isn't the first - - component.selectGroup('foo'); // not a legit group name - expect(locationService.searchResult['group']).toBe('Angular'); - }); - - //// Test Helpers //// - function getComponent(): ContributorListComponent { - const comp = injector.get(ContributorListComponent); - comp.ngOnInit(); - return comp; - } - - interface SearchResult { [index: string]: string; }; - - class TestLocationService { - searchResult: SearchResult = {}; - search = jasmine.createSpy('search').and.callFake(() => this.searchResult); - setSearch = jasmine.createSpy('setSearch') - .and.callFake((label: string, result: SearchResult) => { - this.searchResult = result; - }); - } - - class TestContributorService { - testContributors = getTestData(); - contributors = of(this.testContributors); - } - - function getTestData(): ContributorGroup[] { - return [ - // Not interested in the contributors data in these tests - { name: 'Angular', order: 0, contributors: [] }, - { name: 'GDE', order: 1, contributors: [] }, - ]; - } -}); diff --git a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts new file mode 100644 index 0000000000..fddb975e0b --- /dev/null +++ b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts @@ -0,0 +1,75 @@ +import { ReflectiveInjector } from '@angular/core'; +import { EventListComponent } from './event-list.component'; +import { Event } from './event.model'; + +// Testing the component class behaviors, independent of its template +// Let e2e tests verify how it displays. +describe('EventListComponent', () => { + + let component: EventListComponent; + let injector: ReflectiveInjector; + let events: Event[]; + + beforeEach(() => { + injector = ReflectiveInjector.resolveAndCreate([ + EventListComponent + ]); + }); + + it('should put each event into the correct bucket and correctly format the date range string', () => { + component = getComponent(); + component.currentDate = new Date('01-02-2019'); + const mockEvents: Event[] = [ + { + name: 'conf1', + url: '', + location: '', + startDate: '06-28-2018', + endDate: '07-01-2018' + }, + { + name: 'conf2', + url: '', + location: '', + startDate: '12-25-2018', + endDate: '01-01-2019' + }, + { + name: 'conf3', + url: '', + location: '', + startDate: '01-01-2019', + endDate: '01-03-2019' + }, + { + name: 'conf4', + url: '', + location: '', + endDate: '04-01-2019' + }, + { + name: 'conf5', + url: '', + location: '', + startDate: '04-02-2019', + endDate: '04-02-2019' + }, + ]; + component.events = mockEvents; + expect(component.pastEvents).toBe(mockEvents[0], mockEvents[1]); + expect(component.upcomingEvents).toBe(mockEvents[2], mockEvents[3], mockEvents[4]); + expect(component.pastEvents[0].dateRangeString).toEqual('June 28 - July 1, 2018'); + expect(component.pastEvents[1].dateRangeString).toEqual('December 25, 2018 - January 1, 2019'); + expect(component.upcomingEvents[0].dateRangeString).toEqual('January 1 - 3, 2019'); + expect(component.upcomingEvents[1].dateRangeString).toEqual('April 1, 2019'); + expect(component.upcomingEvents[2].dateRangeString).toEqual('April 2, 2019'); + }); + + + //// Test Helpers //// + function getComponent(): EventListComponent { + const comp = injector.get(EventListComponent); + comp.ngOnInit(); + return comp; + } +}); diff --git a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts index a98381e15e..4dbbbc8c43 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts @@ -43,6 +43,7 @@ import { Event, DisplayEvent } from './event.model'; export class EventListComponent { upcomingEvents: DisplayEvent[]; pastEvents: DisplayEvent[]; + currentDate = new Date(); @Input() set events(value: Event[]) { const displayEvents: DisplayEvent[] = value.map(event => { @@ -55,9 +56,8 @@ export class EventListComponent { dateRangeString: EventListComponent.getDateRange(startDate, endDate) }; }); - const currentDate = new Date(); - this.upcomingEvents = displayEvents.filter(event => event.endDate >= currentDate); - this.pastEvents = displayEvents.filter(event => event.endDate < currentDate); + this.upcomingEvents = displayEvents.filter(event => event.endDate >= this.currentDate); + this.pastEvents = displayEvents.filter(event => event.endDate < this.currentDate); } private static getDateRange(startDate: Date | undefined, endDate: Date): string { From 7b29f1641f30974a0075916f4e9781a338341b3c Mon Sep 17 00:00:00 2001 From: ijz953 Date: Wed, 13 Mar 2019 03:09:10 -0400 Subject: [PATCH 05/19] docs: improve formatting of event-list component --- .../app/custom-elements/events/event-list.component.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts index 4dbbbc8c43..a71de17597 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts @@ -65,9 +65,15 @@ export class EventListComponent { return endDate.toLocaleDateString('en-us', { year: 'numeric', month: 'long', day: 'numeric' }); } else { if (startDate.getMonth() === endDate.getMonth()) { - return startDate.toLocaleString('en-us', { month: 'long' }) + ' ' + startDate.getUTCDate() + ' - ' + endDate.getUTCDate() + ', ' + startDate.getUTCFullYear(); + return startDate.toLocaleString('en-us', { month: 'long' }) + + ' ' + startDate.getUTCDate() + ' - ' + endDate.getUTCDate() + + ', ' + startDate.getUTCFullYear(); } else if (startDate.getUTCFullYear() === endDate.getUTCFullYear()) { - return startDate.toLocaleString('en-us', { month: 'long' }) + ' ' + startDate.getUTCDate() + ' - ' + endDate.toLocaleString('en-us', { month: 'long' }) + ' ' + endDate.getUTCDate() + ', ' + startDate.getUTCFullYear(); + return startDate.toLocaleString('en-us', { month: 'long' }) + + ' ' + startDate.getUTCDate() + + ' - ' + endDate.toLocaleString('en-us', { month: 'long' }) + + ' ' + endDate.getUTCDate() + + ', ' + startDate.getUTCFullYear(); } else { return startDate.toDateString() + ' - ' + endDate.toDateString(); } From 79ebec60d864c00440fdd50965d1cdef4473c8ac Mon Sep 17 00:00:00 2001 From: ijz953 Date: Wed, 13 Mar 2019 03:54:07 -0400 Subject: [PATCH 06/19] docs: fix event-list component tests --- .../events/event-list.component.spec.ts | 6 ++---- .../custom-elements/events/event-list.component.ts | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts index fddb975e0b..50f799df10 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts @@ -8,7 +8,6 @@ describe('EventListComponent', () => { let component: EventListComponent; let injector: ReflectiveInjector; - let events: Event[]; beforeEach(() => { injector = ReflectiveInjector.resolveAndCreate([ @@ -56,8 +55,8 @@ describe('EventListComponent', () => { }, ]; component.events = mockEvents; - expect(component.pastEvents).toBe(mockEvents[0], mockEvents[1]); - expect(component.upcomingEvents).toBe(mockEvents[2], mockEvents[3], mockEvents[4]); + expect(component.pastEvents.length).toEqual(2); + expect(component.upcomingEvents.length).toEqual(3); expect(component.pastEvents[0].dateRangeString).toEqual('June 28 - July 1, 2018'); expect(component.pastEvents[1].dateRangeString).toEqual('December 25, 2018 - January 1, 2019'); expect(component.upcomingEvents[0].dateRangeString).toEqual('January 1 - 3, 2019'); @@ -69,7 +68,6 @@ describe('EventListComponent', () => { //// Test Helpers //// function getComponent(): EventListComponent { const comp = injector.get(EventListComponent); - comp.ngOnInit(); return comp; } }); diff --git a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts index a71de17597..cfd9bda0d7 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts @@ -60,8 +60,17 @@ export class EventListComponent { this.pastEvents = displayEvents.filter(event => event.endDate < this.currentDate); } + /** + * The date range string for the two given dates + * '01-01-2019' until '01-01-2019' -> 'January 1, 2019' + * '01-01-2019' until '01-02-2019' -> 'January 1 - 2, 2019' + * '01-28-2019' until '02-01-2019' -> 'January 28 - February 1, 2019' + * '12-31-2018' until '01-01-2019' -> 'December 31, 2018 - January 1, 2019' + * @param startDate + * @param endDate + */ private static getDateRange(startDate: Date | undefined, endDate: Date): string { - if (!startDate || startDate === endDate) { + if (!startDate || startDate.getTime() === endDate.getTime()) { return endDate.toLocaleDateString('en-us', { year: 'numeric', month: 'long', day: 'numeric' }); } else { if (startDate.getMonth() === endDate.getMonth()) { @@ -75,7 +84,8 @@ export class EventListComponent { + ' ' + endDate.getUTCDate() + ', ' + startDate.getUTCFullYear(); } else { - return startDate.toDateString() + ' - ' + endDate.toDateString(); + return startDate.toLocaleDateString('en-us', { year: 'numeric', month: 'long', day: 'numeric' }) + + ' - ' + endDate.toLocaleDateString('en-us', { year: 'numeric', month: 'long', day: 'numeric' }); } } } From 63adf95681985a359d948b4687ffa91f184e4130 Mon Sep 17 00:00:00 2001 From: ijz953 Date: Wed, 13 Mar 2019 12:00:59 -0400 Subject: [PATCH 07/19] docs: moving events to json with service --- .../ngrx.io/content/marketing/events.html | 20 +------ .../ngrx.io/content/marketing/events.json | 59 +++++++++++++++++++ .../events/event-list.component.ts | 41 +++++++------ .../events/event-list.module.ts | 4 +- .../custom-elements/events/event.service.ts | 30 ++++++++++ 5 files changed, 115 insertions(+), 39 deletions(-) create mode 100644 projects/ngrx.io/content/marketing/events.json create mode 100644 projects/ngrx.io/src/app/custom-elements/events/event.service.ts diff --git a/projects/ngrx.io/content/marketing/events.html b/projects/ngrx.io/content/marketing/events.html index 11ddc879c3..436c358dc7 100755 --- a/projects/ngrx.io/content/marketing/events.html +++ b/projects/ngrx.io/content/marketing/events.html @@ -2,23 +2,5 @@

Events

- +
diff --git a/projects/ngrx.io/content/marketing/events.json b/projects/ngrx.io/content/marketing/events.json new file mode 100644 index 0000000000..0a565a5c16 --- /dev/null +++ b/projects/ngrx.io/content/marketing/events.json @@ -0,0 +1,59 @@ +[ + { + "name": "NgColombia", + "url": "http://www.ngcolombia.com", + "location": "Medellín, Colombia", + "startDate": "09-06-2018", + "endDate": "09-07-2018" + }, + { + "name": "DevFestATL", + "url": "http://devfestatl.com", + "location": "Atlanta, Georgia", + "endDate": "09-22-2018" + }, + { + "name": "Framework Summit", + "url": "http://frameworksummit.com", + "location": "Park City, Utah", + "endDate": "09-22-2018" + }, + { + "name": "DevFestATL", + "url": "http://devfestatl.com", + "location": "Atlanta, Georgia", + "startDate": "10-02-2018", + "endDate": "10-03-2018" + }, + { + "name": "AngularMix - Use the discount code "RYAN" or "ROBERTS" to receive $50 off your registration!", + "url": "http://www.angularmix.com", + "location": "Orlando, Florida", + "startDate": "10-10-2018", + "endDate": "10-12-2018" + }, + { + "name": "AngularConnect", "url": "http://www.angularconnect.com", "location": "Excel, London", "startDate": "11-06-2018", "endDate": "11-07-2018"}, + { + "name": "ngAtlanta", "url": "http://ng-atl.org/", "location": "Atlanta, Georgia", "startDate": "01-09-2019", "endDate": "01-12-2019"}, + { + "name": "ng-India", "url": "https://www.ng-ind.com", "location": "Gurgaon, India", "endDate": "02-23-2019"}, + { + "name": "Open Source 101", "url": "https://opensource101.com/", "location": "Columbia, South Carolina", "endDate": "04-18-2019"}, + { + "name": "NG-Conf", "url": "https://www.ng-conf.org", "location": "Salt Lake City, Utah", "startDate": "05-01-2019", "endDate": "05-03-2019"}, + { + "name": "ngVikings", "url": "https://ngvikings.org/", "location": "Copenhagen, Denmark", "startDate": "05-26-2019", "endDate": "05-28-2019"}, + { + "name": "REFACTR.TECH", "url": "https://refactr.tech/", "location": "Atlanta, Georgia", "startDate": "06-05-2019", "endDate": "06-07-2019"}, + { + "name": "AngularUP", "url": "https://angular-up.com/", "location": "Tel Aviv, Israel", "endDate": "06-12-2019"}, + { + "name": "NG-MY", "url": "https://ng-my.org/", "location": "Kuala Lumpur, Malaysia", "startDate": "07-06-2019", "endDate": "07-07-2019"}, + { + "name": "ngDenver", "url": "http://angulardenver.com/", "location": "Denver, Colorado", "startDate": "08-01-2019", "endDate": "08-02-2019"}, + { + "name": "AngularConnect", "url": "https://www.angularconnect.com/", "location": "London, United Kingdom", "startDate": "09-19-2019", "endDate": "09-20-2019"}, + { + "name": "NG-Rome", "url": "https://ngrome.io/", "location": "Rome, Italy", "endDate": "10-07-2019"} + ] diff --git a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts index cfd9bda0d7..f90092a7bf 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts @@ -1,5 +1,6 @@ -import { Component, Input } from '@angular/core'; -import { Event, DisplayEvent } from './event.model'; +import { Component } from '@angular/core'; +import { DisplayEvent } from './event.model'; +import { EventService } from './event.service'; @Component({ selector: `aio-event-list`, @@ -41,25 +42,10 @@ import { Event, DisplayEvent } from './event.model'; ` }) export class EventListComponent { - upcomingEvents: DisplayEvent[]; - pastEvents: DisplayEvent[]; + upcomingEvents: DisplayEvent[] = []; + pastEvents: DisplayEvent[] = []; currentDate = new Date(); - @Input() set events(value: Event[]) { - const displayEvents: DisplayEvent[] = value.map(event => { - const startDate = event.startDate ? new Date(event.startDate) : undefined; - const endDate = new Date(event.endDate); - return { - ...event, - startDate, - endDate, - dateRangeString: EventListComponent.getDateRange(startDate, endDate) - }; - }); - this.upcomingEvents = displayEvents.filter(event => event.endDate >= this.currentDate); - this.pastEvents = displayEvents.filter(event => event.endDate < this.currentDate); - } - /** * The date range string for the two given dates * '01-01-2019' until '01-01-2019' -> 'January 1, 2019' @@ -89,4 +75,21 @@ export class EventListComponent { } } } + + constructor(private eventService: EventService) { + this.eventService.events.subscribe(value => { + const displayEvents: DisplayEvent[] = value.map(event => { + const startDate = event.startDate ? new Date(event.startDate) : undefined; + const endDate = new Date(event.endDate); + return { + ...event, + startDate, + endDate, + dateRangeString: EventListComponent.getDateRange(startDate, endDate) + }; + }); + this.upcomingEvents = displayEvents.filter(event => event.endDate >= this.currentDate); + this.pastEvents = displayEvents.filter(event => event.endDate < this.currentDate); + }); + } } diff --git a/projects/ngrx.io/src/app/custom-elements/events/event-list.module.ts b/projects/ngrx.io/src/app/custom-elements/events/event-list.module.ts index bc061f7462..bcdd7949c3 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event-list.module.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event-list.module.ts @@ -2,11 +2,13 @@ import { NgModule, Type } from '@angular/core'; import { CommonModule } from '@angular/common'; import { WithCustomElementComponent } from '../element-registry'; import { EventListComponent } from './event-list.component'; +import { EventService } from './event.service'; @NgModule({ imports: [ CommonModule ], declarations: [ EventListComponent ], - entryComponents: [ EventListComponent ] + entryComponents: [ EventListComponent ], + providers: [ EventService ] }) export class EventListModule implements WithCustomElementComponent { customElementComponent: Type = EventListComponent; diff --git a/projects/ngrx.io/src/app/custom-elements/events/event.service.ts b/projects/ngrx.io/src/app/custom-elements/events/event.service.ts new file mode 100644 index 0000000000..b511bbe373 --- /dev/null +++ b/projects/ngrx.io/src/app/custom-elements/events/event.service.ts @@ -0,0 +1,30 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; + +import { ConnectableObservable, Observable } from 'rxjs'; +import { tap, publishLast } from 'rxjs/operators'; + +import { CONTENT_URL_PREFIX } from 'app/documents/document.service'; +import { Event } from './event.model'; + +const resourcesPath = CONTENT_URL_PREFIX + 'events.json'; + +@Injectable() +export class EventService { + events: Observable; + + constructor(private http: HttpClient) { + this.events = this.getEvents(); + } + + private getEvents(): Observable { + + const events = this.http.get(resourcesPath).pipe( + tap(event => console.log('service: ' + event)), + publishLast(), + ); + + (events as ConnectableObservable).connect(); + return events; + }; +} From 315ab6a791ce5794acdacd1749aa26a5a0d90901 Mon Sep 17 00:00:00 2001 From: ijz953 Date: Wed, 13 Mar 2019 12:48:14 -0400 Subject: [PATCH 08/19] docs: adding debug info --- .../app/custom-elements/events/event-list.component.ts | 2 ++ .../src/app/custom-elements/events/event.service.ts | 8 +++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts index f90092a7bf..1657b22a96 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts @@ -77,7 +77,9 @@ export class EventListComponent { } constructor(private eventService: EventService) { + console.log('hello2'); this.eventService.events.subscribe(value => { + console.log('hello3' + value); const displayEvents: DisplayEvent[] = value.map(event => { const startDate = event.startDate ? new Date(event.startDate) : undefined; const endDate = new Date(event.endDate); diff --git a/projects/ngrx.io/src/app/custom-elements/events/event.service.ts b/projects/ngrx.io/src/app/custom-elements/events/event.service.ts index b511bbe373..e7baf435f4 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event.service.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { ConnectableObservable, Observable } from 'rxjs'; -import { tap, publishLast } from 'rxjs/operators'; +import { tap, publishLast, map } from 'rxjs/operators'; import { CONTENT_URL_PREFIX } from 'app/documents/document.service'; import { Event } from './event.model'; @@ -18,8 +18,10 @@ export class EventService { } private getEvents(): Observable { - - const events = this.http.get(resourcesPath).pipe( + console.log('getEvents') + const events = this.http.get(resourcesPath).pipe( + tap(() => console.log('serviceok')), + map(event => event as Event[]), tap(event => console.log('service: ' + event)), publishLast(), ); From 9ed378f91e19a19076a37dd37884b25d56da156b Mon Sep 17 00:00:00 2001 From: ijz953 Date: Wed, 13 Mar 2019 15:11:16 -0400 Subject: [PATCH 09/19] docs: add events.json to index.js --- .../tools/transforms/angular-content-package/index.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/projects/ngrx.io/tools/transforms/angular-content-package/index.js b/projects/ngrx.io/tools/transforms/angular-content-package/index.js index b0635ae198..5fdde81efa 100644 --- a/projects/ngrx.io/tools/transforms/angular-content-package/index.js +++ b/projects/ngrx.io/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'); From 3b5f1f6959be16ca72c87922fd17b302397f390d Mon Sep 17 00:00:00 2001 From: ijz953 Date: Wed, 13 Mar 2019 15:34:11 -0400 Subject: [PATCH 10/19] docs: adding events.json to pathTemplates --- .../ngrx.io/tools/transforms/angular-content-package/index.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/projects/ngrx.io/tools/transforms/angular-content-package/index.js b/projects/ngrx.io/tools/transforms/angular-content-package/index.js index 5fdde81efa..973e2d7b8f 100644 --- a/projects/ngrx.io/tools/transforms/angular-content-package/index.js +++ b/projects/ngrx.io/tools/transforms/angular-content-package/index.js @@ -115,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'} ]); }) From 6f9826b533ec569ace5af52396723c9ac06047f2 Mon Sep 17 00:00:00 2001 From: ijz953 Date: Wed, 13 Mar 2019 20:44:03 -0400 Subject: [PATCH 11/19] docs: move date range and upcoming vs past logic into event service --- .../ngrx.io/content/marketing/events.json | 82 +++++++++--- .../events/event-list.component.spec.ts | 4 +- .../events/event-list.component.ts | 61 ++------- .../app/custom-elements/events/event.model.ts | 4 +- .../events/event.service.spec.ts | 118 ++++++++++++++++++ .../custom-elements/events/event.service.ts | 76 +++++++++-- 6 files changed, 262 insertions(+), 83 deletions(-) create mode 100644 projects/ngrx.io/src/app/custom-elements/events/event.service.spec.ts diff --git a/projects/ngrx.io/content/marketing/events.json b/projects/ngrx.io/content/marketing/events.json index 0a565a5c16..75e930bbf4 100644 --- a/projects/ngrx.io/content/marketing/events.json +++ b/projects/ngrx.io/content/marketing/events.json @@ -26,34 +26,88 @@ "endDate": "10-03-2018" }, { - "name": "AngularMix - Use the discount code "RYAN" or "ROBERTS" to receive $50 off your registration!", + "name": "AngularMix - Use the discount code \"RYAN\" or \"ROBERTS\" to receive $50 off your registration!", "url": "http://www.angularmix.com", "location": "Orlando, Florida", "startDate": "10-10-2018", "endDate": "10-12-2018" }, { - "name": "AngularConnect", "url": "http://www.angularconnect.com", "location": "Excel, London", "startDate": "11-06-2018", "endDate": "11-07-2018"}, + "name": "AngularConnect", + "url": "http://www.angularconnect.com", + "location": "Excel, London", + "startDate": "11-06-2018", + "endDate": "11-07-2018" + }, { - "name": "ngAtlanta", "url": "http://ng-atl.org/", "location": "Atlanta, Georgia", "startDate": "01-09-2019", "endDate": "01-12-2019"}, + "name": "ngAtlanta", + "url": "http://ng-atl.org/", + "location": "Atlanta, Georgia", + "startDate": "01-09-2019", + "endDate": "01-12-2019" + }, { - "name": "ng-India", "url": "https://www.ng-ind.com", "location": "Gurgaon, India", "endDate": "02-23-2019"}, + "name": "ng-India", + "url": "https://www.ng-ind.com", + "location": "Gurgaon, India", + "endDate": "02-23-2019" + }, { - "name": "Open Source 101", "url": "https://opensource101.com/", "location": "Columbia, South Carolina", "endDate": "04-18-2019"}, + "name": "Open Source 101", + "url": "https://opensource101.com/", + "location": "Columbia, South Carolina", + "endDate": "04-18-2019" + }, { - "name": "NG-Conf", "url": "https://www.ng-conf.org", "location": "Salt Lake City, Utah", "startDate": "05-01-2019", "endDate": "05-03-2019"}, + "name": "NG-Conf", + "url": "https://www.ng-conf.org", + "location": "Salt Lake City, Utah", + "startDate": "05-01-2019", "endDate": "05-03-2019"}, { - "name": "ngVikings", "url": "https://ngvikings.org/", "location": "Copenhagen, Denmark", "startDate": "05-26-2019", "endDate": "05-28-2019"}, + "name": "ngVikings", + "url": "https://ngvikings.org/", + "location": "Copenhagen, Denmark", + "startDate": "05-26-2019", + "endDate": "05-28-2019" + }, { - "name": "REFACTR.TECH", "url": "https://refactr.tech/", "location": "Atlanta, Georgia", "startDate": "06-05-2019", "endDate": "06-07-2019"}, + "name": "REFACTR.TECH", + "url": "https://refactr.tech/", + "location": "Atlanta, Georgia", + "startDate": "06-05-2019", + "endDate": "06-07-2019" + }, { - "name": "AngularUP", "url": "https://angular-up.com/", "location": "Tel Aviv, Israel", "endDate": "06-12-2019"}, + "name": "AngularUP", + "url": "https://angular-up.com/", + "location": "Tel Aviv, Israel", + "endDate": "06-12-2019" + }, { - "name": "NG-MY", "url": "https://ng-my.org/", "location": "Kuala Lumpur, Malaysia", "startDate": "07-06-2019", "endDate": "07-07-2019"}, + "name": "NG-MY", + "url": "https://ng-my.org/", + "location": "Kuala Lumpur, Malaysia", + "startDate": "07-06-2019", + "endDate": "07-07-2019" + }, { - "name": "ngDenver", "url": "http://angulardenver.com/", "location": "Denver, Colorado", "startDate": "08-01-2019", "endDate": "08-02-2019"}, + "name": "ngDenver", + "url": "http://angulardenver.com/", + "location": "Denver, Colorado", + "startDate": "08-01-2019", + "endDate": "08-02-2019" + }, { - "name": "AngularConnect", "url": "https://www.angularconnect.com/", "location": "London, United Kingdom", "startDate": "09-19-2019", "endDate": "09-20-2019"}, + "name": "AngularConnect", + "url": "https://www.angularconnect.com/", + "location": "London, United Kingdom", + "startDate": "09-19-2019", + "endDate": "09-20-2019" + }, { - "name": "NG-Rome", "url": "https://ngrome.io/", "location": "Rome, Italy", "endDate": "10-07-2019"} - ] + "name": "NG-Rome", + "url": "https://ngrome.io/", + "location": "Rome, Italy", + "endDate": "10-07-2019" + } +] diff --git a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts index 50f799df10..1537e7d864 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts @@ -1,6 +1,6 @@ import { ReflectiveInjector } from '@angular/core'; import { EventListComponent } from './event-list.component'; -import { Event } from './event.model'; +import { EventResponse } from './event.model'; // Testing the component class behaviors, independent of its template // Let e2e tests verify how it displays. @@ -18,7 +18,7 @@ describe('EventListComponent', () => { it('should put each event into the correct bucket and correctly format the date range string', () => { component = getComponent(); component.currentDate = new Date('01-02-2019'); - const mockEvents: Event[] = [ + const mockEvents: EventResponse[] = [ { name: 'conf1', url: '', diff --git a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts index 1657b22a96..78ff84dddd 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts @@ -1,6 +1,7 @@ import { Component } from '@angular/core'; -import { DisplayEvent } from './event.model'; +import { Event } from './event.model'; import { EventService } from './event.service'; +import { Observable } from 'rxjs'; @Component({ selector: `aio-event-list`, @@ -15,7 +16,7 @@ import { EventService } from './event.service'; - + {{upcomingEvent.name}} {{upcomingEvent.location}} {{upcomingEvent.dateRangeString}} @@ -32,7 +33,7 @@ import { EventService } from './event.service'; - + {{pastEvent.name}} {{pastEvent.location}} {{pastEvent.dateRangeString}} @@ -42,56 +43,8 @@ import { EventService } from './event.service'; ` }) export class EventListComponent { - upcomingEvents: DisplayEvent[] = []; - pastEvents: DisplayEvent[] = []; - currentDate = new Date(); + upcomingEvents$: Observable = this.eventService.upcomingEvents; + pastEvents$: Observable = this.eventService.pastEvents; - /** - * The date range string for the two given dates - * '01-01-2019' until '01-01-2019' -> 'January 1, 2019' - * '01-01-2019' until '01-02-2019' -> 'January 1 - 2, 2019' - * '01-28-2019' until '02-01-2019' -> 'January 28 - February 1, 2019' - * '12-31-2018' until '01-01-2019' -> 'December 31, 2018 - January 1, 2019' - * @param startDate - * @param endDate - */ - private static getDateRange(startDate: Date | undefined, endDate: Date): string { - if (!startDate || startDate.getTime() === endDate.getTime()) { - return endDate.toLocaleDateString('en-us', { year: 'numeric', month: 'long', day: 'numeric' }); - } else { - if (startDate.getMonth() === endDate.getMonth()) { - return startDate.toLocaleString('en-us', { month: 'long' }) - + ' ' + startDate.getUTCDate() + ' - ' + endDate.getUTCDate() - + ', ' + startDate.getUTCFullYear(); - } else if (startDate.getUTCFullYear() === endDate.getUTCFullYear()) { - return startDate.toLocaleString('en-us', { month: 'long' }) - + ' ' + startDate.getUTCDate() - + ' - ' + endDate.toLocaleString('en-us', { month: 'long' }) - + ' ' + endDate.getUTCDate() - + ', ' + startDate.getUTCFullYear(); - } else { - return startDate.toLocaleDateString('en-us', { year: 'numeric', month: 'long', day: 'numeric' }) - + ' - ' + endDate.toLocaleDateString('en-us', { year: 'numeric', month: 'long', day: 'numeric' }); - } - } - } - - constructor(private eventService: EventService) { - console.log('hello2'); - this.eventService.events.subscribe(value => { - console.log('hello3' + value); - const displayEvents: DisplayEvent[] = value.map(event => { - const startDate = event.startDate ? new Date(event.startDate) : undefined; - const endDate = new Date(event.endDate); - return { - ...event, - startDate, - endDate, - dateRangeString: EventListComponent.getDateRange(startDate, endDate) - }; - }); - this.upcomingEvents = displayEvents.filter(event => event.endDate >= this.currentDate); - this.pastEvents = displayEvents.filter(event => event.endDate < this.currentDate); - }); - } + constructor(private eventService: EventService) { } } diff --git a/projects/ngrx.io/src/app/custom-elements/events/event.model.ts b/projects/ngrx.io/src/app/custom-elements/events/event.model.ts index 0b4a5860c2..aab37c5d35 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event.model.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event.model.ts @@ -1,4 +1,4 @@ -export interface Event { +export interface EventResponse { name: string; url: string; location: string; @@ -6,7 +6,7 @@ export interface Event { endDate: string; } -export interface DisplayEvent { +export interface Event { name: string; url: string; location: string; diff --git a/projects/ngrx.io/src/app/custom-elements/events/event.service.spec.ts b/projects/ngrx.io/src/app/custom-elements/events/event.service.spec.ts new file mode 100644 index 0000000000..727101710e --- /dev/null +++ b/projects/ngrx.io/src/app/custom-elements/events/event.service.spec.ts @@ -0,0 +1,118 @@ +import { + HttpClientTestingModule, + HttpTestingController, +} from '@angular/common/http/testing'; +import { Injector } from '@angular/core'; +import { TestBed } from '@angular/core/testing'; +import { EventService } from './event.service'; +import { Event, EventResponse } from './event.model'; + +describe('EventService', () => { + let injector: Injector; + let eventService: EventService; + let httpMock: HttpTestingController; + + beforeEach(() => { + injector = TestBed.configureTestingModule({ + imports: [HttpClientTestingModule], + providers: [EventService], + }); + + eventService = injector.get(EventService); + httpMock = injector.get(HttpTestingController); + }); + + afterEach(() => httpMock.verify()); + + it('should make a single connection to the server', () => { + const req = httpMock.expectOne({}); + expect(req.request.url).toBe('generated/events.json'); + }); + + describe('#events', () => { + let events: Event[]; + let testData: EventResponse[]; + + beforeEach(() => { + testData = getTestEventResponse(); + httpMock.expectOne({}).flush(testData); + eventService.upcomingEvents.subscribe(results => (events = results)); + eventService.pastEvents.subscribe(results => (events = results)); + }); + + it('upcomingEvents observable should complete', () => { + let completed = false; + eventService.upcomingEvents.subscribe( + undefined, + undefined, + () => (completed = true) + ); + expect(completed).toBe(true, 'observable completed'); + }); + + it('pastEvents observable should complete', () => { + let completed = false; + eventService.pastEvents.subscribe( + undefined, + undefined, + () => (completed = true) + ); + expect(completed).toBe(true, 'observable completed'); + }); + + // it('should reshape the contributor json to expected result', () => { + // const groupNames = contribs.map(g => g.name).join(','); + // expect(groupNames).toEqual('Angular,GDE'); + // }); + + // it('should have expected "GDE" contribs in order', () => { + // const gde = contribs[1]; + // const actualAngularNames = gde.contributors.map(l => l.name).join(','); + // const expectedAngularNames = [testData.jeffcross, testData.kapunahelewong] + // .map(l => l.name) + // .join(','); + // expect(actualAngularNames).toEqual(expectedAngularNames); + // }); + }); + + it('should do WHAT(?) if the request fails'); +}); + +function getTestEventResponse(): EventResponse[] { + return [ + { + name: 'conf1', + url: '', + location: '', + startDate: '06-28-2018', + endDate: '07-01-2018' + }, + { + name: 'conf2', + url: '', + location: '', + startDate: '12-25-2018', + endDate: '01-01-2019' + }, + { + name: 'conf3', + url: '', + location: '', + startDate: '01-01-2019', + endDate: '01-03-2019' + }, + { + name: 'conf4', + url: '', + location: '', + endDate: '04-01-2019' + }, + { + name: 'conf5', + url: '', + location: '', + startDate: '04-02-2019', + endDate: '04-02-2019' + }, + ]; +} diff --git a/projects/ngrx.io/src/app/custom-elements/events/event.service.ts b/projects/ngrx.io/src/app/custom-elements/events/event.service.ts index e7baf435f4..0b185b30cc 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event.service.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event.service.ts @@ -1,28 +1,52 @@ import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; - import { ConnectableObservable, Observable } from 'rxjs'; -import { tap, publishLast, map } from 'rxjs/operators'; - +import { publishLast, map } from 'rxjs/operators'; import { CONTENT_URL_PREFIX } from 'app/documents/document.service'; -import { Event } from './event.model'; +import { EventResponse, Event } from './event.model'; const resourcesPath = CONTENT_URL_PREFIX + 'events.json'; @Injectable() export class EventService { - events: Observable; + private currentDate: Date; + private events$: Observable; + upcomingEvents = this.events$.pipe( + map(events => + events.filter(event => event.endDate >= this.currentDate) + ) + ); + pastEvents = this.events$.pipe( + map(events => + events.filter(event => event.endDate < this.currentDate) + ) + ); constructor(private http: HttpClient) { - this.events = this.getEvents(); + this.currentDate = new Date(); + // Compare soley on date, without factoring in time. + this.currentDate.setHours(0, 0, 0, 0); + this.events$ = this.getEvents(); } + /** + * Fetch Event JSON from file and return an Observable that emits an Event array. + */ private getEvents(): Observable { - console.log('getEvents') - const events = this.http.get(resourcesPath).pipe( - tap(() => console.log('serviceok')), - map(event => event as Event[]), - tap(event => console.log('service: ' + event)), + const events = this.http.get(resourcesPath).pipe( + map(eventResponses => + eventResponses.map(eventResponse => { + const startDate = eventResponse.startDate ? new Date(eventResponse.startDate) : undefined; + const endDate = new Date(eventResponse.endDate); + const event: Event = { + ...eventResponse, + startDate, + endDate, + dateRangeString: getDateRange(startDate, endDate) + }; + return event; + }) + ), publishLast(), ); @@ -30,3 +54,33 @@ export class EventService { return events; }; } + +/** + * The date range string for the two given dates + * '01-01-2019' until '01-01-2019' -> 'January 1, 2019' + * '01-01-2019' until '01-02-2019' -> 'January 1 - 2, 2019' + * '01-28-2019' until '02-01-2019' -> 'January 28 - February 1, 2019' + * '12-31-2018' until '01-01-2019' -> 'December 31, 2018 - January 1, 2019' + * @param startDate date the event starts. If undefined, startDate assumed to be same as endDate. + * @param endDate date theh event ends. + */ +function getDateRange(startDate: Date | undefined, endDate: Date): string { + if (!startDate || startDate.getTime() === endDate.getTime()) { + return endDate.toLocaleDateString('en-us', { year: 'numeric', month: 'long', day: 'numeric' }); + } else { + if (startDate.getMonth() === endDate.getMonth()) { + return startDate.toLocaleString('en-us', { month: 'long' }) + + ' ' + startDate.getUTCDate() + ' - ' + endDate.getUTCDate() + + ', ' + startDate.getUTCFullYear(); + } else if (startDate.getUTCFullYear() === endDate.getUTCFullYear()) { + return startDate.toLocaleString('en-us', { month: 'long' }) + + ' ' + startDate.getUTCDate() + + ' - ' + endDate.toLocaleString('en-us', { month: 'long' }) + + ' ' + endDate.getUTCDate() + + ', ' + startDate.getUTCFullYear(); + } else { + return startDate.toLocaleDateString('en-us', { year: 'numeric', month: 'long', day: 'numeric' }) + + ' - ' + endDate.toLocaleDateString('en-us', { year: 'numeric', month: 'long', day: 'numeric' }); + } + } +} From 0ea547a34c6d8d5b6eba8daa40f9e36bb1d4d379 Mon Sep 17 00:00:00 2001 From: ijz953 Date: Thu, 14 Mar 2019 10:01:44 -0400 Subject: [PATCH 12/19] docs: move observable into constructor --- .../events/event-list.component.ts | 4 ++-- .../custom-elements/events/event.service.ts | 22 ++++++++++--------- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts index 78ff84dddd..fa34ca3ff6 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts @@ -43,8 +43,8 @@ import { Observable } from 'rxjs'; ` }) export class EventListComponent { - upcomingEvents$: Observable = this.eventService.upcomingEvents; - pastEvents$: Observable = this.eventService.pastEvents; + upcomingEvents$: Observable = this.eventService.upcomingEvents$; + pastEvents$: Observable = this.eventService.pastEvents$; constructor(private eventService: EventService) { } } diff --git a/projects/ngrx.io/src/app/custom-elements/events/event.service.ts b/projects/ngrx.io/src/app/custom-elements/events/event.service.ts index 0b185b30cc..b97c37b7b0 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event.service.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event.service.ts @@ -11,22 +11,24 @@ const resourcesPath = CONTENT_URL_PREFIX + 'events.json'; export class EventService { private currentDate: Date; private events$: Observable; - upcomingEvents = this.events$.pipe( - map(events => - events.filter(event => event.endDate >= this.currentDate) - ) - ); - pastEvents = this.events$.pipe( - map(events => - events.filter(event => event.endDate < this.currentDate) - ) - ); + upcomingEvents$: Observable; + pastEvents$: Observable; constructor(private http: HttpClient) { this.currentDate = new Date(); // Compare soley on date, without factoring in time. this.currentDate.setHours(0, 0, 0, 0); this.events$ = this.getEvents(); + this.upcomingEvents$ = this.events$.pipe( + map(events => + events.filter(event => event.endDate >= this.currentDate) + ) + ); + this.pastEvents$ = this.events$.pipe( + map(events => + events.filter(event => event.endDate < this.currentDate) + ) + ); } /** From 5939a05c5139f564c98f8a12aa80f4fb79b76d15 Mon Sep 17 00:00:00 2001 From: ijz953 Date: Thu, 14 Mar 2019 11:31:33 -0400 Subject: [PATCH 13/19] docs: testing the event service --- .../events/event.service.spec.ts | 35 ++++++++++++++++--- .../custom-elements/events/event.service.ts | 2 +- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/projects/ngrx.io/src/app/custom-elements/events/event.service.spec.ts b/projects/ngrx.io/src/app/custom-elements/events/event.service.spec.ts index 727101710e..d660e5516b 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event.service.spec.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event.service.spec.ts @@ -19,6 +19,7 @@ describe('EventService', () => { }); eventService = injector.get(EventService); + eventService.currentDate = new Date('01-02-2019'); httpMock = injector.get(HttpTestingController); }); @@ -30,19 +31,20 @@ describe('EventService', () => { }); describe('#events', () => { - let events: Event[]; + let upcomingEvents: Event[]; + let pastEvents: Event[]; let testData: EventResponse[]; beforeEach(() => { testData = getTestEventResponse(); httpMock.expectOne({}).flush(testData); - eventService.upcomingEvents.subscribe(results => (events = results)); - eventService.pastEvents.subscribe(results => (events = results)); + eventService.upcomingEvents$.subscribe(results => (upcomingEvents = results)); + eventService.pastEvents$.subscribe(results => (pastEvents = results)); }); it('upcomingEvents observable should complete', () => { let completed = false; - eventService.upcomingEvents.subscribe( + eventService.upcomingEvents$.subscribe( undefined, undefined, () => (completed = true) @@ -52,7 +54,7 @@ describe('EventService', () => { it('pastEvents observable should complete', () => { let completed = false; - eventService.pastEvents.subscribe( + eventService.pastEvents$.subscribe( undefined, undefined, () => (completed = true) @@ -60,6 +62,29 @@ describe('EventService', () => { expect(completed).toBe(true, 'observable completed'); }); + describe('upcoming events', () => { + it('should emit', () => { + expect(upcomingEvents.length).toEqual(3) + }); + + it('should correct set the date range', () => { + expect(upcomingEvents[0].dateRangeString).toEqual('January 1 - 3, 2019'); + expect(upcomingEvents[1].dateRangeString).toEqual('April 1, 2019'); + expect(upcomingEvents[2].dateRangeString).toEqual('April 2, 2019'); + }); + }); + + describe('past events', () => { + it('should emit', () => { + expect(pastEvents.length).toEqual(2) + }); + + it('should correct set the date range', () => { + expect(pastEvents[0].dateRangeString).toEqual('June 28 - July 1, 2018'); + expect(pastEvents[1].dateRangeString).toEqual('December 25, 2018 - January 1, 2019'); + }); + }); + // it('should reshape the contributor json to expected result', () => { // const groupNames = contribs.map(g => g.name).join(','); // expect(groupNames).toEqual('Angular,GDE'); diff --git a/projects/ngrx.io/src/app/custom-elements/events/event.service.ts b/projects/ngrx.io/src/app/custom-elements/events/event.service.ts index b97c37b7b0..acd1720d27 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event.service.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event.service.ts @@ -9,7 +9,7 @@ const resourcesPath = CONTENT_URL_PREFIX + 'events.json'; @Injectable() export class EventService { - private currentDate: Date; + currentDate: Date; private events$: Observable; upcomingEvents$: Observable; pastEvents$: Observable; From 3e3548ca458bdc929f4f2f97b6be237dc153da05 Mon Sep 17 00:00:00 2001 From: ijz953 Date: Thu, 14 Mar 2019 11:57:03 -0400 Subject: [PATCH 14/19] docs: adding event list component tests --- .../ngrx.io/content/marketing/events.json | 2 +- .../events/event-list.component.spec.ts | 80 +++++-------------- 2 files changed, 19 insertions(+), 63 deletions(-) diff --git a/projects/ngrx.io/content/marketing/events.json b/projects/ngrx.io/content/marketing/events.json index 75e930bbf4..022fc75035 100644 --- a/projects/ngrx.io/content/marketing/events.json +++ b/projects/ngrx.io/content/marketing/events.json @@ -26,7 +26,7 @@ "endDate": "10-03-2018" }, { - "name": "AngularMix - Use the discount code \"RYAN\" or \"ROBERTS\" to receive $50 off your registration!", + "name": "AngularMix", "url": "http://www.angularmix.com", "location": "Orlando, Florida", "startDate": "10-10-2018", diff --git a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts index 1537e7d864..279415f4b8 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts @@ -1,73 +1,29 @@ -import { ReflectiveInjector } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; import { EventListComponent } from './event-list.component'; -import { EventResponse } from './event.model'; +import { of } from 'rxjs'; +import { EventService } from './event.service'; + +class TestEventService { + upcomingEvents$ = of(); + pastEvents$ = of(); +} -// Testing the component class behaviors, independent of its template -// Let e2e tests verify how it displays. describe('EventListComponent', () => { + let fixture: ComponentFixture; let component: EventListComponent; - let injector: ReflectiveInjector; beforeEach(() => { - injector = ReflectiveInjector.resolveAndCreate([ - EventListComponent - ]); - }); + TestBed.configureTestingModule({ + declarations: [ EventListComponent ], + providers: [{ provide: EventService, useClass: TestEventService }] + }); - it('should put each event into the correct bucket and correctly format the date range string', () => { - component = getComponent(); - component.currentDate = new Date('01-02-2019'); - const mockEvents: EventResponse[] = [ - { - name: 'conf1', - url: '', - location: '', - startDate: '06-28-2018', - endDate: '07-01-2018' - }, - { - name: 'conf2', - url: '', - location: '', - startDate: '12-25-2018', - endDate: '01-01-2019' - }, - { - name: 'conf3', - url: '', - location: '', - startDate: '01-01-2019', - endDate: '01-03-2019' - }, - { - name: 'conf4', - url: '', - location: '', - endDate: '04-01-2019' - }, - { - name: 'conf5', - url: '', - location: '', - startDate: '04-02-2019', - endDate: '04-02-2019' - }, - ]; - component.events = mockEvents; - expect(component.pastEvents.length).toEqual(2); - expect(component.upcomingEvents.length).toEqual(3); - expect(component.pastEvents[0].dateRangeString).toEqual('June 28 - July 1, 2018'); - expect(component.pastEvents[1].dateRangeString).toEqual('December 25, 2018 - January 1, 2019'); - expect(component.upcomingEvents[0].dateRangeString).toEqual('January 1 - 3, 2019'); - expect(component.upcomingEvents[1].dateRangeString).toEqual('April 1, 2019'); - expect(component.upcomingEvents[2].dateRangeString).toEqual('April 2, 2019'); + fixture = TestBed.createComponent(EventListComponent); + component = fixture.componentInstance; }); - - //// Test Helpers //// - function getComponent(): EventListComponent { - const comp = injector.get(EventListComponent); - return comp; - } + it('should create', () => { + expect(component).toBeTruthy(); + }); }); From 518223b8f773360edd95b11a305d9b6502a1c8f5 Mon Sep 17 00:00:00 2001 From: ijz953 Date: Thu, 14 Mar 2019 12:22:19 -0400 Subject: [PATCH 15/19] docs: improving event list tests --- .../events/event-list.component.spec.ts | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts index 279415f4b8..a04ad7d164 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts @@ -2,10 +2,31 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { EventListComponent } from './event-list.component'; import { of } from 'rxjs'; import { EventService } from './event.service'; +import { Event } from './event.model'; + +const mockUpcomingEvents: Event[] = [ + { + name: 'NG-Rome', + url: 'https://ngrome.io/', + location: 'Rome, Italy', + endDate: new Date('10-07-2019'), + dateRangeString: 'October 7, 2019' + } +]; + +const mockPastEvents: Event[] = [ + { + name: 'DevFestATL', + url: 'http://devfestatl.com', + location: 'Atlanta, Georgia', + endDate: new Date('09-22-2018'), + dateRangeString: 'September 22, 2018' + } +]; class TestEventService { - upcomingEvents$ = of(); - pastEvents$ = of(); + upcomingEvents$ = of(mockUpcomingEvents); + pastEvents$ = of(mockPastEvents); } describe('EventListComponent', () => { @@ -26,4 +47,12 @@ describe('EventListComponent', () => { it('should create', () => { expect(component).toBeTruthy(); }); + + it('should set the upcomingEvents', () => { + component.upcomingEvents$.subscribe(events => expect(events).toEqual(mockUpcomingEvents)); + }); + + it('should set the pastEvents', () => { + component.pastEvents$.subscribe(events => expect(events).toEqual(mockPastEvents)); + }); }); From 97428fa77ce36a96700542a6784ce17134910b7f Mon Sep 17 00:00:00 2001 From: ijz953 Date: Thu, 14 Mar 2019 12:28:53 -0400 Subject: [PATCH 16/19] docs: removing commented code --- .../events/event.service.spec.ts | 20 ++----------------- 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/projects/ngrx.io/src/app/custom-elements/events/event.service.spec.ts b/projects/ngrx.io/src/app/custom-elements/events/event.service.spec.ts index d660e5516b..78e57ba201 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event.service.spec.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event.service.spec.ts @@ -68,7 +68,7 @@ describe('EventService', () => { }); it('should correct set the date range', () => { - expect(upcomingEvents[0].dateRangeString).toEqual('January 1 - 3, 2019'); + expect(upcomingEvents[0].dateRangeString).toEqual('January 1 - 2, 2019'); expect(upcomingEvents[1].dateRangeString).toEqual('April 1, 2019'); expect(upcomingEvents[2].dateRangeString).toEqual('April 2, 2019'); }); @@ -84,23 +84,7 @@ describe('EventService', () => { expect(pastEvents[1].dateRangeString).toEqual('December 25, 2018 - January 1, 2019'); }); }); - - // it('should reshape the contributor json to expected result', () => { - // const groupNames = contribs.map(g => g.name).join(','); - // expect(groupNames).toEqual('Angular,GDE'); - // }); - - // it('should have expected "GDE" contribs in order', () => { - // const gde = contribs[1]; - // const actualAngularNames = gde.contributors.map(l => l.name).join(','); - // const expectedAngularNames = [testData.jeffcross, testData.kapunahelewong] - // .map(l => l.name) - // .join(','); - // expect(actualAngularNames).toEqual(expectedAngularNames); - // }); }); - - it('should do WHAT(?) if the request fails'); }); function getTestEventResponse(): EventResponse[] { @@ -124,7 +108,7 @@ function getTestEventResponse(): EventResponse[] { url: '', location: '', startDate: '01-01-2019', - endDate: '01-03-2019' + endDate: '01-02-2019' }, { name: 'conf4', From 1159e80202f9b83d907dfecee4e689fe9223f214 Mon Sep 17 00:00:00 2001 From: ijz953 Date: Thu, 14 Mar 2019 12:30:52 -0400 Subject: [PATCH 17/19] docs: rename resourcesPath to eventsPath --- .../ngrx.io/src/app/custom-elements/events/event.service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/ngrx.io/src/app/custom-elements/events/event.service.ts b/projects/ngrx.io/src/app/custom-elements/events/event.service.ts index acd1720d27..4627210edc 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event.service.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event.service.ts @@ -5,7 +5,7 @@ import { publishLast, map } from 'rxjs/operators'; import { CONTENT_URL_PREFIX } from 'app/documents/document.service'; import { EventResponse, Event } from './event.model'; -const resourcesPath = CONTENT_URL_PREFIX + 'events.json'; +const eventsPath = CONTENT_URL_PREFIX + 'events.json'; @Injectable() export class EventService { @@ -35,7 +35,7 @@ export class EventService { * Fetch Event JSON from file and return an Observable that emits an Event array. */ private getEvents(): Observable { - const events = this.http.get(resourcesPath).pipe( + const events = this.http.get(eventsPath).pipe( map(eventResponses => eventResponses.map(eventResponse => { const startDate = eventResponse.startDate ? new Date(eventResponse.startDate) : undefined; From 387753c191e9ae2120f12e5598c8a15715c47801 Mon Sep 17 00:00:00 2001 From: ijz953 Date: Thu, 14 Mar 2019 14:53:09 -0400 Subject: [PATCH 18/19] docs: pull request refactor use spaces in test describe string, correct define model by ending in semi colon --- .../custom-elements/events/event-list.component.spec.ts | 2 +- .../ngrx.io/src/app/custom-elements/events/event.model.ts | 4 ++-- .../src/app/custom-elements/events/event.service.spec.ts | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts index a04ad7d164..345523a7f0 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts @@ -29,7 +29,7 @@ class TestEventService { pastEvents$ = of(mockPastEvents); } -describe('EventListComponent', () => { +describe('Event List Component', () => { let fixture: ComponentFixture; let component: EventListComponent; diff --git a/projects/ngrx.io/src/app/custom-elements/events/event.model.ts b/projects/ngrx.io/src/app/custom-elements/events/event.model.ts index aab37c5d35..6d899b9431 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event.model.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event.model.ts @@ -10,7 +10,7 @@ export interface Event { name: string; url: string; location: string; - startDate?: Date, - endDate: Date + startDate?: Date; + endDate: Date; dateRangeString: string; } diff --git a/projects/ngrx.io/src/app/custom-elements/events/event.service.spec.ts b/projects/ngrx.io/src/app/custom-elements/events/event.service.spec.ts index 78e57ba201..d53dba33b9 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event.service.spec.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event.service.spec.ts @@ -7,7 +7,7 @@ import { TestBed } from '@angular/core/testing'; import { EventService } from './event.service'; import { Event, EventResponse } from './event.model'; -describe('EventService', () => { +describe('Event Service', () => { let injector: Injector; let eventService: EventService; let httpMock: HttpTestingController; @@ -30,7 +30,7 @@ describe('EventService', () => { expect(req.request.url).toBe('generated/events.json'); }); - describe('#events', () => { + describe('events', () => { let upcomingEvents: Event[]; let pastEvents: Event[]; let testData: EventResponse[]; @@ -42,7 +42,7 @@ describe('EventService', () => { eventService.pastEvents$.subscribe(results => (pastEvents = results)); }); - it('upcomingEvents observable should complete', () => { + it('upcomingEvents$ observable should complete', () => { let completed = false; eventService.upcomingEvents$.subscribe( undefined, @@ -52,7 +52,7 @@ describe('EventService', () => { expect(completed).toBe(true, 'observable completed'); }); - it('pastEvents observable should complete', () => { + it('pastEvents$ observable should complete', () => { let completed = false; eventService.pastEvents$.subscribe( undefined, From fc30ba5c6ca5fd57de4e58f30d1f44c51de5487e Mon Sep 17 00:00:00 2001 From: ijz953 Date: Fri, 15 Mar 2019 11:10:30 -0400 Subject: [PATCH 19/19] docs: refactor to use UTC YYYY-MM-DD format and moved date range function into a pipe --- .../ngrx.io/content/marketing/events.json | 58 +++++++++-------- .../events/event-date-range.pipe.spec.ts | 64 +++++++++++++++++++ .../events/event-date-range.pipe.ts | 55 ++++++++++++++++ .../events/event-list.component.spec.ts | 9 ++- .../events/event-list.component.ts | 4 +- .../events/event-list.module.ts | 3 +- .../app/custom-elements/events/event.model.ts | 1 - .../events/event.service.spec.ts | 31 +++------ .../custom-elements/events/event.service.ts | 43 ++----------- 9 files changed, 172 insertions(+), 96 deletions(-) create mode 100644 projects/ngrx.io/src/app/custom-elements/events/event-date-range.pipe.spec.ts create mode 100644 projects/ngrx.io/src/app/custom-elements/events/event-date-range.pipe.ts diff --git a/projects/ngrx.io/content/marketing/events.json b/projects/ngrx.io/content/marketing/events.json index 022fc75035..74e3b6c033 100644 --- a/projects/ngrx.io/content/marketing/events.json +++ b/projects/ngrx.io/content/marketing/events.json @@ -3,111 +3,113 @@ "name": "NgColombia", "url": "http://www.ngcolombia.com", "location": "Medellín, Colombia", - "startDate": "09-06-2018", - "endDate": "09-07-2018" + "startDate": "2018-09-06", + "endDate": "2018-09-07" }, { "name": "DevFestATL", "url": "http://devfestatl.com", "location": "Atlanta, Georgia", - "endDate": "09-22-2018" + "endDate": "2018-09-22" }, { "name": "Framework Summit", "url": "http://frameworksummit.com", "location": "Park City, Utah", - "endDate": "09-22-2018" + "endDate": "2018-09-22" }, { "name": "DevFestATL", "url": "http://devfestatl.com", "location": "Atlanta, Georgia", - "startDate": "10-02-2018", - "endDate": "10-03-2018" + "startDate": "2018-10-02", + "endDate": "2018-10-03" }, { "name": "AngularMix", "url": "http://www.angularmix.com", "location": "Orlando, Florida", - "startDate": "10-10-2018", - "endDate": "10-12-2018" + "startDate": "2018-10-10", + "endDate": "2018-10-12" }, { "name": "AngularConnect", - "url": "http://www.angularconnect.com", + "url": "https://www.angularconnect.com", "location": "Excel, London", - "startDate": "11-06-2018", - "endDate": "11-07-2018" + "startDate": "2018-11-06", + "endDate": "2018-11-07" }, { "name": "ngAtlanta", "url": "http://ng-atl.org/", "location": "Atlanta, Georgia", - "startDate": "01-09-2019", - "endDate": "01-12-2019" + "startDate": "2019-01-09", + "endDate": "2019-01-12" }, { "name": "ng-India", "url": "https://www.ng-ind.com", "location": "Gurgaon, India", - "endDate": "02-23-2019" + "endDate": "2019-02-23" }, { "name": "Open Source 101", "url": "https://opensource101.com/", "location": "Columbia, South Carolina", - "endDate": "04-18-2019" + "endDate": "2019-04-18" }, { "name": "NG-Conf", "url": "https://www.ng-conf.org", "location": "Salt Lake City, Utah", - "startDate": "05-01-2019", "endDate": "05-03-2019"}, + "startDate": "2019-05-01", + "endDate": "2019-05-03" + }, { "name": "ngVikings", "url": "https://ngvikings.org/", "location": "Copenhagen, Denmark", - "startDate": "05-26-2019", - "endDate": "05-28-2019" + "startDate": "2019-05-26", + "endDate": "2019-05-28" }, { "name": "REFACTR.TECH", "url": "https://refactr.tech/", "location": "Atlanta, Georgia", - "startDate": "06-05-2019", - "endDate": "06-07-2019" + "startDate": "2019-06-05", + "endDate": "2019-06-07" }, { "name": "AngularUP", "url": "https://angular-up.com/", "location": "Tel Aviv, Israel", - "endDate": "06-12-2019" + "endDate": "2019-06-12" }, { "name": "NG-MY", "url": "https://ng-my.org/", "location": "Kuala Lumpur, Malaysia", - "startDate": "07-06-2019", - "endDate": "07-07-2019" + "startDate": "2019-07-06", + "endDate": "2019-07-07" }, { "name": "ngDenver", "url": "http://angulardenver.com/", "location": "Denver, Colorado", - "startDate": "08-01-2019", - "endDate": "08-02-2019" + "startDate": "2019-08-01", + "endDate": "2019-08-02" }, { "name": "AngularConnect", "url": "https://www.angularconnect.com/", "location": "London, United Kingdom", - "startDate": "09-19-2019", - "endDate": "09-20-2019" + "startDate": "2019-09-19", + "endDate": "2019-09-20" }, { "name": "NG-Rome", "url": "https://ngrome.io/", "location": "Rome, Italy", - "endDate": "10-07-2019" + "endDate": "2019-10-07" } ] diff --git a/projects/ngrx.io/src/app/custom-elements/events/event-date-range.pipe.spec.ts b/projects/ngrx.io/src/app/custom-elements/events/event-date-range.pipe.spec.ts new file mode 100644 index 0000000000..5a9f284c53 --- /dev/null +++ b/projects/ngrx.io/src/app/custom-elements/events/event-date-range.pipe.spec.ts @@ -0,0 +1,64 @@ +import { EventDateRangePipe } from './event-date-range.pipe'; +import { Event } from './event.model'; + +describe('Pipe: Event Date Range', () => { + let pipe: EventDateRangePipe; + + beforeEach(() => { + pipe = new EventDateRangePipe(); + }); + + it('providing no startDate should format only the endDate in MM DD, YYYY', () => { + const event: Event = { + name: '', + url: '', + location: '', + endDate: new Date('2019-01-01') + }; + expect(pipe.transform(event)).toBe('January 1, 2019'); + }); + + it('providing the same startDate and endDate should format only one in MM DD, YYYY', () => { + const event: Event = { + name: '', + url: '', + location: '', + startDate: new Date('2019-01-01'), + endDate: new Date('2019-01-01') + }; + expect(pipe.transform(event)).toBe('January 1, 2019'); + }); + + it('providing different days in the same month and year should format in MM DD - DD, YYYY format', () => { + const event: Event = { + name: '', + url: '', + location: '', + startDate: new Date('2019-01-01'), + endDate: new Date('2019-01-02') + }; + expect(pipe.transform(event)).toBe('January 1 - 2, 2019'); + }); + + it('providing different days and months in the same year should format in MM DD - MM DD, YYYY format', () => { + const event: Event = { + name: '', + url: '', + location: '', + startDate: new Date('2019-01-01'), + endDate: new Date('2019-01-02') + }; + expect(pipe.transform(event)).toBe('January 1 - 2, 2019'); + }); + + it('providing different days, months, and years should format in MM DD, YYYY - MM DD, YYYY format', () => { + const event: Event = { + name: '', + url: '', + location: '', + startDate: new Date('2018-12-31'), + endDate: new Date('2019-01-01') + }; + expect(pipe.transform(event)).toBe('December 31, 2018 - January 1, 2019'); + }); +}); diff --git a/projects/ngrx.io/src/app/custom-elements/events/event-date-range.pipe.ts b/projects/ngrx.io/src/app/custom-elements/events/event-date-range.pipe.ts new file mode 100644 index 0000000000..f3d7076712 --- /dev/null +++ b/projects/ngrx.io/src/app/custom-elements/events/event-date-range.pipe.ts @@ -0,0 +1,55 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import { Event } from './event.model'; + +/** + * Transforms the startDate and endDate for a given event into a dange range string. + * undefined until '01-01-2019' -> 'January 1, 2019' + * '01-01-2019' until '01-01-2019' -> 'January 1, 2019' + * '01-01-2019' until '01-02-2019' -> 'January 1 - 2, 2019' + * '01-28-2019' until '02-01-2019' -> 'January 28 - February 1, 2019' + * '12-31-2018' until '01-01-2019' -> 'December 31, 2018 - January 1, 2019' + */ +@Pipe({name: 'eventDateRange'}) +export class EventDateRangePipe implements PipeTransform { + transform(event: Event): string { + const startDate = event.startDate; + const endDate = event.endDate; + if (!startDate || startDate.getTime() === endDate.getTime()) { + return getDateString(endDate); + } else { + if (getMonth(startDate) === getMonth(endDate) && getYear(startDate) === getYear(endDate)) { + return getMonth(startDate) + + ' ' + getDay(startDate) + ' - ' + getDay(endDate) + + ', ' + getYear(startDate); + } else if (getYear(startDate) === getYear(endDate)) { + return getMonth(startDate) + + ' ' + getDay(startDate) + + ' - ' + getMonth(endDate) + + ' ' + getDay(endDate) + + ', ' + getYear(startDate); + } else { + return getDateString(startDate) + + ' - ' + getDateString(endDate); + } + } + } +} + +const getDay = (date: Date) => date.getUTCDate(); +const getMonth = (date: Date) => months[date.getUTCMonth()]; +const getYear = (date: Date) => date.getUTCFullYear(); +const getDateString = (date: Date) => getMonth(date) + ' ' + getDay(date) + ', ' + getYear(date); +const months = [ + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December' +]; diff --git a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts index 345523a7f0..3c6a39c13a 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.spec.ts @@ -3,14 +3,14 @@ import { EventListComponent } from './event-list.component'; import { of } from 'rxjs'; import { EventService } from './event.service'; import { Event } from './event.model'; +import { EventDateRangePipe } from './event-date-range.pipe'; const mockUpcomingEvents: Event[] = [ { name: 'NG-Rome', url: 'https://ngrome.io/', location: 'Rome, Italy', - endDate: new Date('10-07-2019'), - dateRangeString: 'October 7, 2019' + endDate: new Date('2019-10-07') } ]; @@ -19,8 +19,7 @@ const mockPastEvents: Event[] = [ name: 'DevFestATL', url: 'http://devfestatl.com', location: 'Atlanta, Georgia', - endDate: new Date('09-22-2018'), - dateRangeString: 'September 22, 2018' + endDate: new Date('2018-09-22') } ]; @@ -36,7 +35,7 @@ describe('Event List Component', () => { beforeEach(() => { TestBed.configureTestingModule({ - declarations: [ EventListComponent ], + declarations: [ EventListComponent, EventDateRangePipe ], providers: [{ provide: EventService, useClass: TestEventService }] }); diff --git a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts index fa34ca3ff6..08e5fa117c 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event-list.component.ts @@ -19,7 +19,7 @@ import { Observable } from 'rxjs'; {{upcomingEvent.name}} {{upcomingEvent.location}} - {{upcomingEvent.dateRangeString}} + {{upcomingEvent | eventDateRange}} @@ -36,7 +36,7 @@ import { Observable } from 'rxjs'; {{pastEvent.name}} {{pastEvent.location}} - {{pastEvent.dateRangeString}} + {{pastEvent | eventDateRange}} diff --git a/projects/ngrx.io/src/app/custom-elements/events/event-list.module.ts b/projects/ngrx.io/src/app/custom-elements/events/event-list.module.ts index bcdd7949c3..0a5e8cb060 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event-list.module.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event-list.module.ts @@ -3,10 +3,11 @@ import { CommonModule } from '@angular/common'; import { WithCustomElementComponent } from '../element-registry'; import { EventListComponent } from './event-list.component'; import { EventService } from './event.service'; +import { EventDateRangePipe } from './event-date-range.pipe'; @NgModule({ imports: [ CommonModule ], - declarations: [ EventListComponent ], + declarations: [ EventListComponent, EventDateRangePipe ], entryComponents: [ EventListComponent ], providers: [ EventService ] }) diff --git a/projects/ngrx.io/src/app/custom-elements/events/event.model.ts b/projects/ngrx.io/src/app/custom-elements/events/event.model.ts index 6d899b9431..6a4599f67f 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event.model.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event.model.ts @@ -12,5 +12,4 @@ export interface Event { location: string; startDate?: Date; endDate: Date; - dateRangeString: string; } diff --git a/projects/ngrx.io/src/app/custom-elements/events/event.service.spec.ts b/projects/ngrx.io/src/app/custom-elements/events/event.service.spec.ts index d53dba33b9..ed51276211 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event.service.spec.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event.service.spec.ts @@ -19,7 +19,7 @@ describe('Event Service', () => { }); eventService = injector.get(EventService); - eventService.currentDate = new Date('01-02-2019'); + eventService.currentDate = new Date('2019-01-02'); httpMock = injector.get(HttpTestingController); }); @@ -66,23 +66,12 @@ describe('Event Service', () => { it('should emit', () => { expect(upcomingEvents.length).toEqual(3) }); - - it('should correct set the date range', () => { - expect(upcomingEvents[0].dateRangeString).toEqual('January 1 - 2, 2019'); - expect(upcomingEvents[1].dateRangeString).toEqual('April 1, 2019'); - expect(upcomingEvents[2].dateRangeString).toEqual('April 2, 2019'); - }); }); describe('past events', () => { it('should emit', () => { expect(pastEvents.length).toEqual(2) }); - - it('should correct set the date range', () => { - expect(pastEvents[0].dateRangeString).toEqual('June 28 - July 1, 2018'); - expect(pastEvents[1].dateRangeString).toEqual('December 25, 2018 - January 1, 2019'); - }); }); }); }); @@ -93,35 +82,35 @@ function getTestEventResponse(): EventResponse[] { name: 'conf1', url: '', location: '', - startDate: '06-28-2018', - endDate: '07-01-2018' + startDate: '2018-06-28', + endDate: '2018-07-01' }, { name: 'conf2', url: '', location: '', - startDate: '12-25-2018', - endDate: '01-01-2019' + startDate: '2018-12-25', + endDate: '2019-01-01' }, { name: 'conf3', url: '', location: '', - startDate: '01-01-2019', - endDate: '01-02-2019' + startDate: '2019-01-01', + endDate: '2019-01-02' }, { name: 'conf4', url: '', location: '', - endDate: '04-01-2019' + endDate: '2019-04-01' }, { name: 'conf5', url: '', location: '', - startDate: '04-02-2019', - endDate: '04-02-2019' + startDate: '2019-04-02', + endDate: '2019-04-02' }, ]; } diff --git a/projects/ngrx.io/src/app/custom-elements/events/event.service.ts b/projects/ngrx.io/src/app/custom-elements/events/event.service.ts index 4627210edc..dccf0394b9 100644 --- a/projects/ngrx.io/src/app/custom-elements/events/event.service.ts +++ b/projects/ngrx.io/src/app/custom-elements/events/event.service.ts @@ -15,9 +15,9 @@ export class EventService { pastEvents$: Observable; constructor(private http: HttpClient) { - this.currentDate = new Date(); - // Compare soley on date, without factoring in time. - this.currentDate.setHours(0, 0, 0, 0); + const now = new Date(); + // Compare soley on UTC date, without factoring in time. + this.currentDate = new Date(Date.UTC(now.getFullYear(), now.getMonth(), now.getDate())); this.events$ = this.getEvents(); this.upcomingEvents$ = this.events$.pipe( map(events => @@ -38,13 +38,10 @@ export class EventService { const events = this.http.get(eventsPath).pipe( map(eventResponses => eventResponses.map(eventResponse => { - const startDate = eventResponse.startDate ? new Date(eventResponse.startDate) : undefined; - const endDate = new Date(eventResponse.endDate); const event: Event = { ...eventResponse, - startDate, - endDate, - dateRangeString: getDateRange(startDate, endDate) + startDate: eventResponse.startDate ? new Date(eventResponse.startDate) : undefined, + endDate: new Date(eventResponse.endDate) }; return event; }) @@ -56,33 +53,3 @@ export class EventService { return events; }; } - -/** - * The date range string for the two given dates - * '01-01-2019' until '01-01-2019' -> 'January 1, 2019' - * '01-01-2019' until '01-02-2019' -> 'January 1 - 2, 2019' - * '01-28-2019' until '02-01-2019' -> 'January 28 - February 1, 2019' - * '12-31-2018' until '01-01-2019' -> 'December 31, 2018 - January 1, 2019' - * @param startDate date the event starts. If undefined, startDate assumed to be same as endDate. - * @param endDate date theh event ends. - */ -function getDateRange(startDate: Date | undefined, endDate: Date): string { - if (!startDate || startDate.getTime() === endDate.getTime()) { - return endDate.toLocaleDateString('en-us', { year: 'numeric', month: 'long', day: 'numeric' }); - } else { - if (startDate.getMonth() === endDate.getMonth()) { - return startDate.toLocaleString('en-us', { month: 'long' }) - + ' ' + startDate.getUTCDate() + ' - ' + endDate.getUTCDate() - + ', ' + startDate.getUTCFullYear(); - } else if (startDate.getUTCFullYear() === endDate.getUTCFullYear()) { - return startDate.toLocaleString('en-us', { month: 'long' }) - + ' ' + startDate.getUTCDate() - + ' - ' + endDate.toLocaleString('en-us', { month: 'long' }) - + ' ' + endDate.getUTCDate() - + ', ' + startDate.getUTCFullYear(); - } else { - return startDate.toLocaleDateString('en-us', { year: 'numeric', month: 'long', day: 'numeric' }) - + ' - ' + endDate.toLocaleDateString('en-us', { year: 'numeric', month: 'long', day: 'numeric' }); - } - } -}