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();