From a52e86a69b2835551ae3eee73d7d3a51eeed47c6 Mon Sep 17 00:00:00 2001
From: Bruce Martin
Date: Wed, 13 Nov 2019 09:40:37 -0800
Subject: [PATCH] improve category and label name validation (#1034)
---
.../src/components/categorical/categorical.js | 103 ++++++++++++------
client/src/components/categorical/category.js | 83 ++++++++++----
.../util/stateManager/annotationsHelpers.js | 5 +
3 files changed, 136 insertions(+), 55 deletions(-)
diff --git a/client/src/components/categorical/categorical.js b/client/src/components/categorical/categorical.js
index 9f9d2941..d9948a5d 100644
--- a/client/src/components/categorical/categorical.js
+++ b/client/src/components/categorical/categorical.js
@@ -14,6 +14,7 @@ import { Select } from "@blueprintjs/select";
import { connect } from "react-redux";
import * as globals from "../../globals";
import Category from "./category";
+import { AnnotationsHelpers } from "../../util/stateManager";
@connect(state => ({
categoricalSelection: state.categoricalSelection,
@@ -50,13 +51,57 @@ class Categories extends React.Component {
};
handleDisableAnnoMode = () => {
- this.setState({ createAnnoModeActive: false });
+ this.setState({
+ createAnnoModeActive: false,
+ categoryToDuplicate: null,
+ newCategoryText: ""
+ });
};
handleModalDuplicateCategorySelection = d => {
this.setState({ categoryToDuplicate: d });
};
+ categoryNameError = name => {
+ /*
+ return false if this is a LEGAL/acceptable category name,
+ or return an error type.
+ */
+ const { categoricalSelection } = this.props;
+ const allCategoryNames = Object.keys(categoricalSelection);
+
+ if (allCategoryNames.indexOf(name) !== -1) {
+ return "duplicate";
+ }
+
+ if (!AnnotationsHelpers.isLegalAnnotationName(name)) {
+ return "characters";
+ }
+
+ return false;
+ };
+
+ categoryNameErrorMessage = name => {
+ const err = this.categoryNameError(name);
+ if (err == "duplicate") {
+ return (
+
+ {name} already exists -
+ no duplicates allowed
+
+ );
+ }
+ if (err == "characters") {
+ return (
+
+ {name} contains illegal
+ characters. Hint: use alpha-numeric and underscore
+
+ );
+ }
+ return err;
+ };
+
render() {
const {
createAnnoModeActive,
@@ -81,30 +126,26 @@ class Categories extends React.Component {
>
{/* READ ONLY CATEGORICAL FIELDS */}
{/* this is duplicative but flat, could be abstracted */}
- {_.map(
- allCategoryNames,
- catName =>
- !schema.annotations.obsByName[catName].writable ? (
-
- ) : null
+ {_.map(allCategoryNames, catName =>
+ !schema.annotations.obsByName[catName].writable ? (
+
+ ) : null
)}
{/* WRITEABLE FIELDS */}
- {_.map(
- allCategoryNames,
- catName =>
- schema.annotations.obsByName[catName].writable ? (
-
- ) : null
+ {_.map(allCategoryNames, catName =>
+ schema.annotations.obsByName[catName].writable ? (
+
+ ) : null
)}
{writableCategoriesEnabled ? (
@@ -124,8 +165,10 @@ class Categories extends React.Component {
New, unique category name:
-
- {newCategoryText}
- {" "}
- already exists
+ {this.categoryNameErrorMessage(newCategoryText)}
@@ -186,9 +227,7 @@ class Categories extends React.Component {
@@ -390,9 +426,10 @@ class Category extends React.Component {