Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mixed support #2409

Open
wants to merge 42 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
f8c2caf
initial mixed renderer support
kchobantonov Dec 29, 2024
c078710
organize imports
kchobantonov Dec 29, 2024
ece92ac
handle correctly the clear where if the property that is cleared in n…
kchobantonov Dec 29, 2024
bd28667
update controls to properly send clear value
kchobantonov Dec 29, 2024
a62efb4
update control to properly send clear value and add support for UI op…
kchobantonov Dec 29, 2024
4bc6b73
optimize the performance of convertDayjsToMaskaFormat function
kchobantonov Dec 29, 2024
4716a43
fix key property where the value is not based on data primary key but…
kchobantonov Dec 29, 2024
807546f
organize imports
kchobantonov Dec 29, 2024
25300db
add translations
kchobantonov Dec 29, 2024
81c81db
make sure that we use new date so that the proxyModel is correctly no…
kchobantonov Dec 29, 2024
3a4f2b9
no need to check props?.schema?.properties
kchobantonov Dec 29, 2024
6b5dca8
proper implementation for the optional translator
kchobantonov Dec 29, 2024
2f96aef
change the way how we determine if default value should be returned
kchobantonov Dec 29, 2024
cc44091
use control.arraySchema instead of Resolve
kchobantonov Dec 29, 2024
d460e6c
use control.arraySchema instead of Resolve, make the header to not ta…
kchobantonov Dec 29, 2024
1f24b21
clean up class
kchobantonov Dec 30, 2024
d716953
use less space
kchobantonov Dec 30, 2024
498cbf1
do not render the div if nothing to renders as children
kchobantonov Dec 30, 2024
72e17d0
use more descriptive name
kchobantonov Dec 30, 2024
89bfb0b
if we are in dynamic context then always prefer the VerticalLayout ov…
kchobantonov Dec 30, 2024
ef24610
if the schema is an object that is selected because of mixed type the…
kchobantonov Dec 30, 2024
492e5fd
when the mixed renderer provides the exact schema to use then there i…
kchobantonov Dec 30, 2024
434a1f9
add core schema meta-schema as example
kchobantonov Dec 30, 2024
532fa9f
Merge branch 'master' into mixed-support
kchobantonov Dec 30, 2024
22760af
resolve schema like 'items': true
kchobantonov Dec 30, 2024
8a1b523
add jsonschema example
kchobantonov Dec 30, 2024
1d51ee8
symplify how we determine that the object renderer should be used whe…
kchobantonov Dec 30, 2024
770531a
items in draft7 can accept boolean
kchobantonov Dec 30, 2024
6ead876
add generic json editor example
kchobantonov Dec 30, 2024
b7460ab
fix items.type
kchobantonov Dec 30, 2024
27c11fe
add some space as title so opening and closing the expansion panel is…
kchobantonov Dec 30, 2024
318950e
for now revert back the change to include the boolean since more code…
kchobantonov Dec 30, 2024
3a6f240
fix the check because of the items type revert
kchobantonov Dec 30, 2024
e3c8b3c
use type array instead of true because of the items type revert
kchobantonov Dec 30, 2024
40dc34f
remove unused imports
kchobantonov Jan 8, 2025
a7fa97b
Merge branch 'master' into mixed-support
kchobantonov Jan 18, 2025
9111316
remove ?
kchobantonov Feb 13, 2025
0a6047f
remove prop param
kchobantonov Feb 13, 2025
1c146bd
Merge branch 'master' into mixed-support
kchobantonov Feb 13, 2025
fd7efb4
remove prop
kchobantonov Feb 13, 2025
0e1577b
Merge branch 'master' into mixed-support
kchobantonov Feb 25, 2025
6b863d9
Merge branch 'master' into mixed-support
sdirix Mar 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 22 additions & 7 deletions packages/core/src/mappers/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ export const doCreateDefaultValue = (
rootSchema: JsonSchema
) => {
const resolvedSchema =
typeof schema.$ref === 'string'
typeof schema?.$ref === 'string'
? Resolve.schema(rootSchema, schema.$ref, rootSchema)
: schema;
if (resolvedSchema.default !== undefined) {
Expand Down Expand Up @@ -592,11 +592,12 @@ export const mapStateToControlProps = (
const required =
controlElement.scope !== undefined &&
isRequired(ownProps.schema, controlElement.scope, rootSchema);
const resolvedSchema = Resolve.schema(
ownProps.schema || rootSchema,
controlElement.scope,
rootSchema
);
const resolvedSchema =
Resolve.schema(
ownProps.schema || rootSchema,
controlElement.scope,
rootSchema
) ?? ownProps.schema; // if resolve fails then rely that the ownProps.schema if exist
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel this is plastering over bugs. If a schema can't be resolved then this means the handed over schema, uischema combination was wrong. It's better to fail early than falling back to the unresolved schema.

const errors = getErrorAt(path, resolvedSchema)(state);

const description =
Expand Down Expand Up @@ -871,7 +872,21 @@ export const mapStateToArrayControlProps = (
const { path, schema, uischema, label, ...props } =
mapStateToControlWithDetailProps(state, ownProps);

const resolvedSchema = Resolve.schema(schema, 'items', props.rootSchema);
let resolvedSchema = Resolve.schema(schema, 'items', props.rootSchema);
if ((resolvedSchema as any) === true) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like the cast to any here. If we really expect Resolve.schema to being able to return booleans, then its typing should indicate that.

// help the testers to determine the mixed control
resolvedSchema = {
type: [
'array',
'boolean',
'integer',
'null',
'number',
'object',
'string',
],
};
}
Comment on lines +876 to +889
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this. Up until now, the schema returned from the mappers was always a sub-schema of the overall schema. Not only does this not return an actual sub-schema, it also produces a new resolvedSchema whenever it is executed, which will break memo barriers.

I'm all for being able to handle boolean (sub-)schemas but the change should be less intrusive. I would like to keep the original prerequisite for now: Always return a sub-schema of the original schema. Once we break that, for example to support schema overrides, this becomes much more complicated because of the object identities.

const childErrors = getSubErrorsAt(path, resolvedSchema)(state);

return {
Expand Down
10 changes: 9 additions & 1 deletion packages/core/src/util/resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,20 @@ const resolveSchemaWithSegments = (
pathSegments: string[],
rootSchema: JsonSchema
): JsonSchema => {
if (
typeof schema === 'boolean' &&
(!pathSegments || pathSegments.length === 0)
) {
// add the case where the schema can be true value for example: items: true or additionalProperties: false
return schema;
}
Comment on lines +126 to +132
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the use case of this? Who hands over segments to resolve if the schema is just a boolean already anyway?

Copy link
Contributor Author

@kchobantonov kchobantonov Feb 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that is to resolve the case where the value of the last path segment is equals to true. For example items: true and you want to bind that items then you need to resolve the jsonschema which can be boolean but in the code we ignore that this can be ever the case.

Also the next check for isEmpty if we pass true/false values which are valid JSON schema will return an undefined when resolved instead of boolean

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The case is already handled via

  if (!pathSegments || pathSegments.length === 0) {
    return schema;
  }

If having a boolean schema breaks the checks before that, then we should fix those checks instead of hard coding the exception at the top.

I guess the typing does not properly reflect that the schema could be a boolean. So we should adjust the typing and the checks to handle the typing.


if (isEmpty(schema)) {
return undefined;
}

// use typeof because schema can by of any type - check singleSegmentResolveSchema below
if (typeof schema.$ref === 'string') {
if (typeof schema?.$ref === 'string') {
schema = resolveSchema(rootSchema, schema.$ref, rootSchema);
}

Expand Down
50 changes: 50 additions & 0 deletions packages/examples/src/examples/json-editor.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
The MIT License

Copyright (c) 2017-2019 EclipseSource Munich
https://github.com/eclipsesource/jsonforms

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
import { registerExamples } from '../register';

export const schema = {
type: ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'],
additionalProperties: true,
items: {
type: ['array', 'boolean', 'integer', 'null', 'number', 'object', 'string'],
},
};

export const uischema = {
type: 'Control',
scope: '#/',
};

const data = undefined as any;

registerExamples([
{
name: 'json-editor',
label: 'JSON Editor',
data,
schema,
uischema,
},
]);
Loading