diff --git a/app/db/README.md b/app/db/README.md index 362b805d..897ba40b 100644 --- a/app/db/README.md +++ b/app/db/README.md @@ -57,3 +57,4 @@ To get more help on the Angular CLI use `ng help` or go check out the [Angular C - Test note search - Make card icons configurable (for future) - remove old ionic project +- Change Card Qry option in drop down diff --git a/app/db/src/app/common/components/card.component.ts b/app/db/src/app/common/components/card.component.ts index 1c1b8e94..5f5cc71f 100644 --- a/app/db/src/app/common/components/card.component.ts +++ b/app/db/src/app/common/components/card.component.ts @@ -4,6 +4,8 @@ import { Observable } from 'rxjs'; import { MatDialog } from '@angular/material/dialog'; import { AddToPageModalComponent } from '../../search/components/saved-page/add-to-page-modal/add-to-page-modal.component'; import { SubscriberComponent } from './subscriber.component'; +import { AppService } from 'src/app/services/app.service'; +import { ListDirection } from '../list-direction'; @Component({ template: '', @@ -20,7 +22,7 @@ export class CardComponent extends SubscriberComponent { icon$: Observable; - constructor(protected elementRef: ElementRef, protected dialog: MatDialog) { + constructor(protected elementRef: ElementRef, protected dialog: MatDialog, protected appService: AppService) { super(); } @@ -63,4 +65,12 @@ export class CardComponent extends SubscriberComponent { data: this.cardItem, }); } + + moveCardDown() { + this.appService.moveCard(this.cardItem, ListDirection.Down); + } + + moveCardUp() { + this.appService.moveCard(this.cardItem, ListDirection.Up); + } } diff --git a/app/db/src/app/common/hashtable.ts b/app/db/src/app/common/hashtable.ts new file mode 100644 index 00000000..c9eb2b5e --- /dev/null +++ b/app/db/src/app/common/hashtable.ts @@ -0,0 +1,3 @@ +export interface HashTable { + readonly [key: string]: T; +} diff --git a/app/db/src/app/common/list-direction.ts b/app/db/src/app/common/list-direction.ts new file mode 100644 index 00000000..065b7126 --- /dev/null +++ b/app/db/src/app/common/list-direction.ts @@ -0,0 +1,4 @@ +export enum ListDirection { + Up, + Down, +} diff --git a/app/db/src/app/models/app-state.ts b/app/db/src/app/models/app-state.ts index e2026e89..19a3b2d0 100644 --- a/app/db/src/app/models/app-state.ts +++ b/app/db/src/app/models/app-state.ts @@ -1,15 +1,19 @@ import { IStorable } from './storable'; +import { NoteItem } from './note-state'; +import { BiblePassageResult } from './passage-state'; +import { StrongsResult } from './strongs-state'; +import { WordLookupResult } from './words-state'; export interface AppState { readonly currentSavedPage: SavedPage; readonly savedPages: IStorable; readonly notes: IStorable; + readonly displaySettings: IStorable; readonly savedPagesLoaded: boolean; readonly mainPages: readonly Page[]; readonly cards: readonly CardItem[]; readonly autocomplete: readonly string[]; readonly error: Error; - readonly displaySettings: IStorable; readonly cardIcons: CardIcons; readonly user: User; } @@ -59,12 +63,6 @@ export type OpenData = { from_search_bar: boolean; }; -export interface HashTable { - readonly [key: string]: T; -} - -//#region Pages and Cards - export interface SavedPage { readonly queries: readonly CardItem[]; readonly title: string; @@ -85,133 +83,3 @@ export class Page { readonly icon?: string; readonly route: string; } - -//#endregion - -//#region Passage - -export interface BiblePassageResult { - readonly cs: readonly BibleParagraphPassage[]; - readonly testament: string; - readonly ref: string; -} - -export interface BibleParagraph { - readonly p: Paragraph; - readonly vss: readonly BibleVerse[]; -} - -export interface BibleParagraphPassage { - readonly ch: number; - readonly paras: readonly BibleParagraph[]; -} - -export interface BiblePassage { - readonly ch: number; - readonly vss: readonly BibleVerse[]; -} - -export interface BibleVerse { - readonly v: number; - readonly w: readonly [ - { - readonly t: string; - readonly s: string; - } - ]; -} - -export interface Paragraph { - readonly h: string; - readonly p: number; -} - -//#endregion - -//#region Strongs - -export type DictionaryType = 'heb' | 'grk'; - -export interface StrongsResult { - readonly prefix: string; - readonly sn: number; - readonly def: StrongsDefinition; - readonly rmac: RMACDefinition; - readonly crossrefs: StrongsCrossReference; - readonly rmaccode: string; -} - -export interface StrongsDefinition { - readonly n: number; - readonly i: string; - readonly tr: string; - readonly de: readonly StrongsDefinitionPart[]; - readonly lemma: string; - readonly p: string; -} - -export interface StrongsDefinitionPart { - readonly sn: string; - readonly w: string; -} -export interface StrongsCrossReference { - readonly id: string; // strongs id H1|G1 - readonly t: string; // strongs testament grk|heb - readonly d: string; // strongs word/data definition Aaron {ah-ar-ohn'} - readonly ss: readonly [ - { - readonly w: string; // translated word - readonly rs: readonly [ - { - readonly r: string; // reference - } - ]; - } - ]; -} - -export interface RMACDefinition { - readonly id: string; - readonly d: readonly string[]; -} - -export interface RMACCrossReference { - readonly i: string; - readonly r: string; -} - -//#endregion - -//#region Word Search - -export interface WordLookupResult { - readonly refs: readonly string[]; - readonly word: string; -} - -export interface IndexResult { - readonly r: readonly string[]; - readonly w: string; -} - -export interface WordToStem { - readonly w: string; - readonly s: string; -} - -//#endregion - -//#region Notes - -export type NoteItem = { - // The Note id - readonly id: string; - // A note title. - readonly title: string; - // An optional cross reference to a bible passage. - readonly xref: string | null; - // The content of the note styled as markdown. - readonly content: string; -}; - -//#endregion diff --git a/app/db/src/app/models/note-state.ts b/app/db/src/app/models/note-state.ts new file mode 100644 index 00000000..284f235e --- /dev/null +++ b/app/db/src/app/models/note-state.ts @@ -0,0 +1,10 @@ +export type NoteItem = { + // The Note id + readonly id: string; + // A note title. + readonly title: string; + // An optional cross reference to a bible passage. + readonly xref: string | null; + // The content of the note styled as markdown. + readonly content: string; +}; diff --git a/app/db/src/app/models/passage-state.ts b/app/db/src/app/models/passage-state.ts new file mode 100644 index 00000000..6fff07a8 --- /dev/null +++ b/app/db/src/app/models/passage-state.ts @@ -0,0 +1,35 @@ +export interface BiblePassageResult { + readonly cs: readonly BibleParagraphPassage[]; + readonly testament: string; + readonly ref: string; +} + +export interface BibleParagraph { + readonly p: Paragraph; + readonly vss: readonly BibleVerse[]; +} + +export interface BibleParagraphPassage { + readonly ch: number; + readonly paras: readonly BibleParagraph[]; +} + +export interface BiblePassage { + readonly ch: number; + readonly vss: readonly BibleVerse[]; +} + +export interface BibleVerse { + readonly v: number; + readonly w: readonly [ + { + readonly t: string; + readonly s: string; + } + ]; +} + +export interface Paragraph { + readonly h: string; + readonly p: number; +} diff --git a/app/db/src/app/models/strongs-state.ts b/app/db/src/app/models/strongs-state.ts new file mode 100644 index 00000000..df8170c0 --- /dev/null +++ b/app/db/src/app/models/strongs-state.ts @@ -0,0 +1,49 @@ +export type StrongsDictionary = 'heb' | 'grk'; + +export interface StrongsResult { + readonly prefix: string; + readonly sn: number; + readonly def: StrongsDefinition; + readonly rmac: RMACDefinition; + readonly crossrefs: StrongsCrossReference; + readonly rmaccode: string; +} + +export interface StrongsDefinition { + readonly n: number; + readonly i: string; + readonly tr: string; + readonly de: readonly StrongsDefinitionPart[]; + readonly lemma: string; + readonly p: string; +} + +export interface StrongsDefinitionPart { + readonly sn: string; + readonly w: string; +} +export interface StrongsCrossReference { + readonly id: string; // strongs id H1|G1 + readonly t: string; // strongs testament grk|heb + readonly d: string; // strongs word/data definition Aaron {ah-ar-ohn'} + readonly ss: readonly [ + { + readonly w: string; // translated word + readonly rs: readonly [ + { + readonly r: string; // reference + } + ]; + } + ]; +} + +export interface RMACDefinition { + readonly id: string; + readonly d: readonly string[]; +} + +export interface RMACCrossReference { + readonly i: string; + readonly r: string; +} diff --git a/app/db/src/app/models/words-state.ts b/app/db/src/app/models/words-state.ts new file mode 100644 index 00000000..f392dbe3 --- /dev/null +++ b/app/db/src/app/models/words-state.ts @@ -0,0 +1,14 @@ +export interface WordLookupResult { + readonly refs: readonly string[]; + readonly word: string; +} + +export interface IndexResult { + readonly r: readonly string[]; + readonly w: string; +} + +export interface WordToStem { + readonly w: string; + readonly s: string; +} diff --git a/app/db/src/app/search/components/note/note-card.component.html b/app/db/src/app/search/components/note/note-card.component.html index 795fbe44..171c3e29 100644 --- a/app/db/src/app/search/components/note/note-card.component.html +++ b/app/db/src/app/search/components/note/note-card.component.html @@ -58,6 +58,14 @@ save Add Card to Saved Page + + diff --git a/app/db/src/app/search/components/note/note-card.component.ts b/app/db/src/app/search/components/note/note-card.component.ts index 44f6ca5c..10d8e194 100644 --- a/app/db/src/app/search/components/note/note-card.component.ts +++ b/app/db/src/app/search/components/note/note-card.component.ts @@ -3,7 +3,7 @@ import { MatDialog } from '@angular/material/dialog'; import { NoteEditModalComponent } from './edit-modal/note-edit-modal.component'; import { CardComponent } from '../../../common/components/card.component'; import { AppService } from '../../../services/app.service'; -import { NoteItem } from 'src/app/models/app-state'; +import { NoteItem } from '../../../models/note-state'; @Component({ selector: 'app-note-card', @@ -13,8 +13,8 @@ import { NoteItem } from 'src/app/models/app-state'; export class NoteCardComponent extends CardComponent { @ViewChild('note') noteElement: ElementRef; - constructor(protected elementRef: ElementRef, private appService: AppService, public dialog: MatDialog) { - super(elementRef, dialog); + constructor(protected elementRef: ElementRef, protected appService: AppService, public dialog: MatDialog) { + super(elementRef, dialog, appService); this.icon$ = appService.select((state) => state.cardIcons.note); } diff --git a/app/db/src/app/search/components/passage/passage-card.component.html b/app/db/src/app/search/components/passage/passage-card.component.html index 9a9be7f8..22344127 100644 --- a/app/db/src/app/search/components/passage/passage-card.component.html +++ b/app/db/src/app/search/components/passage/passage-card.component.html @@ -98,6 +98,14 @@ save Add Card to Saved Page + + diff --git a/app/db/src/app/search/components/passage/passage-card.component.ts b/app/db/src/app/search/components/passage/passage-card.component.ts index 389d9300..b2cde46a 100644 --- a/app/db/src/app/search/components/passage/passage-card.component.ts +++ b/app/db/src/app/search/components/passage/passage-card.component.ts @@ -3,7 +3,7 @@ import { MatDialog } from '@angular/material/dialog'; import { BibleReference } from '../../../common/bible-reference'; import { AppService } from '../../../services/app.service'; import { CardComponent } from '../../../common/components/card.component'; -import { Paragraph } from '../../../models/app-state'; +import { Paragraph } from '../../../models/passage-state'; import { StrongsModalComponent } from '../strongs/modal/strongs-modal.component'; @Component({ @@ -28,8 +28,8 @@ export class PassageCardComponent extends CardComponent implements OnInit { @ViewChild('passage') passageElement: ElementRef; - constructor(protected elementRef: ElementRef, private appService: AppService, public dialog: MatDialog) { - super(elementRef, dialog); + constructor(protected elementRef: ElementRef, protected appService: AppService, public dialog: MatDialog) { + super(elementRef, dialog, appService); this.icon$ = appService.select((state) => state.cardIcons.passage); } diff --git a/app/db/src/app/search/components/strongs/card/strongs-card.component.html b/app/db/src/app/search/components/strongs/card/strongs-card.component.html index 19825fd4..fa2b4025 100644 --- a/app/db/src/app/search/components/strongs/card/strongs-card.component.html +++ b/app/db/src/app/search/components/strongs/card/strongs-card.component.html @@ -46,6 +46,14 @@ save Add Card to Saved Page + + diff --git a/app/db/src/app/search/components/strongs/card/strongs-card.component.ts b/app/db/src/app/search/components/strongs/card/strongs-card.component.ts index 31143110..5dfe5910 100644 --- a/app/db/src/app/search/components/strongs/card/strongs-card.component.ts +++ b/app/db/src/app/search/components/strongs/card/strongs-card.component.ts @@ -16,7 +16,7 @@ export class StrongsCardComponent extends CardComponent { @ViewChild('strongs') strongsElement: ElementRef; constructor(protected elementRef: ElementRef, protected appService: AppService, protected dialog: MatDialog) { - super(elementRef, dialog); + super(elementRef, dialog, appService); this.icon$ = appService.select((state) => state.cardIcons.strongs); this.addSubscription( this.appService.state$.subscribe((state) => { diff --git a/app/db/src/app/search/components/words/words-card.component.html b/app/db/src/app/search/components/words/words-card.component.html index 3800e4cc..ef182d2d 100644 --- a/app/db/src/app/search/components/words/words-card.component.html +++ b/app/db/src/app/search/components/words/words-card.component.html @@ -42,11 +42,18 @@ content_copy Copy References - + + diff --git a/app/db/src/app/search/components/words/words-card.component.ts b/app/db/src/app/search/components/words/words-card.component.ts index bbd57ec4..92b29d99 100644 --- a/app/db/src/app/search/components/words/words-card.component.ts +++ b/app/db/src/app/search/components/words/words-card.component.ts @@ -1,7 +1,7 @@ import { Component, ElementRef, ViewChild } from '@angular/core'; import { AppService } from '../../../services/app.service'; import { CardComponent } from '../../../common/components/card.component'; -import { WordLookupResult } from 'src/app/models/app-state'; +import { WordLookupResult } from '../../../models/words-state'; import { MatDialog } from '@angular/material/dialog'; import { BibleReference } from 'src/app/common/bible-reference'; @@ -14,12 +14,8 @@ import { BibleReference } from 'src/app/common/bible-reference'; export class WordsCardComponent extends CardComponent { @ViewChild('words') wordsElement: ElementRef; - constructor( - protected elementRef: ElementRef, - private appService: AppService, - public dialog: MatDialog - ) { - super(elementRef, dialog); + constructor(protected elementRef: ElementRef, protected appService: AppService, public dialog: MatDialog) { + super(elementRef, dialog, appService); this.icon$ = appService.select((state) => state.cardIcons.words); } @@ -28,11 +24,7 @@ export class WordsCardComponent extends CardComponent { BibleReference.makePassageFromReferenceKey(ref) ); - const html = refs - .map( - (ref) => `${ref}` - ) - .join(', '); + const html = refs.map((ref) => `${ref}`).join(', '); const text = refs.join(', '); this.copyToClip(text, html); } diff --git a/app/db/src/app/services/app.service.ts b/app/db/src/app/services/app.service.ts index 358c60f1..f492c965 100644 --- a/app/db/src/app/services/app.service.ts +++ b/app/db/src/app/services/app.service.ts @@ -1,28 +1,6 @@ import { HttpClient } from '@angular/common/http'; import { Injectable } from '@angular/core'; -import { - AppState, - SavedPage, - HashTable, - Paragraph, - BiblePassage, - BibleVerse, - Error, - BibleParagraph, - BibleParagraphPassage, - CardItem, - DictionaryType, - StrongsDefinition, - StrongsCrossReference, - RMACCrossReference, - RMACDefinition, - WordLookupResult, - WordToStem, - IndexResult, - NoteItem, - DisplaySettings, - User, -} from '../models/app-state'; +import { AppState, SavedPage, Error, CardItem, DisplaySettings, User } from '../models/app-state'; import { Section, BibleReference } from '../common/bible-reference'; import { PageTitles, PageIcons } from '../constants'; import { createStateService } from '../common/state-service'; @@ -30,6 +8,18 @@ import { UUID } from 'angular2-uuid'; import { StorageMap } from '@ngx-pwa/local-storage'; import { AngularFireDatabase } from '@angular/fire/database'; import { IStorable, Storable } from '../models/storable'; +import { NoteItem } from '../models/note-state'; +import { Paragraph, BiblePassage, BibleVerse, BibleParagraphPassage, BibleParagraph } from '../models/passage-state'; +import { + StrongsDefinition, + StrongsCrossReference, + RMACCrossReference, + RMACDefinition, + StrongsDictionary, +} from '../models/strongs-state'; +import { WordToStem, IndexResult, WordLookupResult } from '../models/words-state'; +import { HashTable } from '../common/hashtable'; +import { ListDirection } from '../common/list-direction'; const initialState: AppState = { user: null, @@ -123,6 +113,11 @@ type AppAction = type: 'REMOVE_CARD'; card: CardItem; } + | { + type: 'MOVE_CARD'; + card: CardItem; + direction: ListDirection; + } | { type: 'UPDATE_ERROR'; error: Error; @@ -351,6 +346,32 @@ function reducer(state: AppState, action: AppAction): AppState { cards: [...state.cards.filter((c) => c !== action.card)], }; } + case 'MOVE_CARD': { + let cards = []; + const idx = state.cards.indexOf(action.card); + + if ( + (idx === 0 && action.direction === ListDirection.Up) || // can't go up if you're at the top + (idx === state.cards.length - 1 && action.direction === ListDirection.Down) // can't go down if you're at the bottom + ) { + // you can't go up. + return state; + } + + const before = state.cards.slice(0, idx); + const after = state.cards.slice(idx + 1); + + if (action.direction === ListDirection.Down) { + cards = [...before, after[0], action.card, ...after.slice(1)]; + } else { + cards = [...before.slice(0, before.length - 1), action.card, before[before.length - 1], ...after]; + } + + return { + ...state, + cards, + }; + } case 'SET_USER': { return { ...state, @@ -515,7 +536,13 @@ export class AppService extends createStateService(reducer, initialState) { card, }); } - + moveCard(card: CardItem, direction: ListDirection) { + this.dispatch({ + type: 'MOVE_CARD', + card, + direction, + }); + } dispatchError(msg: string) { this.dispatch({ type: 'UPDATE_ERROR', @@ -651,7 +678,7 @@ export class AppService extends createStateService(reducer, initialState) { //#region Strongs - async getStrongs(strongsNumber: string, dict: DictionaryType, nextToItem: CardItem = null) { + async getStrongs(strongsNumber: string, dict: StrongsDictionary, nextToItem: CardItem = null) { const card = await this.getStrongsCard(strongsNumber, dict); this.dispatch({