diff --git a/frontend/MainContainer.tsx b/frontend/MainContainer.tsx index cb5ea28..fd38a87 100644 --- a/frontend/MainContainer.tsx +++ b/frontend/MainContainer.tsx @@ -7,15 +7,17 @@ import { generateTextFailed, generateText, selectText, + submitEditText, + deleteEditText, foldForm } from './actions'; import TextGenerationControl from "./components/TextGenerationControl"; import TextGenerationResults from "./components/TextGenerationResults"; import TextDetailedAnalysis from "./components/TextDetailedAnalysis"; -import AnalyzedText from "./models/AnalyzedText"; +import TextRecord from "./models/TextRecord"; type ContainerProps = { - analysisResults: AnalyzedText[], + analysisResults: TextRecord[], error: any, loading: any, isFolded: boolean, @@ -25,7 +27,9 @@ type ContainerProps = { generateTextFailed: any, generateText: any selectText: Function, - foldForm: Function + submitEditText: Function, + deleteEditText: Function, + foldForm: Function, } const Container: React.FunctionComponent = ({ @@ -39,6 +43,8 @@ const Container: React.FunctionComponent = ({ generateTextFailed, generateText, selectText, + submitEditText, + deleteEditText, foldForm }) => { const getDetailedAnalysisComponent = () => { @@ -48,7 +54,10 @@ const Container: React.FunctionComponent = ({ const selectedText = selectedTextIds.map(id => analysisResults.find(item => id == item.id)) return ( + selectedText={selectedText} + submitEditText={submitEditText} + deleteEditText={deleteEditText} + /> ); } } @@ -95,6 +104,8 @@ function mapDispatchToProps (dispatch) { generateTextFailed: generateTextFailed, generateText: generateText, selectText: selectText, + submitEditText: submitEditText, + deleteEditText: deleteEditText, foldForm: foldForm, }, dispatch); } diff --git a/frontend/actions.ts b/frontend/actions.ts index efee7d8..a7f1cf9 100644 --- a/frontend/actions.ts +++ b/frontend/actions.ts @@ -7,6 +7,13 @@ function requestGenerateText() { } } +function requestEditText(id) { + return { + type: "REQUEST_EDIT_TEXT", + id: id + } +} + function setGeneratedTextResults(generateTextResults) { return { type: "SET_GENERATED_TEXT_RESULTS", @@ -43,6 +50,40 @@ function selectText(id: number) { } } +function setEditTextResults(id: number, text: string, analysis: any) { + return { + type: "EDIT_TEXT_SUCCEEDED", + id: id, + text: text, + analysis: analysis + } + +} + +function editTextFailed(id: number, error) { + return { + type: "EDIT_TEXT_FAILED", + id: id, + error: error + } +} + +function submitEditText(id: number, text: string) { + return function(dispatch) { + dispatch(requestEditText(id)); + makePostCall("api/v1/analyze_text", {text: text}) + .then(response => dispatch(setEditTextResults(id, text, response.data.text_analysis_result))) + .catch(error => dispatch(editTextFailed(id, error))); + } +} + +function deleteEditText(id: number) { + return { + type: "DELETE_EDIT_TEXT", + id: id + } +} + export { requestGenerateText, @@ -50,5 +91,7 @@ export { generateTextFailed, generateText, selectText, + submitEditText, + deleteEditText, foldForm, }; diff --git a/frontend/components/InteractiveText.tsx b/frontend/components/InteractiveText.tsx new file mode 100644 index 0000000..d7e8a66 --- /dev/null +++ b/frontend/components/InteractiveText.tsx @@ -0,0 +1,222 @@ +import React from "react"; +import TextRecord from "../models/TextRecord"; +import AnalyzedText from "../models/AnalyzedText"; +import { FiEdit, FiX, FiCheck } from "react-icons/fi"; + +type InteractiveTextProps = { + textRecord: TextRecord; + tabColor: string; + editColor: string; + submitEditText: Function; + deleteEditText: Function; +}; + +type InteractiveTextState = { + editMode: boolean; + editText: string; +}; + +class InteractiveText extends React.Component< + InteractiveTextProps, + InteractiveTextState +> { + constructor(props) { + super(props); + + let editText; + if (this.props.textRecord.edited) { + editText = this.props.textRecord.edited.text; + } else { + editText = this.props.textRecord.original.text; + } + + this.state = { + editMode: false, + editText: editText, + }; + + this.enableEditMode = this.enableEditMode.bind(this); + this.handleTextSubmit = this.handleTextSubmit.bind(this); + this.handleTextClear = this.handleTextClear.bind(this); + this.handleTextEdit = this.handleTextEdit.bind(this); + } + + enableEditMode() { + this.setState({ editMode: true }); + } + + handleTextSubmit() { + this.props.submitEditText(this.props.textRecord.id, this.state.editText); + this.setState({ editMode: false }); + } + + handleTextClear() { + this.props.deleteEditText(this.props.textRecord.id); + this.setState({ editMode: false }); + } + + handleTextEdit(event) { + this.setState({ editText: event.target.value }); + } + + render() { + const getEditText = (record: TextRecord) => { + if (record.editLoading) { + return "Loading..."; + } else if (record.editError) { + return ( + <> +
Error: {record.editError.message}
+
{record.edited?.text}
+ + ); + } else { + return record.edited.text; + } + } + + return ( + <> +
+
+ {this.props.textRecord.id} +
+
+ {this.props.textRecord.original.text} +
+ +
+ {(this.props.textRecord.edited || this.props.textRecord.editLoading) && !this.state.editMode ? ( +
+
+ {this.props.textRecord.id}* +
+
+ { getEditText(this.props.textRecord) } +
+ +
+ ) : null} + {this.state.editMode ? ( +
+
+ {this.props.textRecord.id}* +
+