moved saved pages settings to settings component

show current saved page and update option only if on a saved page
setup errors to show as a toast when they appear.
This commit is contained in:
Jason Wall 2020-08-07 21:10:53 -04:00
parent 25ed414aba
commit 5ffed6453e
12 changed files with 176 additions and 56 deletions

View File

@ -38,29 +38,6 @@
position="end"
[opened]="false"
>
<mat-toolbar>Page Settings</mat-toolbar>
<mat-nav-list>
<mat-list-item>
<a mat-list-item (click)="savePage()"
><mat-icon color="accenovert">save</mat-icon> Save Results as New
Page</a
>
</mat-list-item>
<mat-list-item>
<a mat-list-item (click)="updatePage()"
><mat-icon color="accenovert">save</mat-icon> Update Page with
Results</a
>
</mat-list-item>
<mat-list-item>
<a mat-list-item (click)="createNote()"
><mat-icon color="accenovert">create</mat-icon> Create a New Note</a
>
</mat-list-item>
</mat-nav-list>
<app-settings></app-settings>
</mat-sidenav>
<mat-sidenav-content>

View File

@ -6,10 +6,8 @@ import { Observable } from 'rxjs';
import { Breakpoints, BreakpointObserver } from '@angular/cdk/layout';
import { map, shareReplay } from 'rxjs/operators';
import { MatSidenav } from '@angular/material/sidenav';
import { MatDialog } from '@angular/material/dialog';
import { PageEditModalComponent } from './search/components/saved-page/page-edit-modal/page-edit-modal.component';
import { NoteEditModalComponent } from './search/components/note/edit-modal/note-edit-modal.component';
import { SubscriberComponent } from './common/components/subscriber.component';
import { MatSnackBar } from '@angular/material/snack-bar';
@Component({
selector: 'app-root',
@ -21,6 +19,7 @@ export class AppComponent extends SubscriberComponent implements AfterViewInit {
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);
error$ = this.appService.select((state) => state.error);
isHandset$: Observable<boolean> = this.breakpointObserver.observe(Breakpoints.Handset).pipe(
map((result) => result.matches),
@ -35,13 +34,21 @@ export class AppComponent extends SubscriberComponent implements AfterViewInit {
private navService: NavService,
private storageService: StorageService,
private breakpointObserver: BreakpointObserver,
private dialog: MatDialog
private snackBar: MatSnackBar
) {
super();
this.storageService.initSavedPages();
this.storageService.initDisplaySettings();
this.addSubscription(
this.error$.subscribe((err) => {
this.snackBar.open(`Oh no! ${err.msg}`, 'Error', {
duration: 4 * 1000,
});
})
);
//#region Handle recieving updates from firebase
this.addSubscription(
@ -82,16 +89,4 @@ export class AppComponent extends SubscriberComponent implements AfterViewInit {
ngAfterViewInit(): void {
this.navService.setSidenav(this.sidenav, this.settings);
}
savePage() {
this.dialog.open(PageEditModalComponent);
}
updatePage() {
this.appService.updateSavedPage();
}
createNote() {
this.dialog.open(NoteEditModalComponent);
}
}

View File

@ -20,11 +20,12 @@ import { PageEditModalComponent } from './search/components/saved-page/page-edit
import { NoteEditModalComponent } from './search/components/note/edit-modal/note-edit-modal.component';
import { VersePickerModalComponent } from './search/components/verse-picker-modal/verse-picker-modal.component';
import { OkCancelModalComponent } from './common/components/ok-cancel-modal/ok-cancel-modal.component';
import { SettingsComponent } from './common/components/settings/settings.component';
import { PassageCardComponent } from './search/components/passage/passage-card.component';
import { WordsCardComponent } from './search/components/words/words-card.component';
import { NoteCardComponent } from './search/components/note/note-card.component';
import { StrongsComponent } from './search/components/strongs/strongs.component';
import { StrongsCardComponent } from './search/components/strongs/card/strongs-card.component';
import { StrongsModalComponent } from './search/components/strongs/modal/strongs-modal.component';
@ -81,6 +82,7 @@ import { ClipboardModule } from '@angular/cdk/clipboard';
AddToPageModalComponent,
VersePickerModalComponent,
SettingsComponent,
OkCancelModalComponent,
],
imports: [
BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),

View File

@ -0,0 +1,6 @@
<h1 mat-dialog-title>{{ data.title }}</h1>
<div mat-dialog-content>{{ data.content }}</div>
<div mat-dialog-actions>
<button mat-button (click)="ok()">Ok</button>
<button mat-button (click)="cancel()">Cancel</button>
</div>

View File

@ -0,0 +1,24 @@
.close-button {
float: right;
mat-icon {
font-size: 2rem;
}
}
.title {
width: 100%;
padding-left: 1rem;
font-size: 1.5rem;
}
.mat-form-field {
display: block;
}
.note-content {
min-width: 75vw;
textarea {
min-height: 15rem;
}
}

View File

@ -0,0 +1,35 @@
import { Component, Inject } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
@Component({
selector: 'app-ok-cancel-modal',
templateUrl: 'ok-cancel-modal.component.html',
styleUrls: ['./ok-cancel-modal.component.scss'],
})
export class OkCancelModalComponent {
constructor(
@Inject(MAT_DIALOG_DATA) public data: OkCancelData,
public dialogRef: MatDialogRef<OkCancelModalComponent>
) {}
cancel() {
this.dialogRef.close({
ok: false,
});
}
ok() {
this.dialogRef.close({
ok: true,
});
}
}
export interface OkCancelData {
title: string;
content: string;
}
export interface OkCancelResult {
ok: boolean;
data: any | undefined;
}

View File

@ -1,3 +1,25 @@
<mat-toolbar>Page Settings</mat-toolbar>
<mat-nav-list>
<a mat-list-item (click)="savePage()">
<mat-icon matListIcon color="accenovert">save</mat-icon>
Save Results as New Page
</a>
<a
mat-list-item
(click)="updatePage(page)"
*ngIf="currentSavedPage$ | async as page"
>
<mat-icon matListIcon color="accenovert">save</mat-icon>
Update {{ page.title }} with Results
</a>
<a mat-list-item (click)="createNote()">
<mat-icon matListIcon color="accenovert">create</mat-icon>
Create a New Note
</a>
</mat-nav-list>
<mat-toolbar>Search Settings</mat-toolbar>
<mat-nav-list>
<mat-list-item>
@ -73,7 +95,7 @@
<mat-nav-list>
<div class="setting-item">
<div class="settings-h2">Card Font Family</div>
<mat-form-field appearance="fill" class="card-fonts">
<mat-form-field class="card-fonts">
<mat-select
[(value)]="cardFontFamily"
(selectionChange)="cardFontSelected($event)"
@ -102,13 +124,13 @@
<mat-nav-list>
<mat-list-item *ngIf="user$ | async as user; else showLogin">
<button
mat-icon-button
mat-raised-button
aria-label="Login with Google"
color="primary"
class="auth-button"
(click)="logout()"
>
{{ user.displayName }}
{{ user.displayName }}&nbsp;&nbsp;
<mat-icon>logout</mat-icon>
</button>
</mat-list-item>
@ -121,7 +143,7 @@
class="auth-button"
(click)="login()"
>
Login with Google
Login with Google&nbsp;&nbsp;
<mat-icon>login</mat-icon>
</button>
</mat-list-item>

View File

@ -2,13 +2,20 @@ import { Component } from '@angular/core';
import { AppService } from 'src/app/services/app.service';
import { MatSlideToggleChange } from '@angular/material/slide-toggle';
import { SubscriberComponent } from '../subscriber.component';
import { DisplaySettings } from 'src/app/models/app-state';
import { DisplaySettings, SavedPage } from 'src/app/models/app-state';
import { CardFonts } from 'src/app/constants';
import { MatSelectChange } from '@angular/material/select';
import { MatSliderChange } from '@angular/material/slider';
import { AngularFireAuth } from '@angular/fire/auth';
import { auth } from 'firebase/app';
import { Storable } from 'src/app/models/storable';
import { PageEditModalComponent } from '../../../search/components/saved-page/page-edit-modal/page-edit-modal.component';
import { NoteEditModalComponent } from '../../../search/components/note/edit-modal/note-edit-modal.component';
import { MatDialog } from '@angular/material/dialog';
import { OkCancelModalComponent, OkCancelResult } from '../ok-cancel-modal/ok-cancel-modal.component';
import { MatSnackBar } from '@angular/material/snack-bar';
import { SearchPage } from 'src/app/search/components/search-page/search.page';
import { NavService } from 'src/app/services/nav.service';
@Component({
selector: 'app-settings',
@ -20,9 +27,17 @@ export class SettingsComponent extends SubscriberComponent {
fonts: string[];
cardFontFamily = '';
cardFontSize = 10;
currentSavedPage$ = this.appService.select((state) => state.currentSavedPage);
user$ = this.appService.select((state) => state.user);
constructor(public appService: AppService, public authService: AngularFireAuth) {
constructor(
public appService: AppService,
private navService: NavService,
public authService: AngularFireAuth,
private dialog: MatDialog,
private snackBar: MatSnackBar
) {
super();
this.fonts = CardFonts;
this.addSubscription(
@ -52,10 +67,46 @@ export class SettingsComponent extends SubscriberComponent {
console.log('Authenticated.');
});
}
logout() {
this.authService.signOut();
}
//#region Page Settings
savePage() {
this.navService.closeSettings();
this.dialog.open(PageEditModalComponent);
}
updatePage(page: SavedPage) {
this.dialog
.open(OkCancelModalComponent, {
data: {
title: 'Update Saved Page',
content: `Do you want to update saved page: ${page.title}?`,
},
})
.afterClosed()
.subscribe((ds: OkCancelResult) => {
console.log(ds);
if (ds.ok) {
this.appService.updateSavedPage();
this.navService.closeSettings();
this.snackBar.open(`${page.title} has been updated!`, '', {
duration: 3 * 1000,
});
}
});
}
createNote() {
this.navService.closeSettings();
this.dialog.open(NoteEditModalComponent);
}
//#endregion
//#region Font Settings
cardFontSelected(evt: MatSelectChange) {

View File

@ -1,7 +1,7 @@
import { IStorable } from './storable';
export interface AppState {
readonly currentPage: SavedPage;
readonly currentSavedPage: SavedPage;
readonly savedPages: IStorable<readonly SavedPage[]>;
readonly savedPagesLoaded: boolean;
readonly mainPages: readonly Page[];

View File

@ -74,7 +74,7 @@ export class SearchPage extends SubscriberComponent implements OnInit {
// if this is a saved page
const id = this.activatedRoute.snapshot.paramMap.get('id');
this.onSavedPagedLoaded(id);
this.navService.close(); // close the nav immediately.
this.navService.closeNav(); // close the nav immediately.
} else {
// its a blank search. load nothing.
}

View File

@ -47,7 +47,7 @@ const initialState: AppState = {
},
],
autocomplete: [],
currentPage: null,
currentSavedPage: null,
savedPages: {
createdOn: new Date(0).toISOString(),
value: [],
@ -216,10 +216,10 @@ function reducer(state: AppState, action: AppAction): AppState {
}
case 'UPDATE_CURRENT_PAGE': {
const savedPages = new Storable<SavedPage[]>([
...state.savedPages.value.filter((o) => o.id === state.currentPage.id),
...state.savedPages.value.filter((o) => o.id === state.currentSavedPage.id),
{
id: state.currentPage.id,
title: state.currentPage.title,
id: state.currentSavedPage.id,
title: state.currentSavedPage.title,
queries: [...state.cards],
},
]);
@ -254,7 +254,7 @@ function reducer(state: AppState, action: AppAction): AppState {
return {
...state,
currentPage: page,
currentSavedPage: page,
cards: [...page.queries],
};
}

View File

@ -13,19 +13,27 @@ export class NavService {
this.settings = settings;
}
public open() {
public openNav() {
return this.sidenav.open();
}
public async close() {
public async closeNav() {
const r = await this.sidenav.close();
return r;
}
public toggle(): void {
public toggleNav(): void {
this.sidenav.toggle();
}
public openSettings() {
return this.settings.open();
}
public async closeSettings() {
const r = await this.settings.close();
return r;
}
public toggleSettings(): void {
this.settings.toggle();
}