diff --git a/app/db/.editorconfig b/app/db/.editorconfig index 7e71164d..99792db2 100644 --- a/app/db/.editorconfig +++ b/app/db/.editorconfig @@ -15,7 +15,7 @@ end_of_line = lf # this file has a need for arbitrarily long lines, so we exempt this here. [bible-reference.ts] -max_line_length = off +max_line_length = 9999 [*.md] max_line_length = off diff --git a/app/db/README.md b/app/db/README.md index 25926b4a..12456284 100644 --- a/app/db/README.md +++ b/app/db/README.md @@ -28,30 +28,36 @@ To get more help on the Angular CLI use `ng help` or go check out the [Angular C # Punch List -- Swipe to close -- Drop down menu items for move card up/down - Options to merge references \*\* - Merge if overlap - Merge if contains -- Font Size + - Merge if equals + - Don't merge - Page Admin \*\* - Delete Page - - Show page and list of card titles + - Show pages and list of card titles for each page in expansion panel - Remove card from page - - Make page public (private edit only) + - Make page public (private edit only) [available only when logged in] - Notes Admin \*\* - - Edit Note - - Delete Note + - List notes by title + - Edit Note + - Delete Note - Create Note - - Note: Add Cross References - Note: Auto link passages using markdown link syntax -- Passage - - Show Note Cross References \*\* -- Login - Help Page +- Incorporate Jacob's Geo Work +- Android and IOS mobile apps with Ionic Capactor +- Test note persistence +- Test note search +- remove old ionic project +- setup CI/CD +- Edit card query + +## Optionally for Future + +- Swipe to close +- Change Card Qry option in drop down - Settings for theme - Custom Colors for Light/Dark modes - Dark / Light / NightLight Mode -- Merge saved pages lists when unlogged in -> login -- Incorporate Jacob's Geo Work -- Android and IOS mobile apps with Ionic Capactor +- Make card icons configurable (for future) diff --git a/app/db/angular.json b/app/db/angular.json index 8de046db..c68e5a3d 100644 --- a/app/db/angular.json +++ b/app/db/angular.json @@ -23,14 +23,15 @@ "polyfills": "src/polyfills.ts", "tsConfig": "tsconfig.app.json", "aot": true, - "assets": [ - "src/favicon.ico", - "src/assets" - ], - "styles": [ - "src/styles.scss" - ], - "scripts": [] + "assets": ["src/favicon.ico", "src/assets"], + "styles": ["src/styles.scss"], + "scripts": [], + "allowedCommonJsDependencies": [ + "firebase", + "@firebase/app", + "@firebase/auth", + "@firebase/database" + ] }, "configurations": { "production": { @@ -87,13 +88,8 @@ "polyfills": "src/polyfills.ts", "tsConfig": "tsconfig.spec.json", "karmaConfig": "karma.conf.js", - "assets": [ - "src/favicon.ico", - "src/assets" - ], - "styles": [ - "src/styles.scss" - ], + "assets": ["src/favicon.ico", "src/assets"], + "styles": ["src/styles.scss"], "scripts": [] } }, @@ -105,9 +101,7 @@ "tsconfig.spec.json", "e2e/tsconfig.json" ], - "exclude": [ - "**/node_modules/**" - ] + "exclude": ["**/node_modules/**"] } }, "e2e": { @@ -130,4 +124,4 @@ } }, "defaultProject": "db" -} \ No newline at end of file +} diff --git a/app/db/package.json b/app/db/package.json index bbd44cdc..5bbfed43 100644 --- a/app/db/package.json +++ b/app/db/package.json @@ -4,7 +4,7 @@ "scripts": { "ng": "ng", "start": "ng serve", - "build": "ng build", + "build": "ng build --prod", "test": "ng test", "lint": "ng lint", "e2e": "ng e2e" diff --git a/app/db/src/app/app.component.ts b/app/db/src/app/app.component.ts index 662023ba..f90fa13e 100644 --- a/app/db/src/app/app.component.ts +++ b/app/db/src/app/app.component.ts @@ -40,13 +40,12 @@ export class AppComponent extends SubscriberComponent implements AfterViewInit { this.storageService.initSavedPages(); this.storageService.initDisplaySettings(); + this.storageService.initNotes(); this.addSubscription( this.error$.subscribe((err) => { if (err) { - this.snackBar.open(`Oh no! ${err.msg}`, 'Error', { - duration: 4 * 1000, - }); + this.snackBar.open(`Oh no! ${err.msg}`, 'Dismiss Error'); } }) ); diff --git a/app/db/src/app/common/bible-reference.ts b/app/db/src/app/common/bible-reference.ts index 03f84250..20a16fa9 100644 --- a/app/db/src/app/common/bible-reference.ts +++ b/app/db/src/app/common/bible-reference.ts @@ -19,59 +19,7 @@ export class BibleReference { longName: 'Book of Genesis', bookNumber: 1, lastChapter: 66, - chapters: [ - 0, - 31, - 25, - 24, - 26, - 32, - 22, - 24, - 22, - 29, - 32, - 32, - 20, - 18, - 24, - 21, - 16, - 27, - 33, - 38, - 18, - 34, - 24, - 20, - 67, - 34, - 35, - 46, - 22, - 35, - 43, - 55, - 32, - 20, - 31, - 29, - 43, - 36, - 30, - 23, - 23, - 57, - 38, - 34, - 34, - 28, - 34, - 31, - 22, - 33, - 26, - ], + chapters: [0, 31, 25, 24, 26, 32, 22, 24, 22, 29, 32, 32, 20, 18, 24, 21, 16, 27, 33, 38, 18, 34, 24, 20, 67, 34, 35, 46, 22, 35, 43, 55, 32, 20, 31, 29, 43, 36, 30, 23, 23, 57, 38, 34, 34, 28, 34, 31, 22, 33, 26], }, { bookNumber: 2, @@ -79,49 +27,7 @@ export class BibleReference { name: 'Exodus', longName: 'Book of Exodus', lastChapter: 40, - chapters: [ - 0, - 22, - 25, - 22, - 31, - 23, - 30, - 25, - 32, - 35, - 29, - 10, - 51, - 22, - 31, - 27, - 36, - 16, - 27, - 25, - 26, - 36, - 31, - 33, - 18, - 40, - 37, - 21, - 43, - 46, - 38, - 18, - 35, - 23, - 35, - 35, - 38, - 29, - 31, - 43, - 38, - ], + chapters: [0, 22, 25, 22, 31, 23, 30, 25, 32, 35, 29, 10, 51, 22, 31, 27, 36, 16, 27, 25, 26, 36, 31, 33, 18, 40, 37, 21, 43, 46, 38, 18, 35, 23, 35, 35, 38, 29, 31, 43, 38], }, { bookNumber: 3, @@ -129,36 +35,7 @@ export class BibleReference { abbreviation: 'Lev', longName: 'Leviticus', lastChapter: 27, - chapters: [ - 0, - 17, - 16, - 17, - 35, - 19, - 30, - 38, - 36, - 24, - 20, - 47, - 8, - 59, - 57, - 33, - 34, - 16, - 30, - 37, - 27, - 24, - 33, - 44, - 23, - 55, - 46, - 34, - ], + chapters: [0, 17, 16, 17, 35, 19, 30, 38, 36, 24, 20, 47, 8, 59, 57, 33, 34, 16, 30, 37, 27, 24, 33, 44, 23, 55, 46, 34], }, { bookNumber: 4, @@ -166,45 +43,7 @@ export class BibleReference { abbreviation: 'Num', longName: 'Book of Numbers', lastChapter: 36, - chapters: [ - 0, - 54, - 34, - 51, - 49, - 31, - 27, - 89, - 26, - 23, - 36, - 35, - 16, - 33, - 45, - 41, - 50, - 13, - 32, - 22, - 29, - 35, - 41, - 30, - 25, - 18, - 65, - 23, - 31, - 40, - 16, - 54, - 42, - 56, - 29, - 34, - 13, - ], + chapters: [0, 54, 34, 51, 49, 31, 27, 89, 26, 23, 36, 35, 16, 33, 45, 41, 50, 13, 32, 22, 29, 35, 41, 30, 25, 18, 65, 23, 31, 40, 16, 54, 42, 56, 29, 34, 13], }, { bookNumber: 5, @@ -212,43 +51,7 @@ export class BibleReference { abbreviation: 'Deut', longName: 'Book of Deuteronomy', lastChapter: 34, - chapters: [ - 0, - 46, - 37, - 29, - 49, - 33, - 25, - 26, - 20, - 29, - 22, - 32, - 32, - 18, - 29, - 23, - 22, - 20, - 22, - 21, - 20, - 23, - 30, - 25, - 22, - 19, - 19, - 26, - 68, - 29, - 20, - 30, - 52, - 29, - 12, - ], + chapters: [0, 46, 37, 29, 49, 33, 25, 26, 20, 29, 22, 32, 32, 18, 29, 23, 22, 20, 22, 21, 20, 23, 30, 25, 22, 19, 19, 26, 68, 29, 20, 30, 52, 29, 12], }, { bookNumber: 6, @@ -256,33 +59,7 @@ export class BibleReference { abbreviation: 'Josh', longName: 'Book of Joshua', lastChapter: 24, - chapters: [ - 0, - 18, - 24, - 17, - 24, - 15, - 27, - 26, - 35, - 27, - 43, - 23, - 24, - 33, - 15, - 63, - 10, - 18, - 28, - 51, - 9, - 45, - 34, - 16, - 33, - ], + chapters: [0, 18, 24, 17, 24, 15, 27, 26, 35, 27, 43, 23, 24, 33, 15, 63, 10, 18, 28, 51, 9, 45, 34, 16, 33], }, { bookNumber: 7, @@ -290,30 +67,7 @@ export class BibleReference { abbreviation: 'Jud', longName: 'Book of Judges', lastChapter: 21, - chapters: [ - 0, - 36, - 23, - 31, - 24, - 31, - 40, - 25, - 35, - 57, - 18, - 40, - 15, - 25, - 20, - 20, - 31, - 13, - 31, - 30, - 48, - 25, - ], + chapters: [0, 36, 23, 31, 24, 31, 40, 25, 35, 57, 18, 40, 15, 25, 20, 20, 31, 13, 31, 30, 48, 25], }, { bookNumber: 8, @@ -329,40 +83,7 @@ export class BibleReference { abbreviation: '1 Sam', longName: 'First Book of Samuel', lastChapter: 31, - chapters: [ - 0, - 28, - 36, - 21, - 22, - 12, - 21, - 17, - 22, - 27, - 27, - 15, - 25, - 23, - 52, - 35, - 23, - 58, - 30, - 24, - 42, - 15, - 23, - 29, - 22, - 44, - 25, - 12, - 25, - 11, - 31, - 13, - ], + chapters: [0, 28, 36, 21, 22, 12, 21, 17, 22, 27, 27, 15, 25, 23, 52, 35, 23, 58, 30, 24, 42, 15, 23, 29, 22, 44, 25, 12, 25, 11, 31, 13], }, { bookNumber: 10, @@ -370,33 +91,7 @@ export class BibleReference { abbreviation: '2 Sam', longName: 'Second Book of Samuel', lastChapter: 24, - chapters: [ - 0, - 27, - 32, - 39, - 12, - 25, - 23, - 29, - 18, - 13, - 19, - 27, - 31, - 39, - 33, - 37, - 23, - 29, - 33, - 43, - 26, - 22, - 51, - 39, - 25, - ], + chapters: [0, 27, 32, 39, 12, 25, 23, 29, 18, 13, 19, 27, 31, 39, 33, 37, 23, 29, 33, 43, 26, 22, 51, 39, 25], }, { bookNumber: 11, @@ -404,31 +99,7 @@ export class BibleReference { abbreviation: '1 Kng', longName: 'First Book of Kings', lastChapter: 22, - chapters: [ - 0, - 53, - 46, - 28, - 34, - 18, - 38, - 51, - 66, - 28, - 29, - 43, - 33, - 34, - 31, - 34, - 34, - 24, - 46, - 21, - 43, - 29, - 53, - ], + chapters: [0, 53, 46, 28, 34, 18, 38, 51, 66, 28, 29, 43, 33, 34, 31, 34, 34, 24, 46, 21, 43, 29, 53], }, { bookNumber: 12, @@ -436,34 +107,7 @@ export class BibleReference { abbreviation: '2 Kng', longName: 'Second Book of Kings', lastChapter: 25, - chapters: [ - 0, - 18, - 25, - 27, - 44, - 27, - 33, - 20, - 29, - 37, - 36, - 21, - 21, - 25, - 29, - 38, - 20, - 41, - 37, - 37, - 21, - 26, - 20, - 37, - 20, - 30, - ], + chapters: [0, 18, 25, 27, 44, 27, 33, 20, 29, 37, 36, 21, 21, 25, 29, 38, 20, 41, 37, 37, 21, 26, 20, 37, 20, 30], }, { bookNumber: 13, @@ -471,38 +115,7 @@ export class BibleReference { abbreviation: '1 Chr', longName: 'First Book of Chronicles', lastChapter: 29, - chapters: [ - 0, - 54, - 55, - 24, - 43, - 26, - 81, - 40, - 40, - 44, - 14, - 47, - 40, - 14, - 17, - 29, - 43, - 27, - 17, - 19, - 8, - 30, - 19, - 32, - 31, - 31, - 32, - 34, - 21, - 30, - ], + chapters: [0, 54, 55, 24, 43, 26, 81, 40, 40, 44, 14, 47, 40, 14, 17, 29, 43, 27, 17, 19, 8, 30, 19, 32, 31, 31, 32, 34, 21, 30], }, { bookNumber: 14, @@ -510,45 +123,7 @@ export class BibleReference { abbreviation: '2 Chr', longName: 'Second Book of Chronicles', lastChapter: 36, - chapters: [ - 0, - 17, - 18, - 17, - 22, - 14, - 42, - 22, - 18, - 31, - 19, - 23, - 16, - 22, - 15, - 19, - 14, - 19, - 34, - 11, - 37, - 20, - 12, - 21, - 27, - 28, - 23, - 9, - 27, - 36, - 27, - 21, - 33, - 25, - 33, - 27, - 23, - ], + chapters: [0, 17, 18, 17, 22, 14, 42, 22, 18, 31, 19, 23, 16, 22, 15, 19, 14, 19, 34, 11, 37, 20, 12, 21, 27, 28, 23, 9, 27, 36, 27, 21, 33, 25, 33, 27, 23], }, { bookNumber: 15, @@ -580,51 +155,7 @@ export class BibleReference { abbreviation: 'Job', longName: 'Book of Job', lastChapter: 42, - chapters: [ - 0, - 22, - 13, - 26, - 21, - 27, - 30, - 21, - 22, - 35, - 22, - 20, - 25, - 28, - 22, - 35, - 22, - 16, - 21, - 29, - 29, - 34, - 30, - 17, - 25, - 6, - 14, - 23, - 28, - 25, - 31, - 40, - 22, - 33, - 37, - 16, - 33, - 24, - 41, - 30, - 24, - 34, - 17, - ], + chapters: [0, 22, 13, 26, 21, 27, 30, 21, 22, 35, 22, 20, 25, 28, 22, 35, 22, 16, 21, 29, 29, 34, 30, 17, 25, 6, 14, 23, 28, 25, 31, 40, 22, 33, 37, 16, 33, 24, 41, 30, 24, 34, 17], }, { bookNumber: 19, @@ -632,159 +163,7 @@ export class BibleReference { abbreviation: 'Psalm', longName: 'Book of Psalms', lastChapter: 150, - chapters: [ - 0, - 6, - 12, - 8, - 8, - 12, - 10, - 17, - 9, - 20, - 18, - 7, - 8, - 6, - 7, - 5, - 11, - 15, - 50, - 14, - 9, - 13, - 31, - 6, - 10, - 22, - 12, - 14, - 9, - 11, - 12, - 24, - 11, - 22, - 22, - 28, - 12, - 40, - 22, - 13, - 17, - 13, - 11, - 5, - 26, - 17, - 11, - 9, - 14, - 20, - 23, - 19, - 9, - 6, - 7, - 23, - 13, - 11, - 11, - 17, - 12, - 8, - 12, - 11, - 10, - 13, - 20, - 7, - 35, - 36, - 5, - 24, - 20, - 28, - 23, - 10, - 12, - 20, - 72, - 13, - 19, - 16, - 8, - 18, - 12, - 13, - 17, - 7, - 18, - 52, - 17, - 16, - 15, - 5, - 23, - 11, - 13, - 12, - 9, - 9, - 5, - 8, - 28, - 22, - 35, - 45, - 48, - 43, - 13, - 31, - 7, - 10, - 10, - 9, - 8, - 18, - 19, - 2, - 29, - 176, - 7, - 8, - 9, - 4, - 8, - 5, - 6, - 5, - 6, - 8, - 8, - 3, - 18, - 3, - 3, - 21, - 26, - 9, - 8, - 24, - 13, - 10, - 7, - 12, - 15, - 21, - 10, - 20, - 14, - 9, - 6, - ], + chapters: [0, 6, 12, 8, 8, 12, 10, 17, 9, 20, 18, 7, 8, 6, 7, 5, 11, 15, 50, 14, 9, 13, 31, 6, 10, 22, 12, 14, 9, 11, 12, 24, 11, 22, 22, 28, 12, 40, 22, 13, 17, 13, 11, 5, 26, 17, 11, 9, 14, 20, 23, 19, 9, 6, 7, 23, 13, 11, 11, 17, 12, 8, 12, 11, 10, 13, 20, 7, 35, 36, 5, 24, 20, 28, 23, 10, 12, 20, 72, 13, 19, 16, 8, 18, 12, 13, 17, 7, 18, 52, 17, 16, 15, 5, 23, 11, 13, 12, 9, 9, 5, 8, 28, 22, 35, 45, 48, 43, 13, 31, 7, 10, 10, 9, 8, 18, 19, 2, 29, 176, 7, 8, 9, 4, 8, 5, 6, 5, 6, 8, 8, 3, 18, 3, 3, 21, 26, 9, 8, 24, 13, 10, 7, 12, 15, 21, 10, 20, 14, 9, 6], }, { bookNumber: 20, @@ -792,40 +171,7 @@ export class BibleReference { abbreviation: 'Prov', longName: 'Book of Proverbs', lastChapter: 31, - chapters: [ - 0, - 33, - 22, - 35, - 27, - 23, - 35, - 27, - 36, - 18, - 32, - 31, - 28, - 25, - 35, - 33, - 33, - 28, - 24, - 29, - 30, - 31, - 29, - 35, - 34, - 28, - 28, - 27, - 28, - 27, - 33, - 31, - ], + chapters: [0, 33, 22, 35, 27, 23, 35, 27, 36, 18, 32, 31, 28, 25, 35, 33, 33, 28, 24, 29, 30, 31, 29, 35, 34, 28, 28, 27, 28, 27, 33, 31], }, { bookNumber: 21, @@ -849,75 +195,7 @@ export class BibleReference { abbreviation: 'Isa', longName: 'Book of Isaiah', lastChapter: 66, - chapters: [ - 0, - 31, - 22, - 26, - 6, - 30, - 13, - 25, - 22, - 21, - 34, - 16, - 6, - 22, - 32, - 9, - 14, - 14, - 7, - 25, - 6, - 17, - 25, - 18, - 23, - 12, - 21, - 13, - 29, - 24, - 33, - 9, - 20, - 24, - 17, - 10, - 22, - 38, - 22, - 8, - 31, - 29, - 25, - 28, - 28, - 25, - 13, - 15, - 22, - 26, - 11, - 23, - 15, - 12, - 17, - 13, - 12, - 21, - 14, - 21, - 22, - 11, - 12, - 19, - 12, - 25, - 24, - ], + chapters: [0, 31, 22, 26, 6, 30, 13, 25, 22, 21, 34, 16, 6, 22, 32, 9, 14, 14, 7, 25, 6, 17, 25, 18, 23, 12, 21, 13, 29, 24, 33, 9, 20, 24, 17, 10, 22, 38, 22, 8, 31, 29, 25, 28, 28, 25, 13, 15, 22, 26, 11, 23, 15, 12, 17, 13, 12, 21, 14, 21, 22, 11, 12, 19, 12, 25, 24], }, { bookNumber: 24, @@ -925,61 +203,7 @@ export class BibleReference { abbreviation: 'Jer', longName: 'Book of Jeremiah', lastChapter: 52, - chapters: [ - 0, - 19, - 37, - 25, - 31, - 31, - 30, - 34, - 22, - 26, - 25, - 23, - 17, - 27, - 22, - 21, - 21, - 27, - 23, - 15, - 18, - 14, - 30, - 40, - 10, - 38, - 24, - 22, - 17, - 32, - 24, - 40, - 44, - 26, - 22, - 19, - 32, - 21, - 28, - 18, - 16, - 18, - 22, - 13, - 30, - 5, - 28, - 7, - 47, - 39, - 46, - 64, - 34, - ], + chapters: [0, 19, 37, 25, 31, 31, 30, 34, 22, 26, 25, 23, 17, 27, 22, 21, 21, 27, 23, 15, 18, 14, 30, 40, 10, 38, 24, 22, 17, 32, 24, 40, 44, 26, 22, 19, 32, 21, 28, 18, 16, 18, 22, 13, 30, 5, 28, 7, 47, 39, 46, 64, 34], }, { bookNumber: 25, @@ -995,57 +219,7 @@ export class BibleReference { abbreviation: 'Eze', longName: 'Book of Ezekiel', lastChapter: 48, - chapters: [ - 0, - 28, - 10, - 27, - 17, - 17, - 14, - 27, - 18, - 11, - 22, - 25, - 28, - 23, - 23, - 8, - 63, - 24, - 32, - 14, - 49, - 32, - 31, - 49, - 27, - 17, - 21, - 36, - 26, - 21, - 26, - 18, - 32, - 33, - 31, - 15, - 38, - 28, - 23, - 29, - 49, - 26, - 20, - 27, - 31, - 25, - 24, - 23, - 35, - ], + chapters: [0, 28, 10, 27, 17, 17, 14, 27, 18, 11, 22, 25, 28, 23, 23, 8, 63, 24, 32, 14, 49, 32, 31, 49, 27, 17, 21, 36, 26, 21, 26, 18, 32, 33, 31, 15, 38, 28, 23, 29, 49, 26, 20, 27, 31, 25, 24, 23, 35], }, { bookNumber: 27, @@ -1157,37 +331,7 @@ export class BibleReference { abbreviation: 'Matt', longName: 'Gospel of Matthew', lastChapter: 28, - chapters: [ - 0, - 25, - 23, - 17, - 25, - 48, - 34, - 29, - 34, - 38, - 42, - 30, - 50, - 58, - 36, - 39, - 28, - 27, - 35, - 30, - 34, - 46, - 46, - 39, - 51, - 46, - 75, - 66, - 20, - ], + chapters: [0, 25, 23, 17, 25, 48, 34, 29, 34, 38, 42, 30, 50, 58, 36, 39, 28, 27, 35, 30, 34, 46, 46, 39, 51, 46, 75, 66, 20], }, { bookNumber: 41, @@ -1195,25 +339,7 @@ export class BibleReference { abbreviation: 'Mark', longName: 'Gospel of Mark', lastChapter: 16, - chapters: [ - 0, - 45, - 28, - 35, - 41, - 43, - 56, - 37, - 38, - 50, - 52, - 33, - 44, - 37, - 72, - 47, - 20, - ], + chapters: [0, 45, 28, 35, 41, 43, 56, 37, 38, 50, 52, 33, 44, 37, 72, 47, 20], }, { bookNumber: 42, @@ -1221,33 +347,7 @@ export class BibleReference { abbreviation: 'Luke', longName: 'Gospel of Luke', lastChapter: 24, - chapters: [ - 0, - 80, - 52, - 38, - 44, - 39, - 49, - 50, - 56, - 62, - 42, - 54, - 59, - 35, - 35, - 32, - 31, - 37, - 43, - 48, - 47, - 38, - 71, - 56, - 53, - ], + chapters: [0, 80, 52, 38, 44, 39, 49, 50, 56, 62, 42, 54, 59, 35, 35, 32, 31, 37, 43, 48, 47, 38, 71, 56, 53], }, { bookNumber: 43, @@ -1255,30 +355,7 @@ export class BibleReference { abbreviation: 'John', longName: 'Gospel of John', lastChapter: 21, - chapters: [ - 0, - 51, - 25, - 36, - 54, - 47, - 71, - 53, - 59, - 41, - 42, - 57, - 50, - 38, - 31, - 27, - 33, - 26, - 40, - 42, - 31, - 25, - ], + chapters: [0, 51, 25, 36, 54, 47, 71, 53, 59, 41, 42, 57, 50, 38, 31, 27, 33, 26, 40, 42, 31, 25], }, { bookNumber: 44, @@ -1286,37 +363,7 @@ export class BibleReference { abbreviation: 'Acts', longName: 'Acts of the Apostles', lastChapter: 28, - chapters: [ - 0, - 26, - 47, - 26, - 37, - 42, - 15, - 60, - 40, - 43, - 48, - 30, - 25, - 52, - 28, - 41, - 40, - 34, - 28, - 41, - 38, - 40, - 30, - 35, - 27, - 27, - 32, - 44, - 31, - ], + chapters: [0, 26, 47, 26, 37, 42, 15, 60, 40, 43, 48, 30, 25, 52, 28, 41, 40, 34, 28, 41, 38, 40, 30, 35, 27, 27, 32, 44, 31], }, { bookNumber: 45, @@ -1324,25 +371,7 @@ export class BibleReference { abbreviation: 'Rom', longName: 'Epistle to the Romans', lastChapter: 16, - chapters: [ - 0, - 32, - 29, - 31, - 25, - 21, - 23, - 25, - 39, - 33, - 21, - 36, - 21, - 14, - 23, - 33, - 27, - ], + chapters: [0, 32, 29, 31, 25, 21, 23, 25, 39, 33, 21, 36, 21, 14, 23, 33, 27], }, { bookNumber: 46, @@ -1350,25 +379,7 @@ export class BibleReference { abbreviation: '1 Cor', longName: 'First Epistle to the Corinthians', lastChapter: 16, - chapters: [ - 0, - 31, - 16, - 23, - 21, - 13, - 20, - 40, - 13, - 27, - 33, - 34, - 31, - 13, - 40, - 58, - 24, - ], + chapters: [0, 31, 16, 23, 21, 13, 20, 40, 13, 27, 33, 34, 31, 13, 40, 58, 24], }, { bookNumber: 47, @@ -1528,31 +539,7 @@ export class BibleReference { abbreviation: 'Rev', longName: 'Book of Revelations', lastChapter: 22, - chapters: [ - 0, - 20, - 29, - 22, - 11, - 14, - 17, - 17, - 13, - 21, - 11, - 19, - 17, - 18, - 20, - 8, - 21, - 18, - 24, - 21, - 15, - 27, - 21, - ], + chapters: [0, 20, 29, 22, 11, 14, 17, 17, 13, 21, 11, 19, 17, 18, 20, 8, 21, 18, 24, 21, 15, 27, 21], }, ]; @@ -1578,19 +565,14 @@ export class BibleReference { if (this.section.end.chapter === 0) { this.section.end.chapter = this.section.start.chapter; } - if ( - Number(this.section.start.verse) > Number(this.section.end.verse) && - this.section.start.chapter === this.section.end.chapter - ) { + if (Number(this.section.start.verse) > Number(this.section.end.verse) && this.section.start.chapter === this.section.end.chapter) { this.section.end.verse = this.section.start.verse; } if (this.section.start.verse === 0) { this.section.start.verse = 1; } if (this.section.end.verse === 0) { - this.section.end.verse = this.section.book.chapters[ - this.section.end.chapter - ]; + this.section.end.verse = this.section.book.chapters[this.section.end.chapter]; } } @@ -1624,31 +606,19 @@ export class BibleReference { if (fbook.search(/\b(1|i|1st|first)\s*(samuel|sa|sam|sml)\b/i) !== -1) { return this.bookName(9); } - if ( - fbook.search(/\b(2|ii|2nd|second|sec)\s*(samuel|sa|sam|sml)\b/i) !== -1 - ) { + if (fbook.search(/\b(2|ii|2nd|second|sec)\s*(samuel|sa|sam|sml)\b/i) !== -1) { return this.bookName(10); } - if ( - fbook.search(/\b(1|i|1st|first)\s*(kings|king|kgs|kn|k|ki)\b/i) !== -1 - ) { + if (fbook.search(/\b(1|i|1st|first)\s*(kings|king|kgs|kn|k|ki)\b/i) !== -1) { return this.bookName(11); } - if ( - fbook.search(/\b(2|ii|2nd|second|sec)\s*(kings|king|kgs|kn|k|ki)\b/i) !== - -1 - ) { + if (fbook.search(/\b(2|ii|2nd|second|sec)\s*(kings|king|kgs|kn|k|ki)\b/i) !== -1) { return this.bookName(12); } - if ( - fbook.search(/\b(1|i|1st|first)\s*(chronicles|chron|ch|chr)\b/i) !== -1 - ) { + if (fbook.search(/\b(1|i|1st|first)\s*(chronicles|chron|ch|chr)\b/i) !== -1) { return this.bookName(13); } - if ( - fbook.search(/\b(2|ii|2nd|second|sec)\s*(chronicles|chron|ch|chr)\b/i) !== - -1 - ) { + if (fbook.search(/\b(2|ii|2nd|second|sec)\s*(chronicles|chron|ch|chr)\b/i) !== -1) { return this.bookName(14); } if (fbook.search(/\b(ezra|ezr)\b/i) !== -1) { @@ -1669,17 +639,10 @@ export class BibleReference { if (fbook.search(/\b(proverbs|prov|pr|pro|proverb|prv|prvbs)\b/i) !== -1) { return this.bookName(20); } - if ( - fbook.search(/\b(ecclesiastes|eccl|ecc|eccles|ec|ecl|ecclesiaste)\b/i) !== - -1 - ) { + if (fbook.search(/\b(ecclesiastes|eccl|ecc|eccles|ec|ecl|ecclesiaste)\b/i) !== -1) { return this.bookName(21); } - if ( - fbook.search( - /\b(song\sof\ssolomon|song\sof\ssongs|sos|ss|son|so|song|songs)\b/i - ) !== -1 - ) { + if (fbook.search(/\b(song\sof\ssolomon|song\sof\ssongs|sos|ss|son|so|song|songs)\b/i) !== -1) { return this.bookName(22); } if (fbook.search(/\b(isaiah|is|isah|isai|ia)\b/i) !== -1) { @@ -1762,25 +725,13 @@ export class BibleReference { if (fbook.search(/\b(romans|rom|ro|rm|roman)\b/i) !== -1) { return this.bookName(45); } - if ( - fbook.search( - /\b(1|i|1st|first)\s*(corinthian|cor|corinthians|corinth|corin|corth|corint)\b/i - ) !== -1 - ) { + if (fbook.search(/\b(1|i|1st|first)\s*(corinthian|cor|corinthians|corinth|corin|corth|corint)\b/i) !== -1) { return this.bookName(46); } - if ( - fbook.search( - /\b(2|ii|2nd|second|sec)\s*(corinthian|cor|corinthians|corinth|corin|corth|corint)\b/i - ) !== -1 - ) { + if (fbook.search(/\b(2|ii|2nd|second|sec)\s*(corinthian|cor|corinthians|corinth|corin|corth|corint)\b/i) !== -1) { return this.bookName(47); } - if ( - fbook.search( - /\b(galatians|galatian|galations|gal|ga|gala|galation|galat)\b/i - ) !== -1 - ) { + if (fbook.search(/\b(galatians|galatian|galations|gal|ga|gala|galation|galat)\b/i) !== -1) { return this.bookName(48); } if (fbook.search(/\b(ephesians|eph|ep|ephes|ephe|ephs)\b/i) !== -1) { @@ -1789,34 +740,19 @@ export class BibleReference { if (fbook.search(/\b(philippians|phi|phil|ph|philip)\b/i) !== -1) { return this.bookName(50); } - if ( - fbook.search(/\b(colossians|col|co|colossian|colos|coloss)\b/i) !== -1 - ) { + if (fbook.search(/\b(colossians|col|co|colossian|colos|coloss)\b/i) !== -1) { return this.bookName(51); } - if ( - fbook.search( - /\b(1|i|1st|first)\s*(thessalonians|the|thessa|thessalonian|thes|thess|th)\b/i - ) !== -1 - ) { + if (fbook.search(/\b(1|i|1st|first)\s*(thessalonians|the|thessa|thessalonian|thes|thess|th)\b/i) !== -1) { return this.bookName(52); } - if ( - fbook.search( - /\b(2|ii|2nd|second|sec)\s*(thessalonians|the|thessa|thessalonian|thes|thess|th)\b/i - ) !== -1 - ) { + if (fbook.search(/\b(2|ii|2nd|second|sec)\s*(thessalonians|the|thessa|thessalonian|thes|thess|th)\b/i) !== -1) { return this.bookName(53); } - if ( - fbook.search(/\b(1|i|1st|first)\s*(timothy|tim|ti|timoth|tm)\b/i) !== -1 - ) { + if (fbook.search(/\b(1|i|1st|first)\s*(timothy|tim|ti|timoth|tm)\b/i) !== -1) { return this.bookName(54); } - if ( - fbook.search(/\b(2|ii|2nd|second|sec)\s*(timothy|tim|timoth|tm)\b/i) !== - -1 - ) { + if (fbook.search(/\b(2|ii|2nd|second|sec)\s*(timothy|tim|timoth|tm)\b/i) !== -1) { return this.bookName(55); } if (fbook.search(/\b(titus|tit)\b/i) !== -1) { @@ -1831,15 +767,10 @@ export class BibleReference { if (fbook.search(/\b(james|jam|ja|jas|jms|jame|jm)\b/i) !== -1) { return this.bookName(59); } - if ( - fbook.search(/\b(1|i|1st|first)\s*(peter|pe|pet|pete|pt|p)\b/i) !== -1 - ) { + if (fbook.search(/\b(1|i|1st|first)\s*(peter|pe|pet|pete|pt|p)\b/i) !== -1) { return this.bookName(60); } - if ( - fbook.search(/\b(2|ii|2nd|second|sec)\s*(peter|pe|pet|pete|pt|p)\b/i) !== - -1 - ) { + if (fbook.search(/\b(2|ii|2nd|second|sec)\s*(peter|pe|pet|pete|pt|p)\b/i) !== -1) { return this.bookName(61); } if (fbook.search(/\b(jude|ju)\b/i) !== -1) { @@ -1855,22 +786,16 @@ export class BibleReference { static toString(section: Section) { // get the starting book, chapter, verse let ref = section.book.name - .concat(' ') - .concat(section.start.chapter.toString()) - .concat(':') - .concat(section.start.verse.toString()); + .concat(' ') // + .concat(section.start.chapter.toString()) // + .concat(':') // + .concat(section.start.verse.toString()); // - if ( - section.start.chapter === section.end.chapter && - section.start.verse === section.end.verse - ) { + if (section.start.chapter === section.end.chapter && section.start.verse === section.end.verse) { return ref; } - if ( - section.start.chapter === section.end.chapter && - section.start.verse !== section.end.verse - ) { + if (section.start.chapter === section.end.chapter && section.start.verse !== section.end.verse) { return ref.concat(' - ').concat(section.end.verse.toString()); } @@ -1885,18 +810,14 @@ export class BibleReference { return this.Books[booknum]; } - public static locationToIndex(book: number, loc: Location): number { + static locationToIndex(book: number, loc: Location): number { let ref = book * 100000000; ref = ref + loc.chapter * 10000; ref = ref + loc.verse; return ref; } - static formatReferenceKey( - book: number | string, - chapter: number | string, - vs: number | string - ) { + static formatReferenceKey(book: number | string, chapter: number | string, vs: number | string) { return `${book}:${chapter}:${vs}`; } @@ -1906,55 +827,39 @@ export class BibleReference { return new BibleReference(`${book} ${keyArray[1]}:${keyArray[2]}`); } - public static overlap( - leftRef: BibleReference, - rightRef: BibleReference - ): Overlap { - if (leftRef.section.book !== rightRef.section.book) { + static overlap(left: BibleReference, right: BibleReference): Overlap { + if (left.section.book !== right.section.book) { // either of the above means we are not overlapping return Overlap.None; } - let leftStartIndex = leftRef.startIndex(); - let leftEndIndex = leftRef.endIndex(); - let rightStartIndex = rightRef.startIndex(); - let rightEndIndex = rightRef.endIndex(); - - // Both references are equal to each other - if (leftStartIndex === rightStartIndex && leftEndIndex === rightEndIndex) { - return Overlap.Equal; - } if ( // left is subset of right - (leftStartIndex >= rightStartIndex && leftEndIndex <= rightEndIndex) || + (left.startIndex >= right.startIndex && left.endIndex <= right.endIndex) || // right is subset of left - (rightStartIndex >= leftStartIndex && rightEndIndex <= leftEndIndex) + (right.startIndex >= left.startIndex && right.endIndex <= left.endIndex) ) { return Overlap.Subset; } if ( // left overlaps the right - (leftEndIndex >= rightStartIndex && leftEndIndex <= rightEndIndex) || + (left.endIndex >= right.startIndex && left.endIndex <= right.endIndex) || // right overlaps the left - (rightEndIndex >= leftStartIndex && rightEndIndex <= leftEndIndex) + (right.endIndex >= left.startIndex && right.endIndex <= left.endIndex) ) { return Overlap.Intersect; } return Overlap.None; } - public static mergeReference( - ref1: BibleReference, - ref2: BibleReference, - strategy: Overlap - ): BibleReference | null { + public static mergeReference(ref1: BibleReference, ref2: BibleReference, strategy: Overlap): BibleReference | null { if (strategy === Overlap.None) { return null; } if (ref1.toString() === ref2.toString() && strategy === Overlap.Equal) { return ref1; } - let overlapType = BibleReference.overlap(ref1, ref2); + const overlapType = BibleReference.overlap(ref1, ref2); switch (overlapType) { case Overlap.Subset: if (strategy !== Overlap.Subset && strategy !== Overlap.Intersect) { @@ -1969,12 +874,14 @@ export class BibleReference { case Overlap.None: return null; } + // Now it's safe to merge - let mergedRef = new BibleReference(ref1.toString()); + const mergedRef = new BibleReference(ref1.toString()); mergedRef.section.start.chapter = ref1.section.start.chapter <= ref2.section.start.chapter - ? ref1.section.start.chapter - : ref2.section.start.chapter; + ? ref1.section.start.chapter // + : ref2.section.start.chapter; // + if (ref1.section.start.chapter < ref2.section.start.chapter) { mergedRef.section.start.verse = ref1.section.start.verse; } else if (ref2.section.start.chapter < ref1.section.start.chapter) { @@ -1982,13 +889,15 @@ export class BibleReference { } else { mergedRef.section.start.verse = ref1.section.start.verse <= ref2.section.start.verse - ? ref1.section.start.verse - : ref2.section.start.verse; + ? ref1.section.start.verse // + : ref2.section.start.verse; // } + mergedRef.section.end.chapter = ref1.section.end.chapter >= ref2.section.end.chapter - ? ref1.section.end.chapter - : ref2.section.end.chapter; + ? ref1.section.end.chapter // + : ref2.section.end.chapter; // + if (ref1.section.end.chapter > ref2.section.end.chapter) { mergedRef.section.end.verse = ref1.section.end.verse; } else if (ref2.section.end.chapter > ref1.section.end.chapter) { @@ -1996,8 +905,8 @@ export class BibleReference { } else { mergedRef.section.end.verse = ref1.section.end.verse >= ref2.section.end.verse - ? ref1.section.end.verse - : ref2.section.end.verse; + ? ref1.section.end.verse // + : ref2.section.end.verse; // } return mergedRef; } @@ -2136,11 +1045,7 @@ export class BibleReference { }); } - private maybeParseChapterOrVerse( - foundSecondBook: boolean, - foundFirstVerse: boolean, - isEnd: boolean - ) { + private maybeParseChapterOrVerse(foundSecondBook: boolean, foundFirstVerse: boolean, isEnd: boolean) { const self = this; return this.maybeDo(() => { if (self.ref.search(/:/) !== -1 || foundSecondBook || !foundFirstVerse) { @@ -2174,18 +1079,12 @@ export class BibleReference { return BibleReference.toString(this.section); } - public startIndex(): Number { - return BibleReference.locationToIndex( - this.section.book.bookNumber, - this.section.start - ); + get startIndex(): number { + return BibleReference.locationToIndex(this.section.book.bookNumber, this.section.start); } - public endIndex(): Number { - return BibleReference.locationToIndex( - this.section.book.bookNumber, - this.section.end - ); + get endIndex(): number { + return BibleReference.locationToIndex(this.section.book.bookNumber, this.section.end); } } 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/components/settings/settings.component.ts b/app/db/src/app/common/components/settings/settings.component.ts index bdb40671..93094d61 100644 --- a/app/db/src/app/common/components/settings/settings.component.ts +++ b/app/db/src/app/common/components/settings/settings.component.ts @@ -91,7 +91,7 @@ export class SettingsComponent extends SubscriberComponent { .subscribe((ds: OkCancelResult) => { console.log(ds); if (ds.ok) { - this.appService.updateSavedPage(); + this.appService.updateCurrentSavedPage(); this.navService.closeSettings(); this.snackBar.open(`${page.title} has been updated!`, '', { duration: 3 * 1000, 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 3a562a3d..19a3b2d0 100644 --- a/app/db/src/app/models/app-state.ts +++ b/app/db/src/app/models/app-state.ts @@ -1,14 +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; } @@ -58,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; @@ -84,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/edit-modal/note-edit-modal.component.html b/app/db/src/app/search/components/note/edit-modal/note-edit-modal.component.html index 5c93ea76..aa24b8b2 100644 --- a/app/db/src/app/search/components/note/edit-modal/note-edit-modal.component.html +++ b/app/db/src/app/search/components/note/edit-modal/note-edit-modal.component.html @@ -10,6 +10,10 @@ Title + + References + + Content diff --git a/app/db/src/app/search/components/note/edit-modal/note-edit-modal.component.ts b/app/db/src/app/search/components/note/edit-modal/note-edit-modal.component.ts index ef252333..d087f7c5 100644 --- a/app/db/src/app/search/components/note/edit-modal/note-edit-modal.component.ts +++ b/app/db/src/app/search/components/note/edit-modal/note-edit-modal.component.ts @@ -1,7 +1,8 @@ import { Component, Inject } from '@angular/core'; import { FormGroup, FormBuilder } from '@angular/forms'; import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; -import { CardItem, NoteItem } from '../../../../models/app-state'; +import { CardItem } from '../../../../models/app-state'; +import { NoteItem } from '../../../../models/note-state'; import { AppService } from '../../../../services/app.service'; import { UUID } from 'angular2-uuid'; @@ -40,30 +41,12 @@ export class NoteEditModalComponent { } save() { - if (this.isNew) { - this.appService.createNote({ - qry: '', - dict: 'n/a', - type: 'Note', - data: { - ...this.data, - title: this.noteForm.get('title').value, - content: this.noteForm.get('content').value, - }, - }); - } else { - this.appService.editNote( - { - ...this.cardItem, - data: { - ...this.cardItem.data, - title: this.noteForm.get('title').value, - content: this.noteForm.get('content').value, - }, - }, - this.cardItem - ); - } + this.appService.saveNote({ + ...this.data, + title: this.noteForm.get('title').value, + xref: this.noteForm.get('xref').value, + content: this.noteForm.get('content').value, + }); this.dialogRef.close(); } 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 29ce8af9..92b06fe8 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 @@ -16,6 +16,20 @@ {{ cardItem.data.content }} + + + + Cross References + + + +
+ +
+
+
@@ -50,6 +64,14 @@ save Add Card to Saved Page + +
diff --git a/app/db/src/app/search/components/note/note-card.component.scss b/app/db/src/app/search/components/note/note-card.component.scss index 37968379..2f073366 100644 --- a/app/db/src/app/search/components/note/note-card.component.scss +++ b/app/db/src/app/search/components/note/note-card.component.scss @@ -9,3 +9,8 @@ .card-actions { color: var(--note-color-primary); } + +.reference { + width: 100%; + margin: 3px; +} 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 18da52b0..ba88ab4c 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 @@ -1,8 +1,10 @@ -import { Component, ViewChild, ElementRef } from '@angular/core'; +import { Component, ViewChild, ElementRef, OnInit } from '@angular/core'; 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 '../../../models/note-state'; +import { BibleReference } from 'src/app/common/bible-reference'; @Component({ selector: 'app-note-card', @@ -12,12 +14,8 @@ import { AppService } from '../../../services/app.service'; 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); } @@ -28,6 +26,14 @@ export class NoteCardComponent extends CardComponent { this.copyToClip(text, html); } + prepXref(xref: string) { + return xref.split(';').map((o) => new BibleReference(o)); + } + + openPassage(ref: BibleReference) { + this.appService.getPassage(ref, this.cardItem); + } + edit() { this.dialog.open(NoteEditModalComponent, { data: this.cardItem, @@ -35,6 +41,6 @@ export class NoteCardComponent extends CardComponent { } delete() { - this.appService.deleteNote(this.cardItem); + this.appService.deleteNote(this.cardItem.data as NoteItem); } } 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..38cedef3 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 @@ -24,7 +24,12 @@ {{ para.p.h }} -

+

{{ vs.v }}. - + Note References -

note link, note link, note link...

+
+ +
@@ -98,6 +107,14 @@ save Add Card to Saved Page + +
diff --git a/app/db/src/app/search/components/passage/passage-card.component.scss b/app/db/src/app/search/components/passage/passage-card.component.scss index fefe09fe..c8c7a4ef 100644 --- a/app/db/src/app/search/components/passage/passage-card.component.scss +++ b/app/db/src/app/search/components/passage/passage-card.component.scss @@ -18,3 +18,8 @@ font-family: var(--card-heading-font-family); font-weight: 600; } + +.reference { + width: 100%; + margin: 3px; +} 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..72d15e9b 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 @@ -1,10 +1,11 @@ import { Component, OnInit, ElementRef, ViewChild } from '@angular/core'; import { MatDialog } from '@angular/material/dialog'; -import { BibleReference } from '../../../common/bible-reference'; +import { BibleReference, Overlap } 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'; +import { NoteItem } from 'src/app/models/note-state'; @Component({ selector: 'app-passage-card', @@ -24,12 +25,19 @@ export class PassageCardComponent extends CardComponent implements OnInit { displaySettings$ = this.appService.select((state) => state.displaySettings.value); + // whenever the notes changes, look for any notes that reference this passage. + notes$ = this.appService.select((state) => + state.notes.value.filter((o) => { + const refs = o.xref.split(';').map((r) => new BibleReference(r)); + return refs.filter((r) => BibleReference.overlap(this.ref, r) !== Overlap.None).length > 0; + }) + ); hasNotes = false; @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); } @@ -115,6 +123,10 @@ export class PassageCardComponent extends CardComponent implements OnInit { this.appService.updatePassage(this.cardItem, this.ref); } + openNote(note: NoteItem) { + this.appService.getNote(note.id, this.cardItem); + } + async openStrongs(q: string, asModal = false) { const dict = this.cardItem.dict === 'H' ? 'heb' : 'grk'; const numbers = q.split(' '); diff --git a/app/db/src/app/search/components/search-page/search.page.html b/app/db/src/app/search/components/search-page/search.page.html index 2e8602f8..f3b9f9ee 100644 --- a/app/db/src/app/search/components/search-page/search.page.html +++ b/app/db/src/app/search/components/search-page/search.page.html @@ -1,5 +1,5 @@ - 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/strongs/strongs.component.ts b/app/db/src/app/search/components/strongs/strongs.component.ts index f2d14bd8..6fe6b3da 100644 --- a/app/db/src/app/search/components/strongs/strongs.component.ts +++ b/app/db/src/app/search/components/strongs/strongs.component.ts @@ -1,5 +1,5 @@ import { Component, Input, Output, EventEmitter } from '@angular/core'; -import { StrongsResult } from 'src/app/models/app-state'; +import { StrongsResult } from '../../../models/strongs-state'; import { BibleReference } from 'src/app/common/bible-reference'; @Component({ 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 713a055d..2a6cf7e7 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, @@ -40,7 +30,7 @@ const initialState: AppState = { type: 'Note', data: { id: UUID.UUID(), - xref: null, + xref: '1 pe 2:16; jn 3:16', title: 'Title Here', content: '# Content Here\nIn Markdown format.', }, @@ -52,6 +42,10 @@ const initialState: AppState = { createdOn: new Date(0).toISOString(), value: [], }, + notes: { + createdOn: new Date(0).toISOString(), + value: [], + }, savedPagesLoaded: false, mainPages: [ { title: PageTitles.Search, icon: PageIcons.Search, route: 'search' }, @@ -82,6 +76,8 @@ const initialState: AppState = { }, }; +//#region + type AppAction = | { type: 'GET_SAVED_PAGE'; @@ -117,6 +113,11 @@ type AppAction = type: 'REMOVE_CARD'; card: CardItem; } + | { + type: 'MOVE_CARD'; + card: CardItem; + direction: ListDirection; + } | { type: 'UPDATE_ERROR'; error: Error; @@ -140,8 +141,32 @@ type AppAction = | { type: 'SET_USER'; user: User; + } + | { + type: 'FIND_NOTES'; + qry: string; + nextToItem: CardItem; + } + | { + type: 'GET_NOTE'; + noteId: string; + nextToItem: CardItem; + } + | { + type: 'UPDATE_NOTES'; + notes: IStorable; + } + | { + type: 'SAVE_NOTE'; + note: NoteItem; + } + | { + type: 'DELETE_NOTE'; + note: NoteItem; }; +//#endregion Actions + function maybeMutateStorable( state: AppState, candidate: IStorable, @@ -216,7 +241,7 @@ function reducer(state: AppState, action: AppAction): AppState { } case 'UPDATE_CURRENT_PAGE': { const savedPages = new Storable([ - ...state.savedPages.value.filter((o) => o.id === state.currentSavedPage.id), + ...state.savedPages.value.filter((o) => o.id !== state.currentSavedPage.id), { id: state.currentSavedPage.id, title: state.currentSavedPage.title, @@ -326,12 +351,184 @@ 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, user: action.user, }; } + case 'FIND_NOTES': { + const notes = state.notes.value + .filter((o) => o.title.search(action.qry) > -1) + .map((o) => { + return { + qry: o.id, + dict: 'n/a', + type: 'Note', + data: o, + }; + }); + + let cards = []; + + if (action.nextToItem && state.displaySettings.value.insertCardNextToItem) { + const idx = state.cards.indexOf(action.nextToItem); + + if (state.displaySettings.value.appendCardToBottom) { + const before = state.cards.slice(0, idx + 1); + const after = state.cards.slice(idx + 1); + cards = [...before, ...notes, ...after]; + } else { + const before = state.cards.slice(0, idx); + const after = state.cards.slice(idx); + cards = [...before, ...notes, ...after]; + } + } else { + if (state.displaySettings.value.appendCardToBottom) { + cards = [...state.cards, ...notes]; + } else { + cards = [...notes, ...state.cards]; + } + } + return { + ...state, + cards, + }; + } + case 'GET_NOTE': { + const note = state.notes.value.find((o) => o.id === action.noteId); + const card = { + qry: note.id, + dict: 'n/a', + type: 'Note', + data: note, + }; + + return reducer(state, { + type: 'ADD_CARD', + card, + nextToItem: action.nextToItem, + }); + } + case 'UPDATE_NOTES': { + return { + ...state, + notes: action.notes, + }; + } + case 'SAVE_NOTE': { + // you may be creating a new note or updating an existing. + // if its an update, you need to update the note in the following: + // * card list could have it. + // * notes list could have it. + // * it could be in any of the saved pages lists... + // so iterate through all of them and if you find the note + // in any of them, swap it out + + const cards = [ + ...state.cards.map((o) => { + const n = o.data as NoteItem; + if (n && n.id === action.note.id) { + return { + ...o, + data: action.note, + }; + } + return o; + }), + ]; + + const notes = new Storable([ + ...state.notes.value.filter((o) => o.id !== action.note.id), + action.note, + ]); + + const savedPages = new Storable([ + ...state.savedPages.value.map((sp) => { + return { + ...sp, + queries: sp.queries.map((o) => { + const n = o.data as NoteItem; + if (n && n.id === action.note.id) { + return { + ...o, + data: action.note, + }; + } + return o; + }), + }; + }), + ]); + const newState = { + ...state, + cards, + notes, + savedPages, + }; + return newState; + } + case 'DELETE_NOTE': { + // the note may be in any of the following: + // * card list could have it. + // * notes list could have it. + // * it could be in any of the saved pages lists... + // so iterate through all of them and if you find the note + // in any of them, remove it + + const cards = [ + ...state.cards.filter((o) => { + const n = o.data as NoteItem; + return !n || n.id !== action.note.id; + }), + ]; + + const notes = new Storable([...state.notes.value.filter((o) => o.id !== action.note.id)]); + + const savedPages = new Storable([ + ...state.savedPages.value.map((sp) => { + return { + ...sp, + queries: sp.queries.filter((o) => { + const n = o.data as NoteItem; + return !n || n.id !== action.note.id; + }), + }; + }), + ]); + return { + ...state, + cards, + notes, + savedPages, + }; + } } } @@ -352,13 +549,21 @@ export class AppService extends createStateService(reducer, initialState) { this.searchIndexArray = this.buildIndexArray().sort(); } + //#region General + removeCard(card: CardItem) { this.dispatch({ type: 'REMOVE_CARD', card, }); } - + moveCard(card: CardItem, direction: ListDirection) { + this.dispatch({ + type: 'MOVE_CARD', + card, + direction, + }); + } dispatchError(msg: string) { this.dispatch({ type: 'UPDATE_ERROR', @@ -376,6 +581,8 @@ export class AppService extends createStateService(reducer, initialState) { }); } + //#endregion + //#region Saved Pages getSavedPage(pageid: string) { @@ -392,7 +599,7 @@ export class AppService extends createStateService(reducer, initialState) { }); } - updateSavedPage() { + updateCurrentSavedPage() { this.dispatch({ type: 'UPDATE_CURRENT_PAGE', }); @@ -442,101 +649,48 @@ export class AppService extends createStateService(reducer, initialState) { //#region Notes - async getNote(qry: string, nextToItem: CardItem = null) { - const note = (await this.localStorageService.get('notes/' + qry).toPromise()) as NoteItem; - - const card = { - qry, - dict: 'n/a', - type: 'Note', - data: note, - }; - + findNotes(qry: string, nextToItem: CardItem = null) { this.dispatch({ - type: 'ADD_CARD', - card, + type: 'FIND_NOTES', + qry, nextToItem, }); } - async createNote(card: CardItem, nextToItem: CardItem = null) { - this.saveNoteApi(card.data as NoteItem).subscribe( - // success - () => { - this.dispatch({ - type: 'ADD_CARD', - card, - nextToItem, - }); - }, - // error - () => { - this.dispatch({ - type: 'UPDATE_ERROR', - error: { - // tslint:disable-next-line: quotemark - msg: "Something went wrong and the note wasn't saved. :(", - }, - }); - } - ); + async getNote(noteId: string, nextToItem: CardItem = null) { + this.dispatch({ + type: 'GET_NOTE', + noteId, + nextToItem, + }); } - async editNote(newCard: CardItem, oldCard: CardItem) { - this.saveNoteApi(newCard.data as NoteItem).subscribe( - // success - () => { - this.dispatch({ - type: 'UPDATE_CARD', - newCard, - oldCard, - }); - }, - // error - () => { - this.dispatch({ - type: 'UPDATE_ERROR', - error: { - // tslint:disable-next-line: quotemark - msg: "Something went wrong and the note wasn't saved. :(", - }, - }); - } - ); + updateNotes(notes: IStorable) { + this.dispatch({ + type: 'UPDATE_NOTES', + notes, + }); } - async deleteNote(noteCard: CardItem) { - this.deleteNoteApi(noteCard.data as NoteItem).subscribe( - // success - () => { - this.removeCard(noteCard); - }, - // error - () => { - this.dispatch({ - type: 'UPDATE_ERROR', - error: { - // tslint:disable-next-line: quotemark - msg: "Something went wrong and the note wasn't saved. :(", - }, - }); - } - ); + saveNote(note: NoteItem, nextToItem: CardItem = null) { + this.dispatch({ + type: 'SAVE_NOTE', + note, + }); } - private deleteNoteApi(note: NoteItem) { - return this.localStorageService.delete('notes/' + note.id); - } - - private saveNoteApi(note: NoteItem) { - return this.localStorageService.set('notes/' + note.id, note); + deleteNote(note: NoteItem) { + this.dispatch({ + type: 'DELETE_NOTE', + note, + }); } //#endregion //#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({ diff --git a/app/db/src/app/services/storage.service.ts b/app/db/src/app/services/storage.service.ts index 5c2ce5ef..075f12a7 100644 --- a/app/db/src/app/services/storage.service.ts +++ b/app/db/src/app/services/storage.service.ts @@ -4,7 +4,9 @@ import { AngularFireDatabase, AngularFireObject } from '@angular/fire/database'; import { IStorable } from '../models/storable'; import { AppService } from './app.service'; import { DisplaySettings, SavedPage, User } from '../models/app-state'; + import { SubscriberComponent } from '../common/components/subscriber.component'; +import { NoteItem } from '../models/note-state'; @Injectable({ providedIn: 'root', @@ -18,6 +20,10 @@ export class StorageService extends SubscriberComponent { private savedPagesPath = 'savedPaged'; private savedPagesRemoteObject: AngularFireObject>; + private noteItemsState$ = this.appService.select((state) => state.notes); + private noteItemsPath = 'noteItems'; + private noteItemsRemoteObject: AngularFireObject>; + constructor(private local: StorageMap, private remote: AngularFireDatabase, private appService: AppService) { super(); @@ -32,7 +38,7 @@ export class StorageService extends SubscriberComponent { } // update local - this.local.set('displaySettings', settings).subscribe( + this.local.set(this.displaySettingsPath, settings).subscribe( () => { // nop }, @@ -57,7 +63,7 @@ export class StorageService extends SubscriberComponent { } // update local - this.local.set('savedPages', savedPages).subscribe( + this.local.set(this.savedPagesPath, savedPages).subscribe( () => { // nop }, @@ -75,6 +81,31 @@ export class StorageService extends SubscriberComponent { }) ); + this.addSubscription( + this.noteItemsState$.subscribe((notes) => { + if (!notes) { + return; + } + + // update local + this.local.set(this.noteItemsPath, notes).subscribe( + () => { + // nop + }, + // error + () => { + // tslint:disable-next-line: quotemark + this.appService.dispatchError("Something went wrong and the note wasn't saved. :("); + } + ); + + // update remote + if (this.noteItemsRemoteObject) { + this.noteItemsRemoteObject.set(notes); + } + }) + ); + //#endregion } @@ -83,6 +114,7 @@ export class StorageService extends SubscriberComponent { `/${this.displaySettingsPath}/${user.uid}` ); this.savedPagesRemoteObject = this.remote.object>(`/${this.savedPagesPath}/${user.uid}`); + this.noteItemsRemoteObject = this.remote.object>(`/${this.noteItemsPath}/${user.uid}`); // display settings this.addSubscription( @@ -107,6 +139,18 @@ export class StorageService extends SubscriberComponent { } }) ); + + // note items + this.addSubscription( + this.noteItemsRemoteObject + .valueChanges() // when the saved pages have changed + .subscribe((remoteNoteItems) => { + if (remoteNoteItems) { + // update the saved pages locally from remote if it isn't null + this.appService.updateNotes(remoteNoteItems); + } + }) + ); } async initDisplaySettings() { @@ -128,4 +172,14 @@ export class StorageService extends SubscriberComponent { this.appService.updateSavedPages(savedPages); } } + + async initNotes() { + const exists = await this.local.has(this.noteItemsPath).toPromise(); + + if (exists) { + const notes = (await this.local.get(this.noteItemsPath).toPromise()) as IStorable; + + this.appService.updateNotes(notes); + } + } } diff --git a/app/db/src/styles/app.scss b/app/db/src/styles/app.scss index 4830e786..c0371ea6 100644 --- a/app/db/src/styles/app.scss +++ b/app/db/src/styles/app.scss @@ -137,3 +137,8 @@ a { font-size: var(--card-font-size) !important; line-height: calc(var(--card-font-size) * 1.1) !important; } + +.mat-expansion-panel:not([class*="mat-elevation-z"]) { + box-shadow: none !important; + border: 1px solid #eee; +}