Add live video countdown

test
dan 2020-03-21 03:29:57 -06:00
parent a5dec99e4b
commit 04fd77c1be
13 changed files with 376 additions and 4 deletions

View File

@ -951,7 +951,8 @@
"@types/chart.js": {
"version": "2.9.7",
"resolved": "https://registry.npmjs.org/@types/chart.js/-/chart.js-2.9.7.tgz",
"integrity": "sha512-T+oRIWLPu6cXWYSTwihkeZLKk5V4U4O09Uqx4padQto1XVH7YafX4Z4YV1OIWnKbkqMn/4Cuj9ZwWcG6fnKK3A=="
"integrity": "sha512-T+oRIWLPu6cXWYSTwihkeZLKk5V4U4O09Uqx4padQto1XVH7YafX4Z4YV1OIWnKbkqMn/4Cuj9ZwWcG6fnKK3A==",
"dev": true
},
"@types/jasmine": {
"version": "2.8.15",
@ -5997,6 +5998,11 @@
}
}
},
"luxon": {
"version": "1.22.0",
"resolved": "https://registry.npmjs.org/luxon/-/luxon-1.22.0.tgz",
"integrity": "sha512-3sLvlfbFo+AxVEY3IqxymbumtnlgBwjDExxK60W3d+trrUzErNAz/PfvPT+mva+vEUrdIodeCOs7fB6zHtRSrw=="
},
"magic-string": {
"version": "0.25.1",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.1.tgz",

View File

@ -25,6 +25,7 @@
"chartjs-plugin-datalabels": "^0.7.0",
"core-js": "^2.5.4",
"hammerjs": "^2.0.8",
"luxon": "^1.22.0",
"rxjs": "~6.3.3",
"tslib": "^1.9.0",
"zone.js": "~0.8.26"

View File

@ -16,6 +16,7 @@ import { AddTransactionPageComponent } from './components/add-transaction-page/a
import { MissionaryFormPageComponent } from './components/missionary-form-page/missionary-form-page.component';
import { ContributorYearlyReportComponent } from './components/contributor-yearly-report/contributor-yearly-report.component';
import { ContributorAllReportsComponent } from './components/contributor-all-reports/contributor-all-reports.component';
import { LiveStreamComponent } from './components/live-stream/live-stream.component';
const routes =
[
@ -75,6 +76,10 @@ const routes =
path: 'camp',
component: CampPageComponent
},
{
path: 'live',
component: LiveStreamComponent
},
{
path: 'transactions/add',
component: AddTransactionPageComponent

View File

@ -76,6 +76,7 @@ import { MissionaryFormPageComponent } from './components/missionary-form-page/m
import { MissionarySupportService } from './services/missionary-support-service';
import { ContributorYearlyReportComponent } from './components/contributor-yearly-report/contributor-yearly-report.component';
import { ContributorAllReportsComponent } from './components/contributor-all-reports/contributor-all-reports.component';
import { LiveStreamComponent } from './components/live-stream/live-stream.component';
@ -123,7 +124,8 @@ import { ContributorAllReportsComponent } from './components/contributor-all-rep
AddTransactionPopupComponent,
MissionaryFormPageComponent,
ContributorYearlyReportComponent,
ContributorAllReportsComponent
ContributorAllReportsComponent,
LiveStreamComponent
],
imports: [
BrowserModule,

View File

@ -0,0 +1,150 @@
import { DateTime } from "luxon";
export class Countdown {
public days: number = 0;
public hours: number = 0;
public minutes: number = 0;
public seconds: number = 0;
public liveDates: Date[] = [
DateTime.fromObject({year: 2020, month: 3, day: 22, hour: 10, zone: 'America/Denver'}),
DateTime.fromObject({year: 2020, month: 3, day: 22, hour: 11, zone: 'America/Denver'}),
DateTime.fromObject({year: 2020, month: 3, day: 22, hour: 19, zone: 'America/Denver'})
];
public showButton: boolean;
public showCounter: boolean = true;
public dateDisplay: string;
public dateDisplaySmall: string;
public get daysDisplay(): string {
return this.formatDisplay(this.days);
}
public get daysText(): string {
return this.days === 1 ? 'day ' : 'days';
}
public get hoursDisplay(): string {
return this.formatDisplay(this.hours);
}
public get hoursText(): string {
return this.hours === 1 ? 'hr ' : 'hrs';
}
public get minutesDisplay(): string {
return this.formatDisplay(this.minutes);
}
public get minutesText(): string {
return this.minutes === 1 ? 'min ' : 'mins';
}
public get secondsDisplay(): string {
return this.formatDisplay(this.seconds);
}
public get secondsText(): string {
return this.seconds === 1 ? 'sec ' : 'secs';
}
private clock;
constructor() {
if (this.liveDates.length == 0) return;
this.liveDates.sort((a, b) => {
if (a < b) return -1;
if (a === b) return 0;
return 1;
});
this.updateClock();
this.startClock();
}
private resetToZero() {
this.days = 0;
this.hours = 0;
this.minutes = 0;
this.seconds = 0;
}
private updateClock() {
this.showCounter = true;
var now = DateTime.local();
var nearestPast = this.getNearestPastDate(now);
if (nearestPast) {
var pastDiff = now.diff(nearestPast, ['minutes']);
if (pastDiff.minutes < 45) {
this.showButton = true;
this.dateDisplay = nearestPast.toLocaleString(DateTime.DATETIME_HUGE);
this.dateDisplaySmall = nearestPast.toLocaleString(DateTime.DATETIME_MED);
return;
}
}
this.showButton = false;
var nearestFuture = this.getNearestFutureDate(now);
if (!nearestFuture) {
this.stopClock();
this.resetToZero();
this.showCounter = false;
this.dateDisplay = '';
this.dateDisplaySmall = '';
return;
}
var minDiff = nearestFuture.diff(now, ['minutes']);
if (minDiff.minutes <= 10) {
this.showButton = true;
}
var hourDiff = nearestFuture.diff(now, ['hours']);
if (hourDiff.hours >= 48) {
this.showCounter = false;
this.dateDisplay = '';
this.dateDisplaySmall = '';
return;
}
var diff = nearestFuture.diff(now, ['days', 'hours', 'minutes', 'seconds']);
this.days = diff.days;
this.hours = diff.hours;
this.minutes = diff.minutes;
this.seconds = Math.floor(diff.seconds);
this.dateDisplay = nearestFuture.toLocaleString(DateTime.DATETIME_HUGE);
this.dateDisplaySmall = nearestFuture.toLocaleString(DateTime.DATETIME_MED)
}
private startClock() {
this.clock = setInterval(this.updateClock.bind(this), 1000);
}
private stopClock() {
clearInterval(this.clock);
}
private getNearestPastDate(now: DateTime): DateTime {
if (this.liveDates.length === 0) return null;
var now = now || DateTime.local();
var nearestIndex = this.liveDates.findIndex(d => d > now);
if (nearestIndex === 0) return null;
if (nearestIndex === -1) return this.liveDates[this.liveDates.length - 1];
return this.liveDates[nearestIndex - 1];
}
private getNearestFutureDate(now: DateTime): DateTime {
if (this.liveDates.length === 0) return null;
var now = now || DateTime.local();
var nearest = this.liveDates.find(d => d > now);
return nearest;
}
private formatDisplay(val: number): string {
if (val <= 0) {
return '00';
}
if (val < 10) {
return '0' + val.toString();
}
return val.toString();
}
}

View File

@ -30,6 +30,117 @@ img.full {
bottom: 10%;
}
#live-stream-container {
text-align: left;
position: absolute;
left: 10%;
right: 0;
bottom: 20%;
}
#title > .live {
display: inline-block;
background-color: red;
color: white;
padding: 0px 7px;
border-radius: 10px;
}
#live-date {
color: white;
font-weight: bold;
margin-top: 5px;
}
#live-stream-container > #title {
font-size: 25pt;
font-weight: bold;
color: white;
font-family: Franklin Gothic Medium,Franklin Gothic,ITC Franklin Gothic,Arial,sans-serif;
}
#countdown-container {
text-decoration: none;
position: relative;
margin-top: 7px;
display: inline-block;
font-size: 30pt;
font-weight: bold;
border-radius: 10px;
background-color: rgba(255, 255, 255, 1);
padding: 15px 20px;
-webkit-box-shadow: inset 0px 0px 20px -15px rgba(0,0,0,1);
-moz-box-shadow: inset 0px 0px 20px -15px rgba(0,0,0,1);
box-shadow: inset 0px 0px 20px -15px rgba(0,0,0,1);
border: 1px solid green;
font-family: Consolas,monaco,monospace;
}
/*Button*/
#countdown-container.show-button {
background-color:#2dabf9;
color:#ffffff;
text-shadow:0px 1px 0px #263666;
}
#countdown-container.show-button:hover {
background-color:#0688fa;
}
#countdown-container.show-button:active {
position:relative;
top:1px;
}
/*End Button*/
#countdown-container .text {
font-size: 10pt;
}
.opacity-zero {
opacity: 0;
}
#live-button {
position: absolute;
font-size: 25pt;
width: 100%;
height: 100%;
}
@media(max-width:900px){
#live-stream-container > #title {
font-size: 15pt;
}
#countdown-container {
font-size: 20pt;
}
}
.display-sm {
display: none;
}
@media(max-width:600px){
#live-stream-container {
left: 5%;
right: 5%;
bottom: 5%
}
#live-stream-container > #title {
font-size: 11pt;
}
#countdown-container {
font-size: 13pt;
}
.display-none-sm {
display: none;
}
.display-sm {
display: block;
}
}
#action-button {
font-size: 16pt;
max-width: 100%;

