Skip to content
This repository was archived by the owner on Jun 11, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions frontend/MainContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -25,7 +27,9 @@ type ContainerProps = {
generateTextFailed: any,
generateText: any
selectText: Function,
foldForm: Function
submitEditText: Function,
deleteEditText: Function,
foldForm: Function,
}

const Container: React.FunctionComponent<ContainerProps> = ({
Expand All @@ -39,6 +43,8 @@ const Container: React.FunctionComponent<ContainerProps> = ({
generateTextFailed,
generateText,
selectText,
submitEditText,
deleteEditText,
foldForm
}) => {
const getDetailedAnalysisComponent = () => {
Expand All @@ -48,7 +54,10 @@ const Container: React.FunctionComponent<ContainerProps> = ({
const selectedText = selectedTextIds.map(id => analysisResults.find(item => id == item.id))
return (
<TextDetailedAnalysis
selectedText={selectedText} />
selectedText={selectedText}
submitEditText={submitEditText}
deleteEditText={deleteEditText}
/>
);
}
}
Expand Down Expand Up @@ -95,6 +104,8 @@ function mapDispatchToProps (dispatch) {
generateTextFailed: generateTextFailed,
generateText: generateText,
selectText: selectText,
submitEditText: submitEditText,
deleteEditText: deleteEditText,
foldForm: foldForm,
}, dispatch);
}
Expand Down
43 changes: 43 additions & 0 deletions frontend/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -43,12 +50,48 @@ 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,
setGeneratedTextResults,
generateTextFailed,
generateText,
selectText,
submitEditText,
deleteEditText,
foldForm,
};
222 changes: 222 additions & 0 deletions frontend/components/InteractiveText.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<>
<div style={{color: "red"}}>Error: {record.editError.message}</div>
<div>{record.edited?.text}</div>
</>
);
} else {
return record.edited.text;
}
}

return (
<>
<div className="flex items-stretch mb-4" style={{ minHeight: "110px" }}>
<div
className="flex items-center justify-center flex-none px-1"
style={{
backgroundColor: this.props.tabColor,
color: "white",
width: "26px",
fontSize: "18px",
lineHeight: "20px",
}}
>
{this.props.textRecord.id}
</div>
<div
className="flex items-center flex-auto px-4"
style={{
backgroundColor: "#F3F6FD",
fontSize: "18px",
lineHeight: "27px",
}}
>
{this.props.textRecord.original.text}
</div>
<button
className="flex items-center justify-center flex-none px-1"
style={{
backgroundColor: "#E1E6F0",
width: "42px",
fontSize: "18px",
lineHeight: "20px",
}}
onClick={this.enableEditMode}
>
<FiEdit style={{ color: "#167DF5" }} size={20} />
</button>
</div>
{(this.props.textRecord.edited || this.props.textRecord.editLoading) && !this.state.editMode ? (
<div
className="flex items-stretch mb-4"
style={{ minHeight: "110px" }}
>
<div
className="flex items-center flex-none px-1"
style={{
backgroundColor: this.props.editColor,
color: "white",
width: "26px",
fontSize: "18px",
lineHeight: "20px",
}}
>
{this.props.textRecord.id}*
</div>
<div
className="flex flex-col justify-center flex-auto px-4"
style={{
backgroundColor: "#F3F6FD",
fontSize: "18px",
lineHeight: "27px",
}}
>
{ getEditText(this.props.textRecord) }
</div>
<button
className="flex items-center justify-center flex-none px-1"
style={{
backgroundColor: "#E1E6F0",
width: "42px",
fontSize: "18px",
lineHeight: "20px",
}}
onClick={this.enableEditMode}
>
<FiEdit style={{ color: "#167DF5" }} size={20} />
</button>
</div>
) : null}
{this.state.editMode ? (
<div
className="flex items-stretch mb-4"
style={{ minHeight: "110px" }}
>
<div
className="flex items-center flex-none px-1"
style={{
backgroundColor: this.props.editColor,
color: "white",
fontSize: "18px",
lineHeight: "20px",
}}
>
{this.props.textRecord.id}*
</div>
<textarea
className="flex-auto"
style={{
backgroundColor: "white",
fontSize: "18px",
lineHeight: "27px",
padding: "10px",
border: "solid black 1px",
}}
value={this.state.editText}
onChange={this.handleTextEdit}
/>
<div
className="flex flex-col items-center justify-center flex-none px-1"
style={{
backgroundColor: "#E1E6F0",
width: "42px",
lineHeight: "20px",
}}
>
<button
className="flex items-center flex-grow px-1"
style={{
backgroundColor: "#E1E6F0",
lineHeight: "20px",
}}
onClick={this.handleTextClear}
>
<FiX style={{ color: "#167DF5" }} size={20} />
</button>
<button
className="flex items-center flex-grow px-1"
style={{
backgroundColor: "#E1E6F0",
color: "white",
lineHeight: "20px",
}}
onClick={this.handleTextSubmit}
>
<FiCheck style={{ color: "#167DF5" }} size={20}/>
</button>
</div>
</div>
) : null}
</>
);
}
}

export default InteractiveText;
7 changes: 4 additions & 3 deletions frontend/components/PerspectiveScoresBarChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import ReactDOM from "react-dom";
import * as d3 from "d3";
import { DirectionalHint } from 'office-ui-fabric-react/lib/Tooltip';
import { PrimaryButton, DefaultButton } from 'office-ui-fabric-react/lib/Button';
import TextRecord from "../models/TextRecord";
import AnalyzedText from "../models/AnalyzedText";


Expand All @@ -14,7 +15,7 @@ type PerspectiveScoresBarChartProps = {
id: number,
width: number,
defaultSelectedScore: string,
analyzedText: AnalyzedText
textRecord: TextRecord
}

class PerspectiveScoresBarChart extends Component<PerspectiveScoresBarChartProps, PerspectiveScoresBarChartState> {
Expand Down Expand Up @@ -58,7 +59,7 @@ class PerspectiveScoresBarChart extends Component<PerspectiveScoresBarChartProps
var _this = this;
var body = d3.select(this.node.current);

const getResultScoreObj: any = (item: any) => {
const getResultScoreObj: any = (item: AnalyzedText) => {
let resultScores = [
{label: "toxicity", value: item.toxicity, scoreName: "Toxicity"},
{label: "severeToxicity", value: item.severeToxicity, scoreName: "Severe Toxicity"},
Expand All @@ -73,7 +74,7 @@ class PerspectiveScoresBarChart extends Component<PerspectiveScoresBarChartProps
return resultScores;
}

var scores = getResultScoreObj(this.props.analyzedText);
var scores = getResultScoreObj(this.props.textRecord.original);

var margin = { top: 5, right: 15, bottom: 50, left: 55 }
var h = 111 - margin.top - margin.bottom
Expand Down
Loading