Skip to content
This repository was archived by the owner on Nov 19, 2025. It is now read-only.

Commit 73186af

Browse files
committed
Add inline button for add operation
1 parent abcd1aa commit 73186af

File tree

14 files changed

+185
-92
lines changed

14 files changed

+185
-92
lines changed

jsonforms-editor/src/JsonFormsEditor.tsx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,10 @@ import {
2929
defaultEditorRenderers,
3030
defaultPreviewTabs,
3131
EditorPanel,
32-
} from './editor';
33-
import { PreviewTab } from './editor/components/EditorPanel';
34-
import {
35-
defaultPalettePanelTabs,
36-
PalettePanel,
3732
PaletteTab,
38-
} from './palette-panel';
33+
} from './editor';
34+
import { PreviewTab } from './editor';
35+
import { defaultPalettePanelTabs, PalettePanel } from './palette-panel';
3936
import { defaultPropertyRenderers, PropertiesPanel } from './properties';
4037
import {
4138
PropertiesService,
@@ -177,7 +174,12 @@ const JsonFormsEditorUi: React.FC<JsonFormsEditorUiProps> = ({
177174
<Layout
178175
HeaderComponent={header}
179176
FooterComponent={footer}
180-
drawerContent={<PalettePanel propertyRenderers={propertyRenderers} />}
177+
drawerContent={
178+
<PalettePanel
179+
propertyRenderers={propertyRenderers}
180+
paletteTabs={paletteTabs}
181+
/>
182+
}
181183
>
182184
<ReflexContainer
183185
orientation='vertical'
@@ -191,7 +193,7 @@ const JsonFormsEditorUi: React.FC<JsonFormsEditorUiProps> = ({
191193
<ReflexSplitter propagate />
192194
<ReflexElement minSize={200} flex={1}>
193195
<div className={`${classes.pane} ${classes.rightPane}`}>
194-
<PropertiesPanel previewTabs={previewTabs} paletteTabs={paletteTabs} />
196+
<PropertiesPanel previewTabs={previewTabs} />
195197
</div>
196198
</ReflexElement>
197199
</ReflexContainer>

jsonforms-editor/src/core/components/Layout.tsx

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ const useStyles = makeStyles((theme) => ({
3333
container: {
3434
height: '100vh',
3535
display: 'flex',
36+
overflow: 'hidden',
3637
},
3738
footer: {
3839
zIndex: theme.zIndex.drawer + 1,
@@ -74,6 +75,9 @@ const useStyles = makeStyles((theme) => ({
7475
width: theme.spacing(9) + 1,
7576
},
7677
},
78+
drawerContainer: {
79+
overflow: 'auto',
80+
},
7781
}));
7882

7983
interface LayoutProps {
@@ -88,11 +92,11 @@ export const Layout: React.FC<LayoutProps> = ({
8892
drawerContent,
8993
children,
9094
}) => {
91-
const [open, setOpen] = React.useState(true);
95+
const [open, setOpen] = React.useState(false);
9296

93-
// const toggleDrawerClose = () => {
94-
// setOpen(!open);
95-
// };
97+
const toggleDrawerClose = () => {
98+
setOpen(!open);
99+
};
96100
const openDrawer = () => {
97101
setOpen(true);
98102
};
@@ -113,11 +117,13 @@ export const Layout: React.FC<LayoutProps> = ({
113117
>
114118
<DrawerContextInstance.Provider value={{ open, openDrawer }}>
115119
<Toolbar />
116-
{/* <IconButton onClick={toggleDrawerClose}>
117-
{open ? <ChevronLeftIcon /> : <ChevronRightIcon />}
118-
</IconButton>
119-
<Divider /> */}
120-
{drawerContent}
120+
<div className={classes.drawerContainer}>
121+
<IconButton onClick={toggleDrawerClose}>
122+
{open ? <ChevronLeftIcon /> : <ChevronRightIcon />}
123+
</IconButton>
124+
<Divider />
125+
{drawerContent}
126+
</div>
121127
<div className={classes.fakeFooter} />
122128
</DrawerContextInstance.Provider>
123129
</Drawer>

jsonforms-editor/src/core/renderers/DroppableLayout.tsx

Lines changed: 80 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,14 @@ import {
1818
withJsonFormsLayoutProps,
1919
} from '@jsonforms/react';
2020
import { Grid, makeStyles } from '@material-ui/core';
21+
import EditIcon from '@material-ui/icons/Edit';
22+
import SpeedDial from '@material-ui/lab/SpeedDial';
23+
import SpeedDialAction from '@material-ui/lab/SpeedDialAction';
24+
import SpeedDialIcon from '@material-ui/lab/SpeedDialIcon';
2125
import React from 'react';
2226
import { useDrop } from 'react-dnd';
2327

24-
import { useDispatch, useSchema } from '../context';
28+
import { useDispatch, usePaletteService, useSchema } from '../context';
2529
import {
2630
canDropIntoLayout,
2731
canMoveSchemaElementTo,
@@ -73,12 +77,12 @@ export const DroppableLayout: React.FC<DroppableLayoutProps> = ({
7377
spacing={direction === 'row' ? 2 : 0}
7478
wrap='nowrap'
7579
>
76-
<DropPoint index={0} layout={layout} key={`${path}-${0}-drop`} />
80+
<DropPoint index={0} layout={layout} key={`${layout.uuid}-${0}-drop`} />
7781
{layout.elements.map((child, index) => (
78-
<React.Fragment key={`${path}-${index}-fragment`}>
82+
<React.Fragment key={`${layout.uuid}-${index}-fragment`}>
7983
<Grid
8084
item
81-
key={`${path}-${index}`}
85+
key={`${layout.uuid}-${index}`}
8286
className={classes.jsonformsGridItem}
8387
xs
8488
>
@@ -95,14 +99,70 @@ export const DroppableLayout: React.FC<DroppableLayoutProps> = ({
9599
<DropPoint
96100
index={index + 1}
97101
layout={layout}
98-
key={`${path}-${index + 1}-drop`}
102+
key={`${layout.uuid}-${index + 1}-drop`}
99103
/>
100104
</React.Fragment>
101105
))}
102106
</Grid>
103107
);
104108
};
105109

110+
const useActionBarStyles = makeStyles((theme) => ({
111+
speedDial: {
112+
bottom: theme.spacing(2),
113+
right: theme.spacing(2),
114+
},
115+
}));
116+
interface InlineActionBarProps {
117+
layout: EditorLayout;
118+
index: number;
119+
}
120+
const InlineActionBar = ({ layout, index }: InlineActionBarProps) => {
121+
const classes = useActionBarStyles();
122+
const paletteService = usePaletteService();
123+
const dispatch = useDispatch();
124+
const [open, setOpen] = React.useState(false);
125+
const handleOpen = () => {
126+
setOpen(true);
127+
};
128+
129+
const handleClose = () => {
130+
setOpen(false);
131+
};
132+
return (
133+
<SpeedDial
134+
ariaLabel='SpeedDial openIcon example'
135+
className={classes.speedDial}
136+
icon={<SpeedDialIcon openIcon={<EditIcon />} />}
137+
onClose={handleClose}
138+
onOpen={handleOpen}
139+
open={open}
140+
direction={layout.type === 'HorizontalLayout' ? 'down' : 'right'}
141+
>
142+
{paletteService
143+
.getPaletteElements()
144+
.map(({ type, label, icon, uiSchemaElementProvider }) => (
145+
<SpeedDialAction
146+
key={type}
147+
color='primary'
148+
icon={icon as any}
149+
tooltipTitle={label}
150+
onClick={() => {
151+
dispatch(
152+
Actions.addUnscopedElementToLayout(
153+
uiSchemaElementProvider(),
154+
layout.uuid,
155+
index
156+
)
157+
);
158+
handleClose();
159+
}}
160+
/>
161+
))}
162+
</SpeedDial>
163+
);
164+
};
165+
106166
interface DropPointProps {
107167
layout: EditorLayout;
108168
index: number;
@@ -116,10 +176,16 @@ const useDropPointStyles = makeStyles((theme) => ({
116176
: 'none',
117177
backgroundSize: 'calc(10 * 1px) calc(10 * 1px)',
118178
backgroundClip: 'content-box',
119-
minWidth: '2em',
120-
minHeight: props.isOver ? '8em' : '2em',
121-
maxWidth: props.fillWidth || props.isOver ? 'inherit' : '2em',
179+
minWidth: '3em',
180+
minHeight: props.isOver ? '8em' : '3em',
181+
maxWidth: props.fillWidth ? 'inherit' : '3em',
122182
}),
183+
actions: {
184+
opacity: 0,
185+
'&:hover': {
186+
opacity: 1,
187+
},
188+
},
123189
}));
124190

125191
const DropPoint: React.FC<DropPointProps> = ({ layout, index }) => {
@@ -195,8 +261,13 @@ const DropPoint: React.FC<DropPointProps> = ({ layout, index }) => {
195261
ref={drop}
196262
className={classes.dropPointGridItem}
197263
data-cy={`${getDataPath(layout)}-drop-${index}`}
264+
alignItems='stretch'
198265
xs
199-
></Grid>
266+
>
267+
<Grid className={classes.actions} item xs>
268+
<InlineActionBar layout={layout} index={index} />
269+
</Grid>
270+
</Grid>
200271
);
201272
};
202273

jsonforms-editor/src/editor/components/EditorPanel.tsx

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,6 @@ import React from 'react';
1111

1212
import { Editor } from './Editor';
1313

14-
export interface PreviewTab {
15-
name: string;
16-
Component: React.ComponentType;
17-
}
18-
1914
interface EditorPanelProps {
2015
editorRenderers: JsonFormsRendererRegistryEntry[];
2116
}

jsonforms-editor/src/editor/components/EmptyEditor.tsx

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,29 @@
77
*/
88
import { Typography } from '@material-ui/core';
99
import { makeStyles } from '@material-ui/core/styles';
10+
import EditIcon from '@material-ui/icons/Edit';
11+
import SpeedDial from '@material-ui/lab/SpeedDial';
12+
import SpeedDialAction from '@material-ui/lab/SpeedDialAction';
13+
import SpeedDialIcon from '@material-ui/lab/SpeedDialIcon';
1014
import React from 'react';
1115
import { useDrop } from 'react-dnd';
1216

13-
import { useDispatch } from '../../core/context';
17+
import { useDispatch, usePaletteService } from '../../core/context';
1418
import { NEW_UI_SCHEMA_ELEMENT } from '../../core/dnd';
1519
import { Actions } from '../../core/model';
1620

17-
const useStyles = makeStyles({
21+
const useStyles = makeStyles((theme) => ({
1822
root: (props: any) => ({
1923
padding: 10,
2024
fontSize: props.isOver ? '1.1em' : '1em',
2125
border: props.isOver ? '1px solid #D3D3D3' : 'none',
2226
height: '100%',
2327
}),
24-
});
28+
speedDial: {
29+
bottom: theme.spacing(2),
30+
right: theme.spacing(2),
31+
},
32+
}));
2533

2634
export const EmptyEditor: React.FC = () => {
2735
const dispatch = useDispatch();
@@ -35,12 +43,45 @@ export const EmptyEditor: React.FC = () => {
3543
dispatch(Actions.setUiSchema(uiSchemaElement));
3644
},
3745
});
46+
const paletteService = usePaletteService();
47+
const [open, setOpen] = React.useState(false);
48+
const handleOpen = () => {
49+
setOpen(true);
50+
};
51+
52+
const handleClose = () => {
53+
setOpen(false);
54+
};
3855
const classes = useStyles({ isOver });
3956
return (
4057
<div ref={drop} className={classes.root}>
4158
<Typography data-cy={`nolayout-drop`}>
4259
Drag and drop an element from the Palette to begin.
4360
</Typography>
61+
<SpeedDial
62+
ariaLabel='SpeedDial openIcon example'
63+
className={classes.speedDial}
64+
icon={<SpeedDialIcon openIcon={<EditIcon />} />}
65+
onClose={handleClose}
66+
onOpen={handleOpen}
67+
open={open}
68+
direction={'right'}
69+
>
70+
{paletteService
71+
.getPaletteElements()
72+
.map(({ type, label, icon, uiSchemaElementProvider }) => (
73+
<SpeedDialAction
74+
key={type}
75+
color='primary'
76+
icon={icon as any}
77+
tooltipTitle={label}
78+
onClick={() => {
79+
dispatch(Actions.setUiSchema(uiSchemaElementProvider()));
80+
handleClose();
81+
}}
82+
/>
83+
))}
84+
</SpeedDial>
4485
</div>
4586
);
4687
};

jsonforms-editor/src/editor/components/preview/ReactMaterialPreview.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import { useExportSchema, useExportUiSchema } from '../../../core/util/hooks';
1919
import { previewOptions } from './options';
2020

2121
export const ReactMaterialPreview: React.FC = () => {
22-
console.log('IM RENDERER');
2322
const schema = useExportSchema();
2423
const uischema = useExportUiSchema();
2524
const editorSchema = useSchema();

jsonforms-editor/src/editor/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ import {
1515
DroppableHorizontalLayoutRegistration,
1616
DroppableVerticalLayoutRegistration,
1717
} from '../core/renderers/DroppableLayout';
18-
import { PreviewTab } from './components/EditorPanel';
1918
import { ReactMaterialPreview } from './components/preview';
19+
import { PreviewTab } from './interface';
2020

2121
export * from './components/EditorPanel';
2222
export { EditorElement } from './components/EditorElement';
2323

24-
export type { PreviewTab } from './components/EditorPanel';
24+
export * from './interface';
2525
export const defaultPreviewTabs: PreviewTab[] = [
2626
{ name: 'Preview', Component: ReactMaterialPreview },
2727
];
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/**
2+
* ---------------------------------------------------------------------
3+
* Copyright (c) 2020 EclipseSource Munich
4+
* Licensed under MIT
5+
* https://github.com/eclipsesource/jsonforms-editor/blob/master/LICENSE
6+
* ---------------------------------------------------------------------
7+
*/
8+
export interface PreviewTab {
9+
name: string;
10+
Component: React.ComponentType;
11+
}
12+
export interface PaletteTab {
13+
name: string;
14+
Component: React.ReactElement;
15+
}

jsonforms-editor/src/env.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@
77
*/
88
export const env = () => {
99
const { REACT_APP_DEBUG: DEBUG = 'false', NODE_ENV } = process.env;
10-
return { NODE_ENV, DEBUG };
10+
return { NODE_ENV, DEBUG, IS_DEBUG: DEBUG === 'true' };
1111
};

jsonforms-editor/src/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,4 @@ export * from './core/util';
2020
export * from './editor/components/preview';
2121
export * from './editor';
2222
export * from './text-editor';
23-
export * from './palette-panel';
2423
export default JsonFormsEditor;

0 commit comments

Comments
 (0)