Skip to content

Commit

Permalink
refactor: text_area_input.jsx to functional component
Browse files Browse the repository at this point in the history
  • Loading branch information
prathamVaidya committed Apr 21, 2024
1 parent 09f6a53 commit 3eeda65
Showing 1 changed file with 120 additions and 118 deletions.
238 changes: 120 additions & 118 deletions app/assets/javascripts/components/common/text_area_input.jsx
Original file line number Diff line number Diff line change
@@ -1,147 +1,149 @@
import { Editor } from '@tinymce/tinymce-react';
import React from 'react';
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import createReactClass from 'create-react-class';
import InputHOC from '../high_order/input_hoc.jsx';
import InputHOC from '../high_order/input_hoc';
import markdown_it from '../../utils/markdown_it';

const md = markdown_it({ openLinksExternally: true });

const md = require('../../utils/markdown_it.js').default({ openLinksExternally: true });
// This is a flexible text input box. It switches between edit and read mode,
// and can either provide a wysiwyg editor or a plain text editor.
const TextAreaInput = createReactClass({
displayName: 'TextAreaInput',

propTypes: {
onChange: PropTypes.func,
onFocus: PropTypes.func,
onBlur: PropTypes.func,
value: PropTypes.string,
value_key: PropTypes.string,
editable: PropTypes.bool, // switch between read and edit mode
id: PropTypes.string,
focus: PropTypes.bool,
placeholder: PropTypes.string,
autoExpand: PropTypes.bool, // start with one line and expand as needed — plain text only
rows: PropTypes.string, // set the number of rows — plain text only
wysiwyg: PropTypes.bool, // use rich text editor instead of plain text
markdown: PropTypes.bool, // render value as Markdown when in read mode
className: PropTypes.string,
clearOnSubmit: PropTypes.bool
},

getInitialState() {
return { tinymceLoaded: false };
},
const TextAreaInput = ({
onChange,
onFocus,
onBlur,
value,
editable,
id,
focus,
placeholder,
autoExpand,
rows,
wysiwyg,
markdown,
className,
clearOnSubmit,
invalid
}) => {
const [tinymceLoaded, setTinymceLoaded] = useState(false);
const [activeEditor, setActiveEditor] = useState(null);

componentDidMount() {
if (this.props.wysiwyg) {
this.loadTinyMCE();
useEffect(() => {
if (wysiwyg) {
loadTinyMCE();
}
},
}, [wysiwyg]);

loadTinyMCE() {
const user_signed_in = Features.user_signed_in;
const loadTinyMCE = () => {
const user_signed_in = Features.user_signed_in; // Ensure Features is accessible
if (user_signed_in) {
import('../../tinymce').then(() => {
this.setState({
tinymceLoaded: true
});
setTinymceLoaded(true);
});
}
},
};

handleRichTextEditorChange(e) {
this.props.onChange(
{ target: { value: e } },
e
);
},
const handleRichTextEditorChange = (e) => {
onChange({ target: { value: e } }, e);
};

handleSubmit() {
if (this.props.clearOnSubmit) {
this.state.activeEditor.setContent('');
const handleSubmit = () => {
if (clearOnSubmit) {
activeEditor.setContent('');
}
},
};

render() {
let inputElement;
let rawHtml;
let inputElement;
let rawHtml;

// ////////////
// Edit mode //
// ////////////
if (this.props.editable) {
let inputClass;
if (this.props.invalid) {
inputClass = 'invalid';
}
// ////////////
// Edit mode //
// ////////////
if (editable) {
let inputClass = '';
if (invalid) {
inputClass = 'invalid';
}

// Use TinyMCE if props.wysiwyg, otherwise, use a basic textarea.
if (this.props.wysiwyg && this.state.tinymceLoaded) {
inputElement = (
<Editor
value={this.props.value}
onEditorChange={this.handleRichTextEditorChange}
onSubmit={this.handleSubmit}
className={inputClass}
init={{
setup: (editor) => { this.setState({ activeEditor: editor }); },
inline: true,
convert_urls: false,
plugins: 'lists link code',
toolbar: [
'undo redo | styleselect | bold italic',
'alignleft alignright',
'bullist numlist outdent indent',
'link'
],
}}
/>
);
} else {
inputElement = (
<textarea
className={inputClass}
id={this.props.id}
rows={this.props.rows || '8'}
value={this.props.value || ''}
onChange={this.props.onChange}
autoFocus={this.props.focus}
onFocus={this.props.onFocus}
onBlur={this.props.onBlur}
maxLength="30000"
placeholder={this.props.placeholder}
/>
);
}
// Use TinyMCE if props.wysiwyg, otherwise, use a basic textarea.
if (wysiwyg && tinymceLoaded) {
inputElement = (
<Editor
value={value}
onEditorChange={handleRichTextEditorChange}
onSubmit={handleSubmit}
className={inputClass}
init={{
setup: editor => setActiveEditor(editor),
inline: true,
convert_urls: false,
plugins: 'lists link code',
toolbar: [
'undo redo | styleselect | bold italic',
'alignleft alignright',
'bullist numlist outdent indent',
'link'
],
}}
/>
);
} else {
inputElement = (
<textarea
className={inputClass}
id={id}
rows={rows || '8'}
value={value || ''}
onChange={onChange}
autoFocus={focus}
onFocus={onFocus}
onBlur={onBlur}
maxLength="30000"
placeholder={placeholder}
/>
);
}

if (this.props.autoExpand) {
return (
<div className="expandingArea active">
<pre><span>{this.props.value}</span><br /></pre>
{inputElement}
</div>
);
}
if (autoExpand) {
return (
<div>
<div className="expandingArea active">
<pre><span>{value}</span><br /></pre>
{inputElement}
</div>
);
}
return <div>{inputElement}</div>;
}

// ////////////
// Read mode //
// ////////////
if (this.props.markdown) {
rawHtml = md.render(this.props.value || '');
} else {
rawHtml = this.props.value;
}
return (
<div className={this.props.className} dangerouslySetInnerHTML={{ __html: rawHtml }} />
);
// ////////////
// Read mode //
// ////////////
if (markdown) {
rawHtml = md.render(value || '');
} else {
rawHtml = value;
}
}
);

return <div className={className} dangerouslySetInnerHTML={{ __html: rawHtml }} />;
};

TextAreaInput.propTypes = {
onChange: PropTypes.func,
onFocus: PropTypes.func,
onBlur: PropTypes.func,
value: PropTypes.string,
value_key: PropTypes.string,
editable: PropTypes.bool, // switch between read and edit mode
id: PropTypes.string,
focus: PropTypes.bool,
placeholder: PropTypes.string,
autoExpand: PropTypes.bool, // start with one line and expand as needed — plain text only
rows: PropTypes.string, // set the number of rows — plain text only
wysiwyg: PropTypes.bool, // use rich text editor instead of plain text
markdown: PropTypes.bool, // render value as Markdown when in read mode
className: PropTypes.string,
clearOnSubmit: PropTypes.bool
};

export default InputHOC(TextAreaInput);

0 comments on commit 3eeda65

Please sign in to comment.