Skip to content

Commit a01cf43

Browse files
LukasBolllucas-koehler
authored andcommitted
change path to JSON pointer
1 parent ffbb9e2 commit a01cf43

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+453
-381
lines changed

packages/angular-material/src/library/layouts/array-layout.renderer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ export class ArrayLayoutRenderer
233233
}
234234
return {
235235
schema: this.scopedSchema,
236-
path: Paths.compose(this.propsPath, `${index}`),
236+
path: Paths.compose(this.propsPath, `/${index}`),
237237
uischema,
238238
};
239239
}

packages/angular-material/src/library/other/master-detail/master.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ export const removeSchemaKeywords = (path: string) => {
9191
<button
9292
mat-icon-button
9393
class="button item-button hide"
94-
(click)="onDeleteClick(i)"
94+
(click)="onDeleteClick($event, i)"
9595
[ngClass]="{ show: highlightedIdx == i }"
9696
*ngIf="isEnabled()"
9797
>
@@ -224,7 +224,7 @@ export class MasterListComponent
224224
? d.toString()
225225
: get(d, labelRefInstancePath ?? getFirstPrimitiveProp(schema)),
226226
data: d,
227-
path: `${path}.${index}`,
227+
path: `${path}/${index}`,
228228
schema,
229229
uischema: detailUISchema,
230230
};
@@ -278,7 +278,8 @@ export class MasterListComponent
278278
)();
279279
}
280280

