* fix bug in close code

* style the note (headers should always be sans)
* tweak the add note link in settings
This commit is contained in:
walljm 2020-02-01 15:22:48 -05:00
parent cfe3d4eaea
commit f5ba1850f8
9 changed files with 344 additions and 296 deletions

File diff suppressed because one or more lines are too long

View File

@ -901,7 +901,8 @@
"ansi-regex": { "ansi-regex": {
"version": "2.1.1", "version": "2.1.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"aproba": { "aproba": {
"version": "1.2.0", "version": "1.2.0",
@ -922,12 +923,14 @@
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
"concat-map": "0.0.1" "concat-map": "0.0.1"
@ -948,7 +951,8 @@
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
@ -1099,6 +1103,7 @@
"version": "3.0.4", "version": "3.0.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }
@ -1106,12 +1111,14 @@
"minimist": { "minimist": {
"version": "0.0.8", "version": "0.0.8",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"minipass": { "minipass": {
"version": "2.3.5", "version": "2.3.5",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"safe-buffer": "^5.1.2", "safe-buffer": "^5.1.2",
"yallist": "^3.0.0" "yallist": "^3.0.0"
@ -1130,6 +1137,7 @@
"version": "0.5.1", "version": "0.5.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "0.0.8"
} }
@ -1223,6 +1231,7 @@
"version": "1.4.0", "version": "1.4.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"wrappy": "1" "wrappy": "1"
} }
@ -1364,6 +1373,7 @@
"version": "3.0.1", "version": "3.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"ansi-regex": "^2.0.0" "ansi-regex": "^2.0.0"
} }
@ -6082,13 +6092,11 @@
}, },
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true
"optional": true
}, },
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"bundled": true, "bundled": true,
"optional": true,
"requires": { "requires": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
"concat-map": "0.0.1" "concat-map": "0.0.1"
@ -6101,18 +6109,15 @@
}, },
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true
"optional": true
}, },
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"bundled": true, "bundled": true
"optional": true
}, },
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true
"optional": true
}, },
"core-util-is": { "core-util-is": {
"version": "1.0.2", "version": "1.0.2",
@ -6215,8 +6220,7 @@
}, },
"inherits": { "inherits": {
"version": "2.0.3", "version": "2.0.3",
"bundled": true, "bundled": true
"optional": true
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.5",
@ -6226,7 +6230,6 @@
"is-fullwidth-code-point": { "is-fullwidth-code-point": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"optional": true,
"requires": { "requires": {
"number-is-nan": "^1.0.0" "number-is-nan": "^1.0.0"
} }
@ -6239,20 +6242,17 @@
"minimatch": { "minimatch": {
"version": "3.0.4", "version": "3.0.4",
"bundled": true, "bundled": true,
"optional": true,
"requires": { "requires": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }
}, },
"minimist": { "minimist": {
"version": "0.0.8", "version": "0.0.8",
"bundled": true, "bundled": true
"optional": true
}, },
"minipass": { "minipass": {
"version": "2.2.4", "version": "2.2.4",
"bundled": true, "bundled": true,
"optional": true,
"requires": { "requires": {
"safe-buffer": "^5.1.1", "safe-buffer": "^5.1.1",
"yallist": "^3.0.0" "yallist": "^3.0.0"
@ -6269,7 +6269,6 @@
"mkdirp": { "mkdirp": {
"version": "0.5.1", "version": "0.5.1",
"bundled": true, "bundled": true,
"optional": true,
"requires": { "requires": {
"minimist": "0.0.8" "minimist": "0.0.8"
} }
@ -6348,8 +6347,7 @@
}, },
"number-is-nan": { "number-is-nan": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true, "bundled": true
"optional": true
}, },
"object-assign": { "object-assign": {
"version": "4.1.1", "version": "4.1.1",
@ -6359,7 +6357,6 @@
"once": { "once": {
"version": "1.4.0", "version": "1.4.0",
"bundled": true, "bundled": true,
"optional": true,
"requires": { "requires": {
"wrappy": "1" "wrappy": "1"
} }
@ -6465,7 +6462,6 @@
"string-width": { "string-width": {
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"optional": true,
"requires": { "requires": {
"code-point-at": "^1.0.0", "code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0", "is-fullwidth-code-point": "^1.0.0",
@ -7947,7 +7943,7 @@
"is-my-json-valid": { "is-my-json-valid": {
"version": "2.17.1", "version": "2.17.1",
"resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz", "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.17.1.tgz",
"integrity": "sha512-Q2khNw+oBlWuaYvEEHtKSw/pCxD2L5Rc1C+UQme9X6JdRDh7m5D7HkozA0qa3DUkQ6VzCnEm8mVIQPyIRkI5sQ==", "integrity": "sha1-PamJFKcKIvCoVj7xURokbG/FVHE=",
"dev": true, "dev": true,
"requires": { "requires": {
"generate-function": "^2.0.0", "generate-function": "^2.0.0",
@ -14244,12 +14240,14 @@
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
"concat-map": "0.0.1" "concat-map": "0.0.1"
@ -14269,7 +14267,8 @@
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"bundled": true, "bundled": true,
"dev": true "dev": true,
"optional": true
}, },
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
@ -14417,6 +14416,7 @@
"version": "3.0.4", "version": "3.0.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }

View File

@ -0,0 +1,7 @@
Required Versions:
Ionic: 5.3.0
Cordova 8.0.0
Node 10.15.3
In order to install node-sass, you need VS 2017 or the VS 2017 Build tools. If you don't have VS2017 and do have VS2019 then node-gyp will use the wrong version even if the 2017 build tools are installed. so be warned.

View File

@ -1,5 +1,5 @@
<ion-item class="title note-title" (swipe)="close()"> <ion-item class="title note-title" (swipe)="close()">
<ion-icon name="book" item-left></ion-icon><span>Note: </span> <ion-icon name="clipboard" item-left></ion-icon>
<span *ngIf="data !== undefined">{{ data.title }}</span> <span *ngIf="data !== undefined">{{ data.title }}</span>
<!-- TODO(jwall): Put the crossreference somewhere if it exists. --> <!-- TODO(jwall): Put the crossreference somewhere if it exists. -->
<button ion-button icon-only item-end large clear (click)="close()"> <button ion-button icon-only item-end large clear (click)="close()">
@ -7,11 +7,10 @@
</button> </button>
</ion-item> </ion-item>
<ion-card-content> <ion-card-content>
<markdown *ngIf = "data !== undefined" [data]="data.content"></markdown> <markdown *ngIf="data !== undefined" [data]="data.content"></markdown>
</ion-card-content> </ion-card-content>
<div style="float: left"> <div style="float: right">
<button ion-button icon-start clear (click)="edit()"> <button ion-button icon-start clear (click)="edit()">
<ion-icon name="create"></ion-icon> <ion-icon name="create"></ion-icon>
<div>Edit</div>
</button> </button>
</div> </div>

View File

@ -5,12 +5,21 @@ note {
} }
font-family: var(--card-font); font-family: var(--card-font);
markdown {
padding: 2rem 3rem 0 3rem;
display: block;
h1 {
font-family: 'Roboto Condensed';
}
}
} }
note .button { note .button {
color: #735992; color: #0e5055;
} }
.note-title { .note-title {
background-color: #e0bcff; background-color: #44c1ca;
} }

View File

@ -1,76 +1,72 @@
import { Component, EventEmitter, Output, Input, OnInit, ElementRef } from '@angular/core'; import { Component, EventEmitter, Output, Input, OnInit, ElementRef } from '@angular/core';
import { UUID } from 'angular2-uuid'; import { UUID } from 'angular2-uuid';
import { ModalController } from 'ionic-angular'; import { ModalController } from 'ionic-angular';
import { OpenData, CardItem, SearchPage } from '../../pages/search/search'; import { OpenData, CardItem, SearchPage } from '../../pages/search/search';
import { NoteItem, NotesService } from '../../services/notes-service'; import { NoteItem, NotesService } from '../../services/notes-service';
import { NoteCreateModal } from '../../components/note-create-modal/note-create-modal'; import { NoteCreateModal } from '../../components/note-create-modal/note-create-modal';
@Component({ @Component({
selector: 'note', selector: 'note',
templateUrl: 'note.html' templateUrl: 'note.html'
}) })
export class Note implements OnInit export class Note implements OnInit {
{ @Output()
@Output() onItemClicked = new EventEmitter<OpenData>();
onItemClicked = new EventEmitter<OpenData>();
@Output()
@Output() onClose = new EventEmitter<CardItem>();
onClose = new EventEmitter<CardItem>();
@Input()
@Input() cardItem: CardItem;
cardItem: CardItem;
@Input()
@Input() parent: SearchPage;
parent: SearchPage;
data: NoteItem | null;
data: NoteItem | null;
constructor(private elementRef: ElementRef, private noteService: NotesService, public modalCtrl: ModalController) {
constructor(private elementRef: ElementRef, private noteService: NotesService this.data = { id: UUID.UUID(), title: 'A note!', xref: null, content: 'Testing 1 2 3' };
, public modalCtrl: ModalController) }
{
ngOnInit(): void {
this.data = {id: UUID.UUID(), title: "A note!", xref: null, content: "Testing 1 2 3"}; this.noteService
} .getNoteAsPromise(this.cardItem.qry)
.then(note => {
ngOnInit(): void console.log('Got note from service: ', note);
{ this.data = note;
this.noteService.getNoteAsPromise(this.cardItem.qry).then(note => })
{ .catch(e => console.log(e));
console.log("Got note from service: ", note) }
this.data = note;
}).catch(e => console.log(e)); close(ev) {
} let translate = 'translate3d(110%, 0, 0)';
if (ev != null && ev.direction === 2) {
translate = 'translate3d(-110%, 0, 0)';
close() }
{ let d = 250;
let d = 250; this.elementRef.nativeElement.parentElement.animate(
this.elementRef.nativeElement.parentElement.animate({ {
transform: ['none', 'translate3d(110%, 0, 0)'] transform: ['none', translate]
}, { },
fill: 'forwards', {
duration: d, fill: 'forwards',
iterations: 1, duration: d,
easing: 'ease-in-out' iterations: 1,
}); easing: 'ease-in-out'
setTimeout(() => }
{ );
this.onClose.emit(this.cardItem); setTimeout(() => {
}, d); this.onClose.emit(this.cardItem);
} }, d);
}
edit()
{ edit() {
const modal = this.modalCtrl.create(NoteCreateModal, { data: this.data }); const modal = this.modalCtrl.create(NoteCreateModal, { data: this.data });
modal.present(); modal.present();
} }
delete() delete() {
{ this.noteService.deleteNote(this.data).catch(err => console.log(err));
this.noteService.deleteNote(this.data) }
.catch(err => console.log(err)); }
this.close();
}
}

View File

@ -1,94 +1,115 @@
<ion-list> <ion-list>
<ion-list-header> <ion-list-header> <ion-icon name="search" item-left></ion-icon>Search Settings </ion-list-header>
<ion-icon name="notes" item-left></ion-icon>Note Tools
</ion-list-header>
<ion-item>
<button ion-button block (click)='newNote()'>New Note</button>
</ion-item>
</ion-list>
<ion-list>
<ion-list-header>
<ion-icon name='search' item-left></ion-icon>Search Settings
</ion-list-header>
<ion-item> <ion-item>
<ion-label>Show Strongs as Modal</ion-label> <ion-label>Show Strongs as Modal</ion-label>
<ion-toggle color='dark' [(ngModel)]='profileService.profile().strongs_modal' (ionChange)='profileService.localSave()'></ion-toggle> <ion-toggle
color="dark"
[(ngModel)]="profileService.profile().strongs_modal"
(ionChange)="profileService.localSave()"
></ion-toggle>
</ion-item> </ion-item>
<ion-item> <ion-item>
<ion-label>Append Results Below</ion-label> <ion-label>Append Results Below</ion-label>
<ion-toggle color='dark' [(ngModel)]='profileService.profile().append_to_bottom' (ionChange)='profileService.localSave()'></ion-toggle> <ion-toggle
color="dark"
[(ngModel)]="profileService.profile().append_to_bottom"
(ionChange)="profileService.localSave()"
></ion-toggle>
</ion-item> </ion-item>
<ion-item> <ion-item>
<ion-label>Insert Result Next to Item</ion-label> <ion-label>Insert Result Next to Item</ion-label>
<ion-toggle color='dark' [(ngModel)]='profileService.profile().insert_next_to_item' (ionChange)='profileService.localSave()'></ion-toggle> <ion-toggle
color="dark"
[(ngModel)]="profileService.profile().insert_next_to_item"
(ionChange)="profileService.localSave()"
></ion-toggle>
</ion-item> </ion-item>
</ion-list> </ion-list>
<ion-list> <ion-list>
<ion-list-header> <ion-list-header> <ion-icon name="browsers" item-left></ion-icon>Display Settings </ion-list-header>
<ion-icon name='browsers' item-left></ion-icon>Display Settings
</ion-list-header>
<ion-item> <ion-item>
<ion-label>Each Verse on New Line</ion-label> <ion-label>Each Verse on New Line</ion-label>
<ion-toggle color='dark' [(ngModel)]='profileService.profile().verses_on_new_line' (ionChange)='profileService.localSave()'></ion-toggle> <ion-toggle
color="dark"
[(ngModel)]="profileService.profile().verses_on_new_line"
(ionChange)="profileService.localSave()"
></ion-toggle>
</ion-item> </ion-item>
<ion-item> <ion-item>
<ion-label>Show Verse #'s</ion-label> <ion-label>Show Verse #'s</ion-label>
<ion-toggle color='dark' [(ngModel)]='profileService.profile().show_verse_numbers' (ionChange)='profileService.localSave()'></ion-toggle> <ion-toggle
color="dark"
[(ngModel)]="profileService.profile().show_verse_numbers"
(ionChange)="profileService.localSave()"
></ion-toggle>
</ion-item> </ion-item>
<ion-item> <ion-item>
<ion-label>Show Paragraphs</ion-label> <ion-label>Show Paragraphs</ion-label>
<ion-toggle color='dark' [(ngModel)]='profileService.profile().show_paragraphs' (ionChange)='profileService.localSave()'></ion-toggle> <ion-toggle
color="dark"
[(ngModel)]="profileService.profile().show_paragraphs"
(ionChange)="profileService.localSave()"
></ion-toggle>
</ion-item> </ion-item>
<ion-item> <ion-item>
<ion-label>Show Paragraph Headings</ion-label> <ion-label>Show Paragraph Headings</ion-label>
<ion-toggle color='dark' [(ngModel)]='profileService.profile().show_paragraph_headings' (ionChange)='profileService.localSave()'></ion-toggle> <ion-toggle
color="dark"
[(ngModel)]="profileService.profile().show_paragraph_headings"
(ionChange)="profileService.localSave()"
></ion-toggle>
</ion-item> </ion-item>
</ion-list> </ion-list>
<ion-list> <ion-list>
<ion-list-header> <ion-list-header> <ion-icon name="sync" item-left></ion-icon>Profile Settings </ion-list-header>
<ion-icon name='sync' item-left></ion-icon>Profile Settings
</ion-list-header>
<ion-item> <ion-item>
<ion-label>Sync Search Items</ion-label> <ion-label>Sync Search Items</ion-label>
<ion-toggle color='dark' [(ngModel)]='profileService.profile().sync_search_items' (ionChange)='profileService.localSave()'></ion-toggle> <ion-toggle
color="dark"
[(ngModel)]="profileService.profile().sync_search_items"
(ionChange)="profileService.localSave()"
></ion-toggle>
</ion-item> </ion-item>
</ion-list> </ion-list>
<ion-list> <ion-list>
<ion-list-header> <ion-list-header> <ion-icon name="text" item-left></ion-icon>Adjust Text </ion-list-header>
<ion-icon name='text' item-left></ion-icon>Adjust Text
</ion-list-header>
<ion-item> <ion-item>
<ion-range min='6' max='20' step='1' snaps='true' [(ngModel)]='profileService.profile().font_size' (ionChange)='textSizeChanged()'> <ion-range
<ion-label range-left class='small-text'>a</ion-label> min="6"
max="20"
step="1"
snaps="true"
[(ngModel)]="profileService.profile().font_size"
(ionChange)="textSizeChanged()"
>
<ion-label range-left class="small-text">a</ion-label>
<ion-label range-right>A</ion-label> <ion-label range-right>A</ion-label>
</ion-range> </ion-range>
</ion-item> </ion-item>
<ion-item> <ion-item>
<ion-label>Text Font</ion-label> <ion-label>Text Font</ion-label>
<ion-select [(ngModel)]='profileService.profile().font_family' (ionChange)='fontFamilyChanged()'> <ion-select [(ngModel)]="profileService.profile().font_family" (ionChange)="fontFamilyChanged()">
<ion-option value='Roboto, Helvetica, Arial, sans-serif'>Roboto (sans)</ion-option> <ion-option value="Roboto, Helvetica, Arial, sans-serif">Roboto (sans)</ion-option>
<ion-option value='"Open Sans", sans-serif'>Open Sans (sans)</ion-option> <ion-option value='"Open Sans", sans-serif'>Open Sans (sans)</ion-option>
<ion-option value='"PT Sans", sans-serif'>PT Sans (sans)</ion-option> <ion-option value='"PT Sans", sans-serif'>PT Sans (sans)</ion-option>
<ion-option value='Georgia, serif'>Georgia (serif)</ion-option> <ion-option value="Georgia, serif">Georgia (serif)</ion-option>
<ion-option value='Merriweather, serif'>Merriweather (serif)</ion-option> <ion-option value="Merriweather, serif">Merriweather (serif)</ion-option>
<ion-option value='"PT Serif", serif'>PT Serif (serif)</ion-option> <ion-option value='"PT Serif", serif'>PT Serif (serif)</ion-option>
<ion-option value='Inconsolata, monospace'>Inconsolata (mono)</ion-option> <ion-option value="Inconsolata, monospace">Inconsolata (mono)</ion-option>
</ion-select> </ion-select>
</ion-item> </ion-item>
</ion-list> </ion-list>
<ion-list> <ion-list>
<ion-list-header> <ion-list-header> <ion-icon name="log-in" item-left></ion-icon>Login/Logout </ion-list-header>
<ion-icon name='log-in' item-left></ion-icon>Login/Logout
</ion-list-header>
<ng-template [ngIf]='!profileService.currentUser()'> <ng-template [ngIf]="!profileService.currentUser()">
<ion-item center> <ion-item center>
<button ion-button block (click)='profileService.authenticate()'>Login With Google</button> <button ion-button block (click)="profileService.authenticate()">Login With Google</button>
</ion-item> </ion-item>
</ng-template> </ng-template>
<ng-template [ngIf]='profileService.currentUser()'> <ng-template [ngIf]="profileService.currentUser()">
<ion-item center> <ion-item center>
<button ion-button block (click)='profileService.logout()'>Logout</button> <button ion-button block (click)="profileService.logout()">Logout</button>
</ion-item> </ion-item>
</ng-template> </ng-template>
</ion-list> </ion-list>

View File

@ -1,57 +1,82 @@
<ion-menu side='right' [content]='searchcontent' id='actions'> <ion-menu side="right" [content]="searchcontent" id="actions">
<ion-header> <ion-header>
<ion-toolbar> <ion-toolbar>
<ion-title>Actions</ion-title> <ion-title>Actions</ion-title>
</ion-toolbar> </ion-toolbar>
</ion-header> </ion-header>
<ion-content> <ion-content>
<ion-list-header> <ion-list-header>
Current Page: {{this.profileService.title}} Current Page: {{this.profileService.title}}
</ion-list-header> </ion-list-header>
<ion-list> <ion-list>
<button ion-item menuClose='actions' (click)='addPage()'> <button ion-item menuClose="actions" (click)="addPage()">
<ion-icon name='bookmarks' item-left></ion-icon>Save Results as New Page <ion-icon name="bookmarks" item-left></ion-icon>Save Results as New Page
</button> </button>
<button *ngIf='this.profileService.isOnSearchPage()' ion-item menuClose='actions' (click)='updatePage()'> <button *ngIf="this.profileService.isOnSearchPage()" ion-item menuClose="actions" (click)="updatePage()">
<ion-icon name='arrow-up' item-left></ion-icon>Update Page with Results <ion-icon name="arrow-up" item-left></ion-icon>Update Page with Results
</button> </button>
</ion-list> <button ion-item menuClose="actions" (click)="newNote()">
<settings></settings> <ion-icon name="clipboard" item-left></ion-icon>Create a New Note
</ion-content> </button>
</ion-menu> </ion-list>
<settings></settings>
<ion-header> </ion-content>
<ion-navbar> </ion-menu>
<button ion-button icon-only menuToggle left>
<ion-icon name='menu' large></ion-icon> <ion-header>
</button> <ion-navbar>
<ion-auto-complete [dataProvider]='autocompleteService' <button ion-button icon-only menuToggle left>
[(keyword)]='searchQuery' <ion-icon name="menu" large></ion-icon>
(search)='getQuery($event)' (input)='setQuery($event)' </button>
(itemSelected)='itemSelected($event)' [options]='{ showCancelButton : "true" }' <ion-auto-complete
(autoFocus)='showHistory($event)' #searchbar></ion-auto-complete> [dataProvider]="autocompleteService"
<ion-buttons right> [(keyword)]="searchQuery"
<button ion-button icon-only secondary (click)='versePicker()'> (search)="getQuery($event)"
<ion-icon name='albums' large></ion-icon> (input)="setQuery($event)"
</button> (itemSelected)="itemSelected($event)"
<button ion-button icon-only secondary (click)='actionsMenu()'> [options]='{ showCancelButton : "true" }'
<ion-icon name='apps' large></ion-icon> (autoFocus)="showHistory($event)"
</button> #searchbar
</ion-buttons> ></ion-auto-complete>
</ion-navbar> <ion-buttons right>
</ion-header> <button ion-button icon-only secondary (click)="versePicker()">
<ion-icon name="albums" large></ion-icon>
<ion-content #searchcontent padding class='search-card'> </button>
<ion-card *ngFor='let item of this.profileService.profile().items'> <button ion-button icon-only secondary (click)="actionsMenu()">
<passage *ngIf='isPassage(item.type)' [cardItem]='item' (onClose)='this.profileService.removeItem($event)' <ion-icon name="apps" large></ion-icon>
(onItemClicked)='getItemsNextToCard($event)'></passage> </button>
<strongs *ngIf='isStrongs(item.type)' [cardItem]='item' (onClose)='this.profileService.removeItem($event)' </ion-buttons>
(onItemClicked)='getItemsNextToCard($event)'></strongs> </ion-navbar>
<words *ngIf='isWords(item.type)' [cardItem]='item' (onClose)='this.profileService.removeItem($event)' </ion-header>
(onItemClicked)='getItemsNextToCard($event)'></words>
<error *ngIf='isError(item.type)' [cardItem]='item' (onClose)='this.profileService.removeItem($event)'></error> <ion-content #searchcontent padding class="search-card">
<note *ngIf="isNote(item.type)" [cardItem]="item" [parent]="self" (onClose)="removeItem($event)"></note> <ion-card *ngFor="let item of this.profileService.profile().items">
</ion-card> <passage
</ion-content> *ngIf="isPassage(item.type)"
[cardItem]="item"
(onClose)="this.profileService.removeItem($event)"
(onItemClicked)="getItemsNextToCard($event)"
></passage>
<strongs
*ngIf="isStrongs(item.type)"
[cardItem]="item"
(onClose)="this.profileService.removeItem($event)"
(onItemClicked)="getItemsNextToCard($event)"
></strongs>
<words
*ngIf="isWords(item.type)"
[cardItem]="item"
(onClose)="this.profileService.removeItem($event)"
(onItemClicked)="getItemsNextToCard($event)"
></words>
<error *ngIf="isError(item.type)" [cardItem]="item" (onClose)="this.profileService.removeItem($event)"></error>
<note
*ngIf="isNote(item.type)"
[cardItem]="item"
[parent]="self"
(onClose)="this.profileService.removeItem($event)"
></note>
</ion-card>
</ion-content>

View File

@ -1,34 +1,26 @@
import { Type, Component, OnInit, ViewChild } from "@angular/core"; import { Type, Component, OnInit, ViewChild } from '@angular/core';
import { import { Loading, LoadingController, ModalController, NavParams, AlertController, MenuController } from 'ionic-angular';
Loading, import { AutoCompleteComponent } from 'ionic2-auto-complete';
LoadingController,
ModalController,
NavParams,
AlertController,
MenuController,
TextInput,
Searchbar
} from "ionic-angular";
import { AutoCompleteComponent } from "ionic2-auto-complete";
import { StrongsModal } from "../../components/strongs-modal/strongs-modal"; import { StrongsModal } from '../../components/strongs-modal/strongs-modal';
import { VersePickerModal } from "../../components/verse-picker/verse-picker"; import { VersePickerModal } from '../../components/verse-picker/verse-picker';
import { PagesService } from "../../services/pages-service"; import { PagesService } from '../../services/pages-service';
import { ProfileService, User } from "./../../services/profile-service"; import { ProfileService, User } from './../../services/profile-service';
import { SearchAutoCompleteService } from "../../services/search-autocomplete-service"; import { SearchAutoCompleteService } from '../../services/search-autocomplete-service';
import { Reference } from "../../libs/Reference"; import { Reference } from '../../libs/Reference';
import { NotesService } from '../../services/notes-service';
@Component({ @Component({
templateUrl: "search.html", templateUrl: 'search.html',
providers: [SearchAutoCompleteService] providers: [SearchAutoCompleteService]
}) })
export class SearchPage implements OnInit { export class SearchPage implements OnInit {
searchQuery = ""; searchQuery = '';
loader: Loading; loader: Loading;
@ViewChild("searchbar") @ViewChild('searchbar')
searchbar: AutoCompleteComponent; searchbar: AutoCompleteComponent;
constructor( constructor(
@ -38,13 +30,14 @@ export class SearchPage implements OnInit {
public loadingCtrl: LoadingController, public loadingCtrl: LoadingController,
public modalCtrl: ModalController, public modalCtrl: ModalController,
public profileService: ProfileService, public profileService: ProfileService,
public noteService: NotesService,
public params: NavParams, public params: NavParams,
public autocompleteService: SearchAutoCompleteService public autocompleteService: SearchAutoCompleteService
) {} ) {}
ngOnInit(): void { ngOnInit(): void {
if (this.profileService.localIsLoaded) { if (this.profileService.localIsLoaded) {
this.loader = this.loadingCtrl.create({ content: "Loading Page..." }); this.loader = this.loadingCtrl.create({ content: 'Loading Page...' });
this.loader.present().then(() => { this.loader.present().then(() => {
let t = this.profileService.profile(); let t = this.profileService.profile();
this.initializeItems(t); this.initializeItems(t);
@ -53,7 +46,7 @@ export class SearchPage implements OnInit {
} else { } else {
this.profileService.onLocalStorageLoaded.subscribe(t => { this.profileService.onLocalStorageLoaded.subscribe(t => {
// Check if there is a profile saved in local storage // Check if there is a profile saved in local storage
this.loader = this.loadingCtrl.create({ content: "Loading Page..." }); this.loader = this.loadingCtrl.create({ content: 'Loading Page...' });
this.loader.present().then(() => { this.loader.present().then(() => {
this.initializeItems(t); this.initializeItems(t);
this.loader.dismiss(); this.loader.dismiss();
@ -72,17 +65,17 @@ export class SearchPage implements OnInit {
for (let i in u.items) { for (let i in u.items) {
if (u.items.hasOwnProperty(i)) { if (u.items.hasOwnProperty(i)) {
let ci = u.items[i]; let ci = u.items[i];
if (ci["data"] !== undefined) { if (ci['data'] !== undefined) {
if (ci["data"].qry !== undefined) if (ci['data'].qry !== undefined)
u.items[i] = { qry: ci["data"].qry, dict: ci.dict, type: ci.type }; u.items[i] = { qry: ci['data'].qry, dict: ci.dict, type: ci.type };
else if (ci["data"].ref !== undefined) else if (ci['data'].ref !== undefined)
u.items[i] = { qry: ci["data"].ref, dict: ci.dict, type: ci.type }; u.items[i] = { qry: ci['data'].ref, dict: ci.dict, type: ci.type };
else if (ci["data"].word !== undefined) else if (ci['data'].word !== undefined)
u.items[i] = { qry: ci["data"].word, dict: ci.dict, type: ci.type }; u.items[i] = { qry: ci['data'].word, dict: ci.dict, type: ci.type };
else if (ci["data"].sn !== undefined) else if (ci['data'].sn !== undefined)
u.items[i] = { u.items[i] = {
qry: ci["data"].sn, qry: ci['data'].sn,
dict: ci["prefix"] === "G" ? "grk" : "heb", dict: ci['prefix'] === 'G' ? 'grk' : 'heb',
type: ci.type type: ci.type
}; };
@ -95,17 +88,17 @@ export class SearchPage implements OnInit {
for (let i in pg.queries) { for (let i in pg.queries) {
if (pg.queries.hasOwnProperty(i)) { if (pg.queries.hasOwnProperty(i)) {
let ci = pg.queries[i]; let ci = pg.queries[i];
if (ci["data"] !== undefined) { if (ci['data'] !== undefined) {
if (ci["data"].qry !== undefined) if (ci['data'].qry !== undefined)
pg.queries[i] = { qry: ci["data"].qry, dict: ci.dict, type: ci.type }; pg.queries[i] = { qry: ci['data'].qry, dict: ci.dict, type: ci.type };
else if (ci["data"].ref !== undefined) else if (ci['data'].ref !== undefined)
pg.queries[i] = { qry: ci["data"].ref, dict: ci.dict, type: ci.type }; pg.queries[i] = { qry: ci['data'].ref, dict: ci.dict, type: ci.type };
else if (ci["data"].word !== undefined) else if (ci['data'].word !== undefined)
pg.queries[i] = { qry: ci["data"].word, dict: ci.dict, type: ci.type }; pg.queries[i] = { qry: ci['data'].word, dict: ci.dict, type: ci.type };
else if (ci["data"].sn !== undefined) else if (ci['data'].sn !== undefined)
pg.queries[i] = { pg.queries[i] = {
qry: ci["data"].sn, qry: ci['data'].sn,
dict: ci["prefix"] === "G" ? "grk" : "heb", dict: ci['prefix'] === 'G' ? 'grk' : 'heb',
type: ci.type type: ci.type
}; };
@ -122,7 +115,7 @@ export class SearchPage implements OnInit {
if (this.params.data.queries !== undefined) if (this.params.data.queries !== undefined)
this.profileService.profile().items = JSON.parse(JSON.stringify(this.params.data.queries)); this.profileService.profile().items = JSON.parse(JSON.stringify(this.params.data.queries));
if (this.params.data.title === undefined) this.profileService.title = "Search"; if (this.params.data.title === undefined) this.profileService.title = 'Search';
else this.profileService.title = this.params.data.title; else this.profileService.title = this.params.data.title;
if (has_migrated) this.profileService.save(); if (has_migrated) this.profileService.save();
@ -141,28 +134,28 @@ export class SearchPage implements OnInit {
this.profileService.localSave(); this.profileService.localSave();
} }
actionsMenu() { actionsMenu() {
this.menu.open("actions"); this.menu.open('actions');
} }
addPage() { addPage() {
const alert = this.alertCtrl.create({ const alert = this.alertCtrl.create({
title: "Save Search as Page", title: 'Save Search as Page',
inputs: [ inputs: [
{ {
name: "title", name: 'title',
placeholder: "Page Title" placeholder: 'Page Title'
} }
], ],
buttons: [ buttons: [
{ {
text: "Cancel", text: 'Cancel',
role: "cancel", role: 'cancel',
handler: (): void => { handler: (): void => {
console.log("Cancel clicked"); console.log('Cancel clicked');
} }
}, },
{ {
text: "Save", text: 'Save',
handler: data => { handler: data => {
const p = { queries: this.profileService.profile().items.slice(), title: data.title }; const p = { queries: this.profileService.profile().items.slice(), title: data.title };
this.profileService.profile().saved_pages.push(p); this.profileService.profile().saved_pages.push(p);
@ -183,17 +176,17 @@ export class SearchPage implements OnInit {
itemSelected(autocomplete: string) { itemSelected(autocomplete: string) {
let qry = autocomplete; let qry = autocomplete;
let idx = qry.lastIndexOf(";"); let idx = qry.lastIndexOf(';');
let prefix = ""; let prefix = '';
if (idx > -1) { if (idx > -1) {
qry = autocomplete.substr(idx + 1).trim(); qry = autocomplete.substr(idx + 1).trim();
prefix = autocomplete.substr(0, idx).trim() + "; "; prefix = autocomplete.substr(0, idx).trim() + '; ';
} }
const bk = Reference.parseBook(qry); const bk = Reference.parseBook(qry);
if (bk.book_number > 0) { if (bk.book_number > 0) {
this.searchQuery = prefix + qry.trim() + " "; this.searchQuery = prefix + qry.trim() + ' ';
this.searchbar.setFocus(); this.searchbar.setFocus();
} else { } else {
this.searchQuery = prefix + autocomplete; this.searchQuery = prefix + autocomplete;
@ -207,8 +200,8 @@ export class SearchPage implements OnInit {
getQuery() { getQuery() {
const qry = this.searchQuery; const qry = this.searchQuery;
this.searchQuery = ""; this.searchQuery = '';
this.searchbar.setValue(""); this.searchbar.setValue('');
this.profileService.addSearchRequestToHistory(qry); this.profileService.addSearchRequestToHistory(qry);
this.updateUIwithItems(qry, true); this.updateUIwithItems(qry, true);
} }
@ -225,19 +218,19 @@ export class SearchPage implements OnInit {
} }
isError(t: string) { isError(t: string) {
return t === "Error"; return t === 'Error';
} }
isPassage(t: string) { isPassage(t: string) {
return t === "Passage"; return t === 'Passage';
} }
isNote(t: string) { isNote(t: string) {
return t === "Note"; return t === 'Note';
} }
isStrongs(t: string) { isStrongs(t: string) {
return t === "Strongs"; return t === 'Strongs';
} }
isWords(t: string) { isWords(t: string) {
return t === "Words"; return t === 'Words';
} }
versePicker() { versePicker() {
@ -257,40 +250,38 @@ export class SearchPage implements OnInit {
const list: CardItem[] = []; const list: CardItem[] = [];
try { try {
const qs = search.split(";"); const qs = search.split(';');
for (let x in qs) { for (let x in qs) {
if (qs.hasOwnProperty(x)) { if (qs.hasOwnProperty(x)) {
let q = qs[x].trim(); let q = qs[x].trim();
if (q !== "") { if (q !== '') {
if (q.startsWith("note:")) { if (q.startsWith('note:')) {
// It's a note lookup // It's a note lookup
list.push({ list.push({
qry: q.replace("note:", ""), qry: q.replace('note:', ''),
dict: "", dict: '',
type: "Note" type: 'Note'
}); });
} } else if (q.search(/[0-9]/i) === -1) {
else if (q.search(/[0-9]/i) === -1) {
// its a search term. // its a search term.
list.push({ qry: q, dict: "na", type: "Words" }); list.push({ qry: q, dict: 'na', type: 'Words' });
} } else if (q.search(/(H|G)[0-9]/i) !== -1) {
else if (q.search(/(H|G)[0-9]/i) !== -1) {
// its a strongs lookup // its a strongs lookup
let dict = q.substring(0, 1); let dict = q.substring(0, 1);
if (dict.search(/h/i) !== -1) dict = "heb"; if (dict.search(/h/i) !== -1) dict = 'heb';
else dict = "grk"; else dict = 'grk';
q = q.substring(1, q.length); q = q.substring(1, q.length);
list.push({ qry: q, dict: dict, type: "Strongs" }); list.push({ qry: q, dict: dict, type: 'Strongs' });
} else { } else {
// its a verse reference. // its a verse reference.
if (q.trim() !== "") { if (q.trim() !== '') {
const myref = new Reference(q.trim()); const myref = new Reference(q.trim());
list.push({ list.push({
qry: myref.toString(), qry: myref.toString(),
dict: myref.Section.start.book.book_number > 39 ? "G" : "H", dict: myref.Section.start.book.book_number > 39 ? 'G' : 'H',
type: "Passage" type: 'Passage'
}); });
} }
} }
@ -300,7 +291,7 @@ export class SearchPage implements OnInit {
this.profileService.save(); this.profileService.save();
} catch (error) { } catch (error) {
list.push({ qry: error, type: "Error", dict: "na" }); list.push({ qry: error, type: 'Error', dict: 'na' });
console.log(error); console.log(error);
} }
@ -310,14 +301,14 @@ export class SearchPage implements OnInit {
updateUIwithItems(search: string, from_search_bar: boolean) { updateUIwithItems(search: string, from_search_bar: boolean) {
// clear search box. // clear search box.
this.searchQuery = ""; this.searchQuery = '';
this.searchbar.setValue(""); this.searchbar.setValue('');
this.getItemList(search).then(lst => { this.getItemList(search).then(lst => {
this.loader = this.loadingCtrl.create({ content: "Looking up Query..." }); this.loader = this.loadingCtrl.create({ content: 'Looking up Query...' });
this.loader.present().then(() => { this.loader.present().then(() => {
for (let item of lst) { for (let item of lst) {
if (item.type === "Strongs" && this.profileService.profile().strongs_modal && !from_search_bar) { if (item.type === 'Strongs' && this.profileService.profile().strongs_modal && !from_search_bar) {
const modal = this.modalCtrl.create(StrongsModal, { const modal = this.modalCtrl.create(StrongsModal, {
sn: item.qry, sn: item.qry,
dict: item.dict, dict: item.dict,