remove the dict from card item, and add type safety

This commit is contained in:
Jason Wall 2020-08-09 17:01:05 -04:00
parent b5f69fe088
commit 44072579a1
10 changed files with 77 additions and 79 deletions

View File

@ -1,12 +1,12 @@
import { mergeCardList } from './card-operations';
import { BibleReference, Overlap } from './bible-reference';
import { CardType } from '../models/app-state';
import { CardType, CardItem } from '../models/card-state';
describe('Card Merging', () => {
it('Should merge two equal reference cards', () => {
const cardList = [
{ type: CardType.Passage, qry: 'Genesis 1:1', data: null, dict: '' },
{ type: CardType.Passage, qry: 'Genesis 1:1', data: null, dict: '' },
const cardList: CardItem[] = [
{ type: CardType.Passage, qry: 'Genesis 1:1', data: null },
{ type: CardType.Passage, qry: 'Genesis 1:1', data: null },
];
for (const strat of [Overlap.Equal, Overlap.Subset]) {
const merged = mergeCardList(cardList, strat);
@ -16,9 +16,9 @@ describe('Card Merging', () => {
});
it('Should merge two equal word cards', () => {
const cardList = [
{ type: CardType.Word, qry: 'sin', data: null, dict: '' },
{ type: CardType.Word, qry: 'sin', data: null, dict: '' },
const cardList: CardItem[] = [
{ type: CardType.Word, qry: 'sin', data: null },
{ type: CardType.Word, qry: 'sin', data: null },
];
for (const strat of [Overlap.Equal]) {
const merged = mergeCardList(cardList, strat);
@ -28,10 +28,10 @@ describe('Card Merging', () => {
});
it('Should merge two equal word cards with one in the middle', () => {
const cardList = [
{ type: CardType.Word, qry: 'sin', data: null, dict: '' },
{ type: CardType.Word, qry: 'love', data: null, dict: '' },
{ type: CardType.Word, qry: 'sin', data: null, dict: '' },
const cardList: CardItem[] = [
{ type: CardType.Word, qry: 'sin', data: null },
{ type: CardType.Word, qry: 'love', data: null },
{ type: CardType.Word, qry: 'sin', data: null },
];
for (const strat of [Overlap.Equal]) {
const merged = mergeCardList(cardList, strat);
@ -42,9 +42,9 @@ describe('Card Merging', () => {
});
it('Should merge two equal strongs cards', () => {
const cardList = [
{ type: CardType.Strongs, qry: 'G123', data: null, dict: '' },
{ type: CardType.Strongs, qry: 'G123', data: null, dict: '' },
const cardList: CardItem[] = [
{ type: CardType.Strongs, qry: 'G123', data: null },
{ type: CardType.Strongs, qry: 'G123', data: null },
];
for (const strat of [Overlap.Equal]) {
const merged = mergeCardList(cardList, strat);
@ -54,10 +54,10 @@ describe('Card Merging', () => {
});
it('Should merge two equal strongs cards with one in the middle', () => {
const cardList = [
{ type: CardType.Strongs, qry: 'G123', data: null, dict: '' },
{ type: CardType.Passage, qry: 'Genesis 1:1', data: null, dict: '' },
{ type: CardType.Strongs, qry: 'G123', data: null, dict: '' },
const cardList: CardItem[] = [
{ type: CardType.Strongs, qry: 'G123', data: null },
{ type: CardType.Passage, qry: 'Genesis 1:1', data: null },
{ type: CardType.Strongs, qry: 'G123', data: null },
];
for (const strat of [Overlap.Equal]) {
const merged = mergeCardList(cardList, strat);
@ -68,10 +68,10 @@ describe('Card Merging', () => {
});
it('Should merge two equal cards with one in the middle', () => {
const cardList = [
{ type: CardType.Passage, qry: 'Genesis 1:1', data: null, dict: '' },
{ type: CardType.Passage, qry: 'Genesis 1:2', data: null, dict: '' },
{ type: CardType.Passage, qry: 'Genesis 1:1', data: null, dict: '' },
const cardList: CardItem[] = [
{ type: CardType.Passage, qry: 'Genesis 1:1', data: null },
{ type: CardType.Passage, qry: 'Genesis 1:2', data: null },
{ type: CardType.Passage, qry: 'Genesis 1:1', data: null },
];
for (const strat of [Overlap.Equal, Overlap.Subset]) {
const merged = mergeCardList(cardList, strat);
@ -82,9 +82,9 @@ describe('Card Merging', () => {
});
it('Should merge two intersecting cards', () => {
const cardList = [
{ type: CardType.Passage, qry: 'Genesis 1:1-2', data: null, dict: '' },
{ type: CardType.Passage, qry: 'Genesis 1:1', data: null, dict: '' },
const cardList: CardItem[] = [
{ type: CardType.Passage, qry: 'Genesis 1:1-2', data: null },
{ type: CardType.Passage, qry: 'Genesis 1:1', data: null },
];
for (const strat of [Overlap.Intersect, Overlap.Subset]) {
const merged = mergeCardList(cardList, strat);
@ -94,10 +94,10 @@ describe('Card Merging', () => {
});
it('Should merge two intersecting cards with one in the middle', () => {
const cardList = [
{ type: CardType.Passage, qry: 'Genesis 1:1-2', data: null, dict: '' },
{ type: CardType.Passage, qry: 'Genesis 1:4', data: null, dict: '' },
{ type: CardType.Passage, qry: 'Genesis 1:1', data: null, dict: '' },
const cardList: CardItem[] = [
{ type: CardType.Passage, qry: 'Genesis 1:1-2', data: null },
{ type: CardType.Passage, qry: 'Genesis 1:4', data: null },
{ type: CardType.Passage, qry: 'Genesis 1:1', data: null },
];
for (const strat of [Overlap.Intersect, Overlap.Subset]) {
const merged = mergeCardList(cardList, strat);
@ -108,9 +108,9 @@ describe('Card Merging', () => {
});
it('Should not merge two cards of different card types', () => {
const cardList = [
{ type: CardType.Passage, qry: 'Genesis 1:1', data: null, dict: '' },
{ type: CardType.Word, qry: 'sin', data: null, dict: '' },
const cardList: CardItem[] = [
{ type: CardType.Passage, qry: 'Genesis 1:1', data: null },
{ type: CardType.Word, qry: 'sin', data: null },
];
for (const strat of [Overlap.Equal, Overlap.Subset, Overlap.Intersect, Overlap.None]) {
const merged = mergeCardList(cardList, strat);

View File

@ -1,5 +1,5 @@
import { BibleReference, Overlap } from './bible-reference';
import { CardItem, CardType } from '../models/app-state';
import { CardItem, CardType } from '../models/card-state';
export function maybeMergeCards(leftCard: CardItem, rightCard: CardItem, strategy: Overlap): CardItem | null {
if (leftCard.type === rightCard.type) {

View File

@ -5,7 +5,7 @@ import { NoteItem } from 'src/app/models/note-state';
import { CardComponent } from 'src/app/components/card.component';
import { BibleReference, Overlap } from 'src/app/common/bible-reference';
import { AppService } from 'src/app/services/app.service';
import { Paragraph } from 'src/app/models/passage-state';
import { Paragraph, BiblePassageResult } from 'src/app/models/passage-state';
@Component({
selector: 'app-passage-card',
@ -121,7 +121,7 @@ export class PassageCardComponent extends CardComponent implements OnInit {
}
async openStrongs(q: string, asModal = false) {
const dict = this.cardItem.dict === 'H' ? 'heb' : 'grk';
const dict = (this.cardItem.data as BiblePassageResult).dict;
const numbers = q.split(' ');
for (const sn of numbers) {
if (asModal) {

View File

@ -3,7 +3,7 @@ import { StrongsResult } from './strongs-state';
import { WordLookupResult } from './words-state';
import { NoteItem } from './note-state';
export type Data = BiblePassageResult | StrongsResult | WordLookupResult | NoteItem;
export type CardData = BiblePassageResult | StrongsResult | WordLookupResult | NoteItem;
export enum CardType {
Passage,
@ -15,9 +15,8 @@ export enum CardType {
export interface CardItem {
readonly qry: string;
readonly data: Data;
readonly data: CardData;
readonly type: CardType;
readonly dict: string;
}
export interface CardIcons {

View File

@ -1,6 +1,8 @@
import { StrongsDictionary } from './strongs-state';
export interface BiblePassageResult {
readonly cs: readonly BibleParagraphPassage[];
readonly testament: string;
readonly dict: StrongsDictionary;
readonly ref: string;
}

View File

@ -1,6 +1,7 @@
export type StrongsDictionary = 'heb' | 'grk';
export interface StrongsResult {
readonly dict: StrongsDictionary;
readonly prefix: string;
readonly sn: number;
readonly def: StrongsDefinition;

View File

@ -3,22 +3,22 @@ import { UUID } from 'angular2-uuid';
import { AppState } from '../models/app-state';
import { PageTitles, PageIcons } from '../constants';
import { Overlap } from '../common/bible-reference';
import { CardType } from '../models/card-state';
import { CardType, CardItem } from '../models/card-state';
import { NoteItem } from '../models/note-state';
export const initialState: AppState = {
user: null,
cards: [
{
qry: 'UUIDGOESHERE',
dict: 'n/a',
type: CardType.Note,
data: {
id: UUID.UUID(),
xref: '1 pe 2:16; jn 3:16',
title: 'Title Here',
content: '# Content Here\nIn Markdown format.',
},
},
} as NoteItem,
} as CardItem,
],
autocomplete: [],
currentSavedPage: null,

View File

@ -2,8 +2,9 @@ import { TestBed } from '@angular/core/testing';
import { reducer } from './app-state-reducer';
import { AppAction, AppActionFactory } from './app-state-actions';
import { Overlap } from '../common/bible-reference';
import { CardType, SavedPage } from '../models/app-state';
import { IStorable, Storable } from '../common/storable';
import { CardType, CardIcons, CardItem } from '../models/card-state';
import { SavedPage } from '../models/page-state';
describe('AppService Reducer', () => {
const preState = {
@ -95,21 +96,20 @@ describe('AppService Reducer', () => {
});
it('ADD_CARD', () => {
const card1 = {
const card1: CardItem = {
qry: 'H123',
data: null,
type: CardType.Strongs,
dict: 'H',
};
const action1 = AppActionFactory.newAddCard(card1, null);
const testState = reducer(preState, action1);
expect(testState.cards[0]).toBe(card1, 'Failed to add first card to empty list');
const card2 = {
const card2: CardItem = {
qry: 'G123',
data: null,
type: CardType.Strongs,
dict: 'G',
};
const action2 = AppActionFactory.newAddCard(card2, null);
@ -117,11 +117,10 @@ describe('AppService Reducer', () => {
expect(testState2.cards.length).toBe(2, 'Failed to add second card to list with 1 item');
expect(testState2.cards[1]).toBe(card2);
const card3 = {
const card3: CardItem = {
qry: 'G1234',
data: null,
type: CardType.Strongs,
dict: 'G',
};
// append to top, insert next to card
@ -249,14 +248,12 @@ describe('AppService Reducer', () => {
qry: 'H123',
data: null,
type: CardType.Strongs,
dict: 'H',
},
} as CardItem,
{
qry: 'G123',
data: null,
type: CardType.Strongs,
dict: 'G',
},
} as CardItem,
],
// tslint:disable-next-line: quotemark
title: "Jason's Page",

View File

@ -233,10 +233,9 @@ export function reducer(state: AppState, action: AppAction): AppState {
.map((o) => {
return {
qry: o.id,
dict: 'n/a',
type: CardType.Note,
data: o,
};
} as CardItem;
});
let cards = [] as CardItem[];
@ -267,9 +266,8 @@ export function reducer(state: AppState, action: AppAction): AppState {
}
case 'GET_NOTE': {
const note = state.notes.value.find((o) => o.id === action.noteId);
const card = {
const card: CardItem = {
qry: note.id,
dict: 'n/a',
type: CardType.Note,
data: note,
};

View File

@ -7,13 +7,21 @@ import { StorageMap } from '@ngx-pwa/local-storage';
import { AngularFireDatabase } from '@angular/fire/database';
import { IStorable } from '../common/storable';
import { NoteItem } from '../models/note-state';
import { Paragraph, BiblePassage, BibleVerse, BibleParagraphPassage, BibleParagraph } from '../models/passage-state';
import {
Paragraph,
BiblePassage,
BibleVerse,
BibleParagraphPassage,
BibleParagraph,
BiblePassageResult,
} from '../models/passage-state';
import {
StrongsDefinition,
StrongsCrossReference,
RMACCrossReference,
RMACDefinition,
StrongsDictionary,
StrongsResult,
} from '../models/strongs-state';
import { WordToStem, IndexResult, WordLookupResult } from '../models/words-state';
import { HashTable } from '../common/hashtable';
@ -195,16 +203,16 @@ export class AppService extends createStateService(reducer, initialState) {
const result = await this.getStrongsFromApi(strongsNumber, dict);
const d = dict === 'grk' ? 'G' : 'H';
const card = {
const card: CardItem = {
qry: `${d}${strongsNumber}`,
dict: d,
type: CardType.Strongs,
data: result,
};
return card;
}
private async getStrongsFromApi(strongsNumber: string, dict: string) {
private async getStrongsFromApi(strongsNumber: string, dict: string): Promise<StrongsResult> {
const sn = parseInt(strongsNumber, 10);
const result = {
prefix: '',
@ -266,7 +274,7 @@ export class AppService extends createStateService(reducer, initialState) {
});
if (referencesForThisStrongsNumber.length === 0) {
return result;
return result as StrongsResult;
}
result.rmaccode = referencesForThisStrongsNumber[0].r;
} catch (err) {
@ -287,7 +295,7 @@ export class AppService extends createStateService(reducer, initialState) {
}
}
}
return result;
return result as StrongsResult;
}
//#endregion
@ -315,7 +323,6 @@ export class AppService extends createStateService(reducer, initialState) {
const result = await this.getPassageFromApi(ref.section);
return {
qry: ref.toString(),
dict: ref.section.book.bookNumber > 39 ? 'G' : 'H',
type: CardType.Passage,
data: result,
};
@ -324,11 +331,6 @@ export class AppService extends createStateService(reducer, initialState) {
private async getPassageFromApi(section: Section) {
try {
const chapters = []; // the verses from the chapter.
const result = {
cs: [],
testament: '',
ref: BibleReference.toString(section),
};
if (Number(section.start.chapter) > section.book.lastChapter) {
this.dispatchError(
@ -351,7 +353,7 @@ export class AppService extends createStateService(reducer, initialState) {
.toPromise();
chapters.push(d);
} catch (err) {
this.dispatchError(`Unable to retrieve bible passage ${result.ref}.`);
this.dispatchError(`Unable to retrieve bible passage ${BibleReference.toString(section)}.`);
return;
}
}
@ -396,13 +398,13 @@ export class AppService extends createStateService(reducer, initialState) {
}
// convert into paragraphs.
result.cs = await this.convertToParagraphPassages(passages, section);
const cs = await this.convertToParagraphPassages(passages, section);
if (section.book.bookNumber >= 40) {
result.testament = 'new';
} else {
result.testament = 'old';
}
const result = {
cs,
dict: section.book.bookNumber > 39 ? 'grk' : 'heb',
ref: BibleReference.toString(section),
} as BiblePassageResult;
return result;
} catch (error) {
@ -479,10 +481,9 @@ export class AppService extends createStateService(reducer, initialState) {
const card = {
qry,
dict: 'n/a',
type: CardType.Word,
data: result,
};
} as CardItem;
this.dispatch({
type: 'ADD_CARD',