From 27569e4c509f8c12a1b0d8f967c8f5cdba4a55f1 Mon Sep 17 00:00:00 2001 From: Jason Wall Date: Sun, 9 Aug 2020 18:53:04 -0400 Subject: [PATCH] basic page admin bug fix in handling of storage --- app/db/src/app/app-routing.module.ts | 8 +- app/db/src/app/app.component.html | 2 +- app/db/src/app/app.component.ts | 2 +- app/db/src/app/app.module.ts | 5 ++ .../saved-page-card.component.html | 34 ++++++++ .../saved-page-card.component.scss | 15 ++++ .../saved-page-card.component.ts | 85 +++++++++++++++++++ .../words/words-card.component.scss | 2 +- app/db/src/app/constants.ts | 2 + app/db/src/app/models/card-state.ts | 1 + .../saved-pages-admin.page.html | 16 ++++ .../saved-pages-admin.page.scss | 20 +++++ .../saved-pages-admin.page.ts | 20 +++++ app/db/src/app/pages/search/search.page.ts | 3 - app/db/src/app/services/app-state-actions.ts | 22 +++++ .../app/services/app-state-initial-state.ts | 12 +-- app/db/src/app/services/app-state-reducer.ts | 42 ++++++++- app/db/src/app/services/app.service.ts | 13 +++ app/db/src/app/services/storage.service.ts | 4 +- app/db/src/styles/app.scss | 3 + 20 files changed, 293 insertions(+), 18 deletions(-) create mode 100644 app/db/src/app/components/saved-page-card/saved-page-card.component.html create mode 100644 app/db/src/app/components/saved-page-card/saved-page-card.component.scss create mode 100644 app/db/src/app/components/saved-page-card/saved-page-card.component.ts create mode 100644 app/db/src/app/pages/saved-pages-admin/saved-pages-admin.page.html create mode 100644 app/db/src/app/pages/saved-pages-admin/saved-pages-admin.page.scss create mode 100644 app/db/src/app/pages/saved-pages-admin/saved-pages-admin.page.ts diff --git a/app/db/src/app/app-routing.module.ts b/app/db/src/app/app-routing.module.ts index 28d5ad29..baded72a 100644 --- a/app/db/src/app/app-routing.module.ts +++ b/app/db/src/app/app-routing.module.ts @@ -1,6 +1,7 @@ import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { SearchPage } from './pages/search/search.page'; +import { SavedPagesAdminPage } from './pages/saved-pages-admin/saved-pages-admin.page'; const routes: Routes = [ { @@ -19,10 +20,15 @@ const routes: Routes = [ component: SearchPage, }, { - path: 'saved/:id', + path: 'page/:id', pathMatch: 'prefix', component: SearchPage, }, + { + path: 'saved/admin', + pathMatch: 'prefix', + component: SavedPagesAdminPage, + }, ]; @NgModule({ diff --git a/app/db/src/app/app.component.html b/app/db/src/app/app.component.html index 140cccb1..30dfe6f5 100644 --- a/app/db/src/app/app.component.html +++ b/app/db/src/app/app.component.html @@ -23,7 +23,7 @@ library_books {{ p.title }} diff --git a/app/db/src/app/app.component.ts b/app/db/src/app/app.component.ts index b64e3713..19e51ce8 100644 --- a/app/db/src/app/app.component.ts +++ b/app/db/src/app/app.component.ts @@ -15,7 +15,7 @@ import { MatSnackBar } from '@angular/material/snack-bar'; styleUrls: ['./app.component.scss'], }) export class AppComponent extends SubscriberBase implements AfterViewInit { - savedPages$ = this.appService.select((state) => state.savedPages.value); + savedPages$ = this.appService.select((state) => (state.savedPages === null ? null : state.savedPages.value)); mainPages$ = this.appService.select((state) => state.mainPages); fontSize$ = this.appService.select((state) => state.displaySettings.value.cardFontSize + 'pt'); cardFont$ = this.appService.select((state) => state.displaySettings.value.cardFontFamily); diff --git a/app/db/src/app/app.module.ts b/app/db/src/app/app.module.ts index f15ef106..e86017f6 100644 --- a/app/db/src/app/app.module.ts +++ b/app/db/src/app/app.module.ts @@ -51,6 +51,9 @@ import { ClipboardModule } from '@angular/cdk/clipboard'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; +import { SavedPagesAdminPage } from './pages/saved-pages-admin/saved-pages-admin.page'; +import { SavedPageCardComponent } from './components/saved-page-card/saved-page-card.component'; + import { SearchPage } from './pages/search/search.page'; import { OkCancelModalComponent } from './components/ok-cancel-modal/ok-cancel-modal.component'; @@ -70,6 +73,8 @@ import { AddToPageModalComponent } from './components/add-to-page-modal/add-to-p @NgModule({ declarations: [ AppComponent, + SavedPagesAdminPage, + SavedPageCardComponent, SearchPage, PassageCardComponent, StrongsComponent, diff --git a/app/db/src/app/components/saved-page-card/saved-page-card.component.html b/app/db/src/app/components/saved-page-card/saved-page-card.component.html new file mode 100644 index 00000000..690e2c26 --- /dev/null +++ b/app/db/src/app/components/saved-page-card/saved-page-card.component.html @@ -0,0 +1,34 @@ +
+ {{ + icon$ | async + }} + Page: {{ savedPage.title }} +
+
+ + + {{ format(q) }} + + + +
+
+ + + + + + + +
diff --git a/app/db/src/app/components/saved-page-card/saved-page-card.component.scss b/app/db/src/app/components/saved-page-card/saved-page-card.component.scss new file mode 100644 index 00000000..7c1e8669 --- /dev/null +++ b/app/db/src/app/components/saved-page-card/saved-page-card.component.scss @@ -0,0 +1,15 @@ +.pages-title { + background-color: var(--page-color-primary); +} + +.card-actions { + color: var(--page-color-primary); +} + +.card-content { + overflow-y: auto; + max-height: 25rem; + font-family: var(--card-font-family); + font-size: var(--card-font-size); + padding: 0.5rem; +} diff --git a/app/db/src/app/components/saved-page-card/saved-page-card.component.ts b/app/db/src/app/components/saved-page-card/saved-page-card.component.ts new file mode 100644 index 00000000..b889141c --- /dev/null +++ b/app/db/src/app/components/saved-page-card/saved-page-card.component.ts @@ -0,0 +1,85 @@ +import { Component, ElementRef, ChangeDetectionStrategy, Input, OnInit } from '@angular/core'; +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 { CardItem, CardType } from 'src/app/models/card-state'; +import { NoteItem } from 'src/app/models/note-state'; +import { OkCancelModalComponent, OkCancelResult } from '../ok-cancel-modal/ok-cancel-modal.component'; +import { MatSnackBar } from '@angular/material/snack-bar'; + +@Component({ + selector: 'app-saved-page-card', + templateUrl: 'saved-page-card.component.html', + styleUrls: ['./saved-page-card.component.scss'], + preserveWhitespaces: true, +}) +export class SavedPageCardComponent implements OnInit { + icon$: Observable; + + @Input() + savedPage: SavedPage; + + constructor(protected appService: AppService, public dialog: MatDialog, private snackBar: MatSnackBar) { + this.icon$ = appService.select((state) => state.cardIcons.savedPage); + } + + format(item: CardItem) { + if (item.type === CardType.Note) { + return `Note: ${(item.data as NoteItem).title}`; + } else if (item.type === CardType.Passage) { + return `Passage: ${item.qry}`; + } else if (item.type === CardType.Strongs) { + return `Strongs: ${item.qry}`; + } else if (item.type === CardType.Word) { + return `Word Search: ${item.qry}`; + } + return ''; + } + + onRemoveCard(card: CardItem) { + this.dialog + .open(OkCancelModalComponent, { + data: { + title: 'Delete Card from Saved Page', + content: `Do you want to delete this card '${this.format(card)}' from the saved page '${ + this.savedPage.title + }?`, + }, + }) + .afterClosed() + .subscribe((ds: OkCancelResult) => { + if (ds.ok) { + this.appService.updateSavedPage({ + ...this.savedPage, + queries: this.savedPage.queries.filter((o) => o !== card), + }); + this.snackBar.open(`${this.savedPage.title} has been updated!`, '', { + duration: 3 * 1000, + }); + } + }); + } + + onRemovePage() { + this.dialog + .open(OkCancelModalComponent, { + data: { + title: 'Delete Saved Page', + content: `Do you want to delete the saved page '${this.savedPage.title}?`, + }, + }) + .afterClosed() + .subscribe((ds: OkCancelResult) => { + if (ds.ok) { + this.appService.removeSavedPage(this.savedPage); + this.snackBar.open(`${this.savedPage.title} has been deleted!`, '', { + duration: 3 * 1000, + }); + } + }); + } + ngOnInit(): void { + console.log(this.savedPage); + } +} diff --git a/app/db/src/app/components/words/words-card.component.scss b/app/db/src/app/components/words/words-card.component.scss index 7f4eba8b..33bfe2df 100644 --- a/app/db/src/app/components/words/words-card.component.scss +++ b/app/db/src/app/components/words/words-card.component.scss @@ -13,7 +13,7 @@ .card-content { overflow-y: auto; max-height: 25rem; - font-family: var(--card-font); + font-family: var(--card-font-family); font-size: var(--card-font-size); padding: 0.5rem; } diff --git a/app/db/src/app/constants.ts b/app/db/src/app/constants.ts index 01ef32b8..03e77081 100644 --- a/app/db/src/app/constants.ts +++ b/app/db/src/app/constants.ts @@ -1,10 +1,12 @@ export const PageTitles = { Search: 'Search', + PageAdmin: 'Page Admin', Help: 'Help', }; export const PageIcons = { Search: 'search', + PageAdmin: 'library_books', Help: 'help', }; diff --git a/app/db/src/app/models/card-state.ts b/app/db/src/app/models/card-state.ts index e7052220..d47a9f96 100644 --- a/app/db/src/app/models/card-state.ts +++ b/app/db/src/app/models/card-state.ts @@ -24,4 +24,5 @@ export interface CardIcons { readonly passage: string; readonly strongs: string; readonly note: string; + readonly savedPage: string; } diff --git a/app/db/src/app/pages/saved-pages-admin/saved-pages-admin.page.html b/app/db/src/app/pages/saved-pages-admin/saved-pages-admin.page.html new file mode 100644 index 00000000..236e957f --- /dev/null +++ b/app/db/src/app/pages/saved-pages-admin/saved-pages-admin.page.html @@ -0,0 +1,16 @@ + + + Saved Pages Admin + +
+ + + + + + +   + +
diff --git a/app/db/src/app/pages/saved-pages-admin/saved-pages-admin.page.scss b/app/db/src/app/pages/saved-pages-admin/saved-pages-admin.page.scss new file mode 100644 index 00000000..e161d074 --- /dev/null +++ b/app/db/src/app/pages/saved-pages-admin/saved-pages-admin.page.scss @@ -0,0 +1,20 @@ +mat-card { + max-width: 800px; + margin: 1.5rem auto; + padding: 0; +} + +.page-title { + width: 100%; + position: relative; + margin-left: 0.8rem; + margin-right: 0.8rem; +} + +.page-content { + padding: 0 1rem 0 1rem; + overflow-y: scroll; + height: calc(100vh - 66px); + width: calc(100% - 15px); + margin-top: 2px; +} diff --git a/app/db/src/app/pages/saved-pages-admin/saved-pages-admin.page.ts b/app/db/src/app/pages/saved-pages-admin/saved-pages-admin.page.ts new file mode 100644 index 00000000..c3d9f24e --- /dev/null +++ b/app/db/src/app/pages/saved-pages-admin/saved-pages-admin.page.ts @@ -0,0 +1,20 @@ +import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core'; +import { MatDialog } from '@angular/material/dialog'; +import { AppService } from '../../services/app.service'; +import { NavService } from '../../services/nav.service'; +import { SubscriberBase } from '../../common/subscriber-base'; + +@Component({ + selector: 'app-saved-pages-admin', + templateUrl: './saved-pages-admin.page.html', + styleUrls: ['./saved-pages-admin.page.scss'], +}) +export class SavedPagesAdminPage extends SubscriberBase implements OnInit { + savedPages$ = this.appService.select((state) => (state.savedPages === null ? null : state.savedPages.value)); + + constructor(public navService: NavService, private appService: AppService, private dialog: MatDialog) { + super(); + } + + ngOnInit() {} +} diff --git a/app/db/src/app/pages/search/search.page.ts b/app/db/src/app/pages/search/search.page.ts index 9603a630..fb6176a3 100644 --- a/app/db/src/app/pages/search/search.page.ts +++ b/app/db/src/app/pages/search/search.page.ts @@ -54,7 +54,6 @@ export class SearchPage extends SubscriberBase implements OnInit { if (evt instanceof NavigationEnd) { this.init(); } - console.log(evt); }) ); @@ -75,8 +74,6 @@ export class SearchPage extends SubscriberBase implements OnInit { const id = this.activatedRoute.snapshot.paramMap.get('id'); this.onSavedPagedLoaded(id); this.navService.closeNav(); // close the nav immediately. - } else { - // its a blank search. load nothing. } } diff --git a/app/db/src/app/services/app-state-actions.ts b/app/db/src/app/services/app-state-actions.ts index 9fc9a207..c53297f3 100644 --- a/app/db/src/app/services/app-state-actions.ts +++ b/app/db/src/app/services/app-state-actions.ts @@ -33,6 +33,20 @@ export class AppActionFactory { } as AppAction; } + static newUpdateSavedPage(savedPage: SavedPage) { + return { + type: 'UPDATE_SAVED_PAGE', + savedPage, + } as AppAction; + } + + static newRemoveSavedPage(savedPage: SavedPage) { + return { + type: 'REMOVE_SAVED_PAGE', + savedPage, + } as AppAction; + } + static newAddCardToSavedPage(card: CardItem, pageId: string) { return { type: 'ADD_CARD_TO_SAVED_PAGE', @@ -167,6 +181,14 @@ export type AppAction = type: 'UPDATE_SAVED_PAGES'; savedPages: IStorable; } + | { + type: 'UPDATE_SAVED_PAGE'; + savedPage: SavedPage; + } + | { + type: 'REMOVE_SAVED_PAGE'; + savedPage: SavedPage; + } | { type: 'ADD_CARD_TO_SAVED_PAGE'; card: CardItem; diff --git a/app/db/src/app/services/app-state-initial-state.ts b/app/db/src/app/services/app-state-initial-state.ts index e019c3f1..e6686514 100644 --- a/app/db/src/app/services/app-state-initial-state.ts +++ b/app/db/src/app/services/app-state-initial-state.ts @@ -22,17 +22,12 @@ export const initialState: AppState = { ], autocomplete: [], currentSavedPage: null, - savedPages: { - createdOn: new Date(0).toISOString(), - value: [], - }, - notes: { - createdOn: new Date(0).toISOString(), - value: [], - }, + savedPages: null, + notes: null, savedPagesLoaded: false, mainPages: [ { title: PageTitles.Search, icon: PageIcons.Search, route: 'search' }, + { title: PageTitles.PageAdmin, icon: PageIcons.PageAdmin, route: 'saved/admin' }, { title: PageTitles.Help, icon: PageIcons.Help, route: 'help' }, ], error: null, @@ -63,5 +58,6 @@ export const initialState: AppState = { passage: 'menu_book', strongs: 'speaker_notes', note: 'text_snippet', + savedPage: 'library_books', }, }; diff --git a/app/db/src/app/services/app-state-reducer.ts b/app/db/src/app/services/app-state-reducer.ts index 11ab7c23..e767a558 100644 --- a/app/db/src/app/services/app-state-reducer.ts +++ b/app/db/src/app/services/app-state-reducer.ts @@ -17,8 +17,18 @@ function maybeMutateStorable( incumbant: IStorable, composeState: (item: IStorable) => AppState ): AppState { + // if the candidate is null, then return the state. + if (!candidate) { + return state; + } + + // if the incumbant is null, then def use the candidate. + if (!incumbant) { + return composeState(candidate); + } + // only update if the settings are newer. - if (new Date(candidate.createdOn) > new Date(incumbant.createdOn)) { + if (!incumbant || new Date(candidate.createdOn) > new Date(incumbant.createdOn)) { return composeState(candidate); } @@ -83,6 +93,36 @@ export function reducer(state: AppState, action: AppAction): AppState { }; }); } + case 'UPDATE_SAVED_PAGE': { + const savedPages = new Storable( + state.savedPages.value.map((o) => { + if (o.id === action.savedPage.id) { + return action.savedPage; + } + return o; + }) + ); + + return maybeMutateStorable(state, savedPages, state.savedPages, (item) => { + return { + ...state, + savedPagesLoaded: true, + savedPages: item, + }; + }); + } + + case 'REMOVE_SAVED_PAGE': { + const savedPages = new Storable(state.savedPages.value.filter((o) => o.id !== action.savedPage.id)); + + return maybeMutateStorable(state, savedPages, state.savedPages, (item) => { + return { + ...state, + savedPagesLoaded: true, + savedPages: item, + }; + }); + } case 'UPDATE_CURRENT_PAGE': { const savedPages = new Storable([ ...state.savedPages.value.filter((o) => o.id !== state.currentSavedPage.id), diff --git a/app/db/src/app/services/app.service.ts b/app/db/src/app/services/app.service.ts index ff12c42f..408dc2e6 100644 --- a/app/db/src/app/services/app.service.ts +++ b/app/db/src/app/services/app.service.ts @@ -111,6 +111,19 @@ export class AppService extends createStateService(reducer, initialState) { }); } + updateSavedPage(savedPage: SavedPage) { + this.dispatch({ + type: 'UPDATE_SAVED_PAGE', + savedPage, + }); + } + removeSavedPage(savedPage: SavedPage) { + this.dispatch({ + type: 'REMOVE_SAVED_PAGE', + savedPage, + }); + } + addCardToSavedPage(pageId: string, card: CardItem) { this.dispatch({ type: 'ADD_CARD_TO_SAVED_PAGE', diff --git a/app/db/src/app/services/storage.service.ts b/app/db/src/app/services/storage.service.ts index 2af844d1..2f0dcef6 100644 --- a/app/db/src/app/services/storage.service.ts +++ b/app/db/src/app/services/storage.service.ts @@ -18,7 +18,7 @@ export class StorageService extends SubscriberBase { private displaySettingsRemoteObject: AngularFireObject>; private savedPagesState$ = this.appService.select((state) => state.savedPages); - private savedPagesPath = 'savedPaged'; + private savedPagesPath = 'savedPages'; private savedPagesRemoteObject: AngularFireObject>; private noteItemsState$ = this.appService.select((state) => state.notes); @@ -34,7 +34,7 @@ export class StorageService extends SubscriberBase { this.addSubscription( this.displaySettingsState$.subscribe((settings) => { - if (!settings) { + if (!settings || settings.createdOn === new Date(0).toISOString()) { return; } diff --git a/app/db/src/styles/app.scss b/app/db/src/styles/app.scss index c0371ea6..f9133f58 100644 --- a/app/db/src/styles/app.scss +++ b/app/db/src/styles/app.scss @@ -21,6 +21,9 @@ html { --note-color-primary: rgb(71, 1, 54); --note-color-accent: rgb(165, 86, 145); + + --page-color-primary: rgb(46, 42, 54); + --page-color-accent: rgb(111, 109, 116); } body {