View File

@ -2,6 +2,35 @@
<img id="background-image" src="assets/images/home-images/tiny/sunset_b.jpg" alt="background image" width="100%">
<div id="filler">
<div id="live-stream-container" *ngIf="countdown.showCounter">
<div id="title">
<span class="live">LIVE</span>
<span *ngIf="!countdown.showButton"> SERMON STARTS IN</span>
<span *ngIf="countdown.showButton"> SERMON STREAMING NOW</span>
</div>
<a id="countdown-container" routerLink="/live" [class.show-button]="countdown.showButton" >
<div id="live-button" [class.opacity-zero]="!countdown.showButton">
<i ofbicon class="mr-10" >live_tv</i>
Click to Watch Now
</div>
<div [class.opacity-zero]="countdown.showButton">
<span class="number">{{countdown.daysDisplay}}</span>
<span class="text">&nbsp;{{countdown.daysText}}</span>
<span class="number">&nbsp;{{countdown.hoursDisplay}}</span>
<span class="text">&nbsp;{{countdown.hoursText}}</span>
<span class="number">&nbsp;{{countdown.minutesDisplay}}</span>
<span class="text">&nbsp;{{countdown.minutesText}}</span>
<span class="number">&nbsp;{{countdown.secondsDisplay}}</span>
<span class="text">&nbsp;{{countdown.secondsText}}</span>
</div>
</a>
<div id="live-date" class="display-none-sm">
{{countdown.dateDisplay}}
</div>
<div id="live-date" class="display-sm">
{{countdown.dateDisplaySmall}}
</div>
</div>
<div id="call-to-action-container" *ngIf="showCallToAction">
<button id="action-button" routerLink="/camp" mat-raised-button color="accent"><i ofbicon class="mr-10">info_outline</i>2019 Youth Camp</button>
</div>

