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

Improve array related styling of renderer #1146

Merged
4 changes: 1 addition & 3 deletions packages/core/src/generators/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { ControlElement, JsonSchema, UISchemaElement } from '../';
import { generateJsonSchema } from './schema';
import { createControlElement, generateDefaultUISchema } from './uischema';

const Generate: {
export const Generate: {
jsonSchema(instance: Object, options?: any): JsonSchema;
uiSchema(jsonSchema: JsonSchema, layoutType?: string, prefix?: string): UISchemaElement;
controlElement(label: string, ref: string): ControlElement;
Expand All @@ -37,7 +37,5 @@ const Generate: {
controlElement: createControlElement
};

export { Generate };
export default Generate;
export { generateJsonSchema };
export { generateDefaultUISchema };
10 changes: 6 additions & 4 deletions packages/core/src/generators/uischema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@ const deriveType = (jsonSchema: JsonSchema): string => {
* Creates a IControlObject with the given label referencing the given ref
*/
export const createControlElement = (label: string, ref: string): ControlElement => ({
type: 'Control',
label: label,
scope: ref,
type: 'Control',
label: label === undefined ? false : label,
scope: ref,
});

const isLayout = (uischema: UISchemaElement): uischema is Layout =>
Expand Down Expand Up @@ -141,7 +141,9 @@ const generateUISchema =
const layout: Layout = createLayout(layoutType);
schemaElements.push(layout);

addLabel(layout, schemaName);
if (jsonSchema.properties && _.keys(jsonSchema.properties).length > 1) {
addLabel(layout, schemaName);
}

if (!_.isEmpty(jsonSchema.properties)) {
// traverse properties
Expand Down
6 changes: 4 additions & 2 deletions packages/core/src/util/field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,20 +83,22 @@ export interface FieldProps extends StatePropsOfField, DispatchPropsOfField {
* @param field the field to be registered
* @returns {any}
*/
export interface DispatchFieldStateProps extends OwnPropsOfField {
export interface DispatchFieldStateProps extends FieldProps {
fields?: JsonFormsFieldRendererRegistryEntry[];
}

export const mapStateToDispatchFieldProps =
(state: JsonFormsState, ownProps: OwnPropsOfField): DispatchFieldStateProps => {
const props: StatePropsOfField = mapStateToFieldProps(state, ownProps);
return {
...props,
...ownProps,
fields: state.jsonforms.fields || []
};
};

export interface DispatchFieldProps extends DispatchFieldStateProps {

showError: boolean;
}

/**
Expand Down
5 changes: 0 additions & 5 deletions packages/core/test/generators/uischema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,10 +264,6 @@ test(`nested object attributes`, t => {
label: 'Id',
scope: '#/properties/id'
};
const privateLabel: LabelElement = {
type: 'Label',
text: 'Private'
};
const nameControl: ControlElement = {
type: 'Control',
label: 'Name',
Expand All @@ -276,7 +272,6 @@ test(`nested object attributes`, t => {
const nestedLayout: VerticalLayout = {
type: 'VerticalLayout',
elements: [
privateLabel,
nameControl,
]
};
Expand Down
2 changes: 1 addition & 1 deletion packages/core/test/reducers/uischemas.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
} from '../../src/reducers/uischemas';
import { registerUISchema, RemoveUISchemaAction, unregisterUISchema } from '../../src/actions';
import { findUISchema, getSchema } from '../../src/reducers';
import Generate from '../../src/generators';
import { Generate } from '../../src/generators';
import { JsonFormsState } from '../../src';

test('init state empty', t => {
Expand Down
94 changes: 89 additions & 5 deletions packages/core/test/util/renderer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ import test from 'ava';
import * as _ from 'lodash';
import * as Redux from 'redux';
import {
clearAllIds,
createDefaultValue,
mapDispatchToControlProps,
mapStateToControlProps,
mapStateToJsonFormsRendererProps
clearAllIds,
createDefaultValue,
mapDispatchToArrayControlProps,
mapDispatchToControlProps,
mapStateToControlProps,
mapStateToJsonFormsRendererProps,
OwnPropsOfControl
} from '../../src/util';
import configureStore from 'redux-mock-store';
import { init, update, UPDATE_DATA, UpdateAction } from '../../src/actions';
Expand All @@ -39,10 +41,13 @@ import {
ControlElement,
coreReducer,
JsonFormsState,
JsonSchema,
RuleEffect,
UISchemaElement
} from '../../src';
import { jsonformsReducer } from '../../src/reducers';
import { ErrorObject } from 'ajv';
import { combineReducers, createStore, Store } from 'redux';

const middlewares: Redux.Middleware[] = [];
const mockStore = configureStore<JsonFormsState>(middlewares);
Expand Down Expand Up @@ -385,3 +390,82 @@ test(`mapStateToDispatchRendererProps should use UI schema if given via ownProps
);
t.deepEqual(props.uischema, uischema);
});

test('mapDispatchToArrayControlProps should adding items to array', t => {
const data = ['foo'];
const schema: JsonSchema = {
type: 'array',
items: {
type: 'string'
}
};
const uischema: ControlElement = {
type: 'Control',
scope: '#'
};
const initState = {
jsonforms: {
core: {
uischema,
schema,
data,
errors: [] as ErrorObject[]
}
}
};
const store: Store<JsonFormsState> = createStore(
combineReducers({ jsonforms: jsonformsReducer() }),
initState
);
store.dispatch(init(data, schema, uischema));
const ownProps: OwnPropsOfControl = {
schema,
uischema
};
const props = mapDispatchToArrayControlProps(
store.dispatch,
ownProps
);
props.addItem('')();
t.is(store.getState().jsonforms.core.data.length, 2);
});

test('mapDispatchToArrayControlProps should remove items from array', t => {
const data = ['foo', 'bar', 'quux'];
const schema: JsonSchema = {
type: 'array',
items: {
type: 'string'
}
};
const uischema: ControlElement = {
type: 'Control',
scope: '#'
};
const initState = {
jsonforms: {
core: {
uischema,
schema,
data,
errors: [] as ErrorObject[]
}
}
};
const store: Store<JsonFormsState> = createStore(
combineReducers({ jsonforms: jsonformsReducer() }),
initState
);
store.dispatch(init(data, schema, uischema));
const ownProps: OwnPropsOfControl = {
schema,
uischema
};
const props = mapDispatchToArrayControlProps(
store.dispatch,
ownProps
);
props.removeItems('', ['foo', 'bar'])();
t.is(store.getState().jsonforms.core.data.length, 1);
t.is(store.getState().jsonforms.core.data[0], 'quux');
});
8 changes: 4 additions & 4 deletions packages/core/test/util/runtime.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ test('evalVisibility show valid case based on schema condition', t => {
t.is(evalVisibility(uischema, data), true);
});

test.only('evalVisibility show valid case based on schema condition and enum', t => {
test('evalVisibility show valid case based on schema condition and enum', t => {
const condition: SchemaBasedCondition = {
scope: '#/properties/ruleValue',
schema: {
Expand Down Expand Up @@ -257,7 +257,7 @@ test('evalEnablement disable invalid case based on schema condition', t => {
value: 'foo',
ruleValue: 'bar'
};
t.is(evalEnablement(uischema, data), true);
t.is(evalEnablement(uischema, {...data, ruleValue: 'baz'}), true);
t.is(evalEnablement(uischema, {...data, ruleValue: 'foo'}), false);
t.is(evalEnablement(uischema, data), false);
t.is(evalEnablement(uischema, {...data, ruleValue: 'baz'}), false);
t.is(evalEnablement(uischema, {...data, ruleValue: 'foo'}), true);
});
46 changes: 22 additions & 24 deletions packages/examples/src/nestedArrays.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,18 @@ import { AnyAction, Dispatch } from 'redux';
const schema = {
'type': 'object',
'properties': {
'firstarray': {
'exampleArray': {
'type': 'array',
'items': {
'type': 'object',
'properties': {
'objectarrayofstrings': {
'type': 'object',
'properties': {
'choices': {
'type': 'array',
'items': {
'type': 'string'
}
}
'name': { 'type': 'string' },
'choices': {
'type': 'array',
'items': {
'type': 'string'
}
},
'name': { 'type': 'string' }
}
}
}
}
Expand All @@ -62,22 +57,25 @@ const uischema = {
'elements': [
{
'type': 'Control',
'label': '1',
'scope': '#/properties/firstarray'
'label': {
text: 'Example Array',
show: true
},
'scope': '#/properties/exampleArray'
}
]
};

const data = {
'firstarray': [
'exampleArray': [
{
'objectarrayofstrings': {
'choices': [
'CHOICE_STRING_1',
'CHOICE_STRING_2',
'CHOICE_STRING_3'
]
}
'choices': [
'This',
'is',
'an',
'example'
],
'name': 'Hi there'
}
]
};
Expand All @@ -93,7 +91,7 @@ registerExamples([
]);

const nestedArrayTester = (_jsonSchema: JsonSchema, schemaPath: string) => {
return schemaPath === '#/properties/firstarray' ? 2 : NOT_APPLICABLE;
return schemaPath === '#/properties/exampleArray' ? 2 : NOT_APPLICABLE;
};
const control1: ControlElement = {
type: 'Control',
Expand All @@ -102,7 +100,7 @@ const control1: ControlElement = {
// register inner layout
const control2: ControlElement = {
type: 'Control',
scope: '#/properties/objectarrayofstrings/properties/choices'
scope: '#/properties/choices'
};
export const nestedArrayLayout: VerticalLayout = {
type: 'VerticalLayout',
Expand Down
49 changes: 49 additions & 0 deletions packages/material/src/complex/DeleteDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import * as React from 'react';
import Button from '@material-ui/core/Button';
import {
Dialog,
DialogActions,
DialogContent,
DialogContentText,
DialogTitle,
} from '@material-ui/core';

export interface DeleteDialogProps {
open: boolean;
onClose(): void;
onConfirm(): void;
onCancel(): void;
}

export interface WithDeleteDialogSupport {
openDeleteDialog(path: string, data: any): void;
}

export const DeleteDialog = ({ open, onClose, onConfirm, onCancel }: DeleteDialogProps) => {
return (
<Dialog
open={open}
keepMounted
onClose={onClose}
aria-labelledby='alert-dialog-confirmdelete-title'
aria-describedby='alert-dialog-confirmdelete-description'
>
<DialogTitle id='alert-dialog-confirmdelete-title'>
{'Confirm Deletion'}
</DialogTitle>
<DialogContent>
<DialogContentText id='alert-dialog-confirmdelete-description'>
Are you sure you want to delete the selected entry?
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={onCancel} color='primary'>
No
</Button>
<Button onClick={onConfirm} color='primary'>
Yes
</Button>
</DialogActions>
</Dialog>
);
};
Loading