diff --git a/jsonforms-editor/src/core/api/paletteService.tsx b/jsonforms-editor/src/core/api/paletteService.tsx
index 6076110..56ddb8b 100644
--- a/jsonforms-editor/src/core/api/paletteService.tsx
+++ b/jsonforms-editor/src/core/api/paletteService.tsx
@@ -8,9 +8,19 @@
import React from 'react';
-import { GroupIcon, HorizontalIcon, LabelIcon, VerticalIcon } from '../icons';
+import {
+ ControlIcon,
+ GroupIcon,
+ HorizontalIcon,
+ LabelIcon,
+ VerticalIcon,
+} from '../icons';
import { EditorUISchemaElement } from '../model/uischema';
-import { createLabel, createLayout } from '../util/generators/uiSchema';
+import {
+ createEmptyControl,
+ createLabel,
+ createLayout,
+} from '../util/generators/uiSchema';
export interface PaletteService {
getPaletteElements(): PaletteElement[];
@@ -48,6 +58,12 @@ const paletteElements: PaletteElement[] = [
icon: ,
uiSchemaElementProvider: () => createLabel(),
},
+ {
+ type: 'Control',
+ label: 'Control',
+ icon: ,
+ uiSchemaElementProvider: () => createEmptyControl(),
+ },
];
export class DefaultPaletteService implements PaletteService {
diff --git a/jsonforms-editor/src/core/components/EditableControl.tsx b/jsonforms-editor/src/core/components/EditableControl.tsx
new file mode 100644
index 0000000..b3856ce
--- /dev/null
+++ b/jsonforms-editor/src/core/components/EditableControl.tsx
@@ -0,0 +1,95 @@
+/**
+ * ---------------------------------------------------------------------
+ * Copyright (c) 2020 EclipseSource Munich
+ * Licensed under MIT
+ * https://github.com/eclipsesource/jsonforms-editor/blob/master/LICENSE
+ * ---------------------------------------------------------------------
+ */
+
+import { Grid, TextField } from '@material-ui/core';
+import MenuItem from '@material-ui/core/MenuItem';
+import React from 'react';
+
+import { useDispatch, useSchema } from '../context';
+import {
+ Actions,
+ getChildren,
+ getScope,
+ isArrayElement,
+ isObjectElement,
+ SchemaElement,
+} from '../model';
+import { EditorControl } from '../model/uischema';
+
+interface EditableControlProps {
+ uischema: EditorControl;
+}
+export const EditableControl: React.FC = ({
+ uischema,
+}) => {
+ const dispatch = useDispatch();
+ const baseSchema = useSchema() as SchemaElement;
+ const handleLabelChange = (event: React.ChangeEvent) => {
+ dispatch(
+ Actions.updateUISchemaElement(uischema.uuid, {
+ label: event.target.value,
+ })
+ );
+ };
+ const handleScopeChange = (event: React.ChangeEvent) => {
+ dispatch(
+ Actions.changeControlScope(
+ uischema.uuid,
+ (event.target.value as any).scope,
+ (event.target.value as any).uuid
+ )
+ );
+ };
+ const scopes = getChildren(baseSchema)
+ .flatMap((child) => {
+ // if the child is the only item of an array, use its children instead
+ if (
+ (isObjectElement(child) &&
+ isArrayElement(child.parent) &&
+ child.parent.items === child) ||
+ isObjectElement(child)
+ ) {
+ return getChildren(child);
+ }
+ return [child];
+ })
+ .map((e) => ({ scope: `#${getScope(e)}`, uuid: e.uuid }));
+ const scopeValues = scopes.filter((s) => s.scope.endsWith(uischema.scope));
+ const scopeValue =
+ scopeValues && scopeValues.length === 1 ? scopeValues[0] : '';
+ return (
+
+
+
+
+
+
+ {scopes.map((scope) => (
+
+ ))}
+
+
+
+ );
+};
diff --git a/jsonforms-editor/src/core/components/Layout.tsx b/jsonforms-editor/src/core/components/Layout.tsx
index 6b1e929..32e4d7a 100644
--- a/jsonforms-editor/src/core/components/Layout.tsx
+++ b/jsonforms-editor/src/core/components/Layout.tsx
@@ -101,7 +101,7 @@ export const Layout: React.FC = ({
paletteTabs,
children,
}) => {
- const [open, setOpen] = React.useState(true);
+ const [open, setOpen] = React.useState(false);
const [selectedTabName, setSelectedTabName] = React.useState(
paletteTabs ? paletteTabs[0].name : ''
);
diff --git a/jsonforms-editor/src/core/components/index.ts b/jsonforms-editor/src/core/components/index.ts
index d454b75..8472164 100644
--- a/jsonforms-editor/src/core/components/index.ts
+++ b/jsonforms-editor/src/core/components/index.ts
@@ -14,3 +14,4 @@ export * from './ErrorDialog';
export * from './OkCancelDialog';
export * from './ExportDialog';
export * from './ShowMoreLess';
+export * from './EditableControl';
diff --git a/jsonforms-editor/src/core/model/actions.ts b/jsonforms-editor/src/core/model/actions.ts
index c72c2f4..6dfa957 100644
--- a/jsonforms-editor/src/core/model/actions.ts
+++ b/jsonforms-editor/src/core/model/actions.ts
@@ -16,7 +16,8 @@ export type CombinedAction =
| AddScopedElementToLayout
| MoveUiSchemaElement
| RemoveUiSchemaElement
- | AddDetail;
+ | AddDetail
+ | ChangeControlScope;
export type EditorAction = UiSchemaAction | CombinedAction;
@@ -38,6 +39,8 @@ export const UPDATE_UISCHEMA_ELEMENT: 'jsonforms-editor/UPDATE_UISCHEMA_ELEMENT'
'jsonforms-editor/UPDATE_UISCHEMA_ELEMENT';
export const ADD_DETAIL: 'jsonforms-editor/ADD_DETAIL' =
'jsonforms-editor/ADD_DETAIL';
+export const CHANGE_CONTROL_SCOPE: 'jsonforms-editor/CHANGE_CONTROL_SCOPE' =
+ 'jsonforms-editor/CHANGE_CONTROL_SCOPE';
export interface SetSchemaAction {
type: 'jsonforms-editor/SET_SCHEMA';
@@ -89,6 +92,13 @@ export interface UpdateUiSchemaElement {
changedProperties: { [key: string]: any };
}
+export interface ChangeControlScope {
+ type: 'jsonforms-editor/CHANGE_CONTROL_SCOPE';
+ elementUUID: string;
+ scope: string;
+ schemaUUID: string;
+}
+
export interface AddDetail {
type: 'jsonforms-editor/ADD_DETAIL';
uiSchemaElementId: string;
@@ -167,6 +177,12 @@ const addDetail = (
detail,
});
+const changeControlScope = (
+ elementUUID: string,
+ scope: string,
+ schemaUUID: string
+) => ({ type: CHANGE_CONTROL_SCOPE, elementUUID, scope, schemaUUID });
+
export const Actions = {
setSchema,
setUiSchema,
@@ -177,4 +193,5 @@ export const Actions = {
removeUiSchemaElement,
updateUISchemaElement,
addDetail,
+ changeControlScope,
};
diff --git a/jsonforms-editor/src/core/model/reducer.ts b/jsonforms-editor/src/core/model/reducer.ts
index ce4fb56..1c90b17 100644
--- a/jsonforms-editor/src/core/model/reducer.ts
+++ b/jsonforms-editor/src/core/model/reducer.ts
@@ -20,6 +20,7 @@ import {
ADD_DETAIL,
ADD_SCOPED_ELEMENT_TO_LAYOUT,
ADD_UNSCOPED_ELEMENT_TO_LAYOUT,
+ CHANGE_CONTROL_SCOPE,
CombinedAction,
EditorAction,
MOVE_UISCHEMA_ELEMENT,
@@ -118,6 +119,24 @@ export const combinedReducer = (state: EditorState, action: CombinedAction) => {
buildSchemaTree(action.schema),
buildEditorUiSchemaTree(action.uiSchema)
);
+ case CHANGE_CONTROL_SCOPE:
+ return withCloneTrees(
+ state.uiSchema,
+ action.elementUUID,
+ state.schema,
+ action.schemaUUID,
+ state,
+ (newUiSchema, newSchema) => {
+ if (!newSchema || !newUiSchema || !isEditorControl(newUiSchema))
+ return state;
+ linkElements(newUiSchema, newSchema);
+ newUiSchema.scope = action.scope;
+ return {
+ schema: getRoot(newSchema),
+ uiSchema: getRoot(newUiSchema as EditorUISchemaElement),
+ };
+ }
+ );
case ADD_SCOPED_ELEMENT_TO_LAYOUT:
return withCloneTrees(
state.uiSchema,
@@ -361,6 +380,7 @@ export const editorReducer = (state: EditorState, action: EditorAction) => {
schema: state.schema,
uiSchema: uiSchemaReducer(state.uiSchema, action),
};
+ case CHANGE_CONTROL_SCOPE:
case SET_SCHEMA:
case SET_UISCHEMA:
case SET_SCHEMAS:
diff --git a/jsonforms-editor/src/core/renderers/DroppableArrayControl.tsx b/jsonforms-editor/src/core/renderers/DroppableArrayControl.tsx
index 1c8c8ad..e7daa46 100644
--- a/jsonforms-editor/src/core/renderers/DroppableArrayControl.tsx
+++ b/jsonforms-editor/src/core/renderers/DroppableArrayControl.tsx
@@ -15,10 +15,11 @@ import {
JsonFormsDispatch,
withJsonFormsArrayControlProps,
} from '@jsonforms/react';
-import { makeStyles, Typography } from '@material-ui/core';
+import { Grid, makeStyles, Typography } from '@material-ui/core';
import React, { useMemo } from 'react';
import { useDrop } from 'react-dnd';
+import { EditableControl } from '../components';
import { useDispatch, useSchema } from '../context';
import {
canDropIntoScope,
@@ -96,22 +97,28 @@ const DroppableArrayControl: React.FC = ({
return renderers && [...renderers, DroppableElementRegistration];
}, [renderers]);
- if (!uischema.options?.detail) {
- return (
-
- Default array layout. Drag and drop an item here to customize array
- layout.
-
- );
- }
return (
-
+
+
+
+
+
+ {!uischema.options?.detail ? (
+
+ Default array layout. Drag and drop an item here to customize array
+ layout.
+
+ ) : (
+
+ )}
+
+
);
};
diff --git a/jsonforms-editor/src/core/renderers/DroppableControl.tsx b/jsonforms-editor/src/core/renderers/DroppableControl.tsx
new file mode 100644
index 0000000..644adc3
--- /dev/null
+++ b/jsonforms-editor/src/core/renderers/DroppableControl.tsx
@@ -0,0 +1,28 @@
+/**
+ * ---------------------------------------------------------------------
+ * Copyright (c) 2020 EclipseSource Munich
+ * Licensed under MIT
+ * https://github.com/eclipsesource/jsonforms-editor/blob/master/LICENSE
+ * ---------------------------------------------------------------------
+ */
+
+import { ControlProps, isControl, rankWith } from '@jsonforms/core';
+import { withJsonFormsControlProps } from '@jsonforms/react';
+import React from 'react';
+
+import { EditableControl } from '../components';
+import { EditorControl } from '../model/uischema';
+
+interface DroppableControlProps extends ControlProps {
+ uischema: EditorControl;
+}
+const DroppableControl: React.FC = ({ uischema }) => {
+ return ;
+};
+
+export const DroppableControlRegistration = {
+ tester: rankWith(40, isControl), // less than DroppableElement
+ renderer: withJsonFormsControlProps(
+ DroppableControl as React.FC
+ ),
+};
diff --git a/jsonforms-editor/src/core/renderers/DroppableGroupLayout.tsx b/jsonforms-editor/src/core/renderers/DroppableGroupLayout.tsx
index 1530c81..d39d626 100644
--- a/jsonforms-editor/src/core/renderers/DroppableGroupLayout.tsx
+++ b/jsonforms-editor/src/core/renderers/DroppableGroupLayout.tsx
@@ -13,10 +13,13 @@ import {
CardHeader,
Grid,
makeStyles,
+ TextField,
Typography,
} from '@material-ui/core';
import React from 'react';
+import { useDispatch } from '../context';
+import { Actions } from '../model';
import { EditorLayout } from '../model/uischema';
import { DroppableLayout } from './DroppableLayout';
@@ -39,6 +42,14 @@ const Group: React.FC = (props) => {
const { uischema } = props;
const groupLayout = uischema as GroupLayout & EditorLayout;
const classes = useStyles();
+ const dispatch = useDispatch();
+ const handleLabelChange = (event: React.ChangeEvent) => {
+ dispatch(
+ Actions.updateUISchemaElement(groupLayout.uuid, {
+ label: event.target.value,
+ })
+ );
+ };
return (
= (props) => {
)}
>
+
diff --git a/jsonforms-editor/src/core/renderers/DroppableLabel.tsx b/jsonforms-editor/src/core/renderers/DroppableLabel.tsx
new file mode 100644
index 0000000..8cbd679
--- /dev/null
+++ b/jsonforms-editor/src/core/renderers/DroppableLabel.tsx
@@ -0,0 +1,42 @@
+/**
+ * ---------------------------------------------------------------------
+ * Copyright (c) 2020 EclipseSource Munich
+ * Licensed under MIT
+ * https://github.com/eclipsesource/jsonforms-editor/blob/master/LICENSE
+ * ---------------------------------------------------------------------
+ */
+import { LabelElement, LayoutProps, rankWith, uiTypeIs } from '@jsonforms/core';
+import { withJsonFormsLayoutProps } from '@jsonforms/react';
+import { TextField } from '@material-ui/core';
+import React from 'react';
+
+import { useDispatch } from '../context';
+import { Actions } from '../model';
+import { EditorUISchemaElement } from '../model/uischema';
+
+const DroppableLabel: React.FC = (props) => {
+ const { uischema } = props;
+ const labelElement = uischema as LabelElement & EditorUISchemaElement;
+ const dispatch = useDispatch();
+ const handleLabelChange = (event: React.ChangeEvent) => {
+ dispatch(
+ Actions.updateUISchemaElement(labelElement.uuid, {
+ text: event.target.value,
+ })
+ );
+ };
+ return (
+
+ );
+};
+
+export const DroppableLabelRegistration = {
+ tester: rankWith(45, uiTypeIs('Label')),
+ renderer: withJsonFormsLayoutProps(DroppableLabel),
+};
diff --git a/jsonforms-editor/src/core/util/generators/uiSchema.ts b/jsonforms-editor/src/core/util/generators/uiSchema.ts
index b0f55f9..6191520 100644
--- a/jsonforms-editor/src/core/util/generators/uiSchema.ts
+++ b/jsonforms-editor/src/core/util/generators/uiSchema.ts
@@ -44,3 +44,12 @@ export const createLabel = (
uuid: uuid(),
} as LabelElement & EditorUISchemaElement;
};
+
+export const createEmptyControl = (): ControlElement &
+ EditorUISchemaElement => {
+ return {
+ type: 'Control',
+ scope: '',
+ uuid: uuid(),
+ } as ControlElement & EditorUISchemaElement;
+};
diff --git a/jsonforms-editor/src/editor/index.ts b/jsonforms-editor/src/editor/index.ts
index 9fead8e..6d94016 100644
--- a/jsonforms-editor/src/editor/index.ts
+++ b/jsonforms-editor/src/editor/index.ts
@@ -9,8 +9,10 @@ import { JsonFormsRendererRegistryEntry } from '@jsonforms/core';
import { materialRenderers } from '@jsonforms/material-renderers';
import { DroppableArrayControlRegistration } from '../core/renderers/DroppableArrayControl';
+import { DroppableControlRegistration } from '../core/renderers/DroppableControl';
import { DroppableElementRegistration } from '../core/renderers/DroppableElement';
import { DroppableGroupLayoutRegistration } from '../core/renderers/DroppableGroupLayout';
+import { DroppableLabelRegistration } from '../core/renderers/DroppableLabel';
import {
DroppableHorizontalLayoutRegistration,
DroppableVerticalLayoutRegistration,
@@ -33,4 +35,6 @@ export const defaultEditorRenderers: JsonFormsRendererRegistryEntry[] = [
DroppableElementRegistration,
DroppableGroupLayoutRegistration,
DroppableArrayControlRegistration,
+ DroppableControlRegistration,
+ DroppableLabelRegistration,
];