diff --git a/Client/package-lock.json b/Client/package-lock.json index c414a3c..cfbde72 100644 --- a/Client/package-lock.json +++ b/Client/package-lock.json @@ -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", diff --git a/Client/package.json b/Client/package.json index fe2c3c2..c415639 100644 --- a/Client/package.json +++ b/Client/package.json @@ -20,11 +20,12 @@ "@angular/material": "^7.2.1", "@angular/platform-browser": "~7.2.0", "@angular/platform-browser-dynamic": "~7.2.0", - "@angular/router": "~7.2.0", + "@angular/router": "~7.2.0", "chart.js": "^2.9.3", "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" diff --git a/Client/src/app/app-routing.module.ts b/Client/src/app/app-routing.module.ts index d55e06c..3636232 100644 --- a/Client/src/app/app-routing.module.ts +++ b/Client/src/app/app-routing.module.ts @@ -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 diff --git a/Client/src/app/app.module.ts b/Client/src/app/app.module.ts index 7c52391..39b754d 100644 --- a/Client/src/app/app.module.ts +++ b/Client/src/app/app.module.ts @@ -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, diff --git a/Client/src/app/components/home/countdown.ts b/Client/src/app/components/home/countdown.ts new file mode 100644 index 0000000..4cc65c5 --- /dev/null +++ b/Client/src/app/components/home/countdown.ts @@ -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(); + } +} \ No newline at end of file diff --git a/Client/src/app/components/home/home.component.css b/Client/src/app/components/home/home.component.css index 26d607c..9e8575a 100644 --- a/Client/src/app/components/home/home.component.css +++ b/Client/src/app/components/home/home.component.css @@ -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%; diff --git a/Client/src/app/components/home/home.component.html b/Client/src/app/components/home/home.component.html index 89b809b..041dbe8 100644 --- a/Client/src/app/components/home/home.component.html +++ b/Client/src/app/components/home/home.component.html @@ -2,6 +2,35 @@ background image
+
+
+ LIVE + SERMON STARTS IN + SERMON STREAMING NOW +
+ +
+ live_tv + Click to Watch Now +
+
+ {{countdown.daysDisplay}} +  {{countdown.daysText}} +  {{countdown.hoursDisplay}} +  {{countdown.hoursText}} +  {{countdown.minutesDisplay}} +  {{countdown.minutesText}} +  {{countdown.secondsDisplay}} +  {{countdown.secondsText}} +
+
+ +
+ {{countdown.dateDisplaySmall}} +
+
diff --git a/Client/src/app/components/home/home.component.ts b/Client/src/app/components/home/home.component.ts index a15ffda..844e779 100644 --- a/Client/src/app/components/home/home.component.ts +++ b/Client/src/app/components/home/home.component.ts @@ -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']) diff --git a/Client/src/app/components/live-stream/live-stream.component.css b/Client/src/app/components/live-stream/live-stream.component.css new file mode 100644 index 0000000..0a0f280 --- /dev/null +++ b/Client/src/app/components/live-stream/live-stream.component.css @@ -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%; +} \ No newline at end of file diff --git a/Client/src/app/components/live-stream/live-stream.component.html b/Client/src/app/components/live-stream/live-stream.component.html new file mode 100644 index 0000000..fd0bcaa --- /dev/null +++ b/Client/src/app/components/live-stream/live-stream.component.html @@ -0,0 +1,10 @@ + +
+
+ +
+
+
+ +
+
\ No newline at end of file diff --git a/Client/src/app/components/live-stream/live-stream.component.spec.ts b/Client/src/app/components/live-stream/live-stream.component.spec.ts new file mode 100644 index 0000000..18394a8 --- /dev/null +++ b/Client/src/app/components/live-stream/live-stream.component.spec.ts @@ -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; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [ LiveStreamComponent ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(LiveStreamComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/Client/src/app/components/live-stream/live-stream.component.ts b/Client/src/app/components/live-stream/live-stream.component.ts new file mode 100644 index 0000000..c4e907a --- /dev/null +++ b/Client/src/app/components/live-stream/live-stream.component.ts @@ -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() { + } +} diff --git a/Client/src/assets/images/home-images/tiny/sunset_b.jpg b/Client/src/assets/images/home-images/tiny/sunset_b.jpg index cfd5d1e..98b6942 100644 Binary files a/Client/src/assets/images/home-images/tiny/sunset_b.jpg and b/Client/src/assets/images/home-images/tiny/sunset_b.jpg differ