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

feat(MarkdownEditor): Support MarkdownEditor in FormRenderer #110

Merged
merged 12 commits into from
Mar 2, 2021
94 changes: 94 additions & 0 deletions src/components/FormRenderer/components/MarkdownEditor/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/** *******************************************************************************************************************
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License").
You may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. *
******************************************************************************************************************** */
import React, { FunctionComponent, useState } from 'react';
import { useFieldApi } from '@data-driven-forms/react-form-renderer';
import { v4 as uuidv4 } from 'uuid';
import FormField from '../../../FormField';
import MarkdownViewer from '../../../MarkdownViewer';
import Textarea from '../../../Textarea';
import Grid from '../../../../layouts/Grid';
import { Box } from '../../../../layouts';

const MarkdownEditorMapping: FunctionComponent = (props: any) => {
const {
label,
description,
helperText,
isRequired,
isDisabled,
isReadOnly,
placeholder,
validateOnMount,
input,
rows,
showError,
secondaryControl,
onChange,
meta: { error, submitFailed },
} = useFieldApi(props);

const INITIAL_ROWS = 10;

const controlId = input.name || uuidv4();
const errorText = ((validateOnMount || submitFailed || showError) && error) || '';

const updateState = (e: any) => {
onChange && onChange(e);
input.onChange(e);
};

return (
<FormField
controlId={controlId}
label={label}
description={description}
hintText={helperText}
errorText={errorText}
stretch={true}
secondaryControl={secondaryControl}
>
<Grid container alignItems="stretch" spacing={3}>
<Grid item sm={6} xs={12}>
<Textarea
{...input}
rows={rows || INITIAL_ROWS}
placeholder={placeholder}
controlId={controlId}
disabled={isDisabled}
required={isRequired}
readonly={isReadOnly}
invalid={!!errorText}
onChange={updateState}
/>
</Grid>
<Grid item sm={6} xs={12}>
<Box
bgcolor="grey.100"
height="100%"
p={1}
style={{ wordWrap: 'break-word' }}
overflow={'hidden'}
width={'100%'}
>
<MarkdownViewer>{input.value}</MarkdownViewer>
</Box>
</Grid>
</Grid>
</FormField>
);
};

export default MarkdownEditorMapping;
38 changes: 38 additions & 0 deletions src/components/FormRenderer/index.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import Box from '../../layouts/Box';
import Text from '../Text';
import Input from '../Input';
import FileUpload from '../FileUpload';
import Container from '../../layouts/Container';

export default {
component: FormRenderer,
Expand Down Expand Up @@ -1114,3 +1115,40 @@ export const FileUploader = () => {

return <FormRenderer schema={schema} onSubmit={action('Submit')} onCancel={action('Cancel')} />;
};

export const SimpleMarkdownEditor = () => {
const schema = {
submitLabel: 'Save',
cancelLabel: 'Back',
fields: [
{
component: componentTypes.MARKDOWN_EDITOR,
name: 'markdownOne',
label: 'This is a markdown editor',
helperText: 'Helper text provides users some guidance.',
initialValue: '# I am a Markdown editor.\n\rHave a play.',
onChange: action('Markdown content change'),
validate: [
{
type: validatorTypes.REQUIRED,
},
],
},
{
component: componentTypes.MARKDOWN_EDITOR,
name: 'markdownTwo',
label: 'This is a read only markdown editor',
isReadOnly: true,
initialValue: '# I should be read only\n\rAnd you should not be able to edit me',
},
],
header: 'Markdown Editor',
description: 'This component allows a user to enter markdown and renders it in real-time.',
};

return (
<Container>
<FormRenderer schema={schema} onSubmit={action('Submit')} onCancel={action('Cancel')} />
</Container>
);
};
23 changes: 23 additions & 0 deletions src/components/FormRenderer/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -907,4 +907,27 @@ describe('FormRenderer', () => {
});
});
});

it('should render a markdown editor', () => {
const schema = {
submitLabel: 'Save',
cancelLabel: 'Back',
fields: [
{
component: componentTypes.MARKDOWN_EDITOR,
name: 'markdownOne',
label: 'This is a markdown editor',
helperText: 'Helper text provides users some guidance.',
initialValue: '# I am a Markdown editor',
},
],
header: 'Markdown Editor',
description: 'This component allows a user to enter markdown and renders it in real-time.',
};

const { getByText } = render(<FormRenderer schema={schema} onSubmit={handleSubmit} onCancel={handleCancel} />);

expect(getByText('Markdown Editor')).toBeVisible();
expect(getByText('I am a Markdown editor')).toBeInTheDocument();
});
});
2 changes: 2 additions & 0 deletions src/components/FormRenderer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import TextField from './components/TextField';
import TimePicker from './components/TimePicker';
import TreeView from './components/TreeView';
import Wizard from './components/Wizard';
import MarkdownEditor from './components/MarkdownEditor';
import { componentTypes } from './types';

const componentMapper = {
Expand All @@ -51,6 +52,7 @@ const componentMapper = {
[componentTypes.TABLE]: Table,
[componentTypes.REVIEW]: Review,
[componentTypes.CUSTOM]: Custom,
[componentTypes.MARKDOWN_EDITOR]: MarkdownEditor,
};

export interface FormRendererProps {
Expand Down
1 change: 1 addition & 0 deletions src/components/FormRenderer/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,6 @@ export const componentTypes = {
EXPANDABLE_SECTION: 'EXPANDABLE_SECTION',
TABLE: 'TABLE',
REVIEW: 'REVIEW',
MARKDOWN_EDITOR: 'MARKDOWN_EDITOR',
CUSTOM: 'CUSTOM',
};
3 changes: 2 additions & 1 deletion src/components/MarkdownViewer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ export interface MarkdownViewerProps extends ReactMarkdownPropsBase {

const renderers = {
code: ({ language, value }: RenderProps) => {
return <SyntaxHighlighter style={tomorrow} language={language} children={value} />;
if (language && value) return <SyntaxHighlighter style={tomorrow} language={language} children={value} />;
else return <>{value}</>;
},
heading: (props: any) => {
const variant = `h${props.level}` as 'h1' | 'h2' | 'h3' | 'h4' | 'h5';
Expand Down