add google login with firebase

This commit is contained in:
Jason Wall 2020-08-07 10:10:06 -04:00
parent 49439ed857
commit aaa7ec151b
14 changed files with 4251 additions and 216 deletions

11
app/db/.firebaserc Normal file
View File

@ -0,0 +1,11 @@
{
"targets": {
"dynamicbible-7c6cf": {
"hosting": {
"db": [
"dynamicbible-7c6cf"
]
}
}
}
}

View File

@ -121,8 +121,13 @@
"devServerTarget": "db:serve:production" "devServerTarget": "db:serve:production"
} }
} }
},
"deploy": {
"builder": "@angular/fire:deploy",
"options": {}
} }
} }
}}, }
},
"defaultProject": "db" "defaultProject": "db"
} }

28
app/db/firebase.json Normal file
View File

@ -0,0 +1,28 @@
{
"hosting": [
{
"target": "db",
"public": "dist/db",
"ignore": [
"**/.*"
],
"headers": [
{
"source": "*.[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].+(css|js)",
"headers": [
{
"key": "Cache-Control",
"value": "public,max-age=31536000,immutable"
}
]
}
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
]
}

4127
app/db/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -16,6 +16,7 @@
"@angular/common": "~10.0.4", "@angular/common": "~10.0.4",
"@angular/compiler": "~10.0.4", "@angular/compiler": "~10.0.4",
"@angular/core": "~10.0.4", "@angular/core": "~10.0.4",
"@angular/fire": "^6.0.2",
"@angular/forms": "~10.0.4", "@angular/forms": "~10.0.4",
"@angular/material": "^10.0.2", "@angular/material": "^10.0.2",
"@angular/platform-browser": "~10.0.4", "@angular/platform-browser": "~10.0.4",
@ -30,7 +31,8 @@
"reselect": "^4.0.0", "reselect": "^4.0.0",
"rxjs": "~6.5.5", "rxjs": "~6.5.5",
"tslib": "^2.0.0", "tslib": "^2.0.0",
"zone.js": "~0.10.3" "zone.js": "~0.10.3",
"firebase": "^7.13.1"
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "~0.1000.3", "@angular-devkit/build-angular": "~0.1000.3",
@ -50,6 +52,12 @@
"protractor": "~7.0.0", "protractor": "~7.0.0",
"ts-node": "~8.3.0", "ts-node": "~8.3.0",
"tslint": "~6.1.0", "tslint": "~6.1.0",
"typescript": "~3.9.5" "typescript": "~3.9.5",
"@angular-devkit/architect": ">= 0.900 < 0.1100",
"firebase-tools": "^8.0.0",
"fuzzy": "^0.1.3",
"inquirer": "^6.2.2",
"inquirer-autocomplete-prompt": "^1.0.1",
"open": "^7.0.3"
} }
} }

View File

@ -38,7 +38,7 @@
position="end" position="end"
[opened]="false" [opened]="false"
> >
<mat-toolbar>Search Settings</mat-toolbar> <mat-toolbar>Page Settings</mat-toolbar>
<mat-nav-list> <mat-nav-list>
<mat-list-item> <mat-list-item>
<a mat-list-item (click)="savePage()" <a mat-list-item (click)="savePage()"

View File

