Merge remote-tracking branch 'origin/test'
commit
9e7f02e2be
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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 { }
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@
|
|||
</p>
|
||||
<br>
|
||||
<p ofbFadeInOnScroll class="action">
|
||||
<i ofbicon>live_tv</i> <a routerLink="/live" class="align-top">Click here to watch online</a>
|
||||
<i ofbicon>live_tv</i> <a routerLink="/video" class="align-top">Click here to watch online</a>
|
||||
</p>
|
||||
<p ofbFadeInOnScroll class="action">
|
||||
<i ofbicon>headset</i> <a routerLink="/sermons" class="align-top">Click here to listen online</a>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
<div md-dialog-title>
|
||||
<h2>{{title}}</h2>
|
||||
<button mat-icon-button (click)="close()">
|
||||
<i ofbicon>close</i>
|
||||
</button>
|
||||
</div>
|
||||
<hr color="primary">
|
||||
<div md-dialog-content>
|
||||
<iframe width="560" height="315" [src]="embedUrl | safeUrl" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
|
@ -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<YoutubePopupComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ YoutubePopupComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(YoutubePopupComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -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<YoutubePopupComponent>) {
|
||||
this.title = data.title;
|
||||
this.embedUrl = data.embedUrl;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
public close() {
|
||||
this.MatDialogRef.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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%;
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
<div class="wrapper" [@inout]="startFadeIn">
|
||||
<div class="photo">
|
||||
<button mat-button (click)="play()">
|
||||
<img src="{{thumbnailUrl}}" />
|
||||
</button>
|
||||
</div><!--
|
||||
--><div class="info" (click)="toggleState()">
|
||||
<span class="title">{{ title }}</span>
|
||||
<br>
|
||||
<span class="date">{{ publishTime | ofbDate:true }}</span>
|
||||
<br>
|
||||
<p class="description" [@toggleAnimationFade]="state">
|
||||
{{ description }}
|
||||
</p>
|
||||
<div class="fade"><i ofbicon *ngIf="state === 'closed'">arrow_drop_down</i><i ofbicon *ngIf="state === 'open'">arrow_drop_up</i></div>
|
||||
</div>
|
||||
<div class="expanded" [@toggleAnimation]="state" (click)="toggleState()">
|
||||
<p class="expanded-content">
|
||||
{{ description }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button mat-button class="action pct50" (click)="play()" ><i ofbicon>tv</i> Play</button><!--
|
||||
--><button mat-button class="action pct50" (click)="share()" ><i ofbicon>share</i> Share</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -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<VideoItemComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ VideoItemComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(VideoItemComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
|
||||
.side-bar{
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.width100{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#showAllButton{
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<secondary-page-component [hideSideBarOnMobile]="true" >
|
||||
<div mainContent>
|
||||
<app-youtube-list></app-youtube-list>
|
||||
</div>
|
||||
<div sideBar class="side-bar">
|
||||
|
||||
</div>
|
||||
</secondary-page-component>
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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<VideoComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ VideoComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(VideoComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -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() {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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<YoutubeSearchResult> {
|
||||
const url = this.getUrl(undefined);
|
||||
return this.httpClient.get<YoutubeSearchResult>(url).pipe(tap(x => this.nextPageToken = x.nextPageToken));
|
||||
}
|
||||
|
||||
public getNextPage() : Observable<YoutubeSearchResult> {
|
||||
const url = this.getUrl(this.nextPageToken);
|
||||
return this.httpClient.get<YoutubeSearchResult>(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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
|
||||
|
||||
|
||||
<ul>
|
||||
<li *ngFor="let item of items">
|
||||
<app-video-item
|
||||
[title]="item.snippet.title"
|
||||
[description]="item.snippet.description"
|
||||
[publishTime]="item.snippet.publishTime"
|
||||
[thumbnailUrl]="item.snippet.thumbnails.medium.url"
|
||||
shareUrl="https://youtu.be/{{item.id.videoId}}"
|
||||
embedUrl="https://www.youtube.com/embed/{{item.id.videoId}}">
|
||||
|
||||
</app-video-item>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<button *ngIf="showLoadMore()" mat-button [disabled]="loading" class="width100 mt-20" style="text-align: center;" (click)="loadMore()">
|
||||
<i ofbicon *ngIf="loading">access_time</i><span *ngIf="loading"> Loading...</span>
|
||||
<i ofbicon *ngIf="!loading">expand_more</i><span *ngIf="!loading"> Load More</span>
|
||||
</button>
|
||||
|
|
@ -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<YoutubeListComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ YoutubeListComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(YoutubeListComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -1,12 +1,42 @@
|
|||
{
|
||||
"videos": [
|
||||
{
|
||||
"isReady": true,
|
||||
"title": "Sunday Evening",
|
||||
"src": "",
|
||||
"yt": "https://www.youtube.com/embed/MTej_Yk5py0",
|
||||
"date": "2020-05-17T19:00:00-06:00",
|
||||
"archived": false,
|
||||
"message": "Please check back later for the Sunday Evening Service"
|
||||
},
|
||||
|
||||
{
|
||||
"isReady": true,
|
||||
"title": "Sunday Morning",
|
||||
"src": "",
|
||||
"yt": "https://www.youtube.com/embed/7t48zsLmZvM",
|
||||
"date": "2020-05-17T11:00:00-06:00",
|
||||
"archived": true,
|
||||
"message": "Please check back later for the Sunday Morning Service"
|
||||
},
|
||||
|
||||
{
|
||||
"isReady": true,
|
||||
"title": "Wednesday Evening",
|
||||
"src": "",
|
||||
"yt": "https://www.youtube.com/embed/eUOQ4Cm-eKM",
|
||||
"date": "2020-05-13T19:00:00-06:00",
|
||||
"archived": true,
|
||||
"message": "Please check back later for the Wednesday Evening Service"
|
||||
},
|
||||
|
||||
{
|
||||
"isReady": true,
|
||||
"title": "Sunday Evening",
|
||||
"src": "",
|
||||
"yt": "https://www.youtube.com/embed/wCqhj3HnhKU",
|
||||
"date": "2020-05-10T19:00:00-06:00",
|
||||
"archived": false,
|
||||
"archived": true,
|
||||
"message": "Please check back later for the Sunday Evening Service"
|
||||
},
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue