Migrate some apps to components
Using dynamic loading to take advantage of routerLink instead of anchor links
This commit is contained in:
parent
7654dfa0dd
commit
e0af5d19b2
@ -1,7 +1,7 @@
|
|||||||
import { NgModule } from '@angular/core'
|
import { NgModule } from '@angular/core'
|
||||||
import { Routes, RouterModule } from '@angular/router'
|
import { Routes, RouterModule } from '@angular/router'
|
||||||
|
|
||||||
import { ApplicationComponent } from './applications/application/application.component'
|
import { ApplicationComponent } from './applications/application.component'
|
||||||
import { ApplicationListComponent } from './applications/application-list/application-list.component'
|
import { ApplicationListComponent } from './applications/application-list/application-list.component'
|
||||||
import { HomeComponent } from './pages/home/home.component'
|
import { HomeComponent } from './pages/home/home.component'
|
||||||
import { InformationPublicizingComponent } from './pages/about/information-publicizing.component'
|
import { InformationPublicizingComponent } from './pages/about/information-publicizing.component'
|
||||||
|
|||||||
@ -0,0 +1,13 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-all-solutions-link',
|
||||||
|
template: `<p><br><a routerLink="/solutions">« Back to All Solutions</a></p>`
|
||||||
|
})
|
||||||
|
export class AllSolutionsLinkComponent implements OnInit {
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit() { }
|
||||||
|
|
||||||
|
}
|
||||||
6
bit-badger-solutions/src/app/applications/app-item.ts
Normal file
6
bit-badger-solutions/src/app/applications/app-item.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
import { Type } from '@angular/core'
|
||||||
|
|
||||||
|
/** An item representing an app */
|
||||||
|
export class AppItem {
|
||||||
|
constructor(public name: string, public component: Type<any>) { }
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import { Directive, ViewContainerRef } from '@angular/core'
|
||||||
|
|
||||||
|
@Directive({
|
||||||
|
selector: '[app-application-detail]'
|
||||||
|
})
|
||||||
|
export class ApplicationDetailDirective {
|
||||||
|
|
||||||
|
constructor(public viewContainerRef: ViewContainerRef) { }
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
<h1>
|
||||||
|
{{ app.name }}<br>
|
||||||
|
<small><small>
|
||||||
|
<a *ngIf="linkToApp" [href]="app.url">{{ app.url }}</a>
|
||||||
|
<span *ngIf="!linkToApp">{{ app.url }}</span>
|
||||||
|
<span *ngIf="linkToArchive">
|
||||||
|
<a [href]="app.archiveUrl"><small>(Archive)</small></a>
|
||||||
|
</span>
|
||||||
|
</small></small>
|
||||||
|
</h1>
|
||||||
@ -0,0 +1,2 @@
|
|||||||
|
h1
|
||||||
|
line-height: 1.6rem
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
import { Component, OnInit, Input } from '@angular/core'
|
||||||
|
|
||||||
|
import { App } from '../application.types'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-application-header',
|
||||||
|
templateUrl: './application-header.component.html',
|
||||||
|
styleUrls: ['./application-header.component.sass']
|
||||||
|
})
|
||||||
|
export class ApplicationHeaderComponent implements OnInit {
|
||||||
|
|
||||||
|
@Input() app: App
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit() { }
|
||||||
|
|
||||||
|
/** Whether to link to the app's URL */
|
||||||
|
get linkToApp () {
|
||||||
|
return this.app.isActive || this.app.linkInactive
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Whether to link to an archive URL */
|
||||||
|
get linkToArchive () {
|
||||||
|
return !this.app.isActive && !this.app.linkInactive && (this.app.archiveUrl > '')
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
<aside><img [src]="imageLink" [alt]="imageAlt"></aside>
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
aside
|
||||||
|
padding-left: 15px
|
||||||
|
aside img
|
||||||
|
border: dotted 1px darkgray
|
||||||
|
border-radius: 10px
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
import { Component, OnInit, Input } from '@angular/core'
|
||||||
|
|
||||||
|
import { App } from '../application.types'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-application-image',
|
||||||
|
templateUrl: './application-image.component.html',
|
||||||
|
styleUrls: ['./application-image.component.sass']
|
||||||
|
})
|
||||||
|
export class ApplicationImageComponent implements OnInit {
|
||||||
|
|
||||||
|
@Input() app: App
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The link to the screenshot image */
|
||||||
|
get imageLink () {
|
||||||
|
return `/assets/screenshots/${this.app.id}.png`
|
||||||
|
}
|
||||||
|
|
||||||
|
/** The alt text for the screenshot image */
|
||||||
|
get imageAlt () {
|
||||||
|
return `Screen shot for ${this.app.name}`
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,69 @@
|
|||||||
|
import { Component, OnInit, ViewChild, ComponentFactoryResolver } from '@angular/core'
|
||||||
|
import { ActivatedRoute } from '@angular/router'
|
||||||
|
|
||||||
|
import { ApplicationService } from './application.service'
|
||||||
|
import { App } from './application.types'
|
||||||
|
import { AppItem } from './app-item'
|
||||||
|
import { ApplicationDetailDirective } from './application-detail.directive'
|
||||||
|
import { AppDetailComponent } from './solutions/app-detail.component'
|
||||||
|
|
||||||
|
import { PrayerTrackerComponent } from './solutions/prayer-tracker.component'
|
||||||
|
import { VirtualPrayerRoomComponent } from './solutions/virtual-prayer-room.component'
|
||||||
|
import { BayVistaComponent } from './solutions/bay-vista.component'
|
||||||
|
import { CassyFianoComponent } from './solutions/cassy-fiano.component'
|
||||||
|
import { DrMelissaClouthierComponent } from './solutions/dr-melissa-clouthier.component'
|
||||||
|
import { EmeraldMountainChristianSchoolComponent } from './solutions/emerald-mountain-christian-school.component'
|
||||||
|
import { FutilityClosetComponent } from './solutions/futility-closet.component'
|
||||||
|
import { HardCorpsWifeComponent } from './solutions/hard-corps-wife.component'
|
||||||
|
import { LibertyPunditsComponent } from './solutions/liberty-pundits.component'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-application',
|
||||||
|
template: '<ng-template app-application-detail></ng-template>'
|
||||||
|
})
|
||||||
|
export class ApplicationComponent implements OnInit {
|
||||||
|
|
||||||
|
private apps = [
|
||||||
|
new AppItem('bay-vista', BayVistaComponent),
|
||||||
|
new AppItem('cassy-fiano', CassyFianoComponent),
|
||||||
|
new AppItem('dr-melissa-clouthier', DrMelissaClouthierComponent),
|
||||||
|
new AppItem('emerald-mountain-christian-school', EmeraldMountainChristianSchoolComponent),
|
||||||
|
new AppItem('futility-closet', FutilityClosetComponent),
|
||||||
|
new AppItem('hard-corps-wife', HardCorpsWifeComponent),
|
||||||
|
new AppItem('liberty-pundits', LibertyPunditsComponent),
|
||||||
|
new AppItem('prayer-tracker', PrayerTrackerComponent),
|
||||||
|
new AppItem('virtual-prayer-room', VirtualPrayerRoomComponent)
|
||||||
|
]
|
||||||
|
|
||||||
|
@ViewChild(ApplicationDetailDirective, { static: true }) appDetail: ApplicationDetailDirective
|
||||||
|
|
||||||
|
/** The app we're displaying */
|
||||||
|
application: App
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private componentFactoryResolver: ComponentFactoryResolver,
|
||||||
|
private appService: ApplicationService,
|
||||||
|
private route: ActivatedRoute
|
||||||
|
) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.route.params.subscribe(params => this.displayApp(params['appId']))
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Dynamically load the app-ropriate component */
|
||||||
|
displayApp(appId: string) {
|
||||||
|
const appComponent = this.apps.find(a => a.name === appId)
|
||||||
|
|
||||||
|
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(appComponent.component)
|
||||||
|
const viewContainerRef = this.appDetail.viewContainerRef
|
||||||
|
viewContainerRef.clear()
|
||||||
|
|
||||||
|
const componentRef = viewContainerRef.createComponent(componentFactory)
|
||||||
|
this.appService.getApp(appId)
|
||||||
|
.subscribe(app => {
|
||||||
|
(<AppDetailComponent>componentRef.instance).app = app
|
||||||
|
this.application = app
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -13,33 +13,9 @@ bayVista.categoryId = Category.STATIC
|
|||||||
bayVista.frontPageText = 'Biloxi, Mississippi'
|
bayVista.frontPageText = 'Biloxi, Mississippi'
|
||||||
bayVista.frontPageOrder = 1
|
bayVista.frontPageOrder = 1
|
||||||
bayVista.indexText = 'Southern Baptist church in Biloxi, Mississippi'
|
bayVista.indexText = 'Southern Baptist church in Biloxi, Mississippi'
|
||||||
bayVista.paragraphs = [
|
|
||||||
`Bay Vista Baptist Church has served the spiritual needs of Mississippi’s Gulf Coast for decades. They emphasize
|
|
||||||
serving their community as well; they were a hub for <abbr title="Federal Emergency Management Agency">FEMA</abbr>
|
|
||||||
during Hurricane Katrina relief and recovery efforts, and they are a relay point for each year’s
|
|
||||||
<a href="https://www.samaritanspurse.org/what-we-do/operation-christmas-child/">Operation Christmas Child</a>
|
|
||||||
campaign. As of late 2013, the authors of their current website were no longer around, and no one could get to the
|
|
||||||
site to update it. We proposed setting up a site based on WordPress, where multiple people could have the ability to
|
|
||||||
maintain the site, reducing the risk of that happening again. We also mentioned that such a site could also serve a
|
|
||||||
sermon podcast feed, increasing the reach of their ministry.`
|
|
||||||
]
|
|
||||||
bayVista.activities = [
|
|
||||||
new Activity('What We Did (2014)',
|
|
||||||
`We manually downloaded all the publically-accessible parts of their old site, and used that content to create a
|
|
||||||
WordPress-based site, updating a few outdated items along the way. We also established a podcast feed for their
|
|
||||||
sermons. A few months after initially setting up the site, we updated the theme to be more mobile-friendly.`),
|
|
||||||
new Activity('What We Did (2016)',
|
|
||||||
`In the nearly three years since we had set up the site, we were the only ones updating it. We had recently migrated
|
|
||||||
some older blogs to use a static site generator and were impressed with the performance gains. We converted their
|
|
||||||
site, to include writing a custom template to support the podcast feed; it is now generated along with the rest of
|
|
||||||
the site.`),
|
|
||||||
new Activity('What We Still Do',
|
|
||||||
`Bit Badger Solutions hosts this site; we also host the church e-mail accounts, and publish sermons to their podcast
|
|
||||||
feed weekly.`)
|
|
||||||
]
|
|
||||||
bayVista.techStack = [
|
bayVista.techStack = [
|
||||||
new Technology('Hexo', 'static site generation'),
|
new Technology('Hexo', 'static site generation'),
|
||||||
new Technology('Azure', 'podcast file storage')
|
new Technology('Azure', 'podcast file storage and automated builds')
|
||||||
]
|
]
|
||||||
|
|
||||||
/** Cassy Fiano */
|
/** Cassy Fiano */
|
||||||
@ -47,23 +23,6 @@ const cassyFiano = new App('cassy-fiano', 'Cassy Fiano', 'http://www.cassyfiano.
|
|||||||
cassyFiano.isActive = false
|
cassyFiano.isActive = false
|
||||||
cassyFiano.categoryId = Category.WORDPRESS
|
cassyFiano.categoryId = Category.WORDPRESS
|
||||||
cassyFiano.indexText = 'A “rising star” conservative blogger'
|
cassyFiano.indexText = 'A “rising star” conservative blogger'
|
||||||
cassyFiano.paragraphs = [
|
|
||||||
`Cassy Fiano (now Cassy Chesser) began blogging back in 2007 on Blogger. She worked hard to network with other
|
|
||||||
bloggers, and wrote prolifically. As she approached the end of her first year of blogging, she was about to outgrow
|
|
||||||
Blogger. She asked in a blog post if anyone had experience with Movable Type, the platform used by another blog to
|
|
||||||
which she contributed. I replied that I did not, but that I had experience with WordPress.`
|
|
||||||
]
|
|
||||||
cassyFiano.activities = [
|
|
||||||
new Activity('What We Did (2008)',
|
|
||||||
`We assisted her with finding a theme, and customized that theme to contain the same sidebar elements as her current
|
|
||||||
Blogger theme. We modified her old Blogger template to send people to her new blog (using redirection) after
|
|
||||||
displaying a note that the blog had moved.`),
|
|
||||||
new Activity('What We Did (2012)',
|
|
||||||
`In July 2012, we began hosting the site, as well as continuing support for theme updates. This joined her military
|
|
||||||
wife blog <a href="/solutions/hard-corps-wife" title="Hard Corps Wife | Bit Badger Solutions">Hard Corps Wife</a>,
|
|
||||||
which we had begun hosting in mid-2011.`),
|
|
||||||
new Activity('What We Still Do', 'Cassy formally decommissioned this site in early 2014.')
|
|
||||||
]
|
|
||||||
cassyFiano.techStack = [ new Technology('WordPress', 'blogging (with a custom theme)') ]
|
cassyFiano.techStack = [ new Technology('WordPress', 'blogging (with a custom theme)') ]
|
||||||
|
|
||||||
/** Daniel J. Summers */
|
/** Daniel J. Summers */
|
||||||
@ -80,25 +39,6 @@ drMelissaClouthier.categoryId = Category.WORDPRESS
|
|||||||
drMelissaClouthier.frontPageText = 'Information Pollination'
|
drMelissaClouthier.frontPageText = 'Information Pollination'
|
||||||
drMelissaClouthier.frontPageOrder = 1
|
drMelissaClouthier.frontPageOrder = 1
|
||||||
drMelissaClouthier.indexText = 'Politics, health, podcasts and more'
|
drMelissaClouthier.indexText = 'Politics, health, podcasts and more'
|
||||||
drMelissaClouthier.paragraphs = [
|
|
||||||
`Dr. Melissa Clouthier saw our work with
|
|
||||||
<a href="/solutions/cassy-fiano" title="Cassy Fiano | Bit Badger Solutions">Cassy</a>’s site, and asked us to
|
|
||||||
help her move off Blogger as well. Melissa blogs from the political right, but also covers health issues and social
|
|
||||||
media. She had been blogging for a several years, and wanted to bring her old content with her to her new site.`
|
|
||||||
]
|
|
||||||
drMelissaClouthier.activities = [
|
|
||||||
new Activity('What We Did (2009)',
|
|
||||||
`We created a custom theme based on another site, and developed graphics to complement that theme. We also imported
|
|
||||||
the content from her Blogger site into the WordPress site, and created a featured content template for the front
|
|
||||||
page.`),
|
|
||||||
new Activity('What We Did (2018)',
|
|
||||||
`Melissa decommissioned her site; we took final snapshots of the information there, then assisted with shutting it
|
|
||||||
down.`)
|
|
||||||
]
|
|
||||||
drMelissaClouthier.footnotes = [
|
|
||||||
`<em>(NOTE: The thumbnail of the site represents a new skin on the original theme; while the theme is the same, Bit
|
|
||||||
Badger Solutions did not create the graphics.)</em>`
|
|
||||||
]
|
|
||||||
drMelissaClouthier.techStack = [ new Technology('WordPress', 'blogging (with a custom theme)') ]
|
drMelissaClouthier.techStack = [ new Technology('WordPress', 'blogging (with a custom theme)') ]
|
||||||
|
|
||||||
/** Emerald Mountain Christian School */
|
/** Emerald Mountain Christian School */
|
||||||
@ -107,28 +47,6 @@ const emcs = new App('emerald-mountain-christian-school', 'Emerald Mountain Chri
|
|||||||
emcs.isActive = false
|
emcs.isActive = false
|
||||||
emcs.linkInactive = true
|
emcs.linkInactive = true
|
||||||
emcs.indexText = 'Classical, Christ-centered education near Wetumpka, Alabama'
|
emcs.indexText = 'Classical, Christ-centered education near Wetumpka, Alabama'
|
||||||
emcs.paragraphs = [
|
|
||||||
`Emerald Mountain Christian School is a private Christian school founded over 50 years ago. They use the Principle
|
|
||||||
Approach®, which emphasizes research, reasoning, relating, and recording to help students synthesize the
|
|
||||||
information they learn, rather than just requiring rote memorization. More information about the school’s rich
|
|
||||||
history can be found on their site.`
|
|
||||||
]
|
|
||||||
emcs.activities = [
|
|
||||||
new Activity('What We Did (2004)',
|
|
||||||
`They had a website with very basic information and very little styling. We developed a theme (the one in the
|
|
||||||
thumbnail), based in large part on the design of their printed materials, and they approved the design. Initially,
|
|
||||||
the site only contained the content from their previous site. We then put their school calendar of events up on
|
|
||||||
the site, where parents could find the dates for upcoming events. Finally, we put all the material from their
|
|
||||||
Parent Information Packet online, which helped prospective families learn more about the school before visiting
|
|
||||||
it.`),
|
|
||||||
new Activity('What We Did (2011)',
|
|
||||||
`The underlying engine of the basic website was switched from PHP to an ASP MVC web application, and the back-end
|
|
||||||
database was switched from MySQL to a PostgreSQL database.`),
|
|
||||||
new Activity('What We Did (2013)',
|
|
||||||
`We passed off the content and hosting of the site to a new maintainer. They have since redesigned it; it is
|
|
||||||
accessible via the URL above, and at
|
|
||||||
<a href="http://emcspatriots.org" title="EMCS Patriots">EMCSpatriots.org</a>.`)
|
|
||||||
]
|
|
||||||
emcs.techStack = [
|
emcs.techStack = [
|
||||||
new Technology('ASP.NET MVC', 'page generation and interactivity'),
|
new Technology('ASP.NET MVC', 'page generation and interactivity'),
|
||||||
new Technology('PostgreSQL', 'data storage')
|
new Technology('PostgreSQL', 'data storage')
|
||||||
@ -140,20 +58,6 @@ futilityCloset.categoryId = Category.WORDPRESS
|
|||||||
futilityCloset.frontPageText = 'An idler’s miscellany of compendious amusements'
|
futilityCloset.frontPageText = 'An idler’s miscellany of compendious amusements'
|
||||||
futilityCloset.frontPageOrder = 2
|
futilityCloset.frontPageOrder = 2
|
||||||
futilityCloset.indexText = 'An idler’s miscellany of compendious amusements'
|
futilityCloset.indexText = 'An idler’s miscellany of compendious amusements'
|
||||||
futilityCloset.paragraphs = [
|
|
||||||
`Futility Closet exists as a place to give people a break from the dullness of work, by providing puzzles, anecdotes,
|
|
||||||
and more. It began on a shared host, but was growing too large and popular for that platform.`
|
|
||||||
]
|
|
||||||
futilityCloset.activities = [
|
|
||||||
new Activity('What We Did',
|
|
||||||
`We determined what the traffic requirements and size of the blog were, then made some recommendations. Greg Ross,
|
|
||||||
the site author, decided on one of our recommendations. He had backups of the existing database, so we were able to
|
|
||||||
set up a server and restore the data onto that new server. We configured WordPress and locked down the server, and
|
|
||||||
this blog was moved quickly.`),
|
|
||||||
new Activity('What We Still Do',
|
|
||||||
`Bit Badger Solutions still hosts Futility Closet, ensuring that the underlying server receives performance and
|
|
||||||
security upgrades, monitoring site performance, and maintaining regular backups.`)
|
|
||||||
]
|
|
||||||
const fcQuote = new Quote('Greg Ross', 'Futility Closet')
|
const fcQuote = new Quote('Greg Ross', 'Futility Closet')
|
||||||
fcQuote.full =
|
fcQuote.full =
|
||||||
`Bit Badger Solutions has been an absolute godsend for Futility Closet. We have been with them since 2010, initially
|
`Bit Badger Solutions has been an absolute godsend for Futility Closet. We have been with them since 2010, initially
|
||||||
@ -178,17 +82,6 @@ const hardCorpsWife = new App('hard-corps-wife', 'Hard Corps Wife', 'http://www.
|
|||||||
hardCorpsWife.isActive = false
|
hardCorpsWife.isActive = false
|
||||||
hardCorpsWife.categoryId = Category.WORDPRESS
|
hardCorpsWife.categoryId = Category.WORDPRESS
|
||||||
hardCorpsWife.indexText = 'Cassy’s life as a Marine wife'
|
hardCorpsWife.indexText = 'Cassy’s life as a Marine wife'
|
||||||
hardCorpsWife.paragraphs = [
|
|
||||||
`Capitalizing on the growth from her Cassy Fiano blog, Cassy (now Chesser) began a separate blog in which she could
|
|
||||||
chronicle her experience as a military spouse.`
|
|
||||||
]
|
|
||||||
hardCorpsWife.activities = [
|
|
||||||
new Activity('What We Did',
|
|
||||||
'We customized the header and sidebar of the theme, and set up the hardcorpswife.com domain.'),
|
|
||||||
new Activity('What We Still Do',
|
|
||||||
`In 2013, Cassy shifted priorities and closed this site down. She can still be found at other places around the
|
|
||||||
web.`)
|
|
||||||
]
|
|
||||||
hardCorpsWife.techStack = [ new Technology('WordPress', 'blogging') ]
|
hardCorpsWife.techStack = [ new Technology('WordPress', 'blogging') ]
|
||||||
|
|
||||||
/** Liberty Pundits */
|
/** Liberty Pundits */
|
||||||
@ -196,30 +89,6 @@ const libertyPundits = new App('liberty-pundits', 'Liberty Pundits', 'http://lib
|
|||||||
libertyPundits.isActive = false
|
libertyPundits.isActive = false
|
||||||
libertyPundits.categoryId = Category.WORDPRESS
|
libertyPundits.categoryId = Category.WORDPRESS
|
||||||
libertyPundits.indexText = 'The home for conservatives'
|
libertyPundits.indexText = 'The home for conservatives'
|
||||||
libertyPundits.paragraphs = [
|
|
||||||
`At its founding, Liberty Pundits was a joint venture by 3 established bloggers (Melissa Clouthier, Bill Dupray, and
|
|
||||||
Clyde Middleton) that, in their words, was aimed at becoming the new home for conservatives on the Internet. With the
|
|
||||||
three of them all being prolific bloggers in their own right, and the help of many contributors, Liberty Pundits was
|
|
||||||
a bustling hub of information.`
|
|
||||||
]
|
|
||||||
libertyPundits.activities = [
|
|
||||||
new Activity('What We Did',
|
|
||||||
`Bill and Clyde had been part of Patriot Room, an already-recognized powerhouse, and their desire was for Liberty
|
|
||||||
Pundits to contain the content that they had contributed to Patriot Room. The technical lead on that blog had moved
|
|
||||||
on, so we did some divining of what was there. Once we deduced the current setup, we obtained the data from that
|
|
||||||
site, determined how it would need to be manipulated to become part of a WordPress blog, then accomplished the data
|
|
||||||
migration. Initially, this was deployed on the same shared hosting account where LibertyPundits.com, their podcast
|
|
||||||
distribution site, already resided. The site’s traffic quickly overwhelmed that solution. They then were
|
|
||||||
moved by their host to a <abbr title="Virtual Private Server">VPS</abbr>, which performed moderately better, but
|
|
||||||
still had quite a few issues, mostly related to the site’s traffic volume. We recommended a new server
|
|
||||||
configuration, including migrating from a fully-featured web server to a more lightweight web server, along with
|
|
||||||
caching, and configured that server. This configuration eliminated the bottlenecks, and enabled them to have
|
|
||||||
several 100,000+ hit days with no appreciable slowdowns.`),
|
|
||||||
new Activity('What We Still Do',
|
|
||||||
`Bit Badger Solutions maintained the server, keeping it current with performance and security upgrades. We also
|
|
||||||
provided support to the primary 3 bloggers, when they had questions about WordPress or how the site was performing.
|
|
||||||
The site closed in August of 2011, as the primary authors moved on to other endeavors.`)
|
|
||||||
]
|
|
||||||
libertyPundits.techStack = [
|
libertyPundits.techStack = [
|
||||||
new Technology('WordPress', 'blogging'),
|
new Technology('WordPress', 'blogging'),
|
||||||
new Technology('Custom software', 'data migration')
|
new Technology('Custom software', 'data migration')
|
||||||
@ -539,25 +408,6 @@ theSharkTank.activities = [
|
|||||||
const vpr = new App('virtual-prayer-room', 'Virtual Prayer Room', 'https://virtualprayerroom.us')
|
const vpr = new App('virtual-prayer-room', 'Virtual Prayer Room', 'https://virtualprayerroom.us')
|
||||||
vpr.isActive = false
|
vpr.isActive = false
|
||||||
vpr.indexText = 'Gives prayer warriors access to requests from wherever they may be, and sends them daily updates'
|
vpr.indexText = 'Gives prayer warriors access to requests from wherever they may be, and sends them daily updates'
|
||||||
vpr.paragraphs = [
|
|
||||||
`Many churches have prayer rooms – rooms set aside for people to come in to pray. Hoffmantown Church in
|
|
||||||
Albuquerque, New Mexico was one of these churches. However, they had seen the use of this physical prayer room
|
|
||||||
dwindling over the years. People had become less willing to drive to the church, especially at night, and security
|
|
||||||
became an issue as well; either prayer warriors had to know how to disable the security system, or the church would
|
|
||||||
have to remain unlocked.`,
|
|
||||||
`Having seen our work with the <a href="/solutions/nsx/"
|
|
||||||
title="Not So Extreme Makeover: Community Edition | Bit Badger Solutions">Not So Extreme Makeover: Community
|
|
||||||
Edition</a>, the church contacted us to see if something similar could be developed to help their prayer ministry.
|
|
||||||
The resulting application that was developed extended the prayer room to wherever the prayer warrior can get an
|
|
||||||
Internet connection! Prayer warriors could enlist right from the site, and had to be approved. Requests and updates
|
|
||||||
were tracked by date/time, and warriors could record when they’ve prayed for a request from the site, or from
|
|
||||||
clicking a link in the daily e-mail they received with requests from their interest areas. As many prayer needs are
|
|
||||||
confidential, security and confidentiality were very important. Virtual Prayer Room ensured these by providing
|
|
||||||
varying security levels for prayer warriors and the ability to mark each request as confidential.`,
|
|
||||||
`In 2016, Hoffmantown Church elected to begin using another package for their prayer requests. While a few other
|
|
||||||
churches had expressed interest in it, none ultimately decided to use it; so, in 2017, Virtual Prayer Room was
|
|
||||||
officially decommissioned.`
|
|
||||||
]
|
|
||||||
vpr.techStack = [
|
vpr.techStack = [
|
||||||
new Technology('Custom PHP code', 'the application'),
|
new Technology('Custom PHP code', 'the application'),
|
||||||
new Technology('PostgreSQL', 'data storage')
|
new Technology('PostgreSQL', 'data storage')
|
||||||
|
|||||||
@ -1,35 +0,0 @@
|
|||||||
<app-page-title [title]="pageTitle"></app-page-title>
|
|
||||||
<div *ngIf="application">
|
|
||||||
<h1>
|
|
||||||
{{ application.name }}<br>
|
|
||||||
<small><small>
|
|
||||||
<a *ngIf="linkToApp" [href]="application.url">{{ application.url }}</a>
|
|
||||||
<span *ngIf="!linkToApp">{{ application.url }}</span>
|
|
||||||
<span *ngIf="linkToArchive">
|
|
||||||
<a [href]="application.archiveUrl"><small>(Archive)</small></a>
|
|
||||||
</span>
|
|
||||||
</small></small>
|
|
||||||
</h1>
|
|
||||||
<div class="app-info">
|
|
||||||
<aside><img [src]="imageLink" [alt]="imageAlt"></aside>
|
|
||||||
<article class="content">
|
|
||||||
<p *ngFor="let p of application.paragraphs" [innerHtml]="p"></p>
|
|
||||||
<div *ngFor="let act of application.activities">
|
|
||||||
<h3>{{ act.heading }}</h3>
|
|
||||||
<p [innerHtml]="act.narrative"></p>
|
|
||||||
</div>
|
|
||||||
<div *ngIf="application.quotes.length > 0">
|
|
||||||
<h3>What They Say</h3>
|
|
||||||
<blockquote *ngFor="let q of application.quotes">
|
|
||||||
<p class="quote" [innerHtml]="q.full"></p>
|
|
||||||
<p class="source">
|
|
||||||
— <strong class="app-info-heading">{{ q.name }}</strong>
|
|
||||||
<span *ngIf="q.from">, {{ q.from }}</span>
|
|
||||||
</p>
|
|
||||||
</blockquote>
|
|
||||||
</div>
|
|
||||||
<p *ngFor="let p of application.footnotes" [innerHtml]="p"></p>
|
|
||||||
<p><br><a routerLink="/solutions">« Back to All Solutions</a></p>
|
|
||||||
</article>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@ -1,21 +0,0 @@
|
|||||||
h1
|
|
||||||
line-height: 1.6rem
|
|
||||||
.app-info
|
|
||||||
display: flex
|
|
||||||
flex-flow: row-reverse wrap
|
|
||||||
justify-content: center
|
|
||||||
aside
|
|
||||||
padding-left: 15px
|
|
||||||
aside img
|
|
||||||
border: dotted 1px darkgray
|
|
||||||
border-radius: 10px
|
|
||||||
blockquote
|
|
||||||
border-left: solid 1px darkgray
|
|
||||||
margin-left: 25px
|
|
||||||
padding-left: 15px
|
|
||||||
.quote
|
|
||||||
font-style: italic
|
|
||||||
.source
|
|
||||||
text-align: right
|
|
||||||
padding-right: 60px
|
|
||||||
|
|
||||||
@ -1,53 +0,0 @@
|
|||||||
import { Component, OnInit, Input } from '@angular/core'
|
|
||||||
import { ActivatedRoute } from '@angular/router'
|
|
||||||
|
|
||||||
import { ApplicationService } from '../application.service'
|
|
||||||
import { App } from '../application.types'
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'app-application',
|
|
||||||
templateUrl: './application.component.html',
|
|
||||||
styleUrls: ['./application.component.sass']
|
|
||||||
})
|
|
||||||
export class ApplicationComponent implements OnInit {
|
|
||||||
|
|
||||||
/** The app we're displaying */
|
|
||||||
application: App
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
private appService: ApplicationService,
|
|
||||||
private route: ActivatedRoute
|
|
||||||
) { }
|
|
||||||
|
|
||||||
ngOnInit() {
|
|
||||||
const appId = this.route.snapshot.paramMap.get('appId')
|
|
||||||
this.appService.getApp(appId)
|
|
||||||
.subscribe(app => this.application = app)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The page title based on this app */
|
|
||||||
get pageTitle () {
|
|
||||||
return `${this.application.name} « Solutions`
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether to link to the app's URL */
|
|
||||||
get linkToApp () {
|
|
||||||
return this.application.isActive || this.application.linkInactive
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Whether to link to an archive URL */
|
|
||||||
get linkToArchive () {
|
|
||||||
return !this.application.isActive && !this.application.linkInactive && (this.application.archiveUrl > '')
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The link to the screenshot image */
|
|
||||||
get imageLink () {
|
|
||||||
return `/assets/screenshots/${this.application.id}.png`
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The alt text for the screenshot image */
|
|
||||||
get imageAlt () {
|
|
||||||
return `Screen shot for ${this.application.name}`
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -3,15 +3,54 @@ import { CommonModule } from '@angular/common'
|
|||||||
import { RouterModule } from '@angular/router'
|
import { RouterModule } from '@angular/router'
|
||||||
|
|
||||||
import { SharedModule } from '../shared/shared.module'
|
import { SharedModule } from '../shared/shared.module'
|
||||||
import { ApplicationComponent } from './application/application.component';
|
import { ApplicationComponent } from './application.component'
|
||||||
import { ApplicationListComponent } from './application-list/application-list.component';
|
import { ApplicationListComponent } from './application-list/application-list.component'
|
||||||
import { ApplicationListItemComponent } from './application-list-item/application-list-item.component'
|
import { ApplicationListItemComponent } from './application-list-item/application-list-item.component'
|
||||||
|
import { PrayerTrackerComponent } from './solutions/prayer-tracker.component'
|
||||||
|
import { ApplicationHeaderComponent } from './application-header/application-header.component'
|
||||||
|
import { AllSolutionsLinkComponent } from './all-solutions-link.component'
|
||||||
|
import { ApplicationImageComponent } from './application-image/application-image.component'
|
||||||
|
import { VirtualPrayerRoomComponent } from './solutions/virtual-prayer-room.component'
|
||||||
|
import { ApplicationDetailDirective } from './application-detail.directive'
|
||||||
|
import { BayVistaComponent } from './solutions/bay-vista.component'
|
||||||
|
import { CassyFianoComponent } from './solutions/cassy-fiano.component'
|
||||||
|
import { DrMelissaClouthierComponent } from './solutions/dr-melissa-clouthier.component';
|
||||||
|
import { EmeraldMountainChristianSchoolComponent } from './solutions/emerald-mountain-christian-school.component';
|
||||||
|
import { FutilityClosetComponent } from './solutions/futility-closet.component';
|
||||||
|
import { QuotesComponent } from './quotes/quotes.component';
|
||||||
|
import { HardCorpsWifeComponent } from './solutions/hard-corps-wife.component';
|
||||||
|
import { LibertyPunditsComponent } from './solutions/liberty-pundits.component'
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
ApplicationComponent,
|
ApplicationComponent,
|
||||||
ApplicationListComponent,
|
ApplicationListComponent,
|
||||||
ApplicationListItemComponent
|
ApplicationListItemComponent,
|
||||||
|
PrayerTrackerComponent,
|
||||||
|
ApplicationHeaderComponent,
|
||||||
|
AllSolutionsLinkComponent,
|
||||||
|
ApplicationImageComponent,
|
||||||
|
VirtualPrayerRoomComponent,
|
||||||
|
ApplicationDetailDirective,
|
||||||
|
BayVistaComponent,
|
||||||
|
CassyFianoComponent,
|
||||||
|
DrMelissaClouthierComponent,
|
||||||
|
EmeraldMountainChristianSchoolComponent,
|
||||||
|
FutilityClosetComponent,
|
||||||
|
QuotesComponent,
|
||||||
|
HardCorpsWifeComponent,
|
||||||
|
LibertyPunditsComponent
|
||||||
|
],
|
||||||
|
entryComponents: [
|
||||||
|
BayVistaComponent,
|
||||||
|
CassyFianoComponent,
|
||||||
|
DrMelissaClouthierComponent,
|
||||||
|
EmeraldMountainChristianSchoolComponent,
|
||||||
|
FutilityClosetComponent,
|
||||||
|
HardCorpsWifeComponent,
|
||||||
|
LibertyPunditsComponent,
|
||||||
|
PrayerTrackerComponent,
|
||||||
|
VirtualPrayerRoomComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
|
|||||||
@ -0,0 +1,10 @@
|
|||||||
|
<div *ngIf="(quotes || []).length > 0">
|
||||||
|
<h3>What They Say</h3>
|
||||||
|
<blockquote *ngFor="let quote of quotes">
|
||||||
|
<p class="quote" [innerHtml]="quote.full"></p>
|
||||||
|
<p class="source">
|
||||||
|
— <strong>{{ quote.name }}</strong>
|
||||||
|
<span *ngIf="quote.from">, {{ quote.from }}</span>
|
||||||
|
</p>
|
||||||
|
</blockquote>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
blockquote
|
||||||
|
border-left: solid 1px darkgray
|
||||||
|
margin-left: 25px
|
||||||
|
padding-left: 15px
|
||||||
|
.quote
|
||||||
|
font-style: italic
|
||||||
|
.source
|
||||||
|
text-align: right
|
||||||
|
padding-right: 60px
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
import { Component, OnInit, Input } from '@angular/core'
|
||||||
|
|
||||||
|
import { Quote } from '../application.types'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-quotes',
|
||||||
|
templateUrl: './quotes.component.html',
|
||||||
|
styleUrls: ['./quotes.component.sass']
|
||||||
|
})
|
||||||
|
export class QuotesComponent implements OnInit {
|
||||||
|
|
||||||
|
@Input() quotes: Quote[]
|
||||||
|
|
||||||
|
constructor() { }
|
||||||
|
|
||||||
|
ngOnInit() { }
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
import { App } from '../application.types'
|
||||||
|
|
||||||
|
/** An inteface implemented by all app detail components */
|
||||||
|
export class AppDetailComponent {
|
||||||
|
|
||||||
|
/** The app to be displayed */
|
||||||
|
app: App
|
||||||
|
|
||||||
|
/** The page title based on this app */
|
||||||
|
get pageTitle () {
|
||||||
|
return `${this.app.name} « Solutions`
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
<app-page-title [title]="pageTitle"></app-page-title>
|
||||||
|
<app-application-header [app]="app"></app-application-header>
|
||||||
|
<div class="app-info">
|
||||||
|
<app-application-image [app]="app"></app-application-image>
|
||||||
|
<article class="content">
|
||||||
|
<p>
|
||||||
|
Bay Vista Baptist Church has served the spiritual needs of Mississippi’s Gulf Coast for decades. They
|
||||||
|
emphasize serving their community as well; they were a hub for
|
||||||
|
<abbr title="Federal Emergency Management Agency">FEMA</abbr> during Hurricane Katrina relief and recovery
|
||||||
|
efforts, and they are a relay point for each year’s
|
||||||
|
<a href="https://www.samaritanspurse.org/what-we-do/operation-christmas-child/">Operation Christmas Child</a>
|
||||||
|
campaign. As of late 2013, the authors of their current website were no longer around, and no one could get to
|
||||||
|
the site to update it. We proposed setting up a site based on WordPress, where multiple people could have the
|
||||||
|
ability to maintain the site, reducing the risk of that happening again. We also mentioned that such a site could
|
||||||
|
also serve a sermon podcast feed, increasing the reach of their ministry.
|
||||||
|
</p>
|
||||||
|
<div>
|
||||||
|
<h3>What We Did (2014)</h3>
|
||||||
|
<p>
|
||||||
|
We manually downloaded all the publically-accessible parts of their old site, and used that content to create a
|
||||||
|
WordPress-based site, updating a few outdated items along the way. We also established a podcast feed for their
|
||||||
|
sermons. A few months after initially setting up the site, we updated the theme to be more mobile-friendly.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3>What We Did (2016)</h3>
|
||||||
|
<p>
|
||||||
|
In the nearly three years since we had set up the site, we were the only ones updating it. We had recently
|
||||||
|
migrated some older blogs to use a static site generator and were impressed with the performance gains. We
|
||||||
|
converted their site, to include writing a custom template to support the podcast feed; it is now generated
|
||||||
|
along with the rest of the site.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3>What We Did (2019)</h3>
|
||||||
|
<p>
|
||||||
|
We <a href="https://github.com/bayvistabc/www.bayvista.org">open sourced</a> the site's source code, and set up
|
||||||
|
Azure Pipelines to automatically build and deploy the site on demand, as well as the regular podcast episode
|
||||||
|
release time.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3>What We Still Do</h3>
|
||||||
|
<p>
|
||||||
|
Bit Badger Solutions hosts this site; we also host the church e-mail accounts, and publish sermons to their
|
||||||
|
podcast feed weekly.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<app-all-solutions-link></app-all-solutions-link>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
import { Component, Input } from '@angular/core'
|
||||||
|
|
||||||
|
import { AppDetailComponent } from './app-detail.component'
|
||||||
|
import { App } from '../application.types'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-bay-vista',
|
||||||
|
templateUrl: './bay-vista.component.html'
|
||||||
|
})
|
||||||
|
export class BayVistaComponent extends AppDetailComponent {
|
||||||
|
|
||||||
|
@Input() app: App
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
<app-page-title [title]="pageTitle"></app-page-title>
|
||||||
|
<app-application-header [app]="app"></app-application-header>
|
||||||
|
<div class="app-info">
|
||||||
|
<app-application-image [app]="app"></app-application-image>
|
||||||
|
<article class="content">
|
||||||
|
<p>
|
||||||
|
Cassy Fiano (now Cassy Chesser) began blogging back in 2007 on Blogger. She worked hard to network with other
|
||||||
|
bloggers, and wrote prolifically. As she approached the end of her first year of blogging, she was about to
|
||||||
|
outgrow Blogger. She asked in a blog post if anyone had experience with Movable Type, the platform used by
|
||||||
|
another blog to which she contributed. I replied that I did not, but that I had experience with WordPress.
|
||||||
|
</p>
|
||||||
|
<div>
|
||||||
|
<h3>What We Did (2008)</h3>
|
||||||
|
<p>
|
||||||
|
We assisted her with finding a theme, and customized that theme to contain the same sidebar elements as her
|
||||||
|
current Blogger theme. We modified her old Blogger template to send people to her new blog (using redirection)
|
||||||
|
after displaying a note that the blog had moved.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3>What We Did (2012)</h3>
|
||||||
|
<p>
|
||||||
|
In July 2012, we began hosting the site, as well as continuing support for theme updates. This joined her
|
||||||
|
military wife blog <a routerLink="/solutions/hard-corps-wife"
|
||||||
|
title="Hard Corps Wife | Bit Badger Solutions">Hard Corps Wife</a>, which we had begun hosting in mid-2011.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3>What We Still Do</h3>
|
||||||
|
<p>Cassy formally decommissioned this site in early 2014.</p>
|
||||||
|
</div>
|
||||||
|
<app-all-solutions-link></app-all-solutions-link>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
import { Component, Input } from '@angular/core'
|
||||||
|
|
||||||
|
import { AppDetailComponent } from './app-detail.component'
|
||||||
|
import { App } from '../application.types'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-cassy-fiano',
|
||||||
|
templateUrl: './cassy-fiano.component.html'
|
||||||
|
})
|
||||||
|
export class CassyFianoComponent extends AppDetailComponent {
|
||||||
|
|
||||||
|
@Input() app: App
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
<app-page-title [title]="pageTitle"></app-page-title>
|
||||||
|
<app-application-header [app]="app"></app-application-header>
|
||||||
|
<div class="app-info">
|
||||||
|
<app-application-image [app]="app"></app-application-image>
|
||||||
|
<article class="content">
|
||||||
|
<p>
|
||||||
|
Dr. Melissa Clouthier saw our work with <a routerLink="/solutions/cassy-fiano"
|
||||||
|
title="Cassy Fiano | Bit Badger Solutions">Cassy</a>’s site, and asked us to help her move off Blogger as
|
||||||
|
well. Melissa blogs from the political right, but also covers health issues and social media. She had been
|
||||||
|
blogging for a several years, and wanted to bring her old content with her to her new site.
|
||||||
|
</p>
|
||||||
|
<div>
|
||||||
|
<h3>What We Did (2009)</h3>
|
||||||
|
<p>
|
||||||
|
We created a custom theme based on another site, and developed graphics to complement that theme. We also
|
||||||
|
imported the content from her Blogger site into the WordPress site, and created a featured content template for
|
||||||
|
the front page.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3>What We Did (2018)</h3>
|
||||||
|
<p>
|
||||||
|
Melissa decommissioned her site; we took final snapshots of the information there, then assisted with shutting
|
||||||
|
it down.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<small><em>(NOTE: The thumbnail of the site represents a new skin on the original theme; while the theme is the
|
||||||
|
same, Bit Badger Solutions did not create the graphics.)</em></small>
|
||||||
|
</p>
|
||||||
|
<app-all-solutions-link></app-all-solutions-link>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
import { Component, Input } from '@angular/core'
|
||||||
|
|
||||||
|
import { AppDetailComponent } from './app-detail.component'
|
||||||
|
import { App } from '../application.types'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-dr-melissa-clouthier',
|
||||||
|
templateUrl: './dr-melissa-clouthier.component.html'
|
||||||
|
})
|
||||||
|
export class DrMelissaClouthierComponent extends AppDetailComponent {
|
||||||
|
|
||||||
|
@Input() app: App
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
<app-page-title [title]="pageTitle"></app-page-title>
|
||||||
|
<app-application-header [app]="app"></app-application-header>
|
||||||
|
<div class="app-info">
|
||||||
|
<app-application-image [app]="app"></app-application-image>
|
||||||
|
<article class="content">
|
||||||
|
<p>
|
||||||
|
Emerald Mountain Christian School is a private Christian school founded over 50 years ago. They use the Principle
|
||||||
|
Approach®, which emphasizes research, reasoning, relating, and recording to help students synthesize the
|
||||||
|
information they learn, rather than just requiring rote memorization. More information about the school’s
|
||||||
|
rich history can be found on their site.
|
||||||
|
</p>
|
||||||
|
<div>
|
||||||
|
<h3>What We Did (2004)</h3>
|
||||||
|
<p>
|
||||||
|
They had a website with very basic information and very little styling. We developed a theme (the one in the
|
||||||
|
thumbnail), based in large part on the design of their printed materials, and they approved the design.
|
||||||
|
Initially, the site only contained the content from their previous site. We then put their school calendar of
|
||||||
|
events up on the site, where parents could find the dates for upcoming events. Finally, we put all the material
|
||||||
|
from their Parent Information Packet online, which helped prospective families learn more about the school
|
||||||
|
before visiting it.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3>What We Did (2011)</h3>
|
||||||
|
<p>
|
||||||
|
The underlying engine of the basic website was switched from PHP to an ASP MVC web application, and the
|
||||||
|
back-end database was switched from MySQL to a PostgreSQL database.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3>What We Did (2013)</h3>
|
||||||
|
<p>
|
||||||
|
We passed off the content and hosting of the site to a new maintainer. They have since redesigned it; it is
|
||||||
|
accessible via the URL above, and at <a href="http://emcspatriots.org"
|
||||||
|
title="EMCS Patriots">EMCSpatriots.org</a>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<app-all-solutions-link></app-all-solutions-link>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
import { Component, Input } from '@angular/core'
|
||||||
|
|
||||||
|
import { AppDetailComponent } from './app-detail.component'
|
||||||
|
import { App } from '../application.types'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-emerald-mountain-christian-school',
|
||||||
|
templateUrl: './emerald-mountain-christian-school.component.html'
|
||||||
|
})
|
||||||
|
export class EmeraldMountainChristianSchoolComponent extends AppDetailComponent {
|
||||||
|
|
||||||
|
@Input() app: App
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,29 @@
|
|||||||
|
<app-page-title [title]="pageTitle"></app-page-title>
|
||||||
|
<app-application-header [app]="app"></app-application-header>
|
||||||
|
<div class="app-info">
|
||||||
|
<app-application-image [app]="app"></app-application-image>
|
||||||
|
<article class="content">
|
||||||
|
<p>
|
||||||
|
Futility Closet exists as a place to give people a break from the dullness of work, by providing puzzles,
|
||||||
|
anecdotes, and more. It began on a shared host, but was growing too large and popular for that platform.
|
||||||
|
</p>
|
||||||
|
<div>
|
||||||
|
<h3>What We Did</h3>
|
||||||
|
<p>
|
||||||
|
We determined what the traffic requirements and size of the blog were, then made some recommendations. Greg
|
||||||
|
Ross, the site author, decided on one of our recommendations. He had backups of the existing database, so we
|
||||||
|
were able to set up a server and restore the data onto that new server. We configured WordPress and locked down
|
||||||
|
the server, and this blog was moved quickly.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3>What We Still Do</h3>
|
||||||
|
<p>
|
||||||
|
Bit Badger Solutions still hosts Futility Closet, ensuring that the underlying server receives performance and
|
||||||
|
security upgrades, monitoring site performance, and maintaining regular backups.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<app-quotes [quotes]="app.quotes"></app-quotes>
|
||||||
|
<app-all-solutions-link></app-all-solutions-link>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
import { Component, Input } from '@angular/core'
|
||||||
|
|
||||||
|
import { AppDetailComponent } from './app-detail.component'
|
||||||
|
import { App } from '../application.types'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-futility-closet',
|
||||||
|
templateUrl: './futility-closet.component.html'
|
||||||
|
})
|
||||||
|
export class FutilityClosetComponent extends AppDetailComponent {
|
||||||
|
|
||||||
|
@Input() app: App
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
<app-page-title [title]="pageTitle"></app-page-title>
|
||||||
|
<app-application-header [app]="app"></app-application-header>
|
||||||
|
<div class="app-info">
|
||||||
|
<app-application-image [app]="app"></app-application-image>
|
||||||
|
<article class="content">
|
||||||
|
<p>
|
||||||
|
Capitalizing on the growth from her Cassy Fiano blog, Cassy (now Chesser) began a separate blog in which she
|
||||||
|
could chronicle her experience as a military spouse.
|
||||||
|
</p>
|
||||||
|
<div>
|
||||||
|
<h3>What We Did</h3>
|
||||||
|
<p>We customized the header and sidebar of the theme, and set up the hardcorpswife.com domain.</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3>What We Still Do</h3>
|
||||||
|
<p>
|
||||||
|
In 2013, Cassy shifted priorities and closed this site down. She can still be found at other places around the
|
||||||
|
web.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<app-all-solutions-link></app-all-solutions-link>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
import { Component, Input } from '@angular/core'
|
||||||
|
|
||||||
|
import { AppDetailComponent } from './app-detail.component'
|
||||||
|
import { App } from '../application.types'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-hard-corps-wife',
|
||||||
|
templateUrl: './hard-corps-wife.component.html'
|
||||||
|
})
|
||||||
|
export class HardCorpsWifeComponent extends AppDetailComponent {
|
||||||
|
|
||||||
|
@Input() app: App
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
<app-page-title [title]="pageTitle"></app-page-title>
|
||||||
|
<app-application-header [app]="app"></app-application-header>
|
||||||
|
<div class="app-info">
|
||||||
|
<app-application-image [app]="app"></app-application-image>
|
||||||
|
<article class="content">
|
||||||
|
<p>
|
||||||
|
At its founding, Liberty Pundits was a joint venture by 3 established bloggers (Melissa Clouthier, Bill Dupray,
|
||||||
|
and Clyde Middleton) that, in their words, was aimed at becoming the new home for conservatives on the Internet.
|
||||||
|
With the three of them all being prolific bloggers in their own right, and the help of many contributors, Liberty
|
||||||
|
Pundits was a bustling hub of information.
|
||||||
|
</p>
|
||||||
|
<div>
|
||||||
|
<h3>What We Did</h3>
|
||||||
|
<p>
|
||||||
|
Bill and Clyde had been part of Patriot Room, an already-recognized powerhouse, and their desire was for
|
||||||
|
Liberty Pundits to contain the content that they had contributed to Patriot Room. The technical lead on that
|
||||||
|
blog had moved on, so we did some divining of what was there. Once we deduced the current setup, we obtained
|
||||||
|
the data from that site, determined how it would need to be manipulated to become part of a WordPress blog,
|
||||||
|
then accomplished the data migration. Initially, this was deployed on the same shared hosting account where
|
||||||
|
LibertyPundits.com, their podcast distribution site, already resided. The site’s traffic quickly
|
||||||
|
overwhelmed that solution. They then were moved by their host to a
|
||||||
|
<abbr title="Virtual Private Server">VPS</abbr>, which performed moderately better, but still had quite a few
|
||||||
|
issues, mostly related to the site’s traffic volume. We recommended a new server configuration, including
|
||||||
|
migrating from a fully-featured web server to a more lightweight web server, along with caching, and configured
|
||||||
|
that server. This configuration eliminated the bottlenecks, and enabled them to have several 100,000+ hit days
|
||||||
|
with no appreciable slowdowns.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3>What We Still Do</h3>
|
||||||
|
<p>
|
||||||
|
Bit Badger Solutions maintained the server, keeping it current with performance and security upgrades. We also
|
||||||
|
provided support to the primary 3 bloggers, when they had questions about WordPress or how the site was
|
||||||
|
performing. The site closed in August of 2011, as the primary authors moved on to other endeavors.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<app-all-solutions-link></app-all-solutions-link>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
import { Component, Input } from '@angular/core'
|
||||||
|
|
||||||
|
import { AppDetailComponent } from './app-detail.component'
|
||||||
|
import { App } from '../application.types'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-liberty-pundits',
|
||||||
|
templateUrl: './liberty-pundits.component.html'
|
||||||
|
})
|
||||||
|
export class LibertyPunditsComponent extends AppDetailComponent {
|
||||||
|
|
||||||
|
@Input() app: App
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
<app-page-title [title]="pageTitle"></app-page-title>
|
||||||
|
<app-application-header [app]="app"></app-application-header>
|
||||||
|
<div class="app-info">
|
||||||
|
<app-application-image [app]="app"></app-application-image>
|
||||||
|
<article class="content">
|
||||||
|
<p>
|
||||||
|
Years ago, Daniel was responsible for keeping up with prayer requests for his Sunday School class. To help him
|
||||||
|
keep up with requests, automatically drop requests that were old, and track long-term requests, he wrote a custom
|
||||||
|
app made up of a few pages. Over time, he added security mechanisms and other options, arriving at the site that
|
||||||
|
exists today. It is provided free for the asking to any church, Sunday School class, or small group that desires
|
||||||
|
a tool to help them establish a continuous list of prayer requests.
|
||||||
|
</p>
|
||||||
|
<div>
|
||||||
|
<h3>What We Did (2005)</h3>
|
||||||
|
<p>Created the original site.</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3>What We Did (2011)</h3>
|
||||||
|
<p>
|
||||||
|
We rewrote this application using a more modern (at the time) framework (ASP MVC 3), building the security
|
||||||
|
additions from the ground up, and posturing it for an interface with
|
||||||
|
<a routerLink="/solutions/virtual-prayer-room" title="Virtual Prayer Room | Bit Badger Solutions">Virtual
|
||||||
|
Prayer Room</a>.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3>What We Did (2012)</h3>
|
||||||
|
<p>In April 2012, version 4 was released with support for Spanish - our first multi-lingual application!</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3>What We Did (2018)</h3>
|
||||||
|
<p>Version 7 brought full mobile accessibility, along with an upgrade to a modern, ultra-fast web framework.</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3>What We Did (2019)</h3>
|
||||||
|
<p>PrayerTracker became <a href="https://github.com/bit-badger/PrayerTracker">an open source project</a>.</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h3>What We Still Do</h3>
|
||||||
|
<p>Host and maintain this application.</p>
|
||||||
|
</div>
|
||||||
|
<app-all-solutions-link></app-all-solutions-link>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
import { Component, Input } from '@angular/core'
|
||||||
|
|
||||||
|
import { AppDetailComponent } from './app-detail.component'
|
||||||
|
import { App } from '../application.types'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-prayer-tracker',
|
||||||
|
templateUrl: './prayer-tracker.component.html'
|
||||||
|
})
|
||||||
|
export class PrayerTrackerComponent extends AppDetailComponent {
|
||||||
|
|
||||||
|
@Input() app: App
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,32 @@
|
|||||||
|
<app-page-title [title]="pageTitle"></app-page-title>
|
||||||
|
<app-application-header [app]="app"></app-application-header>
|
||||||
|
<div class="app-info">
|
||||||
|
<app-application-image [app]="app"></app-application-image>
|
||||||
|
<article class="content">
|
||||||
|
<p>
|
||||||
|
Many churches have prayer rooms – rooms set aside for people to come in to pray. Hoffmantown Church in
|
||||||
|
Albuquerque, New Mexico was one of these churches. However, they had seen the use of this physical prayer room
|
||||||
|
dwindling over the years. People had become less willing to drive to the church, especially at night, and
|
||||||
|
security became an issue as well; either prayer warriors had to know how to disable the security system, or the
|
||||||
|
church would have to remain unlocked.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Having seen our work with the <a routerLink="/solutions/nsx/"
|
||||||
|
title="Not So Extreme Makeover: Community Edition | Bit Badger Solutions">Not So Extreme Makeover: Community
|
||||||
|
Edition</a>, the church contacted us to see if something similar could be developed to help their prayer
|
||||||
|
ministry. The resulting application that was developed extended the prayer room to wherever the prayer warrior
|
||||||
|
can get an Internet connection! Prayer warriors could enlist right from the site, and had to be approved.
|
||||||
|
Requests and updates were tracked by date/time, and warriors could record when they’ve prayed for a request
|
||||||
|
from the site, or from clicking a link in the daily e-mail they received with requests from their interest areas.
|
||||||
|
As many prayer needs are confidential, security and confidentiality were very important. Virtual Prayer Room
|
||||||
|
ensured these by providing varying security levels for prayer warriors and the ability to mark each request as
|
||||||
|
confidential.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
In 2016, Hoffmantown Church elected to begin using another package for their prayer requests. While a few other
|
||||||
|
churches had expressed interest in it, none ultimately decided to use it; so, in 2017, Virtual Prayer Room was
|
||||||
|
officially decommissioned.
|
||||||
|
</p>
|
||||||
|
<app-all-solutions-link></app-all-solutions-link>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
import { Component, Input } from '@angular/core';
|
||||||
|
|
||||||
|
import { AppDetailComponent } from './app-detail.component';
|
||||||
|
import { App } from '../application.types';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-virtual-prayer-room',
|
||||||
|
templateUrl: './virtual-prayer-room.component.html'
|
||||||
|
})
|
||||||
|
export class VirtualPrayerRoomComponent extends AppDetailComponent {
|
||||||
|
|
||||||
|
@Input() app: App
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -52,3 +52,7 @@ ul
|
|||||||
padding-left: 40px
|
padding-left: 40px
|
||||||
li
|
li
|
||||||
list-style-type: disc
|
list-style-type: disc
|
||||||
|
.app-info
|
||||||
|
display: flex
|
||||||
|
flex-flow: row-reverse wrap
|
||||||
|
justify-content: center
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user