From d803501c310efd61e40c9e4a8979c20120395fb2 Mon Sep 17 00:00:00 2001 From: dan Date: Mon, 18 May 2020 00:29:26 -0600 Subject: [PATCH] Add Youtube Api --- Client/src/app/app-routing.module.ts | 3 +- Client/src/app/app.module.ts | 16 +++- .../app/components/home/home.component.html | 2 +- .../share-popup/share-popup.component.ts | 3 + .../youtube-popup/youtube-popup.component.css | 26 ++++++ .../youtube-popup.component.html | 10 ++ .../youtube-popup.component.spec.ts | 25 +++++ .../youtube-popup/youtube-popup.component.ts | 26 ++++++ .../video-item/video-item.component.css | 92 +++++++++++++++++++ .../video-item/video-item.component.html | 26 ++++++ .../video-item/video-item.component.spec.ts | 25 +++++ .../video-item/video-item.component.ts | 88 ++++++++++++++++++ .../app/components/video/video.component.css | 13 +++ .../app/components/video/video.component.html | 12 +++ .../components/video/video.component.spec.ts | 25 +++++ .../app/components/video/video.component.ts | 15 +++ .../youtube-list/youtube-list-service.ts | 39 ++++++++ .../youtube-list/youtube-list.component.css | 24 +++++ .../youtube-list/youtube-list.component.html | 22 +++++ .../youtube-list.component.spec.ts | 25 +++++ .../youtube-list/youtube-list.component.ts | 58 ++++++++++++ .../youtube-list/youtube-snippet.ts | 48 ++++++++++ Client/src/app/pipes/ofb-date.pipe.ts | 3 + 23 files changed, 621 insertions(+), 5 deletions(-) create mode 100644 Client/src/app/components/popups/youtube-popup/youtube-popup.component.css create mode 100644 Client/src/app/components/popups/youtube-popup/youtube-popup.component.html create mode 100644 Client/src/app/components/popups/youtube-popup/youtube-popup.component.spec.ts create mode 100644 Client/src/app/components/popups/youtube-popup/youtube-popup.component.ts create mode 100644 Client/src/app/components/video-item/video-item.component.css create mode 100644 Client/src/app/components/video-item/video-item.component.html create mode 100644 Client/src/app/components/video-item/video-item.component.spec.ts create mode 100644 Client/src/app/components/video-item/video-item.component.ts create mode 100644 Client/src/app/components/video/video.component.css create mode 100644 Client/src/app/components/video/video.component.html create mode 100644 Client/src/app/components/video/video.component.spec.ts create mode 100644 Client/src/app/components/video/video.component.ts create mode 100644 Client/src/app/components/youtube-list/youtube-list-service.ts create mode 100644 Client/src/app/components/youtube-list/youtube-list.component.css create mode 100644 Client/src/app/components/youtube-list/youtube-list.component.html create mode 100644 Client/src/app/components/youtube-list/youtube-list.component.spec.ts create mode 100644 Client/src/app/components/youtube-list/youtube-list.component.ts create mode 100644 Client/src/app/components/youtube-list/youtube-snippet.ts diff --git a/Client/src/app/app-routing.module.ts b/Client/src/app/app-routing.module.ts index 454c7b8..a6178af 100644 --- a/Client/src/app/app-routing.module.ts +++ b/Client/src/app/app-routing.module.ts @@ -19,6 +19,7 @@ import { ContributorAllReportsComponent } from './components/contributor-all-rep import { LiveStreamComponent } from './components/live-stream/live-stream.component'; import { VideoServicesComponent } from './components/video-services/video-services.component'; import { ImageComponent } from './components/image/image.component'; +import { VideoComponent } from './components/video/video.component'; const routes = [ @@ -52,7 +53,7 @@ const routes = }, { path: 'video', - component: VideoServicesComponent + component: VideoComponent }, { path: 'sermons/:id', diff --git a/Client/src/app/app.module.ts b/Client/src/app/app.module.ts index c4493dd..4759162 100644 --- a/Client/src/app/app.module.ts +++ b/Client/src/app/app.module.ts @@ -79,6 +79,11 @@ import { ContributorAllReportsComponent } from './components/contributor-all-rep import { LiveStreamComponent } from './components/live-stream/live-stream.component'; import { VideoServicesComponent } from './components/video-services/video-services.component'; import { ImageComponent } from './components/image/image.component'; +import { YoutubeListComponent } from './components/youtube-list/youtube-list.component'; +import { VideoComponent } from './components/video/video.component'; +import { YoutubeListService } from './components/youtube-list/youtube-list-service'; +import { VideoItemComponent } from './components/video-item/video-item.component'; +import { YoutubePopupComponent } from './components/popups/youtube-popup/youtube-popup.component'; @@ -129,7 +134,11 @@ import { ImageComponent } from './components/image/image.component'; ContributorYearlyReportComponent, ContributorAllReportsComponent, LiveStreamComponent, - ImageComponent + ImageComponent, + YoutubeListComponent, + VideoComponent, + VideoItemComponent, + YoutubePopupComponent ], imports: [ BrowserModule, @@ -150,7 +159,7 @@ import { ImageComponent } from './components/image/image.component'; MatRadioModule, MatCheckboxModule ], - providers: [LoginService,PrintService,UserService,GoogleAnalyticsService,SermonService,TransactionService,EventService,EmailService,MissionarySupportService,WindowRefService], + providers: [LoginService,PrintService,UserService,GoogleAnalyticsService,SermonService,TransactionService,EventService,EmailService,MissionarySupportService,YoutubeListService,WindowRefService], entryComponents: [AddSermonPopupComponent, LoginPopupComponent, OkPopupComponent, @@ -161,7 +170,8 @@ import { ImageComponent } from './components/image/image.component'; AddEventPopupComponent, AddUserPopupComponent, VideoPopupComponent, - AddTransactionPopupComponent], + AddTransactionPopupComponent, + YoutubePopupComponent], bootstrap: [AppComponent] }) export class AppModule { } diff --git a/Client/src/app/components/home/home.component.html b/Client/src/app/components/home/home.component.html index ac80499..e29becb 100644 --- a/Client/src/app/components/home/home.component.html +++ b/Client/src/app/components/home/home.component.html @@ -55,7 +55,7 @@


