TS migration. #2288. (#2328)

* Added TS. Updated build and linting config. Added types.

* [ts-migrate][.] Rename files from JS/JSX to TS/TSX

Co-authored-by: ts-migrate <>

* [ts-migrate][.] Run TS Migrate

Co-authored-by: ts-migrate <>

* Corrected files mangled by ts-migrate.

* Updated lint config, minor linting.

* Re-enabled Husky.

* Updated tests and config.

* Reverted webpack devtool config.

* Removed obsolete snapshots.

* Added annotations snap.

* Updated tsconfig includes wrt linting.

* Removed ts-migrate.

Co-authored-by: Timmy Huang <tihuan@users.noreply.github.com>
This commit is contained in:
Mim Hastie
2021-07-26 20:18:17 +00:00
committed by GitHub
co-authored by ts-migrate Timmy Huang
parent 7328cbdbd5
commit 934cc5c69b
206 changed files with 4719 additions and 2085 deletions
-301
View File
@@ -1,301 +0,0 @@
import StateMachine from "../util/statemachine";
import createFsmTransitions from "./undoableFsm";
const actionKey = "@@undoable/filterAction";
const stateKey = "@@undoable/filterState";
/*
these actions will not affect history
*/
const skipOnActions = new Set([
"annoMatrix: init complete",
"url changed",
"initial data load start",
"universe: user color load success",
"configuration load complete",
"increment graph render counter",
"window resize",
"reset colorscale",
"reset centroid labels",
"geneset: initial load",
"geneset: set tid",
"graph brush change",
"continuous metadata histogram brush",
"request user defined gene success",
"category value mouse hover start",
"category value mouse hover end",
/* autosave annotations */
"writable obs annotations - save complete",
"writable obs annotations - save started",
"writable obs annotations - save error",
"autosave: genesets started",
"autosave: genesets error",
"autosave: genesets complete",
/* annotation component action */
"annotation: activate add new 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",
/* geneset component action */
"geneset: activate add new geneset mode",
"geneset: disable create geneset mode",
"geneset: activate add new genes mode",
"geneset: disable add new genes mode",
"geneset: activate rename geneset mode",
"geneset: disable rename geneset mode",
]);
/*
identical, repeated occurances of these action types will be debounced.
Entire action must be identical (all keys).
*/
const debounceOnActions = new Set([]);
/*
history will be cleared when these actions occur
*/
const clearOnActions = new Set([
"initial data load complete",
"initial data load error",
]);
/*
An immediate history save will be done for these
*/
const saveOnActions = new Set([
"categorical metadata filter select",
"categorical metadata filter deselect",
"categorical metadata filter all of these",
"categorical metadata filter none of these",
"color by categorical metadata",
"color by continuous metadata",
"color by expression",
"color by geneset mean expression",
"show centroid labels for category",
"set scatterplot x",
"set scatterplot y",
"store current cell selection as differential set 1",
"store current cell selection as differential set 2",
"subset to selection",
"set clip quantiles",
"set layout choice",
"change graph interaction mode",
// user editable annotations
"annotation: create category",
"annotation: add new label to category",
"annotation: delete category",
"annotation: label edited",
"annotation: label current cell selection",
"annotation: delete label",
"annotation: category edited",
/* geneset component action */
"geneset: create",
"geneset: delete",
"geneset: update",
"geneset: add genes",
"geneset: delete genes",
"geneset: set gene description",
]);
/**
StateMachine - processing complex action handling - see FSM graph for
actual structure, in undoableFsm.js
**/
/*
Default FSM actions. Used to side-effect transitions in the graph.
See graph definition for the transitions that use each.
Signature: (fsm, transition, reducerState, reducerAction) => undoableAction
*/
const stashPending = (fsm) => ({
[actionKey]: "stashPending",
[stateKey]: { fsm },
});
const cancelPending = () => ({
[actionKey]: "cancelPending",
[stateKey]: { fsm: null },
});
const applyPending = () => ({
[actionKey]: "applyPending",
[stateKey]: { fsm: null },
});
const skip = (fsm, transition) => ({
[actionKey]: "skip",
[stateKey]: { fsm: transition.to !== "done" ? fsm : null },
});
const clear = () => ({ [actionKey]: "clear", [stateKey]: { fsm: null } });
const save = (fsm, transition) => ({
[actionKey]: "save",
[stateKey]: { fsm: transition.to !== "done" ? fsm : null },
});
/*
Error handler for state transitions that are unexpected. Called by
StateMachine when it doesn't know what to do.
Signature: (fsm, event, from) => undoableAction
*/
const onFsmError = (fsm, event, from) => {
console.error(`FSM error [event: "${event}", state: "${from}"]`, fsm);
// In production, try to recover gracefully if we have unexpected state
return clear();
};
/*
Definition of the transition graph mapping action types to history side effects.
*/
const fsmTransitions = createFsmTransitions(
stashPending,
cancelPending,
applyPending,
skip,
clear,
save
);
/* State machine we clone whenever we need to run it */
const seedFsm = new StateMachine("init", fsmTransitions, onFsmError);
/*
See undoable.js for description action filter interface description.
Basic approach:
* trivial handlers for skip, clear & save cases to keep config simple.
* only implement complex state machines where absolutely required (eg,
multi-event selection and the like)
*/
const actionFilter = (debug) => (state, action, prevFilterState) => {
const actionType = action.type;
const filterState = {
...prevFilterState,
prevAction: action,
};
if (skipOnActions.has(actionType)) {
return { [actionKey]: "skip", [stateKey]: filterState };
}
if (
debounceOnActions.has(actionType) &&
shallowObjectEq(action, prevFilterState.prevAction)
) {
return { [actionKey]: "skip", [stateKey]: filterState };
}
if (clearOnActions.has(actionType)) {
return { [actionKey]: "clear", [stateKey]: filterState };
}
if (saveOnActions.has(actionType)) {
return { [actionKey]: "save", [stateKey]: filterState };
}
/*
Else, something more complex OR unknown to us....
*/
if (seedFsm.events.has(actionType)) {
let { fsm } = filterState;
if (!fsm) {
/* no active FSM, so create one in init state */
fsm = seedFsm.clone("init");
}
return fsm.next(action.type, { state, action });
}
/* else, we have no idea what this is - skip it */
if (debug) console.log("**** ACTION FILTER EVENT HANDLER MISS", actionType);
return { [actionKey]: "skip", [stateKey]: filterState };
};
/*
return true if objA and objB are ===, OR if:
- are both objects and not null
- have same own properties
- all values are strict equal (===)
*/
function shallowObjectEq(objA, objB) {
if (objA === objB) return true;
if (!objA || !objB) return false;
if (!shallowArrayEq(Object.keys(objA), Object.keys(objB))) return false;
if (!shallowArrayEq(Object.values(objA), Object.values(objB))) return false;
return true;
}
/*
return true if arrA and arrB contain the same strict-equal values,
in the same order.
*/
function shallowArrayEq(arrA, arrB) {
if (arrA.length !== arrB.length) return false;
for (let i = 0, l = arrA.length; i < l; i += 1) {
if (arrA[i] !== arrB[i]) return false;
}
return true;
}
/* configuration for the undoable meta reducer */
/*
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 = {
debug,
historyLimit: 50, // maximum history size
actionFilter: actionFilter(debug),
};
/*
this code is strictly for sanity checking configuration, and is only
enabled when we are debugging the undoable configuration (ie, debug === true).
*/
if (debug) {
/*
Confirm no intersection between the various trivial rejection action filters
*/
if (
new Set([...skipOnActions].filter((x) => clearOnActions.has(x))).size > 0 ||
new Set([...skipOnActions].filter((x) => saveOnActions.has(x))).size > 0 ||
new Set([...clearOnActions].filter((x) => saveOnActions.has(x))).size > 0
) {
console.error(
"Undoable misconfiguration - action filters have redundant events"
);
}
/*
Confirm that no FSM events are blocked by a trivial rejection filter.
If this occurs, the FSM can't ever see the events needed to process
state transitions.
*/
const trivialFilters = new Set([
...skipOnActions,
...clearOnActions,
...saveOnActions,
]);
const trivialOverlapWithFsm = new Set(
[...trivialFilters].filter((x) => seedFsm.events.has(x))
);
if (trivialOverlapWithFsm.size > 0) {
console.error(
"Undoable misconfiguration - trivival action filter blocking FSM filter",
[...trivialOverlapWithFsm]
);
}
}
export default undoableConfig;