Compare commits

..

No commits in common. "master" and "Transactions" have entirely different histories.

129 changed files with 560 additions and 17470 deletions

View File

@ -1,3 +0,0 @@
node_modules
.git
.gitignore

View File

@ -29,14 +29,6 @@
"scripts": []
},
"configurations": {
"test": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.test.ts"
}
]
},
"production": {
"fileReplacements": [
{

13526
Client/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -21,24 +21,20 @@
"@angular/platform-browser": "~7.2.0",
"@angular/platform-browser-dynamic": "~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"
},
"devDependencies": {
"@angular-devkit/build-angular": "~0.12.0",
"@angular/cli": "^7.3.8",
"@angular/cli": "~7.2.2",
"@angular/compiler-cli": "~7.2.0",
"@angular/language-service": "~7.2.0",
"@types/node": "~8.9.4",
"@types/jasmine": "~2.8.8",
"@types/jasminewd2": "~2.0.3",
"@types/node": "~8.9.4",
"@types/chart.js": "^2.9.7",
"codelyzer": "~4.5.0",
"jasmine-core": "~2.99.1",
"jasmine-spec-reporter": "~4.2.1",

View File

@ -13,15 +13,6 @@ import { SalvationPageComponent } from './components/salvation-page/salvation-pa
import { CampPageComponent } from './components/camp-page/camp-page.component';
import { MembersPageComponent } from './components/members-page/members-page.component';
import { AddTransactionPageComponent } from './components/add-transaction-page/add-transaction-page.component';
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';
import { VideoServicesComponent } from './components/video-services/video-services.component';
import { ImageComponent } from './components/image/image.component';
import { VideoComponent } from './components/video/video.component';
import { FCCPermitPageComponent } from './components/fcc-permit-page/fcc-permit-page.component';
import { BalloonComponent } from './components/balloon/balloon.component';
const routes =
[
@ -45,18 +36,10 @@ const routes =
path: 'contact',
component: ContactPageComponent
},
{
path: 'missionary',
component: MissionaryFormPageComponent
},
{
path: 'sermons',
component: SermonsComponent
},
{
path: 'video',
component: VideoComponent
},
{
path: 'sermons/:id',
component: SermonsComponent
@ -81,45 +64,13 @@ const routes =
path: 'user',
component: MembersPageComponent
},
{
path: 'covid',
component: ImageComponent,
data: {
imageUrl: 'assets/images/tiny/covid_tract.jpg',
shareName: 'covid'
}
},
{
path: 'covid2',
component: ImageComponent,
data: {
imageUrl: 'assets/images/tiny/covid_tract_2.jpg',
shareName: 'covid2'
}
},
{
path: 'camp',
component: CampPageComponent
},
{
path: 'live',
component: LiveStreamComponent
},
{
path: 'transactions/add',
component: AddTransactionPageComponent
},
{
path: 'contributor/report',
component: ContributorAllReportsComponent
},
{
path: 'fmpermit',
component: FCCPermitPageComponent
},
{
path: 'balloon',
component: BalloonComponent
}
]

View File

@ -3,7 +3,6 @@ import { GoogleAnalyticsService } from './services/google-analytics.service';
import { WindowRefService } from './services/window-ref.service';
import { EmailService } from './services/email.service';
import { SermonService } from './services/sermon.service';
import { PrintService } from './services/print-service';
import { LoginService } from './services/login.service';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
@ -16,9 +15,7 @@ import { MatButtonModule,
MatDialogModule,
MatSelectModule,
MatOptionModule,
MatRadioModule,
MatAutocompleteModule,
MatCheckboxModule} from '@angular/material';
MatAutocompleteModule} from '@angular/material';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import 'hammerjs';
@ -53,8 +50,6 @@ import { EventLargeComponent } from './components/event-large/event-large.compon
import { SalvationPageComponent } from './components/salvation-page/salvation-page.component';
import { MediaPageComponent } from './components/media-page/media-page.component';
import { VideoPopupComponent } from './components/popups/video-popup/video-popup.component';
import { FCCPermitPageComponent } from './components/fcc-permit-page/fcc-permit-page.component';
import { BalloonComponent } from './components/balloon/balloon.component';
//Directives
import { FadeInOnScrollDirective } from './directives/fade-in-on-scroll.directive';
@ -73,20 +68,6 @@ import { AddUserPopupComponent } from './components/popups/add-user-popup/add-us
import { UserService } from './services/user.service';
import { TransactionService } from './services/transaction.service';
import { AddTransactionPageComponent } from './components/add-transaction-page/add-transaction-page.component';
import { AddTransactionPopupComponent } from './components/add-transaction-page/add-transaction-popup/add-transaction-popup.component';
import { MissionaryFormPageComponent } from './components/missionary-form-page/missionary-form-page.component';
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';
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';
@ -111,7 +92,6 @@ import { YoutubePopupComponent } from './components/popups/youtube-popup/youtube
DurationPipe,
LocationComponent,
SermonLargeComponent,
VideoServicesComponent,
AddSermonPopupComponent,
LoginPopupComponent,
OkPopupComponent,
@ -130,20 +110,8 @@ import { YoutubePopupComponent } from './components/popups/youtube-popup/youtube
VideoPopupComponent,
CampPageComponent,
MembersPageComponent,
FCCPermitPageComponent,
BalloonComponent,
AddUserPopupComponent,
AddTransactionPageComponent,
AddTransactionPopupComponent,
MissionaryFormPageComponent,
ContributorYearlyReportComponent,
ContributorAllReportsComponent,
LiveStreamComponent,
ImageComponent,
YoutubeListComponent,
VideoComponent,
VideoItemComponent,
YoutubePopupComponent
AddTransactionPageComponent
],
imports: [
BrowserModule,
@ -160,11 +128,9 @@ import { YoutubePopupComponent } from './components/popups/youtube-popup/youtube
MatSliderModule,
MatSnackBarModule,
MatDialogModule,
MatAutocompleteModule,
MatRadioModule,
MatCheckboxModule
MatAutocompleteModule
],
providers: [LoginService,PrintService,UserService,GoogleAnalyticsService,SermonService,TransactionService,EventService,EmailService,MissionarySupportService,YoutubeListService,WindowRefService],
providers: [LoginService,UserService,GoogleAnalyticsService,SermonService,TransactionService,EventService,EmailService,WindowRefService],
entryComponents: [AddSermonPopupComponent,
LoginPopupComponent,
OkPopupComponent,
@ -174,9 +140,7 @@ import { YoutubePopupComponent } from './components/popups/youtube-popup/youtube
SharePopupComponent,
AddEventPopupComponent,
AddUserPopupComponent,
VideoPopupComponent,
AddTransactionPopupComponent,
YoutubePopupComponent],
VideoPopupComponent],
bootstrap: [AppComponent]
})
export class AppModule { }

View File

