Skip to content

Commit 92aa46c

Browse files
LukasBolllucas-koehler
authored andcommitted
change path to JSON pointer
1 parent 8c4b2f0 commit 92aa46c

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
@@ -248,7 +248,7 @@ export class ArrayLayoutRenderer
248248
}
249249
return {
250250
schema: this.scopedSchema,
251-
path: Paths.compose(this.propsPath, `${index}`),
251+
path: Paths.compose(this.propsPath, `/${index}`),
252252
uischema,
253253
};
254254
}

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ export const removeSchemaKeywords = (path: string) => {
9494
<button
9595
mat-icon-button
9696
class="button item-button hide"
97-
(click)="onDeleteClick(i)"
97+
(click)="onDeleteClick($event, i)"
9898
[ngClass]="{ show: highlightedIdx == i }"
9999
*ngIf="isEnabled()"
100100
>
@@ -229,7 +229,7 @@ export class MasterListComponent
229229
? d.toString()
230230
: get(d, labelRefInstancePath ?? getFirstPrimitiveProp(schema)),
231231
data: d,
232-
path: `${path}.${index}`,
232+
path: `${path}/${index}`,
233233
schema,
234234
uischema: detailUISchema,
235235
};
@@ -283,7 +283,8 @@ export class MasterListComponent
283283
)();
284284
}
285285

286-
onDeleteClick(item: number) {
286+
onDeleteClick(e: any, item: number) {
287+
e.stopPropagation();
287288
this.removeItems(this.propsPath, [item])();
288289
}
289290

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ export const controlWithoutLabel = (scope: string): ControlElement => ({
275275
@Pipe({ name: 'getProps' })
276276
export class GetProps implements PipeTransform {
277277
transform(index: number, props: OwnPropsOfRenderer) {
278-
const rowPath = Paths.compose(props.path, `${index}`);
278+
const rowPath = Paths.compose(props.path, `/${index}`);
279279
return {
280280
schema: props.schema,
281281
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)