281-
onDeleteClick(item: number) {
281+
onDeleteClick(e: any, item: number) {
282+
e.stopPropagation();
282283
this.removeItems(this.propsPath, [item])();
283284
}
284285

packages/angular-material/src/library/other/table.renderer.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ export const controlWithoutLabel = (scope: string): ControlElement => ({
273273
@Pipe({ name: 'getProps' })
274274
export class GetProps implements PipeTransform {
275275
transform(index: number, props: OwnPropsOfRenderer) {
276-
const rowPath = Paths.compose(props.path, `${index}`);
276+
const rowPath = Paths.compose(props.path, `/${index}`);
277277
return {
278278
schema: props.schema,
279279
uischema: props.uischema,

packages/angular-material/test/master-detail.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ describe('Master detail', () => {
223223
// delete 1st item
224224
spyOn(component, 'removeItems').and.callFake(() => () => {
225225
getJsonFormsService(component).updateCore(
226-
Actions.update('orders', () => moreData.orders.slice(1))
226+
Actions.update('/orders', () => moreData.orders.slice(1))
227227
);
228228
fixture.detectChanges();
229229
});
@@ -267,7 +267,7 @@ describe('Master detail', () => {
267267
const copy = moreData.orders.slice();
268268
copy.splice(1, 1);
269269
getJsonFormsService(component).updateCore(
270-
Actions.update('orders', () => copy)
270+
Actions.update('/orders', () => copy)
271271
);
272272
fixture.detectChanges();
273273
});
@@ -382,7 +382,7 @@ describe('Master detail', () => {
382382
customer: { name: 'ACME' },
383383
title: 'Carrots',
384384
},
385-
path: 'orders.0',
385+
path: '/orders/0',
386386
schema: schema.definitions.order,
387387
uischema: {
388388
type: 'VerticalLayout',

packages/core/src/i18n/i18nUtil.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
formatErrorMessage,
1414
getControlPath,
1515
isInternationalized,
16+
toLodashPath,
1617
} from '../util';
1718

1819
export const getI18nKeyPrefixBySchema = (
@@ -31,7 +32,7 @@ export const getI18nKeyPrefixBySchema = (
3132
*/
3233
export const transformPathToI18nPrefix = (path: string): string => {
3334
return (
34-
path
35+
toLodashPath(path)
3536
?.split('.')
3637
.filter((segment) => !/^\d+$/.test(segment))
3738
.join('.') || 'root'

packages/core/src/reducers/core.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,14 @@ import {
4545
import { JsonFormsCore, Reducer, ValidationMode } from '../store';
4646
import Ajv, { ErrorObject } from 'ajv';
4747
import { isFunction } from 'lodash';
48-
import { createAjv, validate } from '../util';
48+
import {
49+
composePaths,
50+
createAjv,
51+
isOneOfEnumSchema,
52+
Reducer,
53+
toLodashSegments,
54+
validate,
55+
} from '../util';
4956

5057
export const initState: JsonFormsCore = {
5158
data: {},
@@ -237,18 +244,19 @@ export const coreReducer: Reducer<JsonFormsCore, CoreActions> = (
237244
errors,
238245
};
239246
} else {
240-
const oldData: any = get(state.data, action.path);
247+
const lodashDataPathSegments = toLodashSegments(action.path);
248+
const oldData: any = get(state.data, lodashDataPathSegments);
241249
const newData = action.updater(cloneDeep(oldData));
242250
let newState: any;
243251
if (newData !== undefined) {
244252
newState = setFp(
245-
action.path,
253+
lodashDataPathSegments,
246254
newData,
247255
state.data === undefined ? {} : state.data
248256
);
249257
} else {
250258
newState = unsetFp(
251-
action.path,
259+
lodashDataPathSegments,
252260
state.data === undefined ? {} : state.data
253261
);
254262
}

packages/core/src/reducers/i18n.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,13 @@
2323
THE SOFTWARE.
2424
*/
2525

26-
import { defaultErrorTranslator, defaultTranslator } from '../i18n';
26+
import {
27+
defaultErrorTranslator,
28+
defaultTranslator,
29+
ErrorTranslator,
30+
JsonFormsI18nState,
31+
Translator,
32+
} from '../i18n';
2733
import {
2834
I18nActions,
2935
SET_LOCALE,
@@ -32,6 +38,7 @@ import {
3238
} from '../actions';
3339
import { Reducer } from '../store/type';
3440
import { JsonFormsI18nState } from '../store';
41+
import { UISchemaElement } from '../models';
3542

3643
export const defaultJsonFormsI18nState: Required<JsonFormsI18nState> = {
3744
locale: 'en',
@@ -50,7 +57,6 @@ export const i18nReducer: Reducer<JsonFormsI18nState, I18nActions> = (
5057
action.translator ?? defaultJsonFormsI18nState.translate;
5158
const translateError =
5259
action.errorTranslator ?? defaultJsonFormsI18nState.translateError;
53-
5460
if (
5561
locale !== state.locale ||
5662
translate !== state.translate ||
@@ -80,3 +86,19 @@ export const i18nReducer: Reducer<JsonFormsI18nState, I18nActions> = (
8086
return state;
8187
}
8288
};
89+
90+
export const wrapTranslateFunction = (translator: Translator): Translator => {
91+
return (id: string, defaultMessage?: string | undefined, values?: any) => {
92+
return translator(toLodashPath(id), defaultMessage, values);
93+
};
94+
};
95+
96+
export const wrapErrorTranslateFunction = (
97+
translator: ErrorTranslator
98+
): ErrorTranslator => {
99+
return (
100+
error: ErrorObject,
101+
translate: Translator,
102+
uischema?: UISchemaElement
103+
) => translator(error, wrapTranslateFunction(translate), uischema);
104+
};

packages/core/src/store/jsonFormsCore.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export const errorAt = (instancePath: string, schema: JsonSchema) =>
3434
getErrorsAt(instancePath, schema, (path) => path === instancePath);
3535
export const subErrorsAt = (instancePath: string, schema: JsonSchema) =>
3636
getErrorsAt(instancePath, schema, (path) =>
37-
path.startsWith(instancePath + '.')
37+
path.startsWith(instancePath + '/')
3838
);
3939

4040
export const getErrorAt =

packages/core/src/util/errors.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
*/
2525

2626
import { ErrorObject } from 'ajv';
27-
import { decode } from './path';
27+
import { composePaths } from './path';
2828
import { JsonSchema } from '../models';
2929
import { isOneOfEnumSchema } from './schema';
3030
import filter from 'lodash/filter';
@@ -47,19 +47,11 @@ export const getControlPath = (error: ErrorObject) => {
4747
// With AJV v8 the property was renamed to 'instancePath'
4848
let controlPath = (error as any).dataPath || error.instancePath || '';
4949

50-
// change '/' chars to '.'
51-
controlPath = controlPath.replace(/\//g, '.');
52-
5350
const invalidProperty = getInvalidProperty(error);
5451
if (invalidProperty !== undefined && !controlPath.endsWith(invalidProperty)) {
55-
controlPath = `${controlPath}.${invalidProperty}`;
52+
controlPath = composePaths(controlPath, invalidProperty);
5653
}
5754

58-
// remove '.' chars at the beginning of paths
59-
controlPath = controlPath.replace(/^./, '');
60-
61-
// decode JSON Pointer escape sequences
62-
controlPath = decode(controlPath);
6355
return controlPath;
6456
};
6557

packages/core/src/util/path.ts

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,26 @@
2626
import isEmpty from 'lodash/isEmpty';
2727
import range from 'lodash/range';
2828

29-
export const compose = (path1: string, path2: string) => {
30-
let p1 = path1;
31-
if (!isEmpty(path1) && !isEmpty(path2) && !path2.startsWith('[')) {
32-
p1 = path1 + '.';
29+
/**
30+
* Composes two JSON pointer. Pointer1 is appended to pointer2.
31+
* JSON pointer is seperated and start with '/' e.g: /foo/0
32+
*
33+
* @param {string} pointer1 JSON pointer
34+
* @param {string} pointer2 JSON pointer
35+
* @returns {string} resulting JSON pointer
36+
*/
37+
export const compose = (pointer1: string, pointer2: string) => {
38+
let p2 = pointer2;
39+
if (!isEmpty(pointer2) && !pointer2.startsWith('/')) {
40+
p2 = '/' + pointer2;
3341
}
3442

35-
if (isEmpty(p1)) {
36-
return path2;
37-
} else if (isEmpty(path2)) {
38-
return p1;
43+
if (isEmpty(pointer1)) {
44+
return p2;
45+
} else if (isEmpty(pointer2)) {
46+
return pointer1;
3947
} else {
40-
return `${p1}${path2}`;
48+
return `${pointer1}${p2}`;
4149
}
4250
};
4351

@@ -75,13 +83,25 @@ export const toDataPathSegments = (schemaPath: string): string[] => {
7583
* Data paths can be used in field change event handlers like handleChange.
7684
*
7785
* @example
78-
* toDataPath('#/properties/foo/properties/bar') === 'foo.bar')
86+
* toDataPath('#/properties/foo/properties/bar') === '/foo/bar')
7987
*
8088
* @param {string} schemaPath the schema path to be converted
8189
* @returns {string} the data path
8290
*/
8391
export const toDataPath = (schemaPath: string): string => {
84-
return toDataPathSegments(schemaPath).join('.');
92+
return '/' + toDataPathSegments(schemaPath).join('/');
93+
};
94+
95+
export const toLodashSegments = (jsonPointer: string): string[] => {
96+
let path = jsonPointer;
97+
if (jsonPointer && jsonPointer.startsWith('/')) {
98+
path = jsonPointer.substring(1);
99+
}
100+
return path ? path.split('/').map(decode) : [];
101+
};
102+
103+
export const toLodashPath = (jsonPointer: string) => {
104+
return toLodashSegments(jsonPointer).join('.');
85105
};
86106

87107
/**

0 commit comments

Comments
 (0)