- live_tv Click here to watch online + live_tv Click here to watch online

headset Click here to listen online diff --git a/Client/src/app/components/popups/share-popup/share-popup.component.ts b/Client/src/app/components/popups/share-popup/share-popup.component.ts index 6b99c77..673b777 100644 --- a/Client/src/app/components/popups/share-popup/share-popup.component.ts +++ b/Client/src/app/components/popups/share-popup/share-popup.component.ts @@ -33,6 +33,9 @@ export class SharePopupComponent implements OnInit { if (this.data.prefix === 'o') { this.shareUrl = this.document.location.protocol + '//' + this.document.location.hostname + port + this.shareBaseUrl + data.prefix + data.otherName; } + if (this.data.url) { + this.shareUrl = this.data.url; + } this.facebookIframeUrl = this.urlPartA + this.shareUrl + this.urlPartB; this.twitterUrl = this.twitterPartA + data.title + " - " + data.description + "&url=" + this.shareUrl; } diff --git a/Client/src/app/components/popups/youtube-popup/youtube-popup.component.css b/Client/src/app/components/popups/youtube-popup/youtube-popup.component.css new file mode 100644 index 0000000..8df3496 --- /dev/null +++ b/Client/src/app/components/popups/youtube-popup/youtube-popup.component.css @@ -0,0 +1,26 @@ +iframe { + max-width: 100%; +} + +h2 { + display: inline-block; + margin-bottom: 15px; + width: calc(100% - 50px); +} + +hr{ + margin-bottom: 15px; +} + +i { + font-size: 24pt; + +} + +.vertical-align-top { + vertical-align: top; +} + +.align-right { + text-align: right; +} \ No newline at end of file diff --git a/Client/src/app/components/popups/youtube-popup/youtube-popup.component.html b/Client/src/app/components/popups/youtube-popup/youtube-popup.component.html new file mode 100644 index 0000000..5c1bc8c --- /dev/null +++ b/Client/src/app/components/popups/youtube-popup/youtube-popup.component.html @@ -0,0 +1,10 @@ +

+

{{title}}

