mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-10-04 19:48:11 +08:00
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
This commit is contained in:
@@ -70,7 +70,7 @@ class AnnoDialog extends React.Component {
|
|||||||
onClick={handleSecondaryButtonSubmit}
|
onClick={handleSecondaryButtonSubmit}
|
||||||
disabled={!text || validationError}
|
disabled={!text || validationError}
|
||||||
intent="none"
|
intent="none"
|
||||||
type="submit"
|
type="button"
|
||||||
>
|
>
|
||||||
{secondaryButtonText}
|
{secondaryButtonText}
|
||||||
</Button>
|
</Button>
|
||||||
|
|||||||
@@ -32,43 +32,43 @@ class Category extends React.Component {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
handleAddNewLabelToCategory = () => {
|
handleAddNewLabelToCategory = e => {
|
||||||
const { dispatch, metadataField } = this.props;
|
const { dispatch, metadataField } = this.props;
|
||||||
const { newLabelText } = this.state;
|
const { newLabelText } = this.state;
|
||||||
|
|
||||||
|
this.disableAddNewLabelMode();
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "annotation: add new label to category",
|
type: "annotation: add new label to category",
|
||||||
metadataField,
|
metadataField,
|
||||||
newLabelText,
|
newLabelText,
|
||||||
assignSelectedCells: false
|
assignSelectedCells: false
|
||||||
});
|
});
|
||||||
this.setState({ newLabelText: "" });
|
e.preventDefault();
|
||||||
};
|
};
|
||||||
|
|
||||||
addLabelAndAssignCells = () => {
|
addLabelAndAssignCells = () => {
|
||||||
const { dispatch, metadataField } = this.props;
|
const { dispatch, metadataField } = this.props;
|
||||||
const { newLabelText } = this.state;
|
const { newLabelText } = this.state;
|
||||||
|
|
||||||
|
this.disableAddNewLabelMode();
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "annotation: add new label to category",
|
type: "annotation: add new label to category",
|
||||||
metadataField,
|
metadataField,
|
||||||
newLabelText,
|
newLabelText,
|
||||||
assignSelectedCells: true
|
assignSelectedCells: true
|
||||||
});
|
});
|
||||||
|
|
||||||
this.setState({ newLabelText: "" });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
handleCreateArbitraryLabel = newLabelTextNotInOntology => {
|
handleCreateArbitraryLabel = newLabelTextNotInOntology => {
|
||||||
const { dispatch, metadataField } = this.props;
|
const { dispatch, metadataField } = this.props;
|
||||||
|
|
||||||
|
this.disableAddNewLabelMode();
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "annotation: add new label to category",
|
type: "annotation: add new label to category",
|
||||||
metadataField,
|
metadataField,
|
||||||
newLabelText: newLabelTextNotInOntology,
|
newLabelText: newLabelTextNotInOntology,
|
||||||
assignSelectedCells: false
|
assignSelectedCells: false
|
||||||
});
|
});
|
||||||
this.setState({ newLabelText: "" });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
labelNameError = name => {
|
labelNameError = name => {
|
||||||
@@ -102,7 +102,9 @@ class Category extends React.Component {
|
|||||||
annotations.categoryAddingNewLabel === metadataField
|
annotations.categoryAddingNewLabel === metadataField
|
||||||
}
|
}
|
||||||
inputProps={{ "data-testid": `${metadataField}:create-label-dialog` }}
|
inputProps={{ "data-testid": `${metadataField}:create-label-dialog` }}
|
||||||
primaryButtonProps={{ "data-testid": `${metadataField}:submit-label` }}
|
primaryButtonProps={{
|
||||||
|
"data-testid": `${metadataField}:submit-label`
|
||||||
|
}}
|
||||||
title="Add new label to category"
|
title="Add new label to category"
|
||||||
instruction="New, unique label name:"
|
instruction="New, unique label name:"
|
||||||
cancelTooltipContent="Close this dialog without adding a label."
|
cancelTooltipContent="Close this dialog without adding a label."
|
||||||
|
|||||||
@@ -32,43 +32,43 @@ class Category extends React.Component {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
handleAddNewLabelToCategory = () => {
|
handleAddNewLabelToCategory = e => {
|
||||||
const { dispatch, metadataField } = this.props;
|
const { dispatch, metadataField } = this.props;
|
||||||
const { newLabelText } = this.state;
|
const { newLabelText } = this.state;
|
||||||
|
|
||||||
|
this.disableAddNewLabelFromOntologyMode();
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "annotation: add new label to category",
|
type: "annotation: add new label to category",
|
||||||
metadataField,
|
metadataField,
|
||||||
newLabelText,
|
newLabelText,
|
||||||
assignSelectedCells: false
|
assignSelectedCells: false
|
||||||
});
|
});
|
||||||
this.setState({ newLabelText: "" });
|
e.preventDefault();
|
||||||
};
|
};
|
||||||
|
|
||||||
addLabelAndAssignCells = () => {
|
addLabelAndAssignCells = () => {
|
||||||
const { dispatch, metadataField } = this.props;
|
const { dispatch, metadataField } = this.props;
|
||||||
const { newLabelText } = this.state;
|
const { newLabelText } = this.state;
|
||||||
|
|
||||||
|
this.disableAddNewLabelFromOntologyMode();
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "annotation: add new label to category",
|
type: "annotation: add new label to category",
|
||||||
metadataField,
|
metadataField,
|
||||||
newLabelText,
|
newLabelText,
|
||||||
assignSelectedCells: true
|
assignSelectedCells: true
|
||||||
});
|
});
|
||||||
|
|
||||||
this.setState({ newLabelText: "" });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
handleCreateArbitraryLabel = newLabelTextNotInOntology => {
|
handleCreateArbitraryLabel = newLabelTextNotInOntology => {
|
||||||
const { dispatch, metadataField } = this.props;
|
const { dispatch, metadataField } = this.props;
|
||||||
|
|
||||||
|
this.disableAddNewLabelFromOntologyMode();
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "annotation: add new label to category",
|
type: "annotation: add new label to category",
|
||||||
metadataField,
|
metadataField,
|
||||||
newLabelText: newLabelTextNotInOntology,
|
newLabelText: newLabelTextNotInOntology,
|
||||||
assignSelectedCells: false
|
assignSelectedCells: false
|
||||||
});
|
});
|
||||||
this.setState({ newLabelText: "" });
|
|
||||||
};
|
};
|
||||||
|
|
||||||
labelNameError = name => {
|
labelNameError = name => {
|
||||||
|
|||||||
@@ -30,13 +30,14 @@ class AnnoDialogEditCategoryName extends React.Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
disableEditCategoryMode = () => {
|
disableEditCategoryMode = () => {
|
||||||
const { dispatch } = this.props;
|
const { dispatch, metadataField } = this.props;
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "annotation: disable category edit mode"
|
type: "annotation: disable category edit mode"
|
||||||
});
|
});
|
||||||
|
this.setState({ newCategoryText: metadataField });
|
||||||
};
|
};
|
||||||
|
|
||||||
handleEditCategory = () => {
|
handleEditCategory = e => {
|
||||||
const { dispatch, metadataField, categoricalSelection } = this.props;
|
const { dispatch, metadataField, categoricalSelection } = this.props;
|
||||||
const { newCategoryText } = this.state;
|
const { newCategoryText } = this.state;
|
||||||
|
|
||||||
@@ -50,12 +51,14 @@ class AnnoDialogEditCategoryName extends React.Component {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.disableEditCategoryMode();
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "annotation: category edited",
|
type: "annotation: category edited",
|
||||||
metadataField,
|
metadataField,
|
||||||
newCategoryText,
|
newCategoryText,
|
||||||
data: newCategoryText
|
data: newCategoryText
|
||||||
});
|
});
|
||||||
|
e.preventDefault();
|
||||||
};
|
};
|
||||||
|
|
||||||
categoryNameErrorMessage = () => {
|
categoryNameErrorMessage = () => {
|
||||||
@@ -121,8 +124,12 @@ class AnnoDialogEditCategoryName extends React.Component {
|
|||||||
annotations.isEditingCategoryName &&
|
annotations.isEditingCategoryName &&
|
||||||
annotations.categoryBeingEdited === metadataField
|
annotations.categoryBeingEdited === metadataField
|
||||||
}
|
}
|
||||||
inputProps={{ "data-testid": `${metadataField}:edit-category-name-dialog` }}
|
inputProps={{
|
||||||
primaryButtonProps={{ "data-testid": `${metadataField}:submit-category-edit` }}
|
"data-testid": `${metadataField}:edit-category-name-dialog`
|
||||||
|
}}
|
||||||
|
primaryButtonProps={{
|
||||||
|
"data-testid": `${metadataField}:submit-category-edit`
|
||||||
|
}}
|
||||||
title="Edit category name"
|
title="Edit category name"
|
||||||
instruction="New, unique category name:"
|
instruction="New, unique category name:"
|
||||||
cancelTooltipContent="Close this dialog without editing this category."
|
cancelTooltipContent="Close this dialog without editing this category."
|
||||||
@@ -134,7 +141,9 @@ class AnnoDialogEditCategoryName extends React.Component {
|
|||||||
handleCancel={this.disableEditCategoryMode}
|
handleCancel={this.disableEditCategoryMode}
|
||||||
annoInput={
|
annoInput={
|
||||||
<AnnoInputs
|
<AnnoInputs
|
||||||
inputProps={{ "data-testid": `${metadataField}:edit-category-name-text`}}
|
inputProps={{
|
||||||
|
"data-testid": `${metadataField}:edit-category-name-text`
|
||||||
|
}}
|
||||||
useSuggest={false}
|
useSuggest={false}
|
||||||
text={newCategoryText}
|
text={newCategoryText}
|
||||||
handleTextChange={this.handleCategoryEditTextChange}
|
handleTextChange={this.handleCategoryEditTextChange}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ class Categories extends React.Component {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
handleCreateUserAnno = () => {
|
handleCreateUserAnno = e => {
|
||||||
const { dispatch } = this.props;
|
const { dispatch } = this.props;
|
||||||
const { newCategoryText, categoryToDuplicate } = this.state;
|
const { newCategoryText, categoryToDuplicate } = this.state;
|
||||||
dispatch({
|
dispatch({
|
||||||
@@ -37,6 +37,7 @@ class Categories extends React.Component {
|
|||||||
categoryToDuplicate: null,
|
categoryToDuplicate: null,
|
||||||
newCategoryText: ""
|
newCategoryText: ""
|
||||||
});
|
});
|
||||||
|
e.preventDefault();
|
||||||
};
|
};
|
||||||
|
|
||||||
handleEnableAnnoMode = () => {
|
handleEnableAnnoMode = () => {
|
||||||
|
|||||||
@@ -83,10 +83,11 @@ class CategoryValue extends React.Component {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
handleEditValue = () => {
|
handleEditValue = e => {
|
||||||
const { dispatch, metadataField, categoryIndex } = this.props;
|
const { dispatch, metadataField, categoryIndex } = this.props;
|
||||||
const { editedLabelText } = this.state;
|
const { editedLabelText } = this.state;
|
||||||
const label = this.getLabel();
|
const label = this.getLabel();
|
||||||
|
this.cancelEditMode();
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "annotation: label edited",
|
type: "annotation: label edited",
|
||||||
editedLabel: editedLabelText,
|
editedLabel: editedLabelText,
|
||||||
@@ -94,12 +95,13 @@ class CategoryValue extends React.Component {
|
|||||||
categoryIndex,
|
categoryIndex,
|
||||||
label
|
label
|
||||||
});
|
});
|
||||||
|
e.preventDefault();
|
||||||
};
|
};
|
||||||
|
|
||||||
handleCreateArbitraryLabel = editedLabelTextNotInOntology => {
|
handleCreateArbitraryLabel = editedLabelTextNotInOntology => {
|
||||||
const { dispatch, metadataField, categoryIndex } = this.props;
|
const { dispatch, metadataField, categoryIndex } = this.props;
|
||||||
const label = this.getLabel();
|
const label = this.getLabel();
|
||||||
|
this.cancelEditMode();
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "annotation: label edited",
|
type: "annotation: label edited",
|
||||||
metadataField,
|
metadataField,
|
||||||
@@ -150,7 +152,7 @@ class CategoryValue extends React.Component {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
cancelEdit = () => {
|
cancelEditMode = () => {
|
||||||
const { dispatch, metadataField, categoryIndex } = this.props;
|
const { dispatch, metadataField, categoryIndex } = this.props;
|
||||||
dispatch({
|
dispatch({
|
||||||
type: "annotation: cancel edit label mode",
|
type: "annotation: cancel edit label mode",
|
||||||
@@ -433,8 +435,12 @@ class CategoryValue extends React.Component {
|
|||||||
<div>
|
<div>
|
||||||
<AnnoDialog
|
<AnnoDialog
|
||||||
isActive={editModeActive}
|
isActive={editModeActive}
|
||||||
inputProps={{ "data-testid": `${metadataField}:edit-label-name-dialog` }}
|
inputProps={{
|
||||||
primaryButtonProps={{ "data-testid": `${metadataField}:${displayString}:submit-label-edit` }}
|
"data-testid": `${metadataField}:edit-label-name-dialog`
|
||||||
|
}}
|
||||||
|
primaryButtonProps={{
|
||||||
|
"data-testid": `${metadataField}:${displayString}:submit-label-edit`
|
||||||
|
}}
|
||||||
title="Edit label"
|
title="Edit label"
|
||||||
instruction={`New label text must be unique within category ${metadataField}:`}
|
instruction={`New label text must be unique within category ${metadataField}:`}
|
||||||
cancelTooltipContent="Close this dialog without editing label text."
|
cancelTooltipContent="Close this dialog without editing label text."
|
||||||
@@ -444,12 +450,14 @@ class CategoryValue extends React.Component {
|
|||||||
validationError={this.labelNameError(editedLabelText)}
|
validationError={this.labelNameError(editedLabelText)}
|
||||||
errorMessage={this.labelNameErrorMessage(editedLabelText)}
|
errorMessage={this.labelNameErrorMessage(editedLabelText)}
|
||||||
handleSubmit={this.handleEditValue}
|
handleSubmit={this.handleEditValue}
|
||||||
handleCancel={this.cancelEdit}
|
handleCancel={this.cancelEditMode}
|
||||||
annoInput={
|
annoInput={
|
||||||
<AnnoInputs
|
<AnnoInputs
|
||||||
useSuggest={ontologyEnabled}
|
useSuggest={ontologyEnabled}
|
||||||
text={editedLabelText}
|
text={editedLabelText}
|
||||||
inputProps={{ "data-testid": `${metadataField}:${displayString}:edit-label-name` }}
|
inputProps={{
|
||||||
|
"data-testid": `${metadataField}:${displayString}:edit-label-name`
|
||||||
|
}}
|
||||||
handleCreateArbitraryLabel={
|
handleCreateArbitraryLabel={
|
||||||
this.handleCreateArbitraryLabel
|
this.handleCreateArbitraryLabel
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,15 +80,6 @@ const Annotations = (
|
|||||||
isAddingNewLabel: false,
|
isAddingNewLabel: false,
|
||||||
categoryAddingNewLabel: null
|
categoryAddingNewLabel: null
|
||||||
};
|
};
|
||||||
/* this handles both cases, since at this point it's just a string */
|
|
||||||
case "annotation: add new label to category":
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
isAddingNewLabel: false,
|
|
||||||
categoryAddingNewLabel: null,
|
|
||||||
isAddingNewLabelFromOntology: false,
|
|
||||||
categoryAddingNewLabelFromOntology: null
|
|
||||||
};
|
|
||||||
case "annotation: activate category edit mode":
|
case "annotation: activate category edit mode":
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
@@ -101,12 +92,6 @@ const Annotations = (
|
|||||||
isEditingCategoryName: false,
|
isEditingCategoryName: false,
|
||||||
categoryBeingEdited: null
|
categoryBeingEdited: null
|
||||||
};
|
};
|
||||||
case "annotation: category edited":
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
isEditingCategoryName: false,
|
|
||||||
categoryBeingEdited: null
|
|
||||||
};
|
|
||||||
|
|
||||||
/* LABEL */
|
/* LABEL */
|
||||||
case "annotation: activate edit label mode":
|
case "annotation: activate edit label mode":
|
||||||
@@ -124,12 +109,6 @@ const Annotations = (
|
|||||||
isEditingLabelName: false,
|
isEditingLabelName: false,
|
||||||
labelEditable: { category: null, label: null }
|
labelEditable: { category: null, label: null }
|
||||||
};
|
};
|
||||||
case "annotation: label edited":
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
isEditingLabelName: false,
|
|
||||||
labelEditable: { category: null, label: null }
|
|
||||||
};
|
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,7 +85,6 @@ const Undoable = (reducer, undoableKeys, options = {}) => {
|
|||||||
);
|
);
|
||||||
const newPast = [...past];
|
const newPast = [...past];
|
||||||
const newState = newPast.pop();
|
const newState = newPast.pop();
|
||||||
const newStateFilterState = newState[filterStateKey];
|
|
||||||
const newFuture = push(future, currentUndoableState);
|
const newFuture = push(future, currentUndoableState);
|
||||||
const nextState = {
|
const nextState = {
|
||||||
...currentState,
|
...currentState,
|
||||||
@@ -94,7 +93,6 @@ const Undoable = (reducer, undoableKeys, options = {}) => {
|
|||||||
[futureKey]: newFuture,
|
[futureKey]: newFuture,
|
||||||
[pendingKey]: null
|
[pendingKey]: null
|
||||||
};
|
};
|
||||||
nextState[filterStateKey] = newStateFilterState;
|
|
||||||
return nextState;
|
return nextState;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,12 +137,13 @@ const Undoable = (reducer, undoableKeys, options = {}) => {
|
|||||||
*/
|
*/
|
||||||
function skip(currentState, action, filterState) {
|
function skip(currentState, action, filterState) {
|
||||||
const past = currentState[pastKey] || [];
|
const past = currentState[pastKey] || [];
|
||||||
|
const future = currentState[futureKey] || [];
|
||||||
const pending = currentState[pendingKey];
|
const pending = currentState[pendingKey];
|
||||||
const res = reducer(currentState, action);
|
const res = reducer(currentState, action);
|
||||||
return {
|
return {
|
||||||
...res,
|
...res,
|
||||||
[pastKey]: past,
|
[pastKey]: past,
|
||||||
[futureKey]: [],
|
[futureKey]: future,
|
||||||
[filterStateKey]: filterState,
|
[filterStateKey]: filterState,
|
||||||
[pendingKey]: pending
|
[pendingKey]: pending
|
||||||
};
|
};
|
||||||
@@ -218,6 +217,7 @@ const Undoable = (reducer, undoableKeys, options = {}) => {
|
|||||||
},
|
},
|
||||||
action
|
action
|
||||||
) => {
|
) => {
|
||||||
|
if (debug > 1) console.log("---- ACTION", action.type);
|
||||||
const aType = action.type;
|
const aType = action.type;
|
||||||
switch (aType) {
|
switch (aType) {
|
||||||
case "@@undoable/undo": {
|
case "@@undoable/undo": {
|
||||||
|
|||||||
@@ -35,18 +35,30 @@ const skipOnActions = new Set([
|
|||||||
"get single gene expression for coloring error",
|
"get single gene expression for coloring error",
|
||||||
|
|
||||||
"category value mouse hover start",
|
"category value mouse hover start",
|
||||||
"category value mouse hover end"
|
"category value mouse hover end",
|
||||||
|
|
||||||
|
/* autosave annotations */
|
||||||
|
"writable obs annotations - save complete",
|
||||||
|
"writable obs annotations - save started",
|
||||||
|
"writable obs annotations - save error",
|
||||||
|
|
||||||
|
/* annotation component action */
|
||||||
|
"annotation: activate add new label mode",
|
||||||
|
"annotation: activate add new ontology label mode",
|
||||||
|
"annotation: disable add new ontology label mode",
|
||||||
|
"annotation: disable add new label mode",
|
||||||
|
"annotation: activate category edit mode",
|
||||||
|
"annotation: disable category edit mode",
|
||||||
|
"annotation: activate edit label mode",
|
||||||
|
"annotation: cancel edit label mode",
|
||||||
|
"set annotations collection name"
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
identical, repeated occurances of these action types will be debounced.
|
identical, repeated occurances of these action types will be debounced.
|
||||||
Entire action must be identical (all keys).
|
Entire action must be identical (all keys).
|
||||||
*/
|
*/
|
||||||
const debounceOnActions = new Set([
|
const debounceOnActions = new Set([]);
|
||||||
"color by categorical metadata",
|
|
||||||
"color by continuous metadata",
|
|
||||||
"color by expression"
|
|
||||||
]);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
history will be cleared when these actions occur
|
history will be cleared when these actions occur
|
||||||
@@ -91,7 +103,8 @@ const saveOnActions = new Set([
|
|||||||
"annotation: delete category",
|
"annotation: delete category",
|
||||||
"annotation: label edited",
|
"annotation: label edited",
|
||||||
"annotation: label current cell selection",
|
"annotation: label current cell selection",
|
||||||
"annotation: delete label"
|
"annotation: delete label",
|
||||||
|
"annotation: category edited"
|
||||||
]);
|
]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -172,8 +185,6 @@ const actionFilter = debug => (state, action, prevFilterState) => {
|
|||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
debounceOnActions.has(actionType) &&
|
debounceOnActions.has(actionType) &&
|
||||||
prevFilterState !== undefined &&
|
|
||||||
prevFilterState.prevAction !== undefined &&
|
|
||||||
shallowObjectEq(action, prevFilterState.prevAction)
|
shallowObjectEq(action, prevFilterState.prevAction)
|
||||||
) {
|
) {
|
||||||
return { [actionKey]: "skip", [stateKey]: filterState };
|
return { [actionKey]: "skip", [stateKey]: filterState };
|
||||||
@@ -229,7 +240,12 @@ function shallowArrayEq(arrA, arrB) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* configuration for the undoable meta reducer */
|
/* configuration for the undoable meta reducer */
|
||||||
const debug = false; // set truish for undoble debugging
|
/*
|
||||||
|
debug: set to any falsish value to disable logging of helpful debugging information.
|
||||||
|
Set to true or 1 for base logging, high number for more verbosity (currently only 1/true
|
||||||
|
or 2).
|
||||||
|
*/
|
||||||
|
const debug = false;
|
||||||
const undoableConfig = {
|
const undoableConfig = {
|
||||||
debug,
|
debug,
|
||||||
historyLimit: 50, // maximum history size
|
historyLimit: 50, // maximum history size
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ def annotations_put_fbs_helper(data_adaptor, annotations, fbs):
|
|||||||
new_label_df = decode_matrix_fbs(fbs)
|
new_label_df = decode_matrix_fbs(fbs)
|
||||||
if not new_label_df.empty:
|
if not new_label_df.empty:
|
||||||
data_adaptor.check_new_labels(new_label_df)
|
data_adaptor.check_new_labels(new_label_df)
|
||||||
annotations.write_labels(new_label_df, data_adaptor)
|
annotations.write_labels(new_label_df, data_adaptor)
|
||||||
|
|
||||||
|
|
||||||
def annotations_obs_put(request, data_adaptor, annotations):
|
def annotations_obs_put(request, data_adaptor, annotations):
|
||||||
|
|||||||
Reference in New Issue
Block a user