Skip to content

Commit

Permalink
Merge pull request #452 from harunurhan/fix-conflict-ui
Browse files Browse the repository at this point in the history
fix add/remove patches for object properties
  • Loading branch information
harunurhan authored Jan 24, 2018
2 parents 4958e26 + 006b4b6 commit 4b9c38a
Show file tree
Hide file tree
Showing 10 changed files with 80 additions and 33 deletions.
12 changes: 12 additions & 0 deletions example/assets/mock-data/patches.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@
"path": "/references/0/reference/misc/0",
"value": "A Misc Thing"
},
{
"op": "add",
"path": "/references/0/reference/publication_info",
"value": {
"journal_title": "Patch Title"
}
},
{
"op": "add",
"path": "/references/1/reference/misc/-",
Expand All @@ -26,6 +33,11 @@
"value": "New Collaboration"
}
},
{
"op": "add",
"path": "/references/1/reference/texkey",
"value": "valuueee123"
},
{
"op": "add",
"path": "/references/-",
Expand Down
36 changes: 29 additions & 7 deletions src/abstract-field/abstract-field.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { OnInit, OnDestroy, ChangeDetectorRef, OnChanges, SimpleChanges } from '

import { AbstractSubscriberComponent } from '../abstract-subscriber';
import { AppGlobalsService, PathUtilService, JsonStoreService, ProblemsService } from '../shared/services';
import { ValidationProblem, PathCache, JSONSchema, JsonPatch } from '../shared/interfaces';
import { ValidationProblem, PathCache, JSONSchema, JsonPatch, JsonPatchesByOp } from '../shared/interfaces';

/**
* This is the base class for fields
Expand All @@ -43,10 +43,13 @@ export abstract class AbstractFieldComponent extends AbstractSubscriberComponent
pathCache: PathCache = {};
externalErrors: Array<ValidationProblem> = [];
schema: JSONSchema;
jsonPatches: Array<JsonPatch> = [];
// used by some components to display remove patch in a different way.

// patches grouped by op because they different UI representation
replaceJsonPatches: Array<JsonPatch> = [];
addJsonPatches: Array<JsonPatch> = [];
removeJsonPatch: JsonPatch;


constructor(public appGlobalsService: AppGlobalsService,
public problemsService: ProblemsService,
public pathUtilService: PathUtilService,
Expand All @@ -62,17 +65,36 @@ export abstract class AbstractFieldComponent extends AbstractSubscriberComponent
this.externalErrors = externalCategorizedProblemMap.errors[this.pathString] || [];
this.changeDetectorRef.markForCheck();
});

this.jsonStoreService.patchesByPath$
.map(patchesByPath => patchesByPath[this.pathString])
.map(patches => this.groupJsonPatchesByOp(patches))
.takeUntil(this.isDestroyed)
.subscribe(patches => {
this.jsonPatches = patches || [];
this.removeJsonPatch = this.jsonPatches
.find(patch => patch.op === 'remove');
.subscribe(patchesByOp => {
this.removeJsonPatch = patchesByOp.remove[0];
this.addJsonPatches = patchesByOp.add;
this.replaceJsonPatches = patchesByOp.replace;
this.changeDetectorRef.markForCheck();
});
}

private groupJsonPatchesByOp(patches: Array<JsonPatch>): JsonPatchesByOp {
const group: JsonPatchesByOp = {
add: [],
remove: [],
replace: []
};

if (patches) {
patches.forEach((patch) => {
const opPatches = group[patch.op];
opPatches.push(patch);
});
}

return group;
}

ngOnChanges(changes: SimpleChanges) {
if (changes['path']) {
this.pathString = this.pathUtilService.toPathString(this.path);
Expand Down
6 changes: 0 additions & 6 deletions src/abstract-list-field/abstract-list-field.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,4 @@ export abstract class AbstractListFieldComponent extends AbstractFieldComponent
getPathStringForChild(index: number): string {
return `${this.pathString}${this.pathUtilService.separator}${index}`;
}

get addJsonPatches(): Array<JsonPatch> {
return this.jsonPatches
.filter(patch => patch.op === 'add');
}

}
10 changes: 10 additions & 0 deletions src/object-field/object-field.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@
<any-type-field [value]="value.get(key) | selfOrEmpty:schema.properties[key]" [schema]=schema.properties[key] [path]="getPathForChild(key)"></any-type-field>
</td>
</tr>
<!-- ADD PATCHES FOR CHILDREN -->
<tr *ngFor="let patch of addJsonPatches">
<td class="label-holder">
<title-dropdown [title]="patch.path | lastPathElement | underscoreToSpace" [isDisabled]="true"></title-dropdown>
</td>
<td>
<add-patch-view [patch]="patch"></add-patch-view>
</td>
</tr>
<!-- REMOVE PATCH FOR ITSELF -->
<tr *ngIf="removeJsonPatch">
<patch-actions [patch]="removeJsonPatch"></patch-actions>
</tr>
Expand Down
21 changes: 13 additions & 8 deletions src/primitive-field/primitive-field.component.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<div [id]="pathString">
<div [id]="pathString" [ngClass]="redLeftBorderClass">
<table class="primitive-field-container" [ngSwitch]="schema.componentType">
<tr [ngClass]="errorClass">
<ng-template #errorsTooltipTemplate>
Expand All @@ -11,7 +11,7 @@
</li>
</ul>
</ng-template>
<td *ngIf="!jsonPatches[0]; else patchTemplate" class="value-container" [class.disabled]="disabled" [tooltip]="errorsTooltipTemplate"
<td *ngIf="!replaceJsonPatches[0]; else patchTemplate" class="value-container" [class.disabled]="disabled" [tooltip]="errorsTooltipTemplate"
[isDisabled]="!hasErrors()" placement="{{tooltipPosition}}" container="body">
<div *ngSwitchCase="'string'">
<string-input [pathString]="pathString" [value]="value" (valueChange)="onValueChange($event)" [disabled]="disabled" [tabIndex]="tabIndex"
Expand All @@ -20,7 +20,8 @@
</div>
<div *ngSwitchCase="'enum'">
<searchable-dropdown [pathString]="pathString" [value]="value" [placeholder]="schema.title" [items]="schema.enum" [shortcutMap]="schema.enumShorcutMap"
(onSelect)="onSearchableDropdownSelect($event)" [displayValueMap]="schema.enumDisplayValueMap" [tabIndex]="tabIndex" (onBlur)="onBlur()"></searchable-dropdown>
(onSelect)="onSearchableDropdownSelect($event)" [displayValueMap]="schema.enumDisplayValueMap" [tabIndex]="tabIndex"
(onBlur)="onBlur()"></searchable-dropdown>
</div>
<div *ngSwitchCase="'autocomplete'">
<autocomplete-input [pathString]="pathString" [value]="value" [path]="path" [autocompletionConfig]="schema.autocompletionConfig"
Expand All @@ -47,17 +48,21 @@
</a>
</td>
</tr>
<tr *ngIf="removeJsonPatch">
<patch-actions [patch]="removeJsonPatch"></patch-actions>
</tr>
</table>
</div>

<ng-template #patchTemplate>
<button class="btn btn-default btn-merge orange-left-border" type="button" [popover]="mergePopover" [popoverContext]="{currentValue: value, patchValue: jsonPatches[0].value}"
<button class="btn btn-default btn-merge orange-left-border" type="button" [popover]="mergePopover" [popoverContext]="{currentValue: value, patchValue: replaceJsonPatches[0].value}"
popoverTitle="Merge" container="body">
{{value}} <i class="fa fa-bolt"></i>
{{value}}
<i class="fa fa-bolt"></i>
</button>
</ng-template>

<ng-template let-currentValue="currentValue" let-patchValue="patchValue" #mergePopover >
<text-diff [currentText]="currentValue.toString()" [newText]="patchValue.toString()"></text-diff>
<patch-actions [patch]="jsonPatches[0]" [addActionEnabled]="isPathToAnIndex"></patch-actions>
<ng-template let-currentValue="currentValue" let-patchValue="patchValue" #mergePopover>
<text-diff [currentText]="currentValue.toString()" [newText]="patchValue ? patchValue.toString() : ''"></text-diff>
<patch-actions [patch]="replaceJsonPatches[0]" [addActionEnabled]="isPathToAnIndex"></patch-actions>
</ng-template>
2 changes: 1 addition & 1 deletion src/primitive-field/primitive-field.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ export class PrimitiveFieldComponent extends AbstractFieldComponent implements O
}

get errorClass(): string {
return !this.jsonPatches[0] && this.hasErrors() ? 'error' : '';
return !this.replaceJsonPatches[0] && this.hasErrors() ? 'error' : '';
}

get isPathToAnIndex(): boolean {
Expand Down
1 change: 1 addition & 0 deletions src/shared/interfaces/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export { KatexData } from './katex-data';
export { JsonPatch } from './json-patch';
export { CustomFormatValidation } from './custom-format-validation';
export { JsonPatchesByPath } from './json-patches-by-path';
export { JsonPatchesByOp } from './json-patches-by-op';
export { ViewTemplateConfig } from './view-template-config';
export { ShortcutActionFunction } from './shortcut-action-function';
export { CustomValidationMessages } from './custom-validation-messages';
Expand Down
7 changes: 7 additions & 0 deletions src/shared/interfaces/json-patches-by-op.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { JsonPatch } from './json-patch';

export interface JsonPatchesByOp {
add: Array<JsonPatch>;
remove: Array<JsonPatch>;
replace: Array<JsonPatch>;
}
4 changes: 2 additions & 2 deletions src/shared/pipes/last-path-element.pipe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export class LastPathElementPipe implements PipeTransform {
constructor(private pathUtilService: PathUtilService) { }

transform(path: string): string {
const elements = path.split(this.pathUtilService.separator);
return elements[elements.length - 1];
return path
.substring(path.lastIndexOf('/') + 1);
}
}
14 changes: 5 additions & 9 deletions src/shared/services/json-store.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,19 +225,15 @@ export class JsonStoreService {

private getComponentPathForPatch(patch: JsonPatch): string {
if (patch.op === 'add') {
return this.convertElementPathToParentArrayPath(patch.path);
// add patches handled by parent component
return this.getParentPath(patch.path);
}
return patch.path;
}

private convertElementPathToParentArrayPath(path: string): string {
private getParentPath(path: string): string {
const pathArray = this.pathUtilService.toPathArray(path);
const lastPathElement = pathArray[pathArray.length - 1];
if (lastPathElement === '-' || !isNaN(Number(lastPathElement))) {
pathArray.pop();
return this.pathUtilService.toPathString(pathArray);
} else {
return path;
}
const parentPathArray = pathArray.slice(0, -1);
return this.pathUtilService.toPathString(parentPathArray);
}
}

0 comments on commit 4b9c38a

Please sign in to comment.