mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-10-07 13:18:11 +08:00
Render categories with one label without checkbox (#1375)
* categories with 1 item rendered without checkbox * break out into helper functions * prettier
This commit is contained in:
@@ -10,11 +10,11 @@ import AnnoSelect from "./annoSelect";
|
|||||||
import LabelInput from "./labelInput";
|
import LabelInput from "./labelInput";
|
||||||
import { labelPrompt } from "./labelUtil";
|
import { labelPrompt } from "./labelUtil";
|
||||||
|
|
||||||
@connect(state => ({
|
@connect((state) => ({
|
||||||
writableCategoriesEnabled: state.config?.parameters?.["annotations"] ?? false,
|
writableCategoriesEnabled: state.config?.parameters?.["annotations"] ?? false,
|
||||||
schema: state.world?.schema,
|
schema: state.world?.schema,
|
||||||
config: state.config,
|
config: state.config,
|
||||||
ontology: state.ontology
|
ontology: state.ontology,
|
||||||
}))
|
}))
|
||||||
class Categories extends React.Component {
|
class Categories extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@@ -23,22 +23,22 @@ class Categories extends React.Component {
|
|||||||
createAnnoModeActive: false,
|
createAnnoModeActive: false,
|
||||||
newCategoryText: "",
|
newCategoryText: "",
|
||||||
categoryToDuplicate: null,
|
categoryToDuplicate: null,
|
||||||
expandedCats: new Set()
|
expandedCats: new Set(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
handleCreateUserAnno = e => {
|
handleCreateUserAnno = (e) => {
|
||||||
const { dispatch } = this.props;
|
const { dispatch } = this.props;
|
||||||
const { newCategoryText, categoryToDuplicate } = this.state;
|
const { newCategoryText, categoryToDuplicate } = this.state;
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "annotation: create category",
|
type: "annotation: create category",
|
||||||
data: newCategoryText,
|
data: newCategoryText,
|
||||||
categoryToDuplicate
|
categoryToDuplicate,
|
||||||
});
|
});
|
||||||
this.setState({
|
this.setState({
|
||||||
createAnnoModeActive: false,
|
createAnnoModeActive: false,
|
||||||
categoryToDuplicate: null,
|
categoryToDuplicate: null,
|
||||||
newCategoryText: ""
|
newCategoryText: "",
|
||||||
});
|
});
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
};
|
};
|
||||||
@@ -51,15 +51,15 @@ class Categories extends React.Component {
|
|||||||
this.setState({
|
this.setState({
|
||||||
createAnnoModeActive: false,
|
createAnnoModeActive: false,
|
||||||
categoryToDuplicate: null,
|
categoryToDuplicate: null,
|
||||||
newCategoryText: ""
|
newCategoryText: "",
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
handleModalDuplicateCategorySelection = d => {
|
handleModalDuplicateCategorySelection = (d) => {
|
||||||
this.setState({ categoryToDuplicate: d });
|
this.setState({ categoryToDuplicate: d });
|
||||||
};
|
};
|
||||||
|
|
||||||
categoryNameError = name => {
|
categoryNameError = (name) => {
|
||||||
/*
|
/*
|
||||||
return false if this is a LEGAL/acceptable category name or NULL/empty string,
|
return false if this is a LEGAL/acceptable category name or NULL/empty string,
|
||||||
or return an error type.
|
or return an error type.
|
||||||
@@ -73,7 +73,7 @@ class Categories extends React.Component {
|
|||||||
we render as categorical.
|
we render as categorical.
|
||||||
*/
|
*/
|
||||||
const { schema } = this.props;
|
const { schema } = this.props;
|
||||||
const allCategoryNames = schema.annotations.obs.columns.map(c => c.name);
|
const allCategoryNames = schema.annotations.obs.columns.map((c) => c.name);
|
||||||
|
|
||||||
/* check category name syntax */
|
/* check category name syntax */
|
||||||
const error = AnnotationsHelpers.annotationNameIsErroneous(name);
|
const error = AnnotationsHelpers.annotationNameIsErroneous(name);
|
||||||
@@ -90,15 +90,15 @@ class Categories extends React.Component {
|
|||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
handleChange = name => {
|
handleChange = (name) => {
|
||||||
this.setState({ newCategoryText: name });
|
this.setState({ newCategoryText: name });
|
||||||
};
|
};
|
||||||
|
|
||||||
handleSelect = name => {
|
handleSelect = (name) => {
|
||||||
this.setState({ newCategoryText: name });
|
this.setState({ newCategoryText: name });
|
||||||
};
|
};
|
||||||
|
|
||||||
instruction = name => {
|
instruction = (name) => {
|
||||||
return labelPrompt(
|
return labelPrompt(
|
||||||
this.categoryNameError(name),
|
this.categoryNameError(name),
|
||||||
"New, unique category name",
|
"New, unique category name",
|
||||||
@@ -106,25 +106,76 @@ class Categories extends React.Component {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
onExpansionChange = catName => {
|
onExpansionChange = (catName) => {
|
||||||
const {expandedCats} = this.state;
|
const { expandedCats } = this.state;
|
||||||
if (expandedCats.has(catName)) {
|
if (expandedCats.has(catName)) {
|
||||||
const _expandedCats = new Set(expandedCats);
|
const _expandedCats = new Set(expandedCats);
|
||||||
_expandedCats.delete(catName)
|
_expandedCats.delete(catName);
|
||||||
this.setState({expandedCats: _expandedCats})
|
this.setState({ expandedCats: _expandedCats });
|
||||||
} else {
|
} else {
|
||||||
const _expandedCats = new Set(expandedCats);
|
const _expandedCats = new Set(expandedCats);
|
||||||
_expandedCats.add(catName)
|
_expandedCats.add(catName);
|
||||||
this.setState({expandedCats: _expandedCats})
|
this.setState({ expandedCats: _expandedCats });
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
|
maybeRenderSingleLabel = (allCategoryNames, schema) => {
|
||||||
|
return allCategoryNames.map((catName) =>
|
||||||
|
!schema.annotations.obsByName[catName].writable &&
|
||||||
|
schema.annotations.obsByName[catName].categories.length === 1 ? (
|
||||||
|
<div style={{ marginBottom: 10 }}>
|
||||||
|
<span style={{ fontWeight: 700 }}>{catName}</span>:{" "}
|
||||||
|
{schema.annotations.obsByName[catName].categories[0]}
|
||||||
|
</div>
|
||||||
|
) : null
|
||||||
|
);
|
||||||
|
};
|
||||||
|
maybeRenderReadOnly = (
|
||||||
|
allCategoryNames,
|
||||||
|
schema,
|
||||||
|
expandedCats,
|
||||||
|
createAnnoModeActive
|
||||||
|
) => {
|
||||||
|
return allCategoryNames.map((catName) =>
|
||||||
|
!schema.annotations.obsByName[catName].writable &&
|
||||||
|
schema.annotations.obsByName[catName].categories.length > 1 ? (
|
||||||
|
<Category
|
||||||
|
key={catName}
|
||||||
|
metadataField={catName}
|
||||||
|
onExpansionChange={this.onExpansionChange}
|
||||||
|
isExpanded={expandedCats.has(catName)}
|
||||||
|
createAnnoModeActive={createAnnoModeActive}
|
||||||
|
isUserAnno={false}
|
||||||
|
/>
|
||||||
|
) : null
|
||||||
|
);
|
||||||
|
};
|
||||||
|
maybeRenderAnnotations = (
|
||||||
|
allCategoryNames,
|
||||||
|
schema,
|
||||||
|
expandedCats,
|
||||||
|
createAnnoModeActive
|
||||||
|
) => {
|
||||||
|
return allCategoryNames.map((catName) =>
|
||||||
|
schema.annotations.obsByName[catName].writable ? (
|
||||||
|
<Category
|
||||||
|
key={catName}
|
||||||
|
metadataField={catName}
|
||||||
|
onExpansionChange={this.onExpansionChange}
|
||||||
|
isExpanded={expandedCats.has(catName)}
|
||||||
|
createAnnoModeActive={createAnnoModeActive}
|
||||||
|
isUserAnno
|
||||||
|
/>
|
||||||
|
) : null
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
createAnnoModeActive,
|
createAnnoModeActive,
|
||||||
categoryToDuplicate,
|
categoryToDuplicate,
|
||||||
newCategoryText,
|
newCategoryText,
|
||||||
expandedCats
|
expandedCats,
|
||||||
} = this.state;
|
} = this.state;
|
||||||
const { writableCategoriesEnabled, schema, config, ontology } = this.props;
|
const { writableCategoriesEnabled, schema, config, ontology } = this.props;
|
||||||
const ontologyEnabled = ontology?.enabled ?? false;
|
const ontologyEnabled = ontology?.enabled ?? false;
|
||||||
@@ -137,7 +188,7 @@ class Categories extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
padding: globals.leftSidebarSectionPadding
|
padding: globals.leftSidebarSectionPadding,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<AnnoDialog
|
<AnnoDialog
|
||||||
@@ -160,7 +211,7 @@ class Categories extends React.Component {
|
|||||||
"data-testid": "new-category-name",
|
"data-testid": "new-category-name",
|
||||||
leftIcon: "tag",
|
leftIcon: "tag",
|
||||||
intent: "none",
|
intent: "none",
|
||||||
autoFocus: true
|
autoFocus: true,
|
||||||
}}
|
}}
|
||||||
newLabelMessage="New category"
|
newLabelMessage="New category"
|
||||||
/>
|
/>
|
||||||
@@ -176,33 +227,33 @@ class Categories extends React.Component {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* READ ONLY CATEGORICAL FIELDS */}
|
<div style={{ marginLeft: 0 }}>
|
||||||
{/* this is duplicative but flat, could be abstracted */}
|
{
|
||||||
{allCategoryNames.map(catName =>
|
this.maybeRenderSingleLabel(
|
||||||
!schema.annotations.obsByName[catName].writable ? (
|
allCategoryNames,
|
||||||
<Category
|
schema,
|
||||||
key={catName}
|
expandedCats,
|
||||||
metadataField={catName}
|
createAnnoModeActive
|
||||||
onExpansionChange={this.onExpansionChange}
|
) /* Categories with only one label */
|
||||||
isExpanded={expandedCats.has(catName)}
|
}
|
||||||
createAnnoModeActive={createAnnoModeActive}
|
</div>
|
||||||
isUserAnno={false}
|
{
|
||||||
/>
|
this.maybeRenderReadOnly(
|
||||||
) : null
|
allCategoryNames,
|
||||||
)}
|
schema,
|
||||||
{/* WRITEABLE FIELDS */}
|
expandedCats,
|
||||||
{allCategoryNames.map(catName =>
|
createAnnoModeActive
|
||||||
schema.annotations.obsByName[catName].writable ? (
|
) /* Read only categorical fields, ostensibly 'normal' mode */
|
||||||
<Category
|
}
|
||||||
key={catName}
|
{
|
||||||
metadataField={catName}
|
this.maybeRenderAnnotations(
|
||||||
onExpansionChange={this.onExpansionChange}
|
allCategoryNames,
|
||||||
isExpanded={expandedCats.has(catName)}
|
schema,
|
||||||
createAnnoModeActive={createAnnoModeActive}
|
expandedCats,
|
||||||
isUserAnno
|
createAnnoModeActive
|
||||||
/>
|
) /* Writable fields, ie., anno */
|
||||||
) : null
|
}
|
||||||
)}
|
|
||||||
{writableCategoriesEnabled ? (
|
{writableCategoriesEnabled ? (
|
||||||
<div>
|
<div>
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
Reference in New Issue
Block a user