Add auto-save support and saving indicator
This commit is contained in:
parent
9a53faf338
commit
9f80842b9f
@ -199,12 +199,15 @@ export class CodeComponent extends EditorNodeContract implements OnInit {
|
||||
public onEditorModelChange($event) {
|
||||
if ( this.editorValue !== this.dbRecord.code ) {
|
||||
this.dirty = true;
|
||||
this.editorService.triggerSave();
|
||||
}
|
||||
}
|
||||
|
||||
public onSelectChange(updateDbRecord = true) {
|
||||
if ( updateDbRecord ) {
|
||||
this.dbRecord.Language = this.editorOptions.language;
|
||||
this.editorService.triggerSave();
|
||||
this.dirty = true;
|
||||
}
|
||||
|
||||
this.editorOptions = {...this.editorOptions};
|
||||
|
@ -71,6 +71,7 @@ export class DatabaseComponent extends EditorNodeContract implements OnInit {
|
||||
|
||||
onCellValueChanged() {
|
||||
this.dirty = true;
|
||||
this.editorService.triggerSave();
|
||||
}
|
||||
|
||||
async onManageColumns() {
|
||||
@ -98,6 +99,7 @@ export class DatabaseComponent extends EditorNodeContract implements OnInit {
|
||||
this.rowData.push({});
|
||||
this.agGridElement.api.setRowData(this.rowData);
|
||||
this.dirty = true;
|
||||
this.editorService.triggerSave();
|
||||
}
|
||||
|
||||
async onRemoveRow() {
|
||||
@ -122,6 +124,7 @@ export class DatabaseComponent extends EditorNodeContract implements OnInit {
|
||||
this.agGridElement.api.setRowData(this.rowData);
|
||||
this.lastClickRow = -1;
|
||||
this.dirty = true;
|
||||
this.editorService.triggerSave();
|
||||
},
|
||||
}
|
||||
],
|
||||
@ -168,6 +171,7 @@ export class DatabaseComponent extends EditorNodeContract implements OnInit {
|
||||
|
||||
this.agGridElement.api.setColumnDefs(this.columnDefs);
|
||||
this.dirty = true;
|
||||
this.editorService.triggerSave();
|
||||
}
|
||||
|
||||
public async performLoad(): Promise<void> {
|
||||
|
@ -62,6 +62,7 @@ export class NormComponent extends EditorNodeContract implements OnInit {
|
||||
const innerHTML = this.editable.nativeElement.innerHTML;
|
||||
if ( this.contents !== innerHTML ) {
|
||||
this.contents = innerHTML;
|
||||
this.editorService.triggerSave();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,12 @@
|
||||
class="title-input"
|
||||
></ion-input>
|
||||
</ion-title>
|
||||
<ion-buttons slot="end">
|
||||
<button class="save-button" (click)="editorService.triggerSave()" title="Manually save this note">
|
||||
<i *ngIf="!(editorService.isSaving || editorService.willSave)" class="fa fa-check-circle"></i>
|
||||
{{ (editorService.isSaving || editorService.willSave) ? 'Saving...' : 'Saved!' }}
|
||||
</button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
|
@ -48,3 +48,11 @@ ion-icon.invisible {
|
||||
color: #4d4d4d;
|
||||
}
|
||||
}
|
||||
|
||||
.save-button {
|
||||
color: #777;
|
||||
|
||||
i {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,17 @@ export class NoPageLoadedError extends Error {
|
||||
}
|
||||
}
|
||||
|
||||
export function debounce(func: (...args: any[]) => any, timeout?: number) {
|
||||
let timer: number | undefined;
|
||||
return (...args: any[]) => {
|
||||
const next = () => func(...args);
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
timer = setTimeout(next, timeout > 0 ? timeout : 300);
|
||||
};
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
@ -21,6 +32,30 @@ export class EditorService {
|
||||
protected dirtyOverride = false;
|
||||
protected ready$: BehaviorSubject<boolean> = new BehaviorSubject<boolean>(false);
|
||||
protected subs: Subscription[] = [];
|
||||
protected saving = false;
|
||||
protected saveTriggered = false;
|
||||
protected privTriggerSave = debounce(() => {
|
||||
if ( this.saving ) {
|
||||
this.triggerSave();
|
||||
} else {
|
||||
this.save();
|
||||
}
|
||||
|
||||
this.saveTriggered = false;
|
||||
}, 3000);
|
||||
|
||||
public triggerSave() {
|
||||
this.saveTriggered = true;
|
||||
this.privTriggerSave();
|
||||
}
|
||||
|
||||
public get isSaving() {
|
||||
return this.saving;
|
||||
}
|
||||
|
||||
public get willSave() {
|
||||
return this.saveTriggered;
|
||||
}
|
||||
|
||||
public get immutableNodes(): HostRecord[] {
|
||||
return [...this.currentNodes];
|
||||
@ -46,9 +81,7 @@ export class EditorService {
|
||||
|
||||
constructor(
|
||||
protected api: ApiService,
|
||||
) {
|
||||
console.log('editor service', this);
|
||||
}
|
||||
) { }
|
||||
|
||||
async startEditing(pageId: string) {
|
||||
if ( this.currentPage ) {
|
||||
@ -58,8 +91,6 @@ export class EditorService {
|
||||
this.currentPage = await this.loadPage(pageId);
|
||||
this.currentNodes = await this.loadNodes(pageId);
|
||||
await this.ready$.next(true);
|
||||
console.log('editing', this.currentPage);
|
||||
console.log('nodes', this.currentNodes);
|
||||
}
|
||||
|
||||
async stopEditing() {
|
||||
@ -72,10 +103,11 @@ export class EditorService {
|
||||
}
|
||||
|
||||
async save() {
|
||||
if ( !(await this.needsSave()) ) {
|
||||
if ( !(await this.needsSave()) || this.saving ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.saving = true;
|
||||
const editors = Object.values(this.nodeIdToEditorContract);
|
||||
|
||||
// Save all editors that handle their data independently first
|
||||
@ -92,6 +124,7 @@ export class EditorService {
|
||||
|
||||
await this.saveNodesAsPage(this.currentPage, this.currentNodes);
|
||||
this.dirtyOverride = false;
|
||||
this.saving = false;
|
||||
}
|
||||
|
||||
async moveNode(node: HostRecord, direction: 'up' | 'down') {
|
||||
@ -117,6 +150,7 @@ export class EditorService {
|
||||
}
|
||||
|
||||
this.dirtyOverride = true;
|
||||
this.triggerSave();
|
||||
}
|
||||
|
||||
async saveNodesAsPage(page: PageRecord, nodes: HostRecord[]): Promise<HostRecord[]> {
|
||||
@ -184,6 +218,7 @@ export class EditorService {
|
||||
|
||||
this.currentNodes = this.currentNodes.filter(x => x.UUID !== nodeId);
|
||||
this.dirtyOverride = true;
|
||||
this.triggerSave();
|
||||
}
|
||||
|
||||
async addNode(type: 'paragraph' | 'code_ref' | 'database_ref' | 'file_ref', position?: 'before' | 'after', positionNodeId?: string) {
|
||||
@ -217,6 +252,7 @@ export class EditorService {
|
||||
}
|
||||
|
||||
this.dirtyOverride = true;
|
||||
this.triggerSave();
|
||||
return host;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user