+ +
+
+
+ +
\ No newline at end of file diff --git a/Client/src/app/components/popups/youtube-popup/youtube-popup.component.spec.ts b/Client/src/app/components/popups/youtube-popup/youtube-popup.component.spec.ts new file mode 100644 index 0000000..f1cd3da --- /dev/null +++ b/Client/src/app/components/popups/youtube-popup/youtube-popup.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { YoutubePopupComponent } from './youtube-popup.component'; + +describe('YoutubePopupComponent', () => { + let component: YoutubePopupComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ YoutubePopupComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(YoutubePopupComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Client/src/app/components/popups/youtube-popup/youtube-popup.component.ts b/Client/src/app/components/popups/youtube-popup/youtube-popup.component.ts new file mode 100644 index 0000000..9f0d789 --- /dev/null +++ b/Client/src/app/components/popups/youtube-popup/youtube-popup.component.ts @@ -0,0 +1,26 @@ +import { Component, OnInit, Inject } from '@angular/core'; +import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material'; + +@Component({ + selector: 'app-youtube-popup', + templateUrl: './youtube-popup.component.html', + styleUrls: ['./youtube-popup.component.css'] +}) +export class YoutubePopupComponent implements OnInit { + + public title: string; + public embedUrl: string; + + constructor(@Inject(MAT_DIALOG_DATA) public data: any, private MatDialogRef: MatDialogRef) { + this.title = data.title; + this.embedUrl = data.embedUrl; + } + + ngOnInit() { + } + + public close() { + this.MatDialogRef.close(); + } + +} diff --git a/Client/src/app/components/video-item/video-item.component.css b/Client/src/app/components/video-item/video-item.component.css new file mode 100644 index 0000000..1b6e10a --- /dev/null +++ b/Client/src/app/components/video-item/video-item.component.css @@ -0,0 +1,92 @@ +.wrapper{ + box-shadow: 0 3px 1px -2px rgba(0,0,0,.2), 0 2px 2px 0 rgba(0,0,0,.14), 0 1px 5px 0 rgba(0,0,0,.12); +} + +.photo{ + box-sizing: border-box; + display: inline-block; + max-width: 180px; + margin: 0; + vertical-align: top; +} + +.fade{ + text-align: center; + vertical-align: bottom; + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: 20px; + padding-bottom: 2px; + /* Permalink - use to edit and share this gradient: http://colorzilla.com/gradient-editor/#ffffff+0,ffffff+100&0+0,0.8+100 */ + background: -moz-linear-gradient(top, rgba(255,255,255,0) 0%, rgba(255,255,255,0.8) 100%); /* FF3.6-15 */ + background: -webkit-linear-gradient(top, rgba(255,255,255,0) 0%,rgba(255,255,255,0.8) 100%); /* Chrome10-25,Safari5.1-6 */ + background: linear-gradient(to bottom, rgba(255,255,255,0) 0%,rgba(255,255,255,0.8) 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#00ffffff', endColorstr='#ccffffff',GradientType=0 ); /* IE6-9 */ +} + +.photo button{ + padding: 0; + vertical-align: top; +} + +button img{ + display: block; + height: 100%; + width: 100%; +} + +.info{ + display: inline-block; + vertical-align: top; + padding: 2px 2px 8px 5px; + box-sizing: border-box; + width: calc(100% - 180px); + overflow-y: hidden; + position: relative; + height: 100px; +} + +.title{ + font-weight: bold; +} + +.date, .author{ + font-style: italic; + font-size: 14px; +} + +.description{ + font-size: 14px; + color: darkgray; + word-wrap: none; + border-top: 0px solid lightgray; + padding-top:6px; + margin-top: 6px; +} +.expanded{ + overflow-y: hidden; +} +.expanded-content{ + margin: 10px; +} + +.buttons, .buttons-edit{ + background-color: lightgray; +} + +.buttons button, .buttons .filler{ + display: inline-block; + width: 50%; +} + +.border{ + margin: 0px 5px 0px 5px; + border-top: 1px inset lightgray; +} + +.buttons-edit button{ + display: inline-block; + width: 50%; +} \ No newline at end of file diff --git a/Client/src/app/components/video-item/video-item.component.html b/Client/src/app/components/video-item/video-item.component.html new file mode 100644 index 0000000..dd7f1d0 --- /dev/null +++ b/Client/src/app/components/video-item/video-item.component.html @@ -0,0 +1,26 @@ +
+
+ +
+ {{ title }} +
+ {{ publishTime | ofbDate:true }} +
+

+ {{ description }} +

+
arrow_drop_downarrow_drop_up
+
+
+

+ {{ description }} +

+
+
+ +
+
\ No newline at end of file diff --git a/Client/src/app/components/video-item/video-item.component.spec.ts b/Client/src/app/components/video-item/video-item.component.spec.ts new file mode 100644 index 0000000..cdc05fd --- /dev/null +++ b/Client/src/app/components/video-item/video-item.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { VideoItemComponent } from './video-item.component'; + +describe('VideoItemComponent', () => { + let component: VideoItemComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ VideoItemComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(VideoItemComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Client/src/app/components/video-item/video-item.component.ts b/Client/src/app/components/video-item/video-item.component.ts new file mode 100644 index 0000000..e98407f --- /dev/null +++ b/Client/src/app/components/video-item/video-item.component.ts @@ -0,0 +1,88 @@ +import { Component, AfterContentInit, Input, Inject } from '@angular/core'; +import { MatDialog, MatDialogConfig } from '@angular/material'; +import { trigger, state, style, transition, animate } from '@angular/animations'; + +import { SharePopupComponent } from './../popups/share-popup/share-popup.component'; +import { YesNoPopupComponent } from './../popups/yes-no-popup/yes-no-popup.component'; +import { YoutubePopupComponent } from '../popups/youtube-popup/youtube-popup.component'; + +@Component({ + selector: 'app-video-item', + templateUrl: './video-item.component.html', + styleUrls: ['./video-item.component.css'], + animations:[ + trigger("inout",[ + state("1", style({ opacity: '1' })), + state("0",style({ opacity: '0' })), + transition('* => 1',[ + animate('500ms ease-in-out') + ]), + transition(':enter',[ + animate('0ms') + ]) + ]), + trigger('toggleAnimation', [ + state('open', style({ + height: '*', + })), + state('closed', style({ + height: '0px', + })), + transition('open <=> closed', animate('500ms ease-in-out')) + ]), + trigger('toggleAnimationFade', [ + state('open', style({ + opacity: 0, + })), + state('closed', style({ + opacity: 1, + })), + transition('open <=> closed', animate('500ms ease-in-out')) + ]) + ] +}) +export class VideoItemComponent implements AfterContentInit { + + public state: string = 'closed'; + + @Input() + id: number; + @Input() + title: string; + @Input() + description: string; + @Input() + publishTime: Date; + @Input() + thumbnailUrl: string; + @Input() + shareUrl: string; + @Input() + embedUrl: string; + public startFadeIn: boolean = false; + @Input() + public delayFadeIn: number = 100; + + constructor(private dialog: MatDialog){ + } + + ngAfterContentInit(): void{ + setTimeout(() => this.startFadeIn = true, this.delayFadeIn); + } + + toggleState(){ + this.state = this.state === 'open' ? 'closed' : 'open' + } + + share(){ + let opts = new MatDialogConfig; + opts.data = { url: this.shareUrl, id: this.id, title: this.title, description: '' }; + let dialog = this.dialog.open(SharePopupComponent, opts); + } + + play(){ + let opts = new MatDialogConfig; + opts.data = { title: this.title, embedUrl:this.embedUrl }; + let dialog = this.dialog.open(YoutubePopupComponent, opts); + } +} diff --git a/Client/src/app/components/video/video.component.css b/Client/src/app/components/video/video.component.css new file mode 100644 index 0000000..b82031c --- /dev/null +++ b/Client/src/app/components/video/video.component.css @@ -0,0 +1,13 @@ + + +.side-bar{ + position: fixed; +} + +.width100{ + width: 100%; +} + +#showAllButton{ + margin-top: 10px; +} diff --git a/Client/src/app/components/video/video.component.html b/Client/src/app/components/video/video.component.html new file mode 100644 index 0000000..a0adb75 --- /dev/null +++ b/Client/src/app/components/video/video.component.html @@ -0,0 +1,12 @@ + +
+ +
+ +
+ + + + diff --git a/Client/src/app/components/video/video.component.spec.ts b/Client/src/app/components/video/video.component.spec.ts new file mode 100644 index 0000000..8b61663 --- /dev/null +++ b/Client/src/app/components/video/video.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { VideoComponent } from './video.component'; + +describe('VideoComponent', () => { + let component: VideoComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ VideoComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(VideoComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Client/src/app/components/video/video.component.ts b/Client/src/app/components/video/video.component.ts new file mode 100644 index 0000000..7e4f57e --- /dev/null +++ b/Client/src/app/components/video/video.component.ts @@ -0,0 +1,15 @@ +import { Component, OnInit } from '@angular/core'; + +@Component({ + selector: 'app-video', + templateUrl: './video.component.html', + styleUrls: ['./video.component.css'] +}) +export class VideoComponent implements OnInit { + + constructor() { } + + ngOnInit() { + } + +} diff --git a/Client/src/app/components/youtube-list/youtube-list-service.ts b/Client/src/app/components/youtube-list/youtube-list-service.ts new file mode 100644 index 0000000..398dd30 --- /dev/null +++ b/Client/src/app/components/youtube-list/youtube-list-service.ts @@ -0,0 +1,39 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { YoutubeSearchResult } from './youtube-snippet'; +import { tap } from 'rxjs/operators'; + +const apiKey = 'AIzaSyDYI1UzFyc-5UvWiN7BqkWm-8vXU6i5Au0'; +const baseUrl = `https://www.googleapis.com/youtube/v3/search`; +const part = `snippet`; +const channelId = `UCplK-bimKe_E8k6Gka87IaQ`; +const maxResults = `20`; +const order = `date`; +const itemType = `video`; + +@Injectable() +export class YoutubeListService { + constructor(private httpClient: HttpClient){} + private nextPageToken: string; + + public getFirstPage() : Observable { + const url = this.getUrl(undefined); + return this.httpClient.get(url).pipe(tap(x => this.nextPageToken = x.nextPageToken)); + } + + public getNextPage() : Observable { + const url = this.getUrl(this.nextPageToken); + return this.httpClient.get(url).pipe(tap(x => this.nextPageToken = x.nextPageToken)); + } + + private getUrl(nextPageToken: string): string { + let url = `${baseUrl}?type=${itemType}&part=${part}&channelId=${channelId}&maxResults=${maxResults}&order=${order}&key=${apiKey}`; + if (nextPageToken) { + url = url + `&pageToken=${nextPageToken}`; + } + return url; + } +} + + diff --git a/Client/src/app/components/youtube-list/youtube-list.component.css b/Client/src/app/components/youtube-list/youtube-list.component.css new file mode 100644 index 0000000..6b566eb --- /dev/null +++ b/Client/src/app/components/youtube-list/youtube-list.component.css @@ -0,0 +1,24 @@ + +.width100 { + width: 100%; +} + +.mt-20 { + margin-top: 20px; +} + +ul{ + list-style: none; +} + +li{ + margin: 40px 0px 40px 0px; /* top right bottom left */ +} + +li:first-child{ + margin-top: 0px; +} + +li:last-child{ + margin-bottom: 0px; +} \ No newline at end of file diff --git a/Client/src/app/components/youtube-list/youtube-list.component.html b/Client/src/app/components/youtube-list/youtube-list.component.html new file mode 100644 index 0000000..dafed8b --- /dev/null +++ b/Client/src/app/components/youtube-list/youtube-list.component.html @@ -0,0 +1,22 @@ + + + + +
    +
  • + + + +
  • +
+ + \ No newline at end of file diff --git a/Client/src/app/components/youtube-list/youtube-list.component.spec.ts b/Client/src/app/components/youtube-list/youtube-list.component.spec.ts new file mode 100644 index 0000000..3751a87 --- /dev/null +++ b/Client/src/app/components/youtube-list/youtube-list.component.spec.ts @@ -0,0 +1,25 @@ +import { async, ComponentFixture, TestBed } from '@angular/core/testing'; + +import { YoutubeListComponent } from './youtube-list.component'; + +describe('YoutubeListComponent', () => { + let component: YoutubeListComponent; + let fixture: ComponentFixture; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ YoutubeListComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(YoutubeListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Client/src/app/components/youtube-list/youtube-list.component.ts b/Client/src/app/components/youtube-list/youtube-list.component.ts new file mode 100644 index 0000000..eda0784 --- /dev/null +++ b/Client/src/app/components/youtube-list/youtube-list.component.ts @@ -0,0 +1,58 @@ +import { Component, OnInit } from '@angular/core'; +import { YoutubeListService } from './youtube-list-service'; +import { take } from 'rxjs/operators'; +import { YoutubeSnippet, YoutubeSnippetItem, YoutubeSearchResult } from './youtube-snippet'; + +@Component({ + selector: 'app-youtube-list', + templateUrl: './youtube-list.component.html', + styleUrls: ['./youtube-list.component.css'] +}) +export class YoutubeListComponent implements OnInit { + public loading: boolean = false; + public items: YoutubeSnippetItem[] = []; + private totalResults: number = 0; + + constructor(private youtube: YoutubeListService) { } + + ngOnInit() { + this.loading = true; + this.youtube.getFirstPage().pipe(take(1)).subscribe(x => { + this.totalResults = x.pageInfo.totalResults; + this.processResults(x); + this.loading = false; + }); + } + + public showLoadMore() { + if (this.items.length < this.totalResults && this.loading === false) { + return true; + } + return false; + } + + public loadMore() { + if (this.items.length >= this.totalResults) { + return; + } + this.loading = true; + this.youtube.getNextPage().pipe(take(1)).subscribe(x => { + this.processResults(x); + this.loading = false; + }); + } + + private processResults(res: YoutubeSearchResult) { + var parser = new DOMParser; + res.items.forEach(x => x.snippet.title = parser.parseFromString(x.snippet.title, "text/html").body.innerHTML); + if (this.items.length === 0) { + this.items = res.items; + } else { + for(let i = 0; i < res.items.length; i++) { + this.items.push(res.items[i]); + } + } + + } + +} diff --git a/Client/src/app/components/youtube-list/youtube-snippet.ts b/Client/src/app/components/youtube-list/youtube-snippet.ts new file mode 100644 index 0000000..cb8c4a9 --- /dev/null +++ b/Client/src/app/components/youtube-list/youtube-snippet.ts @@ -0,0 +1,48 @@ +export class YoutubeSearchResult { + public kind: string; + public etag: string; + public nextPageToken: string; + public regionCode: string; + public pageInfo: YoutubeSearchResultPageInfo; + public items: YoutubeSnippetItem[]; +} + +export class YoutubeSearchResultPageInfo { + public totalResults: number; + public resultsPerPage: number; +} + +export class YoutubeSnippetItem { + public kind: string; + public etag: string; + public id: YoutubeSnippetId; + public snippet: YoutubeSnippet +} + +export class YoutubeSnippetId { + public kind: string; + public videoId: string; +} + +export class YoutubeSnippet { + public publishedAt: Date; + public channelId: string; + public title: string; + public description: string; + public channelTitle: string; + public liveBroadcastContent: string; + public publishTime: Date; + public thumbnails: YoutubeSnippetThumbnails; +} + +export class YoutubeSnippetThumbnails { + public default: YoutubeThumbnail; + public medium: YoutubeThumbnail; + public high: YoutubeThumbnail; +} + +export class YoutubeThumbnail { + public url: string; + public width: number; + public height: number; +} \ No newline at end of file diff --git a/Client/src/app/pipes/ofb-date.pipe.ts b/Client/src/app/pipes/ofb-date.pipe.ts index 49856b9..0bd7022 100644 --- a/Client/src/app/pipes/ofb-date.pipe.ts +++ b/Client/src/app/pipes/ofb-date.pipe.ts @@ -10,6 +10,9 @@ export class OfbDatePipe implements PipeTransform { console.error("value for ofb-date-pipe was undefined or null"); return value; } + if (typeof value === 'string') { + value = new Date(value); + } var year = value.getFullYear(); var month = value.getMonth() + 1; var day = value.getDate();