@ -60,6 +60,8 @@ import { MatDividerModule } from '@angular/material/divider';
import { MatNativeDateModule, MatRippleModule } from '@angular/material/core'; import { MatNativeDateModule, MatRippleModule } from '@angular/material/core';
import { MatTreeModule } from '@angular/material/tree'; import { MatTreeModule } from '@angular/material/tree';
import { ClipboardModule } from '@angular/cdk/clipboard'; import { ClipboardModule } from '@angular/cdk/clipboard';
import { AngularFireModule } from '@angular/fire';
import { FirebaseConfig } from './constants';
@NgModule({ @NgModule({
declarations: [ declarations: [
@ -88,6 +90,8 @@ import { ClipboardModule } from '@angular/cdk/clipboard';
NgxMdModule.forRoot(), NgxMdModule.forRoot(),
AngularFireModule.initializeApp(FirebaseConfig),
MatSidenavModule, MatSidenavModule,
MatToolbarModule, MatToolbarModule,
MatIconModule, MatIconModule,

View File

@ -98,3 +98,32 @@
</mat-slider> </mat-slider>
</div> </div>
</mat-nav-list> </mat-nav-list>
<mat-toolbar>Profile</mat-toolbar>
<mat-nav-list>
<mat-list-item *ngIf="user$ | async as user; else showLogin">
<button
mat-icon-button
aria-label="Login with Google"
color="primary"
class="auth-button"
(click)="logout()"
>
{{ user.displayName }}
<mat-icon>logout</mat-icon>
</button>
</mat-list-item>
<ng-template #showLogin>
<mat-list-item>
<button
mat-raised-button
aria-label="Logout"
color="accent"
class="auth-button"
(click)="login()"
>
Login with Google
<mat-icon>login</mat-icon>
</button>
</mat-list-item>
</ng-template>
</mat-nav-list>

View File

@ -11,3 +11,6 @@
.settings-h2 { .settings-h2 {
font-size: 12pt; font-size: 12pt;
} }
.auth-button {
width: 100%;
}

View File

@ -6,6 +6,8 @@ import { DisplaySettings } from 'src/app/models/app-state';
import { CardFonts } from 'src/app/constants'; import { CardFonts } from 'src/app/constants';
import { MatSelectChange } from '@angular/material/select'; import { MatSelectChange } from '@angular/material/select';
import { MatSliderChange } from '@angular/material/slider'; import { MatSliderChange } from '@angular/material/slider';
import { AngularFireAuth } from '@angular/fire/auth';
import { auth } from 'firebase/app';
@Component({ @Component({
selector: 'app-settings', selector: 'app-settings',
@ -17,8 +19,9 @@ export class SettingsComponent extends SubscriberComponent {
fonts: string[]; fonts: string[];
cardFont = ''; cardFont = '';
cardFontSize = 10; cardFontSize = 10;
user$ = this.appService.select((state) => state.user);
constructor(public appService: AppService) { constructor(public appService: AppService, public authService: AngularFireAuth) {
super(); super();
this.fonts = CardFonts; this.fonts = CardFonts;
this.addSubscription( this.addSubscription(
@ -27,8 +30,28 @@ export class SettingsComponent extends SubscriberComponent {
this.cardFont = state.displaySettings.cardFont; this.cardFont = state.displaySettings.cardFont;
}) })
); );
this.addSubscription(
this.authService.authState.subscribe((user) => {
this.appService.setUser({
uid: user.uid,
displayName: user.displayName,
providerId: user.providerId,
email: user.email,
});
})
);
} }
login() {
this.authService.signInWithPopup(new auth.GoogleAuthProvider());
}
logout() {
this.authService.signOut();
}
//#region Font Settings
cardFontSelected(evt: MatSelectChange) { cardFontSelected(evt: MatSelectChange) {
this.appService.changeCardFontFamily(evt.value); this.appService.changeCardFontFamily(evt.value);
} }
@ -37,6 +60,8 @@ export class SettingsComponent extends SubscriberComponent {
this.appService.changeCardFontSize(evt.value); this.appService.changeCardFontSize(evt.value);
} }
//#endregion
//#region Search Settings //#region Search Settings
toggleStrongsAsModal(toggle: MatSlideToggleChange) { toggleStrongsAsModal(toggle: MatSlideToggleChange) {

View File

@ -14,12 +14,13 @@ export const CardIcons = {
Strongs: 'article', Strongs: 'article',
}; };
export const CardFonts = [ export const CardFonts = ['Merriweather', 'PT Sans', 'PT Serif', 'Open Sans', 'Roboto', 'Roboto Condensed', 'Inconsolata'];
'Merriweather',
'PT Sans', export const FirebaseConfig = {
'PT Serif', apiKey: 'AIzaSyA3UV4s56CV2EumgvZmyJBTyU-vhv0xhc8',
'Open Sans', authDomain: 'dynamicbible-7c6cf.firebaseapp.com',
'Roboto', databaseURL: 'https://dynamicbible-7c6cf.firebaseio.com',
'Roboto Condensed', projectId: 'dynamicbible-7c6cf',
'Inconsolata', storageBucket: '',
]; messagingSenderId: '200739882604',
};

View File

@ -8,17 +8,21 @@ export interface AppState {
readonly error: Error; readonly error: Error;
readonly displaySettings: DisplaySettings; readonly displaySettings: DisplaySettings;
readonly cardIcons: CardIcons; readonly cardIcons: CardIcons;
readonly user: User;
} }
export interface Error { export interface Error {
readonly msg: string; readonly msg: string;
} }
export type Data = export type Data = BiblePassageResult | StrongsResult | WordLookupResult | NoteItem;
| BiblePassageResult
| StrongsResult export interface User {
| WordLookupResult readonly uid: string;
| NoteItem; readonly displayName: string | null;
readonly email: string | null;
readonly providerId: string;
}
export interface CardIcons { export interface CardIcons {
readonly words: string; readonly words: string;

View File

@ -21,15 +21,16 @@ import {
IndexResult, IndexResult,
NoteItem, NoteItem,
DisplaySettings, DisplaySettings,
User,
} from '../models/app-state'; } from '../models/app-state';
import { Section, BibleReference } from '../common/bible-reference'; import { Section, BibleReference } from '../common/bible-reference';
import { PageTitles, PageIcons } from '../constants'; import { PageTitles, PageIcons } from '../constants';
import { createStateService } from '../common/state-service'; import { createStateService } from '../common/state-service';
import { UUID } from 'angular2-uuid'; import { UUID } from 'angular2-uuid';
import { StorageMap } from '@ngx-pwa/local-storage'; import { StorageMap } from '@ngx-pwa/local-storage';
import { SearchPage } from '../search/components/search-page/search.page';
const initialState: AppState = { const initialState: AppState = {
user: null,
cards: [ cards: [
{ {
qry: 'UUIDGOESHERE', qry: 'UUIDGOESHERE',
@ -127,6 +128,10 @@ type AppAction =
| { | {
type: 'UPDATE_DISPLAY_SETTINGS'; type: 'UPDATE_DISPLAY_SETTINGS';
settings: DisplaySettings; settings: DisplaySettings;
}
| {
type: 'SET_USER';
user: User;
}; };
function reducer(state: AppState, action: AppAction): AppState { function reducer(state: AppState, action: AppAction): AppState {
@ -188,9 +193,7 @@ function reducer(state: AppState, action: AppAction): AppState {
}; };
} }
case 'GET_SAVED_PAGE': { case 'GET_SAVED_PAGE': {
const page = state.savedPages.find( const page = state.savedPages.find((o) => o.id.toString() === action.pageId);
(o) => o.id.toString() === action.pageId
);
if (!page) { if (!page) {
return; return;
@ -286,6 +289,12 @@ function reducer(state: AppState, action: AppAction): AppState {
}, },
}; };
} }
case 'SET_USER': {
return {
...state,
user: action.user,
};
}
} }
} }
@ -300,10 +309,7 @@ export class AppService extends createStateService(reducer, initialState) {
private readonly dataPath = 'assets/data'; private readonly dataPath = 'assets/data';
constructor( constructor(private http: HttpClient, private localStorageService: StorageMap) {
private http: HttpClient,
private localStorageService: StorageMap
) {
super(); super();
this.searchIndexArray = this.buildIndexArray().sort(); this.searchIndexArray = this.buildIndexArray().sort();
@ -326,17 +332,10 @@ export class AppService extends createStateService(reducer, initialState) {
console.log(msg); console.log(msg);
} }
changeCardFontFamily(cardFont: string) { setUser(user: User) {
this.dispatch({ this.dispatch({
type: 'UPDATE_FONT_FAMILY', type: 'SET_USER',
cardFont, user,
});
}
changeCardFontSize(size: number) {
this.dispatch({
type: 'UPDATE_FONT_SIZE',
size,
}); });
} }
@ -346,9 +345,7 @@ export class AppService extends createStateService(reducer, initialState) {
const exists = await this.localStorageService.has('savedPages').toPromise(); const exists = await this.localStorageService.has('savedPages').toPromise();
if (exists) { if (exists) {
const savedPages = (await this.localStorageService const savedPages = (await this.localStorageService.get('savedPages').toPromise()) as SavedPage[];
.get('savedPages')
.toPromise()) as SavedPage[];
this.dispatch({ this.dispatch({
type: 'UPDATE_SAVED_PAGES', type: 'UPDATE_SAVED_PAGES',
@ -407,6 +404,20 @@ export class AppService extends createStateService(reducer, initialState) {
//#region Display Settings //#region Display Settings
changeCardFontFamily(cardFont: string) {
this.dispatch({
type: 'UPDATE_FONT_FAMILY',
cardFont,
});
}
changeCardFontSize(size: number) {
this.dispatch({
type: 'UPDATE_FONT_SIZE',
size,
});
}
updateDisplaySettings(settings: DisplaySettings) { updateDisplaySettings(settings: DisplaySettings) {
this.dispatch({ this.dispatch({
type: 'UPDATE_DISPLAY_SETTINGS', type: 'UPDATE_DISPLAY_SETTINGS',
@ -415,9 +426,7 @@ export class AppService extends createStateService(reducer, initialState) {
} }
async initDisplaySettings() { async initDisplaySettings() {
const hasDisplaySettings = await this.localStorageService const hasDisplaySettings = await this.localStorageService.has('displaySettings').toPromise();
.has('displaySettings')
.toPromise();
if (hasDisplaySettings) { if (hasDisplaySettings) {
const settings = await this.getSettingsApi(); const settings = await this.getSettingsApi();
@ -434,9 +443,7 @@ export class AppService extends createStateService(reducer, initialState) {
} }
private async getSettingsApi() { private async getSettingsApi() {
return (await this.localStorageService return (await this.localStorageService.get('displaySettings').toPromise()) as DisplaySettings;
.get('displaySettings')
.toPromise()) as DisplaySettings;
} }
//#endregion //#endregion
@ -444,9 +451,7 @@ export class AppService extends createStateService(reducer, initialState) {
//#region Notes //#region Notes
async getNote(qry: string, nextToItem: CardItem = null) { async getNote(qry: string, nextToItem: CardItem = null) {
const note = (await this.localStorageService const note = (await this.localStorageService.get('notes/' + qry).toPromise()) as NoteItem;
.get('notes/' + qry)
.toPromise()) as NoteItem;
const card = { const card = {
qry, qry,
@ -539,11 +544,7 @@ export class AppService extends createStateService(reducer, initialState) {
//#region Strongs //#region Strongs
async getStrongs( async getStrongs(strongsNumber: string, dict: DictionaryType, nextToItem: CardItem = null) {
strongsNumber: string,
dict: DictionaryType,
nextToItem: CardItem = null
) {
const card = await this.getStrongsCard(strongsNumber, dict); const card = await this.getStrongsCard(strongsNumber, dict);
this.dispatch({ this.dispatch({
@ -580,46 +581,32 @@ export class AppService extends createStateService(reducer, initialState) {
if (dict === 'grk') { if (dict === 'grk') {
result.prefix = 'G'; result.prefix = 'G';
if (sn > 5624 || sn < 1) { if (sn > 5624 || sn < 1) {
this.dispatchError( this.dispatchError(`Strong's Number G${sn} is out of range. Strong's numbers range from 1 - 5624 in the New Testament.`);
`Strong's Number G${sn} is out of range. Strong's numbers range from 1 - 5624 in the New Testament.`
);
return; return;
} }
} else { } else {
result.prefix = 'H'; result.prefix = 'H';
if (sn > 8674 || sn < 1) { if (sn > 8674 || sn < 1) {
this.dispatchError( this.dispatchError(`Strong's Number H${sn} is out of range. Strong's numbers range from 1 - 8674 in the Old Testament.`);
`Strong's Number H${sn} is out of range. Strong's numbers range from 1 - 8674 in the Old Testament.`
);
return; return;
} }
} }
let url = `${dict}${Math.ceil(sn / 100)}.json`; let url = `${dict}${Math.ceil(sn / 100)}.json`;
try { try {
const d = await this.http const d = await this.http.get<StrongsDefinition[]>(`${this.dataPath}/strongs/${url}`).toPromise();
.get<StrongsDefinition[]>(`${this.dataPath}/strongs/${url}`)
.toPromise();
result.def = d.find((el) => el.i === result.prefix + result.sn); result.def = d.find((el) => el.i === result.prefix + result.sn);
} catch (err) { } catch (err) {
this.dispatchError( this.dispatchError(`Unable to retrieve Strong's Data for ${result.prefix}${result.sn}`);
`Unable to retrieve Strong's Data for ${result.prefix}${result.sn}`
);
return; return;
} }
try { try {
const d = await this.http const d = await this.http.get<StrongsCrossReference[]>(`${this.dataPath}/strongscr/cr${url}`).toPromise();
.get<StrongsCrossReference[]>(`${this.dataPath}/strongscr/cr${url}`)
.toPromise();
result.crossrefs = d.find( result.crossrefs = d.find((o) => o.id.toUpperCase() === result.prefix + result.sn);
(o) => o.id.toUpperCase() === result.prefix + result.sn
);
} catch (err) { } catch (err) {
this.dispatchError( this.dispatchError(`Unable to retrieve Strong\'s Cross References for ${result.prefix}${result.sn}`);
`Unable to retrieve Strong\'s Cross References for ${result.prefix}${result.sn}`
);
return; return;
} }
@ -630,16 +617,12 @@ export class AppService extends createStateService(reducer, initialState) {
// rmac is a two get process. // rmac is a two get process.
// first, get the rmac code. // first, get the rmac code.
try { try {
const rmacCrossReferences = await this.http const rmacCrossReferences = await this.http.get<RMACCrossReference[]>(url).toPromise();
.get<RMACCrossReference[]>(url)
.toPromise();
// deal with RMAC // deal with RMAC
const referencesForThisStrongsNumber = rmacCrossReferences.filter( const referencesForThisStrongsNumber = rmacCrossReferences.filter((el, i) => {
(el, i) => { return el.i === sn.toString();
return el.i === sn.toString(); });
}
);
if (referencesForThisStrongsNumber.length === 0) { if (referencesForThisStrongsNumber.length === 0) {
return result; return result;
@ -655,12 +638,8 @@ export class AppService extends createStateService(reducer, initialState) {
url = `${this.dataPath}/rmac/r-${result.rmaccode.substring(0, 1)}.json`; url = `${this.dataPath}/rmac/r-${result.rmaccode.substring(0, 1)}.json`;
try { try {
const rmacDefinitions = await this.http const rmacDefinitions = await this.http.get<RMACDefinition[]>(url).toPromise();
.get<RMACDefinition[]>(url) result.rmac = rmacDefinitions.find((o) => o.id.toLowerCase() === result.rmaccode);
.toPromise();
result.rmac = rmacDefinitions.find(
(o) => o.id.toLowerCase() === result.rmaccode
);
} catch (err) { } catch (err) {
this.dispatchError('Unable to retrieve RMAC'); this.dispatchError('Unable to retrieve RMAC');
return; return;
@ -724,16 +703,10 @@ export class AppService extends createStateService(reducer, initialState) {
return; return;
} }
for ( for (let i = Number(section.start.chapter); i <= Number(section.end.chapter); i++) {
let i = Number(section.start.chapter);
i <= Number(section.end.chapter);
i++
) {
try { try {
const d = await this.http const d = await this.http
.get<BiblePassage>( .get<BiblePassage>(`${this.dataPath}/bibles/kjv_strongs/${section.book.bookNumber}-${i}.json`)
`${this.dataPath}/bibles/kjv_strongs/${section.book.bookNumber}-${i}.json`
)
.toPromise(); .toPromise();
chapters.push(d); chapters.push(d);
} catch (err) { } catch (err) {
@ -796,15 +769,10 @@ export class AppService extends createStateService(reducer, initialState) {
} }
} }
private async convertToParagraphPassages( private async convertToParagraphPassages(chapters: BiblePassage[], section: Section) {
chapters: BiblePassage[],
section: Section
) {
// get the paragraphs the first time if you haven't already. // get the paragraphs the first time if you haven't already.
if (!this.paragraphs) { if (!this.paragraphs) {
this.paragraphs = await this.http this.paragraphs = await this.http.get<HashTable<Paragraph>>(`${this.dataPath}/bibles/paras.json`).toPromise();
.get<HashTable<Paragraph>>(`${this.dataPath}/bibles/paras.json`)
.toPromise();
} }
const passages: BibleParagraphPassage[] = []; const passages: BibleParagraphPassage[] = [];
@ -820,11 +788,7 @@ export class AppService extends createStateService(reducer, initialState) {
return passages; return passages;
} }
private convertToParagraphs( private convertToParagraphs(ch: BiblePassage, section: Section, paragraphMarkers: HashTable<Paragraph>): BibleParagraph[] {
ch: BiblePassage,
section: Section,
paragraphMarkers: HashTable<Paragraph>
): BibleParagraph[] {
// group the verses into paragraphs. // group the verses into paragraphs.
// create an initial paragraph to hold verses that might come before a paragraph. // create an initial paragraph to hold verses that might come before a paragraph.
@ -858,11 +822,7 @@ export class AppService extends createStateService(reducer, initialState) {
} }
private getRefKey(vs: BibleVerse, section: Section) { private getRefKey(vs: BibleVerse, section: Section) {
return BibleReference.formatReferenceKey( return BibleReference.formatReferenceKey(section.book.bookNumber, section.start.chapter, vs.v);
section.book.bookNumber,
section.start.chapter,
vs.v
);
} }
//#endregion //#endregion
@ -915,28 +875,15 @@ export class AppService extends createStateService(reducer, initialState) {
// handle the first case. // handle the first case.
if (stem <= this.searchIndexArray[0]) { if (stem <= this.searchIndexArray[0]) {
results.unshift( results.unshift(await this.getSearchReferences(`${this.dataPath}/index/${this.searchIndexArray[0]}idx.json`, stem));
await this.getSearchReferences(
`${this.dataPath}/index/${this.searchIndexArray[0]}idx.json`,
stem
)
);
break; break;
} }
// For each query term, figure out which file it is in, and get it. // For each query term, figure out which file it is in, and get it.
for (let w = 1; w < this.searchIndexArray.length; w++) { for (let w = 1; w < this.searchIndexArray.length; w++) {
// If we are at the end of the array, we want to use a different test. // If we are at the end of the array, we want to use a different test.
if ( if (stem <= this.searchIndexArray[w] && stem > this.searchIndexArray[w - 1]) {
stem <= this.searchIndexArray[w] && results.unshift(await this.getSearchReferences(`${this.dataPath}/index/${this.searchIndexArray[w]}idx.json`, stem));
stem > this.searchIndexArray[w - 1]
) {
results.unshift(
await this.getSearchReferences(
`${this.dataPath}/index/${this.searchIndexArray[w]}idx.json`,
stem
)
);
} }
} }
} // End of loop through query terms } // End of loop through query terms
@ -977,9 +924,7 @@ export class AppService extends createStateService(reducer, initialState) {
private async getStemWordIndex() { private async getStemWordIndex() {
this.wordToStem = new Map<string, string>(); this.wordToStem = new Map<string, string>();
try { try {
const r = await this.http const r = await this.http.get<WordToStem[]>(`${this.dataPath}/index/word_to_stem_idx.json`).toPromise();
.get<WordToStem[]>(`${this.dataPath}/index/word_to_stem_idx.json`)
.toPromise();
// find the right word // find the right word
for (const i of r) { for (const i of r) {
@ -1324,9 +1269,7 @@ export class AppService extends createStateService(reducer, initialState) {
async getAutoComplete(keyword: string) { async getAutoComplete(keyword: string) {
if (!this.autocomplete) { if (!this.autocomplete) {
// if you have't populated the word list yet, do so... // if you have't populated the word list yet, do so...
const data = await this.http const data = await this.http.get<WordToStem[]>(`${this.dataPath}/index/word_to_stem_idx.json`).toPromise();
.get<WordToStem[]>(`${this.dataPath}/index/word_to_stem_idx.json`)
.toPromise();
this.autocomplete = data.map((o) => o.w); this.autocomplete = data.map((o) => o.w);
} }
@ -1347,8 +1290,7 @@ export class AppService extends createStateService(reducer, initialState) {
for (const item of BibleReference.Books) { for (const item of BibleReference.Books) {
if ( if (
item.name !== 'Unknown' && item.name !== 'Unknown' &&
(item.name.toLowerCase().indexOf(qry.toLowerCase()) > -1 || (item.name.toLowerCase().indexOf(qry.toLowerCase()) > -1 || item.abbreviation.toLowerCase().indexOf(qry.toLowerCase()) > -1)
item.abbreviation.toLowerCase().indexOf(qry.toLowerCase()) > -1)
) { ) {
words.push(prefix + item.name); words.push(prefix + item.name);
if (words.length > 2) { if (words.length > 2) {

View File

@ -1,3 +1,3 @@
export const environment = { export const environment = {
production: true production: true,
}; };