@ -1,73 +1,72 @@
.b-0 {
border: 0;
.d-inline-block {
display: inline-block;
}
.fab-buttons {
display: none;
}
.fw-bold {
.fw-b {
font-weight: bold;
}
.fs-1-2-5 {
font-size: 1.25rem;
.w-5 {
width: 5%;
}
.highlight {
background-color: #F3FAFF;
.w-15 {
width: 15%;
}
.highlight-yellow {
background-color: lightyellow;
.w-20 {
width: 20%;
}
.w-30 {
width: 30%;
}
.w-75 {
width: 75%;
}
.w-80 {
width: 80%;
}
.m-1 {
margin: 1rem;
}
.mt-1 {
margin-top: 1rem;
}
.mt-2 {
margin-top: 2rem;
}
.ml-1 {
margin-left: 1rem;
}
.p-0 {
padding: 0;
.ml-2 {
margin-left: 2rem;
}
.mr-1 {
margin-right: 1rem;
}
.pt-1 {
padding-top: 1rem;
}
.bb-1 {
border-bottom: 1px solid #ff4081;
}
table {
border-collapse: collapse;
width: 100%;
}
td, th {
padding: 5px;
border: 1px solid lightslategray;
border: 1px solid orange;
}
.remove-top-border {
border-top: 0;
}
.remove-border {
border: 0;
}
.side-bar > button {
margin: 20px;
width: calc(100% - 40px);
}
#audio-player-filler{
height: 60px;
background-color: inherit;
}
@media(max-width:800px){
.fab-buttons{
display: inline-block;
position: fixed;
bottom: 20px;
right: 20px;
}
}

View File

@ -1,89 +1,118 @@
<div>&nbsp;</div>
<h2 class="ml-1 mr-1 bb-1">Add Transactions</h2>
<secondary-page-component [fixedSideBar]="true" >
<secondary-page-component [fixedSideBar]="true">
<div mainContent>
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<div formArrayName="contributions" *ngFor="let item of form.get('contributions').controls; let i = index;">
<div class="m-1 mt-2 bb-1" [formGroupName]="i">
<button class="w-5" type="button" mat-icon-button (click)="deleteContributor(i)">
<i ofbicon>delete_forever</i>
</button>
<mat-form-field class="w-20">
<input matInput placeholder="Date" type="date" formControlName="date" >
</mat-form-field>
<mat-form-field class="w-75">
<input type="text" placeholder="Contributor" aria-label="Contributor" matInput formControlName="contributorId" (ngModelChange)="onContributorChange($event)" [matAutocomplete]="auto">
<mat-autocomplete #auto="matAutocomplete" [displayWith]="contirbutorDisplayFn">
<mat-option *ngFor="let option of filteredContributors" [value]="option">
{{option.display}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
<div formArrayName="transactions" *ngFor="let trans of item.get('transactions').controls; let a = index;">
<div [formGroupName]="a">
<button class="w-5" type="button" mat-icon-button (click)="deleteTransaction(i,a)">
<i ofbicon>delete_forever</i>
</button>
<mat-form-field class="w-15">
<mat-select formControlName="typeId">
<mat-option *ngFor="let type of types" [value]="type.value" >
{{type.display}}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field class="w-20">
<input matInput placeholder="Check Number" type="text" formControlName="checkNumber" >
</mat-form-field>
<mat-form-field class="w-20">
<mat-select formControlName="fundId">
<mat-option *ngFor="let fund of funds" [value]="fund.value">
{{fund.display}}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field class="w-20">
<input matInput placeholder="Amount" type="number" formControlName="amount" >
</mat-form-field>
<mat-form-field class="w-20">
<input matInput placeholder="Description" type="text" formControlName="description" >
</mat-form-field>
</div>
</div>
<button class="w-15" mat-stroked-button type="button" (click)="addTransaction(i)">Add Transaction</button>
<div class="ml-1 w-20 d-inline-block">
{{contributorName(i)}}
</div>
<div class="ml-1 w-20 d-inline-block">
General: {{contributorTotal(i, 1)}}
</div>
<div class="w-15 d-inline-block">
Missions: {{contributorTotal(i, 2)}}
</div>
<div class="w-15 d-inline-block">
Total: {{contributorTotal(i, 0)}}
</div>
</div>
</div>
<button mat-stroked-button class="m-1 w-15" type="button" (click)="addContributor()">Add Contributor</button>
<div class="ml-1 w-20 d-inline-block">
Combined
</div>
<div class="ml-1 w-20 d-inline-block">
General: {{combinedTotal(1)}}
</div>
<div class="w-15 d-inline-block">
Missions: {{combinedTotal(2)}}
</div>
<div class="w-15 d-inline-block">
Total: {{combinedTotal(0)}}
</div>
<button mat-raised-button type="submit" [disabled]="!form.valid || submitButtonDisabled">{{ submitButtonText }}</button>
</form>
</div>
<div sideBar class="side-bar">
<table>
<thead>
<tr>
<th>General</th>
<th>Missions</th>
<th>Total</th>
</tr>
</thead>
<tbody>
<ng-container *ngFor="let c of contributions; let ci = index">
<tr [class.bg-red]="!contributorDatesMatch(c.contributorId)">
<td colspan="2" class="fw-bold fs-1-2-5">{{c.date}}</td>
<td colspan="4" class="fw-bold fs-1-2-5">{{contributorName(c.contributorId)}}</td>
<ng-container *ngFor="let c of form.get('contributions').value; let i = index">
<tr>
<td colspan="3" class="pt-1">{{contributorName(i)}}</td>
</tr>
<tr>
<td></td>
<td class="fw-bold">Date</td>
<td class="fw-bold">Type</td>
<td class="fw-bold">Check</td>
<td class="fw-bold">Fund</td>
<td class="fw-bold">Amount</td>
<td>{{contributorTotal(i, 1) | currency}}</td>
<td>{{contributorTotal(i, 2) | currency}}</td>
<td>{{contributorTotal(i, 0) | currency}}</td>
</tr>
<ng-container *ngFor="let t of c.transactions; let ti = index">
<tr [class.highlight]="ti % 2">
<td rowspan="2" style="width: 30px;">
<button mat-icon-button (click)="deleteTransaction(t.contributorId, ti)"><i ofbicon>delete_forever</i></button>
</td>
<td colspan="5" *ngIf="t.description && t.description.length > 0">{{t.description}}</td>
<td colspan="5" *ngIf="!t.description || t.description.length === 0" class="b-0 p-0"></td>
</tr>
<tr [class.highlight]="ti % 2">
<td [class.remove-top-border]="!t.description || t.description.length === 0">{{t.date}}</td>
<td [class.remove-top-border]="!t.description || t.description.length === 0">{{transactionType[t.typeId]}}</td>
<td [class.remove-top-border]="!t.description || t.description.length === 0">{{t.checkNumber}}</td>
<td [class.remove-top-border]="!t.description || t.description.length === 0">{{fund[t.fundId]}}</td>
<td [class.remove-top-border]="!t.description || t.description.length === 0">{{t.amount | currency}}</td>
</tr>
</ng-container>
<tr>
<td></td>
<td></td>
<td></td>
<td class="fw-bold">General</td>
<td class="fw-bold">Missions</td>
<td class="fw-bold">Total</td>
</tr>
<tr class="highlight-yellow">
<td></td>
<td></td>
<td></td>
<td>{{contributorTotal(c.contributorId, 1) | currency}}</td>
<td>{{contributorTotal(c.contributorId, 2) | currency}}</td>
<td>{{contributorTotal(c.contributorId, 0) | currency}}</td>
</tr>
<tr>
<td colspan="5">
<button mat-raised-button (click)="addTransaction(c.contributorId)" >Add Transaction to {{contributorName(c.contributorId)}}</button>
</td>
</tr>
</ng-container>
<tr>
<td colspan="6" class="fw-bold fs-1-2-5">Grand Totals</td>
<td colspan="3" class="pt-1">
Total
</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td class="fw-bold">General</td>
<td class="fw-bold">Missions</td>
<td class="fw-bold">Total</td>
</tr>
<tr class="highlight-yellow">
<td></td>
<td></td>
<td></td>
<td>{{combinedTotal(1) | currency}}</td>
<td>{{combinedTotal(2) | currency}}</td>
<td>{{combinedTotal(0) | currency}}</td>
</tr>
</tbody>
</table>
<div class="fab-buttons" >
<button mat-fab (click)="addTransaction(-1)"><i ofbicon>add</i></button>
</div>
</div>
<div sideBar class="side-bar">
<button mat-raised-button (click)="addTransaction(-1)" >Add Transaction</button>
<button mat-raised-button (click)="submit()" [disabled]="contributions.length === 0 || submitButtonDisabled" >{{submitButtonText}}</button>
</div>
</secondary-page-component>

View File

@ -1,13 +1,11 @@
import { Component, OnInit } from '@angular/core';
import { Transaction } from './transaction';
import { UserService } from '../../services/user.service';
import { UserService } from 'src/app/services/user.service';
import { Contribution } from './contribution';
import { TransactionService } from '../../services/transaction.service';
import { MatDialog } from '@angular/material';
import { AddTransactionPopupComponent, ValDisplay } from './add-transaction-popup/add-transaction-popup.component';
import { TransactionType } from './transaction-type';
import { Fund } from './fund';
import { OkPopupComponent } from '../popups/ok-popup/ok-popup.component';
import { FormBuilder, FormGroup, Validators, FormArray } from '@angular/forms';
import { checkNumberValidator } from './check-number-validator';
import { contributorValidator } from './contributor-validator';
import { TransactionService } from 'src/app/services/transaction.service';
@Component({
selector: 'app-add-transaction-page',
@ -18,115 +16,114 @@ export class AddTransactionPageComponent implements OnInit {
errorMessages = [];
contributions: Contribution[] = [];
form: FormGroup;
submitButtonDisabled: boolean = false;
submitButtonText: string = "Submit Transactions";
transactionType = TransactionType;
fund = Fund;
transactionTypes: ValDisplay[] = [];
funds: ValDisplay[] = [];
submitButtonText: string = "Submit";
types: {value:number,display:string}[] = [];
funds: {value:number,display:string}[] = [];
contributors: {value:number,display:string}[] = [];
filteredContributors: {value:number,display:string}[]
constructor(private dialogService: MatDialog, private userService: UserService, private transactionService: TransactionService) {
for(let m in TransactionType) {
if (typeof TransactionType[m] === 'number') {
this.transactionTypes.push({value:<any>TransactionType[m], display: m});
}
}
for(let m in Fund) {
if (typeof Fund[m] === 'number') {
this.funds.push({value:<any>Fund[m], display: m});
}
}
constructor(private userService: UserService, private formBuilder: FormBuilder, private transactionService: TransactionService) {
this.form = this.formBuilder.group({
contributions: this.formBuilder.array([this.getContribution()])
});
}
ngOnInit() {
ngOnInit() {
this.types = [{value:1, display: 'Cash'},{value:2, display: 'Check'}];
this.funds = [{value:1, display: 'General'},{value:2, display: 'Missions'}];
this.userService.getAll().subscribe(res => this.contributors = (<any>res).users);
}
getContribution(): FormGroup {
const date = new Date();
const dte = date.getFullYear() + "-" + (date.getMonth()<10?'0':'') + (date.getMonth() + 1) + "-" + (date.getDate()<10?'0':'') + date.getDate();
return this.formBuilder.group({
date: [dte, Validators.required],
contributorId: [0, [Validators.required, contributorValidator(this)]],
transactions: this.formBuilder.array([this.getTransaction()])
});
}
addTransaction(contributorId: number) {
const contrib = this.contributors.find(c => c.value === contributorId);
const contributor = this.contributions.find(c => c.contributorId === contributorId);
const lastTransaction = contributor && contributor.transactions.length > 0 ? contributor.transactions[contributor.transactions.length-1] : null;
getTransaction(): FormGroup {
return this.formBuilder.group({
amount: [null, Validators.required],
checkNumber: [''],
description: [''],
fundId: [1, [Validators.required, Validators.min(1), Validators.max(2)]],
taxYear: [(new Date()).getFullYear(), Validators.required],
typeId: [1, [Validators.required, Validators.min(1), Validators.max(2)]],
}, { validators: checkNumberValidator });
}
const ref = this.dialogService.open(AddTransactionPopupComponent, {
data: {
contributors: this.contributors,
funds: this.funds,
types: this.transactionTypes,
contributor: contrib ? contrib : undefined,
typeId: lastTransaction ? lastTransaction.typeId : TransactionType.Cash,
fundId: lastTransaction ? (lastTransaction.fundId === Fund.General ? Fund.Missions : Fund.General) : Fund.General,
checkNumber: lastTransaction ? lastTransaction.checkNumber : '',
goodsOrServices: false
onContributorChange(event) {
if (event && event.value) {
if (event.value === -1) {
// Open new user dialog
}
});
ref.afterClosed().subscribe((res: {transaction:Transaction,saveAndAdd:boolean}) => {
if (res) {
let contrib = this.contributions.find(c => c.contributorId === res.transaction.contributorId);
if (!contrib) {
contrib = new Contribution();
contrib.contributorId = res.transaction.contributorId;
contrib.date = res.transaction.date;
contrib.transactions = [];
this.contributions.push(contrib);
}
res.transaction.taxYear = +res.transaction.date.split('-')[0];
contrib.transactions.push(res.transaction);
if (res.saveAndAdd === true) {
this.addTransaction(contrib.contributorId);
}
}
});
}
deleteContributor(contributorId: number) {
const contrib = this.contributions.findIndex(c => c.contributorId === contributorId);
if (contrib >= 0) {
this.contributions.splice(contrib, 1);
event = event.display;
}
const filterValue = event.toLowerCase();
this.filteredContributors = this.contributors.filter(option => option.display.toLowerCase().indexOf(filterValue) >= 0);
if (this.filteredContributors.length === 0) {
this.filteredContributors.push({value:-1, display:'Add New Contributor'});
}
}
deleteTransaction(contributorId: number, transactionIndex: number) {
const contrib = this.contributions.find(c => c.contributorId === contributorId);
if (contrib) {
contrib.transactions.splice(transactionIndex, 1);
}
if (contrib.transactions.length === 0) {
this.deleteContributor(contributorId);
contirbutorDisplayFn(contributor?: {value:number,display:string}): string | undefined {
return contributor ? contributor.display : undefined;
}
addTransaction(contributorPosition: number) {
const contributors = this.form.get('contributions') as FormArray;
const transactions = contributors.controls[contributorPosition].get('transactions') as FormArray;
const lastTransaction = transactions.value.length > 0 ? transactions.value[transactions.value.length-1] : undefined;
console.log(lastTransaction);
const newTransaction = this.getTransaction();
if (lastTransaction) {
newTransaction.patchValue({
"typeId": lastTransaction.typeId,
"checkNumber": lastTransaction.checkNumber,
"fundId": lastTransaction.fundId === 1 ? 2 : 1
});
}
transactions.push(newTransaction);
}
addContributor() {
const contributors = this.form.get('contributions') as FormArray;
contributors.push(this.getContribution());
}
deleteContributor(index: number) {
const contributors = this.form.get('contributions') as FormArray;
contributors.removeAt(index);
}
deleteTransaction(contributorIndex: number, transactionIndex: number) {
const contributors = this.form.get('contributions') as FormArray;
const transactions = contributors.controls[contributorIndex].get('transactions') as FormArray;
transactions.removeAt(transactionIndex);
}
contributorName(index: number) {
const contributors = this.form.get('contributions') as FormArray;
const contributor = contributors.controls[index].get('contributorId');
if (contributor && contributor.value.display) {
return contributor.value.display;
}
}
contributorName(id: number) {
const contributor = this.contributors.find(c => c.value === id);
return contributor ? contributor.display : undefined;
}
contributorDatesMatch(contributorId: number) {
const contributor = this.contributions.find(c => c.contributorId === contributorId);
if (!contributor) return true;
let match = true;
contributor.transactions.forEach(t => {
if (t.date != contributor.date) {
match = false;
}
});
return match;
}
contributorTotal(contributorId: number, fundId: number) {
const contrib = this.contributions.find(c => c.contributorId === contributorId);
if (!contrib) return 0;
contributorTotal(index: number, fundId: number) {
const contributors = this.form.get('contributions') as FormArray;
const transactions = contributors.controls[index].get('transactions').value;
var sum = 0;
contrib.transactions.forEach(e => {
transactions.forEach(e => {
if (e.fundId === fundId || fundId === 0) {
sum += e.amount;
}
@ -135,8 +132,9 @@ export class AddTransactionPageComponent implements OnInit {
}
combinedTotal(fundId: number) {
const contributors = this.form.get('contributions').value;
var sum = 0;
this.contributions.forEach(c => {
contributors.forEach(c => {
c.transactions.forEach(t => {
if (t.fundId === fundId || fundId === 0) {
sum += +t.amount;
@ -146,29 +144,25 @@ export class AddTransactionPageComponent implements OnInit {
return sum;
}
submit() {
onSubmit() {
this.submitButtonText = 'Submitting...';
this.submitButtonDisabled = true;
var data = this.form.value;
const transactions: Transaction[] = [];
for(let c = 0; c < this.contributions.length; c++) {
for(let t = 0; t < this.contributions[c].transactions.length; t++) {
transactions.push(this.contributions[c].transactions[t]);
for(let c = 0; c < data.contributions.length; c++) {
const contribution = data.contributions[c] as Contribution;
for(let t = 0; t < contribution.transactions.length; t++) {
const transaction = contribution.transactions[t] as Transaction;
transaction.contributorId = (<any>contribution.contributorId).value;
transaction.date = contribution.date;
transactions.push(transaction);
}
}
console.log(transactions);
this.transactionService.createFromArray(transactions).subscribe(x =>{
this.submitButtonText = 'Submit Transactions';
this.submitButtonText = 'Submit';
this.submitButtonDisabled = false;
this.contributions = [];
}, e => {
this.dialogService.open(OkPopupComponent,{
data: {
title: 'Error Saving Transactions',
message: e.toString()
}
});
});
}, e => console.log(e));
}
}

View File

@ -1,11 +0,0 @@
.w-100 {
width: 100%;
}
.w-50 {
width: 50%;
}
.m-5 {
margin: 5px;
}

View File

@ -1,54 +0,0 @@
<div md-dialog-title>
<p>Add Transaction</p>
</div>
<div md-dialog-content>
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<mat-form-field>
<input matInput placeholder="Date" type="date" formControlName="date" >
</mat-form-field>
<mat-form-field>
<input type="text" placeholder="Contributor" aria-label="Contributor" matInput formControlName="contributor" (ngModelChange)="onContributorChange($event)" [matAutocomplete]="auto">
<mat-autocomplete #auto="matAutocomplete" [displayWith]="contributorDisplayFn">
<mat-option *ngFor="let option of filteredContributors" [value]="option">
{{option.display}}
</mat-option>
</mat-autocomplete>
</mat-form-field>
<button mat-button class="m-5" type="button" (click)="addUser()">Add</button>
<br>
<mat-form-field class="w-50">
<mat-select formControlName="typeId">
<mat-option *ngFor="let type of types" [value]="type.value" >
{{type.display}}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field class="w-50">
<input matInput placeholder="Check Number" type="text" formControlName="checkNumber" >
</mat-form-field>
<div></div>
<mat-form-field class="w-50">
<mat-select formControlName="fundId">
<mat-option *ngFor="let fund of funds" [value]="fund.value">
{{fund.display}}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field class="w-50">
<input matInput placeholder="Amount" type="number" formControlName="amount" >
</mat-form-field>
<br>
<mat-form-field class="w-100">
<input matInput placeholder="Description" type="text" formControlName="description" >
</mat-form-field>
<br>
<mat-checkbox formControlName="goodsOrServices">Goods Or Services Received?</mat-checkbox>
<br>
<br>
<button mat-raised-button class="m-5" type="button" (click)="cancel()" >Cancel</button>
<button mat-raised-button class="m-5" type="submit" [disabled]="!form.valid || saveBtnDisabled">{{ saveBtnTxt }}</button>
<button mat-raised-button class="m-5" type="button" (click)="onSubmit(true)" [disabled]="!form.valid || saveBtnDisabled">{{ saveAndAddBtnTxt }}</button>
</form>
</div>

View File

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

View File

@ -1,120 +0,0 @@
import { Component, OnInit, Inject } from '@angular/core';
import { FormBuilder, FormGroup, Validators, FormArray } from '@angular/forms';
import { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef, MatDialog } from '@angular/material';
import { contributorValidator } from '../contributor-validator';
import { Transaction } from '../transaction';
import { AddUserPopupComponent } from '../../popups/add-user-popup/add-user-popup.component';
export interface ValDisplay {
value: number;
display: string;
}
export interface DialogData {
contributors: ValDisplay[],
funds: ValDisplay[],
types: ValDisplay[],
contributor: ValDisplay,
date: string,
typeId: number,
fundId: number,
checkNumber: string,
description: string,
taxYear: number,
goodsOrServices: boolean
}
@Component({
selector: 'app-add-transaction-popup',
templateUrl: './add-transaction-popup.component.html',
styleUrls: ['./add-transaction-popup.component.css']
})
export class AddTransactionPopupComponent implements OnInit {
form: FormGroup;
saveBtnDisabled: boolean = false;
saveBtnTxt: string = 'Save';
saveAndAddBtnTxt: string = 'Save & Add';
contributors: ValDisplay[] = [];
filteredContributors: ValDisplay[]
funds: ValDisplay[];
types: ValDisplay[];
constructor(private dialogService: MatDialog, private formBuilder: FormBuilder, @Inject(MAT_DIALOG_DATA) public data: DialogData, private dialogRef:MatDialogRef<AddTransactionPopupComponent>) {
this.contributors = this.data.contributors || [];
this.funds = this.data.funds || [];
this.types = this.data.types || [];
const date = new Date();
const dte = date.getFullYear() + "-" + (date.getMonth()<10?'0':'') + (date.getMonth() + 1) + "-" + (date.getDate()<10?'0':'') + date.getDate();
this.form = this.formBuilder.group({
date: [this.data.date || dte, [Validators.required]],
contributor: [this.data.contributor, [Validators.required, contributorValidator(this.contributors)]],
typeId: [this.data.typeId || 1, [Validators.required]],
fundId: [this.data.fundId || 1, [Validators.required]],
checkNumber: [this.data.checkNumber],
description: [this.data.description],
amount: ['', [Validators.required]],
taxYear: [this.data.taxYear || new Date().getFullYear(), [Validators.required]],
goodsOrServices: [this.data.goodsOrServices || false]
});
}
ngOnInit() {
}
contributorDisplayFn(contributor?: {value:number,display:string}): string | undefined {
return contributor ? contributor.display : undefined;
}
onContributorChange(event) {
if (event && event.value) {
if (event.value === -1) {
// Open new user dialog
}
event = event.display;
}
const filterValue = event.toLowerCase();
this.filteredContributors = this.contributors.filter(option => option.display.toLowerCase().indexOf(filterValue) >= 0);
if (this.filteredContributors.length === 0) {
this.filteredContributors.push({value:-1, display:'Add New Contributor'});
}
}
onSubmit(saveAndAdd: boolean = false) {
const trans = new Transaction();
trans.amount = this.form.value.amount;
trans.checkNumber = this.form.value.checkNumber;
trans.contributorId = this.form.value.contributor.value;
trans.date = this.form.value.date;
trans.description = this.form.value.description;
trans.fundId = this.form.value.fundId;
trans.taxYear = this.form.value.taxYear;
trans.typeId = this.form.value.typeId;
trans.goodsOrServices = this.form.value.goodsOrServices;
this.dialogRef.close({transaction:trans,saveAndAdd:saveAndAdd});
}
cancel() {
this.dialogRef.close();
}
addUser() {
const ref = this.dialogService.open(AddUserPopupComponent);
ref.afterClosed().subscribe((res: any) => {
if (res && res.id > 0) {
this.contributors.push({ value: res.id, display: res.lastName + ' ' + res.firstName });
let contrib = this.contributors.find(c => c.value === res.id);
this.form.get("contributor").setValue(contrib);
}
});
}
}

View File

@ -1,14 +1,14 @@
import { ValidatorFn, ValidationErrors, AbstractControl } from '@angular/forms';
import { AddTransactionPageComponent } from './add-transaction-page.component';
export function contributorValidator(contributors: {value:number,display:string}[]): ValidatorFn {
export function contributorValidator(comp: AddTransactionPageComponent): ValidatorFn {
return (control: AbstractControl): ValidationErrors | null => {
const val = control.value;
const error = {'invalidName':{value: val}};
if (!val || !val.value) {
return error;
}
const contributor = contributors.findIndex(c => c.value === val.value);
const contributor = comp.contributors.findIndex(c => c.value === val.value);
if (contributor >= 0) {
return null;
}

View File

@ -1,4 +0,0 @@
export enum Fund {
General = 1,
Missions = 2
}

View File

@ -1,4 +0,0 @@
export enum TransactionType {
Cash = 1,
Check = 2
}

View File

@ -7,5 +7,4 @@ export class Transaction {
fundId: number;
taxYear: number;
typeId: number;
goodsOrServices: boolean;
}

View File

@ -1,6 +1,6 @@
div.header{
header{
position:fixed;
top:0;
left:0;
@ -51,7 +51,7 @@ div.header{
padding-bottom: 140px;
}
div.footer{
footer{
background-color: rgb(50,50,50);
padding-top: 20px;
padding-bottom: 20px;
@ -81,7 +81,7 @@ div.footer{
}
@media(max-width: 800px){
div.footer{
footer{
height: 380px;
}
.footer-panel{

View File

@ -1,6 +1,6 @@
<div class="header" [class.print-hide]="printService.isPrinting">
<header>
<div id="header-background" [ngStyle]="{'opacity':headerOpacity}"></div>
<button mat-button class="header-button-home" routerLink="/home"><img id="logo" src="assets/images/tiny/logo.png" height="30" alt="logo"> Old Fashion Baptist</button>
<span class="hideOnMobile"></span>
@ -12,13 +12,13 @@
(click)="mainMenuClick()">
<i ofbicon class="example-icon" style="line-height:20px;">menu</i>
</button>
</div>
</header>
<div class="content" [class.print-hide-children]="printService.isPrinting">
<div class="content">
<router-outlet></router-outlet>
</div>
<div class="footer" [class.print-hide]="printService.isPrinting">
<footer>
<div id="footer-content">
<div id="footer-contact-content" class="footer-panel">
<a target="_blank" href="https://www.google.com/maps/place/Old+Fashion+Baptist+Church/@45.9814004,-112.5320574,11.87z/data=!4m12!1m6!3m5!1s0x535b078c3c74ea33:0xac299097142c5894!2sOld+Fashion+Baptist+Church!8m2!3d45.951287!4d-112.511978!3m4!1s0x535b078c3c74ea33:0xac299097142c5894!8m2!3d45.951287!4d-112.511978">
@ -27,9 +27,8 @@
</a>
<p><a href="tel:+1-406-494-5028" class="phone">(406) 494 - 5028</a></p>
<p>Pastor Derek Loewen</p>
<br>
<p>Pastor Emeritus Ron Derksen</p>
</div>
<div id="footer-services-content" class="footer-panel">
<p>Sunday School: 10AM</p>
<p>Sunday Worship: 11AM</p>
@ -41,14 +40,14 @@
<p><i ofbicon class="copyright">copyright</i> Copyright {{copyrightYear}}</p>
<p>Old Fashion Baptist</p>
<p><a routerLink="/home">ofbbutte.com</a></p>
<p><a href="https://publicfiles.fcc.gov/fm-profile/KFGL" target="_blank">KFGL Public Information File</a></p>
<p>Powered by God</p>
<br>
</div>
</div>
<div class="audio-player-filler" [hidden]="!showAudioPlayer" ></div>
</div>
</footer>
<div class="audio-player" [class.audio-player-slide-up]="showAudioPlayer" [class.print-hide]="printService.isPrinting">
<div class="audio-player" [class.audio-player-slide-up]="showAudioPlayer">
<audio-player-component (closed)="audioPlayerClosed()" (started)="audioPlayerStarted()"></audio-player-component>
</div>

View File

@ -4,7 +4,6 @@ import { Router, NavigationEnd, Event } from '@angular/router';
import { EventService } from '../../services/event.service';
import { AudioPlayerService } from '../../services/audio-player.service';
import { BibleVerseService } from '../../services/bible-verse.service';
import { PrintService } from '../../services/print-service';
@Injectable()
@ -27,8 +26,7 @@ export class AppComponent {
constructor(private router: Router,
private audioPlayerService: AudioPlayerService,
private googleAnalyticsService: GoogleAnalyticsService,
public printService: PrintService){
private googleAnalyticsService: GoogleAnalyticsService){
this.router.events.subscribe((event:Event) => {
if(event instanceof NavigationEnd) {
this.lastRoute = this.currRoute;

View File

@ -1,23 +0,0 @@
.full-width{
width: 100%;
}
.hide{
display: none;
}
.bold {
font-weight: bold;
}
.margin-top-space {
margin-top: 20px;
}
.errorMessages{
color: white;
background-color: rgb(255,90,90);
padding: 10px;
border-radius: 3px;
margin-bottom: 5px;
}

View File

@ -1,49 +0,0 @@
<secondary-page-component [hideSideBarOnMobile]="true" >
<div mainContent>
<br>
<p class="bold">
We are so glad you found one of our balloons. We would love to hear from you
and where you found it!
</p>
<p class="margin-top-space">
Click <a routerLink="/whoweare">here</a> to learn more about us.
</p>
<p class="margin-top-space">
Click <a routerLink="/salvation">here</a> to learn more about <span class="bold">Jesus</span>.
</p>
<br>
<div *ngIf="!formSubmitted">
<form class="form" #contactForm="ngForm" (ngSubmit)="onSubmit()">
<mat-form-field class="full-width">
<input matInput type="text" placeholder="Name" required value="" [(ngModel)]="name" name="name" >
</mat-form-field>
<mat-form-field class="full-width">
<input matInput type="text" placeholder="City, State" required value="" [(ngModel)]="location" name="location" >
</mat-form-field>
<mat-form-field class="full-width">
<input matInput type="email" placeholder="Email" value="" [(ngModel)]="email" name="email" pattern="^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$">
</mat-form-field>
<mat-form-field class="full-width">
<input matInput type="tel" placeholder="Phone" value="" [(ngModel)]="phone" name="phone">
</mat-form-field>
<mat-form-field class="full-width">
<textarea matInput type="text" placeholder="Other Information or Questions" value="" [(ngModel)]="body" name="body" rows="5" ></textarea>
</mat-form-field>
<mat-form-field class="hide">
<input matInput type="text" placeholder="hp" required value="" [(ngModel)]="hp" name="subject">
</mat-form-field>
<div class="errorMessages" *ngIf="errorMessages.length > 0">
<p *ngFor="let error of errorMessages">{{error}}</p>
</div>
<button mat-raised-button type="submit" [disabled]="!contactForm.form.valid || submitButtonDisabled">{{submitButtonText}}</button>
</form>
</div>
<div *ngIf="formSubmitted">
<p><b>Thank You!</b></p>
<p>Your message has been sent.</p>
</div>
</div>
<div sideBar ofbFadeInOnScroll>
</div>
</secondary-page-component>

View File

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

View File

@ -1,84 +0,0 @@
import { Router } from '@angular/router';
import { MatDialogConfig } from '@angular/material';
import { OkPopupComponent } from '../popups/ok-popup/ok-popup.component';
import { EmailService } from '../../services/email.service';
import { Component, OnInit } from '@angular/core';
import { MatDialog } from '@angular/material';
@Component({
selector: 'app-contact-page',
templateUrl: './balloon.component.html',
styleUrls: ['./balloon.component.css']
})
export class BalloonComponent implements OnInit {
public submitButtonText: string = "Submit";
public submitButtonDisabled: boolean = false;
public formSubmitted: boolean = false;
public name: string;
public email: string;
public location: string;
public phone: string;
public body: string;
public hp: string = ".";
public errorMessages: string[] = [];
constructor(private emailService: EmailService,
private MatDialog: MatDialog,
private router: Router) { }
ngOnInit() {
}
onSubmit(){
this.errorMessages = [];
if (this.name == null || this.name == ""){
this.errorMessages.push("Please enter a name");
}
if (this.location == null || this.location == ""){
this.errorMessages.push("Please enter a city and state");
}
if (this.errorMessages.length > 0){ return; }
const body = `Location of balloon: ${this.location}<br>${this.body || ''}`;
let email = this.email;
if (!email || email.length === 0) {
email = 'N/A';
}
this.submitButtonText = "Please Wait...";
this.submitButtonDisabled = true;
this.emailService.sendEmail(this.name,
email,
this.phone || '',
body,
this.hp)
.subscribe(
success => {this.emailSuccess();},
error => {this.emailError();});
}
private emailSuccess(){
let opts = new MatDialogConfig;
opts.data = { title:'Email Sent','message':'Thank You! Your message has been sent.' };
let popup = this.MatDialog.open(OkPopupComponent,opts);
this.submitButtonText = "Submit";
this.submitButtonDisabled = false;
popup.afterClosed().subscribe(()=>{
this.formSubmitted = true;
});
}
private emailError(){
console.error("error");
let opts = new MatDialogConfig;
opts.data = { title:'Email Error','message':'Please make sure that you have entered a valid email address.' };
let popup = this.MatDialog.open(OkPopupComponent,opts);
this.submitButtonText = "Submit";
this.submitButtonDisabled = false;
}
}

View File

@ -1,10 +1,5 @@
<secondary-page-component [hideSideBarOnMobile]="true" >
<div mainContent>
<br>
<p>
For general questions please complete the form below. If you are a missionary requesting
support please complete the <a routerLink="/missionary">Missionary Questionnaire form by clicking here.</a>
</p>
<br>
<div *ngIf="!formSubmitted">
<form class="form" #contactForm="ngForm" (ngSubmit)="onSubmit()">

View File

@ -1,5 +0,0 @@
@media print {
:host {
display: block;
}
}

View File

@ -1,3 +0,0 @@
<app-contributor-yearly-report *ngFor="let c of contributors; let i = index" [index]="i" [contributorTransactions]="c">
</app-contributor-yearly-report>

View File

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

View File

@ -1,50 +0,0 @@
import { Component, OnInit } from '@angular/core';
import { PrintService } from 'src/app/services/print-service';
import { UserService } from 'src/app/services/user.service';
import { TransactionService } from 'src/app/services/transaction.service';
import { forkJoin } from 'rxjs';
@Component({
selector: 'app-contributor-all-reports',
templateUrl: './contributor-all-reports.component.html',
styleUrls: ['./contributor-all-reports.component.css']
})
export class ContributorAllReportsComponent implements OnInit {
public contributors: {contributor:{}, transactions:[]}[] = [];
constructor(private printService: PrintService, private userService: UserService, private transactionService: TransactionService) { }
ngOnInit() {
const taxYear = 2024;
const query = forkJoin([this.userService.getAll(), this.transactionService.getByYear(taxYear), this.transactionService.getByYear(taxYear - 1)]);
query.subscribe(res => this.setup(res[0], res[1], res[2]));
this.printService.setPrinting(true);
}
private setup(contributorResult, transactionResult, priorYearTransactionResult) {
const contributors = contributorResult.users;
const transactions = transactionResult.transactions;
const priorYearTransactions = priorYearTransactionResult.transactions;
const contrib = {};
transactions.forEach(t => {
if (contrib.hasOwnProperty(t.contributorId)) {
contrib[t.contributorId].transactions.push(t);
} else {
const con = contributors.find(c => c.id === t.contributorId);
if (con) {
contrib[con.id] = {contributor: con, transactions: [t]};
contrib[con.id].priorYearTransactions = priorYearTransactions.filter(t => t.contributorId === con.id);
this.contributors.push(contrib[con.id]);
} else {
console.error('coould not find contributor for', t);
}
}
});
}
}

View File

@ -1,140 +0,0 @@
@media screen {
:host {
display: none;
}
}
@media print {
:host {
display: block;
margin-top: -50px;
-webkit-print-color-adjust: exact;
color-adjust: exact;
}
tr.page-break-after:after { content:""; display: block; page-break-before: always; }
}
.h-100 {
height: 300px;
}
.w-100 {
width: 100%;
}
.d-block {
display: block;
}
.flex {
display: flex;
}
.flex-grow-1 {
flex-grow: 1;
}
.flex-direction-column {
flex-direction: column;
}
.flex-align-center {
align-items: center;
}
.flex-justify-space-between {
justify-content: space-between;
}
.flex-align-space-between {
align-content: space-between;
}
.flex-align-top {
align-items: start;
}
.flex-align-stretch {
align-items: stretch;
}
.flex-justify-center {
justify-content: center;
}
.flex-justify-space-between {
justify-content: space-between;
}
hr {
border-top: 1px solid green;
}
.text-center {
text-align: center;
}
.text-right {
text-align: right;
}
.text-left {
text-align: left;
}
.mt-5 {
margin-top: 5px;
}
.mt-20 {
margin-top: 20px;
}
.mb-20 {
margin-bottom: 20px;
}
.mr-40 {
margin-right: 40px;
}
.flex-direction-column {
flex-direction: column;
}
.page-break-before {
page-break-before: always;
}
.fw-bold {
font-weight: bold;
}
.hilight-yellow {
background-color: yellow;
}
table.borders {
border-collapse: collapse;
}
table.borders th, table.borders tr.row td {
border: 1px solid black;
}
table.cell-padding-5 td, table.cell-padding-5 th {
padding: 5px;
}
table.highlight-even tr.row:nth-child(even) {
background-color: #e6ffe6;
}
table tbody tr.footer td {
font-size: small;
vertical-align: bottom;
}
.text-align-right {
text-align: right;
}

View File

@ -1,121 +0,0 @@
<div *ngIf="index > 0" class="page-break-before"></div>
<div class="h-100 flex flex-align-center flex-justify-center flex-direction-column">
<img src="../../../assets/images/original/logo_dark.png">
<p class="mt-5">
Old Fashion Baptist Church Giving Statement {{taxYear}}
</p>
<p class="mt-5">
{{contributorName}}
</p>
<p *ngIf="contributorStreet && contributorCity && contributorState && contributorZip">{{contributorStreet}}</p>
<p *ngIf="contributorStreet && contributorCity && contributorState && contributorZip">{{contributorCity}} {{contributorState}}, {{contributorZip}}</p>
</div>
<div class="page-break-before">
<div class="header flex flex-justify-space-between">
<div>
<img src="../../../assets/images/original/logo_dark.png">
</div>
<div class="text-right">
<p>Old Fashion Baptist Church</p>
<p>5003 Wynne Ave</p>
<p>Butte, MT 59701</p>
<p>(406) 494-5028</p>
<p>ofbbutte.com</p>
</div>
</div>
<hr class="hr mt-20">
<h2 class="text-center mt-20">Old Fashion Baptist Church Giving Statement {{taxYear}}</h2>
<hr class="mt-20">
<div class="flex flex-align-stretch flex-justify-space-between">
<div class="mt-20 mb-20 mr-40 flex-grow-1 flex flex-direction-column flex-justify-space-between">
<div class="mt-20">
<p><b>Name: </b>{{contributorName}}</p>
<p><b>Year: </b>{{taxYear}}</p>
</div>
<table class="cell-padding-5 borders w-100">
<thead>
<tr>
<th colspan="2">{{taxYear}} Giving Summary</th>
</tr>
</thead>
<tbody class="cell-padding-5">
<tr class="row">
<td class="fw-bold">General Fund</td>
<td class="text-right">{{totalGeneral() | currency}}</td>
</tr>
<tr class="row">
<td class="fw-bold">Missions Fund</td>
<td class="text-right">{{totalMissions() | currency}}</td>
</tr>
<tr class="row">
<td class="fw-bold">Total Giving</td>
<td class="text-right hilight-yellow">{{(totalGeneral() + totalMissions()) | currency}}</td>
</tr>
</tbody>
</table>
<div>
Thank you for your support. The information provided in this statement reflects
your gifts on record for {{taxYear}}.
No goods or services were provided in exchange for your contributions.
</div>
</div>
<div class="mt-20">
<canvas #chart width="400" height="300"></canvas>
</div>
</div>
</div>
<table class="highlight-even cell-padding-5 w-100 borders mt-20">
<thead>
<tr>
<th class="text-left">Date</th>
<th nowrap class="text-left">Payment Type</th>
<th nowrap class="text-left">Check Number</th>
<th class="text-left">Fund</th>
<th class="text-left">Description</th>
<th class="text-left">Amount</th>
</tr>
</thead>
<tbody>
<ng-container *ngFor="let t of transactions; let i = index">
<tr class="row">
<td nowrap>{{t.date | date:'MM-dd-yyyy':'UTC'}}</td>
<td nowrap>{{t.typeId === 1 ? 'Cash' : (t.typeId === 2 ? 'Check' : 'NA')}}</td>
<td nowrap>{{t.checkNumber}}</td>
<td nowrap>{{t.fundId === 1 ? 'General' : (t.fundId === 2 ? 'Missions' : 'NA')}}</td>
<td width="99%">{{t.description}}</td>
<td nowrap class="text-align-right">{{t.amount | currency}}</td>
</tr>
<tr *ngIf="isFooter(i+1)" class="footer page-break-after">
<td colspan="6">
<div class="flex flex-justify-space-between">
<p>Old Fashion Baptist Church Giving Statement {{taxYear }}</p>
<p>Page {{calcPage(i+1)}} of {{pages}}</p>
</div>
</td>
<div></div><!--DIV IS HERE TO MAKE PAGE BREAKS WORK CORRECTLY-->
</tr>
</ng-container>
<ng-container *ngFor="let r of fillerRows; let i = index">
<tr>
<td nowrap>&nbsp;</td>
<td nowrap></td>
<td nowrap></td>
<td nowrap></td>
<td width="99%"></td>
<td nowrap></td>
</tr>
<tr *ngIf="i === fillerRows.length-1" class="footer">
<td colspan="6">
<div class="flex flex-justify-space-between">
<p>Old Fashion Baptist Church Giving Statement {{taxYear}}</p>
<p>Page {{pages}} of {{pages}}</p>
</div>
</td>
</tr>
</ng-container>
</tbody>
</table>
<div *ngIf="pagesOdd" class="page-break-before">&nbsp;</div>

View File

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

View File

@ -1,158 +0,0 @@
import { Component, OnInit, Input, ViewChild, ElementRef } from '@angular/core';
import { PrintService } from '../../services/print-service';
import { Transaction } from '../add-transaction-page/transaction';
import * as Chart from 'chart.js';
import ChartDataLabels from 'chartjs-plugin-datalabels';
import { CurrencyPipe } from '@angular/common';
@Component({
selector: 'app-contributor-yearly-report',
templateUrl: './contributor-yearly-report.component.html',
styleUrls: ['./contributor-yearly-report.component.css']
})
export class ContributorYearlyReportComponent implements OnInit {
@ViewChild('chart') chartElement:ElementRef;
@Input() index: number;
@Input() contributorTransactions: {contributor: {}, transactions: {}, priorYearTransactions: {}};
public transactions: Transaction[] = [];
public priorTransactions: Transaction[] = [];
public get contributorName(): string {
const first = (<any>this.contributorTransactions.contributor).firstName;
const last = (<any>this.contributorTransactions.contributor).lastName;
if (last && first) {
return last + ', ' + first;
} else if (last) {
return last;
} else if (first) {
return first;
} else {
return '';
}
}
public contributorStreet: string = '7878 Washington St';
public contributorCity: string = 'Butte';
public contributorState: string = 'MT';
public contributorZip: string = '59701';
public taxYear: number = 2024;
public rowsFirstPage: number = 11;
public rowsPerPage: number = 30;
public get fillerRows(): number[] {
const rowsToFillPage = this.rowsFirstPage + ((this.pages - 2) * this.rowsPerPage);
const rowsNeeded = rowsToFillPage - this.transactions.length;
return Array(rowsNeeded).fill(1).map((x,i)=>i)
}
public get pages(): number {
return Math.ceil((this.transactions.length - this.rowsFirstPage) / this.rowsPerPage) + 2;
}
public get pagesOdd(): boolean {
return !(this.pages % 2 == 0)
}
private currencyPipe: CurrencyPipe = new CurrencyPipe('en-US');
constructor(public printService: PrintService) { }
ngOnInit() {
this.contributorCity = (<any>this.contributorTransactions.contributor).city;
this.contributorState = (<any>this.contributorTransactions.contributor).state;
this.contributorStreet = (<any>this.contributorTransactions.contributor).street;
this.contributorZip = (<any>this.contributorTransactions.contributor).zip;
this.transactions = <any>this.contributorTransactions.transactions;
this.priorTransactions = <any>this.contributorTransactions.priorYearTransactions;
this.renderChart();
}
public totalGeneral() {
let sum = 0;
this.transactions.filter(t => t.fundId === 1).forEach(t => sum += t.amount);
return sum;
}
public priorGeneral() {
let sum = 0;
this.priorTransactions.filter(t => t.fundId === 1).forEach(t => sum += t.amount);
return sum;
}
public totalMissions() {
let sum = 0;
this.transactions.filter(t => t.fundId === 2).forEach(t => sum += t.amount);
return sum;
}
public priorMissions() {
let sum = 0;
this.priorTransactions.filter(t => t.fundId === 2).forEach(t => sum += t.amount);
return sum;
}
public calcPage(index: number): number {
const val = Math.max(index, this.rowsFirstPage);
return Math.ceil((val - this.rowsFirstPage) / this.rowsPerPage) + 2;
}
public isFooter(index: number): boolean {
if (index === this.rowsFirstPage) {
return true;
}
if (index === (this.rowsFirstPage + ((this.calcPage(index) - 2) * this.rowsPerPage))) {
return true;
}
return false;
}
private renderChart() {
const me = this;
var myChart = new Chart(this.chartElement.nativeElement, {
plugins: [ChartDataLabels],
type: 'bar',
data: {
labels: [(this.taxYear - 1).toString(), this.taxYear.toString()],
datasets: [{
label: 'General',
data: [this.priorGeneral(), this.totalGeneral()],
backgroundColor: 'rgba(54, 245, 162, 0.2)',
borderColor: 'rgba(54, 245, 162, 1)',
borderWidth: 1
}, {
label: 'Missions',
data: [this.priorMissions(), this.totalMissions()],
backgroundColor: 'rgba(54, 162, 235, 0.2)',
borderColor: 'rgba(54, 162, 235, 1)',
borderWidth: 1
}]
},
options:{
scales: {
xAxes: [{
stacked: true
}],
yAxes: [{
stacked: true,
ticks: {
callback: function(value, index, values) {
return me.currencyPipe.transform(value, 'USD', 'symbol', '1.0-0');
}
}
}]
},
plugins:{
datalabels:{
font:{
weight: 'bold'
},
formatter: function(value, context){
if (value === 0) {
return '';
}
return me.currencyPipe.transform(value, 'USD', 'symbol', '1.0-2');
}
}
}
}
});
}
}

View File

@ -1,23 +0,0 @@
.section-header{
font-size: 1.2em;
font-weight: bold;
border-bottom: 1px solid gray;
margin-bottom: 10px;
}
a{
color: inherit;
}
a:visited{
color: inherit;
}
.break-word {
overflow-wrap: break-word;
word-wrap: break-word;
-ms-word-break: break-all;
word-break: break-word;
}

View File

@ -1,16 +0,0 @@
<secondary-page-component [hideSideBarOnMobile]="true">
<div mainContent>
<p ofbFadeInOnScroll class="section-header">FCC Noncommercial FM Radio Station Construction Permit</p>
<p ofbFadeInOnScroll class="section-paragraph">
On November 9, 2021, Old Fashion Baptist Church of Butte, applicant for a Noncommercial FM Radio Station on
88.1mhz, in Butte, MT, filed an application with the Federal Communications Commission for a new Noncommercial FM
Station. Members of the public wishing to view this application or obtain information about how to file comments and
petitions on the application can visit <a class="break-word" href="https://enterpriseefiling.fcc.gov/dataentry/views/public/nceDraftCopy?displayType=html&appKey=25076f917cce2f5b0
17cd34cdd450dee&id=25076f917cce2f5b017cd34cdd450dee&goBack=N">https://enterpriseefiling.fcc.gov/dataentry/views/public/nceDraftCopy?displayType=html&appKey=25076f917cce2f5b0
17cd34cdd450dee&id=25076f917cce2f5b017cd34cdd450dee&goBack=N</a>.
</p>
</div>
<div sideBar class="side-bar">
</div>
</secondary-page-component>

View File

@ -1,15 +0,0 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-fcc-permit-page',
templateUrl: './fcc-permit-page.component.html',
styleUrls: ['./fcc-permit-page.component.css']
})
export class FCCPermitPageComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}

View File

@ -1,151 +0,0 @@
import { DateTime } from "luxon";
import { VideoServices, VideoService } from './video-services';
export class Countdown {
public days: number = 0;
public hours: number = 0;
public minutes: number = 0;
public seconds: number = 0;
public services: VideoService[] = [];
public showButton: boolean;
public showCounter: boolean = false;
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(services: VideoService[]) {
if (!services || services.length == 0) return;
this.services = services;
this.services.forEach(v => {
v.date = DateTime.fromISO(v.date, {zone: 'America/Denver'})
});
this.services.sort((a, b) => {
if (a.date < b.date) return -1;
if (a.date === b.date) 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 firstNonArchived = this.getFirstNonArchived(now);
if (!firstNonArchived) {
this.stopClock();
this.resetToZero();
this.showCounter = false;
this.dateDisplay = '';
this.dateDisplaySmall = '';
return;
}
var hourDiff = (<DateTime>firstNonArchived.date).diff(now, ['hours']);
if (hourDiff.hours >= 48) {
this.showCounter = false;
this.dateDisplay = '';
this.dateDisplaySmall = '';
return;
}
var secDiff = (<DateTime>firstNonArchived.date).diff(now, ['seconds']);
if (secDiff.seconds <= 0) {
this.showButton = true;
}
var diff = (<DateTime>firstNonArchived.date).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 = firstNonArchived.date.toLocaleString(DateTime.DATETIME_HUGE);
this.dateDisplaySmall = firstNonArchived.date.toLocaleString(DateTime.DATETIME_MED)
}
private startClock() {
this.clock = setInterval(this.updateClock.bind(this), 1000);
}
private stopClock() {
clearInterval(this.clock);
}
private getFirstNonArchived(now: DateTime): VideoService {
if (this.services.length === 0) return null;
const nonArchived = this.services.filter(s => s.archived === false);
if (!nonArchived || nonArchived.length === 0) return null;
return nonArchived[0];
}
private getNearestPastDate(now: DateTime): VideoService {
if (this.services.length === 0) return null;
const archived = this.services.filter(s => s.archived === false);
if (!archived || archived.length === 0) return null;
var now = now || DateTime.local();
var nearestIndex = archived.findIndex(s => s.date > now);
if (nearestIndex === 0) return null;
if (nearestIndex === -1) return archived[archived.length - 1];
return archived[nearestIndex - 1];
}
private getNearestFutureDate(now: DateTime): VideoService {
if (this.services.length === 0) return null;
var now = now || DateTime.local();
var nearest = this.services.find(s => s.date > 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

@ -7,42 +7,21 @@ a{
color: inherit;
}
a {
text-decoration: underline;
}
a:hover {
cursor: pointer;
}
a:visited{
color: inherit;
}
.bold {
font-weight: bold;
}
img{
width: 70%;
height: auto;
}
img.w-100pct {
width: 100%;
height: auto;
}
img.full {
width: 100%;
height: auto;
}
.color-white {
color: white;
}
#call-to-action-container {
text-align: center;
position: absolute;
@ -51,128 +30,6 @@ 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: 18pt;
}
#countdown-container {
font-size: 20pt;
}
#live-button {
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: 13pt;
}
#countdown-container {
font-size: 13pt;
margin-top: 3px;
}
.display-none-sm {
display: none;
}
.display-sm {
display: block;
}
#live-date {
margin-top: 2px;
}
#live-button {
font-size: 18pt;
margin-top: -5px;
}
}
#action-button {
font-size: 16pt;
max-width: 100%;
@ -182,18 +39,6 @@ img.full {
margin-right: 10px;
}
.w-100 {
width: 100%;
}
.w-200 {
width: 200px;
}
.h-200 {
height: 200px;
}
.action{
font-weight: bold;
font-size: 20px;
@ -330,9 +175,7 @@ img.full {
margin: 10px;
}
img.m-100-lg {
margin-left: 100px;
}
@media(max-width: 850px){
.row-content-col-left, .row-content-col-right{
@ -344,16 +187,5 @@ img.m-100-lg {
img.full {
width: 90%;
}
img.m-100-lg {
margin-left: 0;
}
img.w-100pct {
width: 65%;
}
}
@media(max-width: 600px) {
img.w-100pct {
width: 95%;
}
}

View File

@ -2,112 +2,38 @@
<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="showCountdown && countdown && countdown.showCounter">
<div id="title">
<span class="live">VIDEO</span>
<span *ngIf="!countdown.showButton"> SERVICE STARTS IN</span>
<span *ngIf="countdown.showButton"> SERVICE AVAILABLE 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
</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">
<a id="action-button" href="/assets/Reopening Church Guidelines.pdf" target="_blank" mat-raised-button color="accent"><i ofbicon class="mr-10 color-white">info_outline</i><span class="color-white">Reopening Guidelines</span></a>
</div>
<button id="action-button" routerLink="/camp" mat-raised-button color="accent"><i ofbicon class="mr-10">info_outline</i>2019 Youth Camp</button>
</div>
</div>
<div id="content-wrapper">
<div style="text-align: center; position: relative; margin-bottom: 15px;" *ngIf="showVBS">
<div style="position: absolute; width: 100%; height: calc(65% + 15px); top: 35%; background-color: white;"></div>
<img src="assets/images/home-images/tiny/VBS_small.jpg" style="width:75%; max-width: 350px; position: relative; z-index: 1; box-shadow: 0 0 20px pink;" >
</div>
<div class="row tint" *ngIf="showVGC" >
<div class="row tint" *ngIf="showSpecial" >
<div class="row-content">
<div class="row-content-col-left center">
<img style="max-height:500px" ofbFadeInOnScroll src="assets/images/original/VictoryGospelCrusade.png" height="500">
</div>
<div class="row-content-col-right align-top">
<p ofbFadeInOnScroll class="row-content-header">Victory Gospel Crusade</p>
<br />
<p ofbFadeInOnScroll class="bold">
When
</p>
<p ofbFadeInOnScroll>
August 4 - 9 @ 7PM
<br />
August 11 - 15 @ 7 PM
</p>
<br>
<p ofbFadeInOnScroll class="bold">
Where
</p>
<p ofbFadeInOnScroll>
Behind Pizza Ranch
<br />
1839 Longfellow St, Butte, Mt
<br /><br />
<i ofbicon>directions</i> <a target="_blank" class="align-top" href="https://www.google.com/maps/place/1839+Longfellow+St,+Butte,+MT+59701/@45.9732501,-112.513401,17z/data=!3m1!4b1!4m6!3m5!1s0x535b07e062beaaf7:0x827616c9ef692eed!8m2!3d45.9732464!4d-112.5108261!16s%2Fg%2F11v03h9chf?entry=ttu">View Map</a>
</p>
<p ofbFadeInOnScroll class="action">
<i ofbicon>play_arrow</i> <a (click)="playVictoryGospelCrusade()" class="align-top">Click Here To Watch The Trailer</a>
</p>
</div>
</div>
</div>
<div class="row" *ngIf="showSpecial" >
<div class="row-content">
<div class="row-content-col-left center">
<img style="max-height:500px" ofbFadeInOnScroll src="assets/images/home-images/tiny/Cowboy Carnival.jpg" height="500">
<div class="row-content-col-left">
<a href="assets/images/champ_flyer.jpg" download="champ_flyer.jpg"><img class="full" ofbFadeInOnScroll src="assets/images/home-images/tiny/champ.jpg" height="300"></a>
</div>
<div class="row-content-col-right align-top center">
<p ofbFadeInOnScroll class="row-content-header">Cowboy Carnival</p>
<p ofbFadeInOnScroll class="row-content-header">Champ the Smiling Trick Horse</p>
<p ofbFadeInOnScroll>
Come join us for Ranger Walkers Wild West Cowboy Carnival!
Come join us for this special event happening September 5th and 6th at Old Fashion Baptist!
</p>
<br>
<p ofbFadeInOnScroll class="bold">
Family Fun
<p ofbFadeInOnScroll>
<b>Wednesday, September 5 @ 7 PM</b>
<br>
Bible Preaching & Bluegrass Gospel Music
</p>
<br>
<p ofbFadeInOnScroll class="bold">
Games
<p ofbFadeInOnScroll>
<b>Thursday, September 6 @ 5:30 PM</b>
<br>
Food, Games, Music & Preaching
</p>
<br>
<p ofbFadeInOnScroll class="bold">
Rides
</p>
<br>
<p ofbFadeInOnScroll class="bold">
Inflatables
</p>
<br>
<p ofbFadeInOnScroll style="font-size:1.25em;">
<b>Sunday, September 18 @ 11:00 AM</b>
<p ofbFadeInOnScroll>
<a href="assets/images/champ_flyer.jpg" download="champ_flyer.jpg"><b>Click here to download the flyer</b></a>
</p>
<br>
<p ofbFadeInOnScroll class="action">
@ -119,7 +45,7 @@
<div class="row">
<div class="row-content">
<div class="row-content-col-right align-top">
<div class="row-content-col-left align-top">
<p ofbFadeInOnScroll class="row-content-header">...that ye also may have fellowship with us...</p>
<p ofbFadeInOnScroll>It is exciting to gather together in the name of the Lord and
we sincerily hope that YOU will join us. Guests are always welcome at Old Fashion
@ -127,7 +53,7 @@
<p class="verse" ofbFadeInOnScroll>For where two or three are gathered together in my name, there am I in the midst of them. - Matthew 18:20</p>
<p ofbFadeInOnScroll class="action"><i ofbicon>info_outline</i> <a href="#" routerLink="/whoweare" class="align-top">Learn more about us</a></p>
</div>
<div class="row-content-col-left">
<div class="row-content-col-right">
<!-- <img ofbFadeInOnScroll src="assets/images/home-images/2-church-color.png"> -->
<a routerLink="/whoweare"><img ofbFadeInOnScroll src="assets/images/home-images/tiny/family.jpg"></a>
</div>

View File

@ -2,10 +2,6 @@ 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';
import { HttpClient } from '@angular/common/http';
import { VideoServices } from './video-services';
import { YoutubePopupComponent } from '../popups/youtube-popup/youtube-popup.component';
@Component({
selector: 'home-component',
@ -14,55 +10,20 @@ import { YoutubePopupComponent } from '../popups/youtube-popup/youtube-popup.com
})
export class HomeComponent {
backgroundTop: string = "0px";
public get showVGC() : boolean {
let maxDate = new Date(2024,7,15,11); // August 15th 2018 -- Set the month one month behind since JavaScript dates are 0 based
let now = new Date();
if (now.getFullYear() > maxDate.getFullYear()) return false;
if (now.getFullYear() == maxDate.getFullYear()) {
if (now.getMonth() > maxDate.getMonth()) return false;
if (now.getMonth() == maxDate.getMonth()) {
if (now.getDate() > maxDate.getDate()) return false;
if (now.getDate() == maxDate.getDate()) {
if (now.getHours() > maxDate.getHours()) return false;
}
}
}
return true;
}
public get showSpecial() : boolean {
let maxDate = new Date(2022,8,18,11); // September 18th 2018 -- Set the month one month behind since JavaScript dates are 0 based
let maxDate = new Date(2018,8,6); // September 6th 2018 -- Set the month one month behind since JavaScript dates are 0 based
let now = new Date();
if (now.getFullYear() > maxDate.getFullYear()) return false;
if (now.getFullYear() == maxDate.getFullYear()) {
if (now.getMonth() > maxDate.getMonth()) return false;
if (now.getMonth() == maxDate.getMonth()) {
if (now.getDate() > maxDate.getDate()) return false;
if (now.getDate() == maxDate.getDate()) {
if (now.getHours() > maxDate.getHours()) return false;
}
}
}
return true;
}
public get showCallToAction(): boolean {
let maxDate = new Date(2020,4,10); // July 8th 2018 -- Set the month one month behind since JavaScript dates are 0 based
let now = new Date();
if (now.getFullYear() > maxDate.getFullYear()) return false;
if (now.getFullYear() == maxDate.getFullYear()) {
if (now.getMonth() > maxDate.getMonth()) return false;
if (now.getMonth() == maxDate.getMonth()) {
if (now.getDate() > maxDate.getDate()) return false;
}
}
return true;
}
public get showVBS(): boolean {
let maxDate = new Date(2019,7,22); // August 22nd 2018 -- Set the month one month behind since JavaScript dates are 0 based
let maxDate = new Date(2019,6,8); // September 6th 2018 -- Set the month one month behind since JavaScript dates are 0 based
let now = new Date();
if (now.getFullYear() > maxDate.getFullYear()) return false;
if (now.getFullYear() == maxDate.getFullYear()) {
@ -74,26 +35,11 @@ export class HomeComponent {
return true;
}
public countdown: Countdown;
public showCountdown: boolean = false;
constructor(private dialog: MatDialog, private http: HttpClient)
constructor(private dialog: MatDialog)
{
this.http.get<VideoServices>('assets/json/videoServices.json').subscribe(res => {
this.countdown = new Countdown(res.videos);
});
}
playVictoryGospelCrusade() {
const url = 'https://drive.google.com/file/d/1gPdCTLkJEtNWEyn_y8FQ78PaDi40MU7N/preview'
let opts = new MatDialogConfig;
opts.data = { title: 'Victory Gospel Crusade', embedUrl: url };
let dialog = this.dialog.open(YoutubePopupComponent, opts);
}
@HostListener('window:scroll', ['$event'])
onScroll(event){
let scrollTop = event.target.documentElement.scrollTop || event.target.body.scrollTop || window.pageYOffset;

View File

@ -1,12 +0,0 @@
export class VideoServices {
videos: VideoService[];
}
export class VideoService {
isReady: boolean;
title: string;
src: string;
date: Date;
archived: boolean;
yt: string;
}

View File

@ -1,16 +0,0 @@
.fab-buttons{
display: none;
}
.side-bar{
position: fixed;
}
@media(max-width:800px){
.fab-buttons{
display: inline-block;
position: fixed;
bottom: 20px;
right: 20px;
}
}

View File

@ -1,13 +0,0 @@
<secondary-page-component [hideSideBarOnMobile]="true" >
<div mainContent class="mapWrapper">
<img style="width: 100%" src="{{imageUrl}}">
<div class="fab-buttons" >
<button mat-fab (click)="share()"><i ofbicon>share</i></button>
</div>
</div>
<div sideBar ofbFadeInOnScroll>
<div class="side-bar">
<button style="width: 100%;" mat-stroked-button (click)="share()"><i ofbicon>share</i> Share</button>
</div>
</div>
</secondary-page-component>

View File

@ -1,40 +0,0 @@
import { BibleVerseService } from './../../services/bible-verse.service';
import { Component, OnInit, Inject, Input } from '@angular/core';
import { MatDialogConfig, MatDialog } from '@angular/material';
import { SharePopupComponent } from '../popups/share-popup/share-popup.component';
import { DOCUMENT } from '@angular/platform-browser';
import { Router, ActivatedRouteSnapshot, ActivatedRoute } from '@angular/router';
@Component({
selector: 'image-component',
templateUrl: './image.component.html',
styleUrls: ['./image.component.css']
})
export class ImageComponent implements OnInit {
public imageUrl: string;
public shareName: string
constructor(private dialog: MatDialog, @Inject(DOCUMENT) private document, private route: ActivatedRoute) {
this.imageUrl = this.route.snapshot.data.imageUrl;
this.shareName = this.route.snapshot.data.shareName;
}
ngOnInit() {
// this.bibleVerseService.randomVerse().subscribe(
// verse => {
// },
// error => console.log(error) );
}
public share() {
let opts = new MatDialogConfig;
opts.data = {
prefix: 'o',
otherName: this.shareName
};
let dialog = this.dialog.open(SharePopupComponent, opts);
}
}

View File

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

View File

@ -1,19 +0,0 @@
<secondary-page-component [hideSideBarOnMobile]="true" >
<div mainContent class="mapWrapper">
<h2 *ngIf="!showVideo">{{message}}</h2>
<div class="video-container" *ngIf="showVideo && !yt">
<video [class.opacity-zero]="!showVideo" *ngIf="!error" style="width:100%" [src]="videoSrc" controls [poster]="poster" (error)="vidError()"></video>
</div>
<div *ngIf="showVideo && yt" class="video-container">
<iframe [src]="yt | safeUrl" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
<div style="margin-top: 10px">
<button routerLink="/video" style="margin-top:5px; width:100%;" mat-stroked-button>
<b><i ofbicon style="margin-top:-4px; vertical-align: middle;">play_arrow</i> Click here for previous video services</b>
</button>
</div>
</div>
<div sideBar ofbFadeInOnScroll>
</div>
</secondary-page-component>

View File

@ -1,25 +0,0 @@
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

@ -1,66 +0,0 @@
import { BibleVerseService } from './../../services/bible-verse.service';
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { HttpClient } from '@angular/common/http';
import { VideoServices } from '../home/video-services';
import { DateTime } from "luxon";
@Component({
selector: 'live-stream-component',
templateUrl: './live-stream.component.html',
styleUrls: ['./live-stream.component.css']
})
export class LiveStreamComponent implements OnInit {
public sermonVideo: string = 'https://ofbbutte.com/static/media/video/sermon.mp4';
public pleaseWait: string = 'https://ofbbutte.com/static/media/video/PleaseWait.jpg';
public clickToPlay: string = 'https://ofbbutte.com/static/media/video/ClickToPlay.jpg';
public message: string = "Please Wait...";
public isReady: boolean = false;
public videoSrc: string = this.sermonVideo;
public yt: string;
public poster: string = this.clickToPlay;
public error: boolean = false;
public showVideo: boolean = false;
constructor(private http: HttpClient) { }
private interval;
ngOnInit() {
this.update();
this.interval = setInterval(() => {
this.update();
}, 3000);
}
update() {
this.http.get<VideoServices>('assets/json/videoServices.json').subscribe(res => {
res.videos = res.videos.filter(v => v.archived === false);
res.videos.forEach(v => v.date = DateTime.fromISO(v.date, {zone: 'America/Denver'}));
res.videos.sort((a, b) => {
if (a.date < b.date) return -1;
if (a.date === b.date) return 0;
return 1;
});
var service = res.videos[0];
if (service) {
this.message = (<any>service).message;
if (service.isReady === true) {
this.showVideo = true;
this.videoSrc = '';
this.videoSrc = service.src;
this.yt = service.yt;
clearInterval(this.interval);
}
} else {
this.message = 'No Live Services';
}
});
}
}

View File

@ -1,58 +0,0 @@
.w-50 {
width: 50%;
}
.w-100 {
width: 100%;
}
.section-header{
font-size: 1.2em;
font-weight: bold;
border-bottom: 1px solid gray;
margin-bottom: 10px;
}
.error {
color: red;
}
mat-label {
font-weight: bold;
overflow-wrap: break-word;
}
label {
display: flex;
flex-direction: column;
font-size: 1.15rem;
margin-top: 35px;
color: black;
font-weight: 400;
font-family: Arial, Helvetica, sans-serif
}
ol > li {
margin-left: 20px;
}
mat-label {
font-size: 1.15rem;
color: black;
font-weight: 400;
}
label.sub {
margin-top: 0px;
font-size: .85rem;
}
mat-radio-button {
display: flex;
flex-direction: column;
margin: 15px 0;
}
.hidden {
display: none;
}

View File

@ -1,326 +0,0 @@
<secondary-page-component [hideSideBarOnMobile]="true" >
<div mainContent>
<p class="section-header">
Old Fashion Baptist Church Missionary Questionnaire
</p>
<p>
I hate questionnaires! I've been there. I understand that deputation itself is tough enough already without some pastor probing into all kinds of areas! Then there is the fact that so many fundamental pastors themselves disagree in so many areas!
<br><br>
Now that Ive said what you may have already been thinking, let me also say that I am continually amazed that every church doesnt use a questionnaire to vet their missionaries. The truth is, we take seriously the fact that you are being considered for support by our church and feel that we cant truly get to know you unless we ask some simple questions.
<br><br>
You must understand that anyone whom we consider as a missionary for our Church has certain doctrinal beliefs which are assumed by us or else we would not be sending them a questionnaire. We also realize that good men will differ on some things and will make allowances accordingly. Also, because we have one questionnaire for all candidates, many of the things that are asked would be unnecessary if it were not being sent to everyone. We hope you understand that. In order for a missionary to be considered, we request that every question be answered.
<br><br>
Thank you for your time and understanding. The questions are not meant in any way to be “trick” questions.
<br><br>
God bless you!
<br><br>
Pastor Derek Loewen
</p>
<br><br>
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<mat-form-field class="w-50" [class.background-error]="hasErrors('name')">
<mat-label>Name</mat-label>
<input matInput type="text" formControlName="name" required>
</mat-form-field>
<mat-form-field class="w-50">
<mat-label>Wifes Name</mat-label>
<input matInput type="text" formControlName="wifesName" >
</mat-form-field>
<mat-form-field class="w-100">
<mat-label>Home Phone</mat-label>
<input matInput type="tel" formControlName="homePhone" >
</mat-form-field>
<mat-form-field class="w-100">
<mat-label>Cell Phone</mat-label>
<input matInput type="tel" formControlName="cellPhone" >
</mat-form-field>
<mat-form-field class="w-100">
<mat-label>Field Phone</mat-label>
<input matInput type="tel" formControlName="fieldPhone" >
</mat-form-field>
<mat-form-field class="w-100">
<mat-label>Number of Children</mat-label>
<input matInput type="number" formControlName="numberOfChildren" (keyup)="numberOfChildrenChange($event.target.value)" required >
</mat-form-field>
<div *ngIf="form.get('numberOfChildren').value > 0">
<label id="childrenNamesLabel" >Names of Children</label>
<ol>
<li formArrayName="children" *ngFor="let child of form.get('children').controls; let i = index;">
<div [formGroupName]="i">
<mat-form-field floatLabel="never" class="w-100">
<mat-label>Childs Name</mat-label>
<input matInput type="text" formControlName="name" >
</mat-form-field>
</div>
</li>
</ol>
</div>
<label id="testimonyLabel">Please give your testimony</label>
<mat-form-field class="w-100" floatLabel="never">
<textarea matInput type="text" placeholder="Your Answer" formControlName="testimony" aria-labelledby="testimonyLabel" required></textarea>
</mat-form-field>
<label id="callToFieldLabel">Please explain specifically your call to the field.</label>
<mat-form-field class="w-100" floatLabel="never">
<textarea matInput type="text" placeholder="Your Answer" formControlName="callToField" required></textarea>
</mat-form-field>
<label id="sendingChurchLabel">Sending Church or Missions Board:</label>
<mat-form-field class="w-100" floatLabel="never">
<input matInput type="text" placeholder="Your Answer" formControlName="sendingChurch" required>
</mat-form-field>
<label id="fieldOfServiceLabel">What is your planned field of Service?</label>
<label class="sub">Country and City</label>
<mat-form-field class="w-100" floatLabel="never">
<input matInput type="text" placeholder="Your Answer" formControlName="fieldOfService" required>
</mat-form-field>
<label id="plansLabel">What do your plans include?</label>
<label class="sub">(Starting a church, continuing a church, starting a school, evangelizing the area...)</label>
<mat-form-field class="w-100" floatLabel="never">
<textarea matInput type="text" placeholder="Your Answer" formControlName="plans" required></textarea>
</mat-form-field>
<label id="evaluationOfNationalsLabel">What is your evaluation of the nationals you are trying to reach, spiritually and culturally?</label>
<mat-form-field class="w-100" floatLabel="never">
<textarea matInput type="text" placeholder="Your Answer" formControlName="evaluationOfNationals" required></textarea>
</mat-form-field>
<label id="timeInCountryLabel">How long have you been in this country?</label>
<label class="sub">If you have changed countries, what other countries have you been in and for how long?</label>
<mat-form-field class="w-100" floatLabel="never">
<input matInput type="text" placeholder="Your Answer" formControlName="timeInCountry" required>
</mat-form-field>
<label id="correctWrongOfAnotherMissionaryLabel">If you knew that a fellow missionary was doing wrong or something quesstionable, what would be your course of action?</label>
<mat-form-field class="w-100" floatLabel="never">
<textarea matInput type="text" placeholder="Your Answer" formControlName="correctWrongOfAnotherMissionary" required></textarea>
</mat-form-field>
<label id="financialStatementPrevYearLabel">Would you submit a general financial statement for the past year?</label>
<mat-form-field class="w-100" floatLabel="never">
<textarea matInput type="text" placeholder="Your Answer" formControlName="financialStatementPrevYear" required></textarea>
</mat-form-field>
<label id="currentMonthlySupportLabel">What is your total monthly support (peronal, work fund, etc)?</label>
<mat-form-field class="w-100" floatLabel="never">
<input matInput type="text" placeholder="Your Answer" formControlName="currentMonthlySupport" required>
</mat-form-field>
<label id="monthlySupportNeededLabel">How much monthly support do you calculate you will need?</label>
<label class="sub">(We know that there will be differences)</label>
<mat-form-field class="w-100" floatLabel="never">
<input matInput type="text" placeholder="Your Answer" formControlName="monthlySupportNeeded" required>
</mat-form-field>
<label id="restAndRelaxationLabel">Are you diligent to have "Rest and Relaxation" during your stay on the field? Do you have a set time and plan for such necessary refreshing?</label>
<mat-form-field class="w-100" floatLabel="never">
<textarea matInput type="text" placeholder="Your Answer" formControlName="restAndRelaxation" required></textarea>
</mat-form-field>
<label id="aloneOrTeamLabel">Do you plan to work alone or as a team? What are your feelings about the team concept?</label>
<mat-form-field class="w-100" floatLabel="never">
<textarea matInput type="text" placeholder="Your Answer" formControlName="aloneOrTeam" required></textarea>
</mat-form-field>
<label id="childrenSchoolLabel">Do your children:</label>
<label class="sub">Please mark even if your children are yet to be born.</label>
<mat-radio-group aria-label="Type of School" formControlName="childrenSchool" aria-labelledby="childrenSchoolLabel">
<mat-radio-button class="radio-button" value="1">Attend a Christian School</mat-radio-button>
<mat-radio-button class="radio-button" value="2">Attend a Public School</mat-radio-button>
<mat-radio-button class="radio-button" value="3">Home School</mat-radio-button>
<mat-radio-button class="radio-button" value="4">Other</mat-radio-button>
</mat-radio-group>
<label id="danceLabel">Do you or any of your family ever dance?</label>
<mat-radio-group aria-label="Dance" formControlName="dance" class="w-100">
<mat-radio-button value="true">Yes</mat-radio-button>
<mat-radio-button value="false">No</mat-radio-button>
</mat-radio-group>
<label id="worldlyMusicLabel">Do you or any of your family ever listen to worldly music in your home?</label>
<label class="sub">(Including but not limited to: rock, country/western, r&b, etc.)</label>
<mat-radio-group aria-label="Worldy Music" formControlName="worldlyMusic" class="w-100">
<mat-radio-button value="true">Yes</mat-radio-button>
<mat-radio-button value="false">No</mat-radio-button>
</mat-radio-group>
<label id="movieTheatersLabel">Do you or any of your family ever attend public movie theaters?</label>
<mat-radio-group aria-label="Movie Theaters" formControlName="movieTheaters" class="w-100">
<mat-radio-button value="true">Yes</mat-radio-button>
<mat-radio-button value="false">No</mat-radio-button>
</mat-radio-group>
<label id="alcoholLabel">Do you or any of your family ever use any type of alcoholic beverage?</label>
<mat-radio-group aria-label="Alcohol" formControlName="alcohol" class="w-100">
<mat-radio-button value="true">Yes</mat-radio-button>
<mat-radio-button value="false">No</mat-radio-button>
</mat-radio-group>
<label id="smokingLabel">Do you or any of your family ever engage in any unclean habit such as smoking?</label>
<mat-radio-group aria-label="Smoking" formControlName="smoking" class="w-100">
<mat-radio-button value="true">Yes</mat-radio-button>
<mat-radio-button value="false">No</mat-radio-button>
</mat-radio-group>
<label id="maleHairLabel">If there are boys in your home, do they follow the same hair standard you follow?</label>
<mat-radio-group aria-label="Male Hair" formControlName="maleHair" class="w-100">
<mat-radio-button value="true">Yes</mat-radio-button>
<mat-radio-button value="false">No</mat-radio-button>
</mat-radio-group>
<label id="femalSlacksLabel">Does your wife wear slacks in public?</label>
<mat-radio-group aria-label="Female Slacks" formControlName="femaleSlacks" class="w-100">
<mat-radio-button value="1">Rarely</mat-radio-button>
<mat-radio-button value="2">Often</mat-radio-button>
<mat-radio-button value="3">On Sports Activities</mat-radio-button>
<mat-radio-button value="4">Never</mat-radio-button>
</mat-radio-group>
<label id="femaleShortsLabel">Does your wife wear shorts in public?</label>
<mat-radio-group aria-label="Female Shorts" formControlName="femaleShorts" class="w-100">
<mat-radio-button value="1">Rarely</mat-radio-button>
<mat-radio-button value="2">Often</mat-radio-button>
<mat-radio-button value="3">On Sports Activities</mat-radio-button>
<mat-radio-button value="4">Never</mat-radio-button>
</mat-radio-group>
<label id="femaleDressStandardLabel">Do the girls in your family follow the same dress standard your wife does?</label>
<mat-radio-group aria-label="Female Dress Standard" formControlName="femaleDressStandard" class="w-100">
<mat-radio-button value="true">Yes</mat-radio-button>
<mat-radio-button value="false">No</mat-radio-button>
</mat-radio-group>
<label id="swimmingClothingLabel">What do you do for clothing when you go swimming?</label>
<mat-form-field class="w-100" floatLabel="never">
<textarea matInput type="text" placeholder="Your Answer" formControlName="swimmingClothing" required></textarea>
</mat-form-field>
<label id="televisionLabel">How do you feel about having a television in the home?</label>
<mat-form-field class="w-100" floatLabel="never">
<textarea matInput type="text" placeholder="Your Answer" formControlName="television" required></textarea>
</mat-form-field>
<label id="dailyBibleLabel">Do you MAKE time daily for Bible Reading and Prayer?</label>
<mat-radio-group aria-labeled-by="dailyBibleLabel" formControlName="dailyBible" class="w-100">
<mat-radio-button value="1">Always</mat-radio-button>
<mat-radio-button value="2">Sometimes</mat-radio-button>
<mat-radio-button value="3">Rarely</mat-radio-button>
</mat-radio-group>
<label id="numberLedToChrist">Outside of the church services where you have ministered, estimate how many people you have personally won to Christ in the last six months.</label>
<mat-form-field class="w-100" floatLabel="never">
<input matInput type="number" placeholder="Your Answer" formControlName="numberLedToChrist" required>
</mat-form-field>
<label id="numberWitnessedToLabel">How many people have you personally witnessed to?</label>
<mat-form-field class="w-100" floatLabel="never">
<input matInput type="number" placeholder="Your Answer" formControlName="numberWitnessedTo" required>
</mat-form-field>
<label id="numberWeeklyTractsLabel">On average, how many tracts do you pass out in a week?</label>
<mat-form-field class="w-100" floatLabel="never">
<input matInput type="number" placeholder="Your Answer" formControlName="numberWeeklyTracts" required>
</mat-form-field>
<label id="rateOfSuccessLabel">What is your rate of success in fulfilling the great commission, getting your converts baptized and active in the local church where they may be taught?</label>
<mat-form-field class="w-100" floatLabel="never">
<textarea matInput type="text" placeholder="Your Answer" formControlName="rateOfSuccess" required></textarea>
</mat-form-field>
<label id="predestinationLabel">Explain your position briefly concerning predestination and election.</label>
<mat-form-field class="w-100" floatLabel="never">
<textarea matInput type="text" placeholder="Your Answer" formControlName="predestination" required></textarea>
</mat-form-field>
<label id="fellowshipAssociationLabel">Do you claim identity with any group or fellowship such as BBF, GARB, FBF, Other?</label>
<mat-form-field class="w-100" floatLabel="never">
<textarea matInput type="text" placeholder="Your Answer" formControlName="fellowshipAssociation" required></textarea>
</mat-form-field>
<label id="collegeRecommendationsLabel">To a young person asking you to recommend a Christian College, list two or three Christian Colleges, in order of preference, which you would recommend?</label>
<label class="sub">Please list the name, city, and state for each</label>
<div *ngIf="form.get('collegeRecommendations').errors?.minColleges && (form.touched || form.dirty)" class="error">
{{form.get('collegeRecommendations').errors?.minColleges}}
</div>
<ol>
<li formArrayName="collegeRecommendations" *ngFor="let college of collegeRecommendationFormArray().controls; let i = index;">
<div [formGroupName]="i">
<mat-form-field floatLabel="never" class="w-100">
<mat-label>Name</mat-label>
<input matInput type="text" formControlName="name">
</mat-form-field>
<mat-form-field floatLabel="never" class="w-50">
<mat-label>City</mat-label>
<input matInput type="text" formControlName="city">
</mat-form-field>
<mat-form-field floatLabel="never" class="w-50">
<mat-label>State</mat-label>
<input matInput type="text" formControlName="state">
</mat-form-field>
</div>
<div *ngIf="college.errors?.college && (form.touched || form.dirty)" class="error">
{{college.errors?.college}}
</div>
</li>
</ol>
<label id="admittedWrongLabel">When was the last time you admitted you were wrong about something and apologized?</label>
<mat-form-field class="w-100" floatLabel="never">
<textarea matInput type="text" placeholder="Your Answer" formControlName="admittedWrong" required></textarea>
</mat-form-field>
<label id="divorcedLabel">Have you or your wife ever been divorced?</label>
<mat-radio-group formControlName="divorced" class="w-100">
<mat-radio-button value="true">Yes</mat-radio-button>
<mat-radio-button value="false">No</mat-radio-button>
</mat-radio-group>
<label id="groundsForRemarryLabel">Do you believe there are grounds whereby a man or women may remarry with a previous spouse still living?</label>
<mat-radio-group aria-label="Grounds for Remarry" formControlName="groundsForRemarry" class="w-100">
<mat-radio-button value="true">Yes</mat-radio-button>
<mat-radio-button value="false">No</mat-radio-button>
</mat-radio-group>
<label id="marryADivorceeLabel">Have you married a divorced couple or would you?</label>
<mat-radio-group aria-label="Married a Divorcee" formControlName="marryADivorcee" class="w-100">
<mat-radio-button value="true">Yes</mat-radio-button>
<mat-radio-button value="false">No</mat-radio-button>
</mat-radio-group>
<label id="masonicLodge">Do you believe that being a member of a masonic lodge conflicts with Biblical separation?</label>
<mat-radio-group aria-label="Masonic Lodge" formControlName="masonicLodge" class="w-100">
<mat-radio-button value="true">Yes</mat-radio-button>
<mat-radio-button value="false">No</mat-radio-button>
</mat-radio-group>
<label id="bibleVersionsUsedLabel">Please list the English version(s) of the Bible you use and approve for preaching and teaching.</label>
<mat-form-field class="w-100" floatLabel="never">
<textarea matInput type="text" placeholder="Your Answer" formControlName="bibleVersionsUsed" required></textarea>
</mat-form-field>
<label id="bibleVersionOpinionLabel">Please give your opinion of all English versions of the Bible you use and approve for preaching and teaching.</label>
<mat-form-field class="w-100" floatLabel="never">
<textarea matInput type="text" placeholder="Your Answer" formControlName="bibleVersionOpinion" required></textarea>
</mat-form-field>
<label id="contemporaryMusicLabel">Do you listen to or approve of either "Contemporary Christian Music" or "Gospel rock" music?</label>
<mat-radio-group formControlName="contemporaryMusic" class="w-100">
<mat-radio-button value="true">Yes</mat-radio-button>
<mat-radio-button value="false">No</mat-radio-button>
</mat-radio-group>
<label id="charasmaticismLabel">What is your position in relation to the modern day Charismatic movement?</label>
<mat-form-field class="w-100" floatLabel="never">
<textarea matInput type="text" placeholder="Your Answer" formControlName="charasmaticism" required></textarea>
</mat-form-field>
<label id="tonguesLabel">Do you or any member of your family speak in tongues?</label>
<mat-radio-group formControlName="tongues" class="w-100">
<mat-radio-button value="true">Yes</mat-radio-button>
<mat-radio-button value="false">No</mat-radio-button>
</mat-radio-group>
<label id="repentanceNecessaryLabel">Is Repentance a necessary part of salvation?</label>
<mat-radio-group formControlName="repentanceNecessary" class="w-100">
<mat-radio-button value="true">Yes</mat-radio-button>
<mat-radio-button value="false">No</mat-radio-button>
</mat-radio-group>
<label id="repentanceDefinitionLabel">One definition of repentance is: "Repentance means changing your mind about whatever is keeping you from turning to Jesus."</label>
<label class="sub">Do you agree or disagree? Explain your answer.</label>
<mat-form-field class="w-100" floatLabel="never">
<textarea matInput type="text" placeholder="Your Answer" formControlName="repentanceDefinition" required ></textarea>
</mat-form-field>
<label id="fundamentalistLabel">Do you consider yourself a fundamentalist?</label>
<mat-radio-group formControlName="fundamentalist" class="w-100">
<mat-radio-button value="true">Yes</mat-radio-button>
<mat-radio-button value="false">No</mat-radio-button>
</mat-radio-group>
<label id="billsOnTimeLabel">Do you believe it is important to pay your bills on time?</label>
<mat-radio-group formControlName="billsOnTime" class="w-100">
<mat-radio-button value="true">Yes</mat-radio-button>
<mat-radio-button value="false">No</mat-radio-button>
</mat-radio-group>
<label id="lateBillsLabel">How many times in the last 12 months have you been late paying a bill?</label>
<mat-form-field class="w-100" floatLabel="never">
<textarea matInput type="text" placeholder="Your Answer" formControlName="lateBills" required></textarea>
</mat-form-field>
<label id="lateBillActionTakenLabel">What do you do to "make things right" when you are late paying a bill?</label>
<mat-form-field class="w-100" floatLabel="never">
<textarea matInput type="text" placeholder="Your Answer" formControlName="lateBillActionTaken" required></textarea>
</mat-form-field>
<label id="potentialHarvestLabel">Though we support Missions and Missionaries doing many things and serving on many fields, we look primarily for Missionaries going to the ripe Harvest fields to begin Churches which will eventually become indigenous Churches. Please evaluate for us the potential of the Harvest field to which you have been called by telling the response of the people at large to Tract or Bible Distribution, Door-to-Door Visitation, and Gospel Preaching.</label>
<mat-form-field class="w-100" floatLabel="never">
<textarea matInput type="text" placeholder="Your Answer" formControlName="potentialHarvest" required></textarea>
</mat-form-field>
<mat-form-field class="w-100 hidden" floatLabel="never">
<textarea matInput type="text" placeholder="Your Answer" formControlName="honeyPot" required></textarea>
</mat-form-field>
<button mat-raised-button type="submit" [disabled]="!form.valid || submitButtonDisabled">{{submitButtonText}}</button>
<br>
<p *ngIf="!form.valid">Please complete all fields to submit</p>
</form>
</div>
<div sideBar class="side-bar">
</div>
</secondary-page-component>

View File

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

View File

@ -1,184 +0,0 @@
import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators, FormArray, FormControl, ValidatorFn, ValidationErrors } from '@angular/forms';
import { MissionarySupportService } from 'src/app/services/missionary-support-service';
import { MatDialog, MatDialogConfig } from '@angular/material';
import { OkPopupComponent } from '../popups/ok-popup/ok-popup.component';
@Component({
selector: 'app-missionary-form-page',
templateUrl: './missionary-form-page.component.html',
styleUrls: ['./missionary-form-page.component.css']
})
export class MissionaryFormPageComponent implements OnInit {
form: FormGroup;
submitButtonText: string = 'Submit';
submitButtonDisabled: boolean = false;
errorMessages: string[] = [];
private maxNumberOfChildren: number = 30;
constructor(private formBuilder: FormBuilder, private matDialog: MatDialog, private missionarySupportService: MissionarySupportService) {
this.setupForm();
}
ngOnInit() {
}
setupForm() {
this.form = this.formBuilder.group({
name: ['', [Validators.required]],
homePhone: [''],
cellPhone: [''],
fieldPhone: [''],
wifesName: [''],
numberOfChildren: ['', [Validators.required, Validators.max(this.maxNumberOfChildren)]],
children: this.formBuilder.array([]),
testimony: ['', Validators.required],
callToField: ['', Validators.required],
sendingChurch: ['', Validators.required],
fieldOfService: ['', Validators.required], //Country + City
plans: ['', Validators.required],
evaluationOfNationals: ['', Validators.required],
timeInCountry: ['', Validators.required],
correctWrongOfAnotherMissionary: ['', Validators.required],
financialStatementPrevYear: [undefined, Validators.required],
currentMonthlySupport: ['', Validators.required],
monthlySupportNeeded: ['', Validators.required],
restAndRelaxation: ['', Validators.required],
aloneOrTeam: ['', Validators.required],
childrenSchool: [undefined, Validators.required],
dance: ['', Validators.required],
worldlyMusic: [undefined, Validators.required],
movieTheaters: [undefined, Validators.required],
alcohol: [undefined, Validators.required],
smoking: [undefined, Validators.required],
maleHair: [undefined, Validators.required],
femaleSlacks: [undefined, Validators.required],
femaleShorts: [undefined, Validators.required],
femaleDressStandard: [undefined, Validators.required],
swimmingClothing: [undefined, Validators.required],
television: [undefined, Validators.required],
dailyBible: [undefined, Validators.required],
numberLedToChrist: ['', [Validators.required, Validators.min(0), Validators.max(10000)]],
numberWitnessedTo: ['', [Validators.required, Validators.min(0), Validators.max(10000)]],
numberWeeklyTracts: ['', [Validators.required, Validators.min(0), Validators.max(10000)]],
rateOfSuccess: ['', Validators.required],
predestination: ['', Validators.required],
fellowshipAssociation: ['', Validators.required],
collegeRecommendations: this.formBuilder.array([this.createCollegeRecommendation(),this.createCollegeRecommendation(),this.createCollegeRecommendation()], this.minCollegeValidator),
admittedWrong: ['', Validators.required],
divorced: [undefined, Validators.required],
groundsForRemarry: [undefined, Validators.required],
marryADivorcee: [undefined, Validators.required],
masonicLodge: [undefined, Validators.required],
bibleVersionsUsed: ['', Validators.required],
bibleVersionOpinion: ['', Validators.required],
contemporaryMusic: ['', Validators.required],
charasmaticism: ['', Validators.required],
tongues: [undefined, Validators.required],
repentanceNecessary: [undefined, Validators.required],
repentanceDefinition: [undefined, Validators.required],
fundamentalist: [undefined, Validators.required],
billsOnTime: [undefined, Validators.required],
lateBills: ['', Validators.required],
lateBillActionTaken: ['', Validators.required],
potentialHarvest: ['', Validators.required],
honeyPot: ['.', Validators.required]
});
}
collegeRecommendationFormArray(): FormArray {
return this.form.get('collegeRecommendations') as FormArray;
}
addChildToForm() {
const children = this.form.get('children') as FormArray;
children.push(this.formBuilder.group({
name: ['', Validators.required]
}));
}
createCollegeRecommendation(): FormGroup {
return this.formBuilder.group({
name: [''],
city: [''],
state: ['']
}, { validators: [this.collegeValidator]});
}
numberOfChildrenChange(number: Number) {
let num = +number;
num = num > this.maxNumberOfChildren ? this.maxNumberOfChildren : num;
const children = this.form.get('children') as FormArray;
while (children.length > num) {
children.removeAt(children.length - 1);
}
while (children.length < num) {
children.push(this.formBuilder.group({
name: ['', Validators.required]
}));
}
}
hasErrors(formControlName: string): boolean {
let res = this.form.get(formControlName) && typeof this.form.get(formControlName).errors !== 'undefined';
if (res === true) {
res = this.form.get(formControlName).dirty || (this.form.get(formControlName).touched && this.form.get(formControlName).valid === false);
}
return res;
}
onSubmit(){
this.errorMessages = [];
if (this.errorMessages.length > 0){ return; }
this.submitButtonText = "Please Wait...";
this.submitButtonDisabled = true;
this.missionarySupportService.create(this.form.value)
.subscribe(
success => {this.emailSuccess();},
error => {this.emailError();});
}
private emailSuccess(){
let opts = new MatDialogConfig;
opts.data = { title:'Missionary Support','message':'Thank You! Your submission has been received.' };
let popup = this.matDialog.open(OkPopupComponent,opts);
popup.afterClosed().subscribe(()=>{
this.submitButtonText = "Form Submitted"
});
}
private emailError(){
console.error("error");
let opts = new MatDialogConfig;
opts.data = { title:'Error','message':'Please make sure that you have entered all fields correctly.' };
let popup = this.matDialog.open(OkPopupComponent,opts);
this.submitButtonText = "Submit";
this.submitButtonDisabled = false;
}
private minCollegeValidator(control: FormArray): ValidationErrors | null {
const minRequired = 2;
let valid = 0;
for(let i = 0; i < control.controls.length; i++) {
const val = control.controls[i].value;
if (val.name && val.city && val.state && val.name.length > 0 && val.city.length > 0 && val.state.length > 0) {
valid++;
}
}
return valid >= minRequired ? null : { 'minColleges': 'Please enter at least two colleges.' };
}
private collegeValidator(control: FormGroup): ValidationErrors | null {
const name = control.value.name || '';
const city = control.value.city || '';
const state = control.value.state || '';
if (name.length > 0 || city.length > 0 || state.length > 0) {
if (name.length === 0 || city.length === 0 || state.length === 0) {
return { 'college': 'Please enter name, city and state for each college.' };
}
}
return null;
}
}

View File

@ -88,8 +88,7 @@ export class AddSermonPopupComponent implements OnInit {
if (this.sermonFile == null){
this.errorMessages.push("Please add a sermon MP3 file");
}
if (this.sermonFile != null && this.sermonFile.type != 'audio/mpeg'){
if (this.sermonFile != null && this.sermonFile.type != 'audio/mp3'){
this.errorMessages.push("File must be a MP3");
}
if (this.errorMessages.length > 0){ this.updateAddButton(true); return; }

View File

@ -1,7 +1,3 @@
.full-width {
width: 100%;
}
.m-5 {
margin: 5px;
}

View File

@ -31,7 +31,7 @@
{{error}}
</p>
</div>
<button mat-raised-button class="first m-5" (click)="cancel($event)" >Cancel</button><!--
--><button mat-raised-button class="m-5" type="submit" [disabled]="!addUserForm.form.valid || addUserButtonDisabled">{{ addUserButtonText }}</button>
<button mat-raised-button class="first" (click)="cancel($event)" >Cancel</button><!--
--><button mat-raised-button type="submit" [disabled]="!addUserForm.form.valid || addUserButtonDisabled">{{ addUserButtonText }}</button>
</form>
</div>

View File

@ -30,12 +30,6 @@ export class SharePopupComponent implements OnInit {
this.id = data.id;
let port = this.document.location.port ? ":"+this.document.location.port : "";
this.shareUrl = this.document.location.protocol +'//'+ this.document.location.hostname + port + this.shareBaseUrl + data.prefix + this.id;
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;
}

View File

@ -1,26 +0,0 @@
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;
}

View File

@ -1,10 +0,0 @@
<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>

View File

@ -1,25 +0,0 @@
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();
});
});

View File

@ -1,26 +0,0 @@
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();
}
}

View File

@ -8,7 +8,7 @@
<div class="description">{{ description }}</div><!--
--><div class="action-buttons">
<button mat-button class="action pct40" (click)="play()" ><i ofbicon>headset</i> Listen</button><!--
--><a download="{{title}}" href="{{url}}" mat-button class="action pct50" ><i ofbicon>file_download</i> Download</a><!--
--><button mat-button class="action pct50" (click)="download()" ><i ofbicon>file_download</i> Download</button><!--
--><button mat-button class="action pct10" (click)="share()" ><i ofbicon>share</i> Share</button>
</div><!--
--><div class="action-buttons" *ngIf="loggedIn">

View File

@ -1,92 +0,0 @@
.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%;
}

View File

@ -1,26 +0,0 @@
<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>

View File

@ -1,25 +0,0 @@
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();
});
});

View File

@ -1,88 +0,0 @@
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);
}
}

View File

@ -1,13 +0,0 @@
.yt-container {
position: relative;
padding-bottom: 56.25%; /* 16:9 */
height: 0;
}
.yt-container iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}

View File

@ -1,17 +0,0 @@
<secondary-page-component [hideSideBarOnMobile]="true" >
<div mainContent>
<div *ngFor="let video of services; let i = index;" style="margin-top: 10px;">
<button (click)="showVideo(i)" mat-stroked-button style="margin-bottom: 10px;">
<i ofbicon class="mr-10" >live_tv</i>
{{getTitle(i)}}
</button>
<div *ngIf="video.show && video.yt" class="yt-container">
<iframe [src]="video.yt | safeUrl" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div>
<video style="width:100%" *ngIf="video.show && !video.yt" src="{{video.src}}" controls poster="https://ofbbutte.com/static/media/video/ClickToPlay.jpg"></video>
</div>
</div>
<div sideBar class="side-bar">
</div>
</secondary-page-component>

View File

@ -1,41 +0,0 @@
import { WindowRefService } from './../../services/window-ref.service';
import { Component, HostListener, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { VideoServices, VideoService } from '../home/video-services';
import { DateTime } from "luxon";
@Component({
selector: 'video-services-component',
templateUrl: './video-services.component.html',
styleUrls: ['./video-services.component.css'],
})
export class VideoServicesComponent implements OnInit {
public loading: boolean = true;
public services: VideoService[];
constructor(private http: HttpClient){ }
ngOnInit(){
this.http.get<VideoServices>('assets/json/videoServices.json')
.subscribe(res => {
this.services = res.videos.filter(v => v.isReady === true);
this.loading = false;
});
}
showVideo(index: number) {
this.services.forEach(s => {
(<any>s).show = false;
});
(<any>this.services[index]).show = true;
}
getTitle(index: number): string {
const title = this.services[index].title;
const dte = DateTime.fromISO(this.services[index].date, {zone: 'America/Denver'})
return title + ' | ' + dte.toLocaleString(DateTime.DATETIME_MED);
}
}

View File

@ -1,13 +0,0 @@
.side-bar{
position: fixed;
}
.width100{
width: 100%;
}
#showAllButton{
margin-top: 10px;
}

View File

@ -1,12 +0,0 @@
<secondary-page-component [hideSideBarOnMobile]="true" >
<div mainContent>
<app-youtube-list></app-youtube-list>
</div>
<div sideBar class="side-bar">
</div>
</secondary-page-component>

View File

@ -1,25 +0,0 @@
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();
});
});

View File

@ -1,15 +0,0 @@
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() {
}
}

View File

@ -91,6 +91,6 @@ p.margin-bottom {
@media(max-width: 450px) {
.float-left {
width: 200px;
width: 175px
}
}

View File

@ -17,10 +17,9 @@
<img class="image shadow container-3-col" src="assets/images/home-images/tiny/church.jpg" alt="Church Image" />
</div>
<br><br>
<p ofbFadeInOnScroll class="section-header">Pastor Derek Loewen</p>
<div ofbFadeInOnScroll class="section-paragraph overflow-hidden">
<img class="float-left margin-right-10 border-radius-5" src="assets/images/tiny/pstr3.jpg" alt="Pastor Photo" width="350px" />
<img class="float-left margin-right-10 border-radius-5" src="assets/images/tiny/pstr.jpg" alt="Pastor Photo" width="225px" />
<p class="margin-bottom">
Pastor Derek Loewen heard the gospel for the first time when a friend invited him to
Florence Baptist Church in Florence, Montana. They rode the bus to Sunday School.
@ -30,10 +29,10 @@
</p>
<p class="margin-bottom">
During his senior year of high school, Pastor Loewen yielded his life to the Lord.
Upon graduation from Bible College in 2003, he served in the church he
Upon graduation from Crown College of the Bible in 2003, he served in the church he
was saved in as a young boy before marrying his bride, Rebecca in June 2004.
The Lord has graciously allowed them to serve Him together across the country both
assisting pastors and planting a church. God has blessed their home with 5 delightful
assisting pastors and planting a church. God has blessed their home with 3 delightful
children.
</p>
<p>

View File

@ -1,39 +0,0 @@
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;
}
}

View File

@ -1,24 +0,0 @@
.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;
}

View File

@ -1,22 +0,0 @@
<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>

View File

@ -1,25 +0,0 @@
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();
});
});

View File

@ -1,58 +0,0 @@
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]);
}
}
}
}

View File

@ -1,48 +0,0 @@
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;
}

View File

@ -4,17 +4,15 @@ export const EVENTS_ADD_URL = environment.baseUrl + "/api2/events/a/";
export const EVENT_BY_ID = environment.baseUrl + "/api2/events/";
export const EVENTS_BY_PAGE_URL = environment.baseUrl + "/api2/events/page/";
export const EVENTS_DELETE_BY_ID_URL = environment.baseUrl + "/api2/events/a/";
export const MISSIONARY_SUPPORT_CREATE_URL = environment.baseApi + "/missionary";
export const SERMONS_BY_ID = environment.baseUrl + '/api2/sermons/';
export const SERMONS_BY_PAGE_URL = environment.baseUrl + '/api2/sermons/page/';
export const SERMONS_BY_SEARCH_URL = environment.baseUrl + '/api2/sermons/search';
export const SERMON_MP3_BASE_URL = '/media/';
export const SERMON_MP3_BASE_URL = '//ofbbutte.com/static/media/';
export const SERMON_ADD_URL = environment.baseUrl + "/api2/sermons/a/";
export const SERMON_DELETE_URL = environment.baseUrl + "/api2/sermons/a/";
export const SERMON_UPDATE_URL = environment.baseUrl + "/api2/sermons/a/";
export const SERMON_DOWNLOAD_URL = environment.baseUrl + "/api2/sermons/download/";
export const TRANSACTION_CREATE_URL = environment.baseUrl + "/api2/transactions/a/";
export const TRANSACTION_GET_BY_YEAR_URL = environment.baseUrl + "/api2/transactions/a/";
export const USER_CREATE_URL = environment.baseUrl + "/api2/users/a/";
export const USER_GET_ALL_URL = environment.baseUrl + "/api2/users/a";
export const LOGIN_URL = environment.baseUrl + '/api2/login';

View File

@ -1,7 +1,6 @@
export const ICONS = {
access_time: '&#xE192;',
add: '&#xE145;',
announcement: '&#xE85A;',
close: '&#xE5CD;',
copyright: '&#xE90C;',
delete_forever: '&#xE92B;',

View File

@ -10,9 +10,6 @@ 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();

View File

@ -1,41 +0,0 @@
import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { throwError } from 'rxjs';
import { catchError, tap } from 'rxjs/operators';
import { MISSIONARY_SUPPORT_CREATE_URL } from '../constants/urls';
@Injectable()
export class MissionarySupportService {
private options: {};
constructor(private httpClient: HttpClient){
this.options = {
withCredentials: true
};
}
create(body: any) {
console.log(body);
return this.httpClient.post(MISSIONARY_SUPPORT_CREATE_URL, body, this.options)
.pipe(tap(res => console.log(res)), catchError(this.handleError));
}
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', error.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${error.error}`);
console.error(error);
}
// return an observable with a user-facing error message
return throwError((error && error.error && error.error.message) ? error.error.message :
'Something bad happened; please try again later.');
};
}

View File

@ -1,15 +0,0 @@
import { Injectable } from '@angular/core';
@Injectable()
export class PrintService {
public isPrinting: boolean = false;
constructor(){}
public setPrinting(printing: boolean) {
this.isPrinting = printing;
}
}

View File

@ -4,7 +4,7 @@ import { HttpClient, HttpErrorResponse } from '@angular/common/http';
import { Observable, Subject, throwError, of } from 'rxjs';
import { catchError, map, tap, first } from 'rxjs/operators';
import { TRANSACTION_CREATE_URL, TRANSACTION_GET_BY_YEAR_URL } from '../constants/urls';
import { TRANSACTION_CREATE_URL } from '../constants/urls';
import { Transaction } from '../components/add-transaction-page/transaction';
@Injectable()
@ -41,11 +41,6 @@ export class TransactionService {
.pipe(tap(res => console.log(res)), catchError(this.handleError));
}
getByYear(taxYear: number) {
return this.httpClient.get(TRANSACTION_GET_BY_YEAR_URL + "?taxYear=" + taxYear, this.options)
.pipe(catchError(this.handleError));
}
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.

View File

@ -19,7 +19,7 @@ export class UserService {
getAll(){
return this.httpClient.get(USER_GET_ALL_URL, this.options)
.pipe(catchError(this.handleError));
.pipe(tap(res => console.log(res)), catchError(this.handleError));
}
create(firstName: string, lastName: string, street: string, city: string, state: string, zip: string, country: string) {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Some files were not shown because too many files have changed in this diff Show More