View File

@ -2,6 +2,7 @@ import { Component, HostListener } from '@angular/core';
import { MatDialog, MatDialogConfig } from '@angular/material';
import { VideoPopupComponent } from '../popups/video-popup/video-popup.component';
import { environment } from '../../../environments/environment';
import { Countdown } from './countdown';
@Component({
selector: 'home-component',
@ -47,9 +48,13 @@ export class HomeComponent {
return true;
}
public countdown: Countdown;
public liveDates: Date[] = [];
constructor(private dialog: MatDialog)
{
this.countdown = new Countdown();
this.liveDates = [];
}
@HostListener('window:scroll', ['$event'])

View File

@ -0,0 +1,13 @@
.video-container {
position: relative;
width: 100%;
height: 0;
padding-bottom: 56.25%;
}
.video {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}

View File

@ -0,0 +1,10 @@
<secondary-page-component [hideSideBarOnMobile]="true" >
<div mainContent class="mapWrapper">
<div class="video-container">
<iframe class="video" src="https://www.youtube-nocookie.com/embed/dAxhAF9ZzbA" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
</div>
<div sideBar ofbFadeInOnScroll>
</div>
</secondary-page-component>

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { LiveStreamComponent } from './live-stream.component';
describe('LiveStreamComponent', () => {
let component: LiveStreamComponent;
let fixture: ComponentFixture<LiveStreamComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ LiveStreamComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(LiveStreamComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,15 @@
import { BibleVerseService } from './../../services/bible-verse.service';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'live-stream-component',
templateUrl: './live-stream.component.html',
styleUrls: ['./live-stream.component.css']
})
export class LiveStreamComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 48 KiB