|
|
|
@ -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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|