Files
cellxgene/client/src/components/categorical/annoDialogAddLabel.js
Bruce Martin 7bc58bba2b undo/redo cleanup (#1165)
* fix refactoring error which disabled annotation file clearing

* fix undo behavior on add category label

* fix various undo/redo bugs

* remove logging

* further refinement of annotation undo/redo and actions

* address PR comment
2020-02-24 18:51:26 -07:00

139 lines
4.1 KiB
JavaScript

import React from "react";
import { connect } from "react-redux";
import AnnoDialog from "./annoDialog";
import AnnoInputs from "./annoInputs";
import { labelErrorMessage, isLabelErroneous } from "./labelUtil";
@connect(state => ({
colorAccessor: state.colors.colorAccessor,
categoricalSelection: state.categoricalSelection,
annotations: state.annotations,
universe: state.universe,
ontology: state.ontology,
ontologyLoading: state.ontology?.loading,
ontologyEnabled: state.ontology?.enabled
}))
class Category extends React.Component {
constructor(props) {
super(props);
this.state = {
newLabelText: ""
};
}
disableAddNewLabelMode = () => {
const { dispatch } = this.props;
dispatch({
type: "annotation: disable add new label mode"
});
this.setState({
newLabelText: ""
});
};
handleAddNewLabelToCategory = e => {
const { dispatch, metadataField } = this.props;
const { newLabelText } = this.state;
this.disableAddNewLabelMode();
dispatch({
type: "annotation: add new label to category",
metadataField,
newLabelText,
assignSelectedCells: false
});
e.preventDefault();
};
addLabelAndAssignCells = () => {
const { dispatch, metadataField } = this.props;
const { newLabelText } = this.state;
this.disableAddNewLabelMode();
dispatch({
type: "annotation: add new label to category",
metadataField,
newLabelText,
assignSelectedCells: true
});
};
handleCreateArbitraryLabel = newLabelTextNotInOntology => {
const { dispatch, metadataField } = this.props;
this.disableAddNewLabelMode();
dispatch({
type: "annotation: add new label to category",
metadataField,
newLabelText: newLabelTextNotInOntology,
assignSelectedCells: false
});
};
labelNameError = name => {
const { metadataField, ontology, universe } = this.props;
return isLabelErroneous(name, metadataField, ontology, universe.schema);
};
labelNameErrorMessage = name => {
const { metadataField, ontology, universe } = this.props;
return labelErrorMessage(name, metadataField, ontology, universe.schema);
};
/* leaky to have both of these in multiple components */
handleChoice = e => {
this.setState({ newLabelText: e.target });
};
handleTextChange = text => {
this.setState({ newLabelText: text });
};
render() {
const { newLabelText } = this.state;
const { metadataField, annotations, ontologyEnabled } = this.props;
return (
<>
<AnnoDialog
isActive={
annotations.isAddingNewLabel &&
annotations.categoryAddingNewLabel === metadataField
}
inputProps={{ "data-testid": `${metadataField}:create-label-dialog` }}
primaryButtonProps={{
"data-testid": `${metadataField}:submit-label`
}}
title="Add new label to category"
instruction="New, unique label name:"
cancelTooltipContent="Close this dialog without adding a label."
primaryButtonText="Add label"
secondaryButtonText="Add label and assign currently selected cells"
handleSecondaryButtonSubmit={this.addLabelAndAssignCells}
text={newLabelText}
validationError={this.labelNameError(newLabelText)}
errorMessage={this.labelNameErrorMessage(newLabelText)}
handleSubmit={this.handleAddNewLabelToCategory}
handleCancel={this.disableAddNewLabelMode}
annoInput={
<AnnoInputs
useSuggest={ontologyEnabled}
text={newLabelText}
inputProps={{ "data-testid": `${metadataField}:new-label-name` }}
handleCreateArbitraryLabel={this.handleCreateArbitraryLabel}
handleItemChange={this.handleSuggestActiveItemChange}
handleChoice={this.handleChoice}
handleTextChange={this.handleTextChange}
isTextInvalid={this.labelNameError}
isTextInvalidErrorMessage={this.labelNameErrorMessage}
/>
}
/>
</>
);
}
}
export default Category;