Skip to content

Commit

Permalink
Add 'change answer classification' feature
Browse files Browse the repository at this point in the history
  • Loading branch information
jprodrigues70 committed May 6, 2021
1 parent 125b9c6 commit 80ffdba
Show file tree
Hide file tree
Showing 18 changed files with 410 additions and 149 deletions.
86 changes: 50 additions & 36 deletions src/components/AnswerPane/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ import "./style.sass";
import key from "../../plugins/key";
import AnswerClassifier from "../../plugins/AnswerClassifier";
import AnswerPrinter from "../../contracts/AnswerPrinter";
import Btn from "../Btn";
import SentimentItem from "../SentimentItem";
import SentimentList from "../SentimentList";

export default class AnswerPane extends AnswerPrinter {
constructor(props) {
super(props);
this.state = {
component: <div></div>,
};
constructor(props, context) {
super(props, context);
}

summarizeDates() {
summarizeDates = () => {
const answers = this.valids
.map((i) => i.answer.split(" ")[0])
.reduce((acc, item) => {
Expand All @@ -27,9 +27,9 @@ export default class AnswerPane extends AnswerPrinter {
was the day that received the <b>fewest responses</b>
</span>
);
}
};

summarizeCityState() {
summarizeCityState = () => {
const answers = AnswerClassifier.groupCityAnswers(this.valids);
return this.summaryAnswer(
answers,
Expand All @@ -40,17 +40,18 @@ export default class AnswerPane extends AnswerPrinter {
was the place that received the <b>fewest responses</b>
</span>
);
}
};

summarize() {
summarize = () => {
const answers = AnswerClassifier.groupAnswers(this.valids);
return this.summaryAnswer(answers);
}
};

categorizeAndMerge(type) {
categorizeAndMerge = (type) => {
return this.categoryAnswer(type, (set) => {
const grouped = AnswerClassifier.groupAnswers(set);
return (

return () => (
<ul>
{Object.keys(grouped).map((i) => (
<li key={key(`categorie-${i}`)}>
Expand All @@ -60,47 +61,60 @@ export default class AnswerPane extends AnswerPrinter {
</ul>
);
});
}
};

categorize(type) {
return this.categoryAnswer(type, (set) => {
return (
categorize = (type) => {
return this.categoryAnswer(type, (set, category, change, categories) => {
if (categories.length > 1) {
return () => (
<SentimentList
list={set}
category={category}
categories={categories}
change={change}
hide-sentiment={true}
/>
);
}
return () => (
<ul>
{set.map((i) => (
<li key={key(`nol-${i.line}`)}>{i.answer}</li>
))}
</ul>
);
});
}
};

scoreSentmentsAndCategorize(type) {
const answers = AnswerClassifier.groupByScore(this.valids);
scoreSentimentsAndCategorize = (type) => {
const answers = AnswerClassifier.groupByScore(this.valids, type);

return this.categoryAnswer(
type,
(set) => {
return (
<ul>
{set.map((i) => (
<li key={key(`fdbk-${i.line}`)}>
{i.answer}
<ul>
<li>Sentment Score: {i.sentment.score}</li>
</ul>
</li>
))}
</ul>
(set, category, change) => {
return () => (
<SentimentList
list={set}
category={category}
categories={["negative", "neutral", "positive"]}
change={change}
/>
);
},
answers
);
}
};

componentDidMount() {
this.setState({
component: this.presentByType(),
});
this.presentByType();
}

componentDidUpdate(a, b) {
if (
a["question-classification"] !== this.props["question-classification"]
) {
this.presentByType();
}
}

render() {
Expand Down
5 changes: 5 additions & 0 deletions src/components/AnswerPane/style.sass
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,8 @@
gap: 8px
&__body
margin: 8px 0
&__categorizable
&-list
list-style: none
margin: 0
padding: 0
3 changes: 2 additions & 1 deletion src/components/Btn/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ export default class Btn extends Component {
render() {
const color = this.props.color ? `c-btn--${this.props.color}` : "";
const active = this.props.active ? `c-btn--active` : "";
const small = this.props.small ? `c-btn--small` : "";

return (
<button
ref={this.props.ref}
className={`c-btn ${color} ${active}`}
className={`c-btn ${color} ${active} ${small}`}
onClick={this.props.onClick}
>
<span className="c-btn__background"></span>
Expand Down
3 changes: 3 additions & 0 deletions src/components/Btn/style.sass
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
background-color: #ffe7ce
&--active
border-color: #0d2e57
&--small
padding: 4px 8px
font-size: 11px
&:hover
& > .c-btn__background
background: rgba(0,0,0,.2)
Expand Down
17 changes: 13 additions & 4 deletions src/components/Question/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,12 @@ export default class Question extends Component {

constructor(props, context) {
super(props, context);
const { rows, classifications } = this.context.state["database.table"];
const { rows, classifications, manualSettings } = this.context.state[
"database.table"
];
this.rows = rows || [];
this.classifications = classifications || [];
this.manualSettings = manualSettings || [];

this.state = {
classification: this.props.classifier.getOption(
Expand All @@ -25,11 +28,14 @@ export default class Question extends Component {
classification,
});

const table = JSON.parse(localStorage.getItem("database"))[
this.context.state["database.key"]
];

this.classifications[this.props.position] = classification.key;

CsvExtractor.update(this.context.state["database.key"], {
titles: this.context.state["database.table"].titles,
rows: this.rows,
...table,
classifications: this.classifications,
});
}
Expand All @@ -44,7 +50,9 @@ export default class Question extends Component {
<div className="c-question">
<div className="c-question__header">
<div>
<h2 className="c-question__title">{this.props.title}</h2>
<h2 className="c-question__title">
{this.props.position + 1}. {this.props.title}
</h2>
<p className="c-question__subtitle">
{this.state.classification.title}
</p>
Expand All @@ -60,6 +68,7 @@ export default class Question extends Component {
<AnswerPane
question-classification={this.state.classification}
answers={answers}
question={this.props.position}
></AnswerPane>
</div>
</div>
Expand Down
7 changes: 5 additions & 2 deletions src/components/RawData/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export default class RawData extends Component {
<tr className="c-raw-data__tr">
<th>#</th>
{this.header().map((item, index) => (
<th key={index} className="c-raw-data__th">
<th key={key(`title-${index}`)} className="c-raw-data__th">
{item}
</th>
))}
Expand All @@ -34,7 +34,10 @@ export default class RawData extends Component {
<tr className="c-raw-data__tr" key={key(`line-${line}`)}>
<td className="c-raw-data__td">{line}</td>
{row.map((column, index) => (
<td className="c-raw-data__td" key={key(`column-${column}`)}>
<td
className="c-raw-data__td"
key={key(`column-${line}-${index}`)}
>
{column}
</td>
))}
Expand Down
52 changes: 52 additions & 0 deletions src/components/SentimentItem/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { Component } from "react";
import Btn from "../Btn";
import "./style.sass";

export default class SentimentItem extends Component {
constructor(props) {
super(props);
this.state = {
color: "",
};
}
change = (color) => {
this.setState(
{
color: this.state.color === color ? "" : color,
},
() => {
if (this.props.onChange) {
this.props.onChange(color);
}
}
);
};
render() {
const color = this.state.color
? ` c-sentiment-item--${this.state.color}`
: "";
return (
<li className={`c-sentiment-item${color}`}>
{this.props.format ? (
this.props.format(this.props.item)
) : (
<>
{this.props.item.answer}
{!this.props["hide-sentiment"] && (
<ul>
<li>Sentiment Score: {this.props.item.sentiment.score}</li>
</ul>
)}
<div className="c-sentiment-item__control">
{this.props.categories.map((k) => (
<Btn small color={k} key={k} onClick={() => this.change(k)}>
Change to {k}
</Btn>
))}
</div>
</>
)}
</li>
);
}
}
17 changes: 17 additions & 0 deletions src/components/SentimentItem/style.sass
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.c-sentiment-item
padding: 8px 12px
border: 1px solid #F3F3F4
background-color: #F3F3F4
border-radius: 8px
margin: 4px 0
&__control
padding-top: 8px
text-align: right
&--positive
background-color: #bee2aa
&--negative
background-color: #e2aaaa
&--neutral
background-color: #afd4ff
&--unclassified
background-color: #ffe7ce
34 changes: 34 additions & 0 deletions src/components/SentimentList/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Component } from "react";
import key from "../../plugins/key";
import SentimentItem from "../SentimentItem";

export default class SentimentList extends Component {
constructor(props) {
super(props);
this.state = {
set: this.props.list,
};
}

render() {
return (
<ul className="c-answer-pane__categorizable-list">
{this.state.set.map((i) => {
const categories = this.props.categories.filter(
(j) => j !== this.props.category
);

return (
<SentimentItem
item={i}
categories={categories}
key={key(`fdbk-${i.line}`)}
onChange={(to) => this.props.change(i, to, this.props.category)}
hide-sentiment={this.props["hide-sentiment"]}
/>
);
})}
</ul>
);
}
}
19 changes: 19 additions & 0 deletions src/components/Suitable/Content.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Component } from "react";
import key from "../../plugins/key";

import "./style.sass";

export default class SuitableContent extends Component {
render() {
return this.props.areas.map((item) => {
const Content = item.content;
const _key = item.key.split(":")[0].trim();

return this.props.visible === _key ? (
<div key={key(`suitable-${_key}`)}>
<Content />
</div>
) : null;
});
}
}
Loading

0 comments on commit 80ffdba

Please sign in to comment.