mirror of
https://gitlab.com/walljm/dynamicbible.git
synced 2025-07-23 07:19:50 -04:00
Merge branch '26-bug-fixes-and-linting-issues' into 'main'
Resolve "Bug Fixes and Linting Issues" Closes #26 See merge request walljm/dynamicbible!27
This commit is contained in:
commit
dace1e3f61
@ -1,23 +1,24 @@
|
|||||||
{
|
{
|
||||||
"root": true,
|
"root": true,
|
||||||
"ignorePatterns": [
|
"ignorePatterns": ["projects/**/*"],
|
||||||
"projects/**/*"
|
"parser": "@typescript-eslint/parser",
|
||||||
],
|
"parserOptions": {
|
||||||
|
"project": "./tsconfig.json", // <-- Point to your project's "tsconfig.json" or create a new one.
|
||||||
|
"ecmaVersion": 2020,
|
||||||
|
"sourceType": "module"
|
||||||
|
},
|
||||||
|
"plugins": ["unused-imports", "optimize-regex", "simple-import-sort"],
|
||||||
"overrides": [
|
"overrides": [
|
||||||
{
|
{
|
||||||
"files": [
|
"files": ["*.ts"],
|
||||||
"*.ts"
|
|
||||||
],
|
|
||||||
"parserOptions": {
|
"parserOptions": {
|
||||||
"project": [
|
"project": ["tsconfig.json", "e2e/tsconfig.json"],
|
||||||
"tsconfig.json",
|
|
||||||
"e2e/tsconfig.json"
|
|
||||||
],
|
|
||||||
"createDefaultProgram": true
|
"createDefaultProgram": true
|
||||||
},
|
},
|
||||||
"extends": [
|
"extends": [
|
||||||
"plugin:@angular-eslint/recommended",
|
"plugin:@angular-eslint/recommended",
|
||||||
"plugin:@angular-eslint/template/process-inline-templates"
|
"plugin:@angular-eslint/template/process-inline-templates",
|
||||||
|
"plugin:deprecation/recommended"
|
||||||
],
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
"@angular-eslint/directive-selector": [
|
"@angular-eslint/directive-selector": [
|
||||||
@ -35,18 +36,27 @@
|
|||||||
"prefix": "app",
|
"prefix": "app",
|
||||||
"style": "kebab-case"
|
"style": "kebab-case"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"no-unused-vars": "off", // or "@typescript-eslint/no-unused-vars": "off",
|
||||||
|
"unused-imports/no-unused-imports": "error",
|
||||||
|
"unused-imports/no-unused-vars": [
|
||||||
|
"warn",
|
||||||
|
{
|
||||||
|
"vars": "all",
|
||||||
|
"varsIgnorePattern": "^_",
|
||||||
|
"args": "after-used",
|
||||||
|
"argsIgnorePattern": "^_"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"optimize-regex/optimize-regex": "warn",
|
||||||
|
"simple-import-sort/imports": "warn",
|
||||||
|
"simple-import-sort/exports": "warn"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"files": [
|
"files": ["*.html"],
|
||||||
"*.html"
|
"extends": ["plugin:@angular-eslint/template/recommended"],
|
||||||
],
|
"rules": {}
|
||||||
"extends": [
|
|
||||||
"plugin:@angular-eslint/template/recommended"
|
|
||||||
],
|
|
||||||
"rules": {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -177,8 +177,7 @@
|
|||||||
"schematicCollections": [
|
"schematicCollections": [
|
||||||
"@cypress/schematic",
|
"@cypress/schematic",
|
||||||
"@angular-eslint/schematics",
|
"@angular-eslint/schematics",
|
||||||
"@angular-eslint/schematics",
|
|
||||||
"@schematics/angular"
|
"@schematics/angular"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"extends": "../tsconfig.json",
|
"extends": "../tsconfig.json",
|
||||||
"include": ["**/*.ts"],
|
"include": ["**/*.ts"],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"sourceMap": false,
|
"sourceMap": true,
|
||||||
"types": ["cypress"]
|
"types": ["cypress"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
4197
src/dependency-tree.txt
Normal file
4197
src/dependency-tree.txt
Normal file
File diff suppressed because it is too large
Load Diff
2489
src/package-lock.json
generated
2489
src/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -33,11 +33,9 @@
|
|||||||
"@codetrix-studio/capacitor-google-auth": "^3.4.0-rc.0",
|
"@codetrix-studio/capacitor-google-auth": "^3.4.0-rc.0",
|
||||||
"@ngx-pwa/local-storage": "^17.0.0",
|
"@ngx-pwa/local-storage": "^17.0.0",
|
||||||
"angular2-uuid": "^1.1.1",
|
"angular2-uuid": "^1.1.1",
|
||||||
"component": "^1.1.0",
|
|
||||||
"firebase": "^10.8.0",
|
"firebase": "^10.8.0",
|
||||||
"marked": "^9.0.0",
|
"marked": "^9.0.0",
|
||||||
"ngx-markdown": "^17.1.1",
|
"ngx-markdown": "^17.1.1",
|
||||||
"redux": "^5.0.1",
|
|
||||||
"reselect": "^5.1.0",
|
"reselect": "^5.1.0",
|
||||||
"rxjs": "^7.8.1",
|
"rxjs": "^7.8.1",
|
||||||
"tslib": "^2.6.2",
|
"tslib": "^2.6.2",
|
||||||
@ -59,8 +57,13 @@
|
|||||||
"@types/jasminewd2": "~2.0.13",
|
"@types/jasminewd2": "~2.0.13",
|
||||||
"@types/node": "^20.11.21",
|
"@types/node": "^20.11.21",
|
||||||
"@typescript-eslint/eslint-plugin": "7.1.0",
|
"@typescript-eslint/eslint-plugin": "7.1.0",
|
||||||
"@typescript-eslint/parser": "7.1.0",
|
"@typescript-eslint/parser": "^7.1.0",
|
||||||
|
"cypress": "latest",
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
|
"eslint-plugin-deprecation": "^2.0.0",
|
||||||
|
"eslint-plugin-optimize-regex": "^1.2.1",
|
||||||
|
"eslint-plugin-simple-import-sort": "^12.0.0",
|
||||||
|
"eslint-plugin-unused-imports": "^3.1.0",
|
||||||
"firebase-tools": "^13.4.0",
|
"firebase-tools": "^13.4.0",
|
||||||
"fuzzy": "^0.1.3",
|
"fuzzy": "^0.1.3",
|
||||||
"inquirer": "^9.2.15",
|
"inquirer": "^9.2.15",
|
||||||
@ -74,8 +77,7 @@
|
|||||||
"karma-jasmine-html-reporter": "^2.1.0",
|
"karma-jasmine-html-reporter": "^2.1.0",
|
||||||
"open": "^10.0.4",
|
"open": "^10.0.4",
|
||||||
"ts-node": "~10.9.2",
|
"ts-node": "~10.9.2",
|
||||||
"typescript": "~5.3.3",
|
"typescript": "~5.3.3"
|
||||||
"cypress": "latest"
|
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"last 1 Chrome version",
|
"last 1 Chrome version",
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { Routes, RouterModule } from '@angular/router';
|
import { RouterModule,Routes } from '@angular/router';
|
||||||
import { SearchPageComponent } from './pages/search/search.page';
|
|
||||||
import { SavedPagesAdminPageComponent } from './pages/saved-pages-admin/saved-pages-admin.page';
|
|
||||||
import { NotesAdminPageComponent } from './pages/notes-admin/notes-admin.page';
|
import { NotesAdminPageComponent } from './pages/notes-admin/notes-admin.page';
|
||||||
|
import { SavedPagesAdminPageComponent } from './pages/saved-pages-admin/saved-pages-admin.page';
|
||||||
|
import { SearchPageComponent } from './pages/search/search.page';
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
{
|
{
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
>
|
>
|
||||||
|
|
||||||
<a mat-list-item (click)="showHelp()"
|
<a mat-list-item (click)="showHelp()"
|
||||||
><mat-icon color="accenovert">help</mat-icon>Help</a
|
><mat-icon color="accenovert">help</mat-icon> Help</a
|
||||||
>
|
>
|
||||||
</mat-nav-list>
|
</mat-nav-list>
|
||||||
|
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
import { Component, ViewChild, AfterViewInit, OnDestroy, ChangeDetectorRef } from '@angular/core';
|
import { BreakpointObserver,Breakpoints } from '@angular/cdk/layout';
|
||||||
|
import { AfterViewInit, ChangeDetectorRef,Component, ViewChild } from '@angular/core';
|
||||||
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
|
import { MatSidenav } from '@angular/material/sidenav';
|
||||||
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { map, shareReplay } from 'rxjs/operators';
|
||||||
|
|
||||||
|
import { SubscriberBase } from './common/subscriber-base';
|
||||||
|
import { HelpModalComponent } from './components/help-modal/help-modal.component';
|
||||||
import { AppService } from './services/app.service';
|
import { AppService } from './services/app.service';
|
||||||
import { NavService } from './services/nav.service';
|
import { NavService } from './services/nav.service';
|
||||||
import { StorageService } from './services/storage.service';
|
import { StorageService } from './services/storage.service';
|
||||||
import { Observable } from 'rxjs';
|
|
||||||
import { Breakpoints, BreakpointObserver } from '@angular/cdk/layout';
|
|
||||||
import { map, shareReplay } from 'rxjs/operators';
|
|
||||||
import { MatSidenav } from '@angular/material/sidenav';
|
|
||||||
import { SubscriberBase } from './common/subscriber-base';
|
|
||||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
|
||||||
import { HelpModalComponent } from './components/help-modal/help-modal.component';
|
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-root',
|
selector: 'app-root',
|
||||||
@ -49,6 +50,9 @@ export class AppComponent extends SubscriberBase implements AfterViewInit {
|
|||||||
this.error$.subscribe((err) => {
|
this.error$.subscribe((err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
this.snackBar.open(`Oh no! ${err.msg}`, 'Dismiss Error');
|
this.snackBar.open(`Oh no! ${err.msg}`, 'Dismiss Error');
|
||||||
|
setTimeout(() => {
|
||||||
|
this.snackBar.dismiss(); // dismiss if its still there after 25 seconds.
|
||||||
|
}, 25 * 1000);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -1,73 +1,63 @@
|
|||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
import { ClipboardModule } from '@angular/cdk/clipboard';
|
||||||
import { HttpClientModule } from '@angular/common/http';
|
|
||||||
import { BrowserModule } from '@angular/platform-browser';
|
|
||||||
import { NgModule } from '@angular/core';
|
|
||||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
|
||||||
|
|
||||||
import { MARKED_OPTIONS, MarkdownModule } from 'ngx-markdown';
|
|
||||||
|
|
||||||
import { AngularFireModule } from '@angular/fire/compat';
|
|
||||||
import { FirebaseConfig } from './constants';
|
|
||||||
import { DragDropModule } from '@angular/cdk/drag-drop';
|
import { DragDropModule } from '@angular/cdk/drag-drop';
|
||||||
|
import { HttpClientModule } from '@angular/common/http';
|
||||||
|
import { APP_ID, NgModule } from '@angular/core';
|
||||||
|
import { AngularFireModule } from '@angular/fire/compat';
|
||||||
import { AngularFireAuthModule } from '@angular/fire/compat/auth';
|
import { AngularFireAuthModule } from '@angular/fire/compat/auth';
|
||||||
import { AngularFireDatabaseModule } from '@angular/fire/compat/database';
|
import { AngularFireDatabaseModule } from '@angular/fire/compat/database';
|
||||||
|
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
|
||||||
import { MatButtonModule } from '@angular/material/button';
|
|
||||||
import { MatInputModule } from '@angular/material/input';
|
|
||||||
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
import { MatAutocompleteModule } from '@angular/material/autocomplete';
|
||||||
import { MatFormFieldModule } from '@angular/material/form-field';
|
|
||||||
import { MatRadioModule } from '@angular/material/radio';
|
|
||||||
import { MatSelectModule } from '@angular/material/select';
|
|
||||||
import { MatSliderModule } from '@angular/material/slider';
|
|
||||||
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
|
||||||
import { MatMenuModule } from '@angular/material/menu';
|
|
||||||
import { MatSidenavModule } from '@angular/material/sidenav';
|
|
||||||
import { MatToolbarModule } from '@angular/material/toolbar';
|
|
||||||
import { MatListModule } from '@angular/material/list';
|
|
||||||
import { MatCardModule } from '@angular/material/card';
|
|
||||||
import { MatStepperModule } from '@angular/material/stepper';
|
|
||||||
import { MatExpansionModule } from '@angular/material/expansion';
|
|
||||||
import { MatButtonToggleModule } from '@angular/material/button-toggle';
|
|
||||||
import { MatIconModule } from '@angular/material/icon';
|
|
||||||
import { MatDialogModule } from '@angular/material/dialog';
|
|
||||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
||||||
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
|
||||||
import { MatBadgeModule } from '@angular/material/badge';
|
import { MatBadgeModule } from '@angular/material/badge';
|
||||||
import { MatBottomSheetModule } from '@angular/material/bottom-sheet';
|
import { MatBottomSheetModule } from '@angular/material/bottom-sheet';
|
||||||
import { MatDividerModule } from '@angular/material/divider';
|
import { MatButtonModule } from '@angular/material/button';
|
||||||
|
import { MatButtonToggleModule } from '@angular/material/button-toggle';
|
||||||
|
import { MatCardModule } from '@angular/material/card';
|
||||||
|
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||||
import { MatChipsModule } from '@angular/material/chips';
|
import { MatChipsModule } from '@angular/material/chips';
|
||||||
import { MatNativeDateModule, MatRippleModule } from '@angular/material/core';
|
import { MatNativeDateModule, MatRippleModule } from '@angular/material/core';
|
||||||
import { ClipboardModule } from '@angular/cdk/clipboard';
|
import { MatDialogModule } from '@angular/material/dialog';
|
||||||
|
import { MatDividerModule } from '@angular/material/divider';
|
||||||
|
import { MatExpansionModule } from '@angular/material/expansion';
|
||||||
|
import { MatFormFieldModule } from '@angular/material/form-field';
|
||||||
|
import { MatIconModule } from '@angular/material/icon';
|
||||||
|
import { MatInputModule } from '@angular/material/input';
|
||||||
|
import { MatListModule } from '@angular/material/list';
|
||||||
|
import { MatMenuModule } from '@angular/material/menu';
|
||||||
|
import { MatRadioModule } from '@angular/material/radio';
|
||||||
|
import { MatSelectModule } from '@angular/material/select';
|
||||||
|
import { MatSidenavModule } from '@angular/material/sidenav';
|
||||||
|
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
||||||
|
import { MatSliderModule } from '@angular/material/slider';
|
||||||
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
||||||
|
import { MatStepperModule } from '@angular/material/stepper';
|
||||||
|
import { MatTabsModule } from '@angular/material/tabs';
|
||||||
|
import { MatToolbarModule } from '@angular/material/toolbar';
|
||||||
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||||
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
|
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
|
import { MarkdownModule,MARKED_OPTIONS } from 'ngx-markdown';
|
||||||
|
import { MarkedOptions, MarkedRenderer } from 'ngx-markdown';
|
||||||
|
|
||||||
import { AppRoutingModule } from './app-routing.module';
|
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
|
import { AppRoutingModule } from './app-routing.module';
|
||||||
import { NotesAdminPageComponent } from './pages/notes-admin/notes-admin.page';
|
import { AddToPageModalComponent } from './components/add-to-page-modal/add-to-page-modal.component';
|
||||||
|
|
||||||
import { SavedPagesAdminPageComponent } from './pages/saved-pages-admin/saved-pages-admin.page';
|
|
||||||
import { SavedPageCardComponent } from './components/saved-page-card/saved-page-card.component';
|
|
||||||
|
|
||||||
import { HelpModalComponent } from './components/help-modal/help-modal.component';
|
import { HelpModalComponent } from './components/help-modal/help-modal.component';
|
||||||
|
import { NoteEditModalComponent } from './components/note/edit-modal/note-edit-modal.component';
|
||||||
import { SearchPageComponent } from './pages/search/search.page';
|
import { NoteCardComponent } from './components/note/note-card.component';
|
||||||
|
|
||||||
import { OkCancelModalComponent } from './components/ok-cancel-modal/ok-cancel-modal.component';
|
import { OkCancelModalComponent } from './components/ok-cancel-modal/ok-cancel-modal.component';
|
||||||
import { SettingsComponent } from './components/settings/settings.component';
|
import { PageEditModalComponent } from './components/page-edit-modal/page-edit-modal.component';
|
||||||
|
|
||||||
import { PassageCardComponent } from './components/passage/passage-card.component';
|
import { PassageCardComponent } from './components/passage/passage-card.component';
|
||||||
import { StrongsComponent } from './components/strongs/strongs.component';
|
import { SavedPageCardComponent } from './components/saved-page-card/saved-page-card.component';
|
||||||
|
import { SettingsComponent } from './components/settings/settings.component';
|
||||||
import { StrongsCardComponent } from './components/strongs/card/strongs-card.component';
|
import { StrongsCardComponent } from './components/strongs/card/strongs-card.component';
|
||||||
import { StrongsModalComponent } from './components/strongs/modal/strongs-modal.component';
|
import { StrongsModalComponent } from './components/strongs/modal/strongs-modal.component';
|
||||||
import { WordsCardComponent } from './components/words/words-card.component';
|
import { StrongsComponent } from './components/strongs/strongs.component';
|
||||||
import { NoteCardComponent } from './components/note/note-card.component';
|
|
||||||
import { PageEditModalComponent } from './components/page-edit-modal/page-edit-modal.component';
|
|
||||||
import { NoteEditModalComponent } from './components/note/edit-modal/note-edit-modal.component';
|
|
||||||
import { VersePickerModalComponent } from './components/verse-picker-modal/verse-picker-modal.component';
|
import { VersePickerModalComponent } from './components/verse-picker-modal/verse-picker-modal.component';
|
||||||
import { AddToPageModalComponent } from './components/add-to-page-modal/add-to-page-modal.component';
|
import { WordsCardComponent } from './components/words/words-card.component';
|
||||||
|
import { FirebaseConfig } from './constants';
|
||||||
|
import { NotesAdminPageComponent } from './pages/notes-admin/notes-admin.page';
|
||||||
import { MarkedOptions, MarkedRenderer } from 'ngx-markdown';
|
import { SavedPagesAdminPageComponent } from './pages/saved-pages-admin/saved-pages-admin.page';
|
||||||
|
import { SearchPageComponent } from './pages/search/search.page';
|
||||||
|
|
||||||
// function that returns `MarkedOptions` with renderer override
|
// function that returns `MarkedOptions` with renderer override
|
||||||
export function markedOptionsFactory(): MarkedOptions {
|
export function markedOptionsFactory(): MarkedOptions {
|
||||||
@ -107,7 +97,7 @@ export function markedOptionsFactory(): MarkedOptions {
|
|||||||
OkCancelModalComponent,
|
OkCancelModalComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),
|
BrowserModule,
|
||||||
HttpClientModule,
|
HttpClientModule,
|
||||||
|
|
||||||
ReactiveFormsModule,
|
ReactiveFormsModule,
|
||||||
@ -154,9 +144,10 @@ export function markedOptionsFactory(): MarkedOptions {
|
|||||||
MatSnackBarModule,
|
MatSnackBarModule,
|
||||||
MatTooltipModule,
|
MatTooltipModule,
|
||||||
MatFormFieldModule,
|
MatFormFieldModule,
|
||||||
|
MatTabsModule,
|
||||||
ClipboardModule,
|
ClipboardModule,
|
||||||
],
|
],
|
||||||
providers: [],
|
providers: [{ provide: APP_ID, useValue: 'ng-cli-universal' }],
|
||||||
bootstrap: [AppComponent],
|
bootstrap: [AppComponent],
|
||||||
})
|
})
|
||||||
export class AppModule {}
|
export class AppModule {}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { moveItemUpOrDown, moveItem } from './array-operations';
|
import { moveItem,moveItemUpOrDown } from './array-operations';
|
||||||
import { MoveDirection } from './move-direction';
|
import { MoveDirection } from './move-direction';
|
||||||
|
|
||||||
describe('Array Movement', () => {
|
describe('Array Movement', () => {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { MoveDirection } from './move-direction';
|
|
||||||
import { moveItemInArray } from '@angular/cdk/drag-drop';
|
import { moveItemInArray } from '@angular/cdk/drag-drop';
|
||||||
|
|
||||||
|
import { MoveDirection } from './move-direction';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves an item up (1 index towards 0) or down (1 index away from 0) immutably, returning a new array as the value.
|
* Moves an item up (1 index towards 0) or down (1 index away from 0) immutably, returning a new array as the value.
|
||||||
* @param items Array in which to move the item.
|
* @param items Array in which to move the item.
|
||||||
|
@ -924,7 +924,7 @@ export class BibleReference {
|
|||||||
if (this.ref.length === 0) {
|
if (this.ref.length === 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.parseBook(false);
|
this.parseBook();
|
||||||
this.parseChapter(false);
|
this.parseChapter(false);
|
||||||
|
|
||||||
const foundFirstVerse = this.ref.search(/:.*-/) !== -1;
|
const foundFirstVerse = this.ref.search(/:.*-/) !== -1;
|
||||||
@ -932,7 +932,7 @@ export class BibleReference {
|
|||||||
this.maybeParseRangeSep();
|
this.maybeParseRangeSep();
|
||||||
const foundSecondBook = this.ref.search(/\w\s+\d/i) !== -1;
|
const foundSecondBook = this.ref.search(/\w\s+\d/i) !== -1;
|
||||||
|
|
||||||
this.maybeParseBook(true);
|
this.maybeParseBook();
|
||||||
this.maybeParseChapterOrVerse(foundSecondBook, foundFirstVerse, true);
|
this.maybeParseChapterOrVerse(foundSecondBook, foundFirstVerse, true);
|
||||||
this.maybeParseVerse(true);
|
this.maybeParseVerse(true);
|
||||||
}
|
}
|
||||||
@ -958,7 +958,7 @@ export class BibleReference {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private parseBook(isEnd?: boolean) {
|
private parseBook() {
|
||||||
this.ref = this.ref.toLowerCase().trim();
|
this.ref = this.ref.toLowerCase().trim();
|
||||||
|
|
||||||
let fbook = this.ref.substring(0, this.ref.search(/\w\s+\d/i) + 1);
|
let fbook = this.ref.substring(0, this.ref.search(/\w\s+\d/i) + 1);
|
||||||
@ -1039,10 +1039,10 @@ export class BibleReference {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private maybeParseBook(isEnd: boolean) {
|
private maybeParseBook() {
|
||||||
return this.maybeDo(() => {
|
return this.maybeDo(() => {
|
||||||
if (this.ref.search(/\w\s+\d/i) !== -1) {
|
if (this.ref.search(/\w\s+\d/i) !== -1) {
|
||||||
this.parseBook(isEnd);
|
this.parseBook();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { CardType, CardItem } from '../models/card-state';
|
import { CardItem,CardType } from '../models/card-state';
|
||||||
import { NoteItem } from '../models/note-state';
|
import { NoteItem } from '../models/note-state';
|
||||||
|
import { getCardCacheKey, removeFromCardCache,updateInCardCache } from './card-cache-operations';
|
||||||
import { HashTable } from './hashtable';
|
import { HashTable } from './hashtable';
|
||||||
import { updateInCardCache, getCardCacheKey, removeFromCardCache } from './card-cache-operations';
|
|
||||||
|
|
||||||
describe('Card Cache', () => {
|
describe('Card Cache', () => {
|
||||||
it('updateCache', () => {
|
it('updateCache', () => {
|
||||||
@ -48,16 +48,6 @@ describe('Card Cache', () => {
|
|||||||
type: CardType.Passage,
|
type: CardType.Passage,
|
||||||
data: null,
|
data: null,
|
||||||
};
|
};
|
||||||
const card2: CardItem = {
|
|
||||||
qry: 'jason',
|
|
||||||
type: CardType.Passage,
|
|
||||||
data: {
|
|
||||||
id: 'adsf',
|
|
||||||
xref: '',
|
|
||||||
title: 'adsf',
|
|
||||||
content: '',
|
|
||||||
} as NoteItem,
|
|
||||||
};
|
|
||||||
const card3: CardItem = {
|
const card3: CardItem = {
|
||||||
qry: 'jason3',
|
qry: 'jason3',
|
||||||
type: CardType.Passage,
|
type: CardType.Passage,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { mergeCardList } from './card-operations';
|
import { CardItem,CardType } from '../models/card-state';
|
||||||
import { BibleReference, Overlap } from './bible-reference';
|
import { BibleReference, Overlap } from './bible-reference';
|
||||||
import { CardType, CardItem } from '../models/card-state';
|
import { mergeCardList } from './card-operations';
|
||||||
|
|
||||||
describe('Card Merging', () => {
|
describe('Card Merging', () => {
|
||||||
it('Should merge two equal reference cards', () => {
|
it('Should merge two equal reference cards', () => {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { BibleReference, Overlap } from './bible-reference';
|
|
||||||
import { CardType, DataReference } from '../models/card-state';
|
import { CardType, DataReference } from '../models/card-state';
|
||||||
|
import { BibleReference, Overlap } from './bible-reference';
|
||||||
|
|
||||||
export function maybeMergeCards(
|
export function maybeMergeCards(
|
||||||
leftCard: DataReference,
|
leftCard: DataReference,
|
||||||
|
@ -1,103 +1,6 @@
|
|||||||
import { Store, createStore } from 'redux';
|
|
||||||
|
|
||||||
import { BehaviorSubject, Observable } from 'rxjs';
|
import { BehaviorSubject, Observable } from 'rxjs';
|
||||||
import { distinctUntilChanged, map } from 'rxjs/operators';
|
import { distinctUntilChanged, map } from 'rxjs/operators';
|
||||||
|
|
||||||
/**
|
|
||||||
* A base class from which to extend a service to provide predictable state to components. You should not extend this
|
|
||||||
* class directly; instead, use the {@link createStateService} function to create a base class specific to your service.
|
|
||||||
* @see {@link createStateService}
|
|
||||||
*/
|
|
||||||
class StateService<TState, TAction extends { type: string }> {
|
|
||||||
/** An observable that provides the entire state managed by the service. */
|
|
||||||
public readonly state$: Observable<TState>;
|
|
||||||
|
|
||||||
private readonly store: Store<TState, TAction>;
|
|
||||||
private readonly internalState$: BehaviorSubject<TState>;
|
|
||||||
|
|
||||||
protected constructor(reducer: (state: TState, action: TAction) => TState, initialState: TState) {
|
|
||||||
this.store = createStore(
|
|
||||||
reducer,
|
|
||||||
initialState as any, // this cast is required by Redux's typings, it should have no impact
|
|
||||||
undefined // in the future, we may want to add some middleware to the Redux stores. that goes here!
|
|
||||||
);
|
|
||||||
|
|
||||||
this.internalState$ = new BehaviorSubject<TState>(initialState as TState);
|
|
||||||
|
|
||||||
// BehaviorSubject.asObservable returns a new object, so hold onto it to avoid unnecessary allocations
|
|
||||||
this.state$ = this.internalState$.asObservable();
|
|
||||||
|
|
||||||
this.store.subscribe(() => this.internalState$.next(this.store.getState()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an observable that provides data derived from the state managed by the service.
|
|
||||||
* @param selector A selector that maps the state to the derived data.
|
|
||||||
*/
|
|
||||||
public select<TDerived>(selector: (state: TState) => TDerived): Observable<TDerived> {
|
|
||||||
return this.state$.pipe(map(selector), distinctUntilChanged());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the current state managed by the service. **You should only use the current state to validate operations or
|
|
||||||
* help to construct actions to be dispatched.** Try not to expose any state retrieved using this method outside the
|
|
||||||
* derived service class.
|
|
||||||
*/
|
|
||||||
protected getState(): TState {
|
|
||||||
return this.internalState$.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dispatches an action to the underlying Redux store.
|
|
||||||
* @param action The action to dispatch.
|
|
||||||
*/
|
|
||||||
protected dispatch(action: TAction) {
|
|
||||||
this.store.dispatch(action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a deeply-immutable type from the provided type. Objects' properties will be marked as `readonly`, array types
|
|
||||||
* will be replaced with {@link ReadonlyArray}, {@link Map} types will be replaced with {@link ReadonlyMap}, and
|
|
||||||
* {@link Set} types will be replaced with {@link ReadonlySet}.
|
|
||||||
*/
|
|
||||||
export type Immutable<T> = T extends undefined | null | boolean | string | number
|
|
||||||
? T
|
|
||||||
: T extends Array<infer U>
|
|
||||||
? ImmutableArray<U>
|
|
||||||
: T extends Map<infer K, infer V>
|
|
||||||
? ImmutableMap<K, V>
|
|
||||||
: T extends Set<infer M>
|
|
||||||
? ImmutableSet<M>
|
|
||||||
: { readonly [N in keyof T]: Immutable<T[N]> };
|
|
||||||
|
|
||||||
interface ImmutableArray<T> extends ReadonlyArray<Immutable<T>> {}
|
|
||||||
interface ImmutableMap<K, V> extends ReadonlyMap<Immutable<K>, Immutable<V>> {}
|
|
||||||
interface ImmutableSet<T> extends ReadonlySet<Immutable<T>> {}
|
|
||||||
|
|
||||||
// The below type definition is simpler, but it only works with TypeScript 3.7 and above. Swap this in when we upgrade!
|
|
||||||
|
|
||||||
// export type Immutable<T> = T extends undefined | null | boolean | string | number
|
|
||||||
// ? T
|
|
||||||
// : T extends Array<infer U>
|
|
||||||
// ? ReadonlyArray<Immutable<U>>
|
|
||||||
// : T extends Map<infer K, infer V>
|
|
||||||
// ? ReadonlyMap<Immutable<K>, Immutable<V>>
|
|
||||||
// : T extends Set<infer M>
|
|
||||||
// ? ReadonlySet<Immutable<M>>
|
|
||||||
// : { readonly [N in keyof T]: Immutable<T[N]> };
|
|
||||||
|
|
||||||
type IfEquals<X, Y, A = X, B = never> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? A : B;
|
|
||||||
type IfImmutable<TState extends {}, TImmutable = TState, TMutable = never> = IfEquals<
|
|
||||||
TState,
|
|
||||||
{ readonly [K in keyof TState]: Immutable<TState[K]> },
|
|
||||||
TImmutable,
|
|
||||||
TMutable
|
|
||||||
>;
|
|
||||||
|
|
||||||
// eslint-disable-next-line
|
|
||||||
type YourStateTypeNeedsToBeImmutable<TState> = {};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a base class from which to extend a service to provide predictable state to components.
|
* Creates a base class from which to extend a service to provide predictable state to components.
|
||||||
*
|
*
|
||||||
@ -116,15 +19,75 @@ type YourStateTypeNeedsToBeImmutable<TState> = {};
|
|||||||
* @param reducer A function that takes the previous state and the dispatched action and returns the new state.
|
* @param reducer A function that takes the previous state and the dispatched action and returns the new state.
|
||||||
* @param initialState The initial state of the service.
|
* @param initialState The initial state of the service.
|
||||||
*/
|
*/
|
||||||
export function createStateService<TState, TAction extends { type: string }>(
|
export function createReducingService<TState>(initialState: TState) {
|
||||||
reducer: (state: TState, action: TAction) => TState,
|
const stateServiceClass = class extends ReducingService<TState> {
|
||||||
initialState: TState
|
|
||||||
) {
|
|
||||||
const stateServiceClass = class extends StateService<TState, TAction> {
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super(reducer, initialState);
|
super(initialState);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return stateServiceClass as IfImmutable<TState, typeof stateServiceClass, YourStateTypeNeedsToBeImmutable<TState>>;
|
return stateServiceClass as IfImmutable<TState, typeof stateServiceClass, YourStateTypeNeedsToBeImmutable<TState>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IReducingAction<TState> {
|
||||||
|
handle: (state: TState) => TState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a deeply-immutable type from the provided type. Objects' properties will be marked as `readonly`, array types
|
||||||
|
* will be replaced with {@link ReadonlyArray}, {@link Map} types will be replaced with {@link ReadonlyMap}, and
|
||||||
|
* {@link Set} types will be replaced with {@link ReadonlySet}.
|
||||||
|
*/
|
||||||
|
export type Immutable<T> = T extends undefined | null | boolean | string | number
|
||||||
|
? T
|
||||||
|
: T extends Array<infer U>
|
||||||
|
? ReadonlyArray<Immutable<U>>
|
||||||
|
: T extends Map<infer K, infer V>
|
||||||
|
? ReadonlyMap<Immutable<K>, Immutable<V>>
|
||||||
|
: T extends Set<infer M>
|
||||||
|
? ReadonlySet<Immutable<M>>
|
||||||
|
: { readonly [N in keyof T]: Immutable<T[N]> };
|
||||||
|
|
||||||
|
type IfEquals<X, Y, A = X, B = never> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? A : B;
|
||||||
|
type IfImmutable<TState extends {}, TImmutable = TState, TMutable = never> = IfEquals<
|
||||||
|
TState,
|
||||||
|
{ readonly [K in keyof TState]: Immutable<TState[K]> },
|
||||||
|
TImmutable,
|
||||||
|
TMutable
|
||||||
|
>;
|
||||||
|
|
||||||
|
// eslint-disable-next-line
|
||||||
|
type YourStateTypeNeedsToBeImmutable<TState> = {};
|
||||||
|
|
||||||
|
class ReducingService<TState> {
|
||||||
|
private internalState$: BehaviorSubject<TState>;
|
||||||
|
|
||||||
|
constructor(private initialState: TState) {
|
||||||
|
this.internalState$ = new BehaviorSubject(initialState);
|
||||||
|
}
|
||||||
|
|
||||||
|
// expose as observable.
|
||||||
|
public get state$() {
|
||||||
|
return this.internalState$.asObservable();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected dispatch(action: IReducingAction<TState>) {
|
||||||
|
this.internalState$.next(action.handle(this.internalState$.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current state managed by the service. **You should only use the current state to validate operations or
|
||||||
|
* help to construct actions to be dispatched.** Try not to expose any state retrieved using this method outside the
|
||||||
|
* derived service class.
|
||||||
|
*/
|
||||||
|
protected getState(): TState {
|
||||||
|
return this.internalState$.value;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Creates an observable that provides data derived from the state managed by the service.
|
||||||
|
* @param selector A selector that maps the state to the derived data.
|
||||||
|
*/
|
||||||
|
public select<TDerived>(selector: (state: TState) => TDerived): Observable<TDerived> {
|
||||||
|
return this.internalState$.pipe(map(selector), distinctUntilChanged());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -22,5 +22,5 @@ export interface UserVersion {
|
|||||||
|
|
||||||
export enum StorableType {
|
export enum StorableType {
|
||||||
initial,
|
initial,
|
||||||
modified
|
modified,
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { OnDestroy, Injectable } from '@angular/core';
|
import { Injectable,OnDestroy } from '@angular/core';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
|
@ -1,16 +1,14 @@
|
|||||||
<div mat-dialog-title>
|
<mat-toolbar>
|
||||||
<mat-toolbar>
|
<mat-icon>save</mat-icon>
|
||||||
<mat-icon>save</mat-icon>
|
<div class="title">Add Card to Saved Page</div>
|
||||||
<div class="title">Add Card to Saved Page</div>
|
</mat-toolbar>
|
||||||
</mat-toolbar>
|
|
||||||
</div>
|
|
||||||
<mat-dialog-content class="content">
|
<mat-dialog-content class="content">
|
||||||
<div class="page-list">
|
<div class="page-list">
|
||||||
<mat-selection-list #pageList>
|
<mat-selection-list #pageList>
|
||||||
<mat-list-option
|
<mat-list-option
|
||||||
*ngFor="let page of this.pages$ | async"
|
*ngFor="let page of this.pages$ | async"
|
||||||
[value]="page"
|
[value]="page"
|
||||||
[checkBoxPosition]="before"
|
[checkboxPosition]="'before'"
|
||||||
>
|
>
|
||||||
{{ page.title }}
|
{{ page.title }}
|
||||||
</mat-list-option>
|
</mat-list-option>
|
||||||
@ -26,7 +24,6 @@
|
|||||||
><button
|
><button
|
||||||
class="page-add-button"
|
class="page-add-button"
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
mat-button
|
|
||||||
[disableRipple]="true"
|
[disableRipple]="true"
|
||||||
(click)="addPage()"
|
(click)="addPage()"
|
||||||
>
|
>
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import { Component, Inject, ViewChild } from '@angular/core';
|
import { Component, Inject, ViewChild } from '@angular/core';
|
||||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
|
||||||
import { MatSelectionList } from '@angular/material/list';
|
|
||||||
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
|
||||||
import { AppService } from '../../services/app.service';
|
import { MAT_DIALOG_DATA,MatDialogRef } from '@angular/material/dialog';
|
||||||
|
import { MatSelectionList } from '@angular/material/list';
|
||||||
|
import { AppService } from 'src/app/services/app.service';
|
||||||
|
|
||||||
import { CardItem } from '../../models/card-state';
|
import { CardItem } from '../../models/card-state';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
import { EventEmitter, Output, Input, ElementRef, Component } from '@angular/core';
|
import { Clipboard } from '@angular/cdk/clipboard';
|
||||||
import { Observable } from 'rxjs';
|
import { Component,ElementRef, EventEmitter, Input, Output } from '@angular/core';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { SubscriberBase } from '../common/subscriber-base';
|
import { Observable } from 'rxjs';
|
||||||
import { AppService } from 'src/app/services/app.service';
|
|
||||||
import { MoveDirection } from '../common/move-direction';
|
import { MoveDirection } from '../common/move-direction';
|
||||||
|
import { SubscriberBase } from '../common/subscriber-base';
|
||||||
import { AddToPageModalComponent } from '../components/add-to-page-modal/add-to-page-modal.component';
|
import { AddToPageModalComponent } from '../components/add-to-page-modal/add-to-page-modal.component';
|
||||||
import { CardItem } from '../models/card-state';
|
import { CardItem } from '../models/card-state';
|
||||||
|
import { AppService } from '../services/app.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
template: '',
|
template: '',
|
||||||
@ -19,19 +21,29 @@ export class CardComponent extends SubscriberBase {
|
|||||||
|
|
||||||
icon$: Observable<string>;
|
icon$: Observable<string>;
|
||||||
|
|
||||||
constructor(protected elementRef: ElementRef, protected dialog: MatDialog, protected appService: AppService) {
|
constructor(
|
||||||
|
protected elementRef: ElementRef,
|
||||||
|
protected dialog: MatDialog,
|
||||||
|
protected appService: AppService,
|
||||||
|
protected clipboard: Clipboard
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected copyToClip(text: string, html: string) {
|
protected copyToClip(text: string) {
|
||||||
function listener(e: ClipboardEvent) {
|
this.clipboard.copy(text);
|
||||||
e.clipboardData.setData('text/html', html);
|
const pending = this.clipboard.beginCopy(text);
|
||||||
e.clipboardData.setData('text/plain', text);
|
let remainingAttempts = 3;
|
||||||
e.preventDefault();
|
const attempt = () => {
|
||||||
}
|
const result = pending.copy();
|
||||||
document.addEventListener('copy', listener);
|
if (!result && --remainingAttempts) {
|
||||||
document.execCommand('copy');
|
setTimeout(attempt, 10);
|
||||||
document.removeEventListener('copy', listener);
|
} else {
|
||||||
|
// Remember to destroy when you're done!
|
||||||
|
pending.destroy();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
attempt();
|
||||||
}
|
}
|
||||||
|
|
||||||
close(ev) {
|
close(ev) {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
import { NavService } from '../../services/nav.service';
|
import { NavService } from '../../services/nav.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
<div mat-dialog-title>
|
<mat-toolbar>
|
||||||
<mat-toolbar>
|
<mat-icon>edit</mat-icon>
|
||||||
<mat-icon>edit</mat-icon>
|
<div class="title">Edit: {{ data.title }}</div>
|
||||||
<div class="title">Edit: {{ data.title }}</div>
|
</mat-toolbar>
|
||||||
</mat-toolbar>
|
|
||||||
</div>
|
|
||||||
<mat-dialog-content>
|
<mat-dialog-content>
|
||||||
|
<br />
|
||||||
<form [formGroup]="noteForm">
|
<form [formGroup]="noteForm">
|
||||||
<mat-form-field class="note-title">
|
<mat-form-field class="note-title">
|
||||||
<mat-label>Title</mat-label>
|
<mat-label>Title</mat-label>
|
||||||
@ -15,7 +14,6 @@
|
|||||||
<mat-chip-grid #chipList aria-label="Cross References">
|
<mat-chip-grid #chipList aria-label="Cross References">
|
||||||
<mat-chip-row
|
<mat-chip-row
|
||||||
*ngFor="let ref of references"
|
*ngFor="let ref of references"
|
||||||
[selectable]="selectable"
|
|
||||||
[removable]="removable"
|
[removable]="removable"
|
||||||
(removed)="remove(ref)"
|
(removed)="remove(ref)"
|
||||||
>
|
>
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
import { Component, Inject } from '@angular/core';
|
|
||||||
import { UntypedFormGroup, UntypedFormBuilder } from '@angular/forms';
|
|
||||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
|
||||||
|
|
||||||
import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes';
|
import { COMMA, ENTER, SEMICOLON } from '@angular/cdk/keycodes';
|
||||||
|
import { Component, Inject } from '@angular/core';
|
||||||
|
import { UntypedFormBuilder,UntypedFormGroup } from '@angular/forms';
|
||||||
import { MatChipInputEvent } from '@angular/material/chips';
|
import { MatChipInputEvent } from '@angular/material/chips';
|
||||||
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||||
import { UUID } from 'angular2-uuid';
|
import { UUID } from 'angular2-uuid';
|
||||||
|
import { CardItem } from 'src/app/models/card-state';
|
||||||
import { NoteItem } from 'src/app/models/note-state';
|
import { NoteItem } from 'src/app/models/note-state';
|
||||||
import { AppService } from 'src/app/services/app.service';
|
import { AppService } from 'src/app/services/app.service';
|
||||||
import { CardItem } from 'src/app/models/card-state';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-note-edit-modal',
|
selector: 'app-note-edit-modal',
|
||||||
@ -23,7 +20,6 @@ export class NoteEditModalComponent {
|
|||||||
|
|
||||||
//#region Cross References
|
//#region Cross References
|
||||||
visible = true;
|
visible = true;
|
||||||
selectable = true;
|
|
||||||
removable = true;
|
removable = true;
|
||||||
addOnBlur = true;
|
addOnBlur = true;
|
||||||
readonly separatorKeysCodes: number[] = [ENTER, COMMA, SEMICOLON];
|
readonly separatorKeysCodes: number[] = [ENTER, COMMA, SEMICOLON];
|
||||||
@ -54,16 +50,11 @@ export class NoteEditModalComponent {
|
|||||||
//#region cross refs
|
//#region cross refs
|
||||||
|
|
||||||
add(event: MatChipInputEvent): void {
|
add(event: MatChipInputEvent): void {
|
||||||
const input = event.input;
|
|
||||||
const value = event.value;
|
const value = event.value;
|
||||||
|
|
||||||
if ((value || '').trim()) {
|
if ((value || '').trim()) {
|
||||||
this.references.push(value.trim());
|
this.references.push(value.trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (input) {
|
|
||||||
input.value = '';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
remove(reference: string): void {
|
remove(reference: string): void {
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
import { Component, ViewChild, ElementRef, Input, OnInit } from '@angular/core';
|
import { Clipboard } from '@angular/cdk/clipboard';
|
||||||
|
import { Component, ElementRef, Input,ViewChild } from '@angular/core';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { NoteEditModalComponent } from './edit-modal/note-edit-modal.component';
|
import { BibleReference } from 'src/app/common/bible-reference';
|
||||||
import { CardComponent } from '../../components/card.component';
|
import { NoteItem } from 'src/app/models/note-state';
|
||||||
import { AppService } from '../../services/app.service';
|
import { AppService } from 'src/app/services/app.service';
|
||||||
import { BibleReference } from '../../common/bible-reference';
|
|
||||||
import { NoteItem } from '../../models/note-state';
|
import { CardComponent } from '../card.component';
|
||||||
import { OkCancelModalComponent, OkCancelResult } from '../ok-cancel-modal/ok-cancel-modal.component';
|
import { OkCancelModalComponent, OkCancelResult } from '../ok-cancel-modal/ok-cancel-modal.component';
|
||||||
|
import { NoteEditModalComponent } from './edit-modal/note-edit-modal.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-note-card',
|
selector: 'app-note-card',
|
||||||
@ -22,16 +24,20 @@ export class NoteCardComponent extends CardComponent {
|
|||||||
return this.cardItem.data as NoteItem;
|
return this.cardItem.data as NoteItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(protected elementRef: ElementRef, protected appService: AppService, public dialog: MatDialog) {
|
constructor(
|
||||||
super(elementRef, dialog, appService);
|
protected elementRef: ElementRef,
|
||||||
|
protected appService: AppService,
|
||||||
|
protected clipboard: Clipboard,
|
||||||
|
public dialog: MatDialog
|
||||||
|
) {
|
||||||
|
super(elementRef, dialog, appService, clipboard);
|
||||||
|
|
||||||
this.icon$ = appService.select((state) => state.settings.value.cardIcons.note);
|
this.icon$ = appService.select((state) => state.settings.value.cardIcons.note);
|
||||||
}
|
}
|
||||||
|
|
||||||
copy() {
|
copy() {
|
||||||
const html = this.noteElement.nativeElement.innerHTML;
|
|
||||||
const text = this.noteElement.nativeElement.innerText;
|
const text = this.noteElement.nativeElement.innerText;
|
||||||
this.copyToClip(text, html);
|
this.copyToClip(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
private xrefs: BibleReference[];
|
private xrefs: BibleReference[];
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
<div mat-dialog-title>
|
<mat-toolbar>
|
||||||
<mat-toolbar>
|
<mat-icon>save</mat-icon>
|
||||||
<mat-icon>save</mat-icon>
|
<div class="title">{{ dialogTitle }}</div>
|
||||||
<div class="title">{{ dialogTitle }}</div>
|
</mat-toolbar>
|
||||||
</mat-toolbar>
|
|
||||||
</div>
|
|
||||||
<mat-dialog-content class="content">
|
<mat-dialog-content class="content">
|
||||||
<form [formGroup]="form">
|
<form [formGroup]="form">
|
||||||
<mat-form-field class="page-title">
|
<mat-form-field class="page-title">
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
import { Component, Inject } from '@angular/core';
|
import { Component, Inject } from '@angular/core';
|
||||||
import { UntypedFormGroup, UntypedFormBuilder } from '@angular/forms';
|
import { UntypedFormBuilder,UntypedFormGroup } from '@angular/forms';
|
||||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
import { MAT_DIALOG_DATA,MatDialogRef } from '@angular/material/dialog';
|
||||||
import { AppService } from '../../services/app.service';
|
|
||||||
import { SavedPage } from 'src/app/models/page-state';
|
import { SavedPage } from 'src/app/models/page-state';
|
||||||
|
import { AppService } from 'src/app/services/app.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-page-edit-modal',
|
selector: 'app-page-edit-modal',
|
||||||
|
@ -40,10 +40,10 @@
|
|||||||
<ng-container *ngFor="let w of vs.w">
|
<ng-container *ngFor="let w of vs.w">
|
||||||
<a
|
<a
|
||||||
[title]="getDict(this.cardItem) + w.s"
|
[title]="getDict(this.cardItem) + w.s"
|
||||||
*ngIf="w.s !== null"
|
*ngIf="w.s !== null && w.s !== undefined"
|
||||||
(click)="openStrongs(w.s, display.showStrongsAsModal)"
|
(click)="openStrongs(w.s, display.showStrongsAsModal)"
|
||||||
>{{ w.t }}</a
|
>{{ w.t }}</a
|
||||||
><ng-container *ngIf="w.s === null">{{
|
><ng-container *ngIf="w.s === null || w.s === undefined">{{
|
||||||
w.t
|
w.t
|
||||||
}}</ng-container> </ng-container
|
}}</ng-container> </ng-container
|
||||||
><br *ngIf="display.showVersesOnNewLine" />
|
><br *ngIf="display.showVersesOnNewLine" />
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
import { Component, OnInit, ElementRef, ViewChild, ChangeDetectionStrategy } from '@angular/core';
|
import { Clipboard } from '@angular/cdk/clipboard';
|
||||||
|
import { ChangeDetectionStrategy,Component, ElementRef, OnInit, ViewChild } from '@angular/core';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { StrongsModalComponent } from '../strongs/modal/strongs-modal.component';
|
|
||||||
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 { BibleReference, Overlap } from 'src/app/common/bible-reference';
|
||||||
import { AppService } from 'src/app/services/app.service';
|
|
||||||
import { Paragraph, BiblePassageResult } from 'src/app/models/passage-state';
|
|
||||||
import { CardItem } from 'src/app/models/card-state';
|
|
||||||
import { isNullOrUndefined } from 'src/app/common/helpers';
|
import { isNullOrUndefined } from 'src/app/common/helpers';
|
||||||
|
import { CardComponent } from 'src/app/components/card.component';
|
||||||
|
import { CardItem } from 'src/app/models/card-state';
|
||||||
|
import { NoteItem } from 'src/app/models/note-state';
|
||||||
|
import { BiblePassageResult,Paragraph } from 'src/app/models/passage-state';
|
||||||
|
import { AppService } from 'src/app/services/app.service';
|
||||||
|
|
||||||
|
import { StrongsModalComponent } from '../strongs/modal/strongs-modal.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-passage-card',
|
selector: 'app-passage-card',
|
||||||
@ -40,8 +42,13 @@ export class PassageCardComponent extends CardComponent implements OnInit {
|
|||||||
return this.cardItem.data as BiblePassageResult;
|
return this.cardItem.data as BiblePassageResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(protected elementRef: ElementRef, protected appService: AppService, public dialog: MatDialog) {
|
constructor(
|
||||||
super(elementRef, dialog, appService);
|
protected elementRef: ElementRef,
|
||||||
|
protected appService: AppService,
|
||||||
|
protected clipboard: Clipboard,
|
||||||
|
public dialog: MatDialog
|
||||||
|
) {
|
||||||
|
super(elementRef, dialog, appService, clipboard);
|
||||||
this.icon$ = appService.select((state) => state.settings.value.cardIcons.passage);
|
this.icon$ = appService.select((state) => state.settings.value.cardIcons.passage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,9 +61,8 @@ export class PassageCardComponent extends CardComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
copy() {
|
copy() {
|
||||||
const html = this.passageElement.nativeElement.innerHTML + ` - ${this.ref.toString()}`;
|
const text = this.passageElement.nativeElement.innerText + ` \n - ${this.ref.toString()}`;
|
||||||
const text = this.passageElement.nativeElement.innerText + ` - ${this.ref.toString()}`;
|
this.copyToClip(text);
|
||||||
this.copyToClip(text, html);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
next() {
|
next() {
|
||||||
@ -144,16 +150,20 @@ export class PassageCardComponent extends CardComponent implements OnInit {
|
|||||||
async openStrongs(q: string, asModal = false) {
|
async openStrongs(q: string, asModal = false) {
|
||||||
const dict = (this.cardItem.data as BiblePassageResult).dict;
|
const dict = (this.cardItem.data as BiblePassageResult).dict;
|
||||||
const numbers = q.split(' ');
|
const numbers = q.split(' ');
|
||||||
for (const sn of numbers) {
|
|
||||||
if (asModal) {
|
if (asModal) {
|
||||||
|
const cards: CardItem[] = [];
|
||||||
|
for (const sn of numbers) {
|
||||||
const card = await this.appService.getStrongsCard(sn, dict);
|
const card = await this.appService.getStrongsCard(sn, dict);
|
||||||
this.dialog.open(StrongsModalComponent, {
|
cards.push(card);
|
||||||
data: card,
|
|
||||||
autoFocus: 'content',
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.appService.getStrongs(sn, dict, this.cardItem);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.dialog.open(StrongsModalComponent, {
|
||||||
|
data: cards,
|
||||||
|
autoFocus: 'content',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.appService.getStrongs(numbers, dict, this.cardItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,17 +1,18 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
|
||||||
import { CdkDragDrop } from '@angular/cdk/drag-drop';
|
import { CdkDragDrop } from '@angular/cdk/drag-drop';
|
||||||
|
import { Component, Input } from '@angular/core';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { AppService } from '../../services/app.service';
|
|
||||||
import { Observable } from 'rxjs';
|
|
||||||
import { SavedPage } from 'src/app/models/page-state';
|
|
||||||
import { CardIcons, CardItem, CardType, DataReference } from 'src/app/models/card-state';
|
|
||||||
import { OkCancelModalComponent, OkCancelResult } from '../ok-cancel-modal/ok-cancel-modal.component';
|
|
||||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
import { PageEditModalComponent } from '../page-edit-modal/page-edit-modal.component';
|
import { Observable } from 'rxjs';
|
||||||
|
import { getFromCardCache } from 'src/app/common/card-cache-operations';
|
||||||
import { HashTable } from 'src/app/common/hashtable';
|
import { HashTable } from 'src/app/common/hashtable';
|
||||||
import { SubscriberBase } from 'src/app/common/subscriber-base';
|
import { SubscriberBase } from 'src/app/common/subscriber-base';
|
||||||
import { getFromCardCache } from 'src/app/common/card-cache-operations';
|
import { CardIcons, CardItem, CardType, DataReference } from 'src/app/models/card-state';
|
||||||
import { NoteItem } from 'src/app/models/note-state';
|
import { NoteItem } from 'src/app/models/note-state';
|
||||||
|
import { SavedPage } from 'src/app/models/page-state';
|
||||||
|
import { AppService } from 'src/app/services/app.service';
|
||||||
|
|
||||||
|
import { OkCancelModalComponent, OkCancelResult } from '../ok-cancel-modal/ok-cancel-modal.component';
|
||||||
|
import { PageEditModalComponent } from '../page-edit-modal/page-edit-modal.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-saved-page-card',
|
selector: 'app-saved-page-card',
|
||||||
@ -82,12 +83,12 @@ export class SavedPageCardComponent extends SubscriberBase {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
onRemoveCard(card: CardItem) {
|
onRemoveCard(reference: DataReference) {
|
||||||
this.dialog
|
this.dialog
|
||||||
.open(OkCancelModalComponent, {
|
.open(OkCancelModalComponent, {
|
||||||
data: {
|
data: {
|
||||||
title: 'Delete Card from Saved Page',
|
title: 'Delete Card from Saved Page',
|
||||||
content: `Do you want to delete this card '${this.format(card)}' from the saved page '${
|
content: `Do you want to delete this card '${this.format(reference)}' from the saved page '${
|
||||||
this.savedPage.title
|
this.savedPage.title
|
||||||
}?`,
|
}?`,
|
||||||
},
|
},
|
||||||
@ -97,7 +98,7 @@ export class SavedPageCardComponent extends SubscriberBase {
|
|||||||
if (ds.ok) {
|
if (ds.ok) {
|
||||||
this.appService.updateSavedPage({
|
this.appService.updateSavedPage({
|
||||||
...this.savedPage,
|
...this.savedPage,
|
||||||
queries: this.savedPage.queries.filter((o) => o !== card),
|
queries: this.savedPage.queries.filter((o) => o !== reference),
|
||||||
});
|
});
|
||||||
this.snackBar.open(`${this.savedPage.title} has been updated!`, '', {
|
this.snackBar.open(`${this.savedPage.title} has been updated!`, '', {
|
||||||
duration: 3 * 1000,
|
duration: 3 * 1000,
|
||||||
|
@ -18,6 +18,10 @@
|
|||||||
<mat-icon matListIcon color="accenovert">note_add</mat-icon>
|
<mat-icon matListIcon color="accenovert">note_add</mat-icon>
|
||||||
Create a New Note
|
Create a New Note
|
||||||
</a>
|
</a>
|
||||||
|
<a mat-list-item (click)="clearCurrentCard()">
|
||||||
|
<mat-icon matListIcon color="accenovert">clear_all</mat-icon>
|
||||||
|
Clear Cards
|
||||||
|
</a>
|
||||||
</mat-nav-list>
|
</mat-nav-list>
|
||||||
|
|
||||||
<mat-toolbar>Search Settings</mat-toolbar>
|
<mat-toolbar>Search Settings</mat-toolbar>
|
||||||
@ -118,13 +122,7 @@
|
|||||||
><input
|
><input
|
||||||
matSliderThumb
|
matSliderThumb
|
||||||
[(ngModel)]="cardFontSize"
|
[(ngModel)]="cardFontSize"
|
||||||
(change)="
|
(valueChange)="cardFontSizeChanged($event)"
|
||||||
cardFontSizeChanged({
|
|
||||||
source: ngSliderThumb,
|
|
||||||
parent: ngSlider,
|
|
||||||
value: ngSliderThumb.value
|
|
||||||
})
|
|
||||||
"
|
|
||||||
#ngSliderThumb="matSliderThumb"
|
#ngSliderThumb="matSliderThumb"
|
||||||
/>
|
/>
|
||||||
</mat-slider>
|
</mat-slider>
|
||||||
|
@ -1,27 +1,23 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { MatSlideToggleChange } from '@angular/material/slide-toggle';
|
|
||||||
import { MatSelectChange } from '@angular/material/select';
|
|
||||||
import { MatSliderChange } from '@angular/material/slider';
|
|
||||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
|
||||||
|
|
||||||
import { AngularFireAuth } from '@angular/fire/compat/auth';
|
import { AngularFireAuth } from '@angular/fire/compat/auth';
|
||||||
import firebase from '@firebase/app-compat';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
|
import { MatSelectChange } from '@angular/material/select';
|
||||||
|
import { MatSlideToggleChange } from '@angular/material/slide-toggle';
|
||||||
|
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||||
import { Capacitor } from '@capacitor/core';
|
import { Capacitor } from '@capacitor/core';
|
||||||
import { GoogleAuth } from '@codetrix-studio/capacitor-google-auth'
|
import { GoogleAuth } from '@codetrix-studio/capacitor-google-auth'
|
||||||
|
import firebase from '@firebase/app-compat';
|
||||||
|
import { Overlap } from 'src/app/common/bible-reference';
|
||||||
|
import { NoteEditModalComponent } from 'src/app/components/note/edit-modal/note-edit-modal.component';
|
||||||
|
import { PageEditModalComponent } from 'src/app/components/page-edit-modal/page-edit-modal.component';
|
||||||
|
import { CardFonts } from 'src/app/constants';
|
||||||
|
import { DisplaySettings } from 'src/app/models/app-state';
|
||||||
|
import { SavedPage } from 'src/app/models/page-state';
|
||||||
|
import { AppService } from 'src/app/services/app.service';
|
||||||
|
import { NavService } from 'src/app/services/nav.service';
|
||||||
|
|
||||||
import { SubscriberBase } from '../../common/subscriber-base';
|
import { SubscriberBase } from '../../common/subscriber-base';
|
||||||
import { DisplaySettings } from 'src/app/models/app-state';
|
|
||||||
import { CardFonts } from 'src/app/constants';
|
|
||||||
|
|
||||||
import { NavService } from 'src/app/services/nav.service';
|
|
||||||
import { AppService } from 'src/app/services/app.service';
|
|
||||||
|
|
||||||
import { OkCancelModalComponent, OkCancelResult } from '../ok-cancel-modal/ok-cancel-modal.component';
|
import { OkCancelModalComponent, OkCancelResult } from '../ok-cancel-modal/ok-cancel-modal.component';
|
||||||
import { PageEditModalComponent } from 'src/app/components/page-edit-modal/page-edit-modal.component';
|
|
||||||
import { NoteEditModalComponent } from 'src/app/components/note/edit-modal/note-edit-modal.component';
|
|
||||||
import { SavedPage } from 'src/app/models/page-state';
|
|
||||||
import { Overlap } from 'src/app/common/bible-reference';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-settings',
|
selector: 'app-settings',
|
||||||
@ -83,7 +79,7 @@ export class SettingsComponent extends SubscriberBase {
|
|||||||
const credential = firebase.auth.GoogleAuthProvider.credential(googleUser.authentication.idToken);
|
const credential = firebase.auth.GoogleAuthProvider.credential(googleUser.authentication.idToken);
|
||||||
(await this.authService.app).auth().signInWithCredential(credential);
|
(await this.authService.app).auth().signInWithCredential(credential);
|
||||||
} else {
|
} else {
|
||||||
this.authService.signInWithPopup(new firebase.auth.GoogleAuthProvider()).then((cred) => {
|
this.authService.signInWithPopup(new firebase.auth.GoogleAuthProvider()).then(() => {
|
||||||
console.log('Authenticated.');
|
console.log('Authenticated.');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -134,6 +130,11 @@ export class SettingsComponent extends SubscriberBase {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearCurrentCard(){
|
||||||
|
this.appService.clearCards();
|
||||||
|
this.navService.closeSettings();
|
||||||
|
}
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
|
||||||
//#region Saved Page Settings
|
//#region Saved Page Settings
|
||||||
@ -150,8 +151,8 @@ export class SettingsComponent extends SubscriberBase {
|
|||||||
this.appService.changeCardFontFamily(evt.value);
|
this.appService.changeCardFontFamily(evt.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
cardFontSizeChanged(evt: MatSliderChange) {
|
cardFontSizeChanged(evt: number) {
|
||||||
this.appService.changeCardFontSize(evt.value);
|
this.appService.changeCardFontSize(evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="card-content" *ngIf="cardItem" #strongs>
|
<div class="card-content" *ngIf="cardItem" #strongs>
|
||||||
<app-strongs
|
<app-strongs
|
||||||
[data]="cardItem.data"
|
[data]="strongsResult"
|
||||||
[isCard]="true"
|
[isCard]="true"
|
||||||
(openPassage)="openPassage($event)"
|
(openPassage)="openPassage($event)"
|
||||||
(openStrongs)="openStrongs($event)"
|
(openStrongs)="openStrongs($event)"
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
import { Component, ElementRef, ViewChild, OnInit, ChangeDetectionStrategy } from '@angular/core';
|
import { Clipboard } from '@angular/cdk/clipboard';
|
||||||
|
import { ChangeDetectionStrategy, Component, ElementRef, Input,ViewChild } from '@angular/core';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { StrongsModalComponent } from '../modal/strongs-modal.component';
|
|
||||||
import { CardComponent } from 'src/app/components/card.component';
|
|
||||||
import { AppService } from 'src/app/services/app.service';
|
|
||||||
import { BibleReference } from 'src/app/common/bible-reference';
|
import { BibleReference } from 'src/app/common/bible-reference';
|
||||||
|
import { CardComponent } from 'src/app/components/card.component';
|
||||||
|
import { StrongsResult } from 'src/app/models/strongs-state';
|
||||||
|
import { AppService } from 'src/app/services/app.service';
|
||||||
|
|
||||||
|
import { StrongsModalComponent } from '../modal/strongs-modal.component';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-strongs-card',
|
selector: 'app-strongs-card',
|
||||||
@ -16,8 +19,20 @@ export class StrongsCardComponent extends CardComponent {
|
|||||||
asModal = false;
|
asModal = false;
|
||||||
@ViewChild('strongs') strongsElement: ElementRef;
|
@ViewChild('strongs') strongsElement: ElementRef;
|
||||||
|
|
||||||
constructor(protected elementRef: ElementRef, protected appService: AppService, protected dialog: MatDialog) {
|
@Input()
|
||||||
super(elementRef, dialog, appService);
|
data: StrongsResult;
|
||||||
|
|
||||||
|
get strongsResult() {
|
||||||
|
return this.cardItem.data as StrongsResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
protected elementRef: ElementRef,
|
||||||
|
protected appService: AppService,
|
||||||
|
protected clipboard: Clipboard,
|
||||||
|
protected dialog: MatDialog
|
||||||
|
) {
|
||||||
|
super(elementRef, dialog, appService, clipboard);
|
||||||
this.icon$ = appService.select((state) => state.settings.value.cardIcons.strongs);
|
this.icon$ = appService.select((state) => state.settings.value.cardIcons.strongs);
|
||||||
this.addSubscription(
|
this.addSubscription(
|
||||||
this.appService.state$.subscribe((state) => {
|
this.appService.state$.subscribe((state) => {
|
||||||
@ -27,9 +42,8 @@ export class StrongsCardComponent extends CardComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
copy() {
|
copy() {
|
||||||
const html = this.strongsElement.nativeElement.innerHTML;
|
|
||||||
const text = this.strongsElement.nativeElement.innerText;
|
const text = this.strongsElement.nativeElement.innerText;
|
||||||
this.copyToClip(text, html);
|
this.copyToClip(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
async openStrongs(q: string) {
|
async openStrongs(q: string) {
|
||||||
@ -42,7 +56,7 @@ export class StrongsCardComponent extends CardComponent {
|
|||||||
autoFocus: 'content',
|
autoFocus: 'content',
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.appService.getStrongs(sn, dict, this.cardItem);
|
this.appService.getStrongs([sn], dict, this.cardItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,22 +1,32 @@
|
|||||||
<mat-toolbar>
|
<mat-toolbar>
|
||||||
<mat-icon aria-hidden="false" aria-label="Strongs Entry Icon">{{
|
<mat-icon aria-hidden="false" aria-label="Strongs Entry Icon">{{
|
||||||
icon$ | async
|
icon$ | async
|
||||||
}}</mat-icon>
|
}}</mat-icon>
|
||||||
<div class="title">{{ cardItem.qry }}</div>
|
<div class="title">{{ this.title }}</div>
|
||||||
<span class="close-button">
|
<span class="close-button">
|
||||||
<button
|
<button
|
||||||
mat-icon-button
|
mat-icon-button
|
||||||
mat-dialog-close
|
mat-dialog-close
|
||||||
aria-label="Exit the Strongs Modal"
|
aria-label="Exit the Strongs Modal"
|
||||||
>
|
>
|
||||||
<mat-icon>cancel</mat-icon>
|
<mat-icon>cancel</mat-icon>
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
</mat-toolbar>
|
</mat-toolbar>
|
||||||
<mat-dialog-content class="content">
|
<mat-dialog-content class="content">
|
||||||
<br />
|
<mat-tab-group *ngIf="strongsResults.length > 1">
|
||||||
<app-strongs
|
<mat-tab *ngFor="let card of strongsResults">
|
||||||
[data]="cardItem.data"
|
<ng-template mat-tab-label>{{ card.prefix }}{{ card.sn }}</ng-template>
|
||||||
(openPassage)="openPassage($event)"
|
<app-strongs
|
||||||
></app-strongs>
|
[data]="card"
|
||||||
|
(openPassage)="openPassage($event)"
|
||||||
|
></app-strongs>
|
||||||
|
</mat-tab>
|
||||||
|
</mat-tab-group>
|
||||||
|
<ng-container *ngIf="strongsResults.length === 1">
|
||||||
|
<app-strongs
|
||||||
|
[data]="strongsResults[0]"
|
||||||
|
(openPassage)="openPassage($event)"
|
||||||
|
></app-strongs>
|
||||||
|
</ng-container>
|
||||||
</mat-dialog-content>
|
</mat-dialog-content>
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { Component, Inject, ChangeDetectionStrategy } from '@angular/core';
|
import { ChangeDetectionStrategy,Component, Inject } from '@angular/core';
|
||||||
import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog';
|
import { MAT_DIALOG_DATA,MatDialogRef } from '@angular/material/dialog';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { AppService } from 'src/app/services/app.service';
|
|
||||||
import { BibleReference } from 'src/app/common/bible-reference';
|
import { BibleReference } from 'src/app/common/bible-reference';
|
||||||
import { CardItem } from 'src/app/models/card-state';
|
import { CardItem } from 'src/app/models/card-state';
|
||||||
|
import { StrongsResult } from 'src/app/models/strongs-state';
|
||||||
|
import { AppService } from 'src/app/services/app.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-strongs-modal',
|
selector: 'app-strongs-modal',
|
||||||
@ -14,14 +15,16 @@ import { CardItem } from 'src/app/models/card-state';
|
|||||||
})
|
})
|
||||||
export class StrongsModalComponent {
|
export class StrongsModalComponent {
|
||||||
icon$: Observable<string>;
|
icon$: Observable<string>;
|
||||||
|
strongsResults: StrongsResult[];
|
||||||
|
title: string;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(MAT_DIALOG_DATA) public cardItem: CardItem,
|
@Inject(MAT_DIALOG_DATA) public cardItems: CardItem[],
|
||||||
public dialogRef: MatDialogRef<StrongsModalComponent>,
|
public dialogRef: MatDialogRef<StrongsModalComponent>,
|
||||||
private appService: AppService
|
private appService: AppService
|
||||||
) {
|
) {
|
||||||
console.log(cardItem);
|
this.title = cardItems.map(o => o.qry).reduce((p, c) => `${p}, ${c}`);
|
||||||
|
this.strongsResults = cardItems.map(o => o.data as StrongsResult);
|
||||||
this.icon$ = appService.select((state) => state.settings.value.cardIcons.strongs);
|
this.icon$ = appService.select((state) => state.settings.value.cardIcons.strongs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,6 +34,6 @@ export class StrongsModalComponent {
|
|||||||
|
|
||||||
openPassage(p: string) {
|
openPassage(p: string) {
|
||||||
const ref = BibleReference.makePassageFromReferenceKey(p);
|
const ref = BibleReference.makePassageFromReferenceKey(p);
|
||||||
this.appService.getPassage(ref, this.cardItem);
|
this.appService.getPassage(ref, this.cardItems[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
import { Component, EventEmitter,Input, Output } from '@angular/core';
|
||||||
import { BibleReference } from 'src/app/common/bible-reference';
|
import { BibleReference } from 'src/app/common/bible-reference';
|
||||||
|
|
||||||
import { StrongsResult } from '../../models/strongs-state';
|
import { StrongsResult } from '../../models/strongs-state';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
@ -1,18 +1,12 @@
|
|||||||
<div mat-dialog-title>
|
<mat-toolbar>
|
||||||
<mat-toolbar>
|
<mat-icon>bookmarks</mat-icon>
|
||||||
<mat-icon>bookmarks</mat-icon>
|
<div class="title">Verse Picker</div>
|
||||||
<div class="title">Verse Picker</div>
|
<span class="close-button">
|
||||||
<span class="close-button">
|
<button mat-icon-button mat-dialog-close aria-label="Exit the verse picker">
|
||||||
<button
|
<mat-icon>cancel</mat-icon>
|
||||||
mat-icon-button
|
</button>
|
||||||
mat-dialog-close
|
</span>
|
||||||
aria-label="Exit the verse picker"
|
</mat-toolbar>
|
||||||
>
|
|
||||||
<mat-icon>cancel</mat-icon>
|
|
||||||
</button>
|
|
||||||
</span>
|
|
||||||
</mat-toolbar>
|
|
||||||
</div>
|
|
||||||
<mat-dialog-content class="content">
|
<mat-dialog-content class="content">
|
||||||
<div>
|
<div>
|
||||||
<span *ngIf="hasBook === false">
|
<span *ngIf="hasBook === false">
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { AppService } from 'src/app/services/app.service';
|
|
||||||
import { MatDialogRef } from '@angular/material/dialog';
|
import { MatDialogRef } from '@angular/material/dialog';
|
||||||
import { Book, BibleReference } from 'src/app/common/bible-reference';
|
import { BibleReference,Book } from 'src/app/common/bible-reference';
|
||||||
|
import { AppService } from 'src/app/services/app.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-verse-picker',
|
selector: 'app-verse-picker',
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
import { Component, ElementRef, ViewChild, ChangeDetectionStrategy } from '@angular/core';
|
import { Clipboard } from '@angular/cdk/clipboard';
|
||||||
|
import { ChangeDetectionStrategy,Component, ElementRef, ViewChild } from '@angular/core';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { BibleReference } from 'src/app/common/bible-reference';
|
import { BibleReference } from 'src/app/common/bible-reference';
|
||||||
import { CardComponent } from 'src/app/components/card.component';
|
import { CardComponent } from 'src/app/components/card.component';
|
||||||
import { AppService } from 'src/app/services/app.service';
|
|
||||||
import { WordLookupResult } from 'src/app/models/words-state';
|
import { WordLookupResult } from 'src/app/models/words-state';
|
||||||
|
import { AppService } from 'src/app/services/app.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-words-card',
|
selector: 'app-words-card',
|
||||||
@ -19,8 +20,13 @@ export class WordsCardComponent extends CardComponent {
|
|||||||
return this.cardItem.data as WordLookupResult;
|
return this.cardItem.data as WordLookupResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(protected elementRef: ElementRef, protected appService: AppService, public dialog: MatDialog) {
|
constructor(
|
||||||
super(elementRef, dialog, appService);
|
protected elementRef: ElementRef,
|
||||||
|
protected appService: AppService,
|
||||||
|
protected clipboard: Clipboard,
|
||||||
|
public dialog: MatDialog
|
||||||
|
) {
|
||||||
|
super(elementRef, dialog, appService, clipboard);
|
||||||
this.icon$ = appService.select((state) => state.settings.value.cardIcons.words);
|
this.icon$ = appService.select((state) => state.settings.value.cardIcons.words);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,9 +35,8 @@ export class WordsCardComponent extends CardComponent {
|
|||||||
BibleReference.makePassageFromReferenceKey(ref)
|
BibleReference.makePassageFromReferenceKey(ref)
|
||||||
);
|
);
|
||||||
|
|
||||||
const html = refs.map((ref) => `<a href='http://dynamicbible.com/search/${ref}'>${ref}</a>`).join(', ');
|
|
||||||
const text = refs.join(', ');
|
const text = refs.join(', ');
|
||||||
this.copyToClip(text, html);
|
this.copyToClip(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
makePassage(p: string) {
|
makePassage(p: string) {
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { IStorable } from '../common/storable';
|
|
||||||
import { NoteItem } from './note-state';
|
|
||||||
import { Overlap } from '../common/bible-reference';
|
import { Overlap } from '../common/bible-reference';
|
||||||
import { CardItem, CardIcons, DataReference } from './card-state';
|
|
||||||
import { SavedPage } from './page-state';
|
|
||||||
import { HashTable } from '../common/hashtable';
|
import { HashTable } from '../common/hashtable';
|
||||||
|
import { IStorable } from '../common/storable';
|
||||||
|
import { CardIcons, CardItem, DataReference } from './card-state';
|
||||||
|
import { NoteItem } from './note-state';
|
||||||
|
import { SavedPage } from './page-state';
|
||||||
|
|
||||||
export interface AppState {
|
export interface AppState {
|
||||||
readonly currentSavedPage: SavedPage;
|
readonly currentSavedPage: SavedPage;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
import { NoteItem } from './note-state';
|
||||||
import { BiblePassageResult } from './passage-state';
|
import { BiblePassageResult } from './passage-state';
|
||||||
import { StrongsResult } from './strongs-state';
|
import { StrongsResult } from './strongs-state';
|
||||||
import { WordLookupResult } from './words-state';
|
import { WordLookupResult } from './words-state';
|
||||||
import { NoteItem } from './note-state';
|
|
||||||
|
|
||||||
export type CardData = BiblePassageResult | StrongsResult | WordLookupResult | NoteItem;
|
export type CardData = BiblePassageResult | StrongsResult | WordLookupResult | NoteItem;
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
export type StrongsDictionary = 'heb' | 'grk';
|
export type StrongsDictionary = 'heb' | 'grk';
|
||||||
|
|
||||||
export interface StrongsResult {
|
export interface StrongsResult {
|
||||||
readonly dict: StrongsDictionary;
|
|
||||||
readonly prefix: string;
|
readonly prefix: string;
|
||||||
readonly sn: number;
|
readonly sn: number;
|
||||||
readonly def: StrongsDefinition;
|
readonly def: StrongsDefinition;
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { AppService } from '../../services/app.service';
|
|
||||||
import { NavService } from '../../services/nav.service';
|
|
||||||
import { SubscriberBase } from '../../common/subscriber-base';
|
|
||||||
import { CardItem, CardType } from 'src/app/models/card-state';
|
|
||||||
import { NoteEditModalComponent } from 'src/app/components/note/edit-modal/note-edit-modal.component';
|
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
|
import { SubscriberBase } from 'src/app/common/subscriber-base';
|
||||||
|
import { NoteEditModalComponent } from 'src/app/components/note/edit-modal/note-edit-modal.component';
|
||||||
|
import { CardItem, CardType } from 'src/app/models/card-state';
|
||||||
|
import { AppService } from 'src/app/services/app.service';
|
||||||
|
import { NavService } from 'src/app/services/nav.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-notes-admin',
|
selector: 'app-notes-admin',
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Component, OnInit } from '@angular/core';
|
import { Component, OnInit } from '@angular/core';
|
||||||
import { AppService } from '../../services/app.service';
|
import { SubscriberBase } from 'src/app/common/subscriber-base';
|
||||||
import { NavService } from '../../services/nav.service';
|
import { AppService } from 'src/app/services/app.service';
|
||||||
import { SubscriberBase } from '../../common/subscriber-base';
|
import { NavService } from 'src/app/services/nav.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-saved-pages-admin',
|
selector: 'app-saved-pages-admin',
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
#autoCompleteInput
|
#autoCompleteInput
|
||||||
[formControl]="searchControl"
|
[formControl]="searchControl"
|
||||||
[matAutocomplete]="auto"
|
[matAutocomplete]="auto"
|
||||||
(keyup.enter)="search($event.target.value)"
|
(keyup.enter)="searchWithTarget($event.target)"
|
||||||
/>
|
/>
|
||||||
<mat-autocomplete #auto="matAutocomplete">
|
<mat-autocomplete #auto="matAutocomplete">
|
||||||
<mat-option *ngFor="let option of suggestions$ | async" [value]="option">
|
<mat-option *ngFor="let option of suggestions$ | async" [value]="option">
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
import { Component, OnInit, ViewChild, ChangeDetectionStrategy, ElementRef } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, ElementRef,OnInit, ViewChild } from '@angular/core';
|
||||||
import { ActivatedRoute, Router, NavigationEnd } from '@angular/router';
|
|
||||||
import { UntypedFormControl } from '@angular/forms';
|
import { UntypedFormControl } from '@angular/forms';
|
||||||
|
import { MatAutocomplete,MatAutocompleteTrigger } from '@angular/material/autocomplete';
|
||||||
import { MatDialog } from '@angular/material/dialog';
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
import { MatAutocompleteTrigger, MatAutocomplete } from '@angular/material/autocomplete';
|
import { ActivatedRoute, NavigationEnd,Router } from '@angular/router';
|
||||||
import { AppService } from '../../services/app.service';
|
import { getFromCardCache } from 'src/app/common/card-cache-operations';
|
||||||
import { NavService } from '../../services/nav.service';
|
import { CardItem, CardType } from 'src/app/models/card-state';
|
||||||
|
import { AppService } from 'src/app/services/app.service';
|
||||||
|
|
||||||
import { SubscriberBase } from '../../common/subscriber-base';
|
import { SubscriberBase } from '../../common/subscriber-base';
|
||||||
import { VersePickerModalComponent } from '../../components/verse-picker-modal/verse-picker-modal.component';
|
import { VersePickerModalComponent } from '../../components/verse-picker-modal/verse-picker-modal.component';
|
||||||
import { CardItem, CardType } from 'src/app/models/card-state';
|
import { NavService } from '../../services/nav.service';
|
||||||
import { getFromCardCache } from 'src/app/common/card-cache-operations';
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-search-page',
|
selector: 'app-search-page',
|
||||||
@ -109,6 +110,10 @@ export class SearchPageComponent extends SubscriberBase implements OnInit {
|
|||||||
this.appService.removeCard(card);
|
this.appService.removeCard(card);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async searchWithTarget(target: EventTarget) {
|
||||||
|
const term = (target as HTMLInputElement).value;
|
||||||
|
await this.search(term);
|
||||||
|
}
|
||||||
async search(search: string) {
|
async search(search: string) {
|
||||||
// clear search box.
|
// clear search box.
|
||||||
if (this.clearSearchAfterQuery) {
|
if (this.clearSearchAfterQuery) {
|
||||||
|
@ -1,288 +0,0 @@
|
|||||||
import { Error, User, Settings } from '../models/app-state';
|
|
||||||
import { IStorable } from '../common/storable';
|
|
||||||
import { NoteItem } from '../models/note-state';
|
|
||||||
import { MoveDirection } from '../common/move-direction';
|
|
||||||
import { SavedPage } from '../models/page-state';
|
|
||||||
import { CardItem } from '../models/card-state';
|
|
||||||
import { Overlap } from '../common/bible-reference';
|
|
||||||
|
|
||||||
export class AppActionFactory {
|
|
||||||
static newSavePage(title: string): AppAction {
|
|
||||||
return {
|
|
||||||
type: 'SAVE_PAGE',
|
|
||||||
title,
|
|
||||||
} as AppAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
static newUpdateCurrentPage(): AppAction {
|
|
||||||
return {
|
|
||||||
type: 'UPDATE_CURRENT_PAGE',
|
|
||||||
} as AppAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
static newUpdateSavedPages(savedPages: IStorable<readonly SavedPage[]>): AppAction {
|
|
||||||
return {
|
|
||||||
type: 'UPDATE_SAVED_PAGES',
|
|
||||||
savedPages,
|
|
||||||
} as AppAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
static newUpdateSavedPage(savedPage: SavedPage): AppAction {
|
|
||||||
return {
|
|
||||||
type: 'UPDATE_SAVED_PAGE',
|
|
||||||
savedPage,
|
|
||||||
} as AppAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
static newMoveSavedPageCard(savedPage: SavedPage, fromIndex: number, toIndex: number): AppAction {
|
|
||||||
return {
|
|
||||||
type: 'MOVE_SAVED_PAGE_CARD',
|
|
||||||
savedPage,
|
|
||||||
fromIndex,
|
|
||||||
toIndex,
|
|
||||||
} as AppAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
static newRemoveSavedPage(savedPage: SavedPage): AppAction {
|
|
||||||
return {
|
|
||||||
type: 'REMOVE_SAVED_PAGE',
|
|
||||||
savedPage,
|
|
||||||
} as AppAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
static newAddCardToSavedPage(card: CardItem, pageId: string): AppAction {
|
|
||||||
return {
|
|
||||||
type: 'ADD_CARD_TO_SAVED_PAGE',
|
|
||||||
card,
|
|
||||||
pageId,
|
|
||||||
} as AppAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
static newAddCard(card: CardItem, nextToItem: CardItem): AppAction {
|
|
||||||
return {
|
|
||||||
type: 'ADD_CARD',
|
|
||||||
card,
|
|
||||||
nextToItem,
|
|
||||||
} as AppAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
static newUpdateCard(newCard: CardItem, oldCard: CardItem): AppAction {
|
|
||||||
return {
|
|
||||||
type: 'UPDATE_CARD',
|
|
||||||
newCard,
|
|
||||||
oldCard,
|
|
||||||
} as AppAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
static newRemoveCard(card: CardItem): AppAction {
|
|
||||||
return {
|
|
||||||
type: 'REMOVE_CARD',
|
|
||||||
card,
|
|
||||||
} as AppAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
static newMoveCard(card: CardItem, direction: MoveDirection): AppAction {
|
|
||||||
return {
|
|
||||||
type: 'MOVE_CARD',
|
|
||||||
card,
|
|
||||||
direction,
|
|
||||||
} as AppAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
static newUpdateCards(cards: IStorable<CardItem[]>): AppAction {
|
|
||||||
return {
|
|
||||||
type: 'UPDATE_CARDS',
|
|
||||||
cards,
|
|
||||||
} as AppAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
static newUpdateError(error: Error): AppAction {
|
|
||||||
return {
|
|
||||||
type: 'UPDATE_ERROR',
|
|
||||||
error,
|
|
||||||
} as AppAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
static newUpdateCardMergeStrategy(strategy: Overlap): AppAction {
|
|
||||||
return {
|
|
||||||
type: 'UPDATE_CARD_MERGE_STRATEGY',
|
|
||||||
cardMergeStrategy: strategy,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static newUpdateCardFontSize(cardFontSize: number): AppAction {
|
|
||||||
return {
|
|
||||||
type: 'UPDATE_CARD_FONT_SIZE',
|
|
||||||
cardFontSize,
|
|
||||||
} as AppAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
static newUpdateCardFontFamily(cardFontFamily: string): AppAction {
|
|
||||||
return {
|
|
||||||
type: 'UPDATE_CARD_FONT_FAMILY',
|
|
||||||
cardFontFamily,
|
|
||||||
} as AppAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
static newUpdateAutocomplete(words: string[]): AppAction {
|
|
||||||
return {
|
|
||||||
type: 'UPDATE_AUTOCOMPLETE',
|
|
||||||
words,
|
|
||||||
} as AppAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
static newUpdateSettings(settings: IStorable<Settings>): AppAction {
|
|
||||||
return {
|
|
||||||
type: 'UPDATE_SETTINGS',
|
|
||||||
settings,
|
|
||||||
} as AppAction;
|
|
||||||
}
|
|
||||||
static newUser(user: User): AppAction {
|
|
||||||
return {
|
|
||||||
type: 'SET_USER',
|
|
||||||
user,
|
|
||||||
} as AppAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
static newFindNotes(qry: string, nextToItem: CardItem): AppAction {
|
|
||||||
return {
|
|
||||||
type: 'FIND_NOTES',
|
|
||||||
qry,
|
|
||||||
nextToItem,
|
|
||||||
} as AppAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
static newGetNote(noteId: string, nextToItem: CardItem): AppAction {
|
|
||||||
return {
|
|
||||||
type: 'GET_NOTE',
|
|
||||||
noteId,
|
|
||||||
nextToItem,
|
|
||||||
} as AppAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
static newUpdateNotes(notes: IStorable<readonly NoteItem[]>): AppAction {
|
|
||||||
return {
|
|
||||||
type: 'UPDATE_NOTES',
|
|
||||||
notes,
|
|
||||||
} as AppAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
static newSaveNote(note: NoteItem): AppAction {
|
|
||||||
return {
|
|
||||||
type: 'SAVE_NOTE',
|
|
||||||
note,
|
|
||||||
} as AppAction;
|
|
||||||
}
|
|
||||||
|
|
||||||
static newDeleteNote(note: NoteItem): AppAction {
|
|
||||||
return {
|
|
||||||
type: 'DELETE_NOTE',
|
|
||||||
note,
|
|
||||||
} as AppAction;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export type AppAction =
|
|
||||||
| {
|
|
||||||
type: 'SAVE_PAGE';
|
|
||||||
title: string;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'UPDATE_CURRENT_PAGE';
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'UPDATE_SAVED_PAGES';
|
|
||||||
savedPages: IStorable<readonly SavedPage[]>;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'UPDATE_SAVED_PAGE';
|
|
||||||
savedPage: SavedPage;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'REMOVE_SAVED_PAGE';
|
|
||||||
savedPage: SavedPage;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'MOVE_SAVED_PAGE_CARD';
|
|
||||||
fromIndex: number;
|
|
||||||
toIndex: number;
|
|
||||||
savedPage: SavedPage;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'ADD_CARD_TO_SAVED_PAGE';
|
|
||||||
card: CardItem;
|
|
||||||
pageId: string;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'ADD_CARD';
|
|
||||||
card: CardItem;
|
|
||||||
nextToItem: CardItem;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'UPDATE_CARD';
|
|
||||||
newCard: CardItem;
|
|
||||||
oldCard: CardItem;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'REMOVE_CARD';
|
|
||||||
card: CardItem;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'MOVE_CARD';
|
|
||||||
card: CardItem;
|
|
||||||
direction: MoveDirection;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'UPDATE_CARDS';
|
|
||||||
cards: IStorable<readonly CardItem[]>;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'UPDATE_ERROR';
|
|
||||||
error: Error;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'UPDATE_CARD_MERGE_STRATEGY';
|
|
||||||
cardMergeStrategy: Overlap;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'UPDATE_CARD_FONT_SIZE';
|
|
||||||
cardFontSize: number;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'UPDATE_CARD_FONT_FAMILY';
|
|
||||||
cardFontFamily: string;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'UPDATE_AUTOCOMPLETE';
|
|
||||||
words: string[];
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'UPDATE_SETTINGS';
|
|
||||||
settings: IStorable<Settings>;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'SET_USER';
|
|
||||||
user: User;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'FIND_NOTES';
|
|
||||||
qry: string;
|
|
||||||
nextToItem: CardItem;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'GET_NOTE';
|
|
||||||
noteId: string;
|
|
||||||
nextToItem: CardItem;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'UPDATE_NOTES';
|
|
||||||
notes: IStorable<readonly NoteItem[]>;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'SAVE_NOTE';
|
|
||||||
note: NoteItem;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: 'DELETE_NOTE';
|
|
||||||
note: NoteItem;
|
|
||||||
};
|
|
@ -1,52 +0,0 @@
|
|||||||
import { AppState } from '../models/app-state';
|
|
||||||
import { Overlap } from '../common/bible-reference';
|
|
||||||
import { StorableType } from '../common/storable';
|
|
||||||
|
|
||||||
export const initialState: AppState = {
|
|
||||||
user: null,
|
|
||||||
currentCards: {
|
|
||||||
type: StorableType.initial,
|
|
||||||
createdOn: new Date(0).toISOString(),
|
|
||||||
value: [],
|
|
||||||
},
|
|
||||||
cardCache: {},
|
|
||||||
autocomplete: [],
|
|
||||||
currentSavedPage: null,
|
|
||||||
savedPages: null,
|
|
||||||
notes: {
|
|
||||||
type: StorableType.initial,
|
|
||||||
createdOn: new Date(0).toISOString(),
|
|
||||||
value: [],
|
|
||||||
},
|
|
||||||
savedPagesLoaded: false,
|
|
||||||
error: null,
|
|
||||||
settings: {
|
|
||||||
type: StorableType.initial,
|
|
||||||
createdOn: new Date(0).toISOString(),
|
|
||||||
value: {
|
|
||||||
displaySettings: {
|
|
||||||
showStrongsAsModal: false,
|
|
||||||
appendCardToBottom: true,
|
|
||||||
insertCardNextToItem: true,
|
|
||||||
clearSearchAfterQuery: true,
|
|
||||||
cardFontSize: 12,
|
|
||||||
cardFontFamily: 'PT Serif',
|
|
||||||
showVersesOnNewLine: false,
|
|
||||||
showVerseNumbers: false,
|
|
||||||
showParagraphs: true,
|
|
||||||
showParagraphHeadings: true,
|
|
||||||
syncCardsAcrossDevices: false,
|
|
||||||
},
|
|
||||||
pageSettings: {
|
|
||||||
mergeStrategy: Overlap.Equal,
|
|
||||||
},
|
|
||||||
cardIcons: {
|
|
||||||
words: 'font_download',
|
|
||||||
passage: 'menu_book',
|
|
||||||
strongs: 'speaker_notes',
|
|
||||||
note: 'note',
|
|
||||||
savedPage: 'inbox',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
@ -1,14 +1,38 @@
|
|||||||
import { TestBed } from '@angular/core/testing';
|
import { TestBed } from '@angular/core/testing';
|
||||||
import { reducer, getNewestStorable } from './app-state-reducer';
|
|
||||||
import { AppActionFactory } from './app-state-actions';
|
|
||||||
import { Overlap } from '../common/bible-reference';
|
import { Overlap } from '../common/bible-reference';
|
||||||
import { Storable, StorableType } from '../common/storable';
|
|
||||||
import { CardType, CardItem } from '../models/card-state';
|
|
||||||
import { SavedPage } from '../models/page-state';
|
|
||||||
import { AppState, User } from '../models/app-state';
|
|
||||||
import { getCardCacheKey } from '../common/card-cache-operations';
|
import { getCardCacheKey } from '../common/card-cache-operations';
|
||||||
import { MoveDirection } from '../common/move-direction';
|
import { MoveDirection } from '../common/move-direction';
|
||||||
|
import { Storable, StorableType } from '../common/storable';
|
||||||
|
import { AppState, User } from '../models/app-state';
|
||||||
|
import { CardItem,CardType } from '../models/card-state';
|
||||||
import { NoteItem } from '../models/note-state';
|
import { NoteItem } from '../models/note-state';
|
||||||
|
import { SavedPage } from '../models/page-state';
|
||||||
|
import {
|
||||||
|
addCardsAction,
|
||||||
|
addCardToSavedPageAction,
|
||||||
|
deleteNoteAction,
|
||||||
|
findNotesAction,
|
||||||
|
getNewestStorable,
|
||||||
|
getNotesAction,
|
||||||
|
moveCardAction,
|
||||||
|
moveSavedPageCardAction,
|
||||||
|
removeCardAction,
|
||||||
|
removeSavedPageAction,
|
||||||
|
saveNoteAction,
|
||||||
|
savePageAction,
|
||||||
|
setUserAction,
|
||||||
|
updateAutoCompleteAction,
|
||||||
|
updateCardAction,
|
||||||
|
updateCardFontFamilyAction,
|
||||||
|
updateCardFontSizeAction,
|
||||||
|
updateCardMergeStrategyAction,
|
||||||
|
updateCurrentPageAction,
|
||||||
|
updateNotesAction,
|
||||||
|
updateSavedPageAction,
|
||||||
|
updateSavedPagesAction,
|
||||||
|
updateSettingsAction,
|
||||||
|
} from './app.service';
|
||||||
|
|
||||||
describe('getNewestStorable', () => {
|
describe('getNewestStorable', () => {
|
||||||
it('maybeMutateStorable', () => {
|
it('maybeMutateStorable', () => {
|
||||||
@ -126,8 +150,7 @@ describe('AppService Reducer', () => {
|
|||||||
|
|
||||||
it('UPDATE_CARD_MERGE_STRATEGY', () => {
|
it('UPDATE_CARD_MERGE_STRATEGY', () => {
|
||||||
for (const strategy of [Overlap.None, Overlap.Equal, Overlap.Subset, Overlap.Intersect]) {
|
for (const strategy of [Overlap.None, Overlap.Equal, Overlap.Subset, Overlap.Intersect]) {
|
||||||
const action = AppActionFactory.newUpdateCardMergeStrategy(strategy);
|
const testState = updateCardMergeStrategyAction(strategy).handle(preState);
|
||||||
const testState = reducer(preState, action);
|
|
||||||
expect(testState.settings.value.pageSettings.mergeStrategy).toEqual(strategy);
|
expect(testState.settings.value.pageSettings.mergeStrategy).toEqual(strategy);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -163,20 +186,17 @@ describe('AppService Reducer', () => {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const action = AppActionFactory.newUpdateSettings(settings);
|
const testState = updateSettingsAction(settings).handle(preState);
|
||||||
const testState = reducer(preState, action);
|
|
||||||
expect(testState.settings).toBe(settings, 'Failed to update the display settings');
|
expect(testState.settings).toBe(settings, 'Failed to update the display settings');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('UPDATE_CARD_FONT_SIZE', () => {
|
it('UPDATE_CARD_FONT_SIZE', () => {
|
||||||
const action = AppActionFactory.newUpdateCardFontSize(32);
|
const testState = updateCardFontSizeAction(32).handle(preState);
|
||||||
const testState = reducer(preState, action);
|
|
||||||
expect(testState.settings.value.displaySettings.cardFontSize).toBe(32, 'Failed to change card font size to 32');
|
expect(testState.settings.value.displaySettings.cardFontSize).toBe(32, 'Failed to change card font size to 32');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('UPDATE_CARD_FONT_FAMILY', () => {
|
it('UPDATE_CARD_FONT_FAMILY', () => {
|
||||||
const action = AppActionFactory.newUpdateCardFontFamily('Jason');
|
const testState = updateCardFontFamilyAction('Jason').handle(preState);
|
||||||
const testState = reducer(preState, action);
|
|
||||||
expect(testState.settings.value.displaySettings.cardFontFamily).toBe(
|
expect(testState.settings.value.displaySettings.cardFontFamily).toBe(
|
||||||
'Jason',
|
'Jason',
|
||||||
'Failed to change card font family to "Jason"'
|
'Failed to change card font family to "Jason"'
|
||||||
@ -188,8 +208,7 @@ describe('AppService Reducer', () => {
|
|||||||
it('UPDATE_AUTOCOMPLETE', () => {
|
it('UPDATE_AUTOCOMPLETE', () => {
|
||||||
const words = ['word1', 'word2', 'word3'];
|
const words = ['word1', 'word2', 'word3'];
|
||||||
|
|
||||||
const action = AppActionFactory.newUpdateAutocomplete(words);
|
const testState = updateAutoCompleteAction(words).handle(preState);
|
||||||
const testState = reducer(preState, action);
|
|
||||||
expect(testState.autocomplete).toEqual(words, 'Failed to update the autocomplete array');
|
expect(testState.autocomplete).toEqual(words, 'Failed to update the autocomplete array');
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -210,8 +229,7 @@ describe('AppService Reducer', () => {
|
|||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const action = AppActionFactory.newUpdateSavedPages(savedPages);
|
const testState = updateSavedPagesAction(savedPages).handle(preState);
|
||||||
const testState = reducer(preState, action);
|
|
||||||
expect(testState.savedPages).toBe(savedPages, 'Failed to update the savedPages array');
|
expect(testState.savedPages).toBe(savedPages, 'Failed to update the savedPages array');
|
||||||
expect(testState.savedPages.value.length).toBe(1, 'Updated savedPages is the wrong length');
|
expect(testState.savedPages.value.length).toBe(1, 'Updated savedPages is the wrong length');
|
||||||
expect(testState.savedPages.value[0].queries.length).toBe(
|
expect(testState.savedPages.value[0].queries.length).toBe(
|
||||||
@ -227,8 +245,7 @@ describe('AppService Reducer', () => {
|
|||||||
id: 'myid2',
|
id: 'myid2',
|
||||||
};
|
};
|
||||||
|
|
||||||
const action = AppActionFactory.newUpdateSavedPage(sp);
|
const testState = updateSavedPageAction(sp).handle(preState);
|
||||||
const testState = reducer(preState, action);
|
|
||||||
|
|
||||||
expect(testState.savedPages.value[0].queries.length).toBe(
|
expect(testState.savedPages.value[0].queries.length).toBe(
|
||||||
1,
|
1,
|
||||||
@ -244,8 +261,7 @@ describe('AppService Reducer', () => {
|
|||||||
|
|
||||||
it('REMOVE_SAVED_PAGE', () => {
|
it('REMOVE_SAVED_PAGE', () => {
|
||||||
const sp = preState.savedPages.value[0];
|
const sp = preState.savedPages.value[0];
|
||||||
const action = AppActionFactory.newRemoveSavedPage(sp);
|
const testState = removeSavedPageAction(sp).handle(preState);
|
||||||
const testState = reducer(preState, action);
|
|
||||||
|
|
||||||
expect(testState.savedPages.value.length).toBe(1, 'Updated savedPages should be 1');
|
expect(testState.savedPages.value.length).toBe(1, 'Updated savedPages should be 1');
|
||||||
expect(testState.savedPages.value[0].title).toBe('page2');
|
expect(testState.savedPages.value[0].title).toBe('page2');
|
||||||
@ -258,12 +274,10 @@ describe('AppService Reducer', () => {
|
|||||||
type: CardType.Strongs,
|
type: CardType.Strongs,
|
||||||
};
|
};
|
||||||
|
|
||||||
const action1 = AppActionFactory.newAddCard(card1, null);
|
const testState = addCardsAction([card1], null).handle(preState);
|
||||||
const testState = reducer(preState, action1);
|
|
||||||
expect(testState.currentCards.value[0]).toBe(card1, 'Failed to add first card to empty list');
|
expect(testState.currentCards.value[0]).toBe(card1, 'Failed to add first card to empty list');
|
||||||
|
|
||||||
const action = AppActionFactory.newUpdateCurrentPage();
|
const testState2 = updateCurrentPageAction().handle(testState);
|
||||||
const testState2 = reducer(testState, action);
|
|
||||||
|
|
||||||
expect(testState2.currentSavedPage.queries.length).toBe(1);
|
expect(testState2.currentSavedPage.queries.length).toBe(1);
|
||||||
expect(preState.currentSavedPage.queries.length).toBe(0);
|
expect(preState.currentSavedPage.queries.length).toBe(0);
|
||||||
@ -276,11 +290,9 @@ describe('AppService Reducer', () => {
|
|||||||
type: CardType.Passage,
|
type: CardType.Passage,
|
||||||
};
|
};
|
||||||
|
|
||||||
const action1 = AppActionFactory.newAddCard(card1, null);
|
const preState2 = addCardsAction([card1], null).handle(preState);
|
||||||
const preState2 = reducer(preState, action1);
|
|
||||||
|
|
||||||
const action = AppActionFactory.newSavePage('my saved page');
|
const testState = savePageAction('my saved page').handle(preState2);
|
||||||
const testState = reducer(preState2, action);
|
|
||||||
|
|
||||||
expect(testState.savedPages.value[2].queries.length).toBe(
|
expect(testState.savedPages.value[2].queries.length).toBe(
|
||||||
1,
|
1,
|
||||||
@ -292,8 +304,7 @@ describe('AppService Reducer', () => {
|
|||||||
it('MOVE_SAVED_PAGE_CARD', () => {
|
it('MOVE_SAVED_PAGE_CARD', () => {
|
||||||
const page = preState.savedPages.value[1];
|
const page = preState.savedPages.value[1];
|
||||||
|
|
||||||
const action1 = AppActionFactory.newMoveSavedPageCard(page, 1, 0);
|
const testState = moveSavedPageCardAction(page, 1, 0).handle(preState);
|
||||||
const testState = reducer(preState, action1);
|
|
||||||
expect(testState.savedPages.value[1].queries[0].qry).toBe('G1', 'Failed to move card in saved page');
|
expect(testState.savedPages.value[1].queries[0].qry).toBe('G1', 'Failed to move card in saved page');
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -303,8 +314,7 @@ describe('AppService Reducer', () => {
|
|||||||
data: null,
|
data: null,
|
||||||
type: CardType.Passage,
|
type: CardType.Passage,
|
||||||
};
|
};
|
||||||
const action1 = AppActionFactory.newAddCardToSavedPage(card1, 'myid1');
|
const testState = addCardToSavedPageAction(card1, 'myid1').handle(preState);
|
||||||
const testState = reducer(preState, action1);
|
|
||||||
expect(testState.savedPages.value[0].queries[1].qry).toBe('jn 3:16', 'Failed to add card to saved page');
|
expect(testState.savedPages.value[0].queries[1].qry).toBe('jn 3:16', 'Failed to add card to saved page');
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -319,8 +329,7 @@ describe('AppService Reducer', () => {
|
|||||||
type: CardType.Strongs,
|
type: CardType.Strongs,
|
||||||
};
|
};
|
||||||
|
|
||||||
const action1 = AppActionFactory.newAddCard(card1, null);
|
const testState = addCardsAction([card1], null).handle(preState);
|
||||||
const testState = reducer(preState, action1);
|
|
||||||
expect(testState.currentCards.value[0]).toBe(card1, 'Failed to add first card to empty list');
|
expect(testState.currentCards.value[0]).toBe(card1, 'Failed to add first card to empty list');
|
||||||
|
|
||||||
const card2: CardItem = {
|
const card2: CardItem = {
|
||||||
@ -329,8 +338,7 @@ describe('AppService Reducer', () => {
|
|||||||
type: CardType.Strongs,
|
type: CardType.Strongs,
|
||||||
};
|
};
|
||||||
|
|
||||||
const action2 = AppActionFactory.newAddCard(card2, null);
|
const testState2 = addCardsAction([card2], null).handle(testState);
|
||||||
const testState2 = reducer(testState, action2);
|
|
||||||
expect(testState2.currentCards.value.length).toBe(2, 'Failed to add second card to list with 1 item');
|
expect(testState2.currentCards.value.length).toBe(2, 'Failed to add second card to list with 1 item');
|
||||||
expect(testState2.currentCards.value[1]).toBe(card2);
|
expect(testState2.currentCards.value[1]).toBe(card2);
|
||||||
|
|
||||||
@ -342,125 +350,109 @@ describe('AppService Reducer', () => {
|
|||||||
|
|
||||||
// append to top, insert next to card
|
// append to top, insert next to card
|
||||||
|
|
||||||
let setState = reducer(
|
let setState = updateSettingsAction({
|
||||||
testState2,
|
createdOn: new Date(2020, 1, 1, 0, 0, 0, 0).toISOString(),
|
||||||
AppActionFactory.newUpdateSettings({
|
type: StorableType.initial,
|
||||||
createdOn: new Date(2020, 1, 1, 0, 0, 0, 0).toISOString(),
|
value: {
|
||||||
type: StorableType.initial,
|
...testState2.settings.value,
|
||||||
value: {
|
displaySettings: {
|
||||||
...testState2.settings.value,
|
showStrongsAsModal: true,
|
||||||
displaySettings: {
|
appendCardToBottom: false,
|
||||||
showStrongsAsModal: true,
|
insertCardNextToItem: true,
|
||||||
appendCardToBottom: false,
|
clearSearchAfterQuery: false,
|
||||||
insertCardNextToItem: true,
|
cardFontSize: 100,
|
||||||
clearSearchAfterQuery: false,
|
cardFontFamily: 'Jason',
|
||||||
cardFontSize: 100,
|
showVersesOnNewLine: true,
|
||||||
cardFontFamily: 'Jason',
|
showVerseNumbers: true,
|
||||||
showVersesOnNewLine: true,
|
showParagraphs: false,
|
||||||
showVerseNumbers: true,
|
showParagraphHeadings: false,
|
||||||
showParagraphs: false,
|
syncCardsAcrossDevices: true,
|
||||||
showParagraphHeadings: false,
|
|
||||||
syncCardsAcrossDevices: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
})
|
},
|
||||||
);
|
}).handle(testState2);
|
||||||
|
|
||||||
const action3 = AppActionFactory.newAddCard(card3, card2);
|
const testState3 = addCardsAction([card3], card2).handle(setState);
|
||||||
const testState3 = reducer(setState, action3);
|
|
||||||
expect(testState3.currentCards.value.length).toBe(3, 'Failed to add third card');
|
expect(testState3.currentCards.value.length).toBe(3, 'Failed to add third card');
|
||||||
expect(testState3.currentCards.value[1]).toBe(card3, 'Failed to insert card above the second card');
|
expect(testState3.currentCards.value[1]).toBe(card3, 'Failed to insert card above the second card');
|
||||||
|
|
||||||
// append to bottom, insert next to card
|
// append to bottom, insert next to card
|
||||||
|
|
||||||
setState = reducer(
|
setState = updateSettingsAction({
|
||||||
testState2,
|
createdOn: new Date(2020, 1, 1, 0, 0, 0, 0).toISOString(),
|
||||||
AppActionFactory.newUpdateSettings({
|
type: StorableType.initial,
|
||||||
createdOn: new Date(2020, 1, 1, 0, 0, 0, 0).toISOString(),
|
value: {
|
||||||
type: StorableType.initial,
|
...testState2.settings.value,
|
||||||
value: {
|
displaySettings: {
|
||||||
...testState2.settings.value,
|
showStrongsAsModal: true,
|
||||||
displaySettings: {
|
appendCardToBottom: true,
|
||||||
showStrongsAsModal: true,
|
insertCardNextToItem: true,
|
||||||
appendCardToBottom: true,
|
clearSearchAfterQuery: false,
|
||||||
insertCardNextToItem: true,
|
cardFontSize: 100,
|
||||||
clearSearchAfterQuery: false,
|
cardFontFamily: 'Jason',
|
||||||
cardFontSize: 100,
|
showVersesOnNewLine: true,
|
||||||
cardFontFamily: 'Jason',
|
showVerseNumbers: true,
|
||||||
showVersesOnNewLine: true,
|
showParagraphs: false,
|
||||||
showVerseNumbers: true,
|
showParagraphHeadings: false,
|
||||||
showParagraphs: false,
|
syncCardsAcrossDevices: true,
|
||||||
showParagraphHeadings: false,
|
|
||||||
syncCardsAcrossDevices: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
})
|
},
|
||||||
);
|
}).handle(testState2);
|
||||||
|
|
||||||
const action4 = AppActionFactory.newAddCard(card3, card1);
|
const testState4 = addCardsAction([card3], card1).handle(setState);
|
||||||
const testState4 = reducer(setState, action4);
|
|
||||||
expect(testState4.currentCards.value.length).toBe(3, 'Failed to add third card');
|
expect(testState4.currentCards.value.length).toBe(3, 'Failed to add third card');
|
||||||
expect(testState4.currentCards.value[1]).toBe(card3, 'Failed to insert card below the first card');
|
expect(testState4.currentCards.value[1]).toBe(card3, 'Failed to insert card below the first card');
|
||||||
|
|
||||||
// append to bottom, do not insert next to card
|
// append to bottom, do not insert next to card
|
||||||
|
|
||||||
setState = reducer(
|
setState = updateSettingsAction({
|
||||||
testState2,
|
createdOn: new Date(2020, 1, 1, 0, 0, 0, 0).toISOString(),
|
||||||
AppActionFactory.newUpdateSettings({
|
type: StorableType.initial,
|
||||||
createdOn: new Date(2020, 1, 1, 0, 0, 0, 0).toISOString(),
|
value: {
|
||||||
type: StorableType.initial,
|
...testState2.settings.value,
|
||||||
value: {
|
displaySettings: {
|
||||||
...testState2.settings.value,
|
showStrongsAsModal: true,
|
||||||
displaySettings: {
|
appendCardToBottom: true,
|
||||||
showStrongsAsModal: true,
|
insertCardNextToItem: false,
|
||||||
appendCardToBottom: true,
|
clearSearchAfterQuery: false,
|
||||||
insertCardNextToItem: false,
|
cardFontSize: 100,
|
||||||
clearSearchAfterQuery: false,
|
cardFontFamily: 'Jason',
|
||||||
cardFontSize: 100,
|
showVersesOnNewLine: true,
|
||||||
cardFontFamily: 'Jason',
|
showVerseNumbers: true,
|
||||||
showVersesOnNewLine: true,
|
showParagraphs: false,
|
||||||
showVerseNumbers: true,
|
showParagraphHeadings: false,
|
||||||
showParagraphs: false,
|
syncCardsAcrossDevices: true,
|
||||||
showParagraphHeadings: false,
|
|
||||||
syncCardsAcrossDevices: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
})
|
},
|
||||||
);
|
}).handle(testState2);
|
||||||
|
|
||||||
const action5 = AppActionFactory.newAddCard(card3, card1);
|
const testState5 = addCardsAction([card3], card1).handle(setState);
|
||||||
const testState5 = reducer(setState, action5);
|
|
||||||
expect(testState5.currentCards.value.length).toBe(3, 'Failed to add third card');
|
expect(testState5.currentCards.value.length).toBe(3, 'Failed to add third card');
|
||||||
expect(testState5.currentCards.value[2]).toBe(card3, 'Failed to insert card at end of the list');
|
expect(testState5.currentCards.value[2]).toBe(card3, 'Failed to insert card at end of the list');
|
||||||
|
|
||||||
// append to top, do not insert next to card
|
// append to top, do not insert next to card
|
||||||
|
|
||||||
setState = reducer(
|
setState = updateSettingsAction({
|
||||||
testState2,
|
createdOn: new Date(2020, 1, 1, 0, 0, 0, 0).toISOString(),
|
||||||
AppActionFactory.newUpdateSettings({
|
type: StorableType.initial,
|
||||||
createdOn: new Date(2020, 1, 1, 0, 0, 0, 0).toISOString(),
|
value: {
|
||||||
type: StorableType.initial,
|
...testState2.settings.value,
|
||||||
value: {
|
displaySettings: {
|
||||||
...testState2.settings.value,
|
showStrongsAsModal: true,
|
||||||
displaySettings: {
|
appendCardToBottom: false,
|
||||||
showStrongsAsModal: true,
|
insertCardNextToItem: false,
|
||||||
appendCardToBottom: false,
|
clearSearchAfterQuery: false,
|
||||||
insertCardNextToItem: false,
|
cardFontSize: 100,
|
||||||
clearSearchAfterQuery: false,
|
cardFontFamily: 'Jason',
|
||||||
cardFontSize: 100,
|
showVersesOnNewLine: true,
|
||||||
cardFontFamily: 'Jason',
|
showVerseNumbers: true,
|
||||||
showVersesOnNewLine: true,
|
showParagraphs: false,
|
||||||
showVerseNumbers: true,
|
showParagraphHeadings: false,
|
||||||
showParagraphs: false,
|
syncCardsAcrossDevices: true,
|
||||||
showParagraphHeadings: false,
|
|
||||||
syncCardsAcrossDevices: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
})
|
},
|
||||||
);
|
}).handle(testState2);
|
||||||
|
|
||||||
const action6 = AppActionFactory.newAddCard(card3, card1);
|
const testState6 = addCardsAction([card3], card1).handle(setState);
|
||||||
const testState6 = reducer(setState, action6);
|
|
||||||
expect(testState6.currentCards.value.length).toBe(3, 'Failed to add third card');
|
expect(testState6.currentCards.value.length).toBe(3, 'Failed to add third card');
|
||||||
expect(testState6.currentCards.value[0]).toBe(card3, 'Failed to insert card at start of the list');
|
expect(testState6.currentCards.value[0]).toBe(card3, 'Failed to insert card at start of the list');
|
||||||
});
|
});
|
||||||
@ -472,8 +464,7 @@ describe('AppService Reducer', () => {
|
|||||||
type: CardType.Strongs,
|
type: CardType.Strongs,
|
||||||
};
|
};
|
||||||
|
|
||||||
const action1 = AppActionFactory.newAddCard(oldCard, null);
|
const preState1 = addCardsAction([oldCard], null).handle(preState);
|
||||||
const preState1 = reducer(preState, action1);
|
|
||||||
|
|
||||||
const newCard: CardItem = {
|
const newCard: CardItem = {
|
||||||
qry: 'H88',
|
qry: 'H88',
|
||||||
@ -481,8 +472,7 @@ describe('AppService Reducer', () => {
|
|||||||
type: CardType.Strongs,
|
type: CardType.Strongs,
|
||||||
};
|
};
|
||||||
|
|
||||||
const action2 = AppActionFactory.newUpdateCard(newCard, oldCard);
|
const testState = updateCardAction(newCard, oldCard).handle(preState1);
|
||||||
const testState = reducer(preState1, action2);
|
|
||||||
|
|
||||||
expect(testState.currentCards.value[0].qry).toBe('H88', 'Should update the card');
|
expect(testState.currentCards.value[0].qry).toBe('H88', 'Should update the card');
|
||||||
expect(testState.cardCache[getCardCacheKey(newCard)].qry).toBe('H88', 'Should exist in card cache');
|
expect(testState.cardCache[getCardCacheKey(newCard)].qry).toBe('H88', 'Should exist in card cache');
|
||||||
@ -498,13 +488,14 @@ describe('AppService Reducer', () => {
|
|||||||
type: CardType.Strongs,
|
type: CardType.Strongs,
|
||||||
};
|
};
|
||||||
|
|
||||||
const action1 = AppActionFactory.newAddCard(card, null);
|
const preState1 = addCardsAction([card], null).handle(preState);
|
||||||
const preState1 = reducer(preState, action1);
|
|
||||||
|
|
||||||
const action2 = AppActionFactory.newRemoveCard(card);
|
const testState = removeCardAction(card).handle(preState1);
|
||||||
const testState = reducer(preState1, action2);
|
|
||||||
|
|
||||||
expect(preState1.currentCards.value.length).toBe(1, 'Should have added the card in preparation for removing the card');
|
expect(preState1.currentCards.value.length).toBe(
|
||||||
|
1,
|
||||||
|
'Should have added the card in preparation for removing the card'
|
||||||
|
);
|
||||||
expect(testState.currentCards.value.length).toBe(0, 'Should have removed the card');
|
expect(testState.currentCards.value.length).toBe(0, 'Should have removed the card');
|
||||||
expect(testState.cardCache[getCardCacheKey(card)]).toBeUndefined(
|
expect(testState.cardCache[getCardCacheKey(card)]).toBeUndefined(
|
||||||
'Should be undefined, having been removed from card cache'
|
'Should be undefined, having been removed from card cache'
|
||||||
@ -518,33 +509,30 @@ describe('AppService Reducer', () => {
|
|||||||
type: CardType.Strongs,
|
type: CardType.Strongs,
|
||||||
};
|
};
|
||||||
|
|
||||||
const action1 = AppActionFactory.newAddCard(card1, null);
|
const preState1 = addCardsAction([card1], null).handle(preState);
|
||||||
const preState1 = reducer(preState, action1);
|
|
||||||
|
|
||||||
const card2: CardItem = {
|
const card2: CardItem = {
|
||||||
qry: 'H88',
|
qry: 'H88',
|
||||||
data: null,
|
data: null,
|
||||||
type: CardType.Strongs,
|
type: CardType.Strongs,
|
||||||
};
|
};
|
||||||
const action2 = AppActionFactory.newAddCard(card2, null);
|
|
||||||
const preState2 = reducer(preState1, action2);
|
const preState2 = addCardsAction([card2], null).handle(preState1);
|
||||||
expect(preState2.currentCards.value.length).toBe(2, 'Should have two cards');
|
expect(preState2.currentCards.value.length).toBe(2, 'Should have two cards');
|
||||||
expect(preState2.currentCards.value[0].qry).toBe('G123');
|
expect(preState2.currentCards.value[0].qry).toBe('G123');
|
||||||
expect(preState2.currentCards.value[1].qry).toBe('H88');
|
expect(preState2.currentCards.value[1].qry).toBe('H88');
|
||||||
|
|
||||||
const action3 = AppActionFactory.newMoveCard(card2, MoveDirection.Up);
|
const testState1 = moveCardAction(card2, MoveDirection.Up).handle(preState2);
|
||||||
const testState1 = reducer(preState2, action3);
|
|
||||||
expect(testState1.currentCards.value[0].qry).toBe('H88');
|
expect(testState1.currentCards.value[0].qry).toBe('H88');
|
||||||
expect(testState1.currentCards.value[1].qry).toBe('G123');
|
expect(testState1.currentCards.value[1].qry).toBe('G123');
|
||||||
const testState4 = reducer(preState2, action3);
|
const testState4 = moveCardAction(card2, MoveDirection.Up).handle(preState2);
|
||||||
expect(testState4.currentCards.value[0].qry).toBe('H88');
|
expect(testState4.currentCards.value[0].qry).toBe('H88');
|
||||||
expect(testState4.currentCards.value[1].qry).toBe('G123');
|
expect(testState4.currentCards.value[1].qry).toBe('G123');
|
||||||
|
|
||||||
const action4 = AppActionFactory.newMoveCard(card1, MoveDirection.Down);
|
const testState2 = moveCardAction(card1, MoveDirection.Down).handle(preState2);
|
||||||
const testState2 = reducer(preState2, action4);
|
|
||||||
expect(testState2.currentCards.value[0].qry).toBe('H88');
|
expect(testState2.currentCards.value[0].qry).toBe('H88');
|
||||||
expect(testState2.currentCards.value[1].qry).toBe('G123');
|
expect(testState2.currentCards.value[1].qry).toBe('G123');
|
||||||
const testState3 = reducer(preState2, action4);
|
const testState3 = moveCardAction(card1, MoveDirection.Down).handle(preState2);
|
||||||
expect(testState3.currentCards.value[0].qry).toBe('H88');
|
expect(testState3.currentCards.value[0].qry).toBe('H88');
|
||||||
expect(testState3.currentCards.value[1].qry).toBe('G123');
|
expect(testState3.currentCards.value[1].qry).toBe('G123');
|
||||||
});
|
});
|
||||||
@ -559,8 +547,7 @@ describe('AppService Reducer', () => {
|
|||||||
providerId: 'asdfasf',
|
providerId: 'asdfasf',
|
||||||
};
|
};
|
||||||
|
|
||||||
const action1 = AppActionFactory.newUser(user);
|
const testState = setUserAction(user).handle(preState);
|
||||||
const testState = reducer(preState, action1);
|
|
||||||
|
|
||||||
expect(testState.user).toBe(user, 'Should set the user');
|
expect(testState.user).toBe(user, 'Should set the user');
|
||||||
});
|
});
|
||||||
@ -581,18 +568,14 @@ describe('AppService Reducer', () => {
|
|||||||
xref: 'jn 3:16',
|
xref: 'jn 3:16',
|
||||||
};
|
};
|
||||||
|
|
||||||
const action1 = AppActionFactory.newSaveNote(note1);
|
const preState1 = saveNoteAction(note1).handle(preState);
|
||||||
const preState1 = reducer(preState, action1);
|
const preState2 = saveNoteAction(note2).handle(preState1);
|
||||||
const action2 = AppActionFactory.newSaveNote(note2);
|
|
||||||
const preState2 = reducer(preState1, action2);
|
|
||||||
expect(preState2.notes.value.length).toBe(2, 'Should have two notes');
|
expect(preState2.notes.value.length).toBe(2, 'Should have two notes');
|
||||||
|
|
||||||
const action3 = AppActionFactory.newGetNote('123456789', null);
|
const preState3 = getNotesAction('123456789', null).handle(preState2);
|
||||||
const preState3 = reducer(preState2, action3);
|
|
||||||
expect(preState3.currentCards.value.length).toBe(1, 'Should have added the note card');
|
expect(preState3.currentCards.value.length).toBe(1, 'Should have added the note card');
|
||||||
|
|
||||||
const action4 = AppActionFactory.newGetNote('1234567890', null);
|
const preState4 = getNotesAction('1234567890', null).handle(preState3);
|
||||||
const preState4 = reducer(preState3, action4);
|
|
||||||
expect(preState4.currentCards.value.length).toBe(2, 'Should have added the note card');
|
expect(preState4.currentCards.value.length).toBe(2, 'Should have added the note card');
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -610,19 +593,17 @@ describe('AppService Reducer', () => {
|
|||||||
xref: 'jn 3:16',
|
xref: 'jn 3:16',
|
||||||
};
|
};
|
||||||
|
|
||||||
const action1 = AppActionFactory.newUpdateNotes(new Storable([note1, note2]));
|
const preState1 = updateNotesAction(new Storable([note1, note2])).handle(preState);
|
||||||
const preState1 = reducer(preState, action1);
|
|
||||||
expect(preState1.notes.value.length).toBe(2, 'Should have added the notes');
|
expect(preState1.notes.value.length).toBe(2, 'Should have added the notes');
|
||||||
|
|
||||||
const action2 = AppActionFactory.newFindNotes('note', null);
|
const preState2 = findNotesAction('note', null).handle(preState1);
|
||||||
const preState2 = reducer(preState1, action2);
|
|
||||||
expect(preState2.currentCards.value.length).toBe(2, 'Should have found two notes card');
|
expect(preState2.currentCards.value.length).toBe(2, 'Should have found two notes card');
|
||||||
|
|
||||||
const action3 = AppActionFactory.newDeleteNote(note1);
|
const preState3 = deleteNoteAction(note1).handle(preState2);
|
||||||
const preState3 = reducer(preState2, action3);
|
|
||||||
expect(preState3.currentCards.value.length).toBe(1, 'Should have deleted the note card');
|
expect(preState3.currentCards.value.length).toBe(1, 'Should have deleted the note card');
|
||||||
expect(preState3.notes.value.length).toBe(1, 'Should have added the notes');
|
expect(preState3.notes.value.length).toBe(1, 'Should have added the notes');
|
||||||
});
|
});
|
||||||
|
|
||||||
//#endregion
|
//#endregion
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,480 +0,0 @@
|
|||||||
import { UUID } from 'angular2-uuid';
|
|
||||||
|
|
||||||
import { AppState, Settings } from '../models/app-state';
|
|
||||||
import { IStorable, Storable } from '../common/storable';
|
|
||||||
import { NoteItem } from '../models/note-state';
|
|
||||||
|
|
||||||
import { mergeCardList } from '../common/card-operations';
|
|
||||||
import { updateInCardCache, removeFromCardCache, getFromCardCache } from '../common/card-cache-operations';
|
|
||||||
|
|
||||||
import { AppAction, AppActionFactory } from './app-state-actions';
|
|
||||||
import { initialState } from './app-state-initial-state';
|
|
||||||
import { SavedPage } from '../models/page-state';
|
|
||||||
import { CardType, CardItem, DataReference } from '../models/card-state';
|
|
||||||
import { moveItem, moveItemUpOrDown } from '../common/array-operations';
|
|
||||||
|
|
||||||
export function getNewestStorable<T>(candidate: IStorable<T>, incumbant: IStorable<T>): IStorable<T> {
|
|
||||||
// if the candidate is null, then return the state.
|
|
||||||
if (!candidate) {
|
|
||||||
return incumbant;
|
|
||||||
}
|
|
||||||
|
|
||||||
// only update if the settings are newer.
|
|
||||||
if (!incumbant || new Date(candidate.createdOn) > new Date(incumbant.createdOn)) {
|
|
||||||
return candidate;
|
|
||||||
}
|
|
||||||
|
|
||||||
// candidate didn't win. return state untouched.
|
|
||||||
return incumbant;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function reducer(state: AppState, action: AppAction): AppState {
|
|
||||||
// somtimes the state is null. lets not complain if that happens.
|
|
||||||
if (state === undefined) {
|
|
||||||
state = initialState;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (action.type) {
|
|
||||||
case 'UPDATE_ERROR': {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
error: action.error,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
//#region Settings
|
|
||||||
|
|
||||||
case 'UPDATE_CARD_MERGE_STRATEGY': {
|
|
||||||
const settings = new Storable<Settings>({
|
|
||||||
...state.settings.value,
|
|
||||||
pageSettings: {
|
|
||||||
...state.settings.value.pageSettings,
|
|
||||||
mergeStrategy: action.cardMergeStrategy,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return reducer(state, {
|
|
||||||
type: 'UPDATE_SETTINGS',
|
|
||||||
settings,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'UPDATE_SETTINGS': {
|
|
||||||
const item = getNewestStorable(action.settings, state.settings);
|
|
||||||
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
settings: item,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'UPDATE_CARD_FONT_SIZE': {
|
|
||||||
const settings = new Storable<Settings>({
|
|
||||||
...state.settings.value,
|
|
||||||
displaySettings: {
|
|
||||||
...state.settings.value.displaySettings,
|
|
||||||
cardFontSize: action.cardFontSize,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return reducer(state, {
|
|
||||||
type: 'UPDATE_SETTINGS',
|
|
||||||
settings,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'UPDATE_CARD_FONT_FAMILY': {
|
|
||||||
const settings = new Storable<Settings>({
|
|
||||||
...state.settings.value,
|
|
||||||
displaySettings: {
|
|
||||||
...state.settings.value.displaySettings,
|
|
||||||
cardFontFamily: action.cardFontFamily,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return reducer(state, {
|
|
||||||
type: 'UPDATE_SETTINGS',
|
|
||||||
settings,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
case 'UPDATE_AUTOCOMPLETE': {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
autocomplete: [...action.words],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
//#region Saved Pages
|
|
||||||
|
|
||||||
case 'UPDATE_SAVED_PAGES': {
|
|
||||||
const savedPages = getNewestStorable(action.savedPages, state.savedPages);
|
|
||||||
|
|
||||||
// only true if a currentSavedPage was set, indicating that the user
|
|
||||||
// is currently looking at a saved page.
|
|
||||||
const hasCurrentSavedPage =
|
|
||||||
state.currentSavedPage !== null &&
|
|
||||||
state.currentSavedPage !== undefined &&
|
|
||||||
action.savedPages.value.some((o) => o.id === state.currentSavedPage.id);
|
|
||||||
|
|
||||||
const currentSavedPage = hasCurrentSavedPage
|
|
||||||
? action.savedPages.value.find((o) => o.id === state.currentSavedPage.id)
|
|
||||||
: null;
|
|
||||||
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
// if the currentSavedPage was loaded, replace it with the info from the
|
|
||||||
// new savedPages array, as it might have changed.
|
|
||||||
currentCards: hasCurrentSavedPage ? new Storable(currentSavedPage.queries) : state.currentCards,
|
|
||||||
currentSavedPage: hasCurrentSavedPage ? currentSavedPage : state.currentSavedPage,
|
|
||||||
savedPagesLoaded: true,
|
|
||||||
savedPages, // update the savedPages
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'UPDATE_SAVED_PAGE': {
|
|
||||||
const newSavedPages = new Storable<SavedPage[]>(
|
|
||||||
state.savedPages.value.map((o) => {
|
|
||||||
if (o.id === action.savedPage.id) {
|
|
||||||
return action.savedPage;
|
|
||||||
}
|
|
||||||
return o;
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
const savedPages = getNewestStorable(newSavedPages, state.savedPages);
|
|
||||||
return reducer(state, AppActionFactory.newUpdateSavedPages(savedPages));
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'REMOVE_SAVED_PAGE': {
|
|
||||||
const savedPages = new Storable<SavedPage[]>(state.savedPages.value.filter((o) => o.id !== action.savedPage.id));
|
|
||||||
const item = getNewestStorable(savedPages, state.savedPages);
|
|
||||||
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
savedPagesLoaded: true,
|
|
||||||
savedPages: item,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'UPDATE_CURRENT_PAGE': {
|
|
||||||
const current = {
|
|
||||||
id: state.currentSavedPage.id,
|
|
||||||
title: state.currentSavedPage.title,
|
|
||||||
queries: [...mergeCardList(state.currentCards.value, state.settings.value.pageSettings.mergeStrategy)],
|
|
||||||
};
|
|
||||||
|
|
||||||
const savedPages = new Storable<SavedPage[]>([
|
|
||||||
...state.savedPages.value.filter((o) => o.id !== state.currentSavedPage.id),
|
|
||||||
current,
|
|
||||||
]);
|
|
||||||
|
|
||||||
const item = getNewestStorable(savedPages, state.savedPages);
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
currentSavedPage: current,
|
|
||||||
savedPagesLoaded: true,
|
|
||||||
savedPages: item,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'SAVE_PAGE': {
|
|
||||||
const savedPages = new Storable([
|
|
||||||
...(state.savedPages ? state.savedPages.value : []),
|
|
||||||
{
|
|
||||||
// create a new saved page object
|
|
||||||
title: action.title,
|
|
||||||
id: UUID.UUID().toString(),
|
|
||||||
queries: [...mergeCardList(state.currentCards.value, state.settings.value.pageSettings.mergeStrategy)],
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
return reducer(state, {
|
|
||||||
type: 'UPDATE_SAVED_PAGES',
|
|
||||||
savedPages,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'MOVE_SAVED_PAGE_CARD': {
|
|
||||||
const queries = moveItem(action.savedPage.queries, action.fromIndex, action.toIndex);
|
|
||||||
const savedPage = {
|
|
||||||
...action.savedPage,
|
|
||||||
queries, // update the queries.
|
|
||||||
};
|
|
||||||
|
|
||||||
return reducer(state, AppActionFactory.newUpdateSavedPage(savedPage));
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'ADD_CARD_TO_SAVED_PAGE': {
|
|
||||||
const savedPages = new Storable([
|
|
||||||
...(state.savedPages ? state.savedPages.value : []).map((o) => {
|
|
||||||
if (o.id.toString() === action.pageId) {
|
|
||||||
let references = [] as DataReference[];
|
|
||||||
if (state.settings.value.displaySettings.appendCardToBottom) {
|
|
||||||
references = [...o.queries, action.card];
|
|
||||||
} else {
|
|
||||||
references = [action.card, ...o.queries];
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
...o,
|
|
||||||
queries: mergeCardList(references, state.settings.value.pageSettings.mergeStrategy),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return o;
|
|
||||||
}),
|
|
||||||
]);
|
|
||||||
|
|
||||||
return reducer(state, {
|
|
||||||
type: 'UPDATE_SAVED_PAGES',
|
|
||||||
savedPages,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
//#region Cards
|
|
||||||
|
|
||||||
case 'ADD_CARD': {
|
|
||||||
let cards = [];
|
|
||||||
|
|
||||||
if (action.nextToItem && state.settings.value.displaySettings.insertCardNextToItem) {
|
|
||||||
const idx = state.currentCards.value.indexOf(action.nextToItem);
|
|
||||||
|
|
||||||
if (state.settings.value.displaySettings.appendCardToBottom) {
|
|
||||||
const before = state.currentCards.value.slice(0, idx + 1);
|
|
||||||
const after = state.currentCards.value.slice(idx + 1);
|
|
||||||
cards = [...before, action.card, ...after];
|
|
||||||
} else {
|
|
||||||
const before = state.currentCards.value.slice(0, idx);
|
|
||||||
const after = state.currentCards.value.slice(idx);
|
|
||||||
cards = [...before, action.card, ...after];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (state.settings.value.displaySettings.appendCardToBottom) {
|
|
||||||
cards = [...state.currentCards.value, action.card];
|
|
||||||
} else {
|
|
||||||
cards = [action.card, ...state.currentCards.value];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
currentCards: new Storable(cards),
|
|
||||||
cardCache: updateInCardCache(action.card, state.cardCache),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'UPDATE_CARD': {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
currentCards: new Storable(
|
|
||||||
state.currentCards.value.map((c) => {
|
|
||||||
if (c === action.oldCard) {
|
|
||||||
return action.newCard;
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
})
|
|
||||||
),
|
|
||||||
cardCache: updateInCardCache(action.newCard, removeFromCardCache(action.oldCard, state.cardCache)),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'REMOVE_CARD': {
|
|
||||||
// potentially remove card from a saved page.
|
|
||||||
const currentSavedPage =
|
|
||||||
state.currentSavedPage !== null
|
|
||||||
? {
|
|
||||||
...state.currentSavedPage,
|
|
||||||
queries: state.currentSavedPage.queries.filter((q) => q !== action.card),
|
|
||||||
}
|
|
||||||
: null;
|
|
||||||
|
|
||||||
const savedPages =
|
|
||||||
state.currentSavedPage !== null
|
|
||||||
? new Storable(
|
|
||||||
(state.savedPages ? state.savedPages.value : []).map((o) => {
|
|
||||||
if (o === state.currentSavedPage) {
|
|
||||||
return currentSavedPage;
|
|
||||||
}
|
|
||||||
return o;
|
|
||||||
})
|
|
||||||
)
|
|
||||||
: state.savedPages;
|
|
||||||
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
currentSavedPage,
|
|
||||||
savedPages,
|
|
||||||
currentCards: new Storable([...state.currentCards.value.filter((c) => c !== action.card)]),
|
|
||||||
cardCache: removeFromCardCache(action.card, state.cardCache),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'MOVE_CARD': {
|
|
||||||
const cards = moveItemUpOrDown(state.currentCards.value, action.card, action.direction);
|
|
||||||
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
currentCards: new Storable(cards),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'UPDATE_CARDS': {
|
|
||||||
let cardCache = { ...state.cardCache };
|
|
||||||
for (const card of action.cards.value) {
|
|
||||||
cardCache = updateInCardCache(card, cardCache);
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
currentCards: action.cards,
|
|
||||||
cardCache,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
//#endregion
|
|
||||||
|
|
||||||
case 'SET_USER': {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
user: action.user,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
//#region Notes
|
|
||||||
|
|
||||||
case 'FIND_NOTES': {
|
|
||||||
const notes = state.notes.value
|
|
||||||
.filter((o) => o.title.search(action.qry) > -1)
|
|
||||||
.map((o) => {
|
|
||||||
return {
|
|
||||||
qry: o.id,
|
|
||||||
type: CardType.Note,
|
|
||||||
data: o,
|
|
||||||
} as CardItem;
|
|
||||||
});
|
|
||||||
|
|
||||||
let cards = [] as DataReference[];
|
|
||||||
|
|
||||||
if (action.nextToItem && state.settings.value.displaySettings.insertCardNextToItem) {
|
|
||||||
const idx = state.currentCards.value.indexOf(action.nextToItem);
|
|
||||||
|
|
||||||
if (state.settings.value.displaySettings.appendCardToBottom) {
|
|
||||||
const before = state.currentCards.value.slice(0, idx + 1);
|
|
||||||
const after = state.currentCards.value.slice(idx + 1);
|
|
||||||
cards = [...before, ...notes, ...after];
|
|
||||||
} else {
|
|
||||||
const before = state.currentCards.value.slice(0, idx);
|
|
||||||
const after = state.currentCards.value.slice(idx);
|
|
||||||
cards = [...before, ...notes, ...after];
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (state.settings.value.displaySettings.appendCardToBottom) {
|
|
||||||
cards = [...state.currentCards.value, ...notes];
|
|
||||||
} else {
|
|
||||||
cards = [...notes, ...state.currentCards.value];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let cache = { ...state.cardCache };
|
|
||||||
for (const n of notes) {
|
|
||||||
cache = updateInCardCache(n, cache);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
currentCards: new Storable(cards),
|
|
||||||
cardCache: cache,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'GET_NOTE': {
|
|
||||||
const note = state.notes.value.find((o) => o.id === action.noteId);
|
|
||||||
const card: CardItem = {
|
|
||||||
qry: note.id,
|
|
||||||
type: CardType.Note,
|
|
||||||
data: note,
|
|
||||||
};
|
|
||||||
|
|
||||||
return reducer(state, {
|
|
||||||
type: 'ADD_CARD',
|
|
||||||
card,
|
|
||||||
nextToItem: action.nextToItem,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
case 'UPDATE_NOTES': {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
notes: action.notes ? action.notes : new Storable([]),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
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 notes = new Storable<NoteItem[]>([
|
|
||||||
...state.notes.value.filter((o) => o.id !== action.note.id),
|
|
||||||
action.note,
|
|
||||||
]);
|
|
||||||
|
|
||||||
const newState = {
|
|
||||||
...state,
|
|
||||||
currentCards: new Storable([...state.currentCards.value]), // you want to trigger an update to the cards if a card update is different.
|
|
||||||
notes,
|
|
||||||
};
|
|
||||||
|
|
||||||
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 card = state.currentCards.value.find((o) => o.qry === action.note.id);
|
|
||||||
|
|
||||||
const cards = card
|
|
||||||
? [
|
|
||||||
...state.currentCards.value.filter((o) => {
|
|
||||||
return o.type !== CardType.Note || o.qry !== action.note.id;
|
|
||||||
}),
|
|
||||||
]
|
|
||||||
: state.currentCards.value; // if card is undefined, then it wasn't in the current card list.
|
|
||||||
|
|
||||||
const notes = new Storable<NoteItem[]>([...state.notes.value.filter((o) => o.id !== action.note.id)]);
|
|
||||||
|
|
||||||
const savedPages = new Storable<SavedPage[]>([
|
|
||||||
...(state.savedPages ? state.savedPages.value : []).map((sp) => {
|
|
||||||
return {
|
|
||||||
...sp,
|
|
||||||
queries: sp.queries.filter((o) => {
|
|
||||||
return o.type !== CardType.Note || o.qry !== action.note.id;
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
]);
|
|
||||||
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
currentCards: new Storable(cards),
|
|
||||||
notes,
|
|
||||||
savedPages,
|
|
||||||
cardCache: card
|
|
||||||
? removeFromCardCache(getFromCardCache(card, state.cardCache), state.cardCache)
|
|
||||||
: state.cardCache,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
//#endregion
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -2,13 +2,14 @@ import { Injectable } from '@angular/core';
|
|||||||
import { AngularFireDatabase, AngularFireObject } from '@angular/fire/compat/database';
|
import { AngularFireDatabase, AngularFireObject } from '@angular/fire/compat/database';
|
||||||
import { DataSnapshot } from '@angular/fire/compat/database/interfaces';
|
import { DataSnapshot } from '@angular/fire/compat/database/interfaces';
|
||||||
import { UUID } from 'angular2-uuid';
|
import { UUID } from 'angular2-uuid';
|
||||||
import { AppService } from './app.service';
|
|
||||||
import { Overlap } from '../common/bible-reference';
|
import { Overlap } from '../common/bible-reference';
|
||||||
import { Settings, User } from '../models/app-state';
|
|
||||||
import { SavedPage } from '../models/page-state';
|
|
||||||
import { CardType, DataReference } from '../models/card-state';
|
|
||||||
import { StorageService } from './storage.service';
|
|
||||||
import { Storable, StorableType } from '../common/storable';
|
import { Storable, StorableType } from '../common/storable';
|
||||||
|
import { Settings, User } from '../models/app-state';
|
||||||
|
import { CardType, DataReference } from '../models/card-state';
|
||||||
|
import { SavedPage } from '../models/page-state';
|
||||||
|
import { AppService } from './app.service';
|
||||||
|
import { StorageService } from './storage.service';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { StorageMap } from '@ngx-pwa/local-storage';
|
|
||||||
import { AngularFireDatabase, AngularFireObject } from '@angular/fire/compat/database';
|
import { AngularFireDatabase, AngularFireObject } from '@angular/fire/compat/database';
|
||||||
import { DataSnapshot } from '@angular/fire/compat/database/interfaces';
|
import { DataSnapshot } from '@angular/fire/compat/database/interfaces';
|
||||||
|
import { StorageMap } from '@ngx-pwa/local-storage';
|
||||||
|
import { createSelector } from 'reselect';
|
||||||
|
import { lastValueFrom } from 'rxjs';
|
||||||
|
|
||||||
import { SubscriberBase } from '../common/subscriber-base';
|
import { isNullOrUndefined } from '../common/helpers';
|
||||||
import { IStorable, StorableType, UserVersion } from '../common/storable';
|
import { IStorable, StorableType, UserVersion } from '../common/storable';
|
||||||
import { AppService } from './app.service';
|
import { SubscriberBase } from '../common/subscriber-base';
|
||||||
import { MigrationVersion0to1 } from './migration0to1.service';
|
import { AppState,Settings, User } from '../models/app-state';
|
||||||
|
import { DataReference } from '../models/card-state';
|
||||||
import { User, Settings, AppState } from '../models/app-state';
|
|
||||||
import { NoteItem } from '../models/note-state';
|
import { NoteItem } from '../models/note-state';
|
||||||
import { SavedPage } from '../models/page-state';
|
import { SavedPage } from '../models/page-state';
|
||||||
import { isNullOrUndefined } from '../common/helpers';
|
import { AppService } from './app.service';
|
||||||
import { DataReference } from '../models/card-state';
|
import { MigrationVersion0to1 } from './migration0to1.service';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class handles all the storage needs of the application. It handles both
|
* This class handles all the storage needs of the application. It handles both
|
||||||
@ -186,9 +186,9 @@ export class StorageService extends SubscriberBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async getFromLocal<T>(path: string, action: (storable: IStorable<T>) => void) {
|
private async getFromLocal<T>(path: string, action: (storable: IStorable<T>) => void) {
|
||||||
const hasStorable = await this.local.has(path).toPromise();
|
const hasStorable = await lastValueFrom(this.local.has(path));
|
||||||
if (hasStorable) {
|
if (hasStorable) {
|
||||||
const localData = (await this.local.get(path).toPromise()) as IStorable<T>;
|
const localData = (await lastValueFrom(this.local.get(path))) as IStorable<T>;
|
||||||
// console.log('Data recieved from local store', localData);
|
// console.log('Data recieved from local store', localData);
|
||||||
action(localData);
|
action(localData);
|
||||||
}
|
}
|
||||||
@ -206,14 +206,14 @@ export class StorageService extends SubscriberBase {
|
|||||||
|
|
||||||
// console.log('Data saved to local store', data);
|
// console.log('Data saved to local store', data);
|
||||||
// update local
|
// update local
|
||||||
this.local.set(this.settingsPath, data).subscribe(
|
this.addSubscription(
|
||||||
() => {
|
this.local.set(this.settingsPath, data).subscribe({
|
||||||
// nop
|
next: () => {},
|
||||||
},
|
complete: () => {},
|
||||||
// error
|
error: () => {
|
||||||
() => {
|
this.appService.dispatchError(`Something went wrong and the Settings weren't saved. :(`);
|
||||||
this.appService.dispatchError(`Something went wrong and the Settings weren't saved. :(`);
|
},
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
// update remote
|
// update remote
|
||||||
@ -232,14 +232,14 @@ export class StorageService extends SubscriberBase {
|
|||||||
|
|
||||||
// console.log('Data saved to local store', data);
|
// console.log('Data saved to local store', data);
|
||||||
// update local
|
// update local
|
||||||
this.local.set(this.savedPagesPath, data).subscribe(
|
this.addSubscription(
|
||||||
() => {
|
this.local.set(this.savedPagesPath, data).subscribe({
|
||||||
// nop
|
next: () => {},
|
||||||
},
|
complete: () => {},
|
||||||
// error
|
error: () => {
|
||||||
() => {
|
this.appService.dispatchError(`Something went wrong and the Page wasn't saved. :(`);
|
||||||
this.appService.dispatchError(`Something went wrong and the Page wasn't saved. :(`);
|
},
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
// update remote
|
// update remote
|
||||||
@ -258,14 +258,14 @@ export class StorageService extends SubscriberBase {
|
|||||||
|
|
||||||
// console.log('Data saved to local store', data);
|
// console.log('Data saved to local store', data);
|
||||||
// update local
|
// update local
|
||||||
this.local.set(this.noteItemsPath, data).subscribe(
|
this.addSubscription(
|
||||||
() => {
|
this.local.set(this.noteItemsPath, data).subscribe({
|
||||||
// nop
|
next: () => {},
|
||||||
},
|
complete: () => {},
|
||||||
// error
|
error: () => {
|
||||||
() => {
|
this.appService.dispatchError(`Something went wrong and the Note wasn't saved. :(`);
|
||||||
this.appService.dispatchError(`Something went wrong and the Note wasn't saved. :(`);
|
},
|
||||||
}
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
// update remote
|
// update remote
|
||||||
@ -289,15 +289,15 @@ export class StorageService extends SubscriberBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update local
|
// update local
|
||||||
this.local.set(this.cardsPath, v.currentCards).subscribe({
|
this.addSubscription(
|
||||||
next: () => {
|
this.local.set(this.cardsPath, v.currentCards).subscribe({
|
||||||
// nop
|
next: () => {},
|
||||||
},
|
complete: () => {},
|
||||||
// error
|
error: () => {
|
||||||
error: () => {
|
this.appService.dispatchError(`Something went wrong and the current cards weren't saved. :(`);
|
||||||
this.appService.dispatchError(`Something went wrong and the current cards weren't saved. :(`);
|
},
|
||||||
},
|
})
|
||||||
});
|
);
|
||||||
|
|
||||||
// since you updated the local variable above, this remote update will
|
// since you updated the local variable above, this remote update will
|
||||||
// get picked up by the remote subscription below.
|
// get picked up by the remote subscription below.
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'zone.js/testing';
|
import 'zone.js/testing';
|
||||||
|
|
||||||
import { getTestBed } from '@angular/core/testing';
|
import { getTestBed } from '@angular/core/testing';
|
||||||
import {
|
import {
|
||||||
BrowserDynamicTestingModule,
|
BrowserDynamicTestingModule,
|
||||||
|
@ -5,11 +5,6 @@
|
|||||||
"outDir": "./out-tsc/app",
|
"outDir": "./out-tsc/app",
|
||||||
"types": []
|
"types": []
|
||||||
},
|
},
|
||||||
"files": [
|
"files": ["src/main.ts", "src/polyfills.ts"],
|
||||||
"src/main.ts",
|
"include": ["src/**/*.d.ts"],
|
||||||
"src/polyfills.ts"
|
|
||||||
],
|
|
||||||
"include": [
|
|
||||||
"src/**/*.d.ts"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
|
||||||
{
|
{
|
||||||
"compileOnSave": false,
|
"compileOnSave": false,
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
@ -15,5 +14,9 @@
|
|||||||
"target": "es2022",
|
"target": "es2022",
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"lib": ["es2018", "dom"]
|
"lib": ["es2018", "dom"]
|
||||||
}
|
},
|
||||||
|
"angularCompilerOptions": {
|
||||||
|
"strictTemplates": true
|
||||||
|
},
|
||||||
|
"include": ["src/**/*.ts"]
|
||||||
}
|
}
|
||||||
|
@ -3,16 +3,8 @@
|
|||||||
"extends": "./tsconfig.json",
|
"extends": "./tsconfig.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"outDir": "./out-tsc/spec",
|
"outDir": "./out-tsc/spec",
|
||||||
"types": [
|
"types": ["jasmine"]
|
||||||
"jasmine"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"files": [
|
"files": ["src/test.ts", "src/polyfills.ts"],
|
||||||
"src/test.ts",
|
"include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
|
||||||
"src/polyfills.ts"
|
|
||||||
],
|
|
||||||
"include": [
|
|
||||||
"src/**/*.spec.ts",
|
|
||||||
"src/**/*.d.ts"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user