diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 3ee0f61..16dd4f5 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -13,6 +13,22 @@ import { ComponentsModule } from './components/components.module';
import { TreeModule } from 'angular-tree-component';
import {AgGridModule} from 'ag-grid-angular';
import {MonacoEditorModule} from 'ngx-monaco-editor';
+import { APP_BASE_HREF, PlatformLocation } from '@angular/common';
+
+/**
+ * This function is used internal to get a string instance of the `` value from `index.html`.
+ * This is an exported function, instead of a private function or inline lambda, to prevent this error:
+ *
+ * `Error encountered resolving symbol values statically.`
+ * `Function calls are not supported.`
+ * `Consider replacing the function or lambda with a reference to an exported function.`
+ *
+ * @param platformLocation an Angular service used to interact with a browser's URL
+ * @return a string instance of the `` value from `index.html`
+ */
+export function getBaseHref(platformLocation: PlatformLocation): string {
+ return platformLocation.getBaseHrefFromDOM();
+}
@NgModule({
declarations: [AppComponent],
@@ -30,7 +46,12 @@ import {MonacoEditorModule} from 'ngx-monaco-editor';
providers: [
StatusBar,
SplashScreen,
- { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
+ { provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
+ {
+ provide: APP_BASE_HREF,
+ useFactory: getBaseHref,
+ deps: [PlatformLocation]
+ }
],
bootstrap: [AppComponent]
})
diff --git a/src/app/components/editor/files/files.component.html b/src/app/components/editor/files/files.component.html
index 23f0f0a..df587fd 100644
--- a/src/app/components/editor/files/files.component.html
+++ b/src/app/components/editor/files/files.component.html
@@ -2,6 +2,7 @@
diff --git a/src/app/components/editor/files/files.component.scss b/src/app/components/editor/files/files.component.scss
index 46ebbe3..2a2d50b 100644
--- a/src/app/components/editor/files/files.component.scss
+++ b/src/app/components/editor/files/files.component.scss
@@ -1,4 +1,5 @@
div.files-wrapper {
border: 2px solid #8c8c8c;
border-radius: 3px;
+ margin-top: 15px;
}
diff --git a/src/app/components/editor/files/files.component.ts b/src/app/components/editor/files/files.component.ts
index d072f51..6173fe5 100644
--- a/src/app/components/editor/files/files.component.ts
+++ b/src/app/components/editor/files/files.component.ts
@@ -1,8 +1,9 @@
-import {Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild} from '@angular/core';
+import {Component, ElementRef, EventEmitter, Inject, Input, OnInit, Output, ViewChild} from '@angular/core';
import HostRecord from '../../../structures/HostRecord';
import {ApiService} from '../../../service/api.service';
import {AlertController} from '@ionic/angular';
import {Observable} from 'rxjs';
+import { APP_BASE_HREF } from '@angular/common';
@Component({
selector: 'editor-files',
@@ -23,6 +24,7 @@ export class FilesComponent implements OnInit {
constructor(
protected api: ApiService,
protected alerts: AlertController,
+ @Inject(APP_BASE_HREF) private baseHref: string
) { }
ngOnInit() {
@@ -39,6 +41,10 @@ export class FilesComponent implements OnInit {
this.uploadForm.nativeElement.submit();
}
+ getReturnUrl() {
+ return `${this.baseHref}editor;id=${this.hostRecord.PageId}`;
+ }
+
downloadFile(fileRecord) {
// tslint:disable-next-line:max-line-length
window.open(this.api._build_url(`files/${this.hostRecord.PageId}/${this.hostRecord.UUID}/get/${this.hostRecord.Value.Value}/${fileRecord._id}`), '_blank');
diff --git a/src/app/components/editor/host/host.component.html b/src/app/components/editor/host/host.component.html
index 071815b..fd27e72 100644
--- a/src/app/components/editor/host/host.component.html
+++ b/src/app/components/editor/host/host.component.html
@@ -15,14 +15,17 @@
class="host-host ion-padding"
>
+
+
+
this.listLines.push(group.value));
+ setTimeout(() => {
+ values.forEach((group, i) => {
+ const el = this.liItems.toArray()[i].nativeElement;
+ el.className += ` node-indentation-level-num-${group.indentationLevel}`;
+ });
+ }, 0);
+ }
+ }
onRecordChange($event) {
this.recordChange.emit($event);
@@ -27,13 +38,13 @@ export class HostComponent implements OnInit {
onKeyUp($event) {
const innerText = this.hostContainer.nativeElement.innerText.trim()
- if ( $event.code === 'Enter'
+ if ( $event.code === 'Enter' && this.record.isNorm() && !$event.shiftKey
&& ( this.record.type !== 'block_code'
- || (innerText.endsWith('```') && (innerText.match(/`/g) || []).length >= 6)
+ || (innerText.endsWith('```') && (innerText.match(/`/g) || []).length >= 6) // TODO don't add new if cursor in block
)
) {
- this.newHostRequested.emit(this);
this.hostContainer.nativeElement.innerText = this.hostContainer.nativeElement.innerText.trim();
+ this.newHostRequested.emit(this);
} else if ( $event.code === 'Backspace' && !this.hostContainer.nativeElement.innerText.trim() ) {
this.destroyHostRequested.emit(this);
}
@@ -50,60 +61,119 @@ export class HostComponent implements OnInit {
this.record.type = 'block_code';
} else if ( innerText.startsWith('http') ) {
this.record.type = 'click_link';
- } else if ( false && innerText.startsWith('-') || innerText.startsWith(' -') ) {
- // this.record.type = 'ul';
+ } else if ( innerText === '---' ) {
+ this.record.type = 'page_sep';
+ } else if ( innerText.startsWith('-') || innerText.startsWith(' -') ) {
+ this.record.type = 'ul';
this.listLines = [this.record.value];
setTimeout(() => {
- const item = this.liItems.toArray()[0].nativeElement;
- const s = window.getSelection();
- const r = document.createRange();
- r.setStart(item, 0);
- r.setEnd(item, 0);
- s.removeAllRanges();
- s.addRange(r);
+ this.focusStart(this.liItems.toArray()[0].nativeElement);
}, 0);
}
}
- onRequestDelete($event) {
- this.destroyHostRequested.emit(this);
+ onUlKeyDown($event, index) {
+ if ( $event.code === 'Tab' ) {
+ $event.preventDefault();
+ const elem = this.liItems.toArray()[index];
+ let currentLevel = 0;
+
+ elem.nativeElement.className.split(' ').some(x => {
+ if ( x.startsWith('node-indentation-level-num-') ) {
+ currentLevel = Number(x.replace('node-indentation-level-num-', ''));
+ return true;
+ }
+ });
+
+ const newLevel = $event.shiftKey ? currentLevel - 1 : currentLevel + 1;
+ if ( newLevel <= 5 && newLevel >= 0 ) {
+ const existing = elem.nativeElement.className.split(' ').filter(x => !x.startsWith('node-indentation-level-num-'));
+ existing.push(`node-indentation-level-num-${newLevel}`);
+
+ elem.nativeElement.className = existing.join(' ');
+ }
+ }
}
- onLIKeyUp($event, i) {
- if ( $event.code === 'Enter' ) {
- /*const newListLines = [];
- this.liItems.forEach((li, index) => {
- newListLines.push(li.nativeElement.innerText.trim());
- if ( index === i ) {
- newListLines.push('');
+ onUlKeyUp($event, i) {
+ if ( $event.code === 'Enter' && !$event.shiftKey ) {
+ const e = this.liItems.toArray()[i].nativeElement;
+ e.innerText = e.innerText.trim();
+ if ( this.liItems.toArray()[i].nativeElement.innerText.trim() === '' ) {
+ this.newHostRequested.emit(this);
+ } else {
+ this.listLines.push('');
+ setTimeout(() => {
+ this.focusStart(this.liItems.toArray()[i + 1].nativeElement);
+
+ let newLevel = 0;
+ this.liItems.toArray()[i].nativeElement.className.split(' ').some(x => {
+ if ( x.startsWith('node-indentation-level-num-') ) {
+ newLevel = Number(x.replace('node-indentation-level-num-', ''));
+ return true;
+ }
+ });
+
+ const classes = this.liItems.toArray()[i + 1].nativeElement.className
+ .split(' ')
+ .filter(x => !x.startsWith('node-indentation-level-num-'));
+ classes.push(`node-indentation-level-num-${newLevel}`);
+ this.liItems.toArray()[i + 1].nativeElement.className = classes.join(' ');
+ }, 0);
+ }
+ } else if ( $event.code === 'Backspace' && this.liItems.toArray()[i].nativeElement.innerText.trim() === '' ) {
+ const newLines = [];
+ this.liItems.toArray().forEach((elem, index) => {
+ if ( index !== i ) {
+ newLines.push(elem.innerText ? elem.innerText.trim() : '');
}
});
- this.listLines = newListLines;*/
- // this.listLines[i] = this.liItems[i].innerText.trim()
- // const newLines = []
- // this.listLines.forEach((rec, x) => {
- // newLines.push(rec.trim());
- // if ( i === x ) {
- // newLines.push('');
- // }
- // })
-
-
- // this.listLines = newLines;
-
- // setTimeout(() => {
- // const item = this.liItems.toArray()[i + 1].nativeElement;
- // const s = window.getSelection();
- // const r = document.createRange();
- // r.setStart(item, 0);
- // r.setEnd(item, 0);
- // s.removeAllRanges();
- // s.addRange(r);
- // }, 10);
+ this.listLines = newLines;
+
+ if ( i === 0 && this.listLines.length === 0 ) {
+ this.destroyHostRequested.emit(this);
+ } else {
+ setTimeout(() => {
+ this.focusEnd(this.liItems.toArray()[i - 1].nativeElement);
+ }, 0);
+ }
+ } else if ( $event.code === 'ArrowDown' ) {
+ const liArr = this.liItems.toArray();
+ if ( liArr.length > i + 1 ) {
+ setTimeout(() => {
+ this.focusStart(this.liItems.toArray()[i + 1].nativeElement);
+ }, 0);
+ }
+ } else if ( $event.code === 'ArrowUp' ) {
+ if ( i !== 0 ) {
+ setTimeout(() => {
+ this.focusStart(this.liItems.toArray()[i - 1].nativeElement);
+ }, 0);
+ }
+ } else {
+ const recordValue = this.liItems.toArray().map(item => {
+ const elem = item.nativeElement;
+ const value = elem.innerText.trim();
+ let indentationLevel = 0;
+ elem.className.split(' ').some(x => {
+ if ( x.startsWith('node-indentation-level-num-') ) {
+ indentationLevel = x.replace('node-indentation-level-num-', '');
+ return true;
+ }
+ });
+
+ return {value, indentationLevel};
+ });
+
+ this.record.value = JSON.stringify(recordValue);
}
}
+ onRequestDelete($event) {
+ this.destroyHostRequested.emit(this);
+ }
+
onRequestParentSave($event) {
this.saveHostRequested.emit(this);
}
@@ -114,4 +184,48 @@ export class HostComponent implements OnInit {
}
}
+ takeFocus(fromTop = true) {
+ if ( this.record.type === 'ul' ) {
+ if ( fromTop ) {
+ this.focusStart(this.liItems.toArray()[0].nativeElement);
+ } else {
+ this.focusEnd(this.liItems.toArray().reverse()[0].nativeElement);
+ }
+ } else {
+ if ( fromTop ) {
+ this.focusStart(this.hostContainer.nativeElement);
+ } else {
+ this.focusEnd(this.hostContainer.nativeElement);
+ }
+ }
+ }
+
+ // TODO return an observable here, probably
+ focusEnd(item) {
+ const s = window.getSelection();
+ const r = document.createRange();
+ r.setStart(item, 0);
+ r.setEnd(item, 0);
+ s.removeAllRanges();
+ s.addRange(r);
+ }
+
+ // TODO return an observable here, probably
+ focusStart(item) {
+ const s = window.getSelection();
+ const r = document.createRange();
+ r.setStart(item, 0);
+ r.setEnd(item, 0);
+ s.removeAllRanges();
+ s.addRange(r);
+
+ setTimeout(() => {
+ const r2 = document.createRange();
+ r2.selectNodeContents(item);
+ r2.collapse(false);
+ const s2 = window.getSelection();
+ s2.removeAllRanges();
+ s2.addRange(r2);
+ }, 0);
+ }
}
diff --git a/src/app/components/editor/node-picker/node-picker.component.html b/src/app/components/editor/node-picker/node-picker.component.html
index 56fde2c..b14eb8d 100644
--- a/src/app/components/editor/node-picker/node-picker.component.html
+++ b/src/app/components/editor/node-picker/node-picker.component.html
@@ -19,6 +19,10 @@
Heading 4
+
+
+ Unordered List
+
Monospace Block
@@ -39,4 +43,8 @@
Upload Files
+
+
+ Horizontal Row
+
diff --git a/src/app/pages/editor/editor.page.html b/src/app/pages/editor/editor.page.html
index 3e6416a..8ba7b40 100644
--- a/src/app/pages/editor/editor.page.html
+++ b/src/app/pages/editor/editor.page.html
@@ -16,7 +16,7 @@
-