Skip to content

Commit

Permalink
feat(form-builder): refactored save method #77
Browse files Browse the repository at this point in the history
  • Loading branch information
flauc committed Feb 11, 2022
1 parent 918454d commit fc8ca71
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 123 deletions.
86 changes: 53 additions & 33 deletions projects/form-builder/src/lib/form-builder.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,12 @@ import {
SimpleChanges
} from '@angular/core';
import {FormGroup} from '@angular/forms';
import {forkJoin, of, Subscription} from 'rxjs';
import {map} from 'rxjs/operators';
import {concat, map, of, Subscription, switchMap} from 'rxjs';
import {State} from './enums/state.enum';
import {FormBuilderService} from './form-builder.service';
import {CompiledSegment} from './interfaces/compiled-segment.interface';
import {FormBuilderData} from './interfaces/form-builder-data.interface';
import {GlobalState} from './interfaces/global-state.interface';
import {GlobalState, Operation} from './interfaces/global-state.interface';
import {DEFAULT_SEGMENT} from './utils/default-segment';
import {filterAndCompileSegments} from './utils/filter-and-compile-segments';
import {Parser} from './utils/parser';
Expand Down Expand Up @@ -107,7 +106,8 @@ export class FormBuilderComponent implements OnChanges, OnDestroy {
try {
delete window.jpFb.forms[this.id];
delete window.jpFb.parsers[this.id];
} catch (e) {}
delete window.jpFb.operations[this.id];
} catch (e) { }
}

process() {
Expand All @@ -118,31 +118,43 @@ export class FormBuilderComponent implements OnChanges, OnDestroy {
return this.form.getRawValue();
}

save(
collectionId: string,
documentId: string,
overrideComponents?: any[]
) {
const toExec = (overrideComponents || this.service.saveComponents).map(comp =>
comp.save(collectionId, documentId)
);
save(collectionId: string, documentId: string) {

return (
toExec.length ?
forkJoin(toExec) :
of({})
)
.pipe(
map(() =>
this.form.getRawValue()
)
);
const data = this.form.getRawValue();

/**
* Child forms processes are run on save
* of the parent form
*/
if (!this.parent) {
return of(data);
}

const processes = Object.entries<Operation>(window.jpFb[this.id].processes)
.sort((p1, p2) => p1[1].priority - p2[1].priority)
.filter(process => process[1].save);

if (!processes.length) {
return of(data);
}

const operations = [
...processes.map(([pointer, process]) =>
switchMap(() => process.save({
pointer,
collectionId,
documentId,
entryValue: this.value,
outputValue: data
}))
),
map(() => data)
]

return (of(data).pipe as any)(...operations)
}

saveAndProcess(
collectionId: string,
documentId: string
) {
saveAndProcess(collectionId: string, documentId: string) {
this.process();

return this.save(
Expand All @@ -159,7 +171,7 @@ export class FormBuilderComponent implements OnChanges, OnDestroy {
error: false,
message: ''
};
} catch(error) {
} catch (error) {
return {
error: true,
message: error.message || 'Invalid Schema provided!'
Expand Down Expand Up @@ -193,22 +205,30 @@ export class FormBuilderComponent implements OnChanges, OnDestroy {
if (!window.jpFb) {
window.jpFb = {
forms: {},
parsers: {}
parsers: {},
operations: {}
}
}

window.jpFb.forms[this.id] = this.form;
window.jpFb.parsers[this.id] = this.innerParser;

/**
* Child forms push operations to their parent form
*/
if (!this.parent) {
window.jpFb.operations[this.id] = {};
}

this.innerParser.loadHooks();

this.segments = filterAndCompileSegments({
segments: this.data.segments || [{
title: '',
fields: Object.keys(this.innerParser.pointers),
columnsDesktop: 12,
type: this.defaultSegment || 'empty'
}],
title: '',
fields: Object.keys(this.innerParser.pointers),
columnsDesktop: 12,
type: this.defaultSegment || 'empty'
}],
parser: this.innerParser,
definitions,
injector: this.injector,
Expand Down
17 changes: 0 additions & 17 deletions projects/form-builder/src/lib/form-builder.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,6 @@ export class FormBuilderService {
private snackBar: MatSnackBar
) {}

/**
* Array of components that need to
* run save() methods on single instance
*/
saveComponents: any[] = [];

removeComponent(component) {
const index = this.saveComponents.indexOf(component);

if (index !== -1) {
this.saveComponents.splice(
index,
1
)
}
}

notify(
options: {
success?: string | null;
Expand Down
46 changes: 44 additions & 2 deletions projects/form-builder/src/lib/interfaces/global-state.interface.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,49 @@
import {FormGroup} from '@angular/forms';
import {Observable} from 'rxjs';
import {Parser} from '../utils/parser';

export type Process = <T = any>(data: {
pointer: string,
collectionId: string,
documentId: string,
/**
* Value at form initialization.
* This will only be available when
* updating or deleting
*/
entryValue?: any,

/**
* This is the value passed on to further
* operations and returned by the form
*/
outputValue: any
}) => Observable<T>;

export interface Operation {
priority: number;
save?: Process;
delete?: Process;
};

export interface GlobalState {
forms: {[id: string]: FormGroup}
parsers: {[id: string]: Parser}
forms: {[id: string]: FormGroup};
parsers: {[id: string]: Parser};

/**
* Operators are sorted in order of priority
* and executed when the "save" method is called.
*
* They should each mutate the "outputValue" which
* is forwarded along to each subsuqent "save"
* method and returned by the "save" method.
*
* TODO:
* Implement Delete
*/
operations: {
[id: string]: {
[pointer: string]: Operation
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -156,13 +156,6 @@ export class PageBuilderComponent extends FieldComponent<BlocksData> implements
blocks: TopBlock[];
availableBlocks: Block[];
previewed: number | undefined;
toProcess: {
[key: string]: {
save: (c: string, d: string, comp: any[]) => Observable<any>;
components: any[];
metadata?: any;
}
} = {};
isOpen = false;
originalOverflowY: string;
view: 'fullscreen' | 'desktop' | 'mobile' = 'desktop';
Expand Down Expand Up @@ -385,12 +378,7 @@ export class PageBuilderComponent extends FieldComponent<BlocksData> implements
}
}

/**
* TODO:
* Run save operations
*/
removeBlock() {
delete this.toProcess[(this.selected as Selected).id];
this.selected = null;
this.state = '';
this.blocks.splice(this.selectedIndex, 1);
Expand Down Expand Up @@ -495,18 +483,6 @@ export class PageBuilderComponent extends FieldComponent<BlocksData> implements
return;
}

if (this.blockFormComponent) {
this.toProcess[(this.selected as Selected).id] = {
save: this.blockFormComponent.formBuilderComponent
.save
.bind(
this.blockFormComponent.formBuilderComponent
),
// metadata: this.blockFormComponent.formBuilderComponent.metadata,
components: [...(this.blockFormComponent.formBuilderComponent as any).service.saveComponents]
};
}

this.removeFocus(this.selectedIndex);
this.selected = null;
// @ts-ignore
Expand Down Expand Up @@ -604,53 +580,17 @@ export class PageBuilderComponent extends FieldComponent<BlocksData> implements
return this.blocks.filter(it => it.type === block.id).length >= block.maxInstances;
}

save(moduleId: string, documentId: string) {
const items = Object.entries(this.toProcess);

if (items.length) {
return forkJoin(items.map(it => it[1].save(moduleId, documentId, it[1].components)))
.pipe(
tap((values) => {
this.cData.control.setValue(
this.blocks.map((block, index) => {

let value: any = block.value;

if (this.toProcess[block.id]) {
const itemIndex = items.findIndex(it => it[0] === block.id.toString());
const processedValue = values[itemIndex];
const {metadata} = items[itemIndex][1];

if (metadata?.array) {
value[metadata.array][metadata.index] = processedValue;
} else {
value = processedValue;
}
}

return {
value,
type: block.type,
...this.cData.saveCompiled && {
compiled: this.compRefs[index].location.nativeElement.innerHTML
}
}
})
);
})
);
} else {
this.cData.control.setValue(
this.blocks.map((block, index) => ({
value: block.value,
type: block.type,
...this.cData.saveCompiled && {
compiled: this.compRefs[index].location.nativeElement.innerHTML
}
}))
);
return of(true);
}
save() {
this.cData.control.setValue(
this.blocks.map((block, index) => ({
value: block.value,
type: block.type,
...this.cData.saveCompiled && {
compiled: this.compRefs[index].location.nativeElement.innerHTML
}
}))
);
return of(true);
}

private renderComponent(
Expand Down

0 comments on commit fc8ca71

Please